Parameter transfer between BootLoader and Linux Kernel

Source: Internet
Author: User
Parameter transfer of BootLoader and Linux kernel-general Linux technology-Linux programming and kernel information. For details, see the following. In an embedded system, BootLoader is used to initialize hardware, load the kernel, and pass parameters. Because the hardware environment of the embedded system is different, the BootLoader of the embedded system is also different. The most common one is U-Boot. It supports different architectures, such as ARM, powerPC, X86, MIPS, etc. This article describes the basic function of passing parameters between BootLoader and kernel. The hardware platform is based on AT91RM9200 processor system, and the software platform is the Linux-2.6.19.2 kernel. The kernel image file is zImage.

1. system hardware platform Overview
AT91RM9200 processor, which is a microprocessor based on ARM920T kernel of Atmel. It has a memory management unit and a CPU clock of up to 240 MHz. It has a wide range of standard interfaces and EBI interfaces, static storage controller (SMC), SDRAM controller, and Burst Flash controller are integrated internally. For instructions on processors, see the AT91RM9200 Data Manual. In this system, the SDRAM (64 MB) address is 0x20000000, And the NorFlash (8 MB) address is 0x10000000 [1].

2. Design and Implementation of BootLoader
The documentation/arm/booting [2] document under the kernel source code directory specifies the basic functions of BootLoader Based on the ARM architecture. In addition to completing these basic functions, the BootLoader of the system also adds code handling and other functions based on the features of its own hardware.

The BootLoader process is: after the system is powered on and reset, it starts to run from NorFlash (determined by the connection of the BMS pin of the processor ), because the 0 address of the processor is the first address of NorFlash (0x10000000), and the BootLoader is burned in this position, the AT91RM9200 processor can map only 0x0000 addresses.

-0x001f ffff. The first step of BootLoader execution is to transfer its own code from NorFlash to the RAM inside the processor (0x00200000), and then map the 0 address to the internal RAM, go to the corresponding address of the internal RAM and continue execution. After entering the internal RAM, the system enters the real hardware initialization phase. Various controllers initialized in this phase are required by the kernel, including PMC, EBI, SMC, SDRAM, and USART. The next step is to create the Tagged list. After the chain is created, the kernel image and the root file system image written in NorFlash are moved to the SDRAM, disable interruption, MMU, and data Cache based on the basic requirements of the kernel for BootLoader, and configure r0 = 0, r1 = 0x0000 00fb or 0x00000106 (based on linux/arch/arm/tools/mach-types in the kernel [2]

Specified machine number), r2 = 0x20000100 (the physical address that BootLoader passes to the Kernel Parameter linked list), In the ARM architecture, this address is used by default in the machine Descriptor (machine_desc) of the same processor, so it can be left unspecified here. Finally, the BootLoader directly jumps to the SDRAM kernel for execution.

3. List of Kernel Parameters
BootLoader can pass parameters to the kernel in two ways. One is the old parameter structure (parameter_struct), which is mainly used by the kernel before 2.6. Another method is the tagged list method currently used by the 2.6 kernel. These parameters mainly include the system root device identifier, page size, memory start address and size, RAMDISK start address and size, and the compressed RAMDISK root file system start address and size, kernel command parameters, etc. [3] [4] [5].

The format and description of the Kernel Parameter linked list can be found in include/asm-arm/setup. h [2] in the kernel source code directory tree. The parameter linked list must start with ATAG_CORE and end with ATAG_NONE. Here, ATAG_CORE and ATAG_NONE are the tags of each parameter. They are a 32-bit value, for example, ATAG_CORE = 0x54410001.

Other parameter tags include ATAG_MEM32, ATAG_INITRD, ATAG_RAMDISK, and ATAG_COMDLINE. Each parameter tag represents a parameter struct, which forms a parameter linked list. The parameter struct is defined as follows:

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 using line;
Struct tag_acorn acorn;
Struct tag_memclk memclk;
} U;
};

The parameter struct includes two parts: one is the tag_header struct and the other is the u consortium.

The tag_header struct is defined as follows:
Struct tag_header
{
U32 size;
U32 tag;
};

Size: indicates the size of the entire tag struct (expressed by the number of words, rather than the number of bytes), equal to the size of the tag_header plus the size of the u consortium. For example, the size of the parameter struct ATAG_CORE

Size = (sizeof (tag-> tag_header) + sizeof (tag-> u. core)> 2. Generally, the tag_size (struct * tag_xxx) function is used to obtain the size of each parameter struct. Tag indicates the tag of the entire tag structure, such as ATAG_CORE.

The Consortium u includes all available Kernel Parameter types, including tag_core, tag_mem32, and tag_ramdisk. The traversal between parameter struct is implemented through the tag_next (struct * tag) function. The system parameter linked list includes the following struct types: ATAG_CORE, ATAG_MEM, ATAG_RAMDISK, ATAG_INITRD32, atag_1_line, and ATAG_END. In the parameter linked list, apart from the fixed positions of the parameter struct ATAG_CORE and ATAG_END, the order of the parameter struct is arbitrary. The parameter Chain List passed by this BootLoader is as follows: the first Kernel Parameter structure is marked as ATAG_CORE and the parameter type is tag_core. For the definition of each parameter type, see the source code file.

Tag_array is initialized as a pointer to the first struct of the parameter linked list.

Tag_array-> hdr. tag = ATAG_CORE;
Tag_array-> hdr. size = tag_size (tag_core );
Tag_array-> u. core. flags = 1;
Tag_array-> u. core. pagesize = 4096;
Tag_array-> u. core. rootdev = 0x00100000;
Tag_array = tag_next (tag_array );
Tag_array-> hdr. tag = ATAG_MEM;
Tag_array-> hdr. size = tag_size (tag_mem32 );
Tag_array-> u. mem. size = 0x04000000;
Tag_array-> u. Memory. start = 0x20000000;
Tag_array = tag_next (tag_array );
......
Tag_array-> hdr. tag = ATAG_NONE;
Tag_array-> hdr. size = 0;
Tag_array = tag_next (tag_array );

Finally, copy the linked list of kernel parameters to the default physical address 0x20000100 of the kernel. In this way, the parameter linked list is created.

4. kernel receiving Parameters
The following describes how the Linux kernel receives the kernel parameters passed by BootLoader from the zImage Image Based on the ARM architecture. Shows the zImage startup process.

(The image has time to be painted again)

In the file arch/arm/boot/compressed/head. S [2], start is the starting point of zImage. Some code is as follows:
Start:
Mov r7, r1
Mov r8, r2
......
Mov r0, r4
Mov r3, r7
Bl decompress_kernel
B call_kernel
Call_kernel:
......
Mov r0, #0
Mov r1, r7
Mov r2, r8
Mov pc, r4

First, save the values of r1 (machine number) and r2 (physical address of the parameter linked list) passed by BootLoader to r7 and r8, then, pass r7 as a parameter to the decompressed function decompress_kernel (). In the extract function, pass r7 to the global variable _ machine_arch_type. Restore r7 and r8 to r1 and R2.

In the arch/arm/kernel/head. S [2] File, part of the kernel (vmlinux) entry code is as follows:

Stext:
Mrc p15, 0, r9, c0, c0
Bl _ lookup_processor_type
.........
Bl _ lookup_machine_type

First, the ARM Kernel type is obtained from the special registers (CP15) inside the processor, and from the processor kernel Descriptor (proc_info_list) Table (_ proc_info_begin-_ proc_info_end) to check whether the ARM Kernel type is available. If not, the system exits with an error. The processor kernel descriptor is defined in include/asm-arm/procinfo. h [2], the specific function implementation in arch/arm/mm/proc-xxx.S [2], in the compilation of the connection process to combine various processor kernel descriptors into a table. Then, query whether the machine number specified by the r1 register is available from the machine Descriptor (machine_desc) Table (_ mach_info_begin-_ mach_info_end). If no machine number is available, the system exits with an error. The machine number mach_type_xxx is described in the arch/arm/tools/mach-types [2] file. Each machine descriptor contains a unique machine number, the machine descriptor is defined in include/asm-arm/mach/arch. in h [2], the specific implementation is in the arch/arm/mach-xxxx [2] folder. During the compilation and connection process, different machine descriptors based on the same processor are combined into tables. For example, for various machine descriptors based on the AT91RM9200 processor, refer to arch/arm/mach-at91rm9200/board-xxx.c [2] and machine descriptors numbered 262 are as follows:

MACHINE_START (AT91RM9200DK, "Atmel AT91RM9200-DK ")
/* Maintainer: SAN People/Atmel */
. Phys_io = AT91_BASE_SYS,
. Io_pg_offst = (AT91_VA_BASE_SYS> 18) & 0 xfffc,
. Boot_params = AT91_SDRAM_BASE + 0x100,
. Timer = & at91rm9200_timer,
. Map_io = dk_map_io,
. Init_irq = dk_init_irq,
. Init_machine = dk_board_init,
MACHINE_END

The last step is to open MMU and jump to the start_kernel (initialization system) of init/main. c [2. In init/main. c [2], the code of the start_kernel () function is as follows:

{
......
Setup_arch ();
......
}

In arch/arm/kernel/setup. c [2], part of the code of the setup_arch () function is as follows:

{
......
Setup_processor ();
Mdesc = setup_machine (machine_arch_type );
......
Parse_tags (tags );
......
}

The setup_processor () function finds matching descriptors from the processor kernel Descriptor Table and initializes some processor variables. Setup_machine () uses the machine number (assigned in decompress_kernel) as the parameter to return the machine descriptor. Obtain the physical address of the Kernel Parameter from the machine Descriptor and assign it to the tags variable. Then, call the parse_tags () function to analyze the Kernel Parameter linked list and pass each parameter value to the global variable. In this way, the kernel receives the parameters passed by BootLoader.

5. Verification and testing of parameter passing
The result of passing parameters can be verified through the print information of kernel startup.

Machine: Atmel AT91RM9200-DK
......
Kernel command line: console = ttyS0, 115200 root =/dev/ram rw init =/linuxrc
......
Memory: 64 MB = 64 MB total
......
Checking if image is initramfs... it isn' t (no cpio magic); looks like an initrd
Freeing initrd memory: 1024 K
......
RAMDISK: Compressed image found at block 0

A complete BootLoader is a complex project. This article only describes the basic functions of the embedded system BootLoaer. This basic function is indispensable for any BootLoader. The kernel can be started correctly only when these parameters are received. It also lays a good foundation for kernel porting and debugging.
Related Article

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.