RFC: image: Reduce code duplication and refactor
Subsystems (5)
cover RFC: image: Reduce code duplication and refactor
In creating a new feature[*] I found that the image code includes quite a bit of duplication in places. In particular the code to load a kernel, FDT and ramdisk is all fairly similar, but subtly different.
This series introduces a new function fit_image_load() which loads an image from a FIT and supports the various features. For the bootstage updates, these are standardised so that each file has its own range and the events within that range have corresponding numbers. This means that the boot progress numbers will change slightly with this series.
The image.c file is still very long. Rather than perpetuate the #ifdefs in the code I have split out the image.c code that is dependent on CONFIG_OF_LIBFDT into image-fdt.c.
Several architectures have their own way of setting up a ramdisk and FDT for booting. An attempt is made here to unify these by providing a function image_setup_linux() to handle the overall task, and image_setup_fdt() to set up the FDT.
For ARM, the bootm code is a maze of #ifdefs, which means that many boards compile the code differently and it takes longer to detect breakages. To get around this, some defines are added to ARM's bootm.h to permit the use of if() instead of #ifdef, making use of the compiler's dead code elimination.
Also this series introduces a very basic test of image loading using sandbox. Some patches add bootm support for sandbox, and also a 'sb save' command to save memory to a host file (used to check that the bootm actually worked).
A test program for sandbox is added as a basic sanity check of image loading as performed by bootm.
This series depends on the verified boot series since it builds on the clean-up in that. You can get this series from:
http://git.denx.de/u-boot-x86.git
branch name 'image'.
* The new feature is support for FIT booting on x86, will get back to this later.
Simon Glass (22):
sandbox: Allow -c argument to provide a command list
sandbox: Support 'source' command
fs: Add support for saving data to filesystems
sandbox: fs: Add support for saving files to host filesystem
image: Split libfdt code into image-fdt.c
image: Add device tree setup to image library
arm: Refactor bootm to reduce #ifdefs
arm: Use image_setup_linux() instead of local code
powerpc: Use image_setup_linux() instead of local code
m68k: Use image_setup_linux() instead of local code
sparc: Use image_setup_linux() instead of local code
bootstage: Introduce sub-IDs for use with image loading
mkimage: Add map_sysmem() and IH_ARCH_DEFAULT to simplfy building
image: Introduce fit_image_load() to load images from FITs
image: Use fit_image_load() to load ramdisk
image: Use fit_image_load() to load FDT
sandbox: Adjust bootm command to work with sandbox
image: Use fit_image_load() to load kernel
sandbox: image: Adjust FIT image printing to work with sandbox
bootstage: Remove unused entries related to kernel/ramdisk/fdt load
sandbox: image: Create a test for loading FIT images
WIP: sandbox: config: Remove boot command
arch/arm/include/asm/bootm.h | 54 +++- arch/arm/include/asm/u-boot-arm.h | 2 - arch/arm/lib/Makefile | 1 + arch/arm/lib/bootm-fdt.c | 52 +++ arch/arm/lib/bootm.c | 145 +------- arch/m68k/lib/bootm.c | 15 +- arch/powerpc/lib/bootm.c | 84 +----- arch/sandbox/cpu/start.c | 2 +- arch/sparc/lib/bootm.c | 13 +- common/Makefile | 1 + common/cmd_bootm.c | 182 ++-------- common/cmd_sandbox.c | 18 +- common/cmd_source.c | 11 +- common/image-fdt.c | 512 +++++++++++++++++++++++++ common/image-fit.c | 293 +++++++++++----- common/image.c | 738 ++++--------------------------------- fs/fs.c | 75 ++++ fs/sandbox/sandboxfs.c | 33 ++ include/bootstage.h | 51 ++-- include/common.h | 9 + include/configs/sandbox.h | 1 - include/fdt_support.h | 2 - include/fs.h | 2 + include/image.h | 145 +++++++- include/lmb.h | 2 - include/sandboxfs.h | 1 + test/image/test-fit.py | 422 +++++++++++++++++++++ tools/mkimage.h | 12 + 28 files changed, 1674 insertions(+), 1204 deletions(-) create mode 100644 arch/arm/lib/bootm-fdt.c create mode 100644 common/image-fdt.c create mode 100755 test/image/test-fit.py
Signature · 1 line
1.7.7.3
RFC PATCH 1/22 sandbox: Allow -c argument to provide a command list
This allows passing of entire scripts to sandbox with the -c argument, which is useful for testing. Commands can be delimited with a newline or semicolon.
--- arch/sandbox/cpu/start.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/sandbox/cpu/start.c +1 -1
@@ -90,7 +90,7 @@ int sandbox_main_loop_init(void)/* Execute command if required */ if (state->cmd) { -run_command (state->cmd,0 ); +run_command_list (state->cmd,-1 ,0 );os_exit (state->exit_type); }
Signature · 1 line
1.7.7.3
RFC PATCH 1/22 sandbox: Allow -c argument to provide a command list
Dear Simon Glass,
Quoted 5 lines
This allows passing of entire scripts to sandbox with the -c argument, which is useful for testing. Commands can be delimited with a newline or semicolon.
Signed-off-by Simon Glass <[email protected]>
Quoted 9 lines
--- arch/sandbox/cpu/start.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)arch/sandbox/cpu/start.c +0
-0
arch/sandbox/cpu/start.c int sandbox_main_loop_init(void) · line 95
Quoted 7 lines
arch/sandbox/cpu/start.c +1
-1@@ -90,7 +90,7 @@ int sandbox_main_loop_init(void)/* Execute command if required */ if (state->cmd) { -run_command (state->cmd,0 ); +run_command_list (state->cmd,-1 ,0 );os_exit (state->exit_type); }
Best regards,
Marek Vasut
RFC PATCH 2/22 sandbox: Support 'source' command
In reply to Simon GlassEnhance the source command to work with sandbox, by using map_sysmem() to convert a ulong address into a pointer.
--- common/cmd_source.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)
common/cmd_source.c +7 -4
@@ -36,6 +36,7 @@#include <image.h> #include <malloc.h> #include <asm/byteorder.h> +#include <asm/io.h> #if defined(CONFIG_8xx)#include <mpc8xx.h> #endif
@@ -44,9 +45,10 @@ int source (ulong addr, const char *fit_uname) { ulong len; -image_header_t *hdr; +const image_header_t *hdr;ulong *data;int verify; +const void *buf;#if defined(CONFIG_FIT )const void * fit_hdr;int noffset;
@@ -56,9 +58,10 @@ source (ulong addr, const char *fit_uname) verify =getenv_yesno ("verify" ); -switch (genimg_get_format ((void *)addr)) { + buf =map_sysmem (addr,0 ); +switch (genimg_get_format (buf)) {case IMAGE_FORMAT_LEGACY : - hdr = (image_header_t *)addr; + hdr = buf;if (!image_check_magic (hdr)) {puts ("Bad magic number\n" );
@@ -104,7 +107,7 @@ source (ulong addr, const char *fit_uname)return 1 ; } - fit_hdr = (const void *)addr; + fit_hdr = buf;if (!fit_check_format (fit_hdr)) {puts ("Bad FIT image format\n" );return 1 ;
Signature · 1 line
1.7.7.3
RFC PATCH 2/22 sandbox: Support 'source' command
Dear Simon Glass,
Quoted 4 lines
Enhance the source command to work with sandbox, by using
map_sysmem()to convert a ulong address into a pointer.Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
RFC PATCH 3/22 fs: Add support for saving data to filesystems
In reply to Simon GlassAdd a new method for saving that filesystems can implement. This mirrors the existing load method.
--- fs/fs.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 2 + 2 files changed, 76 insertions(+), 0 deletions(-)
fs/fs.c +74 -0
@@ -47,6 +47,12 @@ static inline int fs_read_unsupported(const char *filename, void *buf,return -1 ; } +static inline int fs_write_unsupported (const char *filename,void *buf, +int offset,int len) +{ +return -1 ; +} +static inline void fs_close_unsupported (void ) { }
@@ -57,6 +63,7 @@ struct fstype_info { disk_partition_t *fs_partition);int (*ls)(const char *dirname);int (*read)(const char *filename,void *buf,int offset,int len); +int (*write)(const char *filename,void *buf,int offset,int len);void (*close)(void ); };
@@ -94,6 +101,7 @@ static struct fstype_info fstypes[] = { .close = fs_close_unsupported, .ls = fs_ls_unsupported, .read = fs_read_unsupported, + .write = fs_write_unsupported, }, };
@@ -125,6 +133,7 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) info->close += gd->reloc_off; info->ls += gd->reloc_off; info->read += gd->reloc_off; + info->write += gd->reloc_off; } relocated =1 ; }
@@ -196,6 +205,30 @@ int fs_read(const char *filename, ulong addr, int offset, int len)return ret; } +int fs_write (const char *filename,ulong addr,int offset,int len) +{ +struct fstype_info *info =fs_get_info (fs_type); +void *buf; +int ret; + +/* +* We don't actually know how many bytes are being read, since len==0 +* means read the whole file. +*/ + buf =map_sysmem (addr, len); + ret = info->write (filename, buf, offset, len); +unmap_sysmem (buf); + +/* If we requested a specific number of bytes, check we got it */ +if (ret >=0 && len && ret != len) { +printf ("** Unable to write file %s **\n" , filename); + ret =-1 ; + } +fs_close (); + +return ret; +} +int do_load (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[],int fstype,int cmdline_base) {
@@ -277,3 +310,44 @@ int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],return 0 ; } + +int do_save (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[], +int fstype,int cmdline_base) +{ +unsigned long addr; +const char *filename; +unsigned long bytes; +unsigned long pos; +int len; +unsigned long time; + +if (argc <6 || argc >7 ) +return CMD_RET_USAGE ; + +if (fs_set_blk_dev (argv[1 ], argv[2 ], fstype)) +return 1 ; + + filename = argv[3 ]; + addr =simple_strtoul (argv[4 ],NULL , cmdline_base); + bytes =simple_strtoul (argv[5 ],NULL , cmdline_base); +if (argc >=7 ) + pos =simple_strtoul (argv[6 ],NULL , cmdline_base); +else + pos =0 ; + + time =get_timer (0 ); + len =fs_write (filename, addr, pos, bytes); + time =get_timer (time); +if (len <=0 ) +return 1 ; + +printf ("%d bytes written in %lu ms" , len, time); +if (time >0 ) { +puts (" (" ); +print_size (len / time *1000 ,"/s" ); +puts (")" ); + } +puts ("\n" ); + +return 0 ; +}
include/fs.h +2 -0
@@ -62,5 +62,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype, int cmdline_base);int do_ls (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[],int fstype); +int do_save (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[], +int fstype,int cmdline_base);#endif /* _FS_H */
Signature · 1 line
1.7.7.3
RFC PATCH 3/22 fs: Add support for saving data to filesystems
Dear Simon Glass,
Quoted 4 lines
Add a new method for saving that filesystems can implement. This mirrors the existing load method.
Signed-off-by Simon Glass <[email protected]>
btw what about fat write support, can this map somehow on it?
Best regards,
Marek Vasut
RFC PATCH 3/22 fs: Add support for saving data to filesystems
Hi Marek,
Quoted 10 lines · Marek Vasut
Dear Simon Glass,
Quoted 4 lines
Add a new method for saving that filesystems can implement. This mirrors the existing load method.
Signed-off-by Simon Glass <[email protected]>Reviewed-by Marek Vasut <[email protected]>btw what about fat write support, can this map somehow on it?
Thanks for reviews.
There is also ext4, am hoping that others might help with this?
Regards,
Simon
Quoted 3 lines
Best regards,
Marek Vasut
RFC PATCH 3/22 fs: Add support for saving data to filesystems
Hi,
Quoted 10 lines · Simon Glass
Hi Marek,
Quoted 7 lines · Marek Vasut
Dear Simon Glass,
Quoted 4 lines
Add a new method for saving that filesystems can implement. This mirrors the existing load method.
Signed-off-by Simon Glass <[email protected]>
Quoted 7 lines
Quoted 3 lines
Reviewed-by Marek Vasut <[email protected]>btw what about fat write support, can this map somehow on it?
Thanks for reviews.
There is also ext4, am hoping that others might help with this?
One thing I meant to put in the cover letter was that we might need a generic CONFIG to enable write support. A lot of people don't want it, and perhaps rather than having fat write, ext4 writes, etc. we have a global write support CONFIG.
Quoted 7 lines
Regards,
SimonQuoted 3 lines
Best regards,
Marek Vasut
RFC PATCH 4/22 sandbox: fs: Add support for saving files to host filesystem
In reply to Simon GlassThis allows write of files from the host filesystem in sandbox. There is currently no concept of overwriting the file and removing its existing contents - all writing is done on top of what is there. This means that writing 10 bytes to the start of a 1KB file will only update those 10 bytes, not truncate the file to 10 byte slong.
If the file does not exist it is created.
--- common/cmd_sandbox.c | 18 ++++++++++++++---- fs/fs.c | 1 + fs/sandbox/sandboxfs.c | 33 +++++++++++++++++++++++++++++++++ include/sandboxfs.h | 1 + 4 files changed, 49 insertions(+), 4 deletions(-)
common/cmd_sandbox.c +14 -4
@@ -32,9 +32,16 @@ static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc,return do_ls (cmdtp, flag, argc, argv,FS_TYPE_SANDBOX ); } +static int do_sandbox_save (cmd_tbl_t *cmdtp,int flag,int argc, +char *const argv[]) +{ +return do_save (cmdtp, flag, argc, argv,FS_TYPE_SANDBOX ,16 ); +} +static cmd_tbl_t cmd_sandbox_sub[] = { -U_BOOT_CMD_MKENT (load,3 ,0 , do_sandbox_load,"" ,"" ), +U_BOOT_CMD_MKENT (load,7 ,0 , do_sandbox_load,"" ,"" ),U_BOOT_CMD_MKENT (ls,3 ,0 , do_sandbox_ls,"" ,"" ), +U_BOOT_CMD_MKENT (save,6 ,0 , do_sandbox_save,"" ,"" ), }; static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -56,8 +63,11 @@ static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, }U_BOOT_CMD ( - sb,6 ,1 , do_sandbox, + sb,8 ,1 , do_sandbox,"Miscellaneous sandbox commands" , -"load host <addr> <filename> [<bytes> <offset>] - load a file from host\n" -"sb ls host <filename> - save a file to host" +"load host <dev> <addr> <filename> [<bytes> <offset>] - " +"load a file from host\n" +"sb ls host <filename> - list files on host\n" +"sb save host <dev> <filename> <addr> <bytes> [<offset>] - " +"save a file to host\n" );
fs/fs.c +1 -0
@@ -93,6 +93,7 @@ static struct fstype_info fstypes[] = { .close = sandbox_fs_close, .ls = sandbox_fs_ls, .read = fs_read_sandbox, + .write = fs_write_sandbox, },#endif {
fs/sandbox/sandboxfs.c +33 -0
@@ -48,6 +48,26 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos,return size; } +long sandbox_fs_write_at (const char *filename,unsigned long pos, +void *buffer,unsigned long towrite) +{ +ssize_t size; +int fd, ret; + + fd =os_open (filename,OS_O_RDWR |OS_O_CREAT ); +if (fd <0 ) +return fd; + ret =os_lseek (fd, pos,OS_SEEK_SET ); +if (ret ==-1 ) { +os_close (fd); +return ret; + } + size =os_write (fd, buffer, towrite); +os_close (fd); + +return size; +} +int sandbox_fs_ls (const char *dirname) {struct os_dirent_node *head, *node;
@@ -81,3 +101,16 @@ int fs_read_sandbox(const char *filename, void *buf, int offset, int len)return len_read; } + +int fs_write_sandbox (const char *filename,void *buf,int offset,int len) +{ +int len_written; + + len_written =sandbox_fs_write_at (filename, offset, buf, len); +if (len_written ==-1 ) { +printf ("** Unable to write file %s **\n" , filename); +return -1 ; + } + +return len_written; +}
include/sandboxfs.h +1 -0
@@ -26,5 +26,6 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos,void sandbox_fs_close (void );int sandbox_fs_ls (const char *dirname);int fs_read_sandbox (const char *filename,void *buf,int offset,int len); +int fs_write_sandbox (const char *filename,void *buf,int offset,int len);#endif
Signature · 1 line
1.7.7.3
RFC PATCH 4/22 sandbox: fs: Add support for saving files to host filesystem
Dear Simon Glass,
Quoted 9 lines
This allows write of files from the host filesystem in sandbox. There is currently no concept of overwriting the file and removing its existing contents - all writing is done on top of what is there. This means that writing 10 bytes to the start of a 1KB file will only update those 10 bytes, not truncate the file to 10 byte slong.
If the file does not exist it is created.
Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
RFC PATCH 5/22 image: Split libfdt code into image-fdt.c
In reply to Simon GlassThe image file is still very large, and some of the code is only used when libfdt is in use. Move this code into a new file.
--- common/Makefile | 1 + common/image-fdt.c | 608 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/image.c | 566 ------------------------------------------------ 3 files changed, 609 insertions(+), 566 deletions(-) create mode 100644 common/image-fdt.c
common/Makefile +1 -0
@@ -223,6 +223,7 @@ COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o COBJS-y += console.o COBJS-y += dlmalloc.o COBJS-y += image.o +COBJS-$(CONFIG_OF_LIBFDT) += image-fdt.o COBJS-$(CONFIG_FIT) += image-fit.o COBJS-$(CONFIG_FIT_SIGNATURE) += image-sig.o COBJS-y += memsize.o
common/image-fdt.c new file +608 -0
608 lines not on this page · raw message
common/image.c +0 -566
572 lines not on this page · raw message
Signature · 1 line
1.7.7.3
RFC PATCH 6/22 image: Add device tree setup to image library
In reply to Simon GlassThis seems to be a common function for several architectures, so create a common function rather than duplicating the code in each arch.
Also make an attempt to avoid introducing #ifdefs in the new code, partly by removing useless #ifdefs around function declarations in the image.h header.
--- common/image-fdt.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ common/image.c | 50 +++++++++++++++++++++++++++++++++++++++ include/common.h | 9 +++++++ include/fdt_support.h | 2 - include/image.h | 62 +++++++++++++++++++++++++++++++++++++++++------- include/lmb.h | 2 - 6 files changed, 174 insertions(+), 13 deletions(-)
common/image-fdt.c +62 -0
@@ -606,3 +606,65 @@ error: *of_size =0 ;return 1 ; } + +/* +* Verify the device tree. +* +* This function is called after all device tree fix-ups have been enacted, +* so that the final device tree can be verified. The definition of "verified" +* is up to the specific implementation. However, it generally means that the +* addresses of some of the devices in the device tree are compared with the +* actual addresses at which U-Boot has placed them. +* +* Returns 1 on success, 0 on failure. If 0 is returned, U-boot will halt the +* boot process. +*/ +__weak int ft_verify_fdt (void *fdt) +{ +return 1 ; +} + +__weak int arch_fixup_memory_node (void *blob) +{ +return 0 ; +} + +int image_setup_libfdt (bootm_headers_t *images,void *blob, +int of_size,struct lmb *lmb) +{ +ulong *initrd_start = &images->initrd_start; +ulong *initrd_end = &images->initrd_end; +int ret; + +if (fdt_chosen (blob,1 ) <0 ) { +puts ("ERROR: /chosen node create failed" ); +puts (" - must RESET the board to recover.\n" ); +return -1 ; + } +arch_fixup_memory_node (blob); +if (IMAAGE_OF_BOARD_SETUP ) +ft_board_setup (blob, gd->bd); +fdt_fixup_ethernet (blob); + +/* Delete the old LMB reservation */ +lmb_free (lmb, (phys_addr_t )(u32 )(uintptr_t )blob, + (phys_size_t )fdt_totalsize (blob)); + + ret =fdt_resize (blob); +if (ret <0 ) +return ret; + of_size = ret; + +if (*initrd_start && *initrd_end) { + of_size +=FDT_RAMDISK_OVERHEAD ; +fdt_set_totalsize (blob, of_size); + } +/* Create a new LMB reservation */ +lmb_reserve (lmb, (ulong )blob, of_size); + +fdt_initrd (blob, *initrd_start, *initrd_end,1 ); +if (!ft_verify_fdt (blob)) +return -1 ; + +return 0 ; +}
common/image.c +50 -0
60 lines not on this page · raw message
include/common.h +9 -0
@@ -312,6 +312,15 @@ int mac_read_from_eeprom(void);extern u8 _binary_dt_dtb_start[];/* embedded device tree blob */ int set_cpu_clk_info (void ); +/* arch/$(ARCH)/lib/bootm.c */ +/** +* arch_fixup_memory_node() - Write arch-specific memory information to fdt +* +* @blob FDT blob to write to +* @return 0 if ok, or -ve FDT_ERR_... on failure +*/ +int arch_fixup_memory_node (void *blob); +/* common/flash.c */ void flash_perror (int );
include/fdt_support.h +0 -2
@@ -78,11 +78,9 @@ static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {}int fdt_pci_dma_ranges (void *blob,int phb_off,struct pci_controller *hose);#endif -#ifdef CONFIG_OF_BOARD_SETUP void ft_board_setup (void *blob,bd_t *bd);void ft_cpu_setup (void *blob,bd_t *bd);void ft_pci_setup (void *blob,bd_t *bd); -#endif void set_working_fdt_addr (void *addr);int fdt_resize (void *blob);
include/image.h +53 -9
101 lines not on this page · raw message
include/lmb.h +0 -2
@@ -1,7 +1,6 @@#ifndef _LINUX_LMB_H#define _LINUX_LMB_H#ifdef __KERNEL__ -#ifdef CONFIG_LMB #include <asm/types.h> /*
@@ -57,7 +56,6 @@ lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)void board_lmb_reserve (struct lmb *lmb);void arch_lmb_reserve (struct lmb *lmb); -#endif /* CONFIG_LMB */ #endif /* __KERNEL__ */ #endif /* _LINUX_LMB_H */
Signature · 1 line
1.7.7.3
RFC PATCH 7/22 arm: Refactor bootm to reduce #ifdefs
In reply to Simon GlassWith fewer #ifdefs the code is more readable and more of the code is compiled for all boards. Add defines in the header file to control what features are enabled, and then use if() instead of #ifdef.
--- arch/arm/include/asm/bootm.h | 54 +++++++++++++++++++++++- arch/arm/include/asm/u-boot-arm.h | 2 - arch/arm/lib/bootm.c | 83 ++++++++---------------------------- 3 files changed, 71 insertions(+), 68 deletions(-)
arch/arm/include/asm/bootm.h +52 -2
@@ -1,4 +1,7 @@ -/* Copyright (C) 2011 +/* +* Copyright (c) 2013, Google Inc. +* +* Copyright (C) 2011 * Corscience GmbH & Co. KG - Simon Schwarz <[email protected]> * * This program is free software; you can redistribute it and/or modify
@@ -19,8 +22,55 @@#ifndef ARM_BOOTM_H #define ARM_BOOTM_H -#ifdef CONFIG_USB_DEVICE extern void udc_disconnect (void ); + +#if defined(CONFIG_SETUP_MEMORY_TAGS ) || \ + defined(CONFIG_CMDLINE_TAG ) || \ + defined(CONFIG_INITRD_TAG ) || \ + defined(CONFIG_SERIAL_TAG ) || \ + defined(CONFIG_REVISION_TAG ) +# define BOOTM_ENABLE_TAGS 1 +#else +# define BOOTM_ENABLE_TAGS 0 +#endif + +#ifdef CONFIG_SETUP_MEMORY_TAGS +# define BOOTM_ENABLE_MEMORY_TAGS 1 +#else +# define BOOTM_ENABLE_MEMORY_TAGS 0 +#endif + +#ifdef CONFIG_CMDLINE_TAG +#define BOOTM_ENABLE_CMDLINE_TAG 1 +#else +#define BOOTM_ENABLE_CMDLINE_TAG 0 +#endif + +#ifdef CONFIG_INITRD_TAG +#define BOOTM_ENABLE_INITRD_TAG 1 +#else +#define BOOTM_ENABLE_INITRD_TAG 0 +#endif + +#ifdef CONFIG_SERIAL_TAG +#define BOOTM_ENABLE_SERIAL_TAG 1 +void get_board_serial (struct tag_serialnr *serialnr); +#else +#define BOOTM_ENABLE_SERIAL_TAG 0 +static inline void get_board_serial (struct tag_serialnr *serialnr) +{ +} +#endif + +#ifdef CONFIG_REVISION_TAG +#define BOOTM_ENABLE_REVISION_TAG 1 +u32 get_board_rev (void ); +#else +#define BOOTM_ENABLE_REVISION_TAG 0 +static inline u32 get_board_rev (void ) +{ +return 0 ; +}#endif #endif
arch/arm/include/asm/u-boot-arm.h +0 -2
@@ -58,8 +58,6 @@ int arch_early_init_r(void);int board_init (void );int dram_init (void );void dram_init_banksize (void ); -void setup_serial_tag (struct tag **params); -void setup_revision_tag (struct tag **params);/* cpu/.../interrupt.c */ int arch_interrupt_init (void );
arch/arm/lib/bootm.c +19 -64
177 lines not on this page · raw message
Signature · 1 line
1.7.7.3
RFC PATCH 7/22 arm: Refactor bootm to reduce #ifdefs
Dear Simon Glass,
Quoted 5 lines
With fewer #ifdefs the code is more readable and more of the code is compiled for all boards. Add defines in the header file to control what features are enabled, and then use
if()instead of #ifdef.Signed-off-by Simon Glass <[email protected]>
Did you try building it with ELDK 4.2 and check if there's no size growth?
Best regards,
Marek Vasut
RFC PATCH 7/22 arm: Refactor bootm to reduce #ifdefs
Hi Marek,
Quoted 9 lines · Marek Vasut
Dear Simon Glass,
Quoted 5 lines
With fewer #ifdefs the code is more readable and more of the code is compiled for all boards. Add defines in the header file to control what features are enabled, and then use
if()instead of #ifdef.Signed-off-by Simon Glass <[email protected]>Did you try building it with ELDK 4.2 and check if there's no size growth?
buildman says:
08: arm: Refactor bootm to reduce #ifdefs
arm: (285 boards) spl/u-boot-spl:text -0.0 text -7.9 bss +1.0
so no size growth there with 4.4.1 (the numbers are changes in bytes for that section averaged over all boards).
The code is basically equivalent, just using a compile-time check instead.
gcc version 4.4.1 (Sourcery G++ Lite 2010q1-202)
Quoted 3 lines
Best regards,
Marek Vasut
Regards,
Simon
RFC PATCH 8/22 arm: Use image_setup_linux() instead of local code
In reply to Simon GlassUse the common FDT setup function that is now available in image. Move the FDT-specific code to a new bootm-fdt.c and remove unused headers from bootm.c.
--- arch/arm/lib/Makefile | 1 + arch/arm/lib/bootm-fdt.c | 52 ++++++++++++++++++++++++++++++++++++++ arch/arm/lib/bootm.c | 62 +--------------------------------------------- 3 files changed, 54 insertions(+), 61 deletions(-) create mode 100644 arch/arm/lib/bootm-fdt.c
arch/arm/lib/Makefile +1 -0
@@ -39,6 +39,7 @@ GLCOBJS += div0.o ifndef CONFIG_SPL_BUILD COBJS-y += board.o COBJS-y += bootm.o +COBJS-$(CONFIG_OF_LIBFDT) += bootm-fdt.o COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o COBJS-y += interrupts.o COBJS-y += reset.o
arch/arm/lib/bootm-fdt.c new file +52 -0
52 lines not on this page · raw message
arch/arm/lib/bootm.c +1 -61
91 lines not on this page · raw message
Signature · 1 line
1.7.7.3
RFC PATCH 8/22 arm: Use image_setup_linux() instead of local code
Dear Simon Glass,
Quoted 5 lines
Use the common FDT setup function that is now available in image. Move the FDT-specific code to a new
bootm-fdt.cand remove unused headers frombootm.c.Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
RFC PATCH 9/22 powerpc: Use image_setup_linux() instead of local code
In reply to Simon GlassRather than having similar code in powerpc, use image_setup_linux() which should be common across all architectures that use the FDT.
--- arch/powerpc/lib/bootm.c | 84 +--------------------------------------------- 1 files changed, 1 insertions(+), 83 deletions(-)
arch/powerpc/lib/bootm.c +1 -83
@@ -222,101 +222,19 @@ static int boot_bd_t_linux(bootm_headers_t *images)return ret; } -/* -* Verify the device tree. -* -* This function is called after all device tree fix-ups have been enacted, -* so that the final device tree can be verified. The definition of "verified" -* is up to the specific implementation. However, it generally means that the -* addresses of some of the devices in the device tree are compared with the -* actual addresses at which U-Boot has placed them. -* -* Returns 1 on success, 0 on failure. If 0 is returned, U-boot will halt the -* boot process. -*/ -static int __ft_verify_fdt (void *fdt) -{ -return 1 ; -} -__attribute__((weak,alias ("__ft_verify_fdt" )))int ft_verify_fdt (void *fdt); -static int boot_body_linux (bootm_headers_t *images) { -ulong rd_len; -struct lmb *lmb = &images->lmb; -ulong *initrd_start = &images->initrd_start; -ulong *initrd_end = &images->initrd_end; -#if defined(CONFIG_OF_LIBFDT ) -ulong of_size = images->ft_len; -char **of_flat_tree = &images->ft_addr; -#endif -int ret; -#if defined(CONFIG_OF_LIBFDT ) -boot_fdt_add_mem_rsv_regions (lmb, *of_flat_tree); -#endif - -/* allocate space and init command line */ - ret =boot_cmdline_linux (images); -if (ret) -return ret; -/* allocate space for kernel copy of board info */ ret =boot_bd_t_linux (images);if (ret)return ret; - rd_len = images->rd_end - images->rd_start; - ret =boot_ramdisk_high (lmb, images->rd_start, rd_len, initrd_start, initrd_end); -if (ret) -return ret; - -#if defined(CONFIG_OF_LIBFDT ) - ret =boot_relocate_fdt (lmb, of_flat_tree, &of_size); + ret =image_setup_linux (images);if (ret)return ret; -/* -* Add the chosen node if it doesn't exist, add the env and bd_t -* if the user wants it (the logic is in the subroutines). -*/ -if (of_size) { -if (fdt_chosen (*of_flat_tree,1 ) <0 ) { -puts ("ERROR: " ); -puts ("/chosen node create failed" ); -puts (" - must RESET the board to recover.\n" ); -return -1 ; - } -#ifdef CONFIG_OF_BOARD_SETUP -/* Call the board-specific fixup routine */ -ft_board_setup (*of_flat_tree, gd->bd); -#endif - -/* Delete the old LMB reservation */ -lmb_free (lmb, (phys_addr_t)(u32)*of_flat_tree, - (phys_size_t )fdt_totalsize (*of_flat_tree)); - - ret =fdt_resize (*of_flat_tree); -if (ret <0 ) -return ret; - of_size = ret; - -if (*initrd_start && *initrd_end) { - of_size +=FDT_RAMDISK_OVERHEAD ; -fdt_set_totalsize (*of_flat_tree, of_size); - } -/* Create a new LMB reservation */ -lmb_reserve (lmb, (ulong)*of_flat_tree, of_size); - -/* fixup the initrd now that we know where it should be */ -if (*initrd_start && *initrd_end) -fdt_initrd (*of_flat_tree, *initrd_start, *initrd_end,1 ); - -if (!ft_verify_fdt (*of_flat_tree)) -return -1 ; - } -#endif /* CONFIG_OF_LIBFDT */ return 0 ; }
Signature · 1 line
1.7.7.3
RFC PATCH 9/22 powerpc: Use image_setup_linux() instead of local code
Dear Simon Glass,
Quoted 4 lines
Rather than having similar code in powerpc, use
image_setup_linux()which should be common across all architectures that use the FDT.Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
RFC PATCH 10/22 m68k: Use image_setup_linux() instead of local code
In reply to Simon GlassRather than having similar code in m68k, use image_setup_linux() which should be common across all architectures that use the FDT.
--- arch/m68k/lib/bootm.c | 15 +++------------ 1 files changed, 3 insertions(+), 12 deletions(-)
arch/m68k/lib/bootm.c +3 -12
@@ -78,13 +78,6 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *imaif ((flag !=0 ) && (flag !=BOOTM_STATE_OS_GO ))return 1 ; -/* allocate space and init command line */ - ret =boot_get_cmdline (lmb, &cmd_start, &cmd_end); -if (ret) { -puts ("ERROR with allocation of cmdline\n" ); - goto error; - } -/* allocate space for kernel copy of board info */ ret =boot_get_kbd (lmb, &kbd);if (ret) {
@@ -93,14 +86,12 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima }set_clocks_in_mhz (kbd); - kernel = (void (*)(bd_t *,ulong ,ulong ,ulong ,ulong ))images->ep; - - rd_len = images->rd_end - images->rd_start; - ret =boot_ramdisk_high (lmb, images->rd_start, rd_len, - &initrd_start, &initrd_end); + ret =image_setup_linux (images);if (ret) goto error; + kernel = (void (*)(bd_t *,ulong ,ulong ,ulong ,ulong ))images->ep; +debug ("## Transferring control to Linux (at address %08lx) ...\n" , (ulong ) kernel);
Signature · 1 line
1.7.7.3
RFC PATCH 10/22 m68k: Use image_setup_linux() instead of local code
Dear Simon Glass,
Quoted 4 lines
Rather than having similar code in m68k, use
image_setup_linux()which should be common across all architectures that use the FDT.Signed-off-by Simon Glass <[email protected]>
Best regards,
Marek Vasut
RFC PATCH 11/22 sparc: Use image_setup_linux() instead of local code
In reply to Simon GlassSparc only really sets up the ramdisk, but we should still use image_setup_linux() so that setup is common across all architectures that use the FDT.
--- arch/sparc/lib/bootm.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-)
arch/sparc/lib/bootm.c +6 -7
@@ -131,17 +131,16 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t * im* extracted and is writeable. */ + ret =image_setup_boot (images); +if (ret) { +puts ("### Failed to relocate RAM disk\n" ); + goto error; + } +/* Calc length of RAM disk, if zero no ramdisk available */ rd_len = images->rd_end - images->rd_start;if (rd_len) { - ret =boot_ramdisk_high (lmb, images->rd_start, rd_len, - &initrd_start, &initrd_end); -if (ret) { -puts ("### Failed to relocate RAM disk\n" ); - goto error; - } -/* Update SPARC kernel header so that Linux knows * what is going on and where to find RAM disk. *
Signature · 1 line
1.7.7.3
RFC PATCH 12/22 bootstage: Introduce sub-IDs for use with image loading
In reply to Simon GlassLoading a ramdisk, kernel or FDT goes through similar stages. Create a block of IDs for each task, and define a consistent numbering within the block. This will allow use of common code for image loading.
--- include/bootstage.h | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-)
include/bootstage.h +22 -0
@@ -37,6 +37,24 @@ enum bootstage_flags { BOOTSTAGEF_ALLOC = 1 << 1, /* Allocate an id */ }; +/* bootstate sub-IDs used for kernel and ramdisk ranges */ +enum { +BOOTSTAGE_SUB_FORMAT , +BOOTSTAGE_SUB_FORMAT_OK , +BOOTSTAGE_SUB_NO_UNIT_NAME , +BOOTSTAGE_SUB_UNIT_NAME , +BOOTSTAGE_SUB_SUBNODE , + +BOOTSTAGE_SUB_CHECK , +BOOTSTAGE_SUB_HASH =5 , +BOOTSTAGE_SUB_CHECK_ARCH =5 , +BOOTSTAGE_SUB_CHECK_ALL , +BOOTSTAGE_SUB_GET_DATA , +BOOTSTAGE_SUB_CHECK_ALL_OK =7 , +BOOTSTAGE_SUB_GET_DATA_OK , +BOOTSTAGE_SUB_LOAD , +}; +/* * A list of boot stages that we know about. Each of these indicates the * state that we are at, and the action that we are about to perform. For
@@ -137,10 +155,12 @@ enum bootstage_id {BOOTSTAGE_ID_NET_DONE_ERR ,BOOTSTAGE_ID_NET_DONE , +BOOTSTAGE_ID_FIT_FDT_START =90 ,/* * Boot stages related to loading a FIT image. Some of these are a * bit wonky. */ +BOOTSTAGE_ID_FIT_KERNEL_START =100 ,BOOTSTAGE_ID_FIT_FORMAT =100 ,BOOTSTAGE_ID_FIT_NO_UNIT_NAME , BOOTSTAGE_ID_FIT_UNIT_NAME,
@@ -161,6 +181,8 @@ enum bootstage_id {BOOTSTAGE_ID_FIT_LOADADDR ,BOOTSTAGE_ID_OVERWRITTEN , +/* Next 10 IDs used by BOOTSTAGE_SUB_... */ +BOOTSTAGE_ID_FIT_RD_START =120 ,/* Ramdisk stages */ BOOTSTAGE_ID_FIT_RD_FORMAT =120 ,BOOTSTAGE_ID_FIT_RD_FORMAT_OK , BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME,
Signature · 1 line
1.7.7.3
RFC PATCH 13/22 mkimage: Add map_sysmem() and IH_ARCH_DEFAULT to simplfy building
In reply to Simon GlassThese are not actually used in mkimage itself, but the image code (which is common with mkimage) does use them. To avoid #ifdefs in the image code just for mkimage, define dummy version of these here. The compiler will eliminate the dead code anyway.
A better way to handle this might be to split out more things from common.h so that mkimage can include them. At present any file that mkimage uses has to be very careful what headers it includes.
--- tools/mkimage.h | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
tools/mkimage.h +12 -0
@@ -44,12 +44,24 @@#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0])) +static inline void *map_sysmem (ulong paddr,unsigned long len) +{ +return (void *)(uintptr_t )paddr; +} + +static inline ulong map_to_sysmem (void *ptr) +{ +return (ulong )(uintptr_t )ptr; +} +#define MKIMAGE_TMPFILE_SUFFIX ".tmp"#define MKIMAGE_MAX_TMPFILE_LEN 256#define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500"#define MKIMAGE_MAX_DTC_CMDLINE_LEN 512#define MKIMAGE_DTC "dtc"/* assume dtc is in $PATH */ +#define IH_ARCH_DEFAULT IH_ARCH_INVALID +/* * This structure defines all such variables those are initialized by * mkimage main core and need to be referred by image type specific
Signature · 1 line
1.7.7.3
RFC PATCH 14/22 image: Introduce fit_image_load() to load images from FITs
In reply to Simon GlassAt present code to load an image from a FIT is duplicated in the three places where it is needed (kernel, fdt, ramdisk).
The differences between these different code copies is fairly minor. Create a new function in the fit code which can handle any of the requirements of those cases.
--- common/image-fit.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/image.h | 77 ++++++++++++++++++- 2 files changed, 296 insertions(+), 2 deletions(-)
common/image-fit.c +221 -0
@@ -32,6 +32,7 @@#else #include <common.h> #include <errno.h> +#include <asm/io.h> DECLARE_GLOBAL_DATA_PTR ;#endif /* !USE_HOSTCC*/
@@ -1491,6 +1492,22 @@ void fit_conf_print(const void *fit, int noffset, const char *p)printf ("%s FDT: %s\n" , p, uname); } +int fit_image_select (const void *fit,int rd_noffset,int verify) +{ +fit_image_print (fit, rd_noffset," " ); + +if (verify) { +puts (" Verifying Hash Integrity ... " ); +if (!fit_image_verify (fit, rd_noffset)) { +puts ("Bad Data Hash\n" ); +return -EACCES ; + } +puts ("OK\n" ); + } + +return 0 ; +} +/** * fit_check_ramdisk - verify FIT format ramdisk subimage * @fit_hdr: pointer to the FIT ramdisk header
@@ -1533,3 +1550,207 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,bootstage_mark (BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK );return 1 ; } + +int fit_get_node_from_config (bootm_headers_t *images,const char *prop_name, +ulong addr) +{ +int cfg_noffset; +void *fit_hdr; +int noffset; + +debug ("* %s: using config '%s' from image at 0x%08lx\n" , + prop_name, images->fit_uname_cfg, addr); + +/* Check whether configuration has this property defined */ + fit_hdr =map_sysmem (addr,0 ); + cfg_noffset =fit_conf_get_node (fit_hdr, images->fit_uname_cfg); +if (cfg_noffset <0 ) { +debug ("* %s: no such config\n" , prop_name); +return -ENOENT ; + } + + noffset =fit_conf_get_prop_node (fit_hdr, cfg_noffset, prop_name); +if (noffset <0 ) { +debug ("* %s: no %s in config\n" , prop_name, prop_name); +return -ENOLINK ; + } + +return noffset; +} + +int fit_image_load (bootm_headers_t *images,const char *prop_name,ulong addr, +const char **fit_unamep,const char *fit_uname_config, +int arch,int image_type,int bootstage_id, +enum fit_load_op load_op,ulong *datap,ulong *lenp) +{ +int cfg_noffset, noffset; +const char *fit_uname; +const void *fit; +const void *buf; +size_t size; +int type_ok, os_ok; +ulong load, data, len; +int ret; + + fit =map_sysmem (addr,0 ); + fit_uname = fit_unamep ? *fit_unamep :NULL ; +printf ("## Loading %s from FIT Image@%08lx ...\n" , prop_name, addr); + +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_FORMAT ); +if (!fit_check_format (fit)) { +printf ("Bad FIT %s image format!\n" , prop_name); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_FORMAT ); +return -ENOEXEC ; + } +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_FORMAT_OK ); +if (fit_uname) { +/* get ramdisk component image node offset */ +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_UNIT_NAME ); + noffset =fit_image_get_node (fit, fit_uname); + }else { +/* +* no image node unit name, try to get config +* node first. If config unit node name is NULL +* fit_conf_get_node() will try to find default config node +*/ +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_NO_UNIT_NAME ); +if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { + cfg_noffset =fit_conf_find_compat (fit,gd_fdt_blob ()); + }else { + cfg_noffset =fit_conf_get_node (fit, + fit_uname_config); + } +if (cfg_noffset <0 ) { +puts ("Could not find configuration node\n" ); +bootstage_error (bootstage_id + +BOOTSTAGE_SUB_NO_UNIT_NAME ); +return -ENOENT ; + } + fit_uname_config =fdt_get_name (fit, cfg_noffset,NULL ); +printf (" Using '%s' configuration\n" , fit_uname_config); +if (image_type ==IH_TYPE_KERNEL ) { +/* Remember (and possibly verify) this config */ + images->fit_uname_cfg = fit_uname_config; +if (IMAGE_ENABLE_VERIFY && images->verify) { +puts (" Verifying Hash Integrity ... " ); +if (!fit_config_verify (fit, cfg_noffset)) { +puts ("Bad Data Hash\n" ); +bootstage_error (bootstage_id + +BOOTSTAGE_SUB_HASH ); +return -EACCES ; + } +puts ("OK\n" ); + } +bootstage_mark (BOOTSTAGE_ID_FIT_CONFIG ); + } + + noffset =fit_conf_get_prop_node (fit, cfg_noffset, + prop_name); + fit_uname =fit_get_name (fit, noffset,NULL ); + } +if (noffset <0 ) { +puts ("Could not find subimage node\n" ); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_SUBNODE ); +return -ENOENT ; + } + +printf (" Trying '%s' %s subimage\n" , fit_uname, prop_name); + + ret =fit_image_select (fit, noffset, images->verify); +if (ret) { +bootstage_error (bootstage_id +BOOTSTAGE_SUB_HASH ); +return ret; + } + +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_CHECK_ARCH ); +if (!fit_image_check_target_arch (fit, noffset)) { +puts ("Unsupported Architecture\n" ); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_CHECK_ARCH ); +return -ENOEXEC ; + } + +if (image_type ==IH_TYPE_FLATDT && + !fit_image_check_comp (fit, noffset,IH_COMP_NONE )) { +puts ("FDT image is compressed" ); +return -EPROTONOSUPPORT ; + } + +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_CHECK_ALL ); + type_ok =fit_image_check_type (fit, noffset, image_type) || + (image_type ==IH_TYPE_KERNEL && +fit_image_check_type (fit, noffset, +IH_TYPE_KERNEL_NOLOAD )); + os_ok = image_type ==IH_TYPE_FLATDT || +fit_image_check_os (fit, noffset,IH_OS_LINUX ); +if (!type_ok || !os_ok) { +printf ("No Linux %s %s Image\n" ,genimg_get_arch_name (arch), +genimg_get_type_name (image_type)); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_CHECK_ALL ); +return -EIO ; + } + +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_CHECK_ALL_OK ); + +/* get image data address and length */ +if (fit_image_get_data (fit, noffset, &buf, &size)) { +printf ("Could not find %s subimage data!\n" , prop_name); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_GET_DATA ); +return -ENOMEDIUM ; + } + len = (ulong )size; + +/* verify that image data is a proper FDT blob */ +if (image_type ==IH_TYPE_FLATDT && +fdt_check_header ((char *)buf)) { +puts ("Subimage data is not a FDT" ); +return -ENOEXEC ; + } + +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_GET_DATA_OK ); + + data =map_to_sysmem ((char *)buf); + +if (load_op ==FIT_LOAD_IGNORED ) { +/* Don't load */ + }else if (fit_image_get_load (fit, noffset, &load)) { +if (load_op ==FIT_LOAD_REQUIRED ) { +printf ("Can't get %s subimage load address!\n" , + prop_name); +bootstage_error (bootstage_id +BOOTSTAGE_SUB_LOAD ); +return -EBADF ; + } + }else { +ulong image_start, image_end; +ulong load_end; +void *dst; + +/* +* move image data to the load address, +* make sure we don't overwrite initial image +*/ + image_start = addr; + image_end = addr +fit_get_size (fit); + + load_end = load + len; +if (image_type !=IH_TYPE_KERNEL && + load < image_end && load_end > image_start) { +printf ("Error: %s overwritten\n" , prop_name); +return -EXDEV ; + } + +printf (" Loading %s from 0x%08lx to 0x%08lx\n" , + prop_name, data, load); + + dst =map_sysmem (load, len); +memmove (dst, buf, len); + data = load; + } +bootstage_mark (bootstage_id +BOOTSTAGE_SUB_LOAD ); + + *datap = data; + *lenp = len; +if (fit_unamep) + *fit_unamep = (char *)fit_uname; + +return noffset; +}
include/image.h +75 -2
105 lines not on this page · raw message
Signature · 1 line
1.7.7.3
RFC PATCH 15/22 image: Use fit_image_load() to load ramdisk
In reply to Simon GlassUse the new common code to load a ramdisk. The functionality should not change.
--- common/image-fit.c | 62 -------------------------- common/image.c | 122 +++++++--------------------------------------------- include/image.h | 1 - 3 files changed, 16 insertions(+), 169 deletions(-)
common/image-fit.c +0 -62
@@ -1412,25 +1412,6 @@ int fit_conf_get_kernel_node(const void *fit, int noffset) }/** -* fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to -* a given configuration -* @fit: pointer to the FIT format image header -* @noffset: configuration node offset -* -* fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from -* configuration FIT_KERNEL_PROP property and translates it to the node -* offset. -* -* returns: -* image node offset when found (>=0) -* negative number on failure (FDT_ERR_* code) -*/ -int fit_conf_get_ramdisk_node (const void *fit,int noffset) -{ -return fit_conf_get_prop_node (fit, noffset,FIT_RAMDISK_PROP ); -} - -/** * fit_conf_get_fdt_node - get fdt image node offset that corresponds to * a given configuration * @fit: pointer to the FIT format image header
@@ -1508,49 +1489,6 @@ int fit_image_select(const void *fit, int rd_noffset, int verify)return 0 ; } -/** -* fit_check_ramdisk - verify FIT format ramdisk subimage -* @fit_hdr: pointer to the FIT ramdisk header -* @rd_noffset: ramdisk subimage node offset within FIT image -* @arch: requested ramdisk image architecture type -* @verify: data CRC verification flag -* -* fit_check_ramdisk() verifies integrity of the ramdisk subimage and from -* specified FIT image. -* -* returns: -* 1, on success -* 0, on failure -*/ -int fit_check_ramdisk (const void *fit,int rd_noffset,uint8_t arch, -int verify) -{ -fit_image_print (fit, rd_noffset," " ); - -if (verify) { -puts (" Verifying Hash Integrity ... " ); -if (!fit_image_verify (fit, rd_noffset)) { -puts ("Bad Data Hash\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_RD_HASH ); -return 0 ; - } -puts ("OK\n" ); - } - -bootstage_mark (BOOTSTAGE_ID_FIT_RD_CHECK_ALL ); -if (!fit_image_check_os (fit, rd_noffset,IH_OS_LINUX ) || - !fit_image_check_arch (fit, rd_noffset, arch) || - !fit_image_check_type (fit, rd_noffset,IH_TYPE_RAMDISK )) { -printf ("No Linux %s Ramdisk Image\n" , -genimg_get_arch_name (arch)); -bootstage_error (BOOTSTAGE_ID_FIT_RD_CHECK_ALL ); -return 0 ; - } - -bootstage_mark (BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK ); -return 1 ; -} -int fit_get_node_from_config (bootm_headers_t *images,const char *prop_name,ulong addr) {
common/image.c +16 -106
155 lines not on this page · raw message
include/image.h +0 -1
@@ -761,7 +761,6 @@ int fit_check_format(const void *fit);int fit_conf_find_compat (const void *fit,const void *fdt);int fit_conf_get_node (const void *fit,const char *conf_uname);int fit_conf_get_kernel_node (const void *fit,int noffset); -int fit_conf_get_ramdisk_node (const void *fit,int noffset);int fit_conf_get_fdt_node (const void *fit,int noffset);/**
Signature · 1 line
1.7.7.3
RFC PATCH 16/22 image: Use fit_image_load() to load FDT
In reply to Simon GlassUse the new common code to load a flat device tree. Also fix up a few casts so that this code works with sandbox. Other than that the functionality should not change.
--- common/cmd_bootm.c | 4 +- common/image-fdt.c | 214 +++++++--------------------------------------------- common/image-fit.c | 19 ----- include/image.h | 6 +- 4 files changed, 33 insertions(+), 210 deletions(-)
common/cmd_bootm.c +2 -2
@@ -295,7 +295,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]#if defined(CONFIG_OF_LIBFDT )/* find flattened device tree */ - ret =boot_get_fdt (flag, argc, argv, &images, + ret =boot_get_fdt (flag, argc, argv,IH_ARCH_DEFAULT , &images, &images.ft_addr, &images.ft_len);if (ret) {puts ("Could not find a valid device tree\n" );
@@ -1609,7 +1609,7 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,#if defined(CONFIG_OF_LIBFDT )/* find flattened device tree */ - ret =boot_get_fdt (flag, argc, argv, images, + ret =boot_get_fdt (flag, argc, argv,IH_ARCH_DEFAULT , images, &images->ft_addr, &images->ft_len);if (ret) {puts ("Could not find a valid device tree\n" );
common/image-fdt.c +28 -186
293 lines not on this page · raw message
common/image-fit.c +0 -19
@@ -1412,25 +1412,6 @@ int fit_conf_get_kernel_node(const void *fit, int noffset) }/** -* fit_conf_get_fdt_node - get fdt image node offset that corresponds to -* a given configuration -* @fit: pointer to the FIT format image header -* @noffset: configuration node offset -* -* fit_conf_get_fdt_node() retrives fdt image node unit name from -* configuration FIT_KERNEL_PROP property and translates it to the node -* offset. -* -* returns: -* image node offset when found (>=0) -* negative number on failure (FDT_ERR_* code) -*/ -int fit_conf_get_fdt_node (const void *fit,int noffset) -{ -return fit_conf_get_prop_node (fit, noffset,FIT_FDT_PROP ); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node
include/image.h +3 -3
@@ -453,8 +453,9 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,int fit_get_node_from_config (bootm_headers_t *images,const char *prop_name,ulong addr); -int boot_get_fdt (int flag,int argc,char *const argv[], -bootm_headers_t *images,char **of_flat_tree,ulong *of_size); +int boot_get_fdt (int flag,int argc,char *const argv[],uint8_t arch, +bootm_headers_t *images, +char **of_flat_tree,ulong *of_size);void boot_fdt_add_mem_rsv_regions (struct lmb *lmb,void *fdt_blob);int boot_relocate_fdt (struct lmb *lmb,char **of_flat_tree,ulong *of_size);
@@ -761,7 +762,6 @@ int fit_check_format(const void *fit);int fit_conf_find_compat (const void *fit,const void *fdt);int fit_conf_get_node (const void *fit,const char *conf_uname);int fit_conf_get_kernel_node (const void *fit,int noffset); -int fit_conf_get_fdt_node (const void *fit,int noffset);/** * fit_conf_get_prop_node() - Get node refered to by a configuration
Signature · 1 line
1.7.7.3
RFC PATCH 17/22 sandbox: Adjust bootm command to work with sandbox
In reply to Simon GlassUse map_sysmem() when converting from addresses to pointers, so that bootm can be used with sandbox.
--- common/cmd_bootm.c | 25 ++++++++++++------------- 1 files changed, 12 insertions(+), 13 deletions(-)
common/cmd_bootm.c +12 -13
@@ -325,12 +325,15 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)ulong image_len = os.image_len;__maybe_unused uint unc_len =CONFIG_SYS_BOOTM_LEN ;int no_overlap =0 ; +void *load_buf, *image_buf;#if defined(CONFIG_LZMA ) || defined(CONFIG_LZO )int ret;#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ const char *type_name =genimg_get_type_name (os.type); + load_buf =map_sysmem (load, image_len); + image_buf =map_sysmem (image_start, image_len);switch (comp) {case IH_COMP_NONE :if (load == blob_start || load == image_start) {
@@ -338,8 +341,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) no_overlap =1 ; }else {printf (" Loading %s ... " , type_name); -memmove_wd ((void *)load, (void *)image_start, - image_len,CHUNKSZ ); +memmove_wd (load_buf, image_buf, image_len,CHUNKSZ ); } *load_end = load + image_len;puts ("OK\n" );
@@ -347,8 +349,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)#ifdef CONFIG_GZIP case IH_COMP_GZIP :printf (" Uncompressing %s ... " , type_name); -if (gunzip ((void *)load, unc_len, - (uchar *)image_start, &image_len) !=0 ) { +if (gunzip (load_buf, unc_len, image_buf, &image_len) !=0 ) {puts ("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n" );if (boot_progress)
@@ -367,9 +368,9 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)* use slower decompression algorithm which requires * at most 2300 KB of memory. */ -int i =BZ2_bzBuffToBuffDecompress ((char *)load, - &unc_len, (char *)image_start, image_len, -CONFIG_SYS_MALLOC_LEN < (4096 *1024 ),0 ); +int i =BZ2_bzBuffToBuffDecompress (load_buf, &unc_len, + image_buf, image_len, +CONFIG_SYS_MALLOC_LEN < (4096 *1024 ),0 );if (i !=BZ_OK ) {printf ("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n" , i);
@@ -386,9 +387,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)SizeT lzma_len = unc_len;printf (" Uncompressing %s ... " , type_name); - ret =lzmaBuffToBuffDecompress ( - (unsigned char *)load, &lzma_len, - (unsigned char *)image_start, image_len); + ret =lzmaBuffToBuffDecompress (load_buf, &lzma_len, + image_buf, image_len); unc_len = lzma_len;if (ret !=SZ_OK ) { printf("LZMA: uncompress or overwrite error %d "
@@ -404,9 +404,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)case IH_COMP_LZO :printf (" Uncompressing %s ... " , type_name); - ret =lzop_decompress ((const unsigned char *)image_start, - image_len, (unsigned char *)load, - &unc_len); + ret =lzop_decompress (image_buf, image_len, load_buf, + &unc_len);if (ret !=LZO_E_OK ) {printf ("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n" , ret);
Signature · 1 line
1.7.7.3
RFC PATCH 18/22 image: Use fit_image_load() to load kernel
In reply to Simon GlassUse the new common code to load a kernel. The functionality should not change.
--- common/cmd_bootm.c | 153 +++------------------------------------------------- common/image-fit.c | 19 ------- include/image.h | 1 - 3 files changed, 8 insertions(+), 165 deletions(-)
common/cmd_bootm.c +8 -145
@@ -88,11 +88,6 @@ static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);static void fixup_silent_linux (void );#endif -static image_header_t *image_get_kernel (ulong img_addr,int verify); -#if defined(CONFIG_FIT ) -static int fit_check_kernel (const void *fit,int os_noffset,int verify); -#endif -static const void *boot_get_kernel (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[],bootm_headers_t *images,ulong *os_data,ulong *os_len);
@@ -778,54 +773,6 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) }/** -* fit_check_kernel - verify FIT format kernel subimage -* @fit_hdr: pointer to the FIT image header -* os_noffset: kernel subimage node offset within FIT image -* @verify: data CRC verification flag -* -* fit_check_kernel() verifies integrity of the kernel subimage and from -* specified FIT image. -* -* returns: -* 1, on success -* 0, on failure -*/ -#if defined(CONFIG_FIT ) -static int fit_check_kernel (const void *fit,int os_noffset,int verify) -{ -fit_image_print (fit, os_noffset," " ); - -if (verify) { -puts (" Verifying Hash Integrity ... " ); -if (!fit_image_verify (fit, os_noffset)) { -puts ("Bad Data Hash\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_CHECK_HASH ); -return 0 ; - } -puts ("OK\n" ); - } -bootstage_mark (BOOTSTAGE_ID_FIT_CHECK_ARCH ); - -if (!fit_image_check_target_arch (fit, os_noffset)) { -puts ("Unsupported Architecture\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_CHECK_ARCH ); -return 0 ; - } - -bootstage_mark (BOOTSTAGE_ID_FIT_CHECK_KERNEL ); -if (!fit_image_check_type (fit, os_noffset,IH_TYPE_KERNEL ) && - !fit_image_check_type (fit, os_noffset,IH_TYPE_KERNEL_NOLOAD )) { -puts ("Not a kernel image\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_CHECK_KERNEL ); -return 0 ; - } - -bootstage_mark (BOOTSTAGE_ID_FIT_CHECKED ); -return 1 ; -} -#endif /* CONFIG_FIT */ - -/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length
@@ -845,12 +792,8 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,ulong img_addr;const void *buf;#if defined(CONFIG_FIT ) -const void *fit_hdr;const char *fit_uname_config =NULL ;const char *fit_uname_kernel =NULL ; -const void *data; -size_t len; -int cfg_noffset;int os_noffset;#endif
@@ -927,96 +870,16 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,break ;#if defined(CONFIG_FIT )case IMAGE_FORMAT_FIT : - fit_hdr = buf; -printf ("## Booting kernel from FIT Image at %08lx ...\n" , - img_addr); - -if (!fit_check_format (fit_hdr)) { -puts ("Bad FIT kernel image format!\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_FORMAT ); + os_noffset =fit_image_load (images,FIT_KERNEL_PROP , + img_addr, + &fit_uname_kernel, fit_uname_config, +IH_ARCH_DEFAULT ,IH_TYPE_KERNEL , +BOOTSTAGE_ID_FIT_KERNEL_START , +FIT_LOAD_IGNORED , os_data, os_len); +if (os_noffset <0 )return NULL ; - } -bootstage_mark (BOOTSTAGE_ID_FIT_FORMAT ); - -if (!fit_uname_kernel) { -/* -* no kernel image node unit name, try to get config -* node first. If config unit node name is NULL -* fit_conf_get_node() will try to find default config -* node -*/ -bootstage_mark (BOOTSTAGE_ID_FIT_NO_UNIT_NAME ); -#ifdef CONFIG_FIT_BEST_MATCH -if (fit_uname_config) - cfg_noffset = -fit_conf_get_node (fit_hdr, - fit_uname_config); -else - cfg_noffset = -fit_conf_find_compat (fit_hdr, - gd->fdt_blob); -#else - cfg_noffset =fit_conf_get_node (fit_hdr, - fit_uname_config); -#endif -if (cfg_noffset <0 ) { -bootstage_error (BOOTSTAGE_ID_FIT_NO_UNIT_NAME ); -return NULL ; - } -/* save configuration uname provided in the first -* bootm argument -*/ - images->fit_uname_cfg =fdt_get_name (fit_hdr, - cfg_noffset, -NULL ); -printf (" Using '%s' configuration\n" , - images->fit_uname_cfg); -if (IMAGE_ENABLE_VERIFY && images->verify) { -puts (" Verifying Hash Integrity ... " ); -if (!fit_config_verify (fit_hdr, - cfg_noffset)) { -puts ("Bad Data Hash\n" ); -bootstage_error ( -BOOTSTAGE_ID_FIT_CHECK_HASH ); -return NULL ; - } -puts ("OK\n" ); - } - -bootstage_mark (BOOTSTAGE_ID_FIT_CONFIG ); - - os_noffset =fit_conf_get_kernel_node (fit_hdr, - cfg_noffset); - fit_uname_kernel =fit_get_name (fit_hdr, os_noffset, -NULL ); - }else { -/* get kernel component image node offset */ -bootstage_mark (BOOTSTAGE_ID_FIT_UNIT_NAME ); - os_noffset =fit_image_get_node (fit_hdr, - fit_uname_kernel); - } -if (os_noffset <0 ) { -bootstage_error (BOOTSTAGE_ID_FIT_CONFIG ); -return NULL ; - } - -printf (" Trying '%s' kernel subimage\n" , fit_uname_kernel); - -bootstage_mark (BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE ); -if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) -return NULL ; - -/* get kernel image data address and length */ -if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { -puts ("Could not find kernel subimage data!\n" ); -bootstage_error (BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR ); -return NULL ; - } -bootstage_mark (BOOTSTAGE_ID_FIT_KERNEL_INFO ); - *os_len = len; - *os_data = (ulong )data; - images->fit_hdr_os = (void *)fit_hdr; + images->fit_hdr_os =map_sysmem (img_addr,0 ); images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset;break ;
common/image-fit.c +0 -19
@@ -1393,25 +1393,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset, }/** -* fit_conf_get_kernel_node - get kernel image node offset that corresponds to -* a given configuration -* @fit: pointer to the FIT format image header -* @noffset: configuration node offset -* -* fit_conf_get_kernel_node() retrives kernel image node unit name from -* configuration FIT_KERNEL_PROP property and translates it to the node -* offset. -* -* returns: -* image node offset when found (>=0) -* negative number on failure (FDT_ERR_* code) -*/ -int fit_conf_get_kernel_node (const void *fit,int noffset) -{ -return fit_conf_get_prop_node (fit, noffset,FIT_KERNEL_PROP ); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node
include/image.h +0 -1
@@ -761,7 +761,6 @@ int fit_check_format(const void *fit);int fit_conf_find_compat (const void *fit,const void *fdt);int fit_conf_get_node (const void *fit,const char *conf_uname); -int fit_conf_get_kernel_node (const void *fit,int noffset);/** * fit_conf_get_prop_node() - Get node refered to by a configuration
Signature · 1 line
1.7.7.3
RFC PATCH 19/22 sandbox: image: Adjust FIT image printing to work with sandbox
In reply to Simon GlassUse map_sysmem() to convert from address to pointer, so that sandbox can print FIT information without crashing.
--- common/image-fit.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
common/image-fit.c +1 -1
@@ -373,7 +373,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)if (ret)printf ("unavailable\n" );else -printf ("0x%08lx\n" , (ulong )data); +printf ("0x%08lx\n" , (ulong )map_to_sysmem ((char *)data));#endif printf ("%s Data Size: " , p);
Signature · 1 line
1.7.7.3
RFC PATCH 20/22 bootstage: Remove unused entries related to kernel/ramdisk/fdt load
In reply to Simon GlassNow that the code for loading these three images from a FIT is common, we don't need individual boostage IDs for each of them.
Note: there are some minor changes in the bootstage numbering, particuarly for kernel loading. I don't believe this matters.
--- include/bootstage.h | 29 +++-------------------------- 1 files changed, 3 insertions(+), 26 deletions(-)
include/bootstage.h +3 -26
@@ -161,20 +161,10 @@ enum bootstage_id {* bit wonky. */ BOOTSTAGE_ID_FIT_KERNEL_START =100 , -BOOTSTAGE_ID_FIT_FORMAT =100 , -BOOTSTAGE_ID_FIT_NO_UNIT_NAME , -BOOTSTAGE_ID_FIT_UNIT_NAME , -BOOTSTAGE_ID_FIT_CONFIG , -BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE , -BOOTSTAGE_ID_FIT_CHECK_HASH =104 , - -BOOTSTAGE_ID_FIT_CHECK_ARCH , -BOOTSTAGE_ID_FIT_CHECK_KERNEL , -BOOTSTAGE_ID_FIT_CHECKED , - -BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR =107 , -BOOTSTAGE_ID_FIT_KERNEL_INFO , + +BOOTSTAGE_ID_FIT_CONFIG =110 ,BOOTSTAGE_ID_FIT_TYPE , +BOOTSTAGE_ID_FIT_KERNEL_INFO ,BOOTSTAGE_ID_FIT_COMPRESSION , BOOTSTAGE_ID_FIT_OS,
@@ -183,19 +173,6 @@ enum bootstage_id {/* Next 10 IDs used by BOOTSTAGE_SUB_... */ BOOTSTAGE_ID_FIT_RD_START =120 ,/* Ramdisk stages */ -BOOTSTAGE_ID_FIT_RD_FORMAT =120 , -BOOTSTAGE_ID_FIT_RD_FORMAT_OK , -BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME , -BOOTSTAGE_ID_FIT_RD_UNIT_NAME , -BOOTSTAGE_ID_FIT_RD_SUBNODE , - -BOOTSTAGE_ID_FIT_RD_CHECK , -BOOTSTAGE_ID_FIT_RD_HASH =125 , -BOOTSTAGE_ID_FIT_RD_CHECK_ALL , -BOOTSTAGE_ID_FIT_RD_GET_DATA , -BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK =127 , -BOOTSTAGE_ID_FIT_RD_GET_DATA_OK , -BOOTSTAGE_ID_FIT_RD_LOAD ,BOOTSTAGE_ID_IDE_FIT_READ =140 , BOOTSTAGE_ID_IDE_FIT_READ_OK,
Signature · 1 line
1.7.7.3
RFC PATCH 21/22 sandbox: image: Create a test for loading FIT images
In reply to Simon GlassThe image code is fairly complex with various different options. It would be useful to have comprehensive tests for this.
As a start, create a script which tries out loading a kernel/ramdisk/fdt from a FIT and checks that the images appear in the right place in memory.
This uses sandbox which now supports bootm and related features.
--- test/image/test-fit.py | 422 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 422 insertions(+), 0 deletions(-) create mode 100755 test/image/test-fit.py
test/image/test-fit.py new file +422 -0
@@ -0,0 +1,422 @@ +#!/usr/bin/python +# +# Copyright (c) 2013, Google Inc. +# +# Sanity check of the FIT handling in U-Boot +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# To run this: +# +# make O=sandbox sandbox_config +# make O=sandbox +# ./test/image/test-fit.py -u sandbox/u-boot + +import doctest +from optparse import OptionParser +import os +import shutil +import struct +import sys +import tempfile + +# The 'command' library in patman is convenient for running commands +base_path = os.path.dirname(sys.argv[0]) +patman = os.path.join(base_path, '../../tools/patman') +sys.path.append(patman) + +import command + +# Define a base ITS which we can adjust using % and a dictionary +base_its = ''' +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel at 1 { + data = /incbin/("%(kernel)s"); + type = "kernel"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x40000>; + entry = <0x8>; + }; + fdt at 1 { + description = "snow"; + data = /incbin/("u-boot.dtb"); + type = "flat_dt"; + arch = "sandbox"; + %(fdt_load)s + compression = "none"; + signature at 1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + ramdisk at 1 { + description = "snow"; + data = /incbin/("%(ramdisk)s"); + type = "ramdisk"; + arch = "sandbox"; + os = "linux"; + %(ramdisk_load)s + compression = "none"; + }; + }; + configurations { + default = "conf at 1"; + conf at 1 { + kernel = "kernel at 1"; + fdt = "fdt at 1"; + %(ramdisk_config)s + }; + }; +}; +''' + +# Define a base FDT - currently we don't use anything in this +base_fdt = ''' +/dts-v1/; + +/ { + model = "Sandbox Verified Boot Test"; + compatible = "sandbox"; + +}; +''' + +# This is the U-Boot script that is run for each test. First load the fit, +# then do the 'bootm' command, then save out memory from the places where +# we expect 'bootm' to write things. Then quit. +base_script = ''' +sb load host 0 %(fit_addr)x %(fit)s +fdt addr %(fit_addr)x +bootm start %(fit_addr)x +bootm loados +sb save host 0 %(kernel_out)s %(kernel_addr)x %(kernel_size)x +sb save host 0 %(fdt_out)s %(fdt_addr)x %(fdt_size)x +sb save host 0 %(ramdisk_out)s %(ramdisk_addr)x %(ramdisk_size)x +reset +''' + +def make_fname(leaf): + """Make a temporary filename + + Args: + leaf: Leaf name of file to create (within temporary directory) + Return: + Temporary filename + """ + global base_dir + + return os.path.join(base_dir, leaf) + +def filesize(fname): + """Get the size of a file + + Args: + fname: Filename to check + Return: + Size of file in bytes + """ + return os.stat(fname).st_size + +def read_file(fname): + """Read the contents of a file + + Args: + fname: Filename to read + Returns: + Contents of file as a string + """ + with open(fname, 'r') as fd: + return fd.read() + +def make_dtb(): + """Make a sample .dts file and compile it to a .dtb + + Returns: + Filename of .dtb file created + """ + src = make_fname('u-boot.dts') + dtb = make_fname('u-boot.dtb') + with open(src, 'w') as fd: + print >>fd, base_fdt + command.Output('dtc', src, '-O', 'dtb', '-o', dtb) + return dtb + +def make_its(params): + """Make a sample .its file with parameters embedded + + Args: + params: Dictionary containing parameters to embed in the %() strings + Returns: + Filename of .its file created + """ + its = make_fname('test.its') + with open(its, 'w') as fd: + print >>fd, base_its % params + return its + +def make_fit(mkimage, params): + """Make a sample .fit file ready for loading + + This creates a .its script with the selected parameters and uses mkimage to + turn this into a .fit image. + + Args: + mkimage: Filename of 'mkimage' utility + params: Dictionary containing parameters to embed in the %() strings + Return: + Filename of .fit file created + """ + fit = make_fname('test.fit') + its = make_its(params) + command.Output(mkimage, '-f', its, fit) + with open(make_fname('u-boot.dts'), 'w') as fd: + print >>fd, base_fdt + return fit + +def make_kernel(): + """Make a sample kernel with test data + + Returns: + Filename of kernel created + """ + fname = make_fname('test-kernel.bin') + data = '' + for i in range(100): + data += 'this kernel %d is unlikely to boot\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def make_ramdisk(): + """Make a sample ramdisk with test data + + Returns: + Filename of ramdisk created + """ + fname = make_fname('test-ramdisk.bin') + data = '' + for i in range(100): + data += 'ramdisk %d was seldom used in the middle ages\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def find_matching(text, match): + """Find a match in a line of text, and return the unmatched line portion + + This is used to extract a part of a line from some text. The match string + is used to locate the line - we use the first line that contains that + match text. + + Once we find a match, we discard the match string itself from the line, + and return what remains. + + TODO: If this function becomes more generally useful, we could change it + to use regex and return groups. + + Args: + text: Text to check (each line separated by \n) + match: String to search for + Return: + String containing unmatched portion of line + Exceptions: + ValueError: If match is not found + + >>> find_matching('first line:10\\nsecond_line:20', 'first line:') + '10' + >>> find_matching('first line:10\\nsecond_line:20', 'second linex') + Traceback (most recent call last): + ... + ValueError: Test aborted + >>> find_matching('first line:10\\nsecond_line:20', 'second_line:') + '20' + """ + for line in text.splitlines(): + pos = line.find(match) + if pos != -1: + return line[:pos] + line[pos + len(match):] + + print "Expected '%s' but not found in output:" + print text + raise ValueError('Test aborted') + +def set_test(name): + """Set the name of the current test and print a message + + Args: + name: Name of test + """ + global test_name + + test_name = name + print name + +def fail(msg): + """Raise an error with a helpful failure message + + Args: + msg: Message to display + """ + raise ValueError("Test '%s' failed: %s" % (test_name, msg)) + +def run_fit_test(mkimage, u_boot): + """Basic sanity check of FIT loading in U-Boot + + TODO: Almost everything: + - hash algorithms - invalid hash/contents should be detected + - signature algorithms - invalid sig/contents should be detected + - compression + - checking that errors are detected like: + - image overwriting + - missing images + - invalid configurations + - incorrect os/arch/type fields + - empty data + - images too large/small + - invalid FDT (e.g. putting a random binary in instead) + - default configuration selection + - bootm command line parameters should have desired effect + - run code coverage to make sure we are testing all the code + """ + global test_name + + # Set up invariant files + control_dtb = make_dtb() + kernel = make_kernel() + ramdisk = make_ramdisk() + kernel_out = make_fname('kernel-out.bin') + fdt_out = make_fname('fdt-out.dtb') + ramdisk_out = make_fname('ramdisk-out.bin') + + # Set up basic parameters with default values + params = { + 'fit_addr' : 0x1000, + + 'kernel' : kernel, + 'kernel_out' : kernel_out, + 'kernel_addr' : 0x40000, + 'kernel_size' : filesize(kernel), + + 'fdt_out' : fdt_out, + 'fdt_addr' : 0x80000, + 'fdt_size' : filesize(control_dtb), + 'fdt_load' : '', + + 'ramdisk' : ramdisk, + 'ramdisk_out' : ramdisk_out, + 'ramdisk_addr' : 0xc0000, + 'ramdisk_size' : filesize(ramdisk), + 'ramdisk_load' : '', + 'ramdisk_config' : '', + } + + # Make a basic FIT and a script to load it + fit = make_fit(mkimage, params) + params['fit'] = fit + cmd = base_script % params + + # First check that we can load a kernel + # We could perhaps reduce duplication with some loss of readability + set_test('Kernel load') + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) == read_file(fdt_out): + fail('FDT loaded but should be ignored') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Find out the offset in the FIT where U-Boot has found the FDT + line = find_matching(stdout, 'Booting using the fdt blob at ') + fit_offset = int(line, 16) - params['fit_addr'] + fdt_magic = struct.pack('>L', 0xd00dfeed) + data = read_file(fit) + + # Now find where it actually is in the FIT (skip the first word) + real_fit_offset = data.find(fdt_magic, 4) + if fit_offset != real_fit_offset: + fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' % + (fit_offset, real_fit_offset)) + + # Now a kernel and an FDT + set_test('Kernel + FDT load') + params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) != read_file(fdt_out): + fail('FDT not loaded') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Try a ramdisk + set_test('Kernel + FDT + Ramdisk load') + params['ramdisk_config'] = 'ramdisk = "ramdisk at 1";' + params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(ramdisk) != read_file(ramdisk_out): + fail('Ramdisk not loaded') + +def run_tests(): + """Parse options, run the FIT tests and print the result""" + global base_path, base_dir + + # Work in a temporary directory + base_dir = tempfile.mkdtemp() + parser = OptionParser() + parser.add_option('-u', '--u-boot', + default=os.path.join(base_path, 'u-boot'), + help='Select U-Boot sandbox binary') + parser.add_option('-k', '--keep', action='store_true', + help="Don't delete temporary directory even when tests pass") + parser.add_option('-t', '--selftest', action='store_true', + help='Run internal self tests') + (options, args) = parser.parse_args() + + # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir + base_path = os.path.dirname(options.u_boot) + mkimage = os.path.join(base_path, 'tools/mkimage') + + # There are a few doctests - handle these here + if options.selftest: + doctest.testmod() + return + + title = 'FIT Tests' + print title, '\n', '=' * len(title) + + run_fit_test(mkimage, options.u_boot) + + print '\nTests passed' + print 'Caveat: this is only a sanity check - test coverage is poor' + + # Remove the tempoerary directory unless we are asked to keep it + if options.keep: + print "Output files are in '%s'" % base_dir + else: + shutil.rmtree(base_dir) + +run_tests()
Signature · 1 line
1.7.7.3
RFC PATCH 22/22 WIP: sandbox: config: Remove boot command
In reply to Simon GlassWe don't really need this now that we can provide a script to sandbox using -c.
This is a test commit only - please do not apply.
--- include/configs/sandbox.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
include/configs/sandbox.h +0 -1
@@ -120,7 +120,6 @@"stderr=serial\0" \ CONFIG_SANDBOX_ENV -#define CONFIG_BOOTCOMMAND "run test"#define CONFIG_BOOTDELAY 0/* -1 to disable auto boot */ #endif
Signature · 1 line
1.7.7.3
cover RFC: image: Reduce code duplication and refactor
In reply to Simon GlassHi,
Quoted 35 lines · Simon Glass
In creating a new feature[*] I found that the image code includes quite a bit of duplication in places. In particular the code to load a kernel, FDT and ramdisk is all fairly similar, but subtly different.
This series introduces a new function
fit_image_load()which loads an image from a FIT and supports the various features. For the bootstage updates, these are standardised so that each file has its own range and the events within that range have corresponding numbers. This means that the boot progress numbers will change slightly with this series.The
image.cfile is still very long. Rather than perpetuate the #ifdefs in the code I have split out theimage.ccode that is dependent onCONFIG_OF_LIBFDTintoimage-fdt.c.Several architectures have their own way of setting up a ramdisk and FDT for booting. An attempt is made here to unify these by providing a function
image_setup_linux()to handle the overall task, andimage_setup_fdt()to set
up the FDT.For ARM, the bootm code is a maze of #ifdefs, which means that many boards compile the code differently and it takes longer to detect breakages. To get
around this, some defines are added to ARM'sbootm.hto permit the use ofif()instead of #ifdef, making use of the compiler's dead code elimination.Also this series introduces a very basic test of image loading using sandbox.
Some patches add bootm support for sandbox, and also a 'sb save' command to save memory to a host file (used to check that the bootm actually worked).A test program for sandbox is added as a basic sanity check of image loading
as performed by bootm.
Quoted 7 lines
This series depends on the verified boot series since it builds on the clean-up in that. You can get this series from:
http://git.denx.de/u-boot-x86.gitbranch name 'image'.
Has anyone taken a look at this series? It is mostly a clean-up, but does also introduces basic tests for FIT.
Regards,
Simon