On 07.01.25 14:30, Ilias Apalodimas wrote:
On Thu, 2 Jan 2025 at 20:11, Heinrich Schuchardt
<[email protected]> wrote:

The debug version of the UEFI shell requires a DXE services table to exist.

Implement the table and let all DXE functions return EFI_UNSUPPORTED.

Signed-off-by: Heinrich Schuchardt <[email protected]>
---
  include/efi_dxe.h          |  54 ++++++++++++
  include/efi_loader.h       |   7 ++
  lib/efi_loader/Kconfig     |   7 ++
  lib/efi_loader/Makefile    |   1 +
  lib/efi_loader/efi_dxe.c   | 176 +++++++++++++++++++++++++++++++++++++
  lib/efi_loader/efi_setup.c |   6 ++
  6 files changed, 251 insertions(+)
  create mode 100644 include/efi_dxe.h
  create mode 100644 lib/efi_loader/efi_dxe.c

diff --git a/include/efi_dxe.h b/include/efi_dxe.h
new file mode 100644
index 00000000000..5623189de0c
--- /dev/null
+++ b/include/efi_dxe.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *  DXE services table
+ *
+ *  Copyright (c) 2025 Heinrich Schuchardt
+ */
+
+#ifndef _EFI_DXE_H
+#define _EFI_DXE_H 1
+
+#include <efi.h>
+
+/**
+ * define DXE_SERVICES_SIGNATURE - DXE services signature ('DXE_SERV')
+ */
+#define DXE_SERVICES_SIGNATURE 0x565245535f455844
+/**
+ * define DXE_SERVICES_REVISION - DXE services revision (1.8)
+ */
+#define DXE_SERVICES_REVISION 0x00010050
+
+/**
+ * define EFI_DXE_SERVICES_TABLE_GUID - GUID of the EFI DXE services table
+ */
+#define EFI_DXE_SERVICES_TABLE_GUID \
+       EFI_GUID(0x5ad34ba, 0x6f02, 0x4214, \
+                0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9)
+
+struct efi_dxe_services {
+       struct efi_table_hdr hdr;
+
+       efi_status_t (EFIAPI *add_memory_space)(void);
+       efi_status_t (EFIAPI *allocate_memory_space)(void);
+       efi_status_t (EFIAPI *free_memory_space)(void);
+       efi_status_t (EFIAPI *remove_memory_space)(void);
+       efi_status_t (EFIAPI *get_memory_space_descriptor)(void);
+       efi_status_t (EFIAPI *set_memory_space_attributes)(void);
+       efi_status_t (EFIAPI *get_memory_space_map)(void);
+       efi_status_t (EFIAPI *add_io_space)(void);
+       efi_status_t (EFIAPI *allocate_io_space)(void);
+       efi_status_t (EFIAPI *free_io_space)(void);
+       efi_status_t (EFIAPI *remove_io_space)(void);
+       efi_status_t (EFIAPI *get_io_space_descriptor)(void);
+       efi_status_t (EFIAPI *get_io_space_map)(void);
+       efi_status_t (EFIAPI *dispatch)(void);
+       efi_status_t (EFIAPI *schedule)(void);
+       efi_status_t (EFIAPI *trust)(void);
+       efi_status_t (EFIAPI *process_firmware_volume)(void);
+       efi_status_t (EFIAPI *set_memory_space_capabilities)(void);
+};
+
+extern efi_guid_t efi_dxe_services_table_guid;
+
+#endif /* _EFI_DXE_H */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index c1258098217..d474866184f 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -663,6 +663,13 @@ efi_status_t efi_smbios_register(void);
   */
  efi_status_t efi_hob_list_register(void);

+/**
+ * efi_dxe_services_register() - install DXE services table
+ *
+ * Return:     status code
+ */
+efi_status_t efi_dxe_services_register(void);
+
  struct efi_simple_file_system_protocol *
  efi_fs_from_path(struct efi_device_path *fp);

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ec38a0ea352..ed3470508ff 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -384,6 +384,13 @@ config EFI_DT_FIXUP
           The EFI device-tree fix-up protocol provides a function to let the
           firmware apply fix-ups. This may be used by boot loaders.

