U-boot START Process Analysis (2) _ Board level (board) section

Source: Internet
Author: User
Tags spl

Transferred from: http://www.wowotech.net/u-boot/boot_flow_2.html

Directory :

1. Preface

2. Generic Board

3. _main

4. Global data introduction and the thinking behind it

5. Pre-board level initialization operation

6. U-boot's Relocation

7. Post-board initialization operation

1. Preface

The book connected to the above (u-boot START process Analysis (1) _ Platform related parts), This article describes the U-boot initiation process and the specific version (board) related parts , that is, Board_init_f/board_init_r represents, Board about the initialization process. The process will continue to u-boot the entire life cycle until Main_loop (the legendary command line).

Note 1: Due to u-boot after the initialization process, basically involved in all the software modules, so this article can not be analyzed one by one, the basic principle is to pick up the pleasing to the eye, cooked hands ~.

2. Generic Board

We introduced the Board_init_f interface in the "U-boot Start Process Analysis (1) _ Platform related section", and in the U-boot migration instructions for x-003-uboot-based on Bubblegum-96 platform, through the board in SPL image _init_f lit an LED light.

The basic strategy of u-boot is to declare a series of APIs (such as Low_level_init, Board_init_f, Board_init_r, and so on) and invoke them in the core logic of U-boot. The porting and the developer of the platform, the need to do is to implement them according to the actual situation.

At the same time, in order to reduce the amount of development effort, U-boot provides a common implementation for most APIs (typically through config configuration items or if you define to control whether or not to compile). Taking the Board_init_f and Board_init_r two board-level initialization interfaces as an example, U-boot provides a generic implementation in COMMON/BOARD_F.C and common/board_r.c two files respectively. See Common/makefile:

Ifndef Config_spl_build
...
# boards
obj-$ (config_sys_generic_board) + = BOARD_F.O
obj-$ (config_sys_generic_board) + = BOARD_R.O
...
ENDIF #! Config_spl_build

These two common interfaces are controlled by the Config_sys_generic_board configuration item and are only compiled in U-boot image. Then through the configuration of the arm platform in Arch/kconfig:

Config ARM
BOOL "ARM Architecture"
Select Create_arch_symlink
Select HAVE_PRIVATE_LIBGCC if! ARM64
Select Have_generic_board
Select Sys_generic_board
Select Support_of_control

The ARM platform automatically enables the Config_sys_generic_board configuration, so u-boot image about the board-level start-up process is implemented by GENERIC Board code, which can refer to subsequent analysis.

NOTE 2: By " u-boot Start-Up Process Analysis (1) _ Platform related parts The analysis in this paper shows that the declaration period of SPL image ends when the custom board_init_f execution completes, so this article will only target u-boot image.

3. _main

Then "u-boot Start Process Analysis (1) _ Platform related section" of the expression, we re-analysis from the _main function (but this is no longer the SPL build, the code is no longer posted). The execution process is as follows:

1) Set the initial stack

The base address is defined by CONFIG_SYS_INIT_SP_ADDR.

2) space required to allocate global data

After the stack is aligned to bits, call the Board_init_f_alloc_reserve interface and, from the beginning of the stack, allocate space for U-boot's global data (struct global_data). As follows:

/* COMMON/INIT/BOARD_INIT.C */

ULONG Board_init_f_alloc_reserve (ULONG top)
{
/* Reserve Early malloc Arena */
#if defined (config_sys_malloc_f)
Top-= Config_sys_malloc_f_len;
#endif
/* Last:reserve GD (rounded up to a multiple of bytes) */
top = RoundDown (top-sizeof (struct global_data), 16);

return top;
}

It is important to note that if Config_sys_malloc_f_len is defined, the space required for early MALLOC is first reserved.

3) Initialize global data

After the spatial allocation of global data, call Board_init_f_init_reserve and initialize global data. The so-called initialization, is nothing more than a few clear 0 operation, but there are several places to note:

