Uboot startup process analysis

U-Boot

U-Boot, the full name of the Universal Boot Loader, is an open source project that follows the GPL terms. The role of U-Boot is system booting. U-Boot evolved from FADSROM, 8xxROM, and PPCBOOT. Its source directory and compilation form are very similar to the Linux kernel. In fact, many U-Boot source code is formed according to the corresponding Linux kernel source program, especially some device drivers, which are from U-Boot source code. This can be reflected in the comments.

U-Boot not only supports booting of embedded Linux systems, it also supports NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android embedded operating systems. The target operating systems currently supported are OpenBSD, NetBSD, FreeBSD, 4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS, android. This is a layer of meaning in Universal in U-Boot. Another meaning is that in addition to supporting the PowerPC series of processors, U-Boot can also support many popular series of processors such as MIPS, x86, ARM, NIOS, and XScale.

These two features are the development goals of the U-Boot project, which supports as many embedded processors and embedded operating systems as possible. For the time being, U-Boot has the richest support for the PowerPC family of processors and the most complete support for Linux. The other series of processors and operating systems were gradually expanded after PPCBOOT was renamed U-Boot in November 2002. The smooth transition from PPCBOOT to U-Boot is largely due to the superb professionalism and persistent efforts of U-Boot's maintainer, Germany's DENX Software Engineering Center Wolfgang Denk [hereinafter referred to as WD]. At present, the U-Boot project is under his leadership. Many embedded developers who are interested in the open source BOOT LOADER porting work are in full swing to expand and deepen the migration of different series of embedded processors to support more. Loading and booting of the embedded operating system.

Uboot startup process analysis

Uboot startup process analysis

It can be seen that the entry of the program is at _start, and the entry _start for finding the discoverable program in SourceInsight is in u-boot-2016.05\arch\arm\lib\vectors.S.

. . .

ENTRY(_start)

SECTIONS

{

. . .

. = 0x00000000;

. = ALIGN(4);

.text :

{

*(.__image_copy_start)

*(.vectors)

CPUDIR/start.o (.text*)

*(.text*)

}

. . .

. = ALIGN(4);

.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

. = ALIGN(4);

.data : {

*(.data*)

}

. = ALIGN(4);

. = . ;

. . .

.bss_start __rel_dyn_start (OVERLAY) : {

KEEP(*(.__bss_start));

__bss_base = . ;

}

.bss __bss_base (OVERLAY) : {

*(.bss*)

. = ALIGN(4);

__bss_limit = . ;

}

.bss_end __bss_limit (OVERLAY) : {

KEEP(*(.__bss_end));

}

. . .

}

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474484849505152

Go to boot-2016.05\arch\arm\lib\vectors.S and you can see that after jumping from _start, you will jump to reset to execute:

. . .

.globl _start

. . .

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG

.word CONFIG_SYS_DV_NOR_BOOT_CFG

#endif

b reset

Ldr pc, _undefined_instrucTIon

Ldr pc, _software_interrupt

Ldr pc, _prefetch_abort

Ldr pc, _data_abort

Ldr pc, _not_used

Ldr pc, _irq

Ldr pc, _fiq

. . .12345678910111213141516171819202122

1. Perform reset from u-boot-2016.05\arch\arm\cpu\arm920t\start.S

The main execution process: reset - "cpu_init_crit -" lowlevel_init -" _main

Reset:

. . .

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

Bl cpu_init_crit

#endif

Bl _main

. . .

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

Cpu_init_crit:

. . .

Bl lowlevel_init

. . .

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

1234567891011121314151617181920212223

2, jump from bl _main to u-boot-2016.05\arch\arm\lib\crt0.S from the entry _main

The main execution process: board_init_f -> relocate_code -> board_init_r

ENTRY(_main)

. . .

Bl board_init_f_alloc_reserve

. . .

Bl board_init_f_init_reserve

. . .

Bl board_init_f

#if ! Defined (CONFIG_SPL_BUILD)

. . .

b relocate_code

. . .

#endif

#if ! Defined(CONFIG_SPL_BUILD) ||defined(CONFIG_SPL_FRAMEWORK)

. . .

#if defined(CONFIG_SYS_THUMB_BUILD)

. . .

#else

Ldr pc, =board_init_r

#endif

#endif

ENDPROC(_main)123456789101112131415161718192021222324252627282930313233

There are three points in this section:

(1), u-boot-2016.05\common\board_f.c: board_init_f executes a series of initialization functions through the initcall_run_list(init_sequence_f) function to implement the first half of the board level initialization. The global structure gd is declared in u-boot-2016.05\arch\arm\include\asm\global_data.h:

#define DECLARE_GLOBAL_DATA_PTR register volaTIle gd_t *gd asm ("r9")1

(2), u-boot-2016.05\arch\arm\libelocate.S: relocate_code to achieve the relocation of the uboot code, if you feel that the source code is not simple and clear, you can rewrite it yourself.

(3), there are two paths to relocate uboot:

One is to set gd-"flags to 0, and jump to relocate_code in the jump_to_copy function in the initialization function sequence init_sequence_f:

staTIc int jump_to_copy(void)

