diff mbox

[U-Boot,V6] BOOT: Add "bootz" command to boot Linux zImage on ARM

Message ID 1331797965-7415-1-git-send-email-marex@denx.de
State Accepted
Headers show

Commit Message

Marek Vasut March 15, 2012, 7:52 a.m. UTC
From: Marek Vasut <marek.vasut@gmail.com>

This command boots Linux zImage from where the zImage is loaded to. Passing
initrd and fdt is supported.

Tested on i.MX28 based DENX M28EVK
Tested on PXA270 based Voipac PXA270.

NOTE: This currently only supports ARM, but other architectures can be easily
added by defining bootz_setup().

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Tom Warren <TWarren@nvidia.com>
Cc: albert.u.boot@aribaud.net
Cc: afleming@gmail.com,
Cc: Simon Glass <sjg@chromium.org>,
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Nicolas Pitre <nico@fluxnic.net>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 README                   |    8 +++
 arch/arm/lib/bootm.c     |   30 ++++++++++
 common/cmd_bootm.c       |  141 +++++++++++++++++++++++++++++++++++++++++++---
 include/config_cmd_all.h |    1 +
 4 files changed, 171 insertions(+), 9 deletions(-)

V2: Use CONFIG_BOOTZ_MAX_KERNEL_LMB_SIZE to reserve kernel LMB
V3: Compute the LMB size at runtime (obsoletes V2)
    Move shared code to image.c/image.h
    Sync with latest U-Boot
V4: Add all this into cmd_bootm. Therefore, this is part of cmd_bootm (basically
    it's stripped-down version). Also, separate out arm-specific component into
    arm-specific location.
V5: Staticize bootz_setup(), add information into README.
V6: Make cmd_bootz() static.

Comments

Rob Herring March 15, 2012, 6:51 p.m. UTC | #1
On 03/15/2012 02:52 AM, Marek Vasut wrote:
> From: Marek Vasut <marek.vasut@gmail.com>
> 
> This command boots Linux zImage from where the zImage is loaded to. Passing
> initrd and fdt is supported.
> 

This is great! However, the initrd is still in the u-boot image format,
right?

If a raw initrd is supported, then we could get rid of flash-kernel on
disk-based debian/ubuntu systems. The file size is known from the
filesystem, but then needs to get to the bootz command somehow.

Rob

> Tested on i.MX28 based DENX M28EVK
> Tested on PXA270 based Voipac PXA270.
> 
> NOTE: This currently only supports ARM, but other architectures can be easily
> added by defining bootz_setup().
> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Tom Warren <TWarren@nvidia.com>
> Cc: albert.u.boot@aribaud.net
> Cc: afleming@gmail.com,
> Cc: Simon Glass <sjg@chromium.org>,
> Cc: Stephen Warren <swarren@nvidia.com>
> Cc: Nicolas Pitre <nico@fluxnic.net>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  README                   |    8 +++
>  arch/arm/lib/bootm.c     |   30 ++++++++++
>  common/cmd_bootm.c       |  141 +++++++++++++++++++++++++++++++++++++++++++---
>  include/config_cmd_all.h |    1 +
>  4 files changed, 171 insertions(+), 9 deletions(-)
> 
> V2: Use CONFIG_BOOTZ_MAX_KERNEL_LMB_SIZE to reserve kernel LMB
> V3: Compute the LMB size at runtime (obsoletes V2)
>     Move shared code to image.c/image.h
>     Sync with latest U-Boot
> V4: Add all this into cmd_bootm. Therefore, this is part of cmd_bootm (basically
>     it's stripped-down version). Also, separate out arm-specific component into
>     arm-specific location.
> V5: Staticize bootz_setup(), add information into README.
> V6: Make cmd_bootz() static.
> 
> diff --git a/README b/README
> index 4021715..b273070 100644
> --- a/README
> +++ b/README
> @@ -3594,6 +3594,7 @@ go	- start application at address 'addr'
>  run	- run commands in an environment variable
>  bootm	- boot application image from memory
>  bootp	- boot image via network using BootP/TFTP protocol
> +bootz   - boot zImage from memory
>  tftpboot- boot image via network using TFTP protocol
>  	       and env variables "ipaddr" and "serverip"
>  	       (and eventually "gatewayip")
> @@ -4414,6 +4415,13 @@ U-Boot supports the following image types:
>  	useful when you configure U-Boot to use a real shell (hush)
>  	as command interpreter.
>  
> +Booting the Linux zImage:
> +-------------------------
> +
> +On some platforms, it's possible to boot Linux zImage. This is done
> +using the "bootz" command. The syntax of "bootz" command is the same
> +as the syntax of "bootm" command.
> +
>  
>  Standalone HOWTO:
>  =================
> diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
> index afa0093..ec46d76 100644
> --- a/arch/arm/lib/bootm.c
> +++ b/arch/arm/lib/bootm.c
> @@ -344,3 +344,33 @@ static ulong get_sp(void)
>  	asm("mov %0, sp" : "=r"(ret) : );
>  	return ret;
>  }
> +
> +#ifdef CONFIG_CMD_BOOTZ
> +
> +struct zimage_header {
> +	uint32_t	code[9];
> +	uint32_t	zi_magic;
> +	uint32_t	zi_start;
> +	uint32_t	zi_end;
> +};
> +
> +#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
> +
> +int bootz_setup(void *image, void **start, void **end)
> +{
> +	struct zimage_header *zi = (struct zimage_header *)image;
> +
> +	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
> +		puts("Bad Linux ARM zImage magic!\n");
> +		return 1;
> +	}
> +
> +	*start = (void *)zi->zi_start;
> +	*end = (void *)zi->zi_end;
> +
> +	debug("Kernel image @ 0x%08x [ 0x%08x - 0x%08x ]\n",
> +		(uint32_t)image, (uint32_t)*start, (uint32_t)*end);
> +
> +	return 0;
> +}
> +#endif	/* CONFIG_CMD_BOOTZ */
> diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
> index d5745b1..b49d4f7 100644
> --- a/common/cmd_bootm.c
> +++ b/common/cmd_bootm.c
> @@ -169,25 +169,25 @@ void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
>  
>  #define IH_INITRD_ARCH IH_ARCH_DEFAULT
>  
> -static void bootm_start_lmb(void)
> -{
>  #ifdef CONFIG_LMB
> +static void boot_start_lmb(bootm_headers_t *images)
> +{
>  	ulong		mem_start;
>  	phys_size_t	mem_size;
>  
> -	lmb_init(&images.lmb);
> +	lmb_init(&images->lmb);
>  
>  	mem_start = getenv_bootm_low();
>  	mem_size = getenv_bootm_size();
>  
> -	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
> +	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
>  
> -	arch_lmb_reserve(&images.lmb);
> -	board_lmb_reserve(&images.lmb);
> +	arch_lmb_reserve(&images->lmb);
> +	board_lmb_reserve(&images->lmb);
> +}
>  #else
> -# define lmb_reserve(lmb, base, size)
> +static inline void boot_start_lmb(bootm_headers_t *images) { }
>  #endif
> -}
>  
>  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
> @@ -197,7 +197,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
>  	memset((void *)&images, 0, sizeof(images));
>  	images.verify = getenv_yesno("verify");
>  
> -	bootm_start_lmb();
> +	boot_start_lmb(&images);
>  
>  	/* get kernel image header, start address and length */
>  	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
> @@ -1523,3 +1523,126 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[],
>  	return 1;
>  }
>  #endif
> +
> +#ifdef CONFIG_CMD_BOOTZ
> +
> +static int __bootz_setup(void *image, void **start, void **end)
> +{
> +	/* Please define bootz_setup() for your platform */
> +
> +	puts("Your platform's zImage format isn't supported yet!\n");
> +	return -1;
> +}
> +int bootz_setup(void *image, void **start, void **end)
> +	__attribute__((weak, alias("__bootz_setup")));
> +
> +/*
> + * zImage booting support
> + */
> +static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
> +			char * const argv[], bootm_headers_t *images)
> +{
> +	int ret;
> +	void *zi_start, *zi_end;
> +
> +	memset(images, 0, sizeof(bootm_headers_t));
> +
> +	boot_start_lmb(images);
> +
> +	/* Setup Linux kernel zImage entry point */
> +	if (argc < 2) {
> +		images->ep = load_addr;
> +		debug("*  kernel: default image load address = 0x%08lx\n",
> +				load_addr);
> +	} else {
> +		images->ep = simple_strtoul(argv[1], NULL, 16);
> +		debug("*  kernel: cmdline image address = 0x%08lx\n",
> +			images->ep);
> +	}
> +
> +	ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
> +	if (ret != 0)
> +		return 1;
> +
> +	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
> +
> +	/* Find ramdisk */
> +	ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
> +			&images->rd_start, &images->rd_end);
> +	if (ret) {
> +		puts("Ramdisk image is corrupt or invalid\n");
> +		return 1;
> +	}
> +
> +#if defined(CONFIG_OF_LIBFDT)
> +	/* find flattened device tree */
> +	ret = boot_get_fdt(flag, argc, argv, images,
> +			   &images->ft_addr, &images->ft_len);
> +	if (ret) {
> +		puts("Could not find a valid device tree\n");
> +		return 1;
> +	}
> +
> +	set_working_fdt_addr(images->ft_addr);
> +#endif
> +
> +	return 0;
> +}
> +
> +static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	ulong		iflag;
> +	bootm_headers_t	images;
> +
> +	if (bootz_start(cmdtp, flag, argc, argv, &images))
> +		return 1;
> +
> +	/*
> +	 * We have reached the point of no return: we are going to
> +	 * overwrite all exception vector code, so we cannot easily
> +	 * recover from any failures any more...
> +	 */
> +	iflag = disable_interrupts();
> +
> +#if defined(CONFIG_CMD_USB)
> +	/*
> +	 * turn off USB to prevent the host controller from writing to the
> +	 * SDRAM while Linux is booting. This could happen (at least for OHCI
> +	 * controller), because the HCCA (Host Controller Communication Area)
> +	 * lies within the SDRAM and the host controller writes continously to
> +	 * this area (as busmaster!). The HccaFrameNumber is for example
> +	 * updated every 1 ms within the HCCA structure in SDRAM! For more
> +	 * details see the OpenHCI specification.
> +	 */
> +	usb_stop();
> +#endif
> +
> +#ifdef CONFIG_SILENT_CONSOLE
> +	fixup_silent_linux();
> +#endif
> +	arch_preboot_os();
> +
> +	do_bootm_linux(0, argc, argv, &images);
> +#ifdef DEBUG
> +	puts("\n## Control returned to monitor - resetting...\n");
> +#endif
> +	do_reset(cmdtp, flag, argc, argv);
> +
> +	return 1;
> +}
> +
> +U_BOOT_CMD(
> +	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
> +	"boot Linux zImage image from memory",
> +	"[addr [initrd] [fdt]]\n    - boot Linux zImage stored in memory\n"
> +	"\tThe argument 'initrd' is optional and specifies the address\n"
> +	"\tof the initrd in memory.\n"
> +#if defined(CONFIG_OF_LIBFDT)
> +	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
> +	"\ta third argument is required which is the address of the\n"
> +	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
> +	"\tuse a '-' for the second argument. If you do not pass a third\n"
> +	"\ta bd_info struct will be passed instead\n"
> +#endif
> +);
> +#endif	/* CONFIG_CMD_BOOTZ */
> diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
> index 9716f9c..2c6b829 100644
> --- a/include/config_cmd_all.h
> +++ b/include/config_cmd_all.h
> @@ -20,6 +20,7 @@
>  #define CONFIG_CMD_BEDBUG	/* Include BedBug Debugger	*/
>  #define CONFIG_CMD_BMP		/* BMP support			*/
>  #define CONFIG_CMD_BOOTD	/* bootd			*/
> +#define CONFIG_CMD_BOOTZ	/* boot zImage			*/
>  #define CONFIG_CMD_BSP		/* Board Specific functions	*/
>  #define CONFIG_CMD_CACHE	/* icache, dcache		*/
>  #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
Marek Vasut March 15, 2012, 7:05 p.m. UTC | #2
Dear Rob Herring,

> On 03/15/2012 02:52 AM, Marek Vasut wrote:
> > From: Marek Vasut <marek.vasut@gmail.com>
> > 
> > This command boots Linux zImage from where the zImage is loaded to.
> > Passing initrd and fdt is supported.
> 
> This is great! However, the initrd is still in the u-boot image format,
> right?
> 
> If a raw initrd is supported, then we could get rid of flash-kernel on
> disk-based debian/ubuntu systems. The file size is known from the
> filesystem, but then needs to get to the bootz command somehow.

Yes. Initrd still needs a bit of work, ideas?

Best regards,
Marek Vasut
Rob Herring March 15, 2012, 7:48 p.m. UTC | #3
On 03/15/2012 02:05 PM, Marek Vasut wrote:
> Dear Rob Herring,
> 
>> On 03/15/2012 02:52 AM, Marek Vasut wrote:
>>> From: Marek Vasut <marek.vasut@gmail.com>
>>>
>>> This command boots Linux zImage from where the zImage is loaded to.
>>> Passing initrd and fdt is supported.
>>
>> This is great! However, the initrd is still in the u-boot image format,
>> right?
>>
>> If a raw initrd is supported, then we could get rid of flash-kernel on
>> disk-based debian/ubuntu systems. The file size is known from the
>> filesystem, but then needs to get to the bootz command somehow.
> 
> Yes. Initrd still needs a bit of work, ideas?

How about:

bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]

I changed the order so the size can be optional without resorting to
using a "-". Then no size means u-boot image format.

File load commands would need to set loadsize env var.

Another idea is to prepend the u-boot image header on file loading. This
would need some way to disable the crc check and specify any other data.
It would probably be hard to do without changing existing commands.

Rob
Marek Vasut March 15, 2012, 8:29 p.m. UTC | #4
Dear Rob Herring,

> On 03/15/2012 02:05 PM, Marek Vasut wrote:
> > Dear Rob Herring,
> > 
> >> On 03/15/2012 02:52 AM, Marek Vasut wrote:
> >>> From: Marek Vasut <marek.vasut@gmail.com>
> >>> 
> >>> This command boots Linux zImage from where the zImage is loaded to.
> >>> Passing initrd and fdt is supported.
> >> 
> >> This is great! However, the initrd is still in the u-boot image format,
> >> right?
> >> 
> >> If a raw initrd is supported, then we could get rid of flash-kernel on
> >> disk-based debian/ubuntu systems. The file size is known from the
> >> filesystem, but then needs to get to the bootz command somehow.
> > 
> > Yes. Initrd still needs a bit of work, ideas?
> 

You lost some people in the Cc ;-)

> How about:
> 
> bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]

What about bootz <kern addr> <initrd addr>[:<initrd size>] <fdt addr>

example: bootz 0x12000000 0x13000000:0x40000 0x14000000

> 
> I changed the order so the size can be optional without resorting to
> using a "-". Then no size means u-boot image format.
> 
> File load commands would need to set loadsize env var.

If you load kernel after initrd, that's screw things up.
> 
> Another idea is to prepend the u-boot image header on file loading. This
> would need some way to disable the crc check and specify any other data.
> It would probably be hard to do without changing existing commands.

Naw, this is weird. What do you think about my idea with the addr:size stuff?
> 
> Rob

Best regards,
Marek Vasut
Wolfgang Denk March 15, 2012, 8:39 p.m. UTC | #5
Dear Rob,

