How to write U-Boot (Bootloader)


1.1.3 U-Boot Linux boot process
U-Boot using the tag list (tagged list) to the Linux way of passing parameters. The data structure is marked tag, in the U-Boot source directory include / asm-arm / setup.h defined as follows:

struct tag_header {

u32 size; / * said the joint u tag data structure in real terms the size of the data stored in * /

u32 tag; / * that the type of tag * /

};

struct tag {

struct tag_header hdr;

union {

struct tag_core core;

struct tag_mem32 mem;

struct tag_videotext videotext;


struct tag_ramdisk ramdisk;

struct tag_initrd initrd;

struct tag_serialnr serialnr;

struct tag_revision revision;

struct tag_videolfb videolfb;

struct tag_cmdline cmdline;

/ *

* Acorn specific

* /

struct tag_acorn acorn;

/ *

* DC21285 specific

* /

struct tag_memclk memclk;

} U;

};
U-Boot to boot using the command bootm already loaded into memory in the kernel. The bootm command actually invokes a do_bootm function. For the Linux kernel, do_bootm function call function to set the mark do_bootm_linux list and start the kernel. do_bootm_linux function lib_arm / bootm.c defined as follows:

59 int do_bootm_linux (int flag, int argc, char * argv [], bootm_headers_t * images)

60 {

61 bd_t * bd = gd-> bd;

62 char * s;

63 int machid = bd-> bi_arch_number;

64 void (* theKernel) (int zero, int arch, uint params);

65

66 # ifdef CONFIG_CMDLINE_TAG

67 char * commandline = getenv ("bootargs"); / * U-Boot environment variables bootargs * /

68 # endif

... ...

73 theKernel = (void (*) (int, int, uint)) images-> ep; / * get kernel entry address * /

... ...

86 # if defined (CONFIG_SETUP_MEMORY_TAGS) | | \

87 defined (CONFIG_CMDLINE_TAG) | | \

88 defined (CONFIG_INITRD_TAG) | | \

89 defined (CONFIG_SERIAL_TAG) | | \

90 defined (CONFIG_REVISION_TAG) | | \

91 defined (CONFIG_LCD) | | \

92 defined (CONFIG_VFD)

93 setup_start_tag (bd); / * set ATAG_CORE flag * /

... ...

100 # ifdef CONFIG_SETUP_MEMORY_TAGS

101 setup_memory_tags (bd); / * set the memory to be marked * /

102 # endif

103 # ifdef CONFIG_CMDLINE_TAG

104 setup_commandline_tag (bd, commandline); / * set the command-line flags * /

105 # endif

... ...

113 setup_end_tag ​​(bd); / * set ATAG_NONE flags * /

114 # endif

115

116 / * we assume that the kernel is in place * /

117 printf ("\ nStarting kernel ... \ n \ n");

... ...

126 cleanup_before_linux (); / * start the kernel before the final setting of the CPU * /

127

128 theKernel (0, machid, bd-> bi_boot_params); / * call kernel * /

129 / * does not return * /

130

131 return 1;

132}

Which setup_start_tag, setup_memory_tags, setup_end_tag ​​function lib_arm / bootm.c defined as follows:

(1) setup_start_tag function

static void setup_start_tag (bd_t * bd)

{

params = (struct tag *) bd-> bi_boot_params; / * start address of kernel parameters * /

params-> hdr.tag = ATAG_CORE;

params-> hdr.size = tag_size (tag_core);

params-> u.core.flags = 0;

params-> u.core.pagesize = 0;

params-> u.core.rootdev = 0;

params = tag_next (params);

}

Tag list must ATAG_CORE start, setup_start_tag function parameters in the kernel set the start address of a ATAG_CORE tag.

(2) setup_memory_tags function

static void setup_memory_tags (bd_t * bd)

{

int i;

/ * Set a memory tag * /

for (i = 0; i
params-> hdr.tag = ATAG_MEM;

params-> hdr.size = tag_size (tag_mem32);

params-> u.mem.start = bd-> bi_dram [i]. start;

params-> u.mem.size = bd-> bi_dram [i]. size;

params = tag_next (params);

}

}

