summaryrefslogtreecommitdiff
path: root/lib/efi_loader/efi_debug_support.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-07-03 08:25:38 -0600
committerTom Rini <trini@konsulko.com>2025-07-03 08:25:38 -0600
commit218db7bdbd0ea115c166f8bf18e1292c588beb10 (patch)
treec724c584750b3f0d1d6e786bc9c0243557c847e3 /lib/efi_loader/efi_debug_support.c
parentc405bab7661dd60420e97a4edeb3162e9d7e02c5 (diff)
parent95732f2bf8700f9ec17983b419073b6a16b79aef (diff)
Merge tag 'efi-next-03072025' of https://source.denx.de/u-boot/custodians/u-boot-tpm into next
Sughosh added EFI HTTP(s) support into our eficonfig application. Up to now we could only enable that via our efidebug command. Users now get that option on the eficonfig menu. Javier implemented support for the EFI_PARTITION_INFO_PROTOCOL, to provide cached partition information for GPT partition types. The protocol describes legacy MBR partition types, but that's for backward compatibility and not implemented by this series. The protocol is needed by [0], an implementation of a UEFI based A/B boot protocol for the root filesystem. Paul added support for EFI_DEBUG_IMAGE_INFO_TABLE. This is part of the EFI spec and is defining a debug protocol that Google currently uses to debug their Generic Bootloader project [1][2], using EFI to load Android. Heinrich contributed a test EFI application for it as well. The efi_realloc() function he added will realloc any type of memory to BootServicesData, but keeping in mind the new protocol is the only consumer he will fix that on a followup patch. Finally another round of smatch fixes from Andrew cleans up coding errors. The CI https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/26935 seems happy [0] https://gitlab.com/CentOS/automotive/src/ukiboot [1] https://lpc.events/event/18/contributions/1704/attachments/1550/3231/Android%20Generic%20Boot%20Loader.pdf [2] https://source.android.com/docs/core/architecture/bootloader/generic-bootloader
Diffstat (limited to 'lib/efi_loader/efi_debug_support.c')
-rw-r--r--lib/efi_loader/efi_debug_support.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/efi_loader/efi_debug_support.c b/lib/efi_loader/efi_debug_support.c
new file mode 100644
index 00000000000..186bdbce750
--- /dev/null
+++ b/lib/efi_loader/efi_debug_support.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * EFI debug support
+ *
+ * Copyright (c) 2025 Ying-Chun Liu, Linaro Ltd. <paul.liu@linaro.org>
+ */
+
+#include <efi_loader.h>
+#include <linux/sizes.h>
+#include <u-boot/crc.h>
+
+struct efi_system_table_pointer __efi_runtime_data * systab_pointer = NULL;
+
+struct efi_debug_image_info_table_header efi_m_debug_info_table_header = {
+ 0,
+ 0,
+ NULL
+};
+
+/* efi_m_max_table_entries is the maximum entries allocated for
+ * the efi_m_debug_info_table_header.efi_debug_image_info_table.
+ */
+static u32 efi_m_max_table_entries;
+
+#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof(union efi_debug_image_info *))
+
+/**
+ * efi_initialize_system_table_pointer() - Initialize system table pointer
+ *
+ * Return: status code
+ */
+efi_status_t efi_initialize_system_table_pointer(void)
+{
+ /* Allocate efi_system_table_pointer structure with 4MB alignment. */
+ systab_pointer = efi_alloc_aligned_pages(sizeof(struct efi_system_table_pointer),
+ EFI_RUNTIME_SERVICES_DATA,
+ SZ_4M);
+
+ if (!systab_pointer) {
+ log_err("Installing EFI system table pointer failed\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ systab_pointer->crc32 = 0;
+
+ systab_pointer->signature = EFI_SYSTEM_TABLE_SIGNATURE;
+ systab_pointer->efi_system_table_base = (uintptr_t)&systab;
+ systab_pointer->crc32 = crc32(0,
+ (const unsigned char *)systab_pointer,
+ sizeof(struct efi_system_table_pointer));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_core_new_debug_image_info_entry() - Add a new efi_loaded_image structure to the
+ * efi_debug_image_info table.
+ *
+ * @image_info_type: type of debug image information
+ * @loaded_image: pointer to the loaded image protocol for the image
+ * being loaded
+ * @image_handle: image handle for the image being loaded
+ *
+ * Re-Allocates the table if it's not large enough to accommodate another
+ * entry.
+ *
+ * Return: status code
+ **/
+efi_status_t efi_core_new_debug_image_info_entry(u32 image_info_type,
+ struct efi_loaded_image *loaded_image,
+ efi_handle_t image_handle)
+{
+ union efi_debug_image_info **table;
+ u32 index;
+ u32 table_size;
+ efi_status_t ret;
+
+ /* Set the flag indicating that we're in the process of updating
+ * the table.
+ */
+ efi_m_debug_info_table_header.update_status |=
+ EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ table = &efi_m_debug_info_table_header.efi_debug_image_info_table;
+
+ if (efi_m_debug_info_table_header.table_size >= efi_m_max_table_entries) {
+ /* table is full, re-allocate the buffer increasing the size
+ * by 4 KiB.
+ */
+ table_size = efi_m_max_table_entries * EFI_DEBUG_TABLE_ENTRY_SIZE;
+
+ ret = efi_realloc((void **)table, table_size + EFI_PAGE_SIZE);
+
+ if (ret != EFI_SUCCESS) {
+ efi_m_debug_info_table_header.update_status &=
+ ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+ return ret;
+ }
+
+ /* Enlarge the max table entries and set the first empty
+ * entry index to be the original max table entries.
+ */
+ efi_m_max_table_entries +=
+ EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+ }
+
+ /* We always put the next entry at the end of the currently consumed
+ * table (i.e. first free entry)
+ */
+ index = efi_m_debug_info_table_header.table_size;
+
+ /* Allocate data for new entry. */
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
+ sizeof(union efi_debug_image_info),
+ (void **)(&(*table)[index].normal_image));
+ if (ret == EFI_SUCCESS && (*table)[index].normal_image) {
+ /* Update the entry. */
+ (*table)[index].normal_image->image_info_type = image_info_type;
+ (*table)[index].normal_image->loaded_image_protocol_instance =
+ loaded_image;
+ (*table)[index].normal_image->image_handle = image_handle;
+
+ /* Increase the number of EFI_DEBUG_IMAGE_INFO elements and
+ * set the efi_m_debug_info_table_header in modified status.
+ */
+ efi_m_debug_info_table_header.table_size++;
+ efi_m_debug_info_table_header.update_status |=
+ EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+ } else {
+ log_err("Adding new efi_debug_image_info failed\n");
+ return ret;
+ }
+
+ efi_m_debug_info_table_header.update_status &=
+ ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_core_remove_debug_image_info_entry() - Remove an efi_debug_image_info entry.
+ *
+ * @image_handle: image handle for the image being removed
+ **/
+void efi_core_remove_debug_image_info_entry(efi_handle_t image_handle)
+{
+ union efi_debug_image_info *table;
+ u32 index;
+
+ efi_m_debug_info_table_header.update_status |=
+ EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ table = efi_m_debug_info_table_header.efi_debug_image_info_table;
+
+ for (index = 0; index < efi_m_max_table_entries; index++) {
+ if (table[index].normal_image &&
+ table[index].normal_image->image_handle == image_handle) {
+ /* Found a match. Free up the table entry.
+ * Move the tail of the table one slot to the front.
+ */
+ efi_free_pool(table[index].normal_image);
+
+ memmove(&table[index],
+ &table[index + 1],
+ (efi_m_debug_info_table_header.table_size -
+ index - 1) * EFI_DEBUG_TABLE_ENTRY_SIZE);
+
+ /* Decrease the number of EFI_DEBUG_IMAGE_INFO
+ * elements and set the efi_m_debug_info_table_header
+ * in modified status.
+ */
+ efi_m_debug_info_table_header.table_size--;
+ table[efi_m_debug_info_table_header.table_size].normal_image =
+ NULL;
+ efi_m_debug_info_table_header.update_status |=
+ EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+ break;
+ }
+ }
+
+ efi_m_debug_info_table_header.update_status &=
+ ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}