In message <4F62479F.8070509@gmail.com> you wrote:
> 
> How about:
> 
> bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]

No.  We hav ebeen used for 12 years to the order first kernel address,
then ramdisk address (and a little less longer ), then dtb address.

Don't change this now, and don;t make it inconsistent for different
commands.

> I changed the order so the size can be optional without resorting to
> using a "-". Then no size means u-boot image format.
> 
> File load commands would need to set loadsize env var.

What's "loadsize"? 

> Another idea is to prepend the u-boot image header on file loading. This
> would need some way to disable the crc check and specify any other data.

CRC checking can be disabled by setting "verify" to "no" (RTFM).
The rest of the data is not really relevant here.  Also note that we
have enverything in place to compute the CRC, so you could implement a
real "mkimage" commands.  Assuming someone thinks this makes sense.

What is the problem of running this on the host?

> It would probably be hard to do without changing existing commands.

How so?

Best regards,

Wolfgang Denk
Rob Herring March 15, 2012, 9:10 p.m. UTC | #6
On 03/15/2012 03:29 PM, Marek Vasut wrote:
> Dear Rob Herring,
> 
>> On 03/15/2012 02:05 PM, Marek Vasut wrote:
>>> Dear Rob Herring,
>>>
>>>> On 03/15/2012 02:52 AM, Marek Vasut wrote:
>>>>> From: Marek Vasut <marek.vasut@gmail.com>
>>>>>
>>>>> This command boots Linux zImage from where the zImage is loaded to.
>>>>> Passing initrd and fdt is supported.
>>>>
>>>> This is great! However, the initrd is still in the u-boot image format,
>>>> right?
>>>>
>>>> If a raw initrd is supported, then we could get rid of flash-kernel on
>>>> disk-based debian/ubuntu systems. The file size is known from the
>>>> filesystem, but then needs to get to the bootz command somehow.
>>>
>>> Yes. Initrd still needs a bit of work, ideas?
>>
> 
> You lost some people in the Cc ;-)
> 

They weren't in the original email header, only in the commit log as Cc's.

>> How about:
>>
>> bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]
> 
> What about bootz <kern addr> <initrd addr>[:<initrd size>] <fdt addr>
> 
> example: bootz 0x12000000 0x13000000:0x40000 0x14000000
> 

Sure. That works for me.

>>
>> I changed the order so the size can be optional without resorting to
>> using a "-". Then no size means u-boot image format.
>>
>> File load commands would need to set loadsize env var.
> 
> If you load kernel after initrd, that's screw things up.

Yes, but you already have to be aware of some commands which will change
env vars. This has to be script-able to be useful. The only other way I
see is adding a command to get the size of a file. Perhaps the ls
commands when given a single file can do that.

Rob

>>
>> Another idea is to prepend the u-boot image header on file loading. This
>> would need some way to disable the crc check and specify any other data.
>> It would probably be hard to do without changing existing commands.
> 
> Naw, this is weird. What do you think about my idea with the addr:size stuff?
>>
>> Rob
> 
> Best regards,
> Marek Vasut
Rob Herring March 15, 2012, 10:02 p.m. UTC | #7
On 03/15/2012 04:10 PM, Rob Herring wrote:
> On 03/15/2012 03:29 PM, Marek Vasut wrote:
>> Dear Rob Herring,
>>
>>> On 03/15/2012 02:05 PM, Marek Vasut wrote:
>>>> Dear Rob Herring,
>>>>
>>>>> On 03/15/2012 02:52 AM, Marek Vasut wrote:
>>>>>> From: Marek Vasut <marek.vasut@gmail.com>
>>>>>>
>>>>>> This command boots Linux zImage from where the zImage is loaded to.
>>>>>> Passing initrd and fdt is supported.
>>>>>
>>>>> This is great! However, the initrd is still in the u-boot image format,
>>>>> right?
>>>>>
>>>>> If a raw initrd is supported, then we could get rid of flash-kernel on
>>>>> disk-based debian/ubuntu systems. The file size is known from the
>>>>> filesystem, but then needs to get to the bootz command somehow.
>>>>
>>>> Yes. Initrd still needs a bit of work, ideas?
>>>
>>
>> You lost some people in the Cc ;-)
>>
> 
> They weren't in the original email header, only in the commit log as Cc's.
> 
>>> How about:
>>>
>>> bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]
>>
>> What about bootz <kern addr> <initrd addr>[:<initrd size>] <fdt addr>
>>
>> example: bootz 0x12000000 0x13000000:0x40000 0x14000000
>>
> 
> Sure. That works for me.
> 
>>>
>>> I changed the order so the size can be optional without resorting to
>>> using a "-". Then no size means u-boot image format.
>>>
>>> File load commands would need to set loadsize env var.
>>
>> If you load kernel after initrd, that's screw things up.
> 
> Yes, but you already have to be aware of some commands which will change
> env vars. This has to be script-able to be useful. The only other way I
> see is adding a command to get the size of a file. Perhaps the ls
> commands when given a single file can do that.

Turns out there is already a filesize variable that gets set on file
load commands.

And RTFM didn't help as that one is not documented... ;)

Rob
Marek Vasut March 16, 2012, 12:53 a.m. UTC | #8
Dear Rob Herring,

