Bootloader 与 内核的交互

Posted y4247464

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bootloader 与 内核的交互相关的知识,希望对你有一定的参考价值。

以下内容源自于:韦东山老师的《嵌入式Linux应用开发 》

目的:了解Bootloader与内核交互的原理

  由于Bootloader和内核交互是单向的,只能是B将参数传给内核,且不能同时运行,那传递参数方法就只有:Bootloader将参数放在某个约定的地方,再启动内核,内核启动后去这个地方获得参数。

  自然,二者还要规定标记参数的结构 --- tagged list --- 标记列表。通过标记列表来传递启动参数。标记的数据结构为 tag ,由一个tag_head结构和一个联合union组成。tag_head表示标记的类型和长度,比如是表示内存还是命令行参数等。对于不同类型的标记使用不同的union,如表示内存就用tag_mem32,表示命令行时使用tag_cmdline。

  在include/asm/setup.h

struct tag_header {
        __u32 size;
        __u32 tag;
};

  其中 size:表示整个tag 结构体的大小(用字的个数来表示,而不是字节的个数),等于tag_header 的大小加上u 联合体的大小,例如,参数结构体ATAG_CORE 的
size=(sizeof(tag->tag_header)+sizeof(tag->u.core))>>2,一般通过函数 tag_size(struct * tag_xxx)来获得每个参数结构体的size。其中tag:表示整个tag 结构体的标记,如:ATAG_CORE等。

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

  联合体u 包括了所有可选择的内核参数类型

下面通过设置内存标记、内存标记、命令行标记为例说明参数的传递。(详见韦书)

  (1)设置标记ATAG_CORE

  标记列表以ATAG_CORE开始,以ATAG_NONE 结束。这里的ATAG_CORE,ATAG_NONE 是各个参数的标记,本身是一个32 位值,例如:ATAG_CORE=0x54410001。

  假设Bootloader与内核约定的参数传递地址为0x30000100,则可以以如下代码设置标记ATAG_CORE:

params = (struct tag *) 0x30000100;

params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
params->u.core.flags = 0;
parama->u.core.pagesize = 0;
params->u.core.rootdev =  0;

params = tag_next (params);

  其中,tag_next指向当前标记末尾;

#define tag_next(t) ((struct tag*)((u32*)(t)+(t)->hdr.size))

  (2)设置内存标记

//假设开发板使用的内存起始地址0x30000000,大小为0x4000000
params
->hdr.tag = ATAG_MEM; params->hdr.size = tag_size (tag_mem32); params->u.mem.start = 0x30000000; parama->u.mem.size = 0x4000000; params = tag_next (params);

  (3)设置命令行标记

命令行即字符串,可控制内核行为,比如:

" root=/dev/mtdblock 2     init=/linuxrc     console = tty SAC0 "

 表示根文件系统在MTD2分区上,系统启动后执行第一个程序为linuxrc,控制台为ttySAC0即第一个串口。

  命令行可以在BootLoader中通过命令标记设置好,然后按照以下构造传给内核:

char *p = " root=/dev/mtdblock 2     init=/linuxrc     console = tty SAC0 "

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

 

以上是关于Bootloader 与 内核的交互的主要内容,如果未能解决你的问题,请参考以下文章

Linux系统启动与内核管理(下)

bootloader 与 uboot的区别

最简单的bootloader的编写

uboot和BootLoader的区别和联系

LINUX PID 1和SYSTEMD PID 0 是内核的一部分,主要用于内进换页,内核初始化的最后一步就是启动 init 进程。这个进程是系统的第一个进程,PID 为 1,又叫超级进程(代码片段

简单BootLoader