Commit fc8cddf2 authored by David Woodhouse's avatar David Woodhouse

MTD: Fix RedBoot FIS table detection.

The redboot partitioning code currently searches for a FIS table entry
named "RedBoot" (including the trailing \0) in one of the first three
entries to try and verify that the sector it is looking at really is a
FIS partition table.

Firstly it fails when RedBoot is stored in some other Flash chip such as
a boot PROM, in this case there is no "RedBoot" entry in the partition
table. However there will always be a "FIS directory" entry in any valid
FIS directory.
        
Secondly it can fail since the RedBoot entry is not always in the first
3 slots -- this can happen for example on an x86 based platform where
the processor expects the boot device to be at the top of memory rather
than the bottom and so RedBoot is at the end of the flash device.
Equally when using "FIS directory" as the entry to search for it very
likely is not in the first three since the directory is typically at the
end of the flash.
Signed-off-by: default avatarIan Campbell <icampbell@arcom.com>
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 3d3387c0
# $Id: Kconfig,v 1.6 2004/08/09 13:19:42 dwmw2 Exp $
# $Id: Kconfig,v 1.7 2004/11/22 11:33:56 ijc Exp $
menu "Memory Technology Devices (MTD)"
......@@ -54,8 +54,8 @@ config MTD_REDBOOT_PARTS
depends on MTD_PARTITIONS
---help---
RedBoot is a ROM monitor and bootloader which deals with multiple
'images' in flash devices by putting a table in the last erase
block of the device, similar to a partition table, which gives
'images' in flash devices by putting a table one of the erase
blocks on the device, similar to a partition table, which gives
the offsets, lengths and names of all the images stored in the
flash.
......@@ -68,6 +68,23 @@ config MTD_REDBOOT_PARTS
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
example.
config MTD_REDBOOT_DIRECTORY_BLOCK
int "Location of RedBoot partition table"
depends on MTD_REDBOOT_PARTS
default "-1"
---help---
This option is the Linux counterpart to the
CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK RedBoot compile time
option.
The option specifies which Flash sectors holds the RedBoot
partition table. A zero or positive value gives an absolete
erase block number. A negative value specifies a number of
sectors before the end of the device.
For example "2" means block number 2, "-1" means the last
block and "-2" means the penultimate block.
config MTD_REDBOOT_PARTS_UNALLOCATED
bool " Include unallocated flash regions"
depends on MTD_REDBOOT_PARTS
......
/*
* $Id: redboot.c,v 1.15 2004/08/10 07:55:16 dwmw2 Exp $
* $Id: redboot.c,v 1.17 2004/11/22 11:33:56 ijc Exp $
*
* Parse RedBoot-style Flash Image System (FIS) tables and
* produce a Linux partition array to match.
......@@ -30,6 +30,9 @@ struct fis_list {
struct fis_list *next;
};
static int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK;
module_param(directory, int, 0);
static inline int redboot_checksum(struct fis_image_desc *img)
{
/* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
......@@ -50,6 +53,8 @@ static int parse_redboot_partitions(struct mtd_info *master,
char *nullname;
int namelen = 0;
int nulllen = 0;
int numslots;
unsigned long offset;
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
static char nullstring[] = "unallocated";
#endif
......@@ -59,8 +64,15 @@ static int parse_redboot_partitions(struct mtd_info *master,
if (!buf)
return -ENOMEM;
/* Read the start of the last erase block */
ret = master->read(master, master->size - master->erasesize,
if ( directory < 0 )
offset = master->size + directory*master->erasesize;
else
offset = directory*master->erasesize;
printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
master->name, offset);
ret = master->read(master, offset,
master->erasesize, &retlen, (void *)buf);
if (ret)
......@@ -71,12 +83,16 @@ static int parse_redboot_partitions(struct mtd_info *master,
goto out;
}
/* RedBoot image could appear in any of the first three slots */
for (i = 0; i < 3; i++) {
if (!memcmp(buf[i].name, "RedBoot", 8))
numslots = (master->erasesize / sizeof(struct fis_image_desc));
for (i = 0; i < numslots; i++) {
if (buf[i].name[0] == 0xff) {
i = numslots;
break;
}
if (!memcmp(buf[i].name, "FIS directory", 14))
break;
}
if (i == 3) {
if (i == numslots) {
/* Didn't find it */
printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
master->name);
......@@ -84,7 +100,7 @@ static int parse_redboot_partitions(struct mtd_info *master,
goto out;
}
for (i = 0; i < master->erasesize / sizeof(struct fis_image_desc); i++) {
for (i = 0; i < numslots; i++) {
struct fis_list *new_fl, **prev;
if (buf[i].name[0] == 0xff)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment