The embedded linux Development uboot transplant ( Four )——uboot The mechanism to start the kernel

One 、 Partition of embedded system

     Embedded systems are deployed in Flash On the device , For different SoC and Flash equipment ,bootloader、kernel、rootfs The partitions are different . samsung S5PV210 The partition scheme of starting equipment is as follows :

    SD/MMC Partition scheme of equipment :

wKiom1dskZOx89k8AAA_UY7gwCc236.png

 NandFlash Partition scheme of equipment :

wKioL1dska2QaJISAAA5S8md_34444.png

When the embedded system starts up ,uboot、kernel、rootfs It can't be stored at will , It must be stored in the corresponding partition , In the startup process uboot、kernel The corresponding content will be loaded in the corresponding partition , Make sure it starts properly , So in embedded system ,uboot and kernel Plan the partition and start the device uoot、kernel、rootfs The actual storage partition of is consistent . In the startup process of embedded system , On startup uboot Running on the SoC Inside SRAM in ,uboot Will be in BL1 The whole stage will be uboot copy to SDRAM in 0xC3E00000 And jump far to SDRAM Medium BL2 function .Uboot start-up kernel when , Will also kernel Copy from boot device to SDRAM The specified kernel Link location , Finally jump to kernel function .

Two 、uboot Supported kernel kernel Format

    Linux krenel After compilation, it will generate a file named vmlinux or vmlinuz Of ELF Format file , When the embedded system is deployed, the burned file format needs to use objcopy Tool to create a burning image format file Image. But because of Image Too big , therefore linux kernel Project pair Image Compressed , And in image A decomposing compression code is attached to the front end of the compressed file , Form a compressed image format zImage. meanwhile ,uboot In order to support linux kernel Start of , stay zImage On the basis of compressed image, we added 64 Byte header information , Use uboot Self contained mkimage The tool generates uboot Its own compressed image format uImage. stay SMDK210 Of uboot In this version, we support zImage and uImage Two compressed image formats .

3、 ... and 、uboot Start kernel process source code analysis

uboot The kernel is actually started with \common\cmd_bootm.c Medium do_bootm Function to implement .

do_bootm Function by using conditional compilation control CONFIG_ZIMAGE_BOOT Macro switch to achieve uboot about zImage Support and unsupport of compressed image .

1、do_bootm Yes zImage Parsing

  By reading the zImage The first part of the head 36 The first four bytes of a byte are related to LINUX_ZIMAGE_MAGIC(0x016f2818) Flag bit contrast , If equal, then the current kernel yes zImage. If at present kernel yes zImage, Then print out ”Boot with zImage”, And for the current uboot Variables that start kernel mirroring images Assign a value , Specify the kernel version and kernel entry address .

#define LINUX_ZIMAGE_MAGIC0x016f2818

if (argc < 2) {

addr = load_addr;// If you don't specify the kernel address , Then use CFG_LOAD_ADDR

} else {

addr = simple_strtoul(argv[1], NULL, 16);// Use the specified kernel address

}

if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {// If at present kernel yes zImage

printf("Boot with zImage\n");// Print information

addr = virt_to_phys(addr);// Convert virtual address to physical address

hdr = (image_header_t *)addr;// Assign the kernel address to the structure type ?

hdr->ih_os = IH_OS_LINUX;// Specify the kernel version

hdr->ih_ep = ntohl(addr);// Specify the kernel entry

memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t));// Assign the kernel information to the current uboot Boot the kernel images Variable

images.legacy_hdr_os = hdr;

images.legacy_hdr_valid = 1;

goto after_header_check;

}

2、do_bootm Yes uImage Support for

Use boot_get_kernel Function verification uImage The header information , Compare the flag bit with the

IH_MAGIC(0x27051956) contrast , If equal, then the current kernel yes uImage, Print information

## Booting kernel from Legacy Image at XXXXXX. What will be obtained uImage Header information for the current uboot Variables that start kernel mirroring images Assign a value , Specify the kernel version and kernel entry address .

case IMAGE_FORMAT_LEGACY:

type = image_get_type (os_hdr);

comp = image_get_comp (os_hdr);

os = image_get_os (os_hdr);

image_end = image_get_image_end (os_hdr);

load_start = image_get_load (os_hdr);

break;

3、do_bootm_linux Boot kernel

