/* Parse the ACPI tables for possible boot-time configuration */ acpi_boot_table_init();
parse_dtb实现如下:
staticvoid __init parse_dtb(void) { /* Early scan of device tree from init memory */ if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) { constchar *name = of_flat_dt_get_machine_name();
if (name) { pr_info("Machine model: %s\n", name); dump_stack_set_arch_desc("%s (DT)", name); } } else { pr_err("No DTB passed to the kernel\n"); } }
/* Setup early mapping for FDT early scan */ create_fdt_early_page_table(__fix_to_virt(FIX_FDT), dtb_pa); ... }
TODO 参数1
参数2就是通过a0传过来的设备树地址。
create_fdt_early_page_table
create_fdt_early_page_table函数定义如下:
/* * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel, * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR * entry. */ staticvoid __init create_fdt_early_page_table(uintptr_t fix_fdt_va, uintptr_t dtb_pa) { #ifndef CONFIG_BUILTIN_DTB uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
/* Make sure the fdt fixmap address is always aligned on PMD size */ BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE));
/* In 32-bit only, the fdt lies in its own PGD */ if (!IS_ENABLED(CONFIG_64BIT)) { create_pgd_mapping(early_pg_dir, fix_fdt_va, pa, MAX_FDT_SIZE, PAGE_KERNEL); } else { create_pmd_mapping(fixmap_pmd, fix_fdt_va, pa, PMD_SIZE, PAGE_KERNEL); create_pmd_mapping(fixmap_pmd, fix_fdt_va + PMD_SIZE, pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL); }
dtb_early_va = (void *)fix_fdt_va + (dtb_pa & (PMD_SIZE - 1)); #else /* * For 64-bit kernel, __va can't be used since it would return a linear * mapping address whereas dtb_early_va will be used before * setup_vm_final installs the linear mapping. For 32-bit kernel, as the * kernel is mapped in the linear mapping, that makes no difference. */ dtb_early_va = kernel_mapping_pa_to_va(dtb_pa); #endif
dtb_early_pa = dtb_pa; }
create_fdt_early_page_table 这个函数的目的是在启动过程中为设备树(Device Tree Blob, DTB)创建早期的内存页表映射。它在内核初始化阶段进行,确保设备树在内存中的地址被正确映射,以便内核能够访问设备树数据。具体来说,这个函数的作用是在虚拟地址空间中为设备树(DTB)创建一个页表映射,允许内核访问设备树。
staticvoid __init parse_dtb(void) { /* Early scan of device tree from init memory */ if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) { constchar *name = of_flat_dt_get_machine_name();
if (name) { pr_info("Machine model: %s\n", name); dump_stack_set_arch_desc("%s (DT)", name); } } else { pr_err("No DTB passed to the kernel\n"); } }
void __init early_init_dt_scan_nodes(void) { int rc;
/* Retrieve various information from the /chosen node */ rc = early_init_dt_scan_chosen(boot_command_line); if (rc) pr_warn("No chosen node found, continuing without\n");
/** * unflatten_device_tree - create tree of device_nodes from flat blob * * unflattens the device-tree passed by the firmware, creating the * tree of struct device_node. It also fills the "name" and "type" * pointers of the nodes so the normal device-tree walking functions * can be used. */ void __init unflatten_device_tree(void) { void *fdt = initial_boot_params;
/* Save the statically-placed regions in the reserved_mem array */ fdt_scan_reserved_mem_reg_nodes();
/* Populate an empty root node when bootloader doesn't provide one */ if (!fdt) { fdt = (void *) __dtb_empty_root_begin; /* fdt_totalsize() will be used for copy size */ if (fdt_totalsize(fdt) > __dtb_empty_root_end - __dtb_empty_root_begin) { pr_err("invalid size in dtb_empty_root\n"); return; } of_fdt_crc32 = crc32_be(~0, fdt, fdt_totalsize(fdt)); fdt = copy_device_tree(fdt); }
/** * __unflatten_device_tree - create tree of device_nodes from flat blob * @blob: The blob to expand * @dad: Parent device node * @mynodes: The device_node tree created by the call * @dt_alloc: An allocator that provides a virtual address to memory * for the resulting tree * @detached: if true set OF_DETACHED on @mynodes * * unflattens a device-tree, creating the tree of struct device_node. It also * fills the "name" and "type" pointers of the nodes so the normal device-tree * walking functions can be used. * * Return: NULL on failure or the memory chunk containing the unflattened * device tree on success. */ void *__unflatten_device_tree(constvoid *blob, struct device_node *dad, struct device_node **mynodes, void *(*dt_alloc)(u64 size, u64 align), bool detached) { int size; void *mem; int ret;
... /* First pass, scan for size */ size = unflatten_dt_nodes(blob, NULL, dad, NULL); if (size <= 0) returnNULL;
size = ALIGN(size, 4); pr_debug(" size is %d, allocating...\n", size);
/* Allocate memory for the expanded device tree */ mem = dt_alloc(size + 4, __alignof__(struct device_node)); if (!mem) returnNULL;
...
/* Second pass, do actual unflattening */ ret = unflatten_dt_nodes(blob, mem, dad, mynodes);
/** * unflatten_dt_nodes - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties * @dad: Parent struct device_node * @nodepp: The device_node tree created by the call * * Return: The size of unflattened device tree or error code */ staticintunflatten_dt_nodes(constvoid *blob, void *mem, struct device_node *dad, struct device_node **nodepp) { structdevice_node *root; int offset = 0, depth = 0, initial_depth = 0; #define FDT_MAX_DEPTH 64 structdevice_node *nps[FDT_MAX_DEPTH]; void *base = mem; bool dryrun = !base; int ret;