Interaction between U-boot and Linux Kernel

Source: Internet
Author: User
Tags crc32
Interaction between U-boot and Linux Kernel

Note: The U-boot version used in this article is 1.1.6 and the platform is S3C2440.

Directory 1. Introduction
1.1 tag list
2. Set the address marked for storage
2.1 struct Definitions
2.2 mark storage Address Settings
3. Tag settings
3.1 set flag atag_core
3.2 set the memory tag atag_mem
3.3 set the command line flag atag_cmdline
3.4 set atag_none 1. Introduction

The interaction between U-boot and Linux kernel is unidirectional. U-boot passes various parameters to the kernel. Since they cannot run at the same time, the transfer method can only be one by one: U-boot puts the parameters in a specified place, and obtains the parameters from this place after starting the kernel and kernel.

1.1 tag list

In addition to specifying the location where parameters are stored, you must specify the parameter structure. All kernels after linux2.4.x PASS Parameters in the form of tagged list. A tag is a data structure. A tag list is the multiple tags that are stored next to each other. The tag list starts with atag_core and ends with atage_none.

The data structure of the tag is tag, which is composed of a tag_header structure and a union. The tag_header struct indicates the type and length of the tag, such as memory or command line parameters. Use different Consortium for different types of tags, such as tag_men32 for memory = and tag_cmdline for command line. It is defined in the include/ASM-arm/setup. c file.

/* * The new way of passing information: a list of tagged entries *//* The list ends with an ATAG_NONE node. */#define ATAG_NONE0x00000000struct tag_header {u32 size;u32 tag;};/* The list must start with an ATAG_CORE node */#define ATAG_CORE0x54410001struct tag_core {u32 flags;/* bit 0 = read-only */u32 pagesize;u32 rootdev;};/* it is allowed to have multiple ATAG_MEM nodes */#define ATAG_MEM0x54410002struct tag_mem32 {u32size;u32start;/* physical start address */};/* VGA text type displays */#define ATAG_VIDEOTEXT0x54410003struct tag_videotext {u8x;u8y;u16video_page;u8video_mode;u8video_cols;u16video_ega_bx;u8video_lines;u8video_isvga;u16video_points;};/* describes how the ramdisk will be used in kernel */#define ATAG_RAMDISK0x54410004struct tag_ramdisk {u32 flags;/* bit 0 = load, bit 1 = prompt */u32 size;/* decompressed ramdisk size in _kilo_ bytes */u32 start;/* starting block of floppy-based RAM disk image */};/* describes where the compressed ramdisk image lives (virtual address) *//* * this one accidentally used virtual addresses - as such, * its depreciated. */#define ATAG_INITRD0x54410005/* describes where the compressed ramdisk image lives (physical address) */#define ATAG_INITRD20x54420005struct tag_initrd {u32 start;/* physical start address */u32 size;/* size of compressed ramdisk image in bytes */};/* board serial number. "64 bits should be enough for everybody" */#define ATAG_SERIAL0x54410006struct tag_serialnr {u32 low;u32 high;};/* board revision */#define ATAG_REVISION0x54410007struct tag_revision {u32 rev;};/* initial values for vesafb-type framebuffers. see struct screen_info * in include/linux/tty.h */#define ATAG_VIDEOLFB0x54410008struct tag_videolfb {u16lfb_width;u16lfb_height;u16lfb_depth;u16lfb_linelength;u32lfb_base;u32lfb_size;u8red_size;u8red_pos;u8green_size;u8green_pos;u8blue_size;u8blue_pos;u8rsvd_size;u8rsvd_pos;};/* command line: \0 terminated string */#define ATAG_CMDLINE0x54410009struct tag_cmdline {charcmdline[1];/* this is the minimum size */};/* acorn RiscPC specific information */#define ATAG_ACORN0x41000101struct tag_acorn {u32 memc_control_reg;u32 vram_pages;u8 sounddefault;u8 adfsdrives;};/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */#define ATAG_MEMCLK0x41000402struct tag_memclk {u32 fmemclk;};struct tag {struct tag_header hdr;union {struct tag_corecore;struct tag_mem32mem;struct tag_videotextvideotext;struct tag_ramdiskramdisk;struct tag_initrdinitrd;struct tag_serialnrserialnr;struct tag_revisionrevision;struct tag_videolfbvideolfb;struct tag_cmdlinecmdline;/* * Acorn specific */struct tag_acornacorn;/* * DC21285 specific */struct tag_memclkmemclk;} u;};#define tag_next(t)((struct tag *)((u32 *)(t) + (t)->hdr.size))#define tag_size(type)((sizeof(struct tag_header) + sizeof(struct type)) >> 2) //???
2. Set struct definitions related to the marked address 2.1

