On Thu, Aug 9, 2012 at 11:23 AM, Brendan Conoboy <[email protected]> wrote:
> On 08/08/2012 08:37 PM, Matt Sealey wrote:
>>
>> uEnv.txt and boot.scr aren't the same thing. uEnv.txt is the U-Boot
>> environment usually on a fat partition. boot.scr is loaded by a readily
>> loaded environment... You either predefined your environment and boot from
>> it or you're using values from that environment. I wouldn't use uEnv.txt to
>> replace a boot.scr on any system..
>
> I don't think that is entirely accurate- uboots such as those for OMAP rely
> on uEnv.txt for everything. Sure, you can daisy-chain load a boot.scr, but
> why do so when uEnv.txt can perform both functions?
Seperation.
Apologies if I re-hash any part of the conversation I missed, but this
is my understanding of what is required and what the current situation
is;
uEnv.txt or the SPI NOR or MMC raw blocks or the default environment
in U-Boot encoded at compile-time then run-time is the thing that
should define the absolute fixed definitions of the board. This is,
after all, the environment you want every time you boot. The reason
it's a text file on OMAP is because on OMAP all they have is a FAT
partition and it's less intrusive to read that file of that filename
out from the disk. It is not to make life for distros more convenient
by negating the need to write boot scripts; especially since every
other ARM, PPC, MIPS, et al architecture might actually need the boot
script. Why differentiate? uEnv.txt needs to be there to load a
DIFFERENT environment, but there's also one compiled into U-Boot
anyway. 99% of the time they're identical. If you need to dynamically
change the booted environment from the default, you can; for instance
to fix some errata that makes booting not work, or write a register or
modify the way the thing boots without modifying the U-Boot compile,
but on OMAP.. you have access to the binary anyway, it's in the same
FAT partition :)
Since uEnv.txt isn't there on all boards, nor required, you could just
do away with uEnv.txt completely, and trust the one compiled into
U-Boot which would be standardized anyway, and just trust the boot.scr
process to do any changes you need to make. That way all the boards
boot one way; U-Boot comes with a standardized environment compiled
in, and boot.scr is the thing it loads to further the boot process in
a distribution-specific way.
boot.scr, as above, is the part that is distribution-specific. It
needs to load from a certain device, the one U-Boot found it on or was
directed to boot from. In environments where there is only one boot
method (for instance, a single SD card slot) bootcmd may just be a
loop through several valid filesystems, culminating in some
environment being set (temporarily, please never saveenv in boot.scr!)
which allows boot.scr to know
a) how to load other files from that media where it can be applied to
common argument list for another command
b) what to load and where to load it
e.g.
setenv loadcmd "${fs}load ${device} ${unit}:${part}"
${loadcmd} ${address_to_load_to} ${filename_to_load}
The address to load to is probably properly defined in the
environment, but if it's not this is a good reason to redefine
uEnv.txt. In the case of a fixed memory start and size, the memory map
is defined in U-Boot but could be done in the script just as well
since the distro will know what location to boot from. In the case of
a dynamic memory start (MX6 does this, it can be 0x10000000 or
0x80000000) or size (with SO-DIMM for example) the script should not
be playing with this value, so it makes sense not to define this in
the script, but to use a standard set of environment variables to
define these addresses, and importantly define these SEPERATELY from
the U-Boot standard ${loadaddr} which means a very specific thing and
has very specific actions - it is the DEFAULT address to load to, if
you for example say "mmc dev 0; mmc part 1; fatload uImage" it will
fill in the blanks for missing device, unit, partition from the
currently selected entities, and use ${loadaddr} to put the file. This
is NOT ALWAYS the place you want your kernel! The example is a good
reason to define ${loadcmd} with specific device, unit and partition
entries too since otherwise the device unit and partition is basically
undefined, random and/or dependent on user fiddling before running
"run bootcmd" if they paused the autoboot process.
So what you'd need are basically an address defined ${kerneladdr},
${ramdiskaddr}, ${dtbaddr} or so which are the arguments for common
bootm or bootz. These need to be set to safe places in the memory map
and these should be hardcoded into U-Boot or provided in a
known-to-be-safe uEnv.txt. The names aren't important, but they're the
places these things are *to be loaded to* and they SHOULD be the same
as the addresses *to be relocated to* in the event they do not match
the configuration. In this sense, what should really happen is people
quit using bootm to source uImage files, and just use zImage and raw
ramdisks. Or fix U-Boot to take a perfectly invalid "load address" or
"entry point" in a uImage header to mean "don't relocate me", or
define a flag in the uImage format that says "do not relocate this
under any circumstances". U-Boot has no idea about what it's doing to
the file in regards to ANY other file you're loading into memory, nor
the constraints around the addresses you want those files at, so
relocation can give non-deterministic behavior, and it also involves
memory copies which slow down boot. U-Boot and Distro would need to
"cooperate" on their use of addresses passed to mkimage to reduce this
if possible. Distro SHOULD also endeavour to not compress any uImage
since in the vast majority of cases, the kernel is pre-compressed
(gzip, lzo, bzip, xz, whatever) and decompresses itself. -C none
should be the default in mkimage for distros. Ramdisks are almost
always compressed, and the kernel will either decompress it fully
(gzipped cpio archive or so) on it's own terms or do it on the fly
(squashfs or so). Either way it has much better compression options
than U-Boot can support (gzip, and that's it). So -C none makes no
sense here anyway unless you are architecturally bound to gzip, and it
would also force a kind of relocation (decompression to another
location than the load address) which is therefore both redundant and
somewhat non-deterministic too. Compressing boot.scr files only makes
sense if your script is absolutely massive, otherwise most of them
check out at about 900 bytes maximum (the biggest we've ever made was
still less than a memory page) - saving yourself 30% on 4KiB isn't
going to save you from any noticable disk access. At the end of the
day though as long as U-Boot is safe within itself in terms of
decompressing the script (i.e. if it does it (and it does currently)
from top of memory and you define your addresses in the low part)
"source" will run it fine and this decompression is quite safe. The
Distro should determine whether compressing a boot.scr is a good idea.
Device trees... also not a lot of point but it COULD happen, but where
it decompresses to MUST be 16-byte (or is it 16KiB?) aligned or
__vet_atags will NULL the pointer. It could also be decompressed to a
place the kernel can't reach or overwrites at random (during
decompression of kernel image). It's safer not to.
And that's it.. other operating systems should either write custom
boot.scr scripts with custom addresses OR re-use kernel, ramdisk, dtb
addr variables for it's own use (or for cleanliness, copy dtbaddr to a
well-named one and use that as the third argument to bootm or bootz,
assuming of course that it follows the Linux kernel entry convention)
or if it is a wonderfully smart or integrated operating system, just
kerneladdr or loadaddr and it can find the rest of the system on it's
own or from it's filesystem or so (Solaris used to do this, Windows
does this, MacOS does this).
The one thing I have never been able to resolve writing bootloaders is
what the memory map should be. Usually what I end up with is, a place
to put the boot script (lets call this scriptaddr), a place for device
tree, place for kernel, place for ramdisk - in that order, in the low
memory map. We usually need to keep 0x100 upwards to a reasonable
amount of memory for legacy ATAGs for the board. So the first address
(where the boot script is loaded to) is usually 32KiB into the memory
map. We add 32KiB and put the dtb there. We add 64KiB (can a device
tree really get that big?) and then the kernel goes there. Add 16MiB
and put the ramdisk there. The ramdisk is a pretty arbitrarily sized
thing, putting it before the kernel means you end up with "I cant'
load ramdisks bigger than n MiB" problems which we've experienced
before. It would be unheard of for a COMPRESSED Linux kernel to be
more than 16MiB though. I find it hard to believe you could have one
uncompressed amassing that amount of code, either (with all the
modules and the kernel image I think my linux-virtual image on VMWare
is about 32MiB added together, though. That's with EVERY module Ubuntu
tries to do, and would assume they are linked into the kernel to be
bigger than 16MiB. Unless Ubuntu want to do static, super-monolithic
kernels, it will never happen IMO...). Your ramdisk is then just
bounded by the limits of the kernel, if I'm putting my kernel at 64KiB
and have 16MiB space for it, and my ramdisk loads there.. automatic
zrel address location requires the kernel entry point to be less than
128MiB into the memory map but I think this is before decompression
(right?) so it's just got to not overwrite the U-Boot stack (probably
around 16MiB at the top of memory including all the binaries,
segments, malloc space and stack). If it's done after decompression my
ramdisk is limited to 128MiB-16MiB-64KiB-SizeOfDecompressedKernel so
it can actually be inside that 128MiB. I'll have to look into that
again... but who's going to make a 100MiB ramdisk anyway, boot from SD
card and NOT use the SD card filesystem? It seems to rare to care
about.
> that can perform all bootup initialization is preferable- no need to
> regenerate boot.scr, which is sometimes not practical (EG, you're creating
> installations on a system without mkimage, or you're half-booted and in
> emergency recovery shell and your initramfs didn't include mkimage).
Why would you be creating installations on a system without mkimage?
How would you prep your kernel?
I think what you're really talking about here is a way for U-Boot to
load a boot.scr file that isn't encoded inside a uImage header, all it
needs to know at this point though is the length of the file so that
"source" knows where it can stop parsing (otherwise it will run the
risk of not having a null terminator and it running into otherwise
unprotected but unwise to access memory).
Like I said, the way we do it on the Efika MX is that the U-Boot
environment (old U-Boot, stored in NOR; new U-Boot, built-in to U-Boot
and not changeable) defines the bootcmd string and that's it. That's
all U-Boot knows as standard apart from loadaddr. There is no bootmmc,
booteth, bootsata, or other env to "run," and it does not really need
them. If you start coding those you have to take into account the
configurability, for instance bootmmc would need variables in the
environment to know which device and partition to use, the filename,
the load addresses for each component shouldn't be hardcoded into the
bootmmc variable. What could be quite simple standardizing the
environment for these variables implies and infers more environment
variables, some unique to some systems and some common, but definitely
not ALL common and standardizable.
As I understand this, the discussion is just talking about how to make
life easier on Linux distributions so they don't have to know about
non-standard U-Boot messes, but this just isn't possible. flash-kernel
on Debian worked fine and could be JUST more modular but, no offense
Loic, making it data driven is what is driving this discussion as a
whole. What should have been less work is now a cross-distro
discussion of why it doesn't really meet real life. What would make
flash-kernel cleaner is if everyone updated their U-Boot.. which is
unlikely. If Linaro have their U-Boot work then they can engineer them
all to boot the same way. We already did this at Genesi, we took a
hint from the Marvell Dove code that was embedded into flash-kernel
and embedded it into our U-Boot so that we didn't have to restrict
everyone to putting boot.scr on a single device (since U-Boot is
capable of scripting looking for it). So Marvell Dove can do it too,
if it worked from boot.scr it will work from bootcmd. OMAP, the same
way. MX6Q SabreLite, we were disappointed that it went halfway and
then bailed and then called the script "6q_bootscript". We fixed that
internally here, now it boots from microSD, SD, SATA in that order
without changing any "boot option registers" or flashing anything to
SPI NOR (although we will have to eventually, the way the i.MX series
works means all we need is a USB cable to load our own U-Boot from any
old system with a USB port. Thanks Troy, Eric for imx_usb_loader so we
don't need Windows anymore :)
What we should do is not pick around talking but collect all the
relevant environments and boot.scr implementations and find the common
points. But I guarantee they all have at least one boot source
soldered to the board that is user-accessible (SD card, SATA drive,
USB port), where they have two it will be easy to dynamically search
for the right file in the right place, and if we fixate on the Linaro
SD card format (partition 1 == for U-Boot on OMAP or other devices,
partition 2 == /boot, partition 3 == /) and copy this for every
expected-to-be-bootable-device for the distro, that's the kind of
standardization we can achieve. The distro just needs the above, and
the ability to write a boot.scr, and we might want to fix
U-Boot-Linaro to be able to load a plaintext boot script instead of
encoding it with mkimage, and to ignore relocation with uImages anyway
at certain flags or impossible values (0xffffffff for example, since
this would nearly always be the top of the memory map if not far
beyond the end of RAM, except on 64-bit, but we'll get to that later),
right?
--
Matt Sealey <[email protected]>
Product Development Analyst, Genesi USA, Inc.
_______________________________________________
cross-distro mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/cross-distro