u boot到kernel的引數傳遞

2021-05-23 22:23:49 字數 4785 閱讀 6312

在u-boot

的最後提到傳遞引數給核心,呼叫如下 //

呼叫核心,暫存器

r0=0,r1=

機器型別,

r2=引數塊位址

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

而這兩個引數是如何傳遞給

kernel

的分析如下(只涉及到非彙編部分) 一.

u-boot

傳遞tag

到kernel

的解析

在setup_arch

函式的parse_tags

中對傳遞過來的

taglist

進行了解析

對每一項的

tag使用

parse_tag

分析,

for (t = &__tagtable_begin; t < &__tagtable_end; t++)

if (tag->hdr.tag == t->tag)

其中__tagtable_begin,__tagtable_end

在vmlinux.ld

中也有定義,這裡看

tagtable

的建立過程

#define __tagtalbe(tag,fn)/

static struct tagtable __tagtable_##fn __tag=

#define __tag __userd __attribute__((__section__(「.taglist.init」)))

對於上述巨集中的

fn,就是

tagtable

結構中的

parse

指標所指向的函式。 而在

setup.c

中,已經通過

__tagtalbe(atag_***,***)

建立起所有可能的

tagtable,

所以可以通過遍歷

__tagtable_begin~__tagtable_end

找到對應的

tagtable,

並呼叫對應的

parse

進行解析並配置

對於如何在指定位址找到傳遞過來的

taglist(u-boot

傳遞過來的

taglist

位於sdram+0x100

位置上,一般情況下這麼設定

)如下, 在

setup_arch

中定義struct tag* tags=(struct tag*)&init_tags,

init_tags

是struct init_tags

結構定義的乙個

default init_tags

,將此變數儲存於「

.init.data」

段中,在

vmlinux.ld

中有定義

同時在setup_arch中,

if (__atags_pointer)

tags = phys_to_virt(__atags_pointer);

else if (mdesc->boot_params)

tags = phys_to_virt(mdesc->boot_params);

將傳遞過來的

boot_params

的實體地址轉換成虛擬位址賦值給

tags,

而boot_params

的實體地址為

sdram+0x100

附帶一句,由於

taglist

中有cmd

,解析完

taglist

後,會呼叫

parse_cmdline

解析傳遞過來的命令 二.

machine_start

在u-boot

傳遞引數給

kernel

時,包括機器型別和

taglist

。機器型別就用來決定相應的

machine_desc

結構。

#define machine_start(_type,_name)/

static const struct machine_desc __mach_desc_##_type/

__used/

__attribute__((__section__(".arch.info.init"))) = ;

假設mach_type_a,

對應的結構為

__mach_desc_a,

machine_start(a, "a")

//這裡由於

u-boot

傳遞過來的機器型號與

machine_start

中的nr

進行匹配 //

如果匹配,則返回對應的

machine_desc結構

/* maintainer: atmel */

.phys_io= at91_base_sys,

.io_pg_offst= (at91_va_base_sys >> 18) & 0xfffc,

.boot_params= at91_sdram_base + 0x100, //

其餘參量在

setup_arch

中用到,如

boot_params

就決定taglist位址

.timer= &at91sam926x_timer,

.map_io=board_map_io, // ------devicemaps_init()

.init_irq= board_init_irq, //init_arch_irq

.init_machine= board_init,//customize_machine-----

將該函式放在

arch_initcall

段裡,自動呼叫

machine_end

通過得到

machine_desc

結構之後,就可以具體對板級做相應的初始化,特別是

.init_machine=board_init

中,對各個硬體做了相關配置初始化。 三.

initcalls

另外寫點關於

__initcall__

在vmlinux.lds

的.init

中定義了

__initcall_

__initcall_start = .;

*(.initcall0.init) *(.initcall0s.init)

*(.initcall1.init) *(.initcall1s.init)

*(.initcall2.init) *(.initcall2s.init)

*(.initcall3.init)*(.initcall3s.init)

*(.initcall4.init) *(.initcall4s.init)

*(.initcall5.init) *(.initcall5s.init)

*(.initcallrootfs.init)

*(.initcall6.init) *(.initcall6s.init)

*(.initcall7.init) *(.initcall7s.init)

__initcall_end = .;

經常在驅動中能看到巨集

subsys_initcall

和module_init

#define subsys_initcall(fn) __define_initcall(「4」,fn,4)

#define __define_initcall(level,fn,id) /

static initcall_t __initcall_##fn##id __attribute_used__/

__attribute__((__section(「.initcall」level」.init」)))=fn

這裡是將

fn存放在

__section

名為.initcall4.init中

而initcall_t

則是函式指標

在系統啟動過程中會根據上面的

initcall

表逐個init

,而subsys_initcall

初始化的函式位於

.initcall4.init段中

呼叫的**大致如下,在函式

do_initcalls中

initcall_t *call

for(call=__initcall_start;call<__initcall_end;call++)

result=(*call)();

同樣的,

#define module_init(x) __initcall(x)

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn) __define_initcall(「6」,fn,6)

即module_init

初始化的函式位於

initcall6.init段中

在init.h

中,還能看到

initcall的段1

是core_initcall,段2

是postcore_initcall,段3

是arch_initcall,段4

是subsys_initcall,段5

是fs_initcall,段6

是device_initcall段7

是late_initcall

uboot移植之uboot和kernel的引數傳遞

從uboot啟動核心的形式thekernel 0,machid,bd bi boot params 可以看出uboot給核心傳遞了3個引數,第1個是0,第2個是機器碼,第3個是引數列表在sdram的起始位置 剛好滿足一下呼叫核心的條件 r0 0。r1 機器型別id r2 啟動引數標記列表在ram 中...

uboot 引導kernel雜談

記錄最近除錯uboot的心得,供後續總結!總結 uboot 主要作用是用來引導kernel啟動,傳遞引數給kernel。大致分為2個階段 第一階段 主要是start.s 彙編階段,主要完成如下設定 1,設定cpu 中斷向量表 2,設定cpu速度,時鐘以及終端 3,初始化sdram 記憶體 4,將ub...

uboot與kernel的flash分割槽

1.我們可以在uboot中修改flash分割槽。2.我們也可以在kernel中修改flash分割槽,但是需要與uboot中的分割槽表一致。3.我們可以通過uboot用引數傳給kernel分割槽資訊,這樣只需要維護uboot的分割槽表即可。這要對bootloader對核心重新分割槽 這需要重新設定一下...