原文地址::http://blogt.chinaunix.net/link.php?url=http://blog.csdn.net%2Flanmanck%2Farchive%2F2009%2F05%2F15%2F4187389.aspx
Bootloader與核心的互動
Bootloader與核心的互動是單向的,Bootloader將各類參數傳給核心。由於它們不能同時運行,傳遞辦法只有一個:Bootloader將參數放在某個約定的地方之後,再啟動核心,核心啟動後從這個地方獲得參數。
除了約定好參數存放的地址外,還要規定參數的結構。Linux 2.4.x 以後的核心都期望以標記列表(tagged list)的形式來傳遞啟動參數。標記,就是一種資料結構;標記列表,就是挨著存放的多個標記。標記列表以標記ATAG_CORE 開始,以標記ATAG_NONE 結束。標記的資料結構為tag,它由一個tag_header結構和一個聯合(union)組成。tag_header結構表示標記的類型及長度,比如是表示記憶體還是表示命令列參數等。對於不同類型的標記使用不同的聯合(union),比如表示記憶體時使用tag_mem32,表示命令列時使用
tag_cmdline。資料結構tag和tag_header定義在Linux核心源碼的include/asm/setup.h標頭檔中:
struct tag_header {
u32 size;
u32 tag;
};
<br>struct tag {
struct tag_header hdr;
union {
struct tag_corecore;
struct tag_mem32mem;
struct tag_videotextvideotext;
struct tag_ramdiskramdisk;
struct tag_initrdinitrd;
struct tag_serialnrserialnr;
struct tag_revisionrevision;
struct tag_videolfbvideolfb;
struct tag_cmdlinecmdline;
<br>/*
* Acorn specific
*/
struct tag_acornacorn;
<br>/*
* DC21285 specific
*/
struct tag_memclkmemclk;
} u;
};
下面以設定記憶體標記、命令列標記為例說明參數的傳遞:
(1)設定標記 ATAG_CORE。
標記列表以標記 ATAG_CORE開始,假設Bootloader與核心約定的參數存放地址為0x30000100,則可以以如下代碼設定標記 ATAG_CORE:
params = (struct tag *) 0x30000100;
<br>params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
<br>params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
<br>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;
params->u.mem.size = 0x4000000;
params = tag_next (params);
(3)設定命令列標記。
命令列就是一個字串,它被用來控制核心的一些行為。比如"root=/dev/mtdblock2 init="/linuxrc" console="ttySAC0""表示根檔案系統在MTD2分區上,系統啟動後執行的第一個程式為/linuxrc,控制台為ttySAC0(即第一個串口)。
命令列可以在Bootloader中通過命令設定好,然後如下構造標記傳給核心:
char *p = "root=/dev/mtdblock2 init="/linuxrc" console="ttySAC0"";
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);
(4)設定標記ATAG_NONE。
標記列表以標記ATAG_NONE結束,如下設定:
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
Bootloader與核心的互動
Bootloader與核心的互動是單向的,Bootloader將各類參數傳給核心。由於它們不能同時運行,傳遞辦法只有一個:Bootloader將參數放在某個約定的地方之後,再啟動核心,核心啟動後從這個地方獲得參數。
除了約定好參數存放的地址外,還要規定參數的結構。Linux 2.4.x 以後的核心都期望以標記列表(tagged list)的形式來傳遞啟動參數。標記,就是一種資料結構;標記列表,就是挨著存放的多個標記。標記列表以標記ATAG_CORE 開始,以標記ATAG_NONE 結束。標記的資料結構為tag,它由一個tag_header結構和一個聯合(union)組成。tag_header結構表示標記的類型及長度,比如是表示記憶體還是表示命令列參數等。對於不同類型的標記使用不同的聯合(union),比如表示記憶體時使用tag_mem32,表示命令列時使用
tag_cmdline。資料結構tag和tag_header定義在Linux核心源碼的include/asm/setup.h標頭檔中:
struct tag_header {
u32 size;
u32 tag;
};
<br>struct tag {
struct tag_header hdr;
union {
struct tag_corecore;
struct tag_mem32mem;
struct tag_videotextvideotext;
struct tag_ramdiskramdisk;
struct tag_initrdinitrd;
struct tag_serialnrserialnr;
struct tag_revisionrevision;
struct tag_videolfbvideolfb;
struct tag_cmdlinecmdline;
<br>/*
* Acorn specific
*/
struct tag_acornacorn;
<br>/*
* DC21285 specific
*/
struct tag_memclkmemclk;
} u;
};
下面以設定記憶體標記、命令列標記為例說明參數的傳遞:
(1)設定標記 ATAG_CORE。
標記列表以標記 ATAG_CORE開始,假設Bootloader與核心約定的參數存放地址為0x30000100,則可以以如下代碼設定標記 ATAG_CORE:
params = (struct tag *) 0x30000100;
<br>params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
<br>params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
<br>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;
params->u.mem.size = 0x4000000;
params = tag_next (params);
(3)設定命令列標記。
命令列就是一個字串,它被用來控制核心的一些行為。比如"root=/dev/mtdblock2 init="/linuxrc" console="ttySAC0""表示根檔案系統在MTD2分區上,系統啟動後執行的第一個程式為/linuxrc,控制台為ttySAC0(即第一個串口)。
命令列可以在Bootloader中通過命令設定好,然後如下構造標記傳給核心:
char *p = "root=/dev/mtdblock2 init="/linuxrc" console="ttySAC0"";
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);
(4)設定標記ATAG_NONE。
標記列表以標記ATAG_NONE結束,如下設定:
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;