U-boot transfers Ram and Linux kernel to read Ram Parameters

Source: Internet
Author: User

U-boot passes many parameters to Linux kernel, such as serial port, ram, and videofb. Linux Kernel also reads and processes these parameters. The two parameters are passed through the struct tag. U-boot stores the objects to be passed to the kernel in the struct tag data structure. When the kernel is started, the physical address of the struct is passed to the kernel. the Linux kernel uses this address, use parse_tags to analyze the passed parameters.
This document describes how to read Ram parameters by using U-boot to pass Ram and Linux kernel.
1. U-boot transfers Ram parameters to the kernel
. In the/common/cmd_bootm.c file, the do_bootm function corresponding to the bootm command is called when the uimage information is found to be Linux OS. /lib_arm/bootm. the do_bootm_linux function in the C file to start Linux kernel.
In the do_bootm_linux function:
Void do_bootm_linux (pai_tbl_t * cmdtp, int flag, int argc, char * argv [],
Ulong ADDR, ulong * len_ptr, int verify)
{
......
# If defined (config_setup_memory_tags) |/
Defined (config_cmdline_tag) |/
Defined (config_initrd_tag) |/
Defined (config_serial_tag) |/
Defined (config_revision_tag) |/
Defined (config_ LCD) |/
Defined (config_vfd)
Setup_start_tag (BD); // starts to initialize the tag struct.
# Ifdef config_serial_tag
Setup_serial_tag (& Params );
# Endif
# Ifdef config_revision_tag
Setup_revision_tag (& Params );
# Endif
# Ifdef config_setup_memory_tags
Setup_memory_tags (BD); // set the ram Parameter
# Endif
# Ifdef config_cmdline_tag
Setup_commandline_tag (BD, CommandLine );
# Endif
# Ifdef config_initrd_tag
If (initrd_start & initrd_end)
Setup_initrd_tag (BD, initrd_start, initrd_end );
# Endif
# If defined (config_vfd) | defined (config_ LCD)
Setup_videolfb_tag (gd_t *) Gd );
# Endif
Setup_end_tag (BD); // The End Of The initialization tag Structure
# Endif
......
......
Thekernel (0, machid, BD-> bi_boot_params );
// The parameter passed to the kernel = (struct tag *) BD-> bi_boot_params
// BD-> bi_boot_params is initialized in the board_init function. For at91rm9200, if it is initialized in the board_init of at91rm9200dk. C: BD-> bi_boot_params = phys_sdram + 0x100;
// This address is also the first address of all taglists. See the setup_start_tag function below.
}

The setup_start_tag and setup_memory_tags functions are described as follows.
The setup_start_tag function is also defined in this file, as follows:
Static void setup_start_tag (bd_t * BD)
{
Params = (struct tag *) BD-> bi_boot_params;
// Initialize (struct tag *) The global variable Params is the address of BD-> bi_boot_params, the following setup_memory_tags related functions of setup tags place the data of other tags on the offset address of this address.

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 );
}

The ram-related parameters are initialized in the setup_memory_tags function in bootm. C:
Static void setup_memory_tags (bd_t * BD)
{
Int I;
For (I = 0; I
Params-> HDR. Tag = atag_mem;
Params-> HDR. size = tag_size (tag_mem32 );
Params-> U. mem. Start = BD-> bi_dram.start;
Params-> U. mem. size = BD-> bi_dram.size;
Params = tag_next (Params );
} // Initialize the memory-related tag
}

2. kernel reads the relevant parameters passed by U-boot.
For Linux kernel, when the ARM platform is started, first execute ARCH/ARM/kernel/head. S, this file will call the function in arch/ARM/kernel/head-common.S, and finally call start_kernel:
......
B start_kernel
......

The start_kernel function in init/Main. C will call the setup_arch function to handle various platform-related actions, including analysis and saving of the parameters passed by U-boot:
Start_kernel ()
{
......
Setup_arch (& command_line );
......
}

