一、board_init_f(common/board_f.c)
该函数位于common/board_f.c文件:
void board_init_f(ulong boot_flags) { #ifdef CONFIG_SYS_GENERIC_GLOBAL_DATA /* * For some archtectures, global data is initialized and used before * calling this function. The data should be preserved. For others, * CONFIG_SYS_GENERIC_GLOBAL_DATA should be defined and use the stack * here to host global data until relocation. */ gd_t data; gd = &data; /* * Clear global data before it is accessed at debug print * in initcall_run_list. Otherwise the debug print probably * get the wrong vaule of gd->have_console. */ zero_global_data(); #endif gd->flags = boot_flags; #0x00 gd->have_console = 0; #0x00 if (initcall_run_list(init_sequence_f)) hang(); #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ !defined(CONFIG_EFI_APP) /* NOTREACHED - jump_to_copy() does not return */ hang(); #endif }
填充了flags和have_console字段后就执行一个初始化列表循环,这个循环里面有很多的函数,只要其中一个出错,u-boot启动就会停止。
initcall_run_list位于lib/initcall.c文件中:
int initcall_run_list(const init_fnc_t init_sequence[]) { const init_fnc_t *init_fnc_ptr; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { unsigned long reloc_ofs = 0; int ret; if (gd->flags & GD_FLG_RELOC) reloc_ofs = gd->reloc_off; #ifdef CONFIG_EFI_APP reloc_ofs = (unsigned long)image_base; #endif debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs); if (gd->flags & GD_FLG_RELOC) debug(" (relocated to %p)\n", (char *)*init_fnc_ptr); else debug("\n"); ret = (*init_fnc_ptr)(); if (ret) { printf("initcall sequence %p failed at call %p (err=%d)\n", init_sequence, (char *)*init_fnc_ptr - reloc_ofs, ret); return -1; } } return 0; }
这里我们记录gd_t这个数据结构:
typedef struct global_data { bd_t *bd; unsigned long flags; unsigned int baudrate; unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */ unsigned long pci_clk; unsigned long mem_clk; #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) unsigned long fb_base; /* Base address of framebuffer mem */ #endif #if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) unsigned long post_log_word; /* Record POST activities */ unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ #endif #ifdef CONFIG_BOARD_TYPES unsigned long board_type; #endif unsigned long have_console; /* serial_init() was called */ #ifdef CONFIG_PRE_CONSOLE_BUFFER unsigned long precon_buf_idx; /* Pre-Console buffer index */ #endif unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long ram_top; /* Top address of RAM used by U-Boot */ unsigned long relocaddr; /* Start address of U-Boot in RAM */ phys_size_t ram_size; /* RAM size */ #ifdef CONFIG_SYS_MEM_RESERVE_SECURE #define MEM_RESERVE_SECURE_SECURED 0x1 #define MEM_RESERVE_SECURE_MAINTAINED 0x2 #define MEM_RESERVE_SECURE_ADDR_MASK (~0x3) /* * Secure memory addr * This variable needs maintenance if the RAM base is not zero, * or if RAM splits into non-consecutive banks. It also has a * flag indicating the secure memory is marked as secure by MMU. * Flags used: 0x1 secured * 0x2 maintained */ phys_addr_t secure_ram; #endif unsigned long mon_len; /* monitor len */ unsigned long irq_sp; /* irq stack pointer */ unsigned long start_addr_sp; /* start_addr_stackpointer */ unsigned long reloc_off; struct global_data *new_gd; /* relocated global data */ #ifdef CONFIG_DM struct udevice *dm_root; /* Root instance for Driver Model */ struct udevice *dm_root_f; /* Pre-relocation root instance */ struct list_head uclass_root; /* Head of core tree */ #endif #ifdef CONFIG_TIMER struct udevice *timer; /* Timer instance for Driver Model */ #endif const void *fdt_blob; /* Our device tree, NULL if none */ void *new_fdt; /* Relocated FDT */ unsigned long fdt_size; /* Space reserved for relocated FDT */ struct jt_funcs *jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ #ifdef CONFIG_TRACE void *trace_buff; /* The trace buffer */ #endif #if defined(CONFIG_SYS_I2C) int cur_i2c_bus; /* current used i2c bus */ #endif #ifdef CONFIG_SYS_I2C_MXC void *srdata[10]; #endif unsigned long timebase_h; unsigned long timebase_l; #ifdef CONFIG_SYS_MALLOC_F_LEN unsigned long malloc_base; /* base address of early malloc() */ unsigned long malloc_limit; /* limit address */ unsigned long malloc_ptr; /* current address */ #endif #ifdef CONFIG_PCI struct pci_controller *hose; /* PCI hose for early use */ phys_addr_t pci_ram_top; /* top of region accessible to PCI */ #endif #ifdef CONFIG_PCI_BOOTDELAY int pcidelay_done; #endif struct udevice *cur_serial_dev; /* current serial device */ struct arch_global_data arch; /* architecture-specific data */ #ifdef CONFIG_CONSOLE_RECORD struct membuff console_out; /* console output */ struct membuff console_in; /* console input */ #endif #ifdef CONFIG_DM_VIDEO ulong video_top; /* Top of video frame buffer area */ ulong video_bottom; /* Bottom of video frame buffer area */ #endif } gd_t; #endif /* * Global Data Flags - the top 16 bits are reserved for arch-specific flags */ #define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ #define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ #define GD_FLG_SILENT 0x00004 /* Silent mode */ #define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */ #define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */ #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ #define GD_FLG_ENV_READY 0x00080 /* Env. imported into hash table */ #define GD_FLG_SERIAL_READY 0x00100 /* Pre-reloc serial console ready */ #define GD_FLG_FULL_MALLOC_INIT 0x00200 /* Full malloc() is ready */ #define GD_FLG_SPL_INIT 0x00400 /* spl_init() has been called */ #define GD_FLG_SKIP_RELOC 0x00800 /* Don't relocate */ #define GD_FLG_RECORD 0x01000 /* Record console */ #endif /* __ASM_GENERIC_GBL_DATA_H */
二、 init_sequence_f
init_sequence_f是一个函数指针数组,里面存放着各种初始化的函数指针,其中大部分函数只有定义了指定了宏才会生效,后面会针对其中比较重要的函数进行一一介绍。
static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_SANDBOX setup_ram_buf, #endif setup_mon_len, #ifdef CONFIG_OF_CONTROL fdtdec_setup, #endif #ifdef CONFIG_TRACE trace_early_init, #endif initf_malloc, initf_console_record, #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* TODO: can this go into arch_cpu_init()? */ probecpu, #endif #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) x86_fsp_init, #endif arch_cpu_init, /* basic arch cpu dependent setup */ initf_dm, arch_cpu_init_dm, mark_bootstage, /* need timer, go after init dm */ #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif /* TODO: can any of this go into arch_cpu_init()? */ #if defined(CONFIG_PPC) && !defined(CONFIG_8xx_CPUCLK_DEFAULT) get_clocks, /* get CPU and bus clocks (etc.) */ #if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \ && !defined(CONFIG_TQM885D) adjust_sdram_tbs_8xx, #endif /* TODO: can we rename this to timer_init()? */ init_timebase, #endif #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \ defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \ defined(CONFIG_SPARC) timer_init, /* initialize timer */ #endif #ifdef CONFIG_SYS_ALLOC_DPRAM #if !defined(CONFIG_CPM2) dpram_init, #endif #endif #if defined(CONFIG_BOARD_POSTCLK_INIT) board_postclk_init, #endif #if defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K) get_clocks, #endif env_init, /* initialize environment */ #if defined(CONFIG_8xx_CPUCLK_DEFAULT) /* get CPU and bus clocks according to the environment variable */ get_clocks_866, /* adjust sdram refresh rate according to the new clock */ sdram_adjust_866, init_timebase, #endif init_baud_rate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ #ifdef CONFIG_SANDBOX sandbox_early_getopt_check, #endif #ifdef CONFIG_OF_CONTROL fdtdec_prepare_fdt, #endif display_options, /* say that we are here */ display_text_info, /* show debugging info if required */ #if defined(CONFIG_MPC8260) prt_8260_rsr, prt_8260_clks, #endif /* CONFIG_MPC8260 */ #if defined(CONFIG_MPC83xx) prt_83xx_rsr, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) checkcpu, #endif print_cpuinfo, /* display cpu info (and speed) */ #if defined(CONFIG_MPC5xxx) prt_mpc5xxx_clks, #endif /* CONFIG_MPC5xxx */ #if defined(CONFIG_DISPLAY_BOARDINFO) show_board_info, #endif INIT_FUNC_WATCHDOG_INIT #if defined(CONFIG_MISC_INIT_F) misc_init_f, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) init_func_i2c, #endif #if defined(CONFIG_HARD_SPI) init_func_spi, #endif announce_dram_init, /* TODO: unify all these dram functions? */ #if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_NDS32) || \ defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) dram_init, /* configure available RAM banks */ #endif #if defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_M68K) init_func_ram, #endif #ifdef CONFIG_POST post_init_f, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_SYS_DRAM_TEST) testdram, #endif /* CONFIG_SYS_DRAM_TEST */ INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_POST init_post, #endif INIT_FUNC_WATCHDOG_RESET /* * Now that we have DRAM mapped and working, we can * relocate the code and continue running from DRAM. * * Reserve memory at end of RAM for (top down in that order): * - area that won't get touched by U-Boot and Linux (optional) * - kernel log buffer * - protected RAM * - LCD framebuffer * - monitor code * - board info struct */ setup_dest_addr, #if defined(CONFIG_BLACKFIN) /* Blackfin u-boot monitor should be on top of the ram */ reserve_uboot, #endif #if defined(CONFIG_SPARC) reserve_prom, #endif #if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) reserve_logbuffer, #endif #ifdef CONFIG_PRAM reserve_pram, #endif reserve_round_4k, #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \ defined(CONFIG_ARM) reserve_mmu, #endif #ifdef CONFIG_DM_VIDEO reserve_video, #else # ifdef CONFIG_LCD reserve_lcd, # endif /* TODO: Why the dependency on CONFIG_8xx? */ # if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \ !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \ !defined(CONFIG_BLACKFIN) && !defined(CONFIG_M68K) reserve_legacy_video, # endif #endif /* CONFIG_DM_VIDEO */ reserve_trace, #if !defined(CONFIG_BLACKFIN) reserve_uboot, #endif #ifndef CONFIG_SPL_BUILD reserve_malloc, reserve_board, #endif setup_machine, reserve_global_data, reserve_fdt, reserve_arch, reserve_stacks, setup_dram_config, show_dram_config, #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) setup_board_part1, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) INIT_FUNC_WATCHDOG_RESET setup_board_part2, #endif display_new_sp, #ifdef CONFIG_SYS_EXTBDINFO setup_board_extra, #endif INIT_FUNC_WATCHDOG_RESET reloc_fdt, setup_reloc, #if defined(CONFIG_X86) || defined(CONFIG_ARC) copy_uboot_to_ram, clear_bss, do_elf_reloc_fixups, #endif #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) jump_to_copy, #endif NULL, };