[OpenWrt-Devel] build: sysupgrade: kernel: mtd: Image too SMALL to Restore Config

Jeff Kletsky lede at allycomm.com
Mon Jul 1 14:21:01 EDT 2019


I've run across some seemingly "wrong" behavior related to sysupgrade
where if the image is "too small" the contents of /sysupgrade.tgz are
not properly recovered on reboot.

It seems as if the various pieces are functioning as expected, but
that they do not work in concert under certain situations. It seems as
though /sysupgrade.tgz is written where

   mtd write -j /tmp/sysupgrade.tgz -

intends, but when the kernel splits the partition into rootfs and
rootfs_data, the split is 0x10000 "early", likely resulting in the
JFFS2 believing that rootfs_data is "empty".

Prior to trying to "fix" this, I'd like to confirm the expected
behavior. `default_do_upgrade()` is writing the upgrade.


---


The smaller, "failing" image contains

003eb6f0  3e 30 0d 8b 02 00 00 00  00 01 59 5a de b2 20 00 
|>0........YZ.. .|
003eb700  00 00 00 00 04 80 00 00  00 00 04 b7 20 00 00 00 |............ 
...|
003eb710  00 00 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
003eb720  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
*
00400000  de ad c0 de 00 00 00 00  00 00 00 00 7b 20 20 22 
|............{  "|
00400010  6d 65 74 61 64 61 74 61  5f 76 65 72 73 69 6f 6e 
|metadata_version|


and results in the MTD firmware partition containing

003eb6f0  3e 30 0d 8b 02 00 00 00  00 01 59 5a de b2 20 00 
|>0........YZ.. .|
003eb700  00 00 00 00 04 80 00 00  00 00 04 b7 20 00 00 00 |............ 
...|
003eb710  00 00 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
003eb720  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
*
00400000  19 85 20 03 00 00 00 0c  f0 60 dc 98 19 85 e0 01  |.. 
......`......|
00400010  00 00 00 36 5d 44 48 fe  00 00 00 01 00 00 00 00 
|...6]DH.........|
00400020  00 00 00 02 00 00 00 00  0e 08 00 00 97 8f 0a 5b 
|...............[|
00400030  31 ff 3d bc 73 79 73 75  70 67 72 61 64 65 2e 74 
|1.=.sysupgrade.t|
00400040  67 7a ff ff 19 85 e0 02  00 00 10 44 ee 2d 30 6f 
|gz.........D.-0o|



The larger, "succeeding" image contains

003effe0  3e 30 0d 8b 02 00 00 00  00 01 59 5a ce fb 20 00 
|>0........YZ.. .|
003efff0  00 00 00 00 04 80 00 00  00 00 f4 ff 20 00 00 00 |............ 
...|
003f0000  00 00 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
003f0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
*
00400000  de ad c0 de 00 00 00 00  00 00 00 00 7b 20 20 22 
|............{  "|
00400010  6d 65 74 61 64 61 74 61  5f 76 65 72 73 69 6f 6e 
|metadata_version|


and results in the MTD firmware partition containing

003effe0  3e 30 0d 8b 02 00 00 00  00 01 59 5a ce fb 20 00 
|>0........YZ.. .|
003efff0  00 00 00 00 04 80 00 00  00 00 f4 ff 20 00 00 00 |............ 
...|
003f0000  00 00 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
003f0010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff 
|................|
*
00400000  19 85 20 03 00 00 00 0c  f0 60 dc 98 19 85 e0 01  |.. 
......`......|
00400010  00 00 00 36 5d 44 48 fe  00 00 00 01 00 00 00 00 
|...6]DH.........|
00400020  00 00 00 02 00 00 00 00  0e 08 00 00 97 8f 0a 5b 
|...............[|
00400030  31 ff 3d bc 73 79 73 75  70 67 72 61 64 65 2e 74 
|1.=.sysupgrade.t|
00400040  67 7a ff ff 19 85 e0 02  00 00 10 44 ee 2d 30 6f 
|gz.........D.-0o|


Note that the difference between the two is the length of the squashfs
crossing an erase-block boundary.

It appears from the build logs that `padjffs2` is being called in the
default image-generation process.  I have not yet located where in the
make files the default rule(s) are defined.

The on-flash data appears to be consistent with the code in
package/system/mtd/src/mtd.c which looks for JFFS2_EOF
#define JFFS2_EOF "\xde\xad\xc0\xde"

---

When the system boots, in the "failing" case, the MTD split is
"early", at at 0x3f0000, compared to the location of the
JFFS2_NODETYPE_CLEANMARKER `19 85 20 03` at 0x400000

[    0.435672] 0x000000050000-0x000000ff0000 : "firmware"
[    0.444132] 2 uimage-fw partitions found on MTD device firmware
[    0.450255] Creating 2 MTD partitions on "firmware":
[    0.455441] 0x000000000000-0x0000001e0000 : "kernel"
[    0.461418] 0x0000001e0000-0x000000fa0000 : "rootfs"
[    0.467345] mtd: device 4 (rootfs) set to be root filesystem
[    0.474785] mtdsplit: squashfs length: 0x20b712
[    0.479477] mtdsplit_squashfs: part_offset:  0x001e0000
[    0.484828] mtdsplit_squashfs: squashfs_len: 0x0020b712
[    0.490222] mtdsplit_squashfs: sum:          0x003eb712
[    0.494923] mtdsplit_squashfs: part->offset: 0x00210000
[    0.505635] 1 squashfs-split partitions found on MTD device rootfs
[    0.512029] 0x0000003f0000-0x000000fa0000 : "rootfs_data"
[    0.518440] 0x000000ff0000-0x000001000000 : "art"


In the "succeeding" case, the split is at the CLEANMARKER

[    0.435680] 0x000000050000-0x000000ff0000 : "firmware"
[    0.444143] 2 uimage-fw partitions found on MTD device firmware
[    0.450264] Creating 2 MTD partitions on "firmware":
[    0.455449] 0x000000000000-0x0000001e0000 : "kernel"
[    0.461425] 0x0000001e0000-0x000000fa0000 : "rootfs"
[    0.467353] mtd: device 4 (rootfs) set to be root filesystem
[    0.474789] mtdsplit: squashfs length: 0x210002
[    0.479477] mtdsplit_squashfs: part_offset:  0x001e0000
[    0.484826] mtdsplit_squashfs: squashfs_len: 0x00210002
[    0.490222] mtdsplit_squashfs: sum:          0x003f0002
[    0.494923] mtdsplit_squashfs: part->offset: 0x00220000
[    0.505635] 1 squashfs-split partitions found on MTD device rootfs
[    0.512028] 0x000000400000-0x000000fa0000 : "rootfs_data"
[    0.518439] 0x000000ff0000-0x000001000000 : "art"


Checking the squashfs indicates that the "failing" image is smaller
than the "succeeding" image, again crossing an erase-block boundary

   size: 2144018 bytes, 840 inodes, blocksize: 262144 bytes
         0x20b712

   size: 2162690 bytes, 841 inodes, blocksize: 262144 bytes
         0x210002

This also seems consistent with the code in
target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c
which calls mtd_get_squashfs_len()
target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit.c
from the super block.

---

I tend to believe that the JFFS2 code from Linux handles the partition
"properly". If so, in the "failing" case it is seeing "erased" space
at the start of the partition, rather than a valid JFFS2 node.

---



Have I interpreted the general behavior of the components correctly?

Before digging into `padjffs2`, is there a reason it doesn't adjust
the super block to the "new" size?


Jeff













_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list