1) if not arm platform (! Config_arm), you can call the ARCH_SETUP_GD interface to set the arch level. Of course, the premise is that the corresponding arch should implement this interface.

2) If Config_sys_malloc_f is defined, the gd->malloc_base is initialized.

4) Perform pre-initialization (front) operations

Call the Board_init_f interface and perform the pre-initialization operation, which is explained in detail later in the chapter.

5) Perform the relocation operation, which will be explained in detail later.

6) Clear BBS segment

7) Perform a post-initialization (rear) operation

Call the Board_init_r interface and perform the pre-initialization operation, which is explained in detail later in the chapter.

4. Global data introduction and the thinking behind 4.1 background knowledge

To understand the meaning of global data, you need to understand the following facts:

U-boot is a bootloader, and in some cases it may be in the system's read-only memory (ROM or flash), and from there it executes.

So, in this case, in the pre-U-boot execution (before you copy it to read-write memory), the storage space in which it resides is not writable, and there are two problems:

1) The stack is unusable and cannot perform function calls, that is, the C environment is not available.

2) There is no data segment (or a properly initialized data segment) available, and there is no way to share it in the form of global variables between different functions or code.

For problem 1, the usual solution is:

After the u-boot is running, a stack space is opened up in a read-write storage area that is not required to perform any initialization actions.

In general, most platforms (such as many arm platforms) have their own SRAM, which can be used as a stack space. If not, there are ways to borrow the CPU's data cache (no more explanation).

For problem 2, the solution is slightly more complex:

First, for developers, never use global variables until u-boot is copied to read-write RAM (this action is called relocation).

Secondly, before relocation, there is a need to pass data in the form of global variables between different modules. What to do? That's what global data needs to solve.

4.2 Global Data

In order to pass data in the form of global variables before relocation, U-boot has devised an ingenious method:

1) Define a struct Global_data data structure that holds a variety of data that needs to be passed

The specific contents of the data structure, the later use of the time of one more explanation, here is no longer detailed introduction. For specific reference: INCLUDE/ASM-GENERIC/GLOBAL_DATA.H

2) After the stack is configured, at the beginning of the stack, reserve space for the struct Global_data (refer to the relevant description in chapter 3rd) and save the start address (that is, a struct global_data pointer) in a register, subsequent delivery, are implemented by pointers saved in registers

For the arm64 platform, the pointer is stored in the X18 register, as follows:

/* Https://github.com/wowotechX/u-boot/blob/x_integration/arch/arm/lib/crt0_64.S */

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

The return value of the above Board_init_f_alloc_reserve (x0) is a pointer to global data.

/* ARCH/ARM/INCLUDE/ASM/GLOBAL_DATA.H */

#ifdef __clang__

#define Declare_global_data_ptr
#define GD GET_GD ()

Static inline gd_t *get_gd (void)
{
gd_t *gd_ptr;

#ifdef config_arm64
...
__asm__ volatile ("mov%0, x18\n": "=r" (gd_ptr));
#else
...
}

#else

#ifdef config_arm64
#define DECLARE_GLOBAL_DATA_PTR Register volatile gd_t *gd asm ("x18")
#else
...
#endif

5. Pre-board level initialization operation

When global data is ready, U-boot performs a pre-board initialization action, known as Board_init_f. The so-called pre-initialization action, which is primarily the initialization operation prior to relocation, is said:

When performing Board_init_f, U-boot is most likely still in read-only memory. This is all you can remember!

Note 3: You may think this is F (front?) and R (rear?) The naming is a bit strange, I guess this software engineer should be a fan, is not borrowing the concept of precursor and rear drive? It's unclear.

For platforms such as ARM, U-boot provides a common Board_init_f interface that uses U-boot's usual design ideas:

U-boot will need to initialize the content in Board_init_f, which is abstracted into a series of APIs. These APIs are declared by U-boot and are implemented by the platform's developers according to the actual situation. Refer to the following description of this chapter for details.

5.1 Board_init_f

The implementation of the Board_init_f interface in COMMON/BOARD_F.C is very simple, as follows (omitting some useless code):