The setup_arch function is implemented in the arch/ARM/kernel/setup. c file as follows:
Void _ init setup_arch (char ** cmdline_p)
{
Struct tag * tags = (struct tag *) & init_tags;
Struct machine_desc * mdesc;
Char * From = default_command_line;
Setup_processor ();
Mdesc = setup_machine (machine_arch_type );
Machine_name = mdesc-> name;
If (mdesc-> soft_reboot)
Reboot_setup ("S ");
If (_ atags_pointer)
// Pointer to the starting position of various tags, which is defined as follows:
// Unsigned int _ atags_pointer _ initdata;
// This Pointer Points to the _ initdata segment. The information of various tags is stored in this segment.
Tags = phys_to_virt (_ atags_pointer );
Else if (mdesc-> boot_params)
Tags = phys_to_virt (mdesc-> boot_params );
If (tags-> HDR. Tag! = Atag_core)
Convert_to_tag_list (TAGS );
If (tags-> HDR. Tag! = Atag_core)
Tags = (struct tag *) & init_tags;
If (mdesc-> fixup)
Mdesc-> fixup (mdesc, tags, & from, & meminfo );
If (tags-> HDR. Tag = atag_core ){
If (meminfo. nr_banks! = 0)
Squash_mem_tags (TAGS );
Save_atags (TAGS );
Parse_tags (TAGS );
// Process various tags, including the processing of Ram parameters.
// This function handles the following tags:
_ Tagtable (atag_mem, parse_tag_mem32 );
_ Tagtable (atag_videotext, parse_tag_videotext );
_ Tagtable (atag_ramdisk, parse_tag_ramdisk );
_ Tagtable (atag_serial, parse_tag_serialnr );
_ Tagtable (atag_revision, parse_tag_revision );
_ Tagtable (atag_cmdline, parse_tag_cmdline );
}
Init_mm.start_code = (unsigned long) & _ text;
Init_mm.end_code = (unsigned long) & _ etext;
Init_mm.end_data = (unsigned long) & _ edata;
Init_mm.brk = (unsigned long) & _ end;
Memcpy (boot_command_line, from, command_line_size );
Boot_command_line [COMMAND_LINE_SIZE-1] = '/0 ';
Parse_cmdline (cmdline_p, from); // process the cmdline transmitted by the specified cmdline or U-boot during kernel Compilation
Paging_init (& meminfo, mdesc );
Request_standard_resources (& meminfo, mdesc );
# Ifdef config_smp
Smp_init_cpus ();
# Endif
Cpu_init ();
Init_arch_irq = mdesc-> init_irq;
System_timer = mdesc-> timer;
Init_machine = mdesc-> init_machine;
# Ifdef config_vt
# If defined (config_vga_console)
Conswitchp = & vga_con;
# Elif defined (config_dummy_console)
Conswitchp = & dummy_con;
# Endif
# Endif
Early_trap_init ();
}

For the tag processing ram, the parse_tag_mem32 function is called:
Static int _ init parse_tag_mem32 (const struct tag * tag)
{
......
Arm_add_memory (tag-> U. mem. Start, tag-> U. mem. size );
......
}
_ Tagtable (atag_mem, parse_tag_mem32 );
The preceding arm_add_memory function is defined as follows:
Static void _ init arm_add_memory (unsigned long start, unsigned Long SIZE)
{
Struct membank * bank;
Size-= Start &~ Page_mask;

Bank = & meminfo. Bank [meminfo. nr_banks ++];
Bank-> Start = page_align (start );
Bank-> size = size & page_mask;
Bank-> node = phys_to_nid (start );
}
As shown above, the parse_tag_mem32 function calls the arm_add_memory function to save parameters such as Ram's start and size to the meminfo struct of the meminfo structure. Finally, execute the following statement in setup_arch:
Paging_init (& meminfo, mdesc );
Call paging_init in arch/ARM/MM/nommu. C on a platform with MMU. Otherwise, call the paging_init function in arch/ARM/MM/MMU. C. The paging_init function in MMU. C is not analyzed here.


