[U-Boot] [PATCH 1/2] image: Implement IH_TYPE_KERNEL_ANYLOAD

The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates just like IH_TYPE_KERNEL, except that the load address header is ignored, and U-Boot does not copy the image to its load address, but rather uses it in-place.
This is useful when sharing a single (uImage-wrapped) zImage across multiple boards with different memory layouts; in this case, a specific load address need not be picked when creating the uImage, but instead is selected by the board-specific U-Boot environment used to load and boot that image.
Signed-off-by: Stephen Warren swarren@nvidia.com --- This is a third attempt to support ARM Linux zImage's ability to run from anywhere in RAM.
This patch actually ended up being much smaller (patch file size) than previous attempts. Both my previous attempts could probably be rewritten to adjust the image load address in the same way as this patch and hence also be just as small; I don't recommend using any of my previous patches wthout rework because of this.
before this patch:
text data bss dec hex filename 166642 3568 217020 387230 5e89e ./u-boot
with this patch:
text data bss dec hex filename 166761 3568 217020 387349 5e915 ./u-boot
Is this small enough to do without a config option? I certainly hope so, because ifdefing every one of these tiny code changes would look ugly.
Tested on NVIDIA Tegra Seaboard:
* Legacy uImage containing a kernel (and appended DT), of type IH_TYPE_KERNEL.
* Legacy uImage containing a kernel (and appended DT), of type IH_TYPE_KERNEL_ANYLOAD.
* Legacy uImage containing a kernel, of type IH_TYPE_KERNEL_ANYLOAD, plus a separate plain FDT (no uImage wrapping).
* Legacy uImage containing a kernel, of type IH_TYPE_KERNEL_ANYLOAD, plus a uImage-wrapped initrd, plus a separate plain FDT (no uImage wrapping).
* FIT image containing both kernel of type IH_TYPE_KERNEL_ANYLOAD and FDT.
* FIT image containing just a kernel of type IH_TYPE_KERNEL_ANYLOAD, plus a separate plain FDT (no FIT/legacy uImage wrapping).
common/cmd_bootm.c | 10 +++++++++- common/image.c | 1 + include/image.h | 1 + tools/default_image.c | 3 ++- 4 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index d301332..2e9df58 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -271,7 +271,13 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] return 1; }
+ if (images.os.type == IH_TYPE_KERNEL_ANYLOAD) { + images.os.load = images.os.image_start; + images.ep += images.os.load; + } + if (((images.os.type == IH_TYPE_KERNEL) || + (images.os.type == IH_TYPE_KERNEL_ANYLOAD) || (images.os.type == IH_TYPE_MULTI)) && (images.os.os == IH_OS_LINUX)) { /* find ramdisk */ @@ -795,7 +801,8 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify) }
show_boot_progress(106); - if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL)) { + if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) && + !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_ANYLOAD)) { puts("Not a kernel image\n"); show_boot_progress(-106); return 0; @@ -873,6 +880,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, /* get os_data and os_len */ switch (image_get_type(hdr)) { case IH_TYPE_KERNEL: + case IH_TYPE_KERNEL_ANYLOAD: *os_data = image_get_data(hdr); *os_len = image_get_data_size(hdr); break; diff --git a/common/image.c b/common/image.c index 555d9d9..8e66e01 100644 --- a/common/image.c +++ b/common/image.c @@ -136,6 +136,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, + { IH_TYPE_KERNEL_ANYLOAD, "kernel_anyload", "Kernel Image (any load address)", }, { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, { IH_TYPE_INVALID, NULL, "Invalid Image", }, diff --git a/include/image.h b/include/image.h index c56a18d..1b3f40a 100644 --- a/include/image.h +++ b/include/image.h @@ -162,6 +162,7 @@ #define IH_TYPE_UBLIMAGE 11 /* Davinci UBL Image */ #define IH_TYPE_OMAPIMAGE 12 /* TI OMAP Config Header Image */ #define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */ +#define IH_TYPE_KERNEL_ANYLOAD 14 /* OS Kernel Image, can run from any load address */
/* * Compression Types diff --git a/tools/default_image.c b/tools/default_image.c index 6ea3b46..bfcaf76 100644 --- a/tools/default_image.c +++ b/tools/default_image.c @@ -35,7 +35,8 @@ static image_header_t header;
static int image_check_image_types(uint8_t type) { - if ((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT)) + if (((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT)) || + (type == IH_TYPE_KERNEL_ANYLOAD)) return EXIT_SUCCESS; else return EXIT_FAILURE;

bootm_load_os() detects when it writes the decompressed image over the top of the compressed image. If this happens, the original image is corrupted. When the original image is a multi-component legacy image, or a (potentially multi-component) FIT image, this implies that other components may be corrupted. In turn, this means that booting is unlikely to be successful.
However, in the case of no image compresssion coupled with an image with load address equal to where the image is already located (e.g. an XIP kernel, or IH_TYPE_KERNEL_ANYLOAD), there has been no copy and hence no corruption, no matter whether it's a single-component legacy image, a multi-component legacy image, or a FIT image. In this case, disable the overlap detection, and allow boot to continue.
Without this change, when booting a single-component legacy image that contains an IH_TYPE_KERNEL_ANYLOAD, bootm_load_os() would have returned BOOTM_ERR_OVERLAP, but the caller ignores this, and boot continues and succeeds. Now, the false error is no longer even returned.
Without this change, when booting a FIT image that contains an IH_TYPE_KERNEL_ANYLOAD, bootm_load_os() would have returned BOOTM_ERR_OVERLAP, which would then cause the caller to reset the board. Now, the false error is no longer returned, and boot succeeds.
Signed-off-by: Stephen Warren swarren@nvidia.com --- common/cmd_bootm.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 2e9df58..8f3c97f 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -319,6 +319,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) ulong image_start = os.image_start; ulong image_len = os.image_len; uint unc_len = CONFIG_SYS_BOOTM_LEN; + int no_overlap = 0; #if defined(CONFIG_LZMA) || defined(CONFIG_LZO) int ret; #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ @@ -329,6 +330,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) case IH_COMP_NONE: if (load == blob_start || load == image_start) { printf(" XIP %s ... ", type_name); + no_overlap = 1; } else { printf(" Loading %s ... ", type_name); memmove_wd((void *)load, (void *)image_start, @@ -423,7 +425,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) if (boot_progress) show_boot_progress(7);
- if ((load < blob_end) && (*load_end > blob_start)) { + if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) { debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,

The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates just like IH_TYPE_KERNEL, except that the load address header is ignored, and U-Boot does not copy the image to its load address, but rather uses it in-place.
This is useful when sharing a single (uImage-wrapped) zImage across multiple boards with different memory layouts; in this case, a specific load address need not be picked when creating the uImage, but instead is selected by the board-specific U-Boot environment used to load and boot that image.
Signed-off-by: Stephen Warren swarren@nvidia.com
Hi Stephen,
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
M

On 11/10/2011 02:58 AM, Marek Vasut wrote:
The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates just like IH_TYPE_KERNEL, except that the load address header is ignored, and U-Boot does not copy the image to its load address, but rather uses it in-place.
This is useful when sharing a single (uImage-wrapped) zImage across multiple boards with different memory layouts; in this case, a specific load address need not be picked when creating the uImage, but instead is selected by the board-specific U-Boot environment used to load and boot that image.
Signed-off-by: Stephen Warren swarren@nvidia.com
Hi Stephen,
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.

On 11/10/2011 02:58 AM, Marek Vasut wrote:
The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates just like IH_TYPE_KERNEL, except that the load address header is ignored, and U-Boot does not copy the image to its load address, but rather uses it in-place.
This is useful when sharing a single (uImage-wrapped) zImage across multiple boards with different memory layouts; in this case, a specific load address need not be picked when creating the uImage, but instead is selected by the board-specific U-Boot environment used to load and boot that image.
Signed-off-by: Stephen Warren swarren@nvidia.com
Hi Stephen,
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.
Well DAMN. I think I'll probably implement bootz, because it seems superior solution which I DID NEED for one of my devices for a while now (if noone is working on it already). I can't say what ETA will be on that, maybe next week, maybe two weeks.
M

On 11/10/2011 10:01 AM, Marek Vasut wrote:
On 11/10/2011 02:58 AM, Marek Vasut wrote:
[Description of IH_TYPE_KERNEL_ANYLOAD]
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.
Well DAMN. I think I'll probably implement bootz, because it seems superior solution which I DID NEED for one of my devices for a while now (if noone is working on it already). I can't say what ETA will be on that, maybe next week, maybe two weeks.
Out of curiosity, why doesn't this bootm feature work for you? Admittedly you still need to wrap the zImage inside a uImage, but I don't think that's insurmountable? Aside from that, doesn't it work exactly like a bootz command would?

On 11/10/2011 10:01 AM, Marek Vasut wrote:
On 11/10/2011 02:58 AM, Marek Vasut wrote:
[Description of IH_TYPE_KERNEL_ANYLOAD]
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.
Well DAMN. I think I'll probably implement bootz, because it seems superior solution which I DID NEED for one of my devices for a while now (if noone is working on it already). I can't say what ETA will be on that, maybe next week, maybe two weeks.
Out of curiosity, why doesn't this bootm feature work for you? Admittedly you still need to wrap the zImage inside a uImage, but I don't think that's insurmountable? Aside from that, doesn't it work exactly like a bootz command would?
Do you still have those +12bytes (sizeof(uImage header)) offset there? I don't like it. Also, I think using zImage might be plain easier.
M

On 11/10/2011 10:47 AM, Marek Vasut wrote:
On 11/10/2011 10:01 AM, Marek Vasut wrote:
On 11/10/2011 02:58 AM, Marek Vasut wrote:
[Description of IH_TYPE_KERNEL_ANYLOAD]
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.
Well DAMN. I think I'll probably implement bootz, because it seems superior solution which I DID NEED for one of my devices for a while now (if noone is working on it already). I can't say what ETA will be on that, maybe next week, maybe two weeks.
Out of curiosity, why doesn't this bootm feature work for you? Admittedly you still need to wrap the zImage inside a uImage, but I don't think that's insurmountable? Aside from that, doesn't it work exactly like a bootz command would?
Do you still have those +12bytes (sizeof(uImage header)) offset there? I don't like it.
The uImage file itself certainly includes the uImage header.
The code in my latest patches should be pointing images.os.load right at the image start itself (i.e. pointing past the header), so I don't think there's any incorrect offset within the code. This was really just a bug in the "-1 load address" patches I posted anyway.
Also, I think using zImage might be plain easier.
Well, admittedly it's slightly simpler not to wrap zImage in uImage, since there's no need to run mkimage. However, with this new IH_TYPE, all the mkimage parameters can be hard-coded (there's no need to specify any real value for the addresses; just use 0), so the command-line is pretty simple. Besides, I imagine the kernel uImage target can be updated (or a new one added) to continue to do this for you.
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Still, I'm not a distro vendor, so I don't know what their feelings are on this topic.

On 11/10/2011 10:47 AM, Marek Vasut wrote:
On 11/10/2011 10:01 AM, Marek Vasut wrote:
On 11/10/2011 02:58 AM, Marek Vasut wrote:
> [Description of IH_TYPE_KERNEL_ANYLOAD]
just a silly question, but didn't we agree on cmd_bootz? Or is this unrelated ?
bootz did seem to be agreed upon initially, but Wolfgang's most recent response suggested that a new IH_TYPE would be acceptable, and it's a lot less code to implement. At a later point, bootz could still be implemented if desired.
Well DAMN. I think I'll probably implement bootz, because it seems superior solution which I DID NEED for one of my devices for a while now (if noone is working on it already). I can't say what ETA will be on that, maybe next week, maybe two weeks.
Out of curiosity, why doesn't this bootm feature work for you? Admittedly you still need to wrap the zImage inside a uImage, but I don't think that's insurmountable? Aside from that, doesn't it work exactly like a bootz command would?
Do you still have those +12bytes (sizeof(uImage header)) offset there? I don't like it.
The uImage file itself certainly includes the uImage header.
The code in my latest patches should be pointing images.os.load right at the image start itself (i.e. pointing past the header), so I don't think there's any incorrect offset within the code. This was really just a bug in the "-1 load address" patches I posted anyway.
Also, I think using zImage might be plain easier.
Well, admittedly it's slightly simpler not to wrap zImage in uImage, since there's no need to run mkimage. However, with this new IH_TYPE, all the mkimage parameters can be hard-coded (there's no need to specify any real value for the addresses; just use 0), so the command-line is pretty simple. Besides, I imagine the kernel uImage target can be updated (or a new one added) to continue to do this for you.
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
Well if you want an image where you have kernel+initrd, why not use initramfs ?
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Hm, isn't FDT supposed to contain the command line now ?
Still, I'm not a distro vendor, so I don't know what their feelings are on this topic.
It's good to discuss stuff actually! It only mustn't turn into flamewar ;-)
M

On 11/10/2011 11:07 AM, Marek Vasut wrote:
Stephen Warren wrote:
...
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
Well if you want an image where you have kernel+initrd, why not use initramfs ?
As I understand it, initramfs is embedded into the kernel image, and initrd is a separate file.
(existing desktop) distros typically want their initrd as a separate file, so they can rebuild the initrd separately from the kernel image - i.e. ship a binary zImage for the kernel, but build the initrd at (distro or kernel update) install time based on whether the user needs RAID, LVM, crypto, random driver, ... modules or not. Rebuilding a separate initrd file is pretty easy. Rebuilding the initramfs already embedded into the kernel zImage is probably not.
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Hm, isn't FDT supposed to contain the command line now ?
Well, I don't think FDT supoprt is far enough along for any (ARM) SoC that a distro could exclusively rely on it yet. But, I may be wrong. I'm also thinking only of mainline; downstream support may be far more advanced in many cases.
Either way, the physical mechanism of passing the command-line to the kernel (ATAGs vs. FDT) isn't relevant to this discussion; it's just a transport mechanism.
Distros will probably still need to adjust the command-line, e.g. to add "quiet splash" to it or not based on whether a recovery or regular boot is required.
The idea is that the board vendor will supply the FDT image somehow, with either a minimal Linux cmdline or perhaps even none at all. The FDT might be stored in some non-filesystem location; perhaps embedded into U-Boot, perhaps in SPI/NOR/NAND flash without a filesystem. As such, the distro can't expect to be able to directly modify the FDT contents at install time in order to set up the cmdline it wants. Even if the FDT were stored in /boot/fdt.uimg, the distro would probably be well advised not to manipulate it on disk, to make it easier for an end-user to install an updated FDT with bugfixes.
Instead, U-Boot must write the cmdline into the FDT/ATAG when it boots the kernel, and the value it writes may need to be manipulated by the distro, I assume by the distro providing a U-Boot script to do the manipulation.

On 11/10/2011 11:07 AM, Marek Vasut wrote:
Stephen Warren wrote:
...
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
Well if you want an image where you have kernel+initrd, why not use initramfs ?
As I understand it, initramfs is embedded into the kernel image, and initrd is a separate file.
(existing desktop) distros typically want their initrd as a separate file, so they can rebuild the initrd separately from the kernel image - i.e. ship a binary zImage for the kernel, but build the initrd at (distro or kernel update) install time based on whether the user needs RAID, LVM, crypto, random driver, ... modules or not. Rebuilding a separate initrd file is pretty easy. Rebuilding the initramfs already embedded into the kernel zImage is probably not.
This is definitelly a good point. But then, if you can load zImage, can't you load initrd with u-boot?
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Hm, isn't FDT supposed to contain the command line now ?
Well, I don't think FDT supoprt is far enough along for any (ARM) SoC that a distro could exclusively rely on it yet. But, I may be wrong. I'm also thinking only of mainline; downstream support may be far more advanced in many cases.
Either way, the physical mechanism of passing the command-line to the kernel (ATAGs vs. FDT) isn't relevant to this discussion; it's just a transport mechanism.
Distros will probably still need to adjust the command-line, e.g. to add "quiet splash" to it or not based on whether a recovery or regular boot is required.
That's true, but you can have the generic command line in FDT and then pass changed command line through u-boot environment. I don't see a reason why you'd want to push it into uImage.
The idea is that the board vendor will supply the FDT image somehow, with either a minimal Linux cmdline or perhaps even none at all. The FDT might be stored in some non-filesystem location; perhaps embedded into U-Boot, perhaps in SPI/NOR/NAND flash without a filesystem. As such, the distro can't expect to be able to directly modify the FDT contents at install time in order to set up the cmdline it wants. Even if the FDT were stored in /boot/fdt.uimg, the distro would probably be well advised not to manipulate it on disk, to make it easier for an end-user to install an updated FDT with bugfixes.
Instead, U-Boot must write the cmdline into the FDT/ATAG when it boots the kernel, and the value it writes may need to be manipulated by the distro, I assume by the distro providing a U-Boot script to do the manipulation.
Exactly, so the command line has nothing to do with uImage.
So basically, in the end, we need to 1) load zImage, 2) load initrd and 3) adjust command line. 1) and 2) can be done via standard commands, 3) via some script.
M

Dear Marek Vasut,
In message 201111101940.40863.marek.vasut@gmail.com you wrote:
So basically, in the end, we need to 1) load zImage, 2) load initrd and 3) adjust command line. 1) and 2) can be done via standard commands, 3) via some script.
Actually there is a _little_ more to do for the boot loader. There are obvious functions (like passing information about size and addresses of avialable memory), less obvious things (like inserting the MAC addresses for the network interfaces into the device tree, thus passing them to the LInux kernel - something that has been impossible so far in ARM land), and even adaption of the device troo to the actual hardware - boards that come in different versions canuse this do disable non-existing (on this board) function blocks in the DT, etc. etc.
Best regards,
Wolfgang Denk

Dear Marek Vasut,
In message 201111101940.40863.marek.vasut@gmail.com you wrote:
So basically, in the end, we need to 1) load zImage, 2) load initrd and 3) adjust command line. 1) and 2) can be done via standard commands, 3) via some script.
Actually there is a _little_ more to do for the boot loader. There are obvious functions (like passing information about size and addresses of avialable memory), less obvious things (like inserting the MAC addresses for the network interfaces into the device tree, thus passing them to the LInux kernel - something that has been impossible so far in ARM land), and even adaption of the device troo to the actual hardware - boards that come in different versions canuse this do disable non-existing (on this board) function blocks in the DT, etc. etc.
Of course, but for that we have external functions (or functions which can be made external).
M

On 11/10/2011 11:40 AM, Marek Vasut wrote:
On 11/10/2011 11:07 AM, Marek Vasut wrote:
Stephen Warren wrote:
...
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
Well if you want an image where you have kernel+initrd, why not use initramfs ?
As I understand it, initramfs is embedded into the kernel image, and initrd is a separate file.
(existing desktop) distros typically want their initrd as a separate file, so they can rebuild the initrd separately from the kernel image - i.e. ship a binary zImage for the kernel, but build the initrd at (distro or kernel update) install time based on whether the user needs RAID, LVM, crypto, random driver, ... modules or not. Rebuilding a separate initrd file is pretty easy. Rebuilding the initramfs already embedded into the kernel zImage is probably not.
This is definitelly a good point. But then, if you can load zImage, can't you load initrd with u-boot?
Well maybe. I don't exactly follow what you're saying. My main point was the if you need/want an initrd (which I think will become more common), you're going to have to use mkimage to get U-Boot to accept it. If you're using mkimage on the initrd anyway, then using mkimage on the zImage seems like basically no extra work; just one more command to run using tools you already have. I /think/ the only advantage of a bootz command over bootm is the ability not to run mkimage on the zImage. Hence, there's not much advantage to a bootz command.
Still, if you don't have an initrd, I guess a bootz command would save you the mkimage step on the zImage.
Either way, I'm not really arguing against a bootz command; just pointing out that in many cases it doesn't buy you that much. Still, it does in other cases.
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Hm, isn't FDT supposed to contain the command line now ?
Well, I don't think FDT supoprt is far enough along for any (ARM) SoC that a distro could exclusively rely on it yet. But, I may be wrong. I'm also thinking only of mainline; downstream support may be far more advanced in many cases.
Either way, the physical mechanism of passing the command-line to the kernel (ATAGs vs. FDT) isn't relevant to this discussion; it's just a transport mechanism.
Distros will probably still need to adjust the command-line, e.g. to add "quiet splash" to it or not based on whether a recovery or regular boot is required.
That's true, but you can have the generic command line in FDT and then pass changed command line through u-boot environment. I don't see a reason why you'd want to push it into uImage.
How can you get the cmdline modifications into U-Boot other that through a (uImage-based) U-Boot script? I don't think a distro installer is going to grovel in U-Boot's saved environment and modify that to its wishes (and even if it could, it shouldn't)

On 11/10/2011 11:40 AM, Marek Vasut wrote:
On 11/10/2011 11:07 AM, Marek Vasut wrote:
Stephen Warren wrote:
...
I did consider that not running mkimage at all would be simpler, but there are other places mkimage would still be needed anyway:
a) Any initrd would still need to be wrapped in a uImage for bootm to recognize it. If you wrote a bootz to accept a raw unwrapped initrd, I imagine that same raw initrd recognition code could just as easily be applied to bootm.
Well if you want an image where you have kernel+initrd, why not use initramfs ?
As I understand it, initramfs is embedded into the kernel image, and initrd is a separate file.
(existing desktop) distros typically want their initrd as a separate file, so they can rebuild the initrd separately from the kernel image - i.e. ship a binary zImage for the kernel, but build the initrd at (distro or kernel update) install time based on whether the user needs RAID, LVM, crypto, random driver, ... modules or not. Rebuilding a separate initrd file is pretty easy. Rebuilding the initramfs already embedded into the kernel zImage is probably not.
This is definitelly a good point. But then, if you can load zImage, can't you load initrd with u-boot?
Well maybe. I don't exactly follow what you're saying. My main point was the if you need/want an initrd (which I think will become more common), you're going to have to use mkimage to get U-Boot to accept it. If you're using mkimage on the initrd anyway, then using mkimage on the zImage seems like basically no extra work; just one more command to run using tools you already have. I /think/ the only advantage of a bootz command over bootm is the ability not to run mkimage on the zImage. Hence, there's not much advantage to a bootz command.
Still, if you don't have an initrd, I guess a bootz command would save you the mkimage step on the zImage.
Well you're contradicting to yourself. You said using initramfs is bad because distros won't have easy way to change it. Now you say adding initrd to uImage via mkimage is good. Why the heck can't we just load zImage and initrd without the envelope at all, uboot can do that?
Either way, I'm not really arguing against a bootz command; just pointing out that in many cases it doesn't buy you that much. Still, it does in other cases.
b) The distro will most likely want to specify either the entire Linux command-line, or at least something to append to it. I imagine this will work by the distro creating a uImage-wrapped U-Boot script e.g. /boot/script.uimg. Creating that script would require mkimage too. Perhaps again U-Boot could be modified to support loading scripts from disk and executing them without requiring a uImage header though.
So, I don't think eliminating mkimage entirely is all that likely. And as such, using mkimage for the kernel itself doesn't seem like a big deal.
Hm, isn't FDT supposed to contain the command line now ?
Well, I don't think FDT supoprt is far enough along for any (ARM) SoC that a distro could exclusively rely on it yet. But, I may be wrong. I'm also thinking only of mainline; downstream support may be far more advanced in many cases.
Either way, the physical mechanism of passing the command-line to the kernel (ATAGs vs. FDT) isn't relevant to this discussion; it's just a transport mechanism.
Distros will probably still need to adjust the command-line, e.g. to add "quiet splash" to it or not based on whether a recovery or regular boot is required.
That's true, but you can have the generic command line in FDT and then pass changed command line through u-boot environment. I don't see a reason why you'd want to push it into uImage.
How can you get the cmdline modifications into U-Boot other that through a (uImage-based) U-Boot script? I don't think a distro installer is going to grovel in U-Boot's saved environment and modify that to its wishes (and even if it could, it shouldn't)
No, but uboot can (and often does) source a script on the same device storing zImage and initrd. You just adjust the script.

Dear Marek Vasut,
In message 201111101907.39470.marek.vasut@gmail.com you wrote:
Well if you want an image where you have kernel+initrd, why not use initramfs ?
Because it may be nice to have this separate, so you can change one and leave the other in place? Or download them separately, only if needed? etc. etc.
Hm, isn't FDT supposed to contain the command line now ?
You can pass the command line there. as you can hard-code a command line in the kernel image.
Guess how many U-Boot users actually do that, and how many _love_ the flexibility they get from "bootargs"?
Best regards,
Wolfgang Denk

Dear Stephen Warren,
In message 1320860840-6347-1-git-send-email-swarren@nvidia.com you wrote:
The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent
You write: an example is...
Are there other Linux kernel image types in addition to zImage that have this property?
this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates
I don't like this name. "ANYLOAD" doesn't really make sense to me; I would interpet this as "U-Boot is free to load the image to any address it likes" - which is not what I think you mean. I guess "IH_TYPE_KERNEL_NOLOAD" would better mach what the code is supposed to do.
But then, I'd like "IH_TYPE_ZIMAGE" even better - assuming of course that only zImages are used here. Are we sure about this?
- if (images.os.type == IH_TYPE_KERNEL_ANYLOAD) {
images.os.load = images.os.image_start;
images.ep += images.os.load;
- }
I'm not sure if we give up flexibility here without need.
Suggestion: IH_TYPE_KERNEL_NOLOAD images should read the entry point address from the image header, and interpret it as an offset relative to the image_start. This adds basicly no code size, an no effort if you don't want to use it (when running mkimage you will probably always use "-a 0 -e 0" anyway), but in case you ever need a different EP you have it, more or less for free.
- { IH_TYPE_KERNEL_ANYLOAD, "kernel_anyload", "Kernel Image (any load address)", },
...IH_TYPE_KERNEL_NOLOAD ..."Kernel Image (no loading done)" ?
Best regards,
Wolfgang Denk

On 11/10/2011 04:59 AM, Wolfgang Denk wrote:
Dear Stephen Warren,
In message 1320860840-6347-1-git-send-email-swarren@nvidia.com you wrote:
The legacy uImage format includes an absolute load and entry-point address. When bootm operates on a kernel uImage in memory that isn't loaded at the address in the image's load address, U-Boot will copy the image to its address in the header.
Some kernel images can actually be loaded and used at any arbitrary address. An example is an ARM Linux kernel zImage file. To represent
You write: an example is...
Are there other Linux kernel image types in addition to zImage that have this property?
I'm sorry, I really don't know.
Note that I even specifically said /ARM/ Linux kernel zImage, because I have no idea if zImage on other architectures is relocatable or not.
this capability, IH_TYPE_KERNEL_ANYLOAD is implemented, which operates
I don't like this name. "ANYLOAD" doesn't really make sense to me; I would interpet this as "U-Boot is free to load the image to any address it likes" - which is not what I think you mean.
I think ANYLOAD describes the situation correctly:
For IH_TYPE_KERNEL, the image is physically loaded to whatever address the U-Boot environment/script loads it to, and then U-Boot relocates the image to the load address in the header if it's not already there (for uncompressed images).
With ANYLOAD, there is still a load address (wherever the U-Boot environment/script placed the image), yet any load address is accepted without relocation rather than just the one specified in the image header, so U-Boot always just skips the relocation.
Put another way: extload/fatload load the image, and bootm just relocates/copies the image rather than loads it.
I guess "IH_TYPE_KERNEL_NOLOAD" would better match what the code is supposed to do.
I did consider that name too, but decided not to use it given my explanation above. I can rename it if you want though.
But then, I'd like "IH_TYPE_ZIMAGE" even better - assuming of course that only zImages are used here. Are we sure about this?
I deliberately didn't pick ZIMAGE, since I can't say for certain that only zImages are relocatable across all kernel image formats across all architectures. And note that ANYLOAD could well be applicable to non-Linux OSs for all I know; bootm appears to be able to boot a whole variety of other OSs, and I wouldn't be entirely surprised if at least one of them had fully relocatable images like ARM Linux kernel zImages.
- if (images.os.type == IH_TYPE_KERNEL_ANYLOAD) {
images.os.load = images.os.image_start;
images.ep += images.os.load;
- }
I'm not sure if we give up flexibility here without need.
Suggestion: IH_TYPE_KERNEL_NOLOAD images should read the entry point address from the image header, and interpret it as an offset relative to the image_start.
Isn't that exactly what the code is doing; note ep is calculated as += not just =.
This adds basicly no code size, an no effort if you don't want to use it (when running mkimage you will probably always use "-a 0 -e 0" anyway), but in case you ever need a different EP you have it, more or less for free.
- { IH_TYPE_KERNEL_ANYLOAD, "kernel_anyload", "Kernel Image (any load address)", },
...IH_TYPE_KERNEL_NOLOAD ..."Kernel Image (no loading done)" ?
Perhaps "(no relocation)"?

Dear Stephen Warren,
In message 4EBBF894.2000409@nvidia.com you wrote:
I don't like this name. "ANYLOAD" doesn't really make sense to me; I would interpet this as "U-Boot is free to load the image to any address it likes" - which is not what I think you mean.
I think ANYLOAD describes the situation correctly:
Sorry about the nitpicking, but I disagree.
For IH_TYPE_KERNEL, the image is physically loaded to whatever address the U-Boot environment/script loads it to, and then U-Boot relocates the image to the load address in the header if it's not already there (for uncompressed images).
In principle you are right, butthe terms you are using are not really correct. "Relocate" has a well-defined meaning, and includes the modification of addresses to adapt the relocated code to it's now position in memory. This is not what's going on.
U-Boot is given an image that is stored somewhere in memory (that's the "M" in "bootm": boot an image in memory), and it _copies_ (or loads) it to the "load address", eventually uncompressing it in this process.
With ANYLOAD, there is still a load address (wherever the U-Boot environment/script placed the image), yet any load address is accepted
No. In the zImage case, U-Boot does exactly NOT perform the loading (= copying) to the address given in the "load adress" header entry. It just leaves the image wherever it happens to bein memory. This is why I would like to call this "NO LOAD" - because no loading is done.
without relocation rather than just the one specified in the image header, so U-Boot always just skips the relocation.
In no case any relocation is ever done by the "bootm" command.
Put another way: extload/fatload load the image, and bootm just relocates/copies the image rather than loads it.
Wrong. "bootm" loads the image from it's original location in memory to the address given in the "load address" entry of the image header. That's why this field is named ih_load : "Data Load Address".
I guess "IH_TYPE_KERNEL_NOLOAD" would better match what the code is supposed to do.
I did consider that name too, but decided not to use it given my explanation above. I can rename it if you want though.
Please reconsider.
I deliberately didn't pick ZIMAGE, since I can't say for certain that only zImages are relocatable across all kernel image formats across all architectures. And note that ANYLOAD could well be applicable to non-Linux OSs for all I know; bootm appears to be able to boot a whole variety of other OSs, and I wouldn't be entirely surprised if at least one of them had fully relocatable images like ARM Linux kernel zImages.
No. "bootm" follows exactly the Linux kernel calling conventions in all details from passing specific values in specific registers, putting specific data at certain addresses / address ranges, etc. "bootm" is to boot Linux. I am not aware of any other OS that can be successfully booted with the "bootm" command (and ifso, it probably gould be started with "go" as well).
- if (images.os.type == IH_TYPE_KERNEL_ANYLOAD) {
images.os.load = images.os.image_start;
images.ep += images.os.load;
- }
I'm not sure if we give up flexibility here without need.
Suggestion: IH_TYPE_KERNEL_NOLOAD images should read the entry point address from the image header, and interpret it as an offset relative to the image_start.
Isn't that exactly what the code is doing; note ep is calculated as += not just =.
Oops. I have to admit that I overlooked the +=. But that - where is the value set that you are adding to?
...IH_TYPE_KERNEL_NOLOAD ..."Kernel Image (no loading done)" ?
Perhaps "(no relocation)"?
Definitely not. There is no relocation involved anywhere here.
Best regards,
Wolfgang Denk

On 11/10/2011 11:53 AM, Wolfgang Denk wrote:
Dear Stephen Warren,
In message 4EBBF894.2000409@nvidia.com you wrote:
I don't like this name. "ANYLOAD" doesn't really make sense to me; I would interpet this as "U-Boot is free to load the image to any address it likes" - which is not what I think you mean.
I think ANYLOAD describes the situation correctly:
Sorry about the nitpicking, but I disagree.
OK, I'll rework the patch based on your desired naming.
However, I do wish to point out that U-Boot's use of the term "load" for what is really a "copy"/"move" is incorrect according to the typically accepted meaning of the word "load". The extload/fatload commands use "load" correctly. I admit relocate is also not a correct phrase to describe what's happening.
...
I deliberately didn't pick ZIMAGE, since I can't say for certain that only zImages are relocatable across all kernel image formats across all architectures. And note that ANYLOAD could well be applicable to non-Linux OSs for all I know; bootm appears to be able to boot a whole variety of other OSs, and I wouldn't be entirely surprised if at least one of them had fully relocatable images like ARM Linux kernel zImages.
No. "bootm" follows exactly the Linux kernel calling conventions in all details from passing specific values in specific registers, putting specific data at certain addresses / address ranges, etc. "bootm" is to boot Linux. I am not aware of any other OS that can be successfully booted with the "bootm" command (and ifso, it probably gould be started with "go" as well).
I didn't want to burden my previous email with details, and I quite admit I may be wrong here since I'm not familiar with U-Boot's code, but what about the following in cmd_bootm.c:
static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_LINUX [IH_OS_LINUX] = do_bootm_linux, #endif #ifdef CONFIG_BOOTM_NETBSD [IH_OS_NETBSD] = do_bootm_netbsd, #endif #ifdef CONFIG_LYNXKDI [IH_OS_LYNXOS] = do_bootm_lynxkdi, #endif #ifdef CONFIG_BOOTM_RTEMS [IH_OS_RTEMS] = do_bootm_rtems, #endif #if defined(CONFIG_BOOTM_OSE) [IH_OS_OSE] = do_bootm_ose, #endif #if defined(CONFIG_CMD_ELF) [IH_OS_VXWORKS] = do_bootm_vxworks, [IH_OS_QNX] = do_bootm_qnxelf, #endif #ifdef CONFIG_INTEGRITY [IH_OS_INTEGRITY] = do_bootm_integrity, #endif };
Don't they allow the bootm command to boot other OSs? Those functions certainly appear to be called at the end of cmd_bootm() to do the actual kernel parameter setup and boot.

Dear Stephen Warren,
In message 4EBC2096.905@nvidia.com you wrote:
OK, I'll rework the patch based on your desired naming.
Thanks.
However, I do wish to point out that U-Boot's use of the term "load" for what is really a "copy"/"move" is incorrect according to the typically accepted meaning of the word "load". The extload/fatload commands use "load" correctly. I admit relocate is also not a correct phrase to describe what's happening.
I agree that these terms are often used intermixed, and few people actually think about their meaning. [Just look up in the mailing list how many people complained that "bootm" did not work when they "loaded" the images to the address given in the "load adress" field.]
However, I still think that as far as "bootm" is related, the term "load" is the correct one. Quoting for example wikipedia:
In computing, a loader is the part of an operating system that is responsible for loading programs. It is one of the essential stages in the process of starting a program, as it places programs into memory and prepares them for execution. Loading a program involves reading the contents of executable file, the file containing the program text, into memory, and then carrying out other required preparatory tasks to prepare the executable for running. Once loading is complete, the operating system starts the program by passing control to the loaded program code.
[http://en.wikipedia.org/wiki/Program_loader]
As for extload/fatload - well, these perform "loading" functions to, in the sense of "reading the contents of a file into memory".
I agree that these terms are often used intermixed, and few people actually think about their meaning. [Just look up in the mailing list how many people complained that "bootm" did not work when they "loaded" the images to the address given in the "load adress" field.]
However, I still think that as far as "bootm" is related, the term "load" is the correct one. Quoting for example wikipedia:
In computing, a loader is the part of an operating system that is responsible for loading programs. It is one of the essential stages in the process of starting a program, as it places programs into memory and prepares them for execution. Loading a program involves reading the contents of executable file, the file containing the program text, into memory, and then carrying out other required preparatory tasks to prepare the executable for running. Once loading is complete, the operating system starts the program by passing control to the loaded program code.
[http://en.wikipedia.org/wiki/Program_loader]
As for extload/fatload - well, these perform "loading" functions to, in the sense of "reading the contents of a file into memory". But I don't think much thought was spent on these names when they were chosen...
"bootm" is to boot Linux. I am not aware of any other OS that can be successfully booted with the "bootm" command (and ifso, it probably gould be started with "go" as well).
I didn't want to burden my previous email with details, and I quite admit I may be wrong here since I'm not familiar with U-Boot's code, but what about the following in cmd_bootm.c:
Indeed, you are right. I had completely forgotten about these. Heck, how long didn't I use any of these any more...
Don't they allow the bootm command to boot other OSs? Those functions certainly appear to be called at the end of cmd_bootm() to do the actual kernel parameter setup and boot.
Yes, you are right. Please ignore my comment.
Best regards,
Wolfgang Denk
participants (3)
-
Marek Vasut
-
Stephen Warren
-
Wolfgang Denk