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
-
fdt boardsetup
- Do board-specific FDT setup
-
fdt chosen
- Create the FDT
/chosen
node
- interrupts off
- Disable interrupts (need
CONFIG_CMD_IRQ
)
-
usb stop
- USB stop (only if USB is supported)
-
dcache off ; icache off
- Disable cache (only needed for the Amiga One 3SE
-
bootm start <os> <initrd> <fdtaddr>
-
bootm start $loadaddr $ramdiskaddr $fdtaddr
- Sets the addresses…
-
bootm ramdisk
- Copies the ramdisk to high memory, honoring the env variable
initrd_high
and leaving room for the logbuffer
-
bootm fdt
- Copies the fdt to a "good" location
-
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 loados
- Copies (with decompressing, if necessary) the OS to its execution address
-
bootm go
Original Sequence
- Initialize / fill out the
images
structure
-
lmb
- env specified region: =getenv_bootm_low(); / getenv_bootm_size();
- board reserved region (optional):
board_lmb_reserve(&lmb);
-
os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, &images, &os_data, &os_len);
-
/* 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
- Disable interrupts
- USB stop (if CONFIG_CMD_USB)
- Disable caches (if CONFIG_AMIGAONEG3SE)
- Decompress the image (based on compression type)
- Sets
load_end
to the proper value
- Some sanity checking (load vs. image start and end, header validity)
- Add image load region to
lmb
- 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
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…
- Copy fdt into destination address
- Copy initrd into destination address
- 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