in efi/libstub/fdt.c [30:161]
static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
void *fdt, int new_fdt_size, char *cmdline_ptr,
u64 initrd_addr, u64 initrd_size)
{
int node, num_rsv;
int status;
u32 fdt_val32;
u64 fdt_val64;
/* Do some checks on provided FDT, if it exists: */
if (orig_fdt) {
if (fdt_check_header(orig_fdt)) {
efi_err("Device Tree header not valid!\n");
return EFI_LOAD_ERROR;
}
/*
* We don't get the size of the FDT if we get if from a
* configuration table:
*/
if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
efi_err("Truncated device tree! foo!\n");
return EFI_LOAD_ERROR;
}
}
if (orig_fdt) {
status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
} else {
status = fdt_create_empty_tree(fdt, new_fdt_size);
if (status == 0) {
/*
* Any failure from the following function is
* non-critical:
*/
fdt_update_cell_size(fdt);
}
}
if (status != 0)
goto fdt_set_fail;
/*
* Delete all memory reserve map entries. When booting via UEFI,
* kernel will use the UEFI memory map to find reserved regions.
*/
num_rsv = fdt_num_mem_rsv(fdt);
while (num_rsv-- > 0)
fdt_del_mem_rsv(fdt, num_rsv);
node = fdt_subnode_offset(fdt, 0, "chosen");
if (node < 0) {
node = fdt_add_subnode(fdt, 0, "chosen");
if (node < 0) {
/* 'node' is an error code when negative: */
status = node;
goto fdt_set_fail;
}
}
if (cmdline_ptr != NULL && strlen(cmdline_ptr) > 0) {
status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
strlen(cmdline_ptr) + 1);
if (status)
goto fdt_set_fail;
}
/* Set initrd address/end in device tree, if present */
if (initrd_size != 0) {
u64 initrd_image_end;
u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start);
if (status)
goto fdt_set_fail;
initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end);
if (status)
goto fdt_set_fail;
}
/* Add FDT entries for EFI runtime services in chosen node. */
node = fdt_subnode_offset(fdt, 0, "chosen");
fdt_val64 = cpu_to_fdt64((u64)(unsigned long)efi_system_table);
status = fdt_setprop_var(fdt, node, "linux,uefi-system-table", fdt_val64);
if (status)
goto fdt_set_fail;
fdt_val64 = U64_MAX; /* placeholder */
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
if (status)
goto fdt_set_fail;
fdt_val32 = U32_MAX; /* placeholder */
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
if (status)
goto fdt_set_fail;
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32);
if (status)
goto fdt_set_fail;
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32);
if (status)
goto fdt_set_fail;
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) {
efi_status_t efi_status;
efi_status = efi_get_random_bytes(sizeof(fdt_val64),
(u8 *)&fdt_val64);
if (efi_status == EFI_SUCCESS) {
status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64);
if (status)
goto fdt_set_fail;
}
}
/* Shrink the FDT back to its minimum size: */
fdt_pack(fdt);
return EFI_SUCCESS;
fdt_set_fail:
if (status == -FDT_ERR_NOSPACE)
return EFI_BUFFER_TOO_SMALL;
return EFI_LOAD_ERROR;
}