tools/firmware-utils: mktplinkfw* fix rootfs offset
authorThibaut VARÈNE <hacks@slashdirt.org>
Fri, 27 Oct 2017 18:12:15 +0000 (20:12 +0200)
committerMathias Kresin <dev@kresin.me>
Wed, 8 Nov 2017 22:18:22 +0000 (23:18 +0100)
With '-a' specified on the command line, the current code:
- computes an aligned _kernel length_ instead of an aligned _rootfs
  offset_.
- does not update the rootfs offset after computing the new kernel
  length, and instead retains the layout default.

When the kernel length exceeds the available space left with this
fixed offset, the resulting image header contains invalid data, with
the recorded rootfs offset overlapping the kernel area.

This patch ensures that rootfs offset is correctly computed and
reflected in the final image.

Furthermore, the build_fw() function special cases the rootfs_align
option because of the above invalid logic. This is also fixed and
the computed (or command-line provided, or layout-provided) rootfs_ofs
value is used in all cases.

There seems to be no valid reason to extend the kernel length beyond
the actual length of the kernel itself (OFW images don't do it) so this
part of the existing behavior is dropped.

Example image before the patch:
Kernel data offset     : 0x00000200 /      512 bytes
Kernel data length     : 0x00158438 /  1410104 bytes
Kernel load address    : 0x00000080
Kernel entry point     : 0x00000080
Rootfs data offset     : 0x00140000 /  1310720 bytes
Rootfs data length     : 0x001e4f7e /  1986430 bytes

Example image after the patch:
Kernel data offset     : 0x00000200 /      512 bytes
Kernel data length     : 0x001583fe /  1410046 bytes
Kernel load address    : 0x00000080
Kernel entry point     : 0x00000080
Rootfs data offset     : 0x00158600 /  1410560 bytes
Rootfs data length     : 0x001e4e22 /  1986082 bytes

Tested-by: Mathias Kresin <dev@kresin.me>
Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
Tested-by: Daniel Engberg <daniel.engberg.lists@pyret.net>
Tested-by: Henryk Heisig <hyniu@o2.pl>
Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
tools/firmware-utils/src/mktplinkfw-lib.c
tools/firmware-utils/src/mktplinkfw.c
tools/firmware-utils/src/mktplinkfw2.c

index 18da13dd047783e85475f96c833d7acb515e2aa6..b2b6de26db9564e1169380221761aed3958130fc 100644 (file)
@@ -236,19 +236,13 @@ int build_fw(size_t header_size)
                goto out_free_buf;
 
        if (!combined) {
-               if (rootfs_align)
-                       p = buf + writelen;
-               else
-                       p = buf + rootfs_ofs;
+               p = buf + rootfs_ofs;
 
                ret = read_to_buf(&rootfs_info, p);
                if (ret)
                        goto out_free_buf;
 
-               if (rootfs_align)
-                       writelen += rootfs_info.file_size;
-               else
-                       writelen = rootfs_ofs + rootfs_info.file_size;
+               writelen = rootfs_ofs + rootfs_info.file_size;
 
                if (add_jffs2_eof)
                        writelen = pad_jffs2(buf, writelen, layout->fw_max_len);
index 9bc112fe6c918f0d6afcb616a6b416de1a9e2a11..ef19e1052943174489bab55b851e26f90f24ca85 100644 (file)
@@ -307,10 +307,10 @@ static int check_options(void)
 
                if (rootfs_align) {
                        kernel_len += sizeof(struct fw_header);
-                       kernel_len = ALIGN(kernel_len, rootfs_align);
+                       rootfs_ofs = ALIGN(kernel_len, rootfs_align);
                        kernel_len -= sizeof(struct fw_header);
 
-                       DBG("kernel length aligned to %u", kernel_len);
+                       DBG("rootfs offset aligned to 0x%u", rootfs_ofs);
 
                        exceed_bytes = kernel_len + rootfs_info.file_size - (fw_max_len - sizeof(struct fw_header));
                        if (exceed_bytes > 0) {
index 892c93f10929941e84d438e56e64ea634460287a..b6caf8a0e5d245aa0686c6845a909e88f3e5d72e 100644 (file)
@@ -267,10 +267,10 @@ static int check_options(void)
 
                if (rootfs_align) {
                        kernel_len += sizeof(struct fw_header);
-                       kernel_len = ALIGN(kernel_len, rootfs_align);
+                       rootfs_ofs = ALIGN(kernel_len, rootfs_align);
                        kernel_len -= sizeof(struct fw_header);
 
-                       DBG("kernel length aligned to %u", kernel_len);
+                       DBG("rootfs offset aligned to 0x%u", rootfs_ofs);
 
                        if (kernel_len + rootfs_info.file_size >
                            layout->fw_max_len - sizeof(struct fw_header)) {