void Board_init_f (ULONG boot_flags)
{
...

Gd->flags = Boot_flags;
Gd->have_console = 0;

if (Initcall_run_list (Init_sequence_f))
Hang ();

...
}

After a simple initialization of global data, the various initialization APIs in the Init_sequence_f array are invoked to perform a variety of initialization actions. The following is a brief introduction to some of the more important APIs related to the arm platform for porting work in the peace station. Other APIs, you can refer to source code self-understanding.

Note 4: The following red font labeling API, is the U-boot porting when there is a great potential need for the API, everyone notice is.

5.2 Fdtdec_setup

#ifdef Config_of_control
Fdtdec_setup,
#endif

If Config_of_control is turned on, call Fdtdec_setup and configure the Gd->fdt_blob pointer (the storage location where device tree resides). For the arm platform, U-boot's makefile will use the connection script to package the DtB file to the u-boot image's "__dtb_dt_begin" location, so there is no need for special attention.

5.3 Trace_early_init

#ifdef Config_trace
Trace_early_init,
#endif

By the Config_trace configuration item control, for the time being not concerned, the later use when the analysis.

5.4 Initf_malloc

If Config_sys_malloc_f_len is defined, call Initf_malloc to initialize the global data associated with MALLOC, such as Gd->malloc_limit, Gd->malloc_ptr.

5.5 Arch_cpu_init

CPU-level initialization operations, which can be implemented by CPU-related code when needed.

5.6 INITF_DM

Driver Model-related initialization operations. If CONFIG_DM is defined, call Dm_init_and_scan to initialize and scan all of the system's device. If config_timer_early is defined, call Dm_timer_init to initialize the TIMER required for driver model.

5.7 Board_early_init_f

#if defined (config_board_early_init_f)
Board_early_init_f,
#endif

If Config_board_early_init_f is defined, the Board_early_init_f interface is called, and the EARLY initialization of the board level is performed. The platform's developers can implement the Board_early_init_f interface as needed to accomplish certain functions.

5.8 Timer_init

Initializes the system timer.

The interface should be implemented by the platform or board-level code, and after the successful initialization, U-boot will get the current timestamp through other APIs, which are described in detail later.

5.9 Get_clocks

Get the current CPU and bus clock frequency and save it in global data:

Gd->cpu_clk

Gd->bus_clk

5.10 Env_init

The logic for initializing environment variables does not require special attention.

5.11 Init_baud_rate

Gd->baudrate = Getenv_ulong ("BaudRate", ten, Config_baudrate);

Gets the current baud rate using the serial port, can have two channels (priority from high to low): from "baudrate", obtained from the Config_baudrate configuration item.

5.12 Serial_init

Initializes the serial, including the U-boot serial core and the specific serial driver. After the function is executed, the serial port of the system (especially for the console) is available.

5.13 Console_init_f

/* called before relocation-use serial functions * *
int Console_init_f (void)
{
Gd->have_console = 1;

#ifdef Config_silent_console
if (getenv ("silent") = NULL)
Gd->flags |= gd_flg_silent;
#endif

Print_pre_console_buffer (pre_console_flushpoint1_serial);

return 0;
}

Initialize the console of the system, then the serial port output is available. You can pay attention to the Config_silent_console configuration item, if enabled, you can control whether the U-boot console is output through the "SILENT" environment variable.

5.14 FDTDEC_PREPARE_FDT

#ifdef Config_of_control
FDTDEC_PREPARE_FDT,
#endif

If Config_of_control is defined, call the FDTDEC_PREPARE_FDT interface and prepare the device tree for the content. An analysis of the subsequent device tree is described in detail.

5.15 Display_options/display_text_info/print_cpuinfo/show_board_info

The console shows some information that can be used for debug.

5.16 Misc_init_f

#if defined (config_misc_init_f)
Misc_init_f,
#endif

If Config_misc_init_f is enabled, call Misc_init_f to perform MISC driver-related initialization.

5.17 INIT_FUNC_I2C

#if defined (CONFIG_HARD_I2C) | | Defined (CONFIG_SYS_I2C)
INIT_FUNC_I2C,
#endif

If CONFIG_HARD_I2C or CONFIG_SYS_I2C is enabled, INIT_FUNC_I2C is called to perform an I²C driver-related initialization.

5.18 Init_func_spi

#if defined (CONFIG_HARD_SPI)
INIT_FUNC_SPI,
#endif

If CONFIG_HARD_SPI is enabled, the INIT_FUNC_SPI is invoked to perform the initialization of the SPI driver.

5.19 Announce_dram_init

Announce that we are going to initialize the DDR (which is actually a line of print).

5.20 Dram_init

#if defined (config_arm) | | Defined (config_x86) | | Defined (CONFIG_NDS32) | | \
Defined (Config_microblaze) | | Defined (CONFIG_AVR32)
Dram_init,/* Configure available RAM banks */
#endif

