Search code examples
u-boot

U-Boot error while decompressing gzipped kernel


I have an older embedded device (PHYTEC phyCORE-LPC3250) that runs the ancient U-Boot 1.3.3.

The Linux kernel uImage gets copied to the NAND flash at 0x200000, then booted with: nboot 80100000 0 200000;bootm

This works fine if the uImage is derived from the self-expanding zImage, but according to this mailing list post it is preferable to have U-Boot perform the decompression itself.

So I have tried creating a uImage that contains a gzipped version of the normal kernel image, but decompression fails:

Image Name:   Poky (Yocto Project Reference Di
Image Type:   ARM Linux Kernel Image (gzip compressed)
Data Size:    4057248 Bytes =  3.9 MB
Load Address: 80008000
Entry Point:  80008000
Verifying Checksum ... OK
Uncompressing Kernel Image ... Error: inflate() returned -3
GUNZIP: uncompress or overwrite error - must RESET board to recover

This scenario is described in the FAQ, which suggests that the problem is running out of RAM. But I have 128 MB of RAM, starting at 0x80000000, and the uncompressed kernel is only 8 MB.

(I validated that the data in the uImage is in fact gzipped.)


Solution

  • First U-Boot copies the uImage from NAND to RAM at the specified address 0x80100000. Then it unpacks the kernel to the load address specified in the uImage header, 0x80008000.

    Since our kernel is about 8 MB uncompressed, that means the kernel's memory from 0x80008000 to approximately 0x80800000 overlaps where we copied the uImage at 0x80100000.

    If the uImage is not compressed, unpacking the kernel can use memmove which handles overlapping address ranges without issue. (If the load address is the address where we copied it in RAM, the kernel gets executed in-place.)

    But for compressed uImages, if we overwrite the compressed data while decompressing, decompression will obviously fail.