The address marked for storage is saved in struct BD. The BD struct is a GD struct. Let's first look at the GD struct, which is defined in the include/ASM-arm/global_data.h file:

Typedefstructglobal_data {bd_t * BD; // parameters related to the Development Board, struct variables, refer to the u-boot.h unsigned longflags; // Indication signs, such as unsigned longbaudrate device has been initialized; // The communication rate of the serial port unsigned longhave_console;/* serial_init () was called if this function is executed, it is set to 1 */unsigned longreloc_off;/** relocation offset, it is the difference between the actual orientation location and the location specified during the compilation connection, generally 0 */unsigned longenv_addr;/* Environment Parameter address */unsigned longenv_valid; /* effective mark of CRC test for environment parameters */unsigned longfb_base;/* base address of the frame buffer */# ifdef config_vfdunsigned charvfd_type;/* display type */# endif # If 0 unsigned longcpu_clk; /* CPU clock */unsigned longbus_clk; // bus clock unsigned longram_size;/* Ram size */unsigned longreset_status;/* reset Status Register at boot */# endifvoid ** JT; /* Jump table to the jump table to register the "function call address" */} gd_t;

Next let's take a look at the BD struct, this struct is defined in the include/ASM-arm/u-boot.h file:

Typedef struct bd_info {serial;/* serial port baud rate */unsigned longbi_ip_addr;/* IP Address */unsigned charbi_enetaddr [6];/* MAC address */struct environment_s * bi_env; ulong bi_arch_number;/* board ID */ulong bi_boot_params;/* startup parameter */struct/* ram configuration */{ulong start; ulong size;} bi_dram [config_nr_dram_banks]; # ifdef config_has_eth1/* Second onboard Ethernet port */unsigned char bi_enet1addr [6]; # endif} bd_t;
2.2 mark storage Address Settings

In the board_init function of board/smdk2410/smdk2410.c, set the bi_boot_params parameter:

Int board_init (void) {s3c24x0_clock_power * const clk_power = s3c24x0_getbase_clock_power (); // obtain the address of the first register of the clock and power configuration register, the above ground of the Register is consecutive s3c24x0_gpio * const gpio = s3c24x0_getbase_gpio (); // obtain the address of the first register of the gpio configuration register/* to reduce PLL lock time, adjust the locktime register */clk_power-> locktime = 0 xffffff;/* configure mpll */clk_power-> mpllcon = (m_mdiv <12) + (m_pdiv <4) + m_sdiv);/* some delay between mpll and upll */delay (4000);/* configure upll */clk_power-> upllcon = (u_m_mdiv <12) + (u_m_pdiv <4) + u_m_sdiv);/* some delay between mpll and upll */delay( 8000 ); /* set up the I/O Ports */gpio-> gpacon = 0x007fffff; gpio-> gpbcon = 0x00044555; gpio-> gpbup = 0x000007ff; gpio-> gpccon = 0 xaaaaaaaa; gpio-> gpcup = 0x0000ffff; gpio-> gpdcon = 0 xaaaaaaaa; gpio-> gpdup = 0x0000ffff; gpio-> gpecon = 0 Protocol; gpio-> gpeup = 0x0000ffff; gpio-> gpfcon = 0x000055aa; gpio-> gpfup = 0x000000ff; gpio-> gpgcon = 0xff95ffba; gpio-> gpgup = 0x0000ffff; gpio-> gphcon = 0x002afaaa; gpio-> gphup = 0x000007ff;/* arch Number of SMDK2410-Board */Gd-> BD-> bi_arch_number = mach_type_smdk2410; /* adress of boot parameters */Gd-> BD-> bi_boot_params = 0x30000100; icache_enable (); // call the CPU/ARM920T/CPU. function dcache_enable (); Return 0;} in C ;}
3. Tag settings

U-boot uses the bootm command to guide the Linux kernel. The bootm command calls the do_bootm_linux function to guide the kernel. The tag is set in the do_bootm_linux function. The function is defined in lib_arm/armlinux. C:

Void do_bootm_linux (pai_tbl_t * effectp, int flag, int argc, char * argv [], ulong ADDR, ulong * len_ptr, int verify) {ulong Len = 0, checksum; ulong initrd_start, initrd_end; ulong data; void (* Thekernel) (INT zero, Int Arch, uint Params); image_header_t * HDR = & header; bd_t * BD = Gd-> BD; # ifdef config_cmdline_tagchar * CommandLine = getenv ("bootargs"); # endifthekernel = (void (*) (INT, Int, uint) ntohl (HDR-> IH _ EP); set the kernal loading address/** check if there is an initrd image */after the User-Defined initrd needs to be loaded in, the whole process needs to carry out the header and the entire data internal school, it is similar to the kernel load validation, Which is omitted here. Initial RAM disk Linux's initial RAM disk (initrd) is a temporary root file system mounted during system boot. It is used to support the two-phase boot process. The initrd file contains various executable programs and drivers that can be used to mount the actual root file system, unmount the initrd RAM disk, and release the memory. In many embedded Linux systems, initrd is the final root file system. If (argc> = 3) {show_boot_progress (9); ADDR = simple_strtoul (argv [2], null, 16 ); printf ("# loading ramdisk image at % 08lx... \ n ", ADDR);/* Copy header so we can blank CRC Field for re-calculation */# ifdef config_has_dataflasvf (addr_dataflash (ADDR) {read_dataflash (ADDR, sizeof (image_header_t), (char *) & header);} else # endifmemcpy (& header, (char *) ADDR, sizeof (image_header_t); If (ntohl (HDR -> Ih_magic )! = Ih_magic) {printf ("Bad magic number \ n"); show_boot_progress (-10); do_reset (repeated TP, flag, argc, argv);} DATA = (ulong) & header; Len = sizeof (image_header_t); checksum = ntohl (HDR-> ih_hcrc); HDR-> ih_hcrc = 0; If (CRC32 (0, (unsigned char *) data, len )! = Checksum) {printf ("Bad header checksum \ n"); show_boot_progress (-11); do_reset (repeated TP, flag, argc, argv);} show_boot_progress (10 ); print_image_hdr (HDR); Data = ADDR + sizeof (image_header_t); Len = ntohl (HDR-> ih_size); # ifdef convert (addr_dataflash (ADDR) {read_dataflash (data, Len, (char *) __load_addr); Data = pai_load_addr;} # endifif (verify) {ulong csum = 0; printf ("verifying C Hecksum... "); csum = CRC32 (0, (unsigned char *) data, Len); If (csum! = Ntohl (HDR-> ih_dcrc) {printf ("Bad Data CRC \ n"); show_boot_progress (-12); do_reset (repeated TP, flag, argc, argv );} printf ("OK \ n");} show_boot_progress (11); If (HDR-> ih_ OS! = Ih_ OS _linux) | (HDR-> ih_arch! = Ih_cpu_arm) | (HDR-> ih_type! = Ih_type_ramdisk) {printf ("No Linux arm ramdisk image \ n"); show_boot_progress (-13); do_reset (repeated TP, flag, argc, argv );} # If defined (config_b2) | defined (config_evb4510) | defined (config_armadillo) /** we need to copy the ramdisk to SRAM to let Linux boot */memmove (void *) ntohl (HDR-> ih_load), (uchar *) data, Len ); data = ntohl (HDR-> ih_load); # endif/* config_b2 | config_evb4510 * // ** now check If we have a Multifile image */} else if (HDR-> ih_type = ih_type_multi) & (len_ptr [1]) {ulong tail = ntohl (len_ptr [0]) % 4; int I; show_boot_progress (13);/* Skip kernel length and terminator */Data = (ulong) (& len_ptr [2]);/* skip any additional image length fields */for (I = 1; len_ptr [I]; ++ I) data ++ = 4; /* Add kernel length, and align */Data + = ntohl (len_ptr [0]); If (tail) {Data + = 4-tail;} l En = ntohl (len_ptr [1]);} else {/** no initrd image */show_boot_progress (14); Len = Data = 0 ;}# ifdefdebugif (! Data) {printf ("No initrd \ n") ;}# endifif (data) {initrd_start = data; initrd_end = initrd_start + Len;} else {initrd_start = 0; initrd_end = 0;} show_boot_progress (15); debug ("# transferring control to Linux (at address % 08lx )... \ n ", (ulong) Thekernel); # 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); set various tags, it is used to pass parameters to Linux # ifdef Merge (milliseconds ms); # endif # ifdef Merge (milliseconds); # endif # ifdef Merge (BD); # endif # ifdef config_cmdline_tagsetup_commandline_tag (BD, commandLine); # endif # ifdef evaluate (initrd_start & initrd_end) values (BD, initrd_start, initrd_end); # endif # If defined (config_vfd) | defined (config_ LCD) setup_videolfb_tag (gd_t *) Gd); # endifsetup_end_tag (BD); # endif/* we assume that the kernel is in place */printf ("\ nstarting kernel... \ n "); print information # ifdef config_usb_device {extern void udc_disconnect (void); udc_disconnect () ;}# endifcleanup_before_linux (); before startup, clean up the CPU/ARM920T/CPU first. the following parameters must be passed when C calls the kernel: R0: Must be 0r1: Machine Type ID, and the local machine is arm (BD-> bi_arch_number) R2: position of the startup parameter list in the memory (BD-> bi_boot_params) Thekernel (0, BD-> bi_arch_number, BD-> bi_boot_params );}
3.1 set flag atag_core

Mark the list to mark atag_core

Static void setup_start_tag (bd_t * BD) {Params = (struct tag *) BD-> bi_boot_params; 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); // point to the end of the current tag}
3.2 set the memory tag atag_mem

In the dram_init function of board/smdk2410/smdk2410.c, set the bi_dram structure of BD:

int dram_init (void){gd->bd->bi_dram[0].start = PHYS_SDRAM_1;gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;return 0;}

Here is the structure of the memory mark:

static void setup_memory_tags (bd_t *bd){int i;for (i = 0; i < CONFIG_NR_DRAM_BANKS; 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);}}
3.3 set the command line flag atag_cmdline

A command line is a string used to control some kernel behaviors. For example, "root =/dev/mtdblock2 init =/linuxrc console = ttysac0" indicates that the first program executed after the root file system is started on the mtd2 partition is/linuxrc, And the console is ttysac0.

static void setup_commandline_tag (bd_t *bd, char *commandline){char *p;if (!commandline)return;/* eat leading white space */for (p = commandline; *p == ' '; p++);/* skip non-existent command lines so the kernel will still * use its default command line. */if (*p == '\0')return;params->hdr.tag = ATAG_CMDLINE;params->hdr.size =(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;strcpy (params->u.cmdline.cmdline, p);params = tag_next (params);}
3.4 set atag_none

Mark the list to mark atag_none introduction.

static void setup_end_tag (bd_t *bd){params->hdr.tag = ATAG_NONE;params->hdr.size = 0;}

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.