setup_memory_tags function sets a ATAG_MEM tag that contains the starting memory address, memory size, these two parameters.

(3) setup_end_tag ​​function

static void setup_end_tag ​​(bd_t * bd)

{

params-> hdr.tag = ATAG_NONE;

params-> hdr.size = 0;

}

Marked the end of the list must be marked ATAG_NONE, setup_end_tag ​​function sets a ATAG_NONE tag that marks the end of the list.

U-Boot after the set list will mark a call to the kernel. But before calling the kernel, CPU must meet the following conditions:

(1) CPU register settings
r0 = 0
r1 = machine code
r2 = kernel parameter marker list start address in RAM

(2) CPU operating modes
Disable IRQ and FIQ interrupts
CPU model for the SVC

(3) the failure of Data Cache and Instruction Cache

do_bootm_linux called cleanup_before_linux function in the complete prohibition and make the Cache fail interrupt function. cleanup_before_linux function cpu/arm920t/cpu. the definition:

int cleanup_before_linux (void)

{

/ *

* This function is called just before we call linux

* It prepares the processor for linux

*

* We turn off caches etc ...

* /

disable_interrupts (); / * prohibit FIQ / IRQ interrupt * /

/ * Turn off I / D-cache * /

icache_disable (); / * Instruction Cache failure to make * /

dcache_disable (); / * Cache the data fail * /

/ * Flush I / D-cache * /

cache_flush (); / * Refresh Cache * /

return 0;

}

As the U-Boot has been working since the start in the SVC mode, the CPU operating mode no need to set up.

do_bootm_linux in:

64 void (* theKernel) (int zero, int arch, uint params);

... ...

73 theKernel = (void (*) (int, int, uint)) images-> ep;

... ...

128 theKernel (0, machid, bd-> bi_boot_params);

73 lines of code to the kernel entry address ï ¿ ½ images-> epï ¿ ½ cast a function pointer. According ATPCS rules, functions, number of parameters more than 4, the use of r0 ~ r3 four registers to pass parameters. So the first line of the function call 128 to 0 will be placed in r0, into machine code machid r1, kernel parameters address bd-> bi_boot_params into r2, thus completing the register set, and finally to the kernel entry address.

Here, U-Boot's work is over, the system jumps to the Linux kernel code execution.
1.1.4 U-Boot command to add the method and process of U-Boot command

The following command to add a menu (Start menu) as an example to explain U-Boot to add commands.

(1) establishing common / cmd_menu.c

General command on the source code used on common directory, and the development board proprietary source code is placed on the command board / directory, and accustomed to "cmd_ . C" for the file name.

(2) defines "menu" command

In cmd_menu.c use the following code defines "menu" command:

_BOOT_CMD (

menu, 3, 0, do_menu,

"Menu - display a menu, to select the items to do something \ n",

"- Display a menu, to select the items to do something"

);

One U_BOOT_CMD command format is as follows:

U_BOOT_CMD (name, maxargs, rep, cmd, usage, help)

The significance of each parameter as follows:

name: command name, not a string, but in U_BOOT_CMD using "#" symbol into a string

maxargs: command the largest number of parameters

rep: whether to automatically repeat (press Enter key to whether it will repeat)

cmd: The command corresponding to the response function

usage: the use of a short description (string)

help: the use of a more detailed description (string)

Save command in the memory field will help take some of the memory, by configuring U-Boot can choose whether to help save the field. If include / configs / mini2440.h CONFIG_SYS_LONGHELP defined macro, then use U-Boot to a command, help command will display help information when the contents of the field usage and help, otherwise only shows usage field content.

U_BOOT_CMD macro in include / command.h defined:

# Define U_BOOT_CMD (name, maxargs, rep, cmd, usage, help) \

cmd_tbl_t __u_boot_cmd_ # # name Struct_Section = {# name, maxargs, rep, cmd, usage, help}