+config EFI_DXE
+       bool 'DXE services table'
+       default y
+       help
+         Install the DXE services table. The debug version of the UEFI shell
+         requires it.
+
  config EFI_LOADER_HII
         bool "HII protocols"
         default y
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 195ed8667fe..4f250f21811 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -33,6 +33,7 @@ obj-y += efi_console.o
  obj-y += efi_device_path.o
  obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
  obj-$(CONFIG_EFI_DEVICE_PATH_UTIL) += efi_device_path_utilities.o
+obj-$(CONFIG_EFI_DXE) += efi_dxe.o
  obj-y += efi_dt_fixup.o
  obj-y += efi_fdt.o
  obj-y += efi_file.o
diff --git a/lib/efi_loader/efi_dxe.c b/lib/efi_loader/efi_dxe.c
new file mode 100644
index 00000000000..f8920575b0c
--- /dev/null
+++ b/lib/efi_loader/efi_dxe.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  DXE services table
+ *
+ *  Copyright (c) 2025 Heinrich Schuchardt
+ */
+
+#include <efi_dxe.h>
+#include <efi_loader.h>
+
+efi_guid_t efi_dxe_services_table_guid = EFI_DXE_SERVICES_TABLE_GUID;
+
+static efi_status_t EFIAPI add_memory_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI allocate_memory_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI free_memory_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI remove_memory_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI get_memory_space_descriptor(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI set_memory_space_attributes(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI get_memory_space_map(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI add_io_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI allocate_io_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI free_io_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI remove_io_space(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI get_io_space_descriptor(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI get_io_space_map(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI dispatch(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI schedule(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI trust(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI process_firmware_volume(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI set_memory_space_capabilities(void)
+{
+       EFI_ENTRY();
+
+       return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static struct efi_dxe_services efi_dxe_services = {
+       .hdr = {
+               .signature = DXE_SERVICES_SIGNATURE,
+               .revision = DXE_SERVICES_REVISION,
+               .headersize = sizeof(struct efi_dxe_services),
+       },
+       .add_memory_space = add_memory_space,
+       .allocate_memory_space = allocate_memory_space,
+       .free_memory_space = free_memory_space,
+       .remove_memory_space = remove_memory_space,
+       .get_memory_space_descriptor = get_memory_space_descriptor,
+       .set_memory_space_attributes = set_memory_space_attributes,
+       .get_memory_space_map = get_memory_space_map,
+       .add_io_space = add_io_space,
+       .allocate_io_space = allocate_io_space,
+       .free_io_space = free_io_space,
+       .remove_io_space = remove_io_space,
+       .get_io_space_descriptor = get_io_space_descriptor,
+       .get_io_space_map = get_io_space_map,
+       .dispatch = dispatch,
+       .schedule = schedule,
+       .trust = trust,
+       .process_firmware_volume = process_firmware_volume,
+       .set_memory_space_capabilities = set_memory_space_capabilities,

Do we plan on ever implementing those? If not we could use a single
function returning EFI_UNSUPPORTED instead of all of them for code
size reasons

Currently I don't plan to implement these. But I wanted to be able to add

    #define _DEBUG 1

to find out which of the functions is possibly used.

On x86 and sandbox I don't think our memory restrictions are very tight.

Best regards

Heinrich


Cheers
/Ilias
+};
+
+efi_status_t efi_dxe_services_register(void)
+{
+       struct efi_dxe_services *dxe;
+
+       dxe = efi_alloc(sizeof(struct efi_dxe_services));
+       if (!dxe)
+               return EFI_OUT_OF_RESOURCES;
+
+       memcpy(dxe, &efi_dxe_services, sizeof(struct efi_dxe_services));
+
+       return efi_install_configuration_table(&efi_dxe_services_table_guid, 
dxe);
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 393b690c3ee..796da5d5678 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -260,6 +260,12 @@ efi_status_t efi_init_obj_list(void)
         if (ret != EFI_SUCCESS)
                 goto out;

+       if (IS_ENABLED(CONFIG_EFI_DXE)) {
+               ret = efi_dxe_services_register();
+               if (ret != EFI_SUCCESS)
+                       goto out;
+       }
+
         if (IS_ENABLED(CONFIG_EFI_ECPT)) {
                 ret = efi_ecpt_register();
                 if (ret != EFI_SUCCESS)
--
2.47.1


Reply via email to