You are here: DENX Home »  U-Boot » Tasks » TaskRefactorBootmImage

Refactor bootm and Image Commands

Problems:
  • bootm has gathered more and more variants of sequences for booting the target OS.
    • Kumar has created a bootm <subcmd> changeset to break the currently unbreakable sequence into steps that can be run sequentially and allows modifications (run commands) in between the bootm steps.
  • image.c has grown large and unwieldy. This was aggravated by adding the FIT image handling to it.
    • Can we split the FIT image processing out into a fit_image.c file?

Sequence

  1. fdt boardsetup
    • Do board-specific FDT setup
  2. fdt chosen
    • Create the FDT /chosen node
  3. interrupts off
    • Disable interrupts (need CONFIG_CMD_IRQ)
  4. usb stop
    • USB stop (only if USB is supported)
  5. dcache off ; icache off
    • Disable cache (only needed for the Amiga One 3SE
  6. bootm start <os> <initrd> <fdtaddr>
    • bootm start $loadaddr $ramdiskaddr $fdtaddr
    • Sets the addresses…
  7. bootm ramdisk
    • Copies the ramdisk to high memory, honoring the env variable initrd_high and leaving room for the logbuffer
  8. bootm fdt
    • Copies the fdt to a "good" location
  9. bootm bdt
    • Sets up the bd_t struct values (legacy)
  10. bootm cmdline
    • Sets up the (linux) command line
  11. bootm prepos
    • OS-specific preparations before relocation or go
  12. bootm loados
    • Copies (with decompressing, if necessary) the OS to its execution address
  13. bootm go

Original Sequence

  1. Initialize / fill out the images structure
  2. lmb
    • env specified region: =getenv_bootm_low(); / getenv_bootm_size();
    • board reserved region (optional): board_lmb_reserve(&lmb);
  3. os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, &images, &os_data, &os_len);
  4. /* get image parameters */ (different methods of filling out these variables based on IMAGE_FORMAT_LEGACY or IMAGE_FORMAT_FIT)
    • type
    • comp
    • os
    • image_end
    • load_start
    • image_start
    • load_end (set to zero, filled in after decompressing)
    • type_name
  5. Disable interrupts
  6. USB stop (if CONFIG_CMD_USB)
  7. Disable caches (if CONFIG_AMIGAONEG3SE)
  8. Decompress the image (based on compression type)
    • Sets load_end to the proper value
  9. Some sanity checking (load vs. image start and end, header validity)
  10. Add image load region to lmb
  11. OS-specific start function - should not return

  • We need to support the ability to load the images but not actually transfer control to the OS
  • We need to support the ability to modify the device tree before its handled to the OS. These modification need to be controlled at runtime and not compile time.

  • Traditional: bootm <osaddr> [(-|<ramdisk>) [<fdtaddr>]]
=> bootm $loadaddr $ramdiskaddr $fdtaddr
## Booting kernel from Legacy Image at 00408000 …
   Image Name:   Linux-2.6.26-06077-gc010b2f
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    1391935 Bytes =  1.3 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum … OK
## Loading init Ramdisk from Legacy Image at 01000000 …
   Image Name:   Simple Embedded Linux Framework
   Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
   Data Size:    1731902 Bytes =  1.7 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum … OK
## Flattened Device Tree blob at 00400000
   Booting using the fdt blob at 0x400000
   Uncompressing Kernel Image … OK
   Loading Ramdisk to 0fdf7000, end 0ff9dd3e … OK

