[PATCH 2/2] ARM: remove the 4x expansion presumption while decompressing the kernel
Nicolas Pitre
nico at fluxnic.net
Thu Feb 17 15:40:15 EST 2011
On Thu, 17 Feb 2011, Russell King - ARM Linux wrote:
> On Thu, Feb 17, 2011 at 10:51:56AM -0700, Grant Likely wrote:
> > As for knowing where it can relocate to, we already know (actually
> > current code just makes an assumption) about how long the kernel
> > proper image is and where it wants to live in the zImage's head.S.
> > Assuming enough ram, if r6 reflects the size of the zImage + the size
> > of the appended data then it should be good.
>
> That isn't a valid argument. Just because "the decompressor already
> does it" does not mean that it'll work with ramdisks. We've been
> lucky so far that it has worked with the kernel - and that's exactly
> what it is - luck.
Two things here:
1) It is possible to know the length of an ATAG or DT block. The size
of a ramdisk image is not known without external information.
2) If the size of a ramdisk was discoverable by the zImage code, and if
the ramdisk image was simply appended to zImage itself, then there
would be no guessing as to where to allocate and load things as
separate blobs.
Let's suppose zImage is 1MB in size, the appended ramdisk image is 16MB,
and the decompressed kernel is 3MB. And for simplicity let's ignore
TEXT_OFFSET for the moment.
If zImage is loaded at 3MB from start of physical memory (or above) then
nothing needs to be relocated. It will simply decompress the kernel
from 0MB up to 3MB from start of physical memory. If a ramdisk is
appended to zImage then that location can be passed straight to the
kernel. We only need to make sure the kernel .bss is not larger than
1MB in that case which should be the norm. No guessing, no reliance on
luck. The only limitation is that you need at least 20MB of RAM here,
and there is no way around it whatever the booting method. (Actually you
could save 1MB by not using zImage but a straight Image, but if you're
so tight in RAM you shouldn't use a ramdisk to start with.)
If zImage is loaded at 0MB (typical) then it has to move things around.
Currently the code decompress the kernel and store it from the 1MB
address up to the 4MB address, and then move the kernel back down to 0MB
(a 3MB copy). What my patch does is to have zImage copy itself (1MB
large) to the 3MB address and then decompress the kernel from 0MB to
3MB.
Now if there is a ramdisk image appended to zImage, the zImage
relocation becomes a 17MB copy. And to be 100% safe, we might consider
the end of the kernel .bss to determine the relocation address for
zImage. But still, the final situation is the same as the case where no
relocation is needed. The ramdisk image is relocated along with zImage
to the optimal location i.e. from 4MB upwards. Again, no guessing, no
reliance on luck, no risk of overwriting a separately loaded ramdisk.
Of course this doesn't work on targets with segmented memory such as on
SA1100. For those the conventional method of loading the kernel in one
segment and the ramdisk in another must be preserved.
But with modern ARM machines, it would be far simpler to just
cat zImage ramdisk.gz > boot_image
and load that boot_image anywhere in memory and no bother with guesses
as to where to separately load the ramdisk and hope it won't get
overwritten at some point by the kernel decompressor.
But we're not there with initrd yet. I believe the rework of the
decompressor code has great value on its own. And then the
concatenation trick could be used for DTB which can be easily be self
sized. Doing that with a ramdisk image would require some information
header in between. But one step at a time.
Nicolas
More information about the linux-arm-kernel
mailing list