[U-Boot] [PATCH 0/2] efi_loader: print information about loaded UEFI images

If an exception occurs in a UEFI loaded image we need the start address of the image to determine the relocation offset.
This patch series adds the necessary lines after the registers in the crash dump. A possible output would be:
UEFI image start 0x7fdb4000, size 0xa7b60 pc offset 0x72ca /\snp.efi
With the offset 0x72ca we can now find the relevant instruction in the disassembled 'snp.efi' binary.
Heinrich Schuchardt (2): efi_loader: new functions to print loaded image information arm: print information about loaded UEFI images
arch/arm/lib/interrupts.c | 17 +++++++++++++++ include/efi_loader.h | 4 ++++ lib/efi_loader/efi_image_loader.c | 45 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+)

Introduce functions to print information about loaded images.
If we want to analyze an exception in an EFI image we need the offset between the PC and the start of the loaded image.
With efi_print_image_info() we can print the necessary information for a single image, e.g.
UEFI image start 0x7fdb4000, size 0xa7b60 pc offset 0x72ca /\snp.efi
efi_print_image_infos() provides output for all loaded images.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- include/efi_loader.h | 4 ++++ lib/efi_loader/efi_image_loader.c | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 07730c3f39..5ed6ff04d8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -284,6 +284,10 @@ efi_status_t efi_setup_loaded_image( struct efi_device_path *file_path); efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); +/* Print information about a loaded image */ +efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc); +/* Print information about all loaded images */ +void efi_print_image_infos(void *pc);
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index cac64ba9fe..9750da551a 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -22,6 +22,51 @@ const efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+/* + * Print information about a loaded image. + * + * If the program counter is located within the image the offset to the base + * address is shown. + * + * @image: loaded image + * @pc: program counter (use NULL to suppress offset output) + * @return: status code + */ +efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc) +{ + if (!image) + return EFI_INVALID_PARAMETER; + printf("UEFI image\nstart 0x%p, size 0x%llx\n", + image->image_base, image->image_size); + if (pc && pc >= image->image_base && + pc < image->image_base + image->image_size) + printf("pc offset 0x%zx\n", pc - image->image_base); + if (image->file_path) + printf("%pD\n", image->file_path); + return EFI_SUCCESS; +} + +/* + * Print information about all loaded images. + * + * @pc: program counter (use NULL to suppress offset output) + */ +void efi_print_image_infos(void *pc) +{ + struct efi_object *efiobj; + struct efi_handler *handler; + + list_for_each_entry(efiobj, &efi_obj_list, link) { + list_for_each_entry(handler, &efiobj->protocols, link) { + if (!guidcmp(handler->guid, &efi_guid_loaded_image)) { + printf("\n"); + efi_print_image_info( + handler->protocol_interface, pc); + } + } + } +} + static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, unsigned long rel_size, void *efi_reloc) {

On 29.03.18 23:54, Heinrich Schuchardt wrote:
Introduce functions to print information about loaded images.
If we want to analyze an exception in an EFI image we need the offset between the PC and the start of the loaded image.
With efi_print_image_info() we can print the necessary information for a single image, e.g.
UEFI image start 0x7fdb4000, size 0xa7b60 pc offset 0x72ca /\snp.efi
efi_print_image_infos() provides output for all loaded images.
This is the only function we're actually calling. That means if you have 3 images loaded, things become quite unpleasant to read, with each image spanning over 4 lines.
Can you please condense the image information down to a single line? Something like this:
UEFI image "foo.efi" [0x70db4000:0x70e5b000] UEFI image "snp.efi" [0x7fdb4000:0x7fe5bb60] pc=0x72ca UEFI image "bar.efi" [0x7cdb4000:0x7ce50000]
Alex
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
include/efi_loader.h | 4 ++++ lib/efi_loader/efi_image_loader.c | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 07730c3f39..5ed6ff04d8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -284,6 +284,10 @@ efi_status_t efi_setup_loaded_image( struct efi_device_path *file_path); efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); +/* Print information about a loaded image */ +efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc); +/* Print information about all loaded images */ +void efi_print_image_infos(void *pc);
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER extern void *efi_bounce_buffer; diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index cac64ba9fe..9750da551a 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -22,6 +22,51 @@ const efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+/*
- Print information about a loaded image.
- If the program counter is located within the image the offset to the base
- address is shown.
- @image: loaded image
- @pc: program counter (use NULL to suppress offset output)
- @return: status code
- */
+efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc) +{
- if (!image)
return EFI_INVALID_PARAMETER;
- printf("UEFI image\nstart 0x%p, size 0x%llx\n",
image->image_base, image->image_size);
- if (pc && pc >= image->image_base &&
pc < image->image_base + image->image_size)
printf("pc offset 0x%zx\n", pc - image->image_base);
- if (image->file_path)
printf("%pD\n", image->file_path);
- return EFI_SUCCESS;
+}
+/*
- Print information about all loaded images.
- @pc: program counter (use NULL to suppress offset output)
- */
+void efi_print_image_infos(void *pc) +{
- struct efi_object *efiobj;
- struct efi_handler *handler;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
list_for_each_entry(handler, &efiobj->protocols, link) {
if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
printf("\n");
efi_print_image_info(
handler->protocol_interface, pc);
}
}
- }
+}
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, unsigned long rel_size, void *efi_reloc) {

If an exception occurs in a UEFI loaded image we need the start address of the image to determine the relocation offset.
This patch adds the necessary lines after the registers in the crash dump. A possible output would be:
UEFI image start 0x7fdb4000, size 0xa7b60 pc offset 0x72ca /\snp.efi
With the offset 0x72ca we can now find the relevant instruction in the disassembled 'snp.efi' binary.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- arch/arm/lib/interrupts.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c index 80869adb61..a28fef8f46 100644 --- a/arch/arm/lib/interrupts.c +++ b/arch/arm/lib/interrupts.c @@ -20,6 +20,7 @@ */
#include <common.h> +#include <efi_loader.h> #include <asm/proc-armv/ptrace.h> #include <asm/u-boot-arm.h> #include <efi_loader.h> @@ -51,6 +52,14 @@ void bad_mode (void) reset_cpu (0); }
+static void show_efi_loaded_images(struct pt_regs *regs) +{ +#if defined(CONFIG_EFI_LOADER) && \ + !defined(CONFIG_SPL_BUILD) && !defined(API_BUILD) + efi_print_image_infos((void *)instruction_pointer(regs)); +#endif +} + void show_regs (struct pt_regs *regs) { unsigned long __maybe_unused flags; @@ -77,6 +86,7 @@ void show_regs (struct pt_regs *regs) printf("sp : %08lx ip : %08lx fp : %08lx\n", regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); @@ -106,6 +116,7 @@ void do_undefined_instruction (struct pt_regs *pt_regs) printf ("undefined instruction\n"); fixup_pc(pt_regs, -4); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -115,6 +126,7 @@ void do_software_interrupt (struct pt_regs *pt_regs) printf ("software interrupt\n"); fixup_pc(pt_regs, -4); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -124,6 +136,7 @@ void do_prefetch_abort (struct pt_regs *pt_regs) printf ("prefetch abort\n"); fixup_pc(pt_regs, -8); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -133,6 +146,7 @@ void do_data_abort (struct pt_regs *pt_regs) printf ("data abort\n"); fixup_pc(pt_regs, -8); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -142,6 +156,7 @@ void do_not_used (struct pt_regs *pt_regs) printf ("not used\n"); fixup_pc(pt_regs, -8); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -151,6 +166,7 @@ void do_fiq (struct pt_regs *pt_regs) printf ("fast interrupt request\n"); fixup_pc(pt_regs, -8); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
@@ -160,5 +176,6 @@ void do_irq (struct pt_regs *pt_regs) printf ("interrupt request\n"); fixup_pc(pt_regs, -8); show_regs (pt_regs); + show_efi_loaded_images(pt_regs); bad_mode (); }
participants (2)
-
Alexander Graf
-
Heinrich Schuchardt