Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| u-boot_boot_sequence [2019/12/27 17:40] – [arch/arm/lib/crt0_64.S [ENTRY(_main)]] rpjday | u-boot_boot_sequence [2019/12/28 08:33] (current) – [1.] rpjday | ||
|---|---|---|---|
| Line 19: | Line 19: | ||
| ===== arch/ | ===== arch/ | ||
| - | ==== 1. ==== | + | ==== Prologue |
| - | ==== 2. ==== | + | < |
| + | * This file handles the target-independent stages of the U-Boot | ||
| + | * start-up where a C runtime environment is needed. Its entry point | ||
| + | * is _main and is branched into from the target' | ||
| + | </ | ||
| - | ==== 3. ==== | + | ==== 1. ==== |
| - | ==== 4a. ==== | + | < |
| - | + | * 1. Set up initial environment for calling board_init_f(). | |
| - | ==== 4b. ==== | + | * This environment |
| - | + | * the GD (' | |
| - | ==== 5. ==== | + | * available RAM (SRAM, locked cache...). In this context, VARIABLE |
| - | + | * global data, initialized or not (BSS), are UNAVAILABLE; | |
| - | ==== 6. ==== | + | * CONSTANT initialized data are available. GD should be zeroed |
| - | + | * before board_init_f() is called. | |
| - | ==== 7. ==== | + | </code> |
| - | + | ||
| - | ===== common/ | + | |
| - | + | ||
| - | ===== common/ | + | |
| - | + | ||
| - | ==== initr_dm() [C] ==== | + | |
| - | ==== board_init() [A,B] ==== | + | |
| - | + | ||
| - | ==== board_early_init_r() (not for Zynq) ==== | + | |
| - | + | ||
| - | ==== arch_early_init_r() [A] ==== | + | |
| - | + | ||
| - | * arch/ | + | |
| - | * arch/arm/ | + | |
| < | < | ||
| - | #if defined(CONFIG_ARCH_EARLY_INIT_R) | + | ENTRY(_main) |
| - | int arch_early_init_r(void) | + | |
| - | { | + | |
| - | #if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \ | + | |
| - | (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD)) | + | |
| - | int cpu_id = cpu_desc_id(); | + | |
| - | if (cpu_id < 0) | + | /* |
| - | | + | * Set up initial C runtime environment and call board_init_f(0). |
| - | + | */ | |
| - | | + | #if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK) |
| - | | + | |
| - | | + | #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) |
| - | | + | |
| - | #endif | + | #elif defined(CONFIG_INIT_SP_RELATIVE) |
| - | | + | |
| - | } | + | |
| + | #else | ||
| + | | ||
| #endif | #endif | ||
| + | bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ | ||
| + | mov x0, sp | ||
| + | bl board_init_f_alloc_reserve | ||
| + | mov sp, x0 | ||
| + | /* set up gd here, outside any C code */ | ||
| + | mov x18, x0 | ||
| + | bl board_init_f_init_reserve | ||
| </ | </ | ||
| - | ==== initr_mmc() [C] ==== | + | ==== 2. ==== |
| < | < | ||
| - | #ifdef CONFIG_MMC | + | * 2. Call board_init_f(). This function prepares the hardware for |
| - | static int initr_mmc(void) | + | * execution from system RAM (DRAM, DDR...) As system RAM may not |
| - | { | + | * be available yet, , board_init_f() must use the current GD to |
| - | puts(" | + | * store any data which must be passed on to later stages. These |
| - | | + | * data include the relocation destination, |
| - | | + | * the future GD location. |
| - | } | + | |
| - | #endif | + | |
| </ | </ | ||
| - | |||
| - | ==== initr_env() [C] ==== | ||
| < | < | ||
| - | static int initr_env(void) | + | mov x0, #0 |
| - | { | + | |
| - | /* initialize environment */ | + | </code> |
| - | if (should_load_env()) | + | |
| - | env_relocate(); | + | |
| - | else | + | |
| - | set_default_env(NULL, 0); | + | |
| - | #ifdef CONFIG_OF_CONTROL | + | |
| - | | + | |
| - | | + | |
| - | #endif | + | |
| - | /* Initialize from environment */ | + | ==== 3. ==== |
| - | load_addr | + | |
| - | return 0; | + | < |
| - | } | + | * 3. Set up intermediate environment where the stack and GD are the |
| + | | ||
| + | | ||
| </ | </ | ||
| - | |||
| - | ==== show_board_info() [C] ==== | ||
| - | |||
| - | From '' | ||
| < | < | ||
| - | int __weak checkboard(void) | + | #if !defined(CONFIG_SPL_BUILD) |
| - | { | + | |
| - | return 0; | + | |
| - | } | + | |
| /* | /* | ||
| - | | + | |
| - | | + | |
| + | * ' | ||
| */ | */ | ||
| - | int __weak show_board_info(void) | + | ldr x0, [x18, #GD_START_ADDR_SP] |
| - | { | + | |
| - | #ifdef CONFIG_OF_CONTROL | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | + | #if CONFIG_POSITION_INDEPENDENT | |
| - | | + | /* Add in link-vs-runtime offset */ |
| - | | + | adr x0, _start |
| + | ldr x9, _TEXT_BASE | ||
| + | | ||
| + | | ||
| #endif | #endif | ||
| - | + | /* Add in link-vs-relocation offset */ | |
| - | return | + | |
| - | } | + | add lr, lr, x9 /* new return |
| + | | ||
| </ | </ | ||
| + | ==== 4a. ==== | ||
| - | For '' | + | < |
| + | * 4a.For U-Boot proper (not SPL), call relocate_code(). This function | ||
| + | | ||
| + | | ||
| + | </ | ||
| < | < | ||
| - | int checkboard(void) | + | b |
| - | { | + | |
| - | | + | relocation_return: |
| - | return 0; | + | |
| - | } | + | |
| </ | </ | ||
| - | ==== arch_misc_init() | + | ==== 4b. ==== |
| - | + | ||
| - | Some arches and boards, not Zynq. | + | |
| < | < | ||
| - | #ifdef CONFIG_ARCH_MISC_INIT | + | * 4b.For SPL, board_init_f() just returns (to crt0). There is no |
| - | arch_misc_init, | + | * code relocation in SPL. |
| - | #endif | + | |
| </ | </ | ||
| - | ==== misc_init_r() | + | ==== 5. ==== |
| < | < | ||
| - | #ifdef CONFIG_MISC_INIT_R | + | * 5. Set up final environment for calling board_init_r(). This |
| - | | + | * environment has BSS (initialized to 0), initialized non-const |
| - | #endif | + | * data (initialized to their intended value), and stack in system |
| + | | ||
| + | | ||
| </ | </ | ||
| - | ==== initr_enable_interrupts() | + | ==== 6. ==== |
| < | < | ||
| - | #ifdef CONFIG_ARM | + | * 6. For U-Boot proper |
| - | static int initr_enable_interrupts(void) | + | * at this point regarding memory, so call c_runtime_cpu_setup. |
| - | { | + | |
| - | enable_interrupts(); | + | |
| - | return 0; | + | |
| - | } | + | |
| - | #endif | + | |
| </ | </ | ||
| - | |||
| - | From '' | ||
| < | < | ||
| - | int interrupt_init | + | /* |
| - | { | + | * Set up final (full) environment |
| + | */ | ||
| + | bl c_runtime_cpu_setup | ||
| + | #endif /* !CONFIG_SPL_BUILD */ | ||
| + | #if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK) | ||
| + | #if defined(CONFIG_SPL_BUILD) | ||
| + | bl spl_relocate_stack_gd | ||
| + | /* set up gd here, outside any C code, if new stack is returned */ | ||
| + | cmp x0, #0 | ||
| + | | ||
| /* | /* | ||
| - | | + | |
| + | * around the constraint that conditional moves can not | ||
| + | * have ' | ||
| */ | */ | ||
| - | | + | |
| + | cmp x0, #0 | ||
| + | csel x0, x0, x1, ne | ||
| + | mov sp, x0 | ||
| + | #endif | ||
| - | return 0; | + | /* |
| - | } | + | * Clear BSS section |
| + | */ | ||
| + | ldr x0, =__bss_start | ||
| + | ldr x1, =__bss_end | ||
| + | clear_loop: | ||
| + | str xzr, [x0], #8 | ||
| + | cmp x0, x1 | ||
| + | b.lo clear_loop | ||
| - | void enable_interrupts | + | /* call board_init_r(gd_t *id, ulong dest_addr) */ |
| - | { | + | |
| - | | + | |
| - | } | + | |
| - | int disable_interrupts (void) | + | |
| - | { | + | |
| - | | + | |
| - | } | + | |
| </ | </ | ||
| - | ==== initr_ethaddr() [C] ==== | + | ==== 7. ==== |
| < | < | ||
| - | #ifdef CONFIG_CMD_NET | + | * 7. Branch to board_init_r(). |
| - | initr_ethaddr, | + | |
| - | #endif | + | |
| </ | </ | ||
| < | < | ||
| - | #ifdef CONFIG_CMD_NET | + | b |
| - | static int initr_ethaddr(void) | + | |
| - | { | + | |
| - | bd_t *bd = gd->bd; | + | |
| - | /* kept around for legacy kernels only ... ignore the next section */ | + | /* NOTREACHED |
| - | eth_env_get_enetaddr(" | + | |
| - | #ifdef CONFIG_HAS_ETH1 | + | |
| - | eth_env_get_enetaddr(" | + | |
| - | #endif | + | |
| - | #ifdef CONFIG_HAS_ETH2 | + | |
| - | eth_env_get_enetaddr(" | + | |
| - | #endif | + | |
| - | #ifdef CONFIG_HAS_ETH3 | + | |
| - | eth_env_get_enetaddr(" | + | |
| - | #endif | + | |
| - | #ifdef CONFIG_HAS_ETH4 | + | |
| - | eth_env_get_enetaddr(" | + | |
| - | #endif | + | |
| - | #ifdef CONFIG_HAS_ETH5 | + | |
| - | eth_env_get_enetaddr(" | + | |
| - | #endif | + | |
| - | | + | |
| - | } | + | |
| - | #endif /* CONFIG_CMD_NET | + | |
| </ | </ | ||
| - | ==== board_late_init() [B] ==== | + | ===== common/ |
| - | (Defined in board/ | + | < |
| + | void board_init_f(ulong boot_flags) | ||
| + | { | ||
| + | gd-> | ||
| + | gd-> | ||
| - | < | + | if (initcall_run_list(init_sequence_f)) |
| - | #ifdef CONFIG_BOARD_LATE_INIT | + | |
| - | | + | ... |
| - | #endif | + | |
| </ | </ | ||
| - | ==== initr_net() | + | ===== common/ |
| < | < | ||
| - | #ifdef CONFIG_CMD_NET | + | void board_init_r(gd_t *new_gd, ulong dest_addr) |
| - | static int initr_net(void) | + | |
| { | { | ||
| - | | + | |
| - | | + | * Set up the new global data pointer. So far only x86 does this |
| - | #if defined(CONFIG_RESET_PHY_R) | + | * here. |
| - | debug("Reset Ethernet PHY\n"); | + | * TODO(sjg@chromium.org): Consider doing this for all archs, or |
| - | | + | * dropping the new_gd parameter. |
| + | */ | ||
| + | #if CONFIG_IS_ENABLED(X86_64) | ||
| + | | ||
| #endif | #endif | ||
| - | return 0; | + | |
| - | } | + | #ifdef CONFIG_NEEDS_MANUAL_RELOC |
| + | int i; | ||
| #endif | #endif | ||
| - | </ | ||
| + | #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) | ||
| + | gd = new_gd; | ||
| + | #endif | ||
| + | gd-> | ||
| + | |||
| + | #ifdef CONFIG_NEEDS_MANUAL_RELOC | ||
| + | for (i = 0; i < ARRAY_SIZE(init_sequence_r); | ||
| + | init_sequence_r[i] += gd-> | ||
| + | #endif | ||
| + | |||
| + | if (initcall_run_list(init_sequence_r)) | ||
| + | hang(); | ||
| + | |||
| + | /* NOTREACHED - run_main_loop() does not return */ | ||
| + | hang(); | ||
| + | </ | ||