do_bootm_linux Function in uboot/lib_arm/bootm.c in , The main function is to get the kernel pass parameters in the environment variables , Get current uboot start-up kernel Of images In variables kernel Entrance address , obtain uboot Machine code in , Prepare to kernel Parameters passed , Finally jump to kernel perform ,uboot completion of enforcement .uboot Printed before execution is complete ”Starting kernel ...” Information . If uboot Actual start kernel Printed out in the process ”Starting kernel ...” Information , It means uboot In the load 、 check kernel That's right. . If uboot Final launch kenel Failure , Most of the reasons are uboot Error passing parameters to kernel .

void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],

     bootm_headers_t *images)

{

ulonginitrd_start, initrd_end;

ulongep = 0;

bd_t*bd = gd->bd;

char*s;

intmachid = bd->bi_arch_number;//uboot Machine code

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

intret;

#ifdef CONFIG_CMDLINE_TAG

char *commandline = getenv ("bootargs");// Get the kernel pass parameter variable in the environment variable

#endif

if (images->legacy_hdr_valid) {

ep = image_get_ep (&images->legacy_hdr_os_copy);// obtain images The kernel entry address in the variable

} else {

puts ("Could not find kernel entry point!\n");

goto error;

}

theKernel = (void (*)(int, int, uint))ep;

s = getenv ("machid");// Machine code in environment variables

if (s) {// If the machine code variable is defined in the environment variable , Use the machine code in the environment variable

machid = simple_strtoul (s, NULL, 16);

printf ("Using machid 0x%x from environment\n", machid);

}

ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM,

&initrd_start, &initrd_end);

if (ret)

goto error;

show_boot_progress (15);

//uboot Prepare for kernel Pass parameters

#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) || \

    defined (CONFIG_MTDPARTITION)

setup_start_tag (bd);

#ifdef CONFIG_SERIAL_TAG

setup_serial_tag (ms);

#endif

#ifdef CONFIG_REVISION_TAG

setup_revision_tag (ms);

#endif

#ifdef CONFIG_SETUP_MEMORY_TAGS

setup_memory_tags (bd);

#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

#ifdef CONFIG_MTDPARTITION

setup_mtdpartition_tag();

#endif

setup_end_tag (bd);

#endif

printf ("\nStarting kernel ...\n\n");// Print information Starting kernel ...

#ifdef CONFIG_USB_DEVICE

{

extern void udc_disconnect (void);

udc_disconnect ();

}

#endif

cleanup_before_linux ();

theKernel (0, machid, bd->bi_boot_params);// Jump to kernel perform

return;

error:

do_reset (cmdtp, flag, argc, argv);

return;

}

Four 、uboot The transmission mechanism of

1、uboot The mechanism of parameter transmission

    uboot Use tag Mode reference ,tag It's a data structure , And linux kernel Medium tag It's the same data structure .tag The structure contains tag_header and tag_xxxx member ,tag_header The structure contains tag Size and type encoding of ,kernel Received tag The parameter is determined according to the type code in the header information tag The type of .

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;

                struct tag_acorn        acorn;

                struct tag_memclk       memclk;  

                struct tag_mtdpart      mtdpart_info;

        } u;

};

struct tag_header {

u32 size;

u32 tag;

};

uboot Pass the source code :

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \

    defined (CONFIG_CMDLINE_TAG) || \

    defined (CONFIG_INITRD_TAG) || CONFIG_MTDPARTITION

setup_start_tag (bd);

#ifdef CONFIG_SETUP_MEMORY_TAGS

setup_memory_tags (bd);

#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

#ifdef CONFIG_MTDPARTITION

setup_mtdpartition_tag();

#endif

setup_end_tag (bd);

#endif

     start tag yes ATAG_CORE type , end tag yes ATAG_NONE type , Other types tag It's valid information , environment variable bootargs Pass to CONFIG_CMDLINE_TAG type tag. environment variable mtdpart The stored boot device partition table information is passed to ATAG_MTDPART type tag.

uboot By calling theKernel (0, machid, bd->bi_boot_params) Function to start the kernel ,theKernel The three parameters of the function are passed through the register , The first 1 Parameters 0 Store in R0 in , The first 2 A parameter machine code is stored in R1 in , The first 3 Parameters bd->bi_boot_params( The ginseng tag The first address ) Store in R2 in .

2、bootargs Parameter interpretation

bootargs yes uboot The most important variable in the ,uboot The setting of environment variables is ultimately through bootargs Pass to kernel Of .

bootargs The parameters are interpreted as follows :

 

