{ 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
#define APPLE_PROPERTIES_PROTOCOL_GUID \
{ 0x91bd12fe, 0xf6c3, 0x44fb, { 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0} }
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID \
+ { 0xb122a263, 0x3661, 0x4f68, {0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80} }
+#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION 1
+
+typedef struct {
+ EFI_GUID FwClass;
+ UINT32 FwType;
+ UINT32 FwVersion;
+ UINT32 LowestSupportedFwVersion;
+ UINT32 CapsuleFlags;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+} EFI_SYSTEM_RESOURCE_ENTRY;
+
+typedef struct {
+ UINT32 FwResourceCount;
+ UINT32 FwResourceCountMax;
+ UINT64 FwResourceVersion;
+ EFI_SYSTEM_RESOURCE_ENTRY Entries[];
+} EFI_SYSTEM_RESOURCE_TABLE;
typedef EFI_STATUS
(/* _not_ EFIAPI */ *EFI_SHIM_LOCK_VERIFY) (
}
#endif
+static UINTN __initdata esrt = EFI_INVALID_TABLE_ADDR;
+
+static size_t __init get_esrt_size(const EFI_MEMORY_DESCRIPTOR *desc)
+{
+ size_t available_len, len;
+ const UINTN physical_start = desc->PhysicalStart;
+ const EFI_SYSTEM_RESOURCE_TABLE *esrt_ptr;
+
+ len = desc->NumberOfPages << EFI_PAGE_SHIFT;
+ if ( esrt == EFI_INVALID_TABLE_ADDR )
+ return 0;
+ if ( physical_start > esrt || esrt - physical_start >= len )
+ return 0;
+ /*
+ * The specification requires EfiBootServicesData, but accept
+ * EfiRuntimeServicesData, which is a more logical choice.
+ */
+ if ( (desc->Type != EfiRuntimeServicesData) &&
+ (desc->Type != EfiBootServicesData) )
+ return 0;
+ available_len = len - (esrt - physical_start);
+ if ( available_len <= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries) )
+ return 0;
+ available_len -= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries);
+ esrt_ptr = (const EFI_SYSTEM_RESOURCE_TABLE *)esrt;
+ if ( (esrt_ptr->FwResourceVersion !=
+ EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION) ||
+ !esrt_ptr->FwResourceCount )
+ return 0;
+ if ( esrt_ptr->FwResourceCount > available_len / sizeof(esrt_ptr->Entries[0]) )
+ return 0;
+
+ return esrt_ptr->FwResourceCount * sizeof(esrt_ptr->Entries[0]);
+}
+
/*
* Include architecture specific implementation here, which references the
* static globals defined above.
return gop_mode;
}
+static EFI_GUID __initdata esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+
static void __init efi_tables(void)
{
unsigned int i;
efi.smbios = (unsigned long)efi_ct[i].VendorTable;
if ( match_guid(&smbios3_guid, &efi_ct[i].VendorGuid) )
efi.smbios3 = (unsigned long)efi_ct[i].VendorTable;
+ if ( match_guid(&esrt_guid, &efi_ct[i].VendorGuid) )
+ esrt = (UINTN)efi_ct[i].VendorTable;
}
#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
(EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+static void __init efi_relocate_esrt(EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS status;
+ UINTN info_size = 0, map_key, mdesc_size;
+ void *memory_map = NULL;
+ UINT32 ver;
+ unsigned int i;
+
+ for ( ; ; )
+ {
+ status = efi_bs->GetMemoryMap(&info_size, memory_map, &map_key,
+ &mdesc_size, &ver);
+ if ( status == EFI_SUCCESS && memory_map != NULL )
+ break;
+ if ( status == EFI_BUFFER_TOO_SMALL || memory_map == NULL )
+ {
+ info_size += 8 * mdesc_size;
+ if ( memory_map != NULL )
+ efi_bs->FreePool(memory_map);
+ memory_map = NULL;
+ status = efi_bs->AllocatePool(EfiLoaderData, info_size, &memory_map);
+ if ( status == EFI_SUCCESS )
+ continue;
+ PrintErr(L"Cannot allocate memory to relocate ESRT\r\n");
+ }
+ else
+ PrintErr(L"Cannot obtain memory map to relocate ESRT\r\n");
+ return;
+ }
+
+ /* Try to obtain the ESRT. Errors are not fatal. */
+ for ( i = 0; i < info_size; i += mdesc_size )
+ {
+ /*
+ * ESRT needs to be moved to memory of type EfiRuntimeServicesData
+ * so that the memory it is in will not be used for other purposes.
+ */
+ void *new_esrt = NULL;
+ size_t esrt_size = get_esrt_size(memory_map + i);
+
+ if ( !esrt_size )
+ continue;
+ if ( ((EFI_MEMORY_DESCRIPTOR *)(memory_map + i))->Type ==
+ EfiRuntimeServicesData )
+ break; /* ESRT already safe from reuse */
+ status = efi_bs->AllocatePool(EfiRuntimeServicesData, esrt_size,
+ &new_esrt);
+ if ( status == EFI_SUCCESS && new_esrt )
+ {
+ memcpy(new_esrt, (void *)esrt, esrt_size);
+ status = efi_bs->InstallConfigurationTable(&esrt_guid, new_esrt);
+ if ( status != EFI_SUCCESS )
+ {
+ PrintErr(L"Cannot install new ESRT\r\n");
+ efi_bs->FreePool(new_esrt);
+ }
+ }
+ else
+ PrintErr(L"Cannot allocate memory for ESRT\r\n");
+ break;
+ }
+
+ efi_bs->FreePool(memory_map);
+}
+
static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS status;
if ( gop )
efi_set_gop_mode(gop, gop_mode);
+ efi_relocate_esrt(SystemTable);
+
efi_exit_boot(ImageHandle, SystemTable);
efi_arch_post_exit_boot(); /* Doesn't return. */
unmap_domain_page(efi_l4t);
}
#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */