blob: 9927b47fa111274cb91b8e6fa82af4463ac6afa7 [file] [log] [blame]
OVERVIEW
========
It is useful to be able to access partitions on block devices in a general
purpose fashion, however to do so can require device specific knowledge. For
example, some devices require erases before writes and some partitions need to
have the hardware in a different configuration (e.g. different forms of ECC
for different partitions stored in NAND). To allow such things to be handled
in a generic fashion, the following functions are provided:
int get_partition_by_name(block_dev_desc_t *dev, const char *partition_name,
disk_partition_t *partition);
int partition_erase_blks(block_dev_desc_t *dev, disk_partition_t *partition,
lbaint_t *blkcnt);
int partition_erase_bytes(block_dev_desc_t *dev, disk_partition_t *partition,
loff_t *bytecnt);
int partition_read_blks(block_dev_desc_t *dev, disk_partition_t *partition,
lbaint_t *blkcnt, void *buffer);
int partition_read_bytes(block_dev_desc_t *dev, disk_partition_t *partition,
loff_t *bytecnt, void *buffer);
int partition_write_blks(block_dev_desc_t *dev, disk_partition_t *partition,
lbaint_t *blkcnt, const void *buffer);
int partition_write_bytes(block_dev_desc_t *dev, disk_partition_t *partition,
loff_t *bytecnt, const void *buffer);
An important note is that all of these functions round up the sizes that are
passed to them to the next logical boundary.
Example 1: If you ask for a single byte to be read from a partition,
an entire block of data is going to be placed in the buffer. The
caller must ensure that enough space is available in the buffer to
prevent overflow.
Example 2: For a NAND flash the size of a block for the partition
functions is equivalent to the size of the NAND's "write page". However,
the smallest unit that can be erased on a NAND is an "erase block" which
is made up of multiple "write pages". This means that if you use the
partition_erase_* functions to erase a single byte or a single block on a
NAND, it will round up to erasing an entire "erase block" which will be
multiple "write pages".
PRE_ AND POST_ ENVIRONMENT VARIABLES
====================================
To accomplish the partition dependent configuration, these functions will use
environment variables to specify what commands need to be executed before and
after the operation is performed. The names of the environment variables that
will be used are of the form:
<when>_<operation>.<partition_name>
where:
<when> is "pre" or "post"
<operation> is "erase", "read" or "write"
<partition_name> is the name of the partition that the commands apply to.
As an example of using these, some boards use NAND memory but require
different ECC methods for different MTD partitions. Historically, these
partitions were written using something like the following sequence of
commands:
nandecc hw
nand erase.part x-loader
nand write 0x80000000 x-loader # Write x-loader from memory at 0x80000000
nandecc sw
To use the partition functions for doing this, your board configuration should
include:
"pre_write.xloader=nandecc hw\0post_write.xloader=nandecc sw\0"
in the CONFIG_EXTRA_ENV_SETTINGS or else have executed the commands:
setenv pre_write.x-loader nandecc hw
setenv post_write.x-loader nandecc sw
With those environment variables set and using the blk command, you can simply
do:
blk write 0x80000000 x-loader
The blk write command will call partition_write_blks() which in turn takes
care of fetching the values of the environment variables, and if they are set,
executing them as U-Boot commands. In this case, that means that the NAND's
ECC will be set to use hardware ECC before the partition is written and then
set back to software ECC after the partition is written.
ERASE BEFORE WRITE
==================
It should be noted that whether or not an erase is done before a write is
controlled by the C preprocessor define CONFIG_ERASE_PARTITION_ALWAYS. If it
is defined in the board configuration file, the following sequence will be
followed when a write is done:
pre_write.<partition_name> commands
erase
write
post_write.<partition_name> commands
Note that this means that if you need to set pre_erase and/or post_erase,
you'll probably need pre_write and post_write to contain those same commands.
CALLING BLOCK FUNCTIONS DIRECTLY
================================
There are times where it is required to access portions of the partition
instead of reading or writing the entire partition. For example, a header
needs to be read to know how much of the partition needs to be read. To do
this, the code should use the block_read or block_write function pointers
within the struct block_dev_desc and wrap those with calls to execute the pre_
and post_ environment variables. The following functions are provided for
that purpose:
int partition_erase_pre(disk_partition_t *ptn);
int partition_erase_post(disk_partition_t *ptn);
int partition_read_pre(disk_partition_t *ptn);
int partition_read_post(disk_partition_t *ptn);
int partition_write_pre(disk_partition_t *ptn);
int partition_write_post(disk_partition_t *ptn);