"# #" And "#" are pre-compiled a string concatenation operator ,"##" function, "#" followed by that followed a string.

Which cmd_tbl_t in include / command.h defined as follows:

struct cmd_tbl_s {

char * name; / * command name * /

int maxargs; / * maximum number of arguments * /

int repeatable; / * whether to automatically repeat * /

int (* cmd) (struct cmd_tbl_s *, int, int, char *[]); / * response function * /

char * usage; / * short help * /

# Ifdef CONFIG_SYS_LONGHELP

char * help; / * more detailed help information * /

# Endif

# Ifdef CONFIG_AUTO_COMPLETE

/ * The auto completion function * /

int (* complete) (int argc, char * argv [], char last_char, int maxv, char * cmdv []);

# Endif

};

typedef struct cmd_tbl_s cmd_tbl_t;

A cmd_tbl_t structure variable contains a command called the information they need.

Which Struct_Section in include / command.h defined as follows:

# Define Struct_Section __attribute__ ((unused, section (". U_boot_cmd")))

All with __attribute__ ((unused, section (". U_boot_cmd")) attributes declared variables will be stored in ". U_boot_cmd" section, and even if the variables are not explicit in the code using the compiler does not generate warning message.

Connect the U-Boot script u-boot.lds defined ". U_boot_cmd" section:

. =.;

__u_boot_cmd_start =.; / * will __u_boot_cmd_start designated as the current address * /

. U_boot_cmd: {* (. U_boot_cmd)}

__u_boot_cmd_end =.; / * will __u_boot_cmd_end specified as the current address * /

This indicates that with the ï ¿ ½. U_boot_cmdï ¿ ½ declare a function or variable will be stored in the ï ¿ ½ u_boot_cmdï ¿ ½ segments. So long as the U-Boot command corresponding cmd_tbl_t all variables with ï ¿ ½. U_boot_cmdï ¿ ½ statement, the compiler will automatically be placed in ï ¿ ½ u_boot_cmdï ¿ ½ section to find cmd_tbl_t variable between as long as __u_boot_cmd_start and __u_boot_cmd_end find it.

Therefore ï ¿ ½ menuï ¿ ½ macro command after the commencement of the definition is as follows:

cmd_tbl_t __u_boot_cmd_menu __attribute__ ((unused, section (". u_boot_cmd"))) = {menu, 3, 0, do_menu, "menu - display a menu, to select the items to do something \ n", "- display a menu, to select the items to do something "}

In essence, is to use the information U_BOOT_CMD macro constructs a cmd_tbl_t type of structure. Compiler structure on the ï ¿ ½ u_boot_cmdï ¿ ½ segment, execute the command you can ï ¿ ½ u_boot_cmdï ¿ ½ segment to the corresponding cmd_tbl_t find the type of structure.

(3) to achieve a function of command

Add ï ¿in cmd_menu.c ½ menuï ¿ ½ order response function implementation. Specific implementation code slightly:

int do_menu (cmd_tbl_t * cmdtp, int flag, int argc, char * argv [])

{

/ * Implement the code slightly * /

}

(4) common / cmd_menu.c compiled u-boot.bin

In common / Makefile add the following code:

COBJS-$ (CONFIG_BOOT_MENU) + = cmd_menu.o

In include/configs/mini2440.h participate in such a code:

# Define CONFIG_BOOT_MENU 1

Download U-Boot to recompile, you can use menu commands

(5) menu command in the process

Enter the U-Boot ï ¿ ½ menuï ¿ ½ command is executed, U-Boot to receive input string ï ¿ ½ menuï ¿ ½, passed to run_command function. run_command function call common / command.c implemented find_cmd function __u_boot_cmd_start and __u_boot_cmd_end between the find command, and returns the menu command cmd_tbl_t structure. Then run_command function uses the return cmd_tbl_t structure function pointer call menu command response function do_menu, thus completing the execution of the command.

No comments:

Post a Comment

Thank You , For Immediate Assistance Plz Put Email Copy to Deviceporting@gmail.com