> On 03/15/2012 04:10 PM, Rob Herring wrote:
> > On 03/15/2012 03:29 PM, Marek Vasut wrote:
> >> Dear Rob Herring,
> >> 
> >>> On 03/15/2012 02:05 PM, Marek Vasut wrote:
> >>>> Dear Rob Herring,
> >>>> 
> >>>>> On 03/15/2012 02:52 AM, Marek Vasut wrote:
> >>>>>> From: Marek Vasut <marek.vasut@gmail.com>
> >>>>>> 
> >>>>>> This command boots Linux zImage from where the zImage is loaded to.
> >>>>>> Passing initrd and fdt is supported.
> >>>>> 
> >>>>> This is great! However, the initrd is still in the u-boot image
> >>>>> format, right?
> >>>>> 
> >>>>> If a raw initrd is supported, then we could get rid of flash-kernel
> >>>>> on disk-based debian/ubuntu systems. The file size is known from the
> >>>>> filesystem, but then needs to get to the bootz command somehow.
> >>>> 
> >>>> Yes. Initrd still needs a bit of work, ideas?
> >> 
> >> You lost some people in the Cc ;-)
> > 
> > They weren't in the original email header, only in the commit log as
> > Cc's.
> > 
> >>> How about:
> >>> 
> >>> bootz <kern addr> [<fdt addr> [<initrd addr> [<initrd size>]]]
> >> 
> >> What about bootz <kern addr> <initrd addr>[:<initrd size>] <fdt addr>
> >> 
> >> example: bootz 0x12000000 0x13000000:0x40000 0x14000000
> > 
> > Sure. That works for me.
> > 
> >>> I changed the order so the size can be optional without resorting to
> >>> using a "-". Then no size means u-boot image format.
> >>> 
> >>> File load commands would need to set loadsize env var.
> >> 
> >> If you load kernel after initrd, that's screw things up.
> > 
> > Yes, but you already have to be aware of some commands which will change
> > env vars. This has to be script-able to be useful. The only other way I
> > see is adding a command to get the size of a file. Perhaps the ls
> > commands when given a single file can do that.
> 
> Turns out there is already a filesize variable that gets set on file
> load commands.
> 
> And RTFM didn't help as that one is not documented... ;)

Rob, I just send in support for RAW initrd. Can you give it a go?

Best regards,
Marek Vasut
Wolfgang Denk March 16, 2012, 7:16 a.m. UTC | #9
Dear Rob Herring,

In message <4F626711.8030808@gmail.com> you wrote:
>
> Turns out there is already a filesize variable that gets set on file
> load commands.
> 
> And RTFM didn't help as that one is not documented... ;)

Are you sure?  I'm pretty sure I can see it in the section of the
manual that deals with environment variables.  See
http://www.denx.de/wiki/view/DULG/UBootEnvVariables

You may have to scroll down to the end of the file.

Best regards,

Wolfgang Denk
Rob Herring March 16, 2012, 6:20 p.m. UTC | #10
On 03/16/2012 02:16 AM, Wolfgang Denk wrote:
> Dear Rob Herring,
> 
> In message <4F626711.8030808@gmail.com> you wrote:
>>
>> Turns out there is already a filesize variable that gets set on file
>> load commands.
>>
>> And RTFM didn't help as that one is not documented... ;)
> 
> Are you sure?  I'm pretty sure I can see it in the section of the
> manual that deals with environment variables.  See
> http://www.denx.de/wiki/view/DULG/UBootEnvVariables
> 
> You may have to scroll down to the end of the file.

Okay. I was referring to the README and any other docs in the source tree.

Regards,
Rob
Wolfgang Denk March 30, 2012, 8:59 p.m. UTC | #11
Dear Marek Vasut,

In message <1331797965-7415-1-git-send-email-marex@denx.de> you wrote:
> From: Marek Vasut <marek.vasut@gmail.com>
> 
> This command boots Linux zImage from where the zImage is loaded to. Passing
> initrd and fdt is supported.
> 
> Tested on i.MX28 based DENX M28EVK
> Tested on PXA270 based Voipac PXA270.
> 
> NOTE: This currently only supports ARM, but other architectures can be easily
> added by defining bootz_setup().
> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Tom Warren <TWarren@nvidia.com>
> Cc: albert.u.boot@aribaud.net
> Cc: afleming@gmail.com,
> Cc: Simon Glass <sjg@chromium.org>,
> Cc: Stephen Warren <swarren@nvidia.com>
> Cc: Nicolas Pitre <nico@fluxnic.net>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  README                   |    8 +++
>  arch/arm/lib/bootm.c     |   30 ++++++++++
>  common/cmd_bootm.c       |  141 +++++++++++++++++++++++++++++++++++++++++++---
>  include/config_cmd_all.h |    1 +
>  4 files changed, 171 insertions(+), 9 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk
Mike Frysinger March 31, 2012, 7:10 p.m. UTC | #12
On Thursday 15 March 2012 03:52:45 Marek Vasut wrote:
> --- a/common/cmd_bootm.c
> +++ b/common/cmd_bootm.c
> 
> -static void bootm_start_lmb(void)
> -{
>  #ifdef CONFIG_LMB
> +static void boot_start_lmb(bootm_headers_t *images)
> +{
>  	ulong		mem_start;
>  	phys_size_t	mem_size;
> 
> -	lmb_init(&images.lmb);
> +	lmb_init(&images->lmb);
> 
>  	mem_start = getenv_bootm_low();
>  	mem_size = getenv_bootm_size();
> 
> -	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
> +	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
> 
> -	arch_lmb_reserve(&images.lmb);
> -	board_lmb_reserve(&images.lmb);
> +	arch_lmb_reserve(&images->lmb);
> +	board_lmb_reserve(&images->lmb);
> +}
>  #else
> -# define lmb_reserve(lmb, base, size)
> +static inline void boot_start_lmb(bootm_headers_t *images) { }
>  #endif
> -}

