drivers/firmware/efi/libstub/fdt.c

Source file repositories/reference/linux-study-clean/drivers/firmware/efi/libstub/fdt.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/efi/libstub/fdt.c
Extension
.c
Size
9966 bytes
Lines
380
Domain
Driver Families
Bucket
drivers/firmware
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct exit_boot_struct {
	struct efi_boot_memmap	*boot_memmap;
	efi_memory_desc_t	*runtime_map;
	int			runtime_entry_count;
	void			*new_fdt_addr;
};

static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
{
	struct exit_boot_struct *p = priv;

	p->boot_memmap = map;

	/*
	 * Update the memory map with virtual addresses. The function will also
	 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
	 * entries so that we can pass it straight to SetVirtualAddressMap()
	 */
	efi_get_virtmap(map->map, map->map_size, map->desc_size,
			p->runtime_map, &p->runtime_entry_count);

	return update_fdt_memmap(p->new_fdt_addr, map);
}

#ifndef MAX_FDT_SIZE
# define MAX_FDT_SIZE SZ_2M
#endif

/*
 * Allocate memory for a new FDT, then add EFI and commandline related fields
 * to the FDT.  This routine increases the FDT allocation size until the
 * allocated memory is large enough.  EFI allocations are in EFI_PAGE_SIZE
 * granules, which are fixed at 4K bytes, so in most cases the first allocation
 * should succeed.  EFI boot services are exited at the end of this function.
 * There must be no allocations between the get_memory_map() call and the
 * exit_boot_services() call, so the exiting of boot services is very tightly
 * tied to the creation of the FDT with the final memory map in it.
 */
static
efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
					    efi_loaded_image_t *image,
					    unsigned long *new_fdt_addr,
					    char *cmdline_ptr)
{
	unsigned long desc_size;
	u32 desc_ver;
	efi_status_t status;
	struct exit_boot_struct priv;
	unsigned long fdt_addr = 0;
	unsigned long fdt_size = 0;

	if (!efi_novamap) {
		status = efi_alloc_virtmap(&priv.runtime_map, &desc_size,
					   &desc_ver);
		if (status != EFI_SUCCESS) {
			efi_err("Unable to retrieve UEFI memory map.\n");
			return status;
		}
	}

	/*
	 * Unauthenticated device tree data is a security hazard, so ignore
	 * 'dtb=' unless UEFI Secure Boot is disabled.  We assume that secure
	 * boot is enabled if we can't determine its state.
	 */
	if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
	    efi_get_secureboot() != efi_secureboot_mode_disabled) {
		if (strstr(cmdline_ptr, "dtb="))
			efi_err("Ignoring DTB from command line.\n");
	} else {
		status = efi_load_dtb(image, &fdt_addr, &fdt_size);

		if (status != EFI_SUCCESS && status != EFI_NOT_READY) {
			efi_err("Failed to load device tree!\n");
			goto fail;
		}
	}

	if (fdt_addr) {
		efi_info("Using DTB from command line\n");
	} else {
		/* Look for a device tree configuration table entry. */
		fdt_addr = (uintptr_t)get_fdt(&fdt_size);
		if (fdt_addr)
			efi_info("Using DTB from configuration table\n");
	}

	if (!fdt_addr)
		efi_info("Generating empty DTB\n");

Annotation

Implementation Notes