APEI consists on H/W which cooperate with OS in case of error occurrence. Cooperation relay on read/write to/from APEI specific registers. Since currently there is no APEI support on any available ARM boards, we need to simulate it via set aside RAM memory which pretends these APEI regions, registers. The easiest way to do that is loading APEI blob being in GRUB stage. Now we can use 'apei' command to load APEI blob to given address. This is only for APEI test purpose and should not be merged to the mail line.
Signed-off-by: Tomasz Nowicki tomasz.nowicki@linaro.org --- grub-core/loader/arm64/linux.c | 70 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-)
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 75ad871..17938ba 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -54,6 +54,8 @@ static grub_addr_t initrd_end; static void *loaded_fdt; static void *fdt;
+static void *apei_data; + static void * get_firmware_fdt (void) { @@ -241,6 +243,69 @@ out: }
static grub_err_t +grub_cmd_apei (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_efi_physical_address_t apei_phy_addr; + grub_efi_boot_services_t *b; + grub_efi_status_t status; + grub_file_t apei; + void *blob = NULL; + int size; + + if (!loaded) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("you need to load the kernel first")); + return GRUB_ERR_BAD_OS; + } + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + apei = grub_file_open (argv[0]); + if (!apei) + goto out; + + size = grub_file_size (apei); + if (size == 0) + goto out; + + blob = grub_malloc (size); + if (!blob) + goto out; + + if (grub_file_read (apei, blob, size) < size) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); + goto out; + } + + grub_dprintf ("linux", "allocating %ld bytes for APEI blob\n", size); + apei_phy_addr = 0x80000000 + 0x2000000 - 0x200000; + apei_data = grub_efi_allocate_pages (apei_phy_addr, BYTES_TO_PAGES(size)); + if (!apei_data) { + grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("can not allocate at 0x%lx"), apei_phy_addr); + goto out; + } + + grub_memmove (apei_data, blob, size); + + grub_dprintf ("linux", "Installed APEI blob @ %p\n", apei_data); + +out: + if (apei) + grub_file_close (apei); + + if (blob) + grub_free (blob); + + return grub_errno; +} + +static grub_err_t grub_linux_boot (void) { grub_efi_memory_mapped_device_path_t *mempath; @@ -465,7 +530,7 @@ fail: }
-static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree; +static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree, cmd_apei;
GRUB_MOD_INIT (linux) { @@ -476,6 +541,9 @@ GRUB_MOD_INIT (linux) cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree, 0, N_("Load DTB file.")); + + cmd_apei = grub_register_command ("apei", grub_cmd_apei, 0, + N_("Load APEI blob.")); my_mod = mod; }