in efi/esrt.c [241:340]
void __init efi_esrt_init(void)
{
void *va;
struct efi_system_resource_table tmpesrt;
size_t size, max, entry_size, entries_size;
efi_memory_desc_t md;
int rc;
phys_addr_t end;
if (!efi_enabled(EFI_MEMMAP))
return;
pr_debug("esrt-init: loading.\n");
if (!esrt_table_exists())
return;
rc = efi_mem_desc_lookup(efi.esrt, &md);
if (rc < 0 ||
(!(md.attribute & EFI_MEMORY_RUNTIME) &&
md.type != EFI_BOOT_SERVICES_DATA &&
md.type != EFI_RUNTIME_SERVICES_DATA)) {
pr_warn("ESRT header is not in the memory map.\n");
return;
}
max = efi_mem_desc_end(&md);
if (max < efi.esrt) {
pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n",
(void *)efi.esrt, (void *)max);
return;
}
size = sizeof(*esrt);
max -= efi.esrt;
if (max < size) {
pr_err("ESRT header doesn't fit on single memory map entry. (size: %zu max: %zu)\n",
size, max);
return;
}
va = early_memremap(efi.esrt, size);
if (!va) {
pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
size);
return;
}
memcpy(&tmpesrt, va, sizeof(tmpesrt));
early_memunmap(va, size);
if (tmpesrt.fw_resource_version != 1) {
pr_err("Unsupported ESRT version %lld.\n",
tmpesrt.fw_resource_version);
return;
}
entry_size = sizeof(struct efi_system_resource_entry_v1);
if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) {
pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n",
max - size, entry_size);
return;
}
/*
* The format doesn't really give us any boundary to test here,
* so I'm making up 128 as the max number of individually updatable
* components we support.
* 128 should be pretty excessive, but there's still some chance
* somebody will do that someday and we'll need to raise this.
*/
if (tmpesrt.fw_resource_count > 128) {
pr_err("ESRT says fw_resource_count has very large value %d.\n",
tmpesrt.fw_resource_count);
return;
}
/*
* We know it can't be larger than N * sizeof() here, and N is limited
* by the previous test to a small number, so there's no overflow.
*/
entries_size = tmpesrt.fw_resource_count * entry_size;
if (max < size + entries_size) {
pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n",
size, max);
return;
}
size += entries_size;
esrt_data = (phys_addr_t)efi.esrt;
esrt_data_size = size;
end = esrt_data + size;
pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end);
if (md.type == EFI_BOOT_SERVICES_DATA)
efi_mem_reserve(esrt_data, esrt_data_size);
pr_debug("esrt-init: loaded.\n");
}