Re: [PATCH 1/2 v4] efi: Add ESRT to the EFI system table

2021-02-26 Thread Heinrich Schuchardt
On 23.02.21 17:50, Jose Marinho wrote:
> The ESRT is initialised during efi_init_objlist after
> efi_initialize_system_table().
>
> The ESRT is recreated from scratch at the following events:
> - successful UpdateCapsule;
> - FMP instance install.
>
> The code ensures that every ESRT entry has a unique fw_class value.
>
> Limitations:
> - The ESRT is not updated when an FMP instance is uninstalled;
> - the fields image_type and flags are currently set to UNKNOWN and 0
> respectively. The mapping between fw_class and the image_type/flags
> fields is platform specific. A mapping function is lacking from the
> current implementation but should be added in the future.
>
> Signed-off-by: Jose Marinho 
>
> CC: Heinrich Schuchardt   
> CC: Sughosh Ganu 
> CC: AKASHI Takahiro 
> CC: Ilias Apalodimas 
> CC: Andre Przywara 
> CC: Alexander Graf 
> CC: n...@arm.com
>
> ---
>  cmd/efidebug.c   |   4 +
>  include/efi_api.h|  21 ++
>  include/efi_loader.h |  20 ++
>  lib/efi_loader/Kconfig   |   7 +
>  lib/efi_loader/Makefile  |   1 +
>  lib/efi_loader/efi_capsule.c |   8 +
>  lib/efi_loader/efi_esrt.c| 518 +++
>  lib/efi_loader/efi_setup.c   |   6 +
>  8 files changed, 585 insertions(+)
>  create mode 100644 lib/efi_loader/efi_esrt.c
>
> diff --git a/cmd/efidebug.c b/cmd/efidebug.c
> index bbbcb0a546..a7dace2f80 100644
> --- a/cmd/efidebug.c
> +++ b/cmd/efidebug.c
> @@ -459,6 +459,10 @@ static const struct {
>   "Block IO",
>   EFI_BLOCK_IO_PROTOCOL_GUID,
>   },
> + {
> + "EFI System Resource Table",
> + EFI_SYSTEM_RESOURCE_TABLE_GUID,
> + },
>   {
>   "Simple File System",
>   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
> diff --git a/include/efi_api.h b/include/efi_api.h
> index 48e48a6263..fb53637419 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -1722,6 +1722,23 @@ struct efi_load_file_protocol {
>void *buffer);
>  };
>
> +struct efi_system_resource_entry {
> + efi_guid_t fw_class;
> + u32 fw_type;
> + u32 fw_version;
> + u32 lowest_supported_fw_version;
> + u32 capsule_flags;
> + u32 last_attempt_version;
> + u32 last_attempt_status;
> +} __packed;
> +
> +struct efi_system_resource_table {
> + u32 fw_resource_count;
> + u32 fw_resource_count_max;
> + u64 fw_resource_version;
> + struct efi_system_resource_entry entries[];
> +} __packed;
> +
>  /* Boot manager load options */
>  #define LOAD_OPTION_ACTIVE   0x0001
>  #define LOAD_OPTION_FORCE_RECONNECT  0x0002
> @@ -1740,6 +1757,10 @@ struct efi_load_file_protocol {
>  #define ESRT_FW_TYPE_DEVICEFIRMWARE  0x0002
>  #define ESRT_FW_TYPE_UEFIDRIVER  0x0003
>
> +#define EFI_SYSTEM_RESOURCE_TABLE_GUID\
> + EFI_GUID(0xb122a263, 0x3661, 0x4f68,\
> + 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
> +
>  /* Last Attempt Status Values */
>  #define LAST_ATTEMPT_STATUS_SUCCESS  0x
>  #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL   0x0001
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index f470bbd636..c2720f2823 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -214,6 +214,8 @@ extern const efi_guid_t efi_guid_rng_protocol;
>  extern const efi_guid_t efi_guid_capsule_report;
>  /* GUID of firmware management protocol */
>  extern const efi_guid_t efi_guid_firmware_management_protocol;
> +/* GUID for the ESRT */
> +extern const efi_guid_t efi_esrt_guid;
>
>  extern unsigned int __efi_runtime_start, __efi_runtime_stop;
>  extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
> @@ -884,4 +886,22 @@ static inline efi_status_t efi_launch_capsules(void)
>
>  #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
>
> +/**
> + * Install the ESRT system table.
> + *
> + * @return   status code
> + */
> +efi_status_t efi_esrt_register(void);
> +
> +/**
> + * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
> + * present in the system.
> + * If an ESRT already exists, the old ESRT is replaced in the system table.
> + * The memory of the old ESRT is deallocated.
> + *
> + * Return:
> + * - EFI_SUCCESS if the ESRT is correctly created
> + * - error code otherwise.
> + */
> +efi_status_t efi_esrt_populate(void);
>  #endif /* _EFI_LOADER_H */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index e729f727df..a96014ce18 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -347,4 +347,11 @@ config EFI_SECURE_BOOT
> it is signed with a trusted key. To do that, you need to install,
> at least, PK, KEK and db.
>
> +config EFI_ESRT
> + bool "Enable the UEFI ESRT generation"
> + depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> + default y
> + help
> +   Enabling this option creates the ESRT UEFI system table.
> +
>  end

[PATCH 1/2 v4] efi: Add ESRT to the EFI system table

2021-02-23 Thread Jose Marinho
The ESRT is initialised during efi_init_objlist after
efi_initialize_system_table().

The ESRT is recreated from scratch at the following events:
- successful UpdateCapsule;
- FMP instance install.

The code ensures that every ESRT entry has a unique fw_class value.

Limitations:
- The ESRT is not updated when an FMP instance is uninstalled;
- the fields image_type and flags are currently set to UNKNOWN and 0
respectively. The mapping between fw_class and the image_type/flags
fields is platform specific. A mapping function is lacking from the
current implementation but should be added in the future.

Signed-off-by: Jose Marinho 

CC: Heinrich Schuchardt 
CC: Sughosh Ganu 
CC: AKASHI Takahiro 
CC: Ilias Apalodimas 
CC: Andre Przywara 
CC: Alexander Graf 
CC: n...@arm.com

---
 cmd/efidebug.c   |   4 +
 include/efi_api.h|  21 ++
 include/efi_loader.h |  20 ++
 lib/efi_loader/Kconfig   |   7 +
 lib/efi_loader/Makefile  |   1 +
 lib/efi_loader/efi_capsule.c |   8 +
 lib/efi_loader/efi_esrt.c| 518 +++
 lib/efi_loader/efi_setup.c   |   6 +
 8 files changed, 585 insertions(+)
 create mode 100644 lib/efi_loader/efi_esrt.c

diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index bbbcb0a546..a7dace2f80 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -459,6 +459,10 @@ static const struct {
"Block IO",
EFI_BLOCK_IO_PROTOCOL_GUID,
},
+   {
+   "EFI System Resource Table",
+   EFI_SYSTEM_RESOURCE_TABLE_GUID,
+   },
{
"Simple File System",
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
diff --git a/include/efi_api.h b/include/efi_api.h
index 48e48a6263..fb53637419 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1722,6 +1722,23 @@ struct efi_load_file_protocol {
 void *buffer);
 };
 
+struct efi_system_resource_entry {
+   efi_guid_t fw_class;
+   u32 fw_type;
+   u32 fw_version;
+   u32 lowest_supported_fw_version;
+   u32 capsule_flags;
+   u32 last_attempt_version;
+   u32 last_attempt_status;
+} __packed;
+
+struct efi_system_resource_table {
+   u32 fw_resource_count;
+   u32 fw_resource_count_max;
+   u64 fw_resource_version;
+   struct efi_system_resource_entry entries[];
+} __packed;
+
 /* Boot manager load options */
 #define LOAD_OPTION_ACTIVE 0x0001
 #define LOAD_OPTION_FORCE_RECONNECT0x0002
@@ -1740,6 +1757,10 @@ struct efi_load_file_protocol {
 #define ESRT_FW_TYPE_DEVICEFIRMWARE0x0002
 #define ESRT_FW_TYPE_UEFIDRIVER0x0003
 
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID\
+   EFI_GUID(0xb122a263, 0x3661, 0x4f68,\
+   0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
+
 /* Last Attempt Status Values */
 #define LAST_ATTEMPT_STATUS_SUCCESS0x
 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL 0x0001
diff --git a/include/efi_loader.h b/include/efi_loader.h
index f470bbd636..c2720f2823 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -214,6 +214,8 @@ extern const efi_guid_t efi_guid_rng_protocol;
 extern const efi_guid_t efi_guid_capsule_report;
 /* GUID of firmware management protocol */
 extern const efi_guid_t efi_guid_firmware_management_protocol;
+/* GUID for the ESRT */
+extern const efi_guid_t efi_esrt_guid;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -884,4 +886,22 @@ static inline efi_status_t efi_launch_capsules(void)
 
 #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
+/**
+ * Install the ESRT system table.
+ *
+ * @return status code
+ */
+efi_status_t efi_esrt_register(void);
+
+/**
+ * efi_esrt_populate() - Populates the ESRT entries from the FMP instances
+ * present in the system.
+ * If an ESRT already exists, the old ESRT is replaced in the system table.
+ * The memory of the old ESRT is deallocated.
+ *
+ * Return:
+ * - EFI_SUCCESS if the ESRT is correctly created
+ * - error code otherwise.
+ */
+efi_status_t efi_esrt_populate(void);
 #endif /* _EFI_LOADER_H */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e729f727df..a96014ce18 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -347,4 +347,11 @@ config EFI_SECURE_BOOT
  it is signed with a trusted key. To do that, you need to install,
  at least, PK, KEK and db.
 
+config EFI_ESRT
+   bool "Enable the UEFI ESRT generation"
+   depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+   default y
+   help
+ Enabling this option creates the ESRT UEFI system table.
+
 endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 10b42e8847..9a8127846f 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -52,6 +52,7 @@ obj-y += efi_variable.o
 obj-$(CONFIG_EFI_VARIABLES_PRESEED) += ef