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_pointer是bootloader传递参数的物理地址
//这个函数获取内核前期初始化需要的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 */
//参数params是bootloader传递参数的物理地址转化为虚拟地址,保存设备树起始地址
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_line及size
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
浙公网安备 33010602011771号