On Fri, Jul 27, 2012 at 2:31 PM, Stephen Warren swarren@wwwdotorg.org wrote:
On 07/26/2012 04:12 AM, Loïc Minier wrote:
On Wed, Jul 25, 2012, David Marlin wrote: [...]
Other boards provide similar features, including some (e.g., Trim-Slice) that 'scan' through a list of devices until a boot.scr is found, load it, and then boot using that script, but the load addresses are literals.
That's definitely a great feature which kinds of mimic the behavior of the SoC or of a BIOS to try to boot from multiple bootable devices.
Does anyone else think it would be useful to include a 'standard' set of such definitions in U-Boot (default) that could be used to abstract the board/vendor specific details and provide a more consistent user experience? If so, could this list be used to help define such a set, and encourage its use across ARM systems and distros?
Definitely; thanks for starting this!
There are various difficulties along the way:
...
- there's probably not an universal boot order for devices, so that this needs to remain configurable; it might be valid to try booting from the network and fallback to flash for some use cases, and it might be inappropriate in other cases, or the same story with SD/MMC vs. SATA etc.; this is probably the hardest problem; in some cases you might event want the end-user to be able to chose the method / boot order interactively (e.g. by pressing a button on beagleboards or by chosing from a menu on the serial console etc.)
The approach I took on Tegra was to have a U-Boot environment variable that defines the boot order. An example setting might be:
boot_targets=dhcp mmc1 mmc0 usb0
For details, see "4878343 tegra: bootcmd enhancements" in git://git.denx.de/u-boot-tegra.git master
With such a variable, one could have a completely standardized core bootcmd that iterates over boot_targets, with boot_targets being defined initially by the per-board U-Boot configuration file (to limit it to the set of devices the board has and apply default boot order policy) but which can also be over-ridden by the user by editing/saving the environment for customization. Perhaps we could even allow customization using an interactive menu system (I vaguely recall someone may have ported/been-porting barebox's menu system to U-Boot?)
cross-distro mailing list cross-distro@lists.linaro.org http://lists.linaro.org/mailman/listinfo/cross-distro
CCing Matt as this email comes from him.
FYI this is how we are doing it internally for Efika MX Smarttop and Smartbook - this U-Boot will get released fairly soon; sorry for the paste out of the code..
#define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0xffffffff\0" \ "initrd_high=0xffffffff\0" \ "model=" ADDR(CONFIG_EFIKAMX_MODEL) "\0" \ "firmware_version=" U_BOOT_TIMESTAMP "\0" \ "script=boot.scr\0" \ "kerneladdr=" ADDR(CONFIG_KERNEL_ADDR) "\0" \ "scriptaddr=" ADDR(CONFIG_SCRIPT_ADDR) "\0" \ "ramdiskaddr=" ADDR(CONFIG_RD_ADDR) "\0" \ "dtaddr=" ADDR(CONFIG_DT_ADDR) "\0" \ "bootdevices=mmc ide\0" \ "units=0\0" \ "console=ttymxc0,115200n8" /* * Note: make sure the last EXTRA_ENV_SETTINGS item has no null terminator! */
#define CONFIG_BOOTCOMMAND \ "for device in ${bootdevices}; do " \ "if test ${device} = "ide"; then " \ "ide reset; setenv units "0"; " \ "elif test ${device} = "mmc"; then " \ "mmc rescan; setenv units "1 0"; " \ "fi; " \ "for unit in ${units}; do " \ "${device} dev ${unit}; " \ "for part in "1 2 3"; do " \ "for fs in "ext2 fat"; do " \ "echo Trying ${device} ${unit}:${part},${fs} ..; " \ "setenv loadcmd "${fs}load ${device} ${unit}:${part}"; " \ "if ${loadcmd} ${scriptaddr} ${script}; then " \ "if imi ${scriptaddr}; then " \ "source ${scriptaddr}; " \ "fi; " \ "fi; " \ "done; " \ "done; " \ "done; " \ "done; "
Essentially bootdevices is the order devices are used, "mmc ide" here but on MX53, BoundaryDevices MX6 and other more capable SoCs and boards or so it might be "mmc usb sata" and on other devices, some other list of devices. This is hardcoded here as it's tied specifically to the board configuration at compile time, if we don't compile in USB then there's no point running the USB commands to scan for devices and then load files from them, there's also no point adding extra filesystems that U-Boot does not have compiled in, for example.
I'm sure the "fdt_load" variable is handy to be common across boards, but in the end this ends up being done in a boot.scr on our platforms. The actual *loading* step is always broken out into the boot.scr so that it can be replaced by the user (or developer) without messing with the U-Boot environment. Therefore ${soc}-${board}.dts may not be the name we define for our device tree, nor what the developer calls an in-development device tree, and since they can change this in their boot.scr source file, it doesn't really matter at the U-Boot environment level. We tried to define as little as possible in the environment, and only what the boot.scr script would require to actually do it's job (therefore we abstract load commands, filesystems etc, into environment variables). We define "model" as "mx" or "sb" just so we can do the firmware update process (u-boot.mx or u-boot.sb to fit 8.3 convention and not invoke a ton of VFAT craziness and bugginess) and the decision was that everything's going to be called efika-something anyway. firmware_version is the same way. This process is entirely board-specific and there for our customer's convenience of imaging an SD card with a special script that does The Right Thing(tm) for any system they plug it into.
Note that we do not bother to use bootcmd_mmc or bootcmd_base or do anything with bootargs in U-Boot - this is down to the operating system that generates a working boot.scr in our opinion. We also will not be shipping to customers with a "saveenv"-able environment - you get what you are given, so modifying the environment from the OS side will be impossible, since we want to make sure that an operating system does not accidentally trash the environment with weird variable definitions or removing variables that are needed.
While loadaddr and kerneladdr are identical on this board, actually this is just a legacy compatibility hack since we wanted to make sure kernels were loaded in a very specific place (${kerneladdr}) which may not actually be the same as the CONFIG_LOADADDR in any board configuration). We tried to keep the naming as OS-agnostic as possible. But anyway, we want to put the kernel at one place and make sure people hacking around in hush do not overwrite their loaded kernel by just typing "ext2load" or so.
In effect, there are far too many variables (not to mention actual environment variables) and different ways of booting to actually make this glue in the U-Boot environment worthwhile to standardize to the level of filenames and addresses. The variables that define the load addresses could be hardcoded in boot.scr just as well as being referenced through variables (especially if you want to change OS load behavior without updating firmware just to change a few addresses) and the variables that the script can make use of (${loadcmd} for example) would also be U-Boot specific if there is significant extra work to be done and the last two items in the command string aren't "address" and "filename".
Hardcoding filenames other than the boot script ("boot.scr" here, but one of the BoundaryDevices boards use 6q_bootscript by default, we made this the only "configurable" item regarding filenames because it is bootloader specific and not OS specific) should be frowned upon IMHO, and making any decisions that force a specifically Linux-based boot process would also be somewhat frowned upon (as long as the OS uses the same boot argument ABI such as ATAGs and register setup for device tree, a pointer to a mountable ramdisk or RAM storage area in certain registers as Linux, bootm, bootz will work identically for any OS..)