this breaks all non-lmb configs.  before, lmb_reverse() was stubbed out, but 
now it's not, leading to build failures:

cmd_bootm.c: In function ‘do_bootm_subcommand’:
cmd_bootm.c:518:23: error: ‘bootm_headers_t’ has no member named ‘lmb’
cmd_bootm.c: In function ‘do_bootm’:
cmd_bootm.c:665:21: error: ‘bootm_headers_t’ has no member named ‘lmb’
make[2]: *** [cmd_bootm.o] Error 1
-mike
Marek Vasut March 31, 2012, 7:27 p.m. UTC | #13
Dear Mike Frysinger,

> On Thursday 15 March 2012 03:52:45 Marek Vasut wrote:
> > --- a/common/cmd_bootm.c
> > +++ b/common/cmd_bootm.c
> > 
> > -static void bootm_start_lmb(void)
> > -{
> > 
> >  #ifdef CONFIG_LMB
> > 
> > +static void boot_start_lmb(bootm_headers_t *images)
> > +{
> > 
> >  	ulong		mem_start;
> >  	phys_size_t	mem_size;
> > 
> > -	lmb_init(&images.lmb);
> > +	lmb_init(&images->lmb);
> > 
> >  	mem_start = getenv_bootm_low();
> >  	mem_size = getenv_bootm_size();
> > 
> > -	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
> > +	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
> > 
> > -	arch_lmb_reserve(&images.lmb);
> > -	board_lmb_reserve(&images.lmb);
> > +	arch_lmb_reserve(&images->lmb);
> > +	board_lmb_reserve(&images->lmb);
> > +}
> > 
> >  #else
> > 
> > -# define lmb_reserve(lmb, base, size)
> > +static inline void boot_start_lmb(bootm_headers_t *images) { }
> > 
> >  #endif
> > 
> > -}
> 
> this breaks all non-lmb configs.  before, lmb_reverse() was stubbed out,
> but now it's not, leading to build failures:
> 
> cmd_bootm.c: In function ‘do_bootm_subcommand’:
> cmd_bootm.c:518:23: error: ‘bootm_headers_t’ has no member named ‘lmb’
> cmd_bootm.c: In function ‘do_bootm’:
> cmd_bootm.c:665:21: error: ‘bootm_headers_t’ has no member named ‘lmb’
> make[2]: *** [cmd_bootm.o] Error 1
> -mike

Well tested on arm/ppc ... can you submit patch for these platforms please ?

I'll be able to run mips/x86 next week.

Best regards,
Marek Vasut
Graeme Russ April 1, 2012, 11:25 a.m. UTC | #14
Hi Marek,

On 04/01/2012 05:27 AM, Marek Vasut wrote:
> Dear Mike Frysinger,
> 
>> On Thursday 15 March 2012 03:52:45 Marek Vasut wrote:
>>> --- a/common/cmd_bootm.c
>>> +++ b/common/cmd_bootm.c
>>>
>>> -static void bootm_start_lmb(void)
>>> -{
>>>
>>>  #ifdef CONFIG_LMB
>>>
>>> +static void boot_start_lmb(bootm_headers_t *images)
>>> +{
>>>
>>>  	ulong		mem_start;
>>>  	phys_size_t	mem_size;
>>>
>>> -	lmb_init(&images.lmb);
>>> +	lmb_init(&images->lmb);
>>>
>>>  	mem_start = getenv_bootm_low();
>>>  	mem_size = getenv_bootm_size();
>>>
>>> -	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
>>> +	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
>>>
>>> -	arch_lmb_reserve(&images.lmb);
>>> -	board_lmb_reserve(&images.lmb);
>>> +	arch_lmb_reserve(&images->lmb);
>>> +	board_lmb_reserve(&images->lmb);
>>> +}
>>>
>>>  #else
>>>
>>> -# define lmb_reserve(lmb, base, size)
>>> +static inline void boot_start_lmb(bootm_headers_t *images) { }
>>>
>>>  #endif
>>>
>>> -}
>>
>> this breaks all non-lmb configs.  before, lmb_reverse() was stubbed out,
>> but now it's not, leading to build failures:
>>
>> cmd_bootm.c: In function ‘do_bootm_subcommand’:
>> cmd_bootm.c:518:23: error: ‘bootm_headers_t’ has no member named ‘lmb’
>> cmd_bootm.c: In function ‘do_bootm’:
>> cmd_bootm.c:665:21: error: ‘bootm_headers_t’ has no member named ‘lmb’
>> make[2]: *** [cmd_bootm.o] Error 1
>> -mike
> 
> Well tested on arm/ppc ... can you submit patch for these platforms please ?

I think the 'You Break, You Fix' rule applies ;)

