arm64

@font-face { font-family: "Times New Roman"; }@font-face { font-family: "宋体"; }@font-face { font-family: "Calibri"; }p.MsoNormal { margin: 0pt 0pt 0.0001pt; text-align: justify; font-family: Calibri; font-size: 10.5pt; }span.msoIns { text-decoration: underline; color: blue; }span.msoDel { text-decoration: line-through; color: red; }div.Section0 { page: Section0; }

Arm64/kernel/setup.c

Void __init setup_arch(char **cmdline_p)

 

 

 

{

Setup_machine_fdt(__fdt_pointer)

__Fdt_pointerbootloader传递参数的物理地址

//这个函数获取内核前期初始化需要的bootargs,cmd_line等系统引导参数

Unflatten_device_tree()//解析设备树,构建一个由device_node结构连接而成的单项链表

void __init unflatten_device_tree(void)

{

__unflatten_device_tree(initial_boot_params, &of_allnodes,

early_init_dt_alloc_memory_arch);

 

/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */

of_alias_scan(early_init_dt_alloc_memory_arch);

}

使用全局变量of_allnodes指针来保存这个链表的头指针,

内核调用of提供的api函数获取of_allnodes链表信息来初始化内核其他子系统,设备等

const char * __init of_flat_dt_get_machine_name(void)

{

const char *name;

//找到设备树的根节点,dt_root指向根节点的属性地址处

unsigned long dt_root = of_get_flat_dt_root();

//将根节点的compatible属性的属性值打印出来

name = of_get_flat_dt_prop(dt_root, "model", NULL);

if (!name)

name = of_get_flat_dt_prop(dt_root, "compatible", NULL);

return name;

}

 

 

}

static void __init setup_machine_fdt(phys_addr_t dt_phys)

{

if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) {

early_print("\n"

"Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"

"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"

"\nPlease check your bootloader.\n",

dt_phys, phys_to_virt(dt_phys));

 

while (true)

cpu_relax();

}

 

machine_name = of_flat_dt_get_machine_name();

if (machine_name)

pr_info("Machine: %s\n", machine_name);

}

 

首先在内核入口处将u-boot传递过来的镜像基地址

通过调用early_init_dt_scan(phys_to_virt(dt_phys函数获取内核前期初始化所需要的bootargs,cmd_line等系统引导参数

根据boottargs,cmd_line等系统引导参数进入start_kernel()函数,进行内核的第二阶段的初始化

 

 

arch/init/main.c

asmlinkage void __init start_kernel(void)

{

char * command_line;

extern const struct kernel_param __start___param[], __stop___param[];

 

 

local_irq_disable();

early_boot_irqs_disabled = true;

 

/*

 * Interrupts are still disabled. Do necessary setups, then

 * enable them

 */

boot_cpu_init();

page_address_init();

pr_notice("%s", linux_banner);

setup_arch(&command_line);

 

 

/drivers/of/fdt.c

 

//bootloader传递参数的物理地址不为空,并将物理地址转化为虚拟地址

//通过这个函数从设备树中读出bootargs,cmd_line等系统引导参数

bool __init early_init_dt_scan(void *params)

{

if (!params)

return false;

 

/* Setup flat device-tree pointer */

//参数paramsbootloader传递参数的物理地址转化为虚拟地址,保存设备树起始地址

initial_boot_params = params;

 

/* check device tree validity */

if (fdt_check_header(params)) {

initial_boot_params = NULL;

return false;

}

 

/* Retrieve various information from the /chosen node */

 

//从设备树中读取chosen节点信息,包括命令行boot_command_linesize

of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);

 

/* Initialize {size,address}-cells info */

//得到根节点{size address}-cells信息

of_scan_flat_dt(early_init_dt_scan_root, NULL);

 

/* Setup memory, calling early_init_dt_add_memory_arch */

读出设备树的系统内存设置

of_scan_flat_dt(early_init_dt_scan_memory, NULL);

 

return true;

}

 

 

//读出设备树的系统内存设置

int __init of_scan_flat_dt(int (*it)(unsigned long node,

     const char *uname, int depth,

     void *data),

   void *data)

{

const void *blob = initial_boot_params;

const char *pathp;

int offset, rc = 0, depth = -1;

 

        for (offset = fdt_next_node(blob, -1, &depth);

             offset >= 0 && depth >= 0 && !rc;

             offset = fdt_next_node(blob, offset, &depth)) {

 

pathp = fdt_get_name(blob, offset, NULL);

如果是节点路径,则返回路径的最后一段,假如为/root/my_root,则返回my_root,

即获得节点名

 

if (*pathp == '/')

pathp = kbasename(pathp);

//调用相应的节点处理函数,offset指向节点属性地址

rc = it(offset, pathp, depth, data);

}

return rc;

void __init early_init_dt_check_for_initrd(unsigned long node)

{

u64 start, end;

int len;

const __be32 *prop;

 

pr_debug("Looking for initrd properties... ");

 

prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);

if (!prop)

return;

start = of_read_number(prop, len/4);

 

prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);

if (!prop)

return;

end = of_read_number(prop, len/4);

 

early_init_dt_setup_initrd_arch(start, end);

pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n",

 (unsigned long long)start, (unsigned long long)end);

}

#else

posted @ 2017-02-08 16:01  小k的布熊  阅读(420)  评论(0)    收藏  举报