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