> I'll be able to run mips/x86 next week.

Dang, I need it building now :P

I'm going to but in some really dodgy hacks just to get my build going
again, but I would appreciate a fix ASAP

Regards,

Graeme
Marek Vasut April 1, 2012, 2:02 p.m. UTC | #15
Dear Graeme Russ,

> Hi Marek,
> 
> On 04/01/2012 05:27 AM, Marek Vasut wrote:
> > Dear Mike Frysinger,
> > 
> >> On Thursday 15 March 2012 03:52:45 Marek Vasut wrote:
> >>> --- a/common/cmd_bootm.c
> >>> +++ b/common/cmd_bootm.c
> >>> 
> >>> -static void bootm_start_lmb(void)
> >>> -{
> >>> 
> >>>  #ifdef CONFIG_LMB
> >>> 
> >>> +static void boot_start_lmb(bootm_headers_t *images)
> >>> +{
> >>> 
> >>>  	ulong		mem_start;
> >>>  	phys_size_t	mem_size;
> >>> 
> >>> -	lmb_init(&images.lmb);
> >>> +	lmb_init(&images->lmb);
> >>> 
> >>>  	mem_start = getenv_bootm_low();
> >>>  	mem_size = getenv_bootm_size();
> >>> 
> >>> -	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
> >>> +	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
> >>> 
> >>> -	arch_lmb_reserve(&images.lmb);
> >>> -	board_lmb_reserve(&images.lmb);
> >>> +	arch_lmb_reserve(&images->lmb);
> >>> +	board_lmb_reserve(&images->lmb);
> >>> +}
> >>> 
> >>>  #else
> >>> 
> >>> -# define lmb_reserve(lmb, base, size)
> >>> +static inline void boot_start_lmb(bootm_headers_t *images) { }
> >>> 
> >>>  #endif
> >>> 
> >>> -}
> >> 
> >> this breaks all non-lmb configs.  before, lmb_reverse() was stubbed out,
> >> but now it's not, leading to build failures:
> >> 
> >> cmd_bootm.c: In function ‘do_bootm_subcommand’:
> >> cmd_bootm.c:518:23: error: ‘bootm_headers_t’ has no member named ‘lmb’
> >> cmd_bootm.c: In function ‘do_bootm’:
> >> cmd_bootm.c:665:21: error: ‘bootm_headers_t’ has no member named ‘lmb’
> >> make[2]: *** [cmd_bootm.o] Error 1
> >> -mike
> > 
> > Well tested on arm/ppc ... can you submit patch for these platforms
> > please ?
> 
> I think the 'You Break, You Fix' rule applies ;)
> 
> > I'll be able to run mips/x86 next week.
> 
> Dang, I need it building now :P
> 
> I'm going to but in some really dodgy hacks just to get my build going
> again, but I would appreciate a fix ASAP
> 
> Regards,
> 
> Graeme

Sent.

Best regards,
Marek Vasut
diff mbox

Patch

diff --git a/README b/README
index 4021715..b273070 100644
--- a/README
+++ b/README
@@ -3594,6 +3594,7 @@  go	- start application at address 'addr'
 run	- run commands in an environment variable
 bootm	- boot application image from memory
 bootp	- boot image via network using BootP/TFTP protocol
+bootz   - boot zImage from memory
 tftpboot- boot image via network using TFTP protocol
 	       and env variables "ipaddr" and "serverip"
 	       (and eventually "gatewayip")
@@ -4414,6 +4415,13 @@  U-Boot supports the following image types:
 	useful when you configure U-Boot to use a real shell (hush)
 	as command interpreter.
 
+Booting the Linux zImage:
+-------------------------
+
+On some platforms, it's possible to boot Linux zImage. This is done
+using the "bootz" command. The syntax of "bootz" command is the same
+as the syntax of "bootm" command.
+
 
 Standalone HOWTO:
 =================
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index afa0093..ec46d76 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -344,3 +344,33 @@  static ulong get_sp(void)
 	asm("mov %0, sp" : "=r"(ret) : );
 	return ret;
 }
+
+#ifdef CONFIG_CMD_BOOTZ
+
+struct zimage_header {
+	uint32_t	code[9];
+	uint32_t	zi_magic;
+	uint32_t	zi_start;
+	uint32_t	zi_end;
+};
+
+#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
+
+int bootz_setup(void *image, void **start, void **end)
+{
+	struct zimage_header *zi = (struct zimage_header *)image;
+
+	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
+		puts("Bad Linux ARM zImage magic!\n");
+		return 1;
+	}
+
+	*start = (void *)zi->zi_start;
+	*end = (void *)zi->zi_end;
+
+	debug("Kernel image @ 0x%08x [ 0x%08x - 0x%08x ]\n",
+		(uint32_t)image, (uint32_t)*start, (uint32_t)*end);
+
+	return 0;
+}
+#endif	/* CONFIG_CMD_BOOTZ */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index d5745b1..b49d4f7 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -169,25 +169,25 @@  void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
 
 #define IH_INITRD_ARCH IH_ARCH_DEFAULT
 
