Replaced non-working (on NAS100d) redboot byteswap partition truncate patch with the one that has been tested on NSLU2, NAS100d, Loft, etc., accepted by linux-mtd, and should be in 2.6.20

SVN-Revision: 5813
This commit is contained in:
Rod Whitby 2006-12-17 03:05:52 +00:00
parent ee1839c4f2
commit b3dcce7d75
2 changed files with 61 additions and 61 deletions

View file

@ -0,0 +1,61 @@
Redboot supports storing the FIS directory and the RedBoot
configuration information in the same block of flash memory. This is
not the most common RedBoot configuration, but it is used on
commercially available boards supported by the kernel.
A recent patch to mtd/redboot.c (http://lkml.org/lkml/2006/3/20/410)
which corrected the skipping of deleted table entries has exposed the
latent problem of the kernel redboot parser running off the end of the
FIS directory and interpreting the RedBoot configuration information
as table entries.
This patch terminates the table parsing when the first truly empty
entry is found (table entry deletion only clears the first byte of the
name, so two cleared bytes in a row indicates the end of the table),
thereby supporting the combined redboot FIS directory and RedBoot
configuration information flash layout scenario.
Signed-off-by: Rod Whitby <rod@whitby.id.au>
--
Index: linux-2.6.19/drivers/mtd/redboot.c
===================================================================
--- linux-2.6.19.orig/drivers/mtd/redboot.c
+++ linux-2.6.19/drivers/mtd/redboot.c
@@ -96,7 +96,19 @@ static int parse_redboot_partitions(stru
*/
if (swab32(buf[i].size) == master->erasesize) {
int j;
- for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
+ for (j = 0; j < numslots; ++j) {
+
+ /* A single 0xff denotes a deleted entry.
+ * Two of them in a row is the end of the table.
+ */
+ if (buf[j].name[0] == 0xff) {
+ if (buf[j].name[1] == 0xff) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
/* The unsigned long fields were written with the
* wrong byte sex, name and pad have no byte sex.
*/
@@ -123,8 +135,13 @@ static int parse_redboot_partitions(stru
for (i = 0; i < numslots; i++) {
struct fis_list *new_fl, **prev;
- if (buf[i].name[0] == 0xff)
- continue;
+ if (buf[i].name[0] == 0xff) {
+ if (buf[i].name[1] == 0xff) {
+ break;
+ } else {
+ continue;
+ }
+ }
if (!redboot_checksum(&buf[i]))
break;

View file

@ -1,61 +0,0 @@
diff -urN linux-2.6.19.old/drivers/mtd/redboot.c linux-2.6.19.dev/drivers/mtd/redboot.c
--- linux-2.6.19.old/drivers/mtd/redboot.c 2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.19.dev/drivers/mtd/redboot.c 2006-12-14 03:13:35.000000000 +0100
@@ -92,22 +92,47 @@
* swab32(erasesize) then we know we are looking at
* a byte swapped FIS directory - swap all the entries!
* (NOTE: this is 'size' not 'data_length'; size is
- * the full size of the entry.)
+ * the full size of the entry.)
+ *
+ * Handle cases where the FIS directory is less than
+ * a full erase block (like combine FIS directory
+ * and RedBoot config).
+ *
+ * IMHO the best solution would be to compute the
+ * flash address of the RedBoot FIS directory and
+ * compare that with the entry in the FIS directory
+ * entry swabbed. However, I haven't yet figured out
+ * how to compute that.
*/
- if (swab32(buf[i].size) == master->erasesize) {
+
+ unsigned long erasesize_mask = master->erasesize -1;
+ unsigned long eraseaddr_mask = 0xFFFFFFFF ^ erasesize_mask;
+
+ if (((swab32(buf[i].size)+erasesize_mask)
+ & eraseaddr_mask) == master->erasesize) {
int j;
- for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
+
+ /* N.B. The full table being processed so adjust size now */
+ numslots = swab32(buf[i].size) / sizeof (struct fis_image_desc);
+ for (j = 0; j < numslots; ++j) {
/* The unsigned long fields were written with the
* wrong byte sex, name and pad have no byte sex.
+ *
+ * Only process non-deleted entries. Don't exit early.
*/
- swab32s(&buf[j].flash_base);
- swab32s(&buf[j].mem_base);
- swab32s(&buf[j].size);
- swab32s(&buf[j].entry_point);
- swab32s(&buf[j].data_length);
- swab32s(&buf[j].desc_cksum);
- swab32s(&buf[j].file_cksum);
+ if (buf[j].name[0] != 0xff) {
+ swab32s(&buf[j].flash_base);
+ swab32s(&buf[j].mem_base);
+ swab32s(&buf[j].size);
+ swab32s(&buf[j].entry_point);
+ swab32s(&buf[j].data_length);
+ swab32s(&buf[j].desc_cksum);
+ swab32s(&buf[j].file_cksum);
+ }
}
+ } else {
+ /* Update numslots based on actual FIS directory size */
+ numslots = buf[i].size / sizeof (struct fis_image_desc);
}
break;
}