diff mbox series

[RESEND,RFC,07/10] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor

Message ID 20211125071302.3644-8-sughosh.ganu@linaro.org
State New
Headers show
Series FWU: Add support for FWU Multi Bank Update feature | expand

Commit Message

Sughosh Ganu Nov. 25, 2021, 7:12 a.m. UTC
The FWU Multi Banks Update feature allows updating different types of
updatable firmware images on the platform. These image types are
identified using the ImageTypeId GUID value. Add support in the
GetImageInfo function of the FMP protocol to get the GUID values for
the individual images and populate these in the image descriptor for
the corresponding images.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
 lib/efi_loader/efi_firmware.c | 76 ++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 5 deletions(-)

Comments

Heinrich Schuchardt Nov. 26, 2021, 12:43 p.m. UTC | #1
On 11/25/21 08:12, Sughosh Ganu wrote:
> The FWU Multi Banks Update feature allows updating different types of
> updatable firmware images on the platform. These image types are
> identified using the ImageTypeId GUID value. Add support in the
> GetImageInfo function of the FMP protocol to get the GUID values for
> the individual images and populate these in the image descriptor for
> the corresponding images.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>   lib/efi_loader/efi_firmware.c | 76 ++++++++++++++++++++++++++++++++---
>   1 file changed, 71 insertions(+), 5 deletions(-)
>
> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> index a1b88dbfc2..a2b639b448 100644
> --- a/lib/efi_loader/efi_firmware.c
> +++ b/lib/efi_loader/efi_firmware.c
> @@ -10,6 +10,7 @@
>   #include <charset.h>
>   #include <dfu.h>
>   #include <efi_loader.h>
> +#include <fwu_metadata.h>
>   #include <image.h>
>   #include <signatures.h>
>
> @@ -106,7 +107,8 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
>    * @descriptor_size:		Pointer to descriptor size
>    * package_version:		Package version
>    * package_version_name:	Package version's name
> - * image_type:			Image type GUID
> + * guid_array:			Image type GUID array
> + * nparts:			Number of partions on the storage device
>    *
>    * Return information bout the current firmware image in @image_info.
>    * @image_info will consist of a number of descriptors.
> @@ -122,7 +124,7 @@ static efi_status_t efi_get_dfu_info(
>   	efi_uintn_t *descriptor_size,
>   	u32 *package_version,
>   	u16 **package_version_name,
> -	const efi_guid_t *image_type)
> +	const efi_guid_t *guid_array, u32 nparts)
>   {
>   	struct dfu_entity *dfu;
>   	size_t names_len, total_size;
> @@ -145,6 +147,19 @@ static efi_status_t efi_get_dfu_info(
>   		return EFI_SUCCESS;
>   	}
>
> +	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {

The concept of multiple banks is not related to the concept of multiple
GUIDs. So this if statement should be removed.

> +		/*
> +		 * For FWU multi bank updates, the number of partitions
> +		 * should at least be same as dfu partitions or less
> +		 */
> +		if (nparts > dfu_num) {
> +			log_err("Number of dfu alt no's less than partitions\n");
> +			dfu_free_entities();
> +
> +			return EFI_INVALID_PARAMETER;
> +		}
> +	}
> +
>   	total_size = sizeof(*image_info) * dfu_num + names_len;
>   	/*
>   	 * we will assume that sizeof(*image_info) * dfu_name
> @@ -172,7 +187,11 @@ static efi_status_t efi_get_dfu_info(
>   	next = name;
>   	list_for_each_entry(dfu, &dfu_list, list) {
>   		image_info[i].image_index = dfu->alt + 1;
> -		image_info[i].image_type_id = *image_type;
> +		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))

The number of GUIDs is not related to the number of banks.
Please, remove this test.

> +			image_info[i].image_type_id = guid_array[i];

The sequence of GUIDs in a capsule should not influence the update. The
design lacks a configuration defining which GUID maps to which DFU part.

Please, get rid of all DFU environment variables and describe the update
in a configuration file that you add to the capsule.

> +		else
> +			image_info[i].image_type_id = *guid_array;

Do you want to write the same image to multiple places? Why?

Best regards

Heirnich

> +
>   		image_info[i].image_id = dfu->alt;
>
>   		/* copy the DFU entity name */
> @@ -249,7 +268,9 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
>   	u32 *package_version,
>   	u16 **package_version_name)
>   {
> +	u32 nparts;
>   	efi_status_t ret;
> +	efi_guid_t *part_guid_arr;
>
>   	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
>   		  image_info_size, image_info,
> @@ -264,12 +285,24 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
>   	     !descriptor_size || !package_version || !package_version_name))
>   		return EFI_EXIT(EFI_INVALID_PARAMETER);
>
> +	part_guid_arr = malloc(sizeof(efi_guid_t));
> +	if (!part_guid_arr) {
> +		log_err("Unable to allocate memory for guid array\n");
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +
> +	guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_fit);
> +	nparts = 1;
> +
>   	ret = efi_get_dfu_info(image_info_size, image_info,
>   			       descriptor_version, descriptor_count,
>   			       descriptor_size,
>   			       package_version, package_version_name,
> -			       &efi_firmware_image_type_uboot_fit);
> +			       part_guid_arr, nparts);
>
> +out:
> +	free(part_guid_arr);
>   	return EFI_EXIT(ret);
>   }
>
> @@ -358,7 +391,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>   	u32 *package_version,
>   	u16 **package_version_name)
>   {
> +	u32 nparts;
> +	int status;
>   	efi_status_t ret = EFI_SUCCESS;
> +	efi_guid_t *part_guid_arr;
>
>   	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
>   		  image_info_size, image_info,
> @@ -373,12 +409,42 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>   	     !descriptor_size || !package_version || !package_version_name))
>   		return EFI_EXIT(EFI_INVALID_PARAMETER);
>
> +	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> +		/*
> +		 * Read the ImageType GUID values. Populate the guid array
> +		 * with thesevalues. These are the values to be used in the
> +		 * capsule for ImageTypeId.
> +		 */
> +		status = fwu_fill_partition_guid_array(&part_guid_arr,
> +						       &nparts);
> +		if (status < 0) {
> +			log_err("Unable to get partiion guid's\n");
> +			if (status == -EIO)
> +				ret = EFI_DEVICE_ERROR;
> +			else if (status == -ENOMEM)
> +				ret = EFI_OUT_OF_RESOURCES;
> +			goto out;
> +		}
> +	} else {
> +		part_guid_arr = malloc(sizeof(efi_guid_t));
> +		if (!part_guid_arr) {
> +			log_err("Unable to allocate memory for guid array\n");
> +			ret = EFI_OUT_OF_RESOURCES;
> +			goto out;
> +		}
> +
> +		guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_raw);
> +		nparts = 1;
> +	}
> +
>   	ret = efi_get_dfu_info(image_info_size, image_info,
>   			       descriptor_version, descriptor_count,
>   			       descriptor_size,
>   			       package_version, package_version_name,
> -			       &efi_firmware_image_type_uboot_raw);
> +			       part_guid_arr, nparts);
>
> +out:
> +	free(part_guid_arr);
>   	return EFI_EXIT(ret);
>   }
>
>
Sughosh Ganu Nov. 29, 2021, 11:38 a.m. UTC | #2
hi Heinrich,
Thanks for taking up the review.

