U-boot會(huì)給Linux Kernel傳遞很多參數(shù),如:串口,RAM,videofb等。而Linux kernel也會(huì)讀取和處理這些參數(shù)。兩者之間通過struct tag來傳遞參數(shù)。U-boot把要傳遞給kernel的東西保存在struct tag數(shù)據(jù)結(jié)構(gòu)中,啟動(dòng)kernel時(shí),把這個(gè)結(jié)構(gòu)體的物理地址傳給kernel;Linux kernel通過這個(gè)地址,用parse_tags分析出傳遞過來的參數(shù)。
這里主要以U-boot傳遞RAM和Linux kernel讀取RAM參數(shù)為例進(jìn)行說明。
1、u-boot給kernel傳RAM參數(shù)
./common/cmd_bootm.c文件中(指Uboot的根目錄),bootm命令對(duì)應(yīng)的do_bootm函數(shù),當(dāng)分析uImage中信息發(fā)現(xiàn)OS是Linux時(shí),調(diào)用./lib_arm/bootm.c文件中的do_bootm_linux函數(shù)來啟動(dòng)Linux kernel。
在do_bootm_linux函數(shù)中:
void do_bootm_linux (cmd_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); //初始化tag結(jié)構(gòu)體開始
#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); //設(shè)置RAM參數(shù)
#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); //初始化tag結(jié)構(gòu)體結(jié)束
#endif
......
......
theKernel (0, machid, bd->bi_boot_params);
//傳給Kernel的參數(shù)= (struct tag *)型的bd->bi_boot_params
//bd->bi_boot_params在board_init函數(shù)中初始化,如對(duì)于at91rm9200,初始化在at91rm9200dk.c的board_init中進(jìn)行:bd->bi_boot_params=PHYS_SDRAM + 0x100;
//這個(gè)地址也是所有taglist的首地址,見下面的setup_start_tag函數(shù)
}
對(duì)于setup_start_tag和setup_memory_tags函數(shù)說明如下。
函數(shù)setup_start_tag也在此文件中定義,如下:
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;
//初始化(struct tag *)型的全局變量params為bd->bi_boot_params的地址,之后的setup tags相關(guān)函數(shù)如下面的setup_memory_tags就把其它tag的數(shù)據(jù)放在此地址的偏移地址上。
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);
}
RAM相關(guān)參數(shù)在bootm.c中的函數(shù)setup_memory_tags中初始化:
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);
} //初始化內(nèi)存相關(guān)tag
}
2、Kernel讀取U-boot傳遞的相關(guān)參數(shù)
對(duì)于Linux Kernel,ARM平臺(tái)啟動(dòng)時(shí),先執(zhí)行arch/arm/kernel/head.S,此文件會(huì)調(diào)用arch/arm/kernel/head-common.S和arch/arm/mm/proc-arm920.S中的函數(shù),并最后調(diào)用start_kernel:
......
b start_kernel
......
init/main.c中的start_kernel函數(shù)中會(huì)調(diào)用setup_arch函數(shù)來處理各種平臺(tái)相關(guān)的動(dòng)作,包括了u-boot傳遞過來參數(shù)的分析和保存:
start_kernel()
{
......
setup_arch(&command_line);
......
}
其中,setup_arch函數(shù)在arch/arm/kernel/setup.c文件中實(shí)現(xiàn),如下:
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)
//指向各種tag起始位置的指針,定義如下:
//unsigned int __atags_pointer __initdata;
//此指針指向__initdata段,各種tag的信息保存在這個(gè)段中。
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);
//處理各種tags,其中包括了RAM參數(shù)的處理。
//這個(gè)函數(shù)處理如下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);//處理編譯內(nèi)核時(shí)指定的cmdline或u-boot傳遞的cmdline
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();
}
對(duì)于處理RAM的tag,調(diào)用了parse_tag_mem32函數(shù):
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);
上述的arm_add_memory函數(shù)定義如下:
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);
}
如上可見,parse_tag_mem32函數(shù)調(diào)用arm_add_memory函數(shù)把RAM的start和size等參數(shù)保存到了meminfo結(jié)構(gòu)的meminfo結(jié)構(gòu)體中。最后,在setup_arch中執(zhí)行下面語句:
paging_init(&meminfo, mdesc);
對(duì)沒有MMU的平臺(tái)上調(diào)用arch/arm/mm/nommu.c中的paging_init,否則調(diào)用arch/arm/mm/mmu.c中的paging_init函數(shù)。這里暫不分析mmu.c中的paging_init函數(shù)。
3、關(guān)于U-boot中的bd和gd
U-boot中有一個(gè)用來保存很多有用信息的全局結(jié)構(gòu)體--gd_t(global data縮寫),其中包括了bd變量,可以說gd_t結(jié)構(gòu)體包括了u-boot中所有重要全局變量。最后傳遞給內(nèi)核的參數(shù),都是從gd和bd中來的,如上述的setup_memory_tags函數(shù)的作用就是用bd中的值來初始化RAM相應(yīng)的tag。
對(duì)于ARM平臺(tái)這個(gè)結(jié)構(gòu)體的定義大致如下:
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;
在U-boot中使用gd結(jié)構(gòu)之前要用先用宏DECLARE_GLOBAL_DATA_PTR來聲明。這個(gè)宏的定義如下:
include/asm-arm/global_data.h
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
從這個(gè)宏的定義可以看出,gd是一個(gè)保存在ARM的r8寄存器中的gd_t結(jié)構(gòu)體的指針。
本文的版本為U-boot-1.3.4、Linux-2.6.28,平臺(tái)是ARM。
-
RAM
+關(guān)注
關(guān)注
8文章
1369瀏覽量
115066 -
Linux
+關(guān)注
關(guān)注
87文章
11351瀏覽量
210505 -
u-boot
+關(guān)注
關(guān)注
0文章
121瀏覽量
38329 -
Kernel
+關(guān)注
關(guān)注
0文章
48瀏覽量
11245
原文標(biāo)題:Uboot與Linux之間的參數(shù)傳遞詳解
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
U-Boot介紹
U-boot的基本介紹
![<b class='flag-5'>U-boot</b>的基本介紹](https://file1.elecfans.com/web2/M00/8C/C4/wKgaomSxDC-AIi1QAACKegMzhAU876.png)
u-boot和linux kernel在RK3399上是如何部署的
u-boot的Makefile分析
u-boot簡介
詳解U-Boot引導(dǎo)內(nèi)核分析
![詳解<b class='flag-5'>U-Boot</b>引導(dǎo)內(nèi)核分析](https://file.elecfans.com/web1/M00/4F/0E/pIYBAFrQW7yAFJIBAAAUPCpHWVE886.png)
你了解u-boot與linux內(nèi)核間的參數(shù)傳遞過程?
![你了解<b class='flag-5'>u-boot</b>與<b class='flag-5'>linux</b>內(nèi)核間的<b class='flag-5'>參數(shù)</b><b class='flag-5'>傳遞</b>過程?](https://file.elecfans.com/web1/M00/91/F5/pIYBAFzYzxmAUDe8AAKA9U6nVcE814.png)
Linux下獲取虛擬地址對(duì)應(yīng)的物理地址的方式
設(shè)備樹的傳遞及kernel 對(duì)設(shè)備樹的解析
![設(shè)備樹的<b class='flag-5'>傳遞</b>及<b class='flag-5'>kernel</b> 對(duì)設(shè)備樹的<b class='flag-5'>解析</b>](https://file.elecfans.com/web2/M00/0D/1B/pYYBAGECHw6ANXVFAAAoHiuiNb0929.png)
深度解析U-Boot網(wǎng)絡(luò)實(shí)現(xiàn)
![深度<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b>網(wǎng)絡(luò)實(shí)現(xiàn)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
U-Boot架構(gòu)淺析
![<b class='flag-5'>U-Boot</b>架構(gòu)淺析](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Linux U-Boot開發(fā)指南
![<b class='flag-5'>Linux</b> <b class='flag-5'>U-Boot</b>開發(fā)指南](https://file.elecfans.com//web2/M00/95/B6/poYBAGQFT7mAWRkKAAFz-Z4R0zY051.png)
評(píng)論