Call the Dram_init interface to initialize the system's DDR. Dram_init should be implemented by platform-related code.

If the DDR has already been initialized in SPL, there is no need to reinitialize, just keep the DDR information in global data, for example:

Gd->ram_size = ...

5.21 Testdram

#if defined (config_sys_dram_test)
Testdram,
#endif/* Config_sys_dram_test */

If config_sys_dram_test is defined, a test operation that Testdram performs DDR is called. Can be opened in the development phase, the system is stable and closed.

allocation of 5.22 DRAM space

After the DRAM initialization is complete, you can start planning the parts of the u-boot that you need to use, such as:

Figure 1 usage of DRAM in U-boot

summarized as follows :

1) Considering that subsequent kernel are decompressed and executed at the low end of the RAM, U-boot will use the top address of the DRAM, the location represented by Gd->ram_top, in order to avoid trouble. Where Gd->ram_top is configured by the SETUP_DEST_ADDR function.

2) The DRAM used by U-boot is divided into three main categories: space required for various special functions, such as log buffer, MMU page table, LCD fb buffer, trace buffer, and so on; U-boot code snippet, data segment, The space occupied by the BSS segment (that is, the execution space after the U-boot relocate), marked by GD->RELOCADDR, and the stack space descending from the gd->start_addr_sp.

3) Special functions and u-boot required space, is reserved by the RESERVE_XXX series functions, the specific reference source code, which is no longer detailed analysis.

4) After the reserve space allocation is complete, the stack is immediately followed by a decrement.

5.23 Setup_dram_config

Call the Dram_init_banksize interface (implemented by the specific platform code) to initialize the bank information for the DDR.

5.24 RELOC_FDT

If config_of_embed is not defined, the device tree is first copied to the location of picture 1 NEW_FDT, which is the relocation operation of the device tree.

5.25 Setup_reloc

Calculate relocation related information, mainly Gd->reloc_off, the formula is as follows:

Gd->reloc_off = gd->relocaddr-config_sys_text_base;

Where Config_sys_text_base is U-boot relocation before (read-only) memory location (also at compile-time specified location), GD->RELOCADDR is the location after relocation, so gd-> The Reloc_off represents the offset after the U-boot relocation operation, which is used later relocation.

At the same time, the function, by the way, copies global data to the "new global Data" as shown in Figure 1, which is actually the relocation of global data.

6. U-boot's Relocation

As mentioned earlier, U-boot is possible to start in a read-only memory. For simplicity's sake, U-boot assumes that all launches are so, so U-boot's startup logic is designed for this scenario. In this case, it is based on the following considerations:

1) Execute in read only memory, code should be carefully written (cannot use global variables, etc.).

2) read-only memory execution speed is usually slower.

U-boot need at a certain point in time, to copy themselves from "Read Memory", to read-write memory (such as SDRAM, hereafter referred to as RAM, note and SRAM differentiated, do not understand the wrong) continue to execute, this is the relocation (relocation) operation.