Refactoring cmd_bootm.c

  • External functions
    • extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp);
    • extern void bz_internal_error(int);
    • extern flash_info_t flash_info[]; /* info for FLASH chips */ (used by "imls" command)
    • extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);

  • Helper functions
    • static void fixup_silent_linux (void);
    • static image_header_t *image_get_kernel (ulong img_addr, int verify);
    • static int fit_check_kernel (const void *fit, int os_noffset, int verify);
    • static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len);

  • Board-specific helper functions
    • void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve")));

  • Command functions
    • int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
    • static int image_info (unsigned long addr); - iminfo command
    • static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - imls command

  • Function pointer
    • typedef void boot_os_fn (cmd_tbl_t cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images); / pointers to os/initrd/fdt */
    • extern boot_os_fn do_bootm_linux; - Q: Why is this one extern? (Probably cause its implemented in the /bootm.c)
    • static boot_os_fn do_bootm_netbsd;
    • static boot_os_fn do_bootm_lynxkdi;
    • static boot_os_fn do_bootm_rtems;
    • static boot_os_fn do_bootm_vxworks;
    • static boot_os_fn do_bootm_qnxelf;
    • static boot_os_fn do_bootm_artos;
    • …and support functions used with the function pointers
      • extern void lynxkdi_boot (image_header_t *);
      • int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
      • int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);

Refactoring image.c

  • External functions
    • Legacy image handling
      • int image_check_hcrc (image_header_t *hdr) (legacy support)
      • int image_check_dcrc (image_header_t *hdr) (legacy support)
      • ulong image_multi_count (image_header_t *hdr) (legacy support)
      • void image_multi_getimg (image_header_t *hdr, ulong idx, ulong *data, ulong *len) (legacy support)
      • void image_print_contents (image_header_t *hdr) (legacy support)
      • int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base)
    • Externally available utility functions
      • int getenv_yesno (char *var) (utility)
      • ulong getenv_bootm_low(void) - returns the env variable bootm_low or, if not defined, the lowest address of RAM (utility)
      • phys_size_t getenv_bootm_size(void) - returns the env variable =bootm_size or, if not defined, the size of RAM (utility)
      • void memmove_wd (void *to, void *from, size_t len, ulong chunksz) - move memory, kicking the WDT
    • New image handling
      • int genimg_get_format (void *img_addr) - new image format detection and identification
      • ulong genimg_get_image (ulong img_addr)
      • int genimg_has_config (bootm_headers_t *images)
      • int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end)
      • int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, ulong *initrd_start, ulong *initrd_end) - used by lib_*/bootm.c - seems misplaced.
      • int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, char **of_flat_tree, ulong *of_size)
      • int boot_get_fdt (int flag, int argc, char *argv[], bootm_headers_t *images, char **of_flat_tree, ulong *of_size)
      • int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, ulong bootmap_base)

    • Translate IDs to strings
      • const char *genimg_get_os_name (uint8_t os)
      • const char *genimg_get_arch_name (uint8_t arch)
      • const char *genimg_get_type_name (uint8_t type)
      • const char *genimg_get_comp_name (uint8_t comp)
    • Translate strings to IDs
      • int genimg_get_os_id (const char *name)
      • int genimg_get_arch_id (const char *name)
      • int genimg_get_type_id (const char *name)
      • int genimg_get_comp_id (const char *name)

  • Helper functions
    • static void image_print_type (image_header_t *hdr)
    • static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify)
    • static void genimg_print_size (uint32_t size)
    • static void genimg_print_time (time_t timestamp)
    • static char *get_table_entry_name (table_entry_t *table, char *msg, int id) - translate an ID to a printable name
    • static int get_table_entry_id (table_entry_t *table, const char *table_name, const char *name)
    • static void fdt_error (const char *msg)
    • static image_header_t *image_get_fdt (ulong fdt_addr)
    • static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)

    • static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, ulong *addr, const char **name)
    • inline int fit_parse_conf (const char *spec, ulong addr_curr, ulong *addr, const char **conf_name)
    • inline int fit_parse_subimage (const char *spec, ulong addr_curr, ulong *addr, const char **image_name)
    • static void fit_get_debug (const void *fit, int noffset, char *prop_name, int err)
    • void fit_print_contents (const void *fit)
    • void fit_image_print (const void *fit, int image_noffset, const char *p)
    • void fit_image_print_hash (const void *fit, int noffset, const char *p)
    • int fit_get_desc (const void *fit, int noffset, char **desc)
    • int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp)
    • int fit_image_get_node (const void *fit, const char *image_uname)
    • int fit_image_get_os (const void *fit, int noffset, uint8_t *os)
    • int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch)
    • int fit_image_get_type (const void *fit, int noffset, uint8_t *type)
    • int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp)
    • int fit_image_get_load (const void *fit, int noffset, ulong *load)
    • int fit_image_get_entry (const void *fit, int noffset, ulong *entry)
    • int fit_image_get_data (const void *fit, int noffset, const void **data, size_t *size)
    • int fit_image_hash_get_algo (const void *fit, int noffset, char **algo)
    • int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value, int *value_len)
    • int fit_set_timestamp (void *fit, int noffset, time_t timestamp)
    • static int calculate_hash (const void *data, int data_len, const char *algo, uint8_t *value, int *value_len)
    • int fit_set_hashes (void *fit)
    • int fit_image_set_hashes (void *fit, int image_noffset)
    • int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, int value_len)
    • int fit_image_check_hashes (const void *fit, int image_noffset)
    • int fit_all_image_check_hashes (const void *fit)
    • int fit_image_check_os (const void *fit, int noffset, uint8_t os)
    • int fit_image_check_arch (const void *fit, int noffset, uint8_t arch)
    • int fit_image_check_type (const void *fit, int noffset, uint8_t type)
    • int fit_image_check_comp (const void *fit, int noffset, uint8_t comp)
    • int fit_check_format (const void *fit)
    • int fit_conf_get_node (const void *fit, const char *conf_uname)
    • static int __fit_conf_get_prop_node (const void *fit, int noffset, const char *prop_name)
    • 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)
    • void fit_conf_print (const void *fit, int noffset, const char *p)
    • static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify)

  • Board-specific helper functions

  • Command functions

  • Function pointer

