Re: [RFC 08/14] efi_loader: capsule: support firmware update

2020-03-18 Thread Sughosh Ganu
On Tue, 17 Mar 2020 at 07:42, AKASHI Takahiro 
wrote:

> A capsule tagged with the guid, EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID,
> is handled as a firmware update object.
> What efi_update_capsule() basically does is to load any firmware management
> protocol (or fmp) drivers contained in a capsule, find out an appropriate
> fmp driver and then invoke its set_image() interface against each binary
> in a capsule.
> In this commit, however, installing drivers is not supported yet.
>
> The result of applying a capsule is set to be stored in "Capsule"
> variable, but its implementation is deferred to a fmp driver.
>
> Signed-off-by: AKASHI Takahiro 
> ---
>  include/efi_api.h| 127 +++
>  lib/efi_loader/Kconfig   |  12 +++
>  lib/efi_loader/efi_capsule.c | 165 +++
>  lib/efi_loader/efi_setup.c   |   4 +
>  4 files changed, 308 insertions(+)
>




> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
> index f3e2a555a6b9..f3526beed681 100644
> --- a/lib/efi_loader/efi_capsule.c
> +++ b/lib/efi_loader/efi_capsule.c
> @@ -14,10 +14,164 @@
>  #include 
>




>  /*
>   * Launch a capsule
>   */
> @@ -54,6 +208,17 @@ efi_status_t EFIAPI efi_update_capsule(
> ret = EFI_SUCCESS;
> for (i = 0, capsule = *capsule_header_array; i < capsule_count;
>  i++, capsule = *(++capsule_header_array)) {
> +   EFI_PRINT("EFI Capsule (guid:%pUl)\n",
> >capsule_guid);
> +   if (!guidcmp(>capsule_guid,
> +_guid_firmware_management_capsule_id))
> +   ret  = efi_capsule_update_firmware(
> +   (struct
> efi_firmware_management_capsule_header *)
> +   ((void *)capsule +
> sizeof(*capsule)));
>

Instead of sizeof(*capsule), please use header_size member of
efi_capsule_header. The spec mentions that the size of the capsule header
might be larger than the capsule header structure. Moreover, when testing
with a capsule built from the edk2 capsule generation script, i do see that
the header_size is greater than sizeof(efi_capsule_header).

-sughosh


[RFC 08/14] efi_loader: capsule: support firmware update

2020-03-16 Thread AKASHI Takahiro
A capsule tagged with the guid, EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID,
is handled as a firmware update object.
What efi_update_capsule() basically does is to load any firmware management
protocol (or fmp) drivers contained in a capsule, find out an appropriate
fmp driver and then invoke its set_image() interface against each binary
in a capsule.
In this commit, however, installing drivers is not supported yet.

The result of applying a capsule is set to be stored in "Capsule"
variable, but its implementation is deferred to a fmp driver.

Signed-off-by: AKASHI Takahiro 
---
 include/efi_api.h| 127 +++
 lib/efi_loader/Kconfig   |  12 +++
 lib/efi_loader/efi_capsule.c | 165 +++
 lib/efi_loader/efi_setup.c   |   4 +
 4 files changed, 308 insertions(+)

diff --git a/include/efi_api.h b/include/efi_api.h
index b7bf21cac7ad..e103369186a2 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -225,6 +225,10 @@ enum efi_reset_type {
EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \
 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72)
 
+#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \
+   EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \
+0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a)
+
 struct efi_capsule_header {
efi_guid_t capsule_guid;
u32 header_size;
@@ -253,6 +257,32 @@ struct efi_memory_range_capsule {
struct efi_memory_range memory_ranges[];
 } __packed;
 
+struct efi_firmware_management_capsule_header {
+   u32 version;
+   u16 embedded_driver_count;
+   u16 payload_item_count;
+   u64 item_offset_list[];
+} __packed;
+
+struct efi_firmware_management_capsule_image_header {
+   u32 version;
+   efi_guid_t update_image_type_id;
+   u8 update_image_index;
+   u8 reserved[3];
+   u32 update_image_size;
+   u32 update_vendor_code_size;
+   u64 update_hardware_instance;
+} __packed;
+
+struct efi_capsule_result_variable_fmp {
+   u16 version;
+   u8 payload_index;
+   u8 update_image_index;
+   efi_guid_t update_image_type_id;
+   // u16 capsule_file_name[];
+   // u16 capsule_target[];
+} __packed;
+
 #define EFI_RT_SUPPORTED_GET_TIME  0x0001
 #define EFI_RT_SUPPORTED_SET_TIME  0x0002
 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME   0x0004
@@ -1683,4 +1713,101 @@ struct efi_unicode_collation_protocol {
 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x1000
 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x4000
 
+/*
+ * Firmware management protocol
+ */
+#define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \
+   EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \
+0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7)
+
+#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID \
+   EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \
+0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47)
+
+#define EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE0x1
+#define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED 0x2
+#define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED0x4
+#define EFI_IMAGE_ATTRIBUTE_IN_USE 0x8
+#define EFI_IMAGE_ATTRIBUTE_UEFI_IMAGE 0x10
+
+#define EFI_IMAGE_COMPATIBILITY_CHECK_SUPPORTED0x1
+#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION  4
+
+#define EFI_IMAGE_UPDATABLE_VALID  0x1
+#define EFI_IMAGE_UPDATABLE_INVALID0x2
+#define EFI_IMAGE_UPDATABLE_INVALID_TYPE   0x4
+#define EFI_IMAGE_UPDATABLE_INVALID_OLLD   0x8
+#define EFI_IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE 0x10
+
+#define EFI_PACKAGE_ATTRIBUTE_VERSION_UPDATABLE0x1
+#define EFI_PACKAGE_ATTRIBUTE_RESET_REQUIRED   0x2
+#define EFI_PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED  0x4
+
+typedef struct efi_firmware_image_dependencies {
+   u8 dependencies[0];
+} efi_fmp_dep_t;
+
+struct efi_firmware_image_descriptor {
+   u8 image_index;
+   efi_guid_t image_type_id;
+   u64 image_id;
+   u16 *image_id_name;
+   u32 version;
+   u16 *version_name;
+   efi_uintn_t size;
+   u64 attributes_supported;
+   u64 attributes_setting;
+   u64 compatibilities;
+   u32 lowest_supported_image_version;
+   u32 last_attempt_version;
+   u32 last_attempt_status;
+   u64 hardware_instance;
+   efi_fmp_dep_t *dependencies;
+};
+
+struct efi_firmware_management_protocol {
+   efi_status_t (EFIAPI *get_image_info)(
+   struct efi_firmware_management_protocol *this,
+   efi_uintn_t *image_info_size,
+   struct efi_firmware_image_descriptor *image_info,
+   u32 *descriptor_version,
+   u8 *descriptor_count,
+   efi_uintn_t *descriptor_size,
+   u32