The time point of the relocation can be any point in time after the system can read and write memory starts. According to the current code logic of U-boot, after Board_init_f execution is complete, because Board_init_f completes a lot of relocation related preparation action, can refer to the description of the 5th chapter.

The code for U-boot relocation is as follows (for example, arm64):

/* Https://github.com/wowotechX/u-boot/blob/x_integration/arch/arm/lib/crt0_64.S */

        ldr     x0, [x18, #GD_START_ADDR_SP]    /* x0 <-gd->start_addr_sp */ 
        bic      SP, x0, #0xf    /* 16-byte alignment for ABI compliance */ 
         ldr     x18, [x18, #GD_BD]              /* x18 <-gd->bd */ 
        sub      x18, x18, #GD_SIZE               /* New GD is below BD */

ADR LR, Relocation_return
Ldr X9, [x18, #GD_RELOC_OFF]/* x9 <-gd->reloc_off * *
Add LR, LR, x9/* New return address after relocation */
Ldr x0, [x18, #GD_RELOCADDR]/* x0 <-gd->relocaddr * *
b Relocate_code

Relocation_return:

Logic is relatively simple:

1) After removing relocation from global data, the stack base address, 16-byte, is saved to the SP.

2) Save the new global data pointer to the X18 register.

3) Calculate the relocation after the execution address (Relocation_return), the calculation method is the current Relocation_return location plus gd->reloc_off.

4) to relocation the destination address (GD->RELOCADDR) as the parameter, call Relocate_code to perform the actual relocation action, is to u-boot the code snippet, data segment, BSS segment and other data, Copy to the new location (GD->RELOCADDR).

7. Post-board initialization operation

After the relocate is complete, the real C-run environment is established, followed by a "post-board initialization operation", the Board_init_r function. Board_init_r and Board_init_f design ideas are basically the same, there is a very long initialization sequence----init_sequence_r, the sequence contains the following initialization function (logic is relatively simple, here is no longer involved in details, the right to List index bar):

Note 5: The usual, red-labeled function is a more important function.

1) Initr_trace, initialize and enable u-boot of the tracing system, the configuration items involved are config_trace.

2) Initr_reloc, set relocation to complete the logo.

3) Initr_caches, enable Dcache, Icache, etc., the configuration items involved have config_arm.

4) Initr_malloc,malloc related initialization.

5) After initr_dm,relocate, the DM is reinitialized, and the configuration item involved is CONFIG_DM.

6) Board_init, the specific board level initialization, need to be implemented by board code as needed, the configuration items involved have config_arm.

7) Set_cpu_clk_info,initialize Clock Framework, the configuration items involved are config_clocks.

8) Initr_serial, re-initialize the serial port (not very clear what meaning).

9) Initr_announce, announced that it has been executed in RAM, will print the address after relocate.

Board_early_init_r, implemented by board-level code, involves a configuration item with Config_board_early_init_r.

One) Arch_early_init_r, implemented by the arch code, involves configuration items that are config_arch_early_init_r.

Power_init_board, board-level power init code, implemented by board-level code, such as hold power.

Initr_flash, Initr_nand, Initr_onenand, Initr_mmc, Initr_dataflash, the initialization of various flash devices.

Initr_env, the initialization of the environment variable.

INITR_SECONDARY_CPU, initialize the other CPU cores.

Stdio_add_devices, the initialization of various input, such as LCD driver.

Interrupt_init, interrupts the initialization of the related.

Initr_enable_interrupts, enable system interruption, involving the configuration of the Config_arm (ARM platform U-boot is actually running in the case of an interruption).

Initr_status_led, the status indicates the initialization of the LED, the configuration items involved are config_status_led, status_led_boot.

Initr_ethaddr,ethernet initialization, the configuration items involved are config_cmd_net.

Board_late_init, implemented by board-level code, involves a configuration item with Config_board_late_init.

22) etc...

Run_main_loop/main_loop, execute to main_loop, start command line operation.

U-boot START Process Analysis (2) _ Board level (board) section

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.