{

If (gd-"flags & GD_FLG_SKIP_RELOC)

Return 0;

. . .

#if defined(CONFIG_X86) ||defined(CONFIG_ARC)

. . .

#else

Relocate_code(gd-"start_addr_sp, gd-"new_gd, gd-"relocaddr);

#endif

Return 0;

}1234567891011121314

The other is to not define CONFIG_SPL_BUILD, and then pass in u-boot-2016.05\arch\arm\lib\crt0.S

#if ! Defined (CONFIG_SPL_BUILD)

. . .

b relocate_code

. . .

#endif123456789

To jump to relocate_code. Choose one of the above two methods, and the other must be removed.

3. In the previous step, enter the u-boot-2016.05\common\board_r.c:board_init_r function through the ldr pc, =board_init_r command , and then call the initcall_run_list(init_sequence_r) function to execute a series of initialization functions to implement the second half of the board level initialization, and Entering run_main_loop in the initcall_run_list function no longer returns.

Void board_init_r(gd_t *new_gd, ulong dest_addr)

{

. . .

If (initcall_run_list(init_sequence_r))

Hang();

/* NOTREACHED - run_main_loop() does not return */

Hang();

}

1234567891011

Init_sequence_r is an array of function pointers that store a number of initialization function pointers. There are two important function pointers initr_announce and run_main_loop:

Init_fnc_t init_sequence_r[] = {

. . .

Initr_announce,

. . .

Run_main_loop,

};12345678910

The initr_announce function declares that the program will jump to RAM and run from here:

Static int initr_announce(void)

{

Debug("Now running in RAM - U-Boot at: %08lx", gd-"relocaddr);

Return 0;

}12345

The last item is run_main_loop , which is not returned after entering run_main_loop.

4, in the run_main_loop will enter u-boot-2016.05\common\main.c: main_loop function

Static int run_main_loop(void)

{

. . .

For (;;)

Main_loop();

Return 0;

}12345678

Initialization is completed before entering main_loop, and then ready to process the command

/* We come here after U-Boot is initialised and ready to process commands */

Void main_loop(void)

{

Const char *s;

Bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");

. . .

/* get environment_variable: s = getenv("bootcmd"); -" bootcmd */

s = bootdelay_process();

. . .

Autoboot_command(s);

. . .

}123456789101112131415161718

There are two important processes in the main_loop function:

(1) First, in the bootdelay_process function, get the bootcmd parameter and return the bootcmd parameter by s = getenv ("bootcmd").

Const char *bootdelay_process(void)

{

Char *s;

Int bootdelay;

. . .

s = getenv("bootdelay");

. . .

Debug("### main_loop entered: bootdelay=%d", bootdelay);

. . .

s = getenv("bootcmd");

. . .

Stored_bootdelay = bootdelay;

Return s;

}1234567891011121314151617181920212223

Among them, the bootcmd parameter is specified in the following way:

First in u-boot-2016.05\include\env_default.h

#ifdef CONFIG_BOOTCOMMAND

"bootcmd=" CONFIG_BOOTCOMMAND "\0"

#endif123

Then specify in u-boot-2016.05\include\configs\smdk2440.h

#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel;bootm 30000000"1

(2), then enter the autoboot_command function, and pass the bootcmd parameter, then enter the run_command_list function, continue to pass the bootcmd parameter

Void autoboot_command(const char *s)

{

. . .

If (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {

. . .

Run_command_list(s, -1, 0);

. . .

}

. . .

}

123456789101112

5, after entering the u-boot-2016.05\common\cli.c:run_command_list function from the autoboot_command function, the board_run_command function will be called to execute the command.

Int run_command_list(const char *cmd, int len, int flag)

{

Int need_buff = 1;

Char *buff = (char *)cmd; /* cast away const */

Int rcode = 0;

If (len == -1) {

Len = strlen(cmd);

#ifdef CONFIG_SYS_HUSH_PARSER

. . .

#else

/* the built-in parser will change our string if it sees */

Need_buff = strchr(cmd, '') ! = NULL;

#endif

}

If (need_buff) {

Buff = malloc(len + 1);

If (!buff)

Return 1;

Memcpy(buff, cmd, len);

Buff[len] = '\0';

}

#ifdef CONFIG_SYS_HUSH_PARSER

. . .

#ifdef CONFIG_CMDLINE

. . .

#else

Rcode = board_run_command(buff);

#endif

#endif

. . .

}1234567891011121314151617181920212223242526272829303132

So, how does board_run_command execute the command?

First, the board_run_command function finds u-boot-2016.05\cmd\bootm.c through the bootm command in the bootcmd parameter.

U_BOOT_CMD(

Bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,

"boot application image from memory", bootm_help_text

);1234

Then, based on this information, find the handler function pointer do_bootm that executes the bootm command, and enter the do_bootm function to execute the relevant code, and U_BOOT_CMD is defined in u-boot-2016.05\include\command.h:

#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \

U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)12

#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \

_comp) \

_CMD_REMOVE(sub_ ## _name, _cmd)123

#define _CMD_REMOVE(_name, _cmd) \

Int __remove_ ## _name(void) \

{ \

If (0) \

_cmd(NULL, 0, 0, NULL); \

Return 0; \

}1234567

Here, the board_run_command function will also assign the parameters in the bootm command (the address of the kernel image) 30000000 to the bootm_headers_t structure variable images, then the first address of the images is 30000000, and the images are defined in u-boot-2016.05\cmd\bootm.c :

Bootm_headers_t images; 1

Fiber Optic Box

Fiber Optic Box,Fiber Optics Box,Fiber Optic Boxes,Fiber Optic Junction Box

Cixi Dani Plastic Products Co.,Ltd , https://www.danifiberoptic.com