On Fri, 26 Nov 2021 at 18:18, Heinrich Schuchardt <xypron.glpk@gmx.de>
wrote:

> On 11/25/21 08:12, Sughosh Ganu wrote:
> > The FWU Multi Banks Update feature allows updating different types of
> > updatable firmware images on the platform. These image types are
> > identified using the ImageTypeId GUID value. Add support in the
> > GetImageInfo function of the FMP protocol to get the GUID values for
> > the individual images and populate these in the image descriptor for
> > the corresponding images.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >   lib/efi_loader/efi_firmware.c | 76 ++++++++++++++++++++++++++++++++---
> >   1 file changed, 71 insertions(+), 5 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_firmware.c
> b/lib/efi_loader/efi_firmware.c
> > index a1b88dbfc2..a2b639b448 100644
> > --- a/lib/efi_loader/efi_firmware.c
> > +++ b/lib/efi_loader/efi_firmware.c
> > @@ -10,6 +10,7 @@
> >   #include <charset.h>
> >   #include <dfu.h>
> >   #include <efi_loader.h>
> > +#include <fwu_metadata.h>
> >   #include <image.h>
> >   #include <signatures.h>
> >
> > @@ -106,7 +107,8 @@ efi_status_t EFIAPI
> efi_firmware_set_package_info_unsupported(
> >    * @descriptor_size:                Pointer to descriptor size
> >    * package_version:         Package version
> >    * package_version_name:    Package version's name
> > - * image_type:                       Image type GUID
> > + * guid_array:                       Image type GUID array
> > + * nparts:                   Number of partions on the storage device
> >    *
> >    * Return information bout the current firmware image in @image_info.
> >    * @image_info will consist of a number of descriptors.
> > @@ -122,7 +124,7 @@ static efi_status_t efi_get_dfu_info(
> >       efi_uintn_t *descriptor_size,
> >       u32 *package_version,
> >       u16 **package_version_name,
> > -     const efi_guid_t *image_type)
> > +     const efi_guid_t *guid_array, u32 nparts)
> >   {
> >       struct dfu_entity *dfu;
> >       size_t names_len, total_size;
> > @@ -145,6 +147,19 @@ static efi_status_t efi_get_dfu_info(
> >               return EFI_SUCCESS;
> >       }
> >
> > +     if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
>
> The concept of multiple banks is not related to the concept of multiple
> GUIDs. So this if statement should be removed.


Okay. Will make the change.


>


> > +             /*
> > +              * For FWU multi bank updates, the number of partitions
> > +              * should at least be same as dfu partitions or less
> > +              */
> > +             if (nparts > dfu_num) {
> > +                     log_err("Number of dfu alt no's less than
> partitions\n");
> > +                     dfu_free_entities();
> > +
> > +                     return EFI_INVALID_PARAMETER;
> > +             }
> > +     }
> > +
> >       total_size = sizeof(*image_info) * dfu_num + names_len;
> >       /*
> >        * we will assume that sizeof(*image_info) * dfu_name
> > @@ -172,7 +187,11 @@ static efi_status_t efi_get_dfu_info(
> >       next = name;
> >       list_for_each_entry(dfu, &dfu_list, list) {
> >               image_info[i].image_index = dfu->alt + 1;
> > -             image_info[i].image_type_id = *image_type;
> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
>
> The number of GUIDs is not related to the number of banks.
> Please, remove this test.
>

Okay, will make it common, as you suggest.


>
> > +                     image_info[i].image_type_id = guid_array[i];
>
> The sequence of GUIDs in a capsule should not influence the update. The
> design lacks a configuration defining which GUID maps to which DFU part.
>
> Please, get rid of all DFU environment variables and describe the update
> in a configuration file that you add to the capsule.
>

Like we discussed, the information on the update, like the device,
partition number etc cannot be stored as part of the capsule header
currently. So, for now, we have to make do with using the dfu variables for
this.


> > +             else
> > +                     image_info[i].image_type_id = *guid_array;
>
> Do you want to write the same image to multiple places? Why?
>

I was keeping the logic consistent with the way it is currently. This will
go away as the explicit check for CONFIG_FWU_MULTI_BANK_UPDATE is removed
based on your comment above.

-sughosh


> Best regards
>
> Heirnich
>
> > +
> >               image_info[i].image_id = dfu->alt;
> >
> >               /* copy the DFU entity name */
> > @@ -249,7 +268,9 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> >       u32 *package_version,
> >       u16 **package_version_name)
> >   {
> > +     u32 nparts;
> >       efi_status_t ret;
> > +     efi_guid_t *part_guid_arr;
> >
> >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> >                 image_info_size, image_info,
> > @@ -264,12 +285,24 @@ efi_status_t EFIAPI
> efi_firmware_fit_get_image_info(
> >            !descriptor_size || !package_version ||
> !package_version_name))
> >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> >
> > +     part_guid_arr = malloc(sizeof(efi_guid_t));
> > +     if (!part_guid_arr) {
> > +             log_err("Unable to allocate memory for guid array\n");
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_fit);
> > +     nparts = 1;
> > +
> >       ret = efi_get_dfu_info(image_info_size, image_info,
> >                              descriptor_version, descriptor_count,
> >                              descriptor_size,
> >                              package_version, package_version_name,
> > -                            &efi_firmware_image_type_uboot_fit);
> > +                            part_guid_arr, nparts);
> >
> > +out:
> > +     free(part_guid_arr);
> >       return EFI_EXIT(ret);
> >   }
> >
> > @@ -358,7 +391,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> >       u32 *package_version,
> >       u16 **package_version_name)
> >   {
> > +     u32 nparts;
> > +     int status;
> >       efi_status_t ret = EFI_SUCCESS;
> > +     efi_guid_t *part_guid_arr;
> >
> >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> >                 image_info_size, image_info,
> > @@ -373,12 +409,42 @@ efi_status_t EFIAPI
> efi_firmware_raw_get_image_info(
> >            !descriptor_size || !package_version ||
> !package_version_name))
> >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> >
> > +     if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > +             /*
> > +              * Read the ImageType GUID values. Populate the guid array
> > +              * with thesevalues. These are the values to be used in the
> > +              * capsule for ImageTypeId.
> > +              */
> > +             status = fwu_fill_partition_guid_array(&part_guid_arr,
> > +                                                    &nparts);
> > +             if (status < 0) {
> > +                     log_err("Unable to get partiion guid's\n");
> > +                     if (status == -EIO)
> > +                             ret = EFI_DEVICE_ERROR;
> > +                     else if (status == -ENOMEM)
> > +                             ret = EFI_OUT_OF_RESOURCES;
> > +                     goto out;
> > +             }
> > +     } else {
> > +             part_guid_arr = malloc(sizeof(efi_guid_t));
> > +             if (!part_guid_arr) {
> > +                     log_err("Unable to allocate memory for guid
> array\n");
> > +                     ret = EFI_OUT_OF_RESOURCES;
> > +                     goto out;
> > +             }
> > +
> > +             guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_raw);
> > +             nparts = 1;
> > +     }
> > +
> >       ret = efi_get_dfu_info(image_info_size, image_info,
> >                              descriptor_version, descriptor_count,
> >                              descriptor_size,
> >                              package_version, package_version_name,
> > -                            &efi_firmware_image_type_uboot_raw);
> > +                            part_guid_arr, nparts);
> >
> > +out:
> > +     free(part_guid_arr);
> >       return EFI_EXIT(ret);
> >   }
> >
> >
>
>
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index a1b88dbfc2..a2b639b448 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -10,6 +10,7 @@ 
 #include <charset.h>
 #include <dfu.h>
 #include <efi_loader.h>
