uboot傳遞核心引數全解析

2021-06-06 03:39:26 字數 3267 閱讀 2593

一:啟動引數的傳遞過程

啟動引數是包裝在資料結構裡的,在linux kernel啟動的時候,bootloader把這個資料結構拷貝到某個位址,

在改動pc跳向核心介面的同時,通過通用暫存器r2來傳遞這個位址的值,下面這句話就是uboot跳向linux

kernel的**(bootm命令)

thekernel (0, bd->bi_arch_number, bd->bi_boot_params);

thekernel其實不是個函式,而是指向核心入口位址的指標,把它強行轉化為帶三個引數的函式指標,會把三個

引數儲存到通用暫存器中,實現了向kernel傳遞資訊的功能,在這個例子裡,會把r0賦值為0,r1賦值為機器號

r2賦值為啟動引數資料結構的首位址

因此,要向核心傳遞引數很簡單,只要把啟動引數封裝在linux預定好的資料結構裡,拷貝到某個位址(一般

約定俗成是記憶體首位址+100dex)

二:啟動引數的資料結構

啟動引數可儲存在兩種資料結構中,param_struct和tag,前者是2.4核心用的,後者是2.6以後的核心更期望用的

但是,到目前為止,2.6的核心也可以相容前一種結構,兩種資料結構具體定義如下(arm cpu):

struct param_struct s;

char unused[256];

} u1;

union s;

} u2;

char commandline[command_line_size];

};param_struct只需要設定cmmandline,u1.s.page_size,u1.s.nr_pages三個域,具體使用可參見下面的例子

對於tag來說,在實際使用中是乙個struct tag組成的列表,在tag->tag_header中,一項是u32 tag(重名,注意型別)

其值用巨集atag_core,atag_mem,atag_cmdline,atag_none等等來表示,此時下面union就會使用與之相關的資料結構

同時,規定tag列表中第一項必須是atag_core,最後一項必須是atag_none,比如在linux**中,找到啟動引數之後

首先看tag列表中的第一項的tag->hdr.tag是否為atag_core,如果不是,就會認為啟動引數不是tag結構而是param_struct

結構,然後呼叫函式來轉換.在tag->tag_header中,另一項是u32 size,表示tag的大小,tag組成列表的方式就是

指標+size,實際使用中用tag_next (params).tag的具體使用見三中的例子

struct tag u;

};需要注意的是,這兩個資料結構在uboot中和linux中分別有定義,這個定義必須一直才能正常傳遞引數

如果實際使用中不一致的話就不能正常傳遞,可以自行修改

三:通過兩種資料結構傳遞引數的具體例子

1:例子一:通過param_struct讓uboot中的go命令可以傳遞引數

分析:go的**在common/cmd_boot.c中,裡面並沒有拷貝啟動引數的**,轉向核心的時候也沒有傳送

啟動引數所在的位址,因此新增如下**用於拷貝引數,可以看到,對於param_struct只需要設定cmmandline

u1.s.page_size,u1.s.nr_pages三個域

char *commandline = getenv("bootargs");

struct param_struct *lxy_params=(struct param_struct *)0x80000100;

printf("setup linux parameters at 0x80000100\n");

memset(lxy_params,0,sizeof(struct param_struct));

lxy_params->u1.s.page_size=(0x1<<12); //4k 這個是必須有的,否則無法啟動

lxy_params->u1.s.nr_pages=(0x4000000)>>12; //64m 這個是必須有的,否則無法啟動

memcpy(lxy_params->commandline,commandline,strlen(commandline)+1);

printf("linux command line is: \"%s\"\n",lxy_params->commandline);

然後還要向核心傳遞引數位址,將下面一行**修改:

rc = ((ulong (*)(int, char *))addr) (--argc, &argv[1]);  //需要被修改的**

rc = ((ulong(*)(int,int,uint))addr) (0, gd->bd->bi_arch_number,gd->bd->bi_boot_params);//修改之後的**

2:例子二:bootm命令中通過拷貝tag傳遞引數

為方便閱讀,進行了少許修改,但功能不變,該函式引數為存放啟動引數的位址

static void setup_linux_tag(ulong param_base)

params->hdr.size = (sizeof(struct tag_header)+strlen(linux_cmd)+1+4) >> 2;

memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd)+1);

params = tag_next(params);

/* step3: setup end tag */

params->hdr.tag = atag_none;

params->hdr.size = 0;

}四:其他

在uboot中,進行設定tag的函式都在lib_arm/armlinux.c中,在這些函式前面是有ifdef的

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

因此,如果你的bootm命令不能傳遞核心引數,就應該是在你的board的config檔案裡沒有對上述的

巨集進行設定,定義一下即可

u boot和Linux核心之間的引數傳遞

今天學了u boot和linux核心之間的引數傳遞,分享一下,寫得不好勿怪.u boot完成的硬體的相關初始化,是知道linux核心的相關資訊的,但是linux是直接被載入到記憶體中去的,剛開始對u boot是一臉懵逼的,那怎麼辦呢?當然是u boot告訴linux核心一些資訊,這就是所謂的引數傳遞...

u boot向Linux核心傳遞引數tag原理分析

u boot最主要的功能是引導os,目前對linux支援的相對比較好,引導 的意義不僅僅是拷貝核心,執行核心,還要給核心kernel傳遞板子的相關引數,打個比方,u boot相當於是一名專業功底深厚的 接待員 他會先初始化好一些外圍裝置,比如說串列埠,sdram nand flash mmc等,初始...

uboot向核心模組傳遞引數的方法

1 module param name,type,perm 定義乙個模組引數,name 變數名 type 資料型別 bool 布林型 invbool 乙個布林型 true 或者 false 值 相關的變數應當是 int 型別 invbool 型別顛倒了值,所以真值變成 false,反之亦然.char...