Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MBRBlockDevice.h Source File

MBRBlockDevice.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020  * SOFTWARE.
00021  */
00022 #ifndef MBED_MBR_BLOCK_DEVICE_H
00023 #define MBED_MBR_BLOCK_DEVICE_H
00024 
00025 #include "BlockDevice.h"
00026 #include "mbed.h"
00027 
00028 
00029 /** Additional error codes used for MBR records
00030  */
00031 enum {
00032     BD_ERROR_INVALID_MBR       = -3101,
00033     BD_ERROR_INVALID_PARTITION = -3102,
00034 };
00035 
00036 
00037 /** Block device for managing a Master Boot Record
00038  *  https://en.wikipedia.org/wiki/Master_boot_record
00039  *
00040  *  Here is an example of partitioning a heap backed block device
00041  *  @code
00042  *  #include "mbed.h"
00043  *  #include "HeapBlockDevice.h"
00044  *  #include "MBRBlockDevice.h"
00045  *
00046  *  // Create a block device with 64 blocks of size 512
00047  *  HeapBlockDevice mem(64*512, 512);
00048  *
00049  *  // Partition into two partitions with ~half the blocks
00050  *  MBRBlockDevice::partition(&mem, 1, 0x83, 0*512, 32*512);
00051  *  MBRBlockDevice::partition(&mem, 2, 0x83, 32*512);
00052  *
00053  *  // Create a block device that maps to the first 32 blocks (excluding MBR block)
00054  *  MBRBlockDevice part1(&mem, 1);
00055  *
00056  *  // Create a block device that maps to the last 32 blocks
00057  *  MBRBlockDevice part2(&mem, 2);
00058  *  @endcode
00059  *
00060  *  Here is a more realistic example where the MBRBlockDevice is used
00061  *  to partition a region of space on an SD card. When plugged into a computer,
00062  *  the partitions will be recognized appropriately.
00063  *  @code
00064  *  #include "mbed.h"
00065  *  #include "SDBlockDevice.h"
00066  *  #include "MBRBlockDevice.h"
00067  *  #include "FATFileSystem.h"
00068  *
00069  *  // Create an SD card
00070  *  SDBlockDevice sd(s0, s1, s2, s3);
00071  *
00072  *  // Create a partition with 1 GB of space
00073  *  MBRBlockDevice::partition(&sd, 1, 0x83, 0, 1024*1024);
00074  *
00075  *  // Create the block device that represents the partition
00076  *  MBRBlockDevice part1(&sd, 1);
00077  *
00078  *  // Format the partition with a FAT filesystem
00079  *  FATFileSystem::format(&part1);
00080  *
00081  *  // Create the FAT filesystem instance, files can now be written to
00082  *  // the FAT filesystem in partition 1
00083  *  FATFileSystem fat("fat", &part1);
00084  *  @endcode
00085  *
00086  *  @note
00087  *  The MBR partition table is relatively limited:
00088  *  - At most 4 partitions are supported
00089  *  - Extended partitions are currently not supported and will error during init
00090  */
00091 class MBRBlockDevice : public BlockDevice
00092 {
00093 public:
00094     /** Format the MBR to contain the following partition
00095      *
00096      *  @param bd       Block device to partition
00097      *  @param part     Partition to use, 1-4
00098      *  @param type     8-bit partition type to identitfy partition's contents
00099      *  @param start    Start block address to map to block 0 of partition, 
00100      *                  negative addresses are calculated from the end of the
00101      *                  underlying block devices. Block 0 is implicitly ignored
00102      *                  from the range to store the MBR.
00103      *  @return         0 on success or a negative error code on failure
00104      *  @note This is the same as partition(bd, part, type, start, bd->size())
00105      */
00106     static int partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start);
00107 
00108     /** Format the MBR to contain the following partition
00109      *
00110      *  @param bd       Block device to partition
00111      *  @param part     Partition to use, 1-4
00112      *  @param type     8-bit partition type to identitfy partition's contents
00113      *  @param start    Start block address to map to block 0 of partition, 
00114      *                  negative addresses are calculated from the end of the
00115      *                  underlying block devices. Block 0 is implicitly ignored
00116      *                  from the range to store the MBR.
00117      *  @param stop     End block address to mark the end of the partition,
00118      *                  this block is not mapped, negative addresses are calculated
00119      *                  from the end of the underlying block device.
00120      *  @return         0 on success or a negative error code on failure
00121      */
00122     static int partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start, bd_addr_t stop);
00123 
00124     /** Lifetime of the block device
00125      *
00126      *  @param bd       Block device to back the MBRBlockDevice
00127      *  @param part     Partition to use, 1-4
00128      */
00129     MBRBlockDevice(BlockDevice *bd, int part);
00130 
00131     /** Lifetime of the block device
00132      */
00133     virtual ~MBRBlockDevice() {};
00134 
00135     /** Initialize a block device
00136      *
00137      *  @return         0 on success or a negative error code on failure
00138      */
00139     virtual int init();
00140 
00141     /** Deinitialize a block device
00142      *
00143      *  @return         0 on success or a negative error code on failure
00144      */
00145     virtual int deinit();
00146 
00147     /** Ensure data on storage is in sync with the driver
00148      *
00149      *  @return         0 on success or a negative error code on failure
00150      */
00151     virtual int sync();
00152 
00153     /** Read blocks from a block device
00154      *
00155      *  @param buffer   Buffer to read blocks into
00156      *  @param addr     Address of block to begin reading from
00157      *  @param size     Size to read in bytes, must be a multiple of read block size
00158      *  @return         0 on success, negative error code on failure
00159      */
00160     virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
00161 
00162     /** Program blocks to a block device
00163      *
00164      *  The blocks must have been erased prior to being programmed
00165      *
00166      *  @param buffer   Buffer of data to write to blocks
00167      *  @param addr     Address of block to begin writing to
00168      *  @param size     Size to write in bytes, must be a multiple of program block size
00169      *  @return         0 on success, negative error code on failure
00170      */
00171     virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
00172 
00173     /** Erase blocks on a block device
00174      *
00175      *  The state of an erased block is undefined until it has been programmed,
00176      *  unless get_erase_value returns a non-negative byte value
00177      *
00178      *  @param addr     Address of block to begin erasing
00179      *  @param size     Size to erase in bytes, must be a multiple of erase block size
00180      *  @return         0 on success, negative error code on failure
00181      */
00182     virtual int erase(bd_addr_t addr, bd_size_t size);
00183 
00184     /** Get the size of a readable block
00185      *
00186      *  @return         Size of a readable block in bytes
00187      */
00188     virtual bd_size_t get_read_size() const;
00189 
00190     /** Get the size of a programmable block
00191      *
00192      *  @return         Size of a programmable block in bytes
00193      *  @note Must be a multiple of the read size
00194      */
00195     virtual bd_size_t get_program_size() const;
00196 
00197     /** Get the size of an erasable block
00198      *
00199      *  @return         Size of an erasable block in bytes
00200      *  @note Must be a multiple of the program size
00201      */
00202     virtual bd_size_t get_erase_size() const;
00203 
00204     /** Get the size of an erasable block given address
00205      *
00206      *  @param addr     Address within the erasable block
00207      *  @return         Size of an erasable block in bytes
00208      *  @note Must be a multiple of the program size
00209      */
00210     virtual bd_size_t get_erase_size(bd_addr_t addr) const;
00211 
00212     /** Get the value of storage when erased
00213      *
00214      *  If get_erase_value returns a non-negative byte value, the underlying
00215      *  storage is set to that value when erased, and storage containing
00216      *  that value can be programmed without another erase.
00217      *
00218      *  @return         The value of storage when erased, or -1 if you can't
00219      *                  rely on the value of erased storage
00220      */
00221     virtual int get_erase_value() const;
00222 
00223     /** Get the total size of the underlying device
00224      *
00225      *  @return         Size of the underlying device in bytes
00226      */
00227     virtual bd_size_t size() const;
00228 
00229     /** Get the offset of the partition on the underlying block device
00230      *  @return         Offset of the partition on the underlying device
00231      */
00232     virtual bd_addr_t get_partition_start() const;
00233 
00234     /** Get size of partition on underlying block device
00235      *  @return         Size of the partition on the underlying device
00236      */
00237     virtual bd_addr_t get_partition_stop() const;
00238 
00239     /** Get 8-bit type of the partition
00240      *  @return         8-bit type of partition assigned during format
00241      */
00242     virtual uint8_t get_partition_type() const;
00243 
00244     /** Get the partition number
00245      *  @return         The partition number, 1-4
00246      */
00247     virtual int get_partition_number() const;
00248 
00249 protected:
00250     BlockDevice *_bd;
00251     bd_size_t _offset;
00252     bd_size_t _size;
00253     uint8_t _type;
00254     uint8_t _part;
00255 };
00256 
00257 
00258 #endif