+#include <fwu_metadata.h>
 #include <image.h>
 #include <signatures.h>
 
@@ -106,7 +107,8 @@  efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
  * @descriptor_size:		Pointer to descriptor size
  * package_version:		Package version
  * package_version_name:	Package version's name
- * image_type:			Image type GUID
+ * guid_array:			Image type GUID array
+ * nparts:			Number of partions on the storage device
  *
  * Return information bout the current firmware image in @image_info.
  * @image_info will consist of a number of descriptors.
@@ -122,7 +124,7 @@  static efi_status_t efi_get_dfu_info(
 	efi_uintn_t *descriptor_size,
 	u32 *package_version,
 	u16 **package_version_name,
-	const efi_guid_t *image_type)
+	const efi_guid_t *guid_array, u32 nparts)
 {
 	struct dfu_entity *dfu;
 	size_t names_len, total_size;
@@ -145,6 +147,19 @@  static efi_status_t efi_get_dfu_info(
 		return EFI_SUCCESS;
 	}
 
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		/*
+		 * For FWU multi bank updates, the number of partitions
+		 * should at least be same as dfu partitions or less
+		 */
+		if (nparts > dfu_num) {
+			log_err("Number of dfu alt no's less than partitions\n");
+			dfu_free_entities();
+
+			return EFI_INVALID_PARAMETER;
+		}
+	}
+
 	total_size = sizeof(*image_info) * dfu_num + names_len;
 	/*
 	 * we will assume that sizeof(*image_info) * dfu_name
@@ -172,7 +187,11 @@  static efi_status_t efi_get_dfu_info(
 	next = name;
 	list_for_each_entry(dfu, &dfu_list, list) {
 		image_info[i].image_index = dfu->alt + 1;
-		image_info[i].image_type_id = *image_type;
+		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
+			image_info[i].image_type_id = guid_array[i];
+		else
+			image_info[i].image_type_id = *guid_array;
+
 		image_info[i].image_id = dfu->alt;
 
 		/* copy the DFU entity name */