New Commands Thoughts…

This section is some thoughts about if we made an imload command with subcommands rather than shoehorning the image manipulation into the bootm command.
  • I'm wondering whether the OS/ramdisk/fdtblob needs to be loaded into RAM separately. The fdtblob needs to be modified before booting, that needs to be separate. The ramdisk may not exist. Conclusion: yes, might as well do all of them separately.
  • We already have a copy command for memory chunks and fdt move for fdtblobs. We should be able to script things using existing+new commands. Missing:
    • An "uncompress" command.
    • A way of getting addresses and length information from the images. Unfortunately, our hush shell doesn't implement back-ticks "`". We could hack our way around this by setting env variables as side effects. fUgly… frown, sad smile

  1. Copy fdt into destination address
  2. Copy initrd into destination address
  3. Decompress/copy OFP into destination address (requires interrupts disabled)

  • imload fit <fitaddr>
    • Load a FIT image into appropriate locations
  • imload os <osaddr>
    • Load an OS image into the appropriate location
    • Return (set env variables?) for start and end addresses
  • imload ramdisk <ramdisk>
    • Load a RAMDISK image into the appropriate location
    • Return (set env variables?) for start and end addresses
    • What is needed is the ramdisk start address, destination address, and length. Then a cp command can do the move?!
  • imload fdt <fdtaddr>
    • Load a FDT blob into the appropriate location
    • Return (set env variables?) for start and end addresses
    • What is needed is the blob start address, destination address, and length. Then a fdt move (or cp?) command can do the move?!

  • bootm bdt
    • Sets up the bd_t struct values (legacy)
  • bootm cmdline
    • Sets up the (linux) command line
  • bootm prepos
    • OS-specific preparations before relocation or go
  • bootm go
Copyright © 2002-2022 by DENX Software Engineering GmbH ImprintTerms & ConditionsPrivacyFeedback
This website is using cookies. More info. That's Fine