A、root

     Used to specify rootfs The location of ,  Common situations are :

    root=/dev/ram rw  

    root=/dev/ram0 rw

  root=/dev/mtdx rw

    root=/dev/mtdblockx rw

     root=/dev/nfs, The file system is based on nfs When using the file system . Appoint root=/dev/nfs after , You need to specify the nfsroot=serverip:nfs_dir.

 

B、rootfstype

     and root In combination with , Generally, if the root file system is ext2, Options are optional , If it is jffs2,squashfs Wait for the file system , Need rootfstype Indicates the type of file system , Otherwise, the root partition cannot be mounted .

 

C、console

console=tty<n>   Use virtual serial port terminal device <n>

    console=ttyS<n>[,options] Using a specific serial port <n>,options It can be in the form of bbbbpnx, here bbbb It refers to the baud rate of the serial port ,p It's a parity bit ,n It means bits.

    console=ttySAC<n>[,options] Same as above .

 

D、mem

    mem=xxM  Specify the size of the memory , You don't have to

 

E、ramdisk_size

ramdisk=xxxxx            Not recommended   

ramdisk_size=xxxxx    recommend

ramdisk  drive , Created ramdisk Of size, By default 4M

 

F、 initrd, noinitrd

     If not used ramdisk Start the system , You need to use noinitrd Parameters . If used ramdisk Start the system , You need to specify initrd=r_addr,size, r_addr Express initrd Location in memory ,size Express initrd Size .

 

G、init

    init Specifies that after the kernel starts , Enter the first script to run in the system , commonly init=/linuxrc,  perhaps init=/etc/preinit,preinit The general content of is to create console,null Device node , function init Program , Mount some file systems and so on .

 

H、mtdparts

mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)

        mtdparts Parameters need to be in the kernel mtd Drive support , That is, when configuring the kernel, you need to select Device Drivers  ---> Memory Technology Device (MTD) support  ---> Command line partition table parsing

mtdparts The format is as follows :

mtdparts=<mtddef>[;<mtddef]

<mtddef>  := <mtd-id>:<partdef>[,<partdef>]

 <partdef> := <size>[@offset][<name>][ro]

 <mtd-id>  := unique id used in mapping driver/device

<size>    := standard linux memsize OR "-" to denote all remaining space

<name>    := (NAME)

mtdparts The format used :

mtdparts=mtd-id:<size1>@<offset1>(<name1>),<size2>@<offset2>(<name2>)

        mtd-id  It has to be the same as the current platform flash Of mtd-id Agreement , Otherwise the whole mtdparts It will fail

        size It can be set for the actual size(xxM,xxk,xx), It can also be used. '-' Represents all the remaining space .

     hypothesis flash  Of mtd-id yes sc1200, Then you can use the following method to set up :

        mtdparts=sc1200:-     →   There's only one division

        mtdparts=sc1200:256k(ARMboot)ro,-(root)  →   There are two sections

 

I、ip

     Specify the network card after system startup ip Address , If you use a method based on nfs File system , Must specify ip Parameters . Set up ip There are two ways :

 ip = ip addr

 ip=ip addr:server ip addr:gateway:netmask::which netcard:off

which netcard  It refers to the network card on the development board , Instead of the network card on the host .

 

     Several common bootargs The usage settings of are as follows :

     Suppose the file system is ramdisk, And it's directly in memory ,bootargs The settings are as follows :

setenv bootargs ‘initrd=0x32000000,0xa00000 root=/dev/ram0 console=ttySAC0 mem=64M init=/linuxrc’

     Suppose the file system is ramdisk, And in flash in ,bootargs The settings are as follows :

setenv bootargs ‘mem=32M console=ttyS0,115200 root=/dev/ram rw init=/linuxrc’

     Need to be in bootm The order specifies ramdisk stay flash Address in , Such as bootm kernel_addr ramdisk_addr (fdt_addr)

     Suppose the file system is jffs2 Type of , And in flash in ,bootargs The settings should be as follows

setenv bootargs ‘mem=32M console=ttyS0,115200 noinitrd root=/dev/mtdblock2 rw rootfstype=jffs2 init=/linuxrc’

     Suppose the file system is based on nfs Of ,bootargs The settings should be as follows

setenv bootargs ‘noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5:192.168.0.3:192.168.0.3:255.255.255.0::eth0:off’

perhaps

setenv bootargs ‘noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5’

bootargs The setting of parameters is extremely flexible , It needs to be set flexibly according to the platform .