@@ -249,7 +268,9 @@  efi_status_t EFIAPI efi_firmware_fit_get_image_info(
 	u32 *package_version,
 	u16 **package_version_name)
 {
+	u32 nparts;
 	efi_status_t ret;
+	efi_guid_t *part_guid_arr;
 
 	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
 		  image_info_size, image_info,
@@ -264,12 +285,24 @@  efi_status_t EFIAPI efi_firmware_fit_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	part_guid_arr = malloc(sizeof(efi_guid_t));
+	if (!part_guid_arr) {
+		log_err("Unable to allocate memory for guid array\n");
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_fit);
+	nparts = 1;
+
 	ret = efi_get_dfu_info(image_info_size, image_info,
 			       descriptor_version, descriptor_count,
 			       descriptor_size,
 			       package_version, package_version_name,
-			       &efi_firmware_image_type_uboot_fit);
+			       part_guid_arr, nparts);
 
+out:
+	free(part_guid_arr);
 	return EFI_EXIT(ret);
 }
 
@@ -358,7 +391,10 @@  efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	u32 *package_version,
 	u16 **package_version_name)
 {
+	u32 nparts;
+	int status;
 	efi_status_t ret = EFI_SUCCESS;
+	efi_guid_t *part_guid_arr;
 
 	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
 		  image_info_size, image_info,
@@ -373,12 +409,42 @@  efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		/*
+		 * Read the ImageType GUID values. Populate the guid array
+		 * with thesevalues. These are the values to be used in the
+		 * capsule for ImageTypeId.
+		 */
+		status = fwu_fill_partition_guid_array(&part_guid_arr,
+						       &nparts);
+		if (status < 0) {
+			log_err("Unable to get partiion guid's\n");
+			if (status == -EIO)
+				ret = EFI_DEVICE_ERROR;
+			else if (status == -ENOMEM)
+				ret = EFI_OUT_OF_RESOURCES;
+			goto out;
+		}
+	} else {
+		part_guid_arr = malloc(sizeof(efi_guid_t));
+		if (!part_guid_arr) {
+			log_err("Unable to allocate memory for guid array\n");
+			ret = EFI_OUT_OF_RESOURCES;
+			goto out;
+		}
+
+		guidcpy(part_guid_arr, &efi_firmware_image_type_uboot_raw);
+		nparts = 1;
+	}
+
 	ret = efi_get_dfu_info(image_info_size, image_info,
 			       descriptor_version, descriptor_count,
 			       descriptor_size,
 			       package_version, package_version_name,
-			       &efi_firmware_image_type_uboot_raw);
+			       part_guid_arr, nparts);
 
+out:
+	free(part_guid_arr);
 	return EFI_EXIT(ret);
 }