-static void bootm_start_lmb(void)
-{
 #ifdef CONFIG_LMB
+static void boot_start_lmb(bootm_headers_t *images)
+{
 	ulong		mem_start;
 	phys_size_t	mem_size;
 
-	lmb_init(&images.lmb);
+	lmb_init(&images->lmb);
 
 	mem_start = getenv_bootm_low();
 	mem_size = getenv_bootm_size();
 
-	lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
+	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
 
-	arch_lmb_reserve(&images.lmb);
-	board_lmb_reserve(&images.lmb);
+	arch_lmb_reserve(&images->lmb);
+	board_lmb_reserve(&images->lmb);
+}
 #else
-# define lmb_reserve(lmb, base, size)
+static inline void boot_start_lmb(bootm_headers_t *images) { }
 #endif
-}
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -197,7 +197,7 @@  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 	memset((void *)&images, 0, sizeof(images));
 	images.verify = getenv_yesno("verify");
 
-	bootm_start_lmb();
+	boot_start_lmb(&images);
 
 	/* get kernel image header, start address and length */
 	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -1523,3 +1523,126 @@  static int do_bootm_integrity(int flag, int argc, char * const argv[],
 	return 1;
 }
 #endif
+
+#ifdef CONFIG_CMD_BOOTZ
+
+static int __bootz_setup(void *image, void **start, void **end)
+{
+	/* Please define bootz_setup() for your platform */
+
+	puts("Your platform's zImage format isn't supported yet!\n");
+	return -1;
+}
+int bootz_setup(void *image, void **start, void **end)
+	__attribute__((weak, alias("__bootz_setup")));
+
+/*
+ * zImage booting support
+ */
+static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[], bootm_headers_t *images)
+{
+	int ret;
+	void *zi_start, *zi_end;
+
+	memset(images, 0, sizeof(bootm_headers_t));
+
+	boot_start_lmb(images);
+
+	/* Setup Linux kernel zImage entry point */
+	if (argc < 2) {
+		images->ep = load_addr;
+		debug("*  kernel: default image load address = 0x%08lx\n",
+				load_addr);
+	} else {
+		images->ep = simple_strtoul(argv[1], NULL, 16);
+		debug("*  kernel: cmdline image address = 0x%08lx\n",
+			images->ep);
+	}
+
+	ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
+	if (ret != 0)
+		return 1;
+
+	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
+
+	/* Find ramdisk */
+	ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
+			&images->rd_start, &images->rd_end);
+	if (ret) {
+		puts("Ramdisk image is corrupt or invalid\n");
+		return 1;
+	}
+
+#if defined(CONFIG_OF_LIBFDT)
+	/* find flattened device tree */
+	ret = boot_get_fdt(flag, argc, argv, images,
+			   &images->ft_addr, &images->ft_len);
+	if (ret) {
+		puts("Could not find a valid device tree\n");
+		return 1;
+	}
+
+	set_working_fdt_addr(images->ft_addr);
+#endif
+
+	return 0;
+}
+
+static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	ulong		iflag;
+	bootm_headers_t	images;
+
+	if (bootz_start(cmdtp, flag, argc, argv, &images))
+		return 1;
+
+	/*
+	 * We have reached the point of no return: we are going to
+	 * overwrite all exception vector code, so we cannot easily
+	 * recover from any failures any more...
+	 */
+	iflag = disable_interrupts();
+
+#if defined(CONFIG_CMD_USB)
+	/*
+	 * turn off USB to prevent the host controller from writing to the
+	 * SDRAM while Linux is booting. This could happen (at least for OHCI
+	 * controller), because the HCCA (Host Controller Communication Area)
+	 * lies within the SDRAM and the host controller writes continously to
+	 * this area (as busmaster!). The HccaFrameNumber is for example
+	 * updated every 1 ms within the HCCA structure in SDRAM! For more
+	 * details see the OpenHCI specification.
+	 */
+	usb_stop();
+#endif
+
+#ifdef CONFIG_SILENT_CONSOLE
+	fixup_silent_linux();
+#endif
+	arch_preboot_os();
+
+	do_bootm_linux(0, argc, argv, &images);
+#ifdef DEBUG
+	puts("\n## Control returned to monitor - resetting...\n");
+#endif
+	do_reset(cmdtp, flag, argc, argv);
+
+	return 1;
+}
+
+U_BOOT_CMD(
+	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
+	"boot Linux zImage image from memory",
+	"[addr [initrd] [fdt]]\n    - boot Linux zImage stored in memory\n"
+	"\tThe argument 'initrd' is optional and specifies the address\n"
+	"\tof the initrd in memory.\n"
+#if defined(CONFIG_OF_LIBFDT)
+	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
+	"\ta third argument is required which is the address of the\n"
+	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+	"\tuse a '-' for the second argument. If you do not pass a third\n"
+	"\ta bd_info struct will be passed instead\n"
+#endif
+);
+#endif	/* CONFIG_CMD_BOOTZ */
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 9716f9c..2c6b829 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -20,6 +20,7 @@ 
 #define CONFIG_CMD_BEDBUG	/* Include BedBug Debugger	*/
 #define CONFIG_CMD_BMP		/* BMP support			*/
 #define CONFIG_CMD_BOOTD	/* bootd			*/
+#define CONFIG_CMD_BOOTZ	/* boot zImage			*/
 #define CONFIG_CMD_BSP		/* Board Specific functions	*/
 #define CONFIG_CMD_CACHE	/* icache, dcache		*/
 #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/