3. About BD and Gd in U-boot
U-boot has a global structure used to save a lot of useful information-gd_t (short for global data), which includes the BD variable, it can be said that the gd_t struct includes all important global variables in U-boot. Finally, all the parameters passed to the kernel come from GD and BD. For example, the setup_memory_tags function above serves to initialize the corresponding Ram tag with the value in BD.
The structure of the ARM platform is defined as follows:
Include/ASM-arm/global_data.h
Typedef struct global_data {
Bd_t * BD;
Unsigned long flags;
Unsigned long baudrate;
Unsigned long have_console;/* serial_init () was called */
Unsigned long reloc_off;/* relocation offset */
Unsigned long env_addr;/* address of Environment struct */
Unsigned long env_valid;/* checksum of Environment valid? */
Unsigned long fb_base;/* base address of Frame Buffer */
Void ** JT;/* Jump table */
} Gd_t;

Before using the GD structure in U-boot, use the macro declare_global_data_ptr to declare the structure. The macro is defined as follows:
Include/ASM-arm/global_data.h
# Define declare_global_data_ptr register volatile gd_t * gd asm ("R8 ")
The macro definition shows that GD is a pointer to the gd_t struct stored in the R8 register of arm.

(The version of this article for the U-boot-1.3.4, Linux-2.6.28, the platform is arm.

// Add:
From: http://hi.baidu.com/armfans/blog/item/306cd5035f24ff084afb514b.html
Bootloader uses function pointers and parameter passing specifications to pass R0: 0x0, R1: machine number, R2: parameter address to the kernel. since R0 and R1 are relatively simple, no further instructions are required. it takes some time to understand the R2 register.
The R2 register transmits a pointer pointing to a tag area. uboot and Linux kernel use this Extended Tag area to transmit complex parameters, such as command line and file system information, you can also extend this tag to transfer more parameters. the address in the tag area, that is, the R2 value, is in/board/yourboard/youboard. the board_init function in C is initialized, for example, Gd-> BD-> bi_boot_params = 0x30000100 in ub4020. This is an absolute address.
The structure of the tag area is relatively simple and can be considered as the arrangement of tags (array ?), Each tag transmits a specific type of parameter. For definitions of various system tags, see./include/ASM-arm/setup. h.
The following is an example of a tag area:
0x30000100 00000005 54410001 00000000
0x30000110 00000000 0000000f 54410009 746f6f72
0x30000120 65642f3d 61722f76 7220306d 6f632077
0x30000130 6c6f736e 74743d65 2c305379 30303639
0x30000140 696e6920 6c2f3d74 78756e69 ea006372
0x30000150 00000004 54420005 30300040
0x30000160 00000000 00000000
We can see that there are three tags in total:
The length of the first tag is five characters and the type is atag_core (54410001). There are three elements, all of which are zero. The tag must start with this tag.
The second tag is f characters in length and the type is atag_cmdline (54410009). This is a string and is the kernel command line passed to the kernel.
The third tag is 4 characters in length and belongs to the atag_initrd2 (54410005) type. It has two elements: Start: 30300040 (30300000 + 40) and size: 200000 (2 m)
If there is still the fourth tag, it is the end of the two completely Zero, this is the tag end sign.
These tags are in. do_bootm_linux function in/lib_arm/arm_linux.c. the specific tag is determined by the corresponding control macro. for details, refer to the relevant code. in this example, the first tag is the starting tag. If the environment variable contains bootargs, the second tag is created. If bootm has two parameters (boot file system ), the System reads the necessary information in the file system header and creates the third tag.
After the kernel is started, the tags are found based on the value of the R2 register, and corresponding processing functions are called Based on the tag type to obtain the necessary information for Kernel running.

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.