On Fri, 1 May 2020 at 00:09, Heinrich Schuchardt <xypron.g...@gmx.de> wrote:
> On 4/30/20 7:36 PM, Sughosh Ganu wrote: > > Add support for the get_image_info and set_image routines, which are > > part of the efi firmware management protocol. > > > > The current implementation uses the set_image routine for updating the > > u-boot binary image for the qemu arm64 platform. This is supported > > using the capsule-on-disk feature of the uefi specification, wherein > > the firmware image to be updated is placed on the efi system partition > > as a efi capsule under EFI/UpdateCapsule/ directory. Support has been > > added for updating the u-boot image on platforms booting with arm > > trusted firmware(tf-a), where the u-boot image gets booted as the BL33 > > payload(bl33.bin). > > > > The feature can be enabled by the following config options > > > > CONFIG_EFI_CAPSULE_ON_DISK=y > > CONFIG_EFI_FIRMWARE_MANAGEMENT_PROTOCOL=y > > > > Signed-off-by: Sughosh Ganu <sughosh.g...@linaro.org> > > U-Boot's UEFI subsystem should work in the same way for x86, ARM, and > RISC-V. Please, come up with an architecture independent solution. > Please check the explanation that I gave in the other mail. If you check the patch series, the actual capsule authentication logic has been kept architecture agnostic, in efi_capsule.c. The fmp protocol is very much intended for allowing platforms to define their firmware update routines. Edk2 also has platform specific implementation of the fmp protocol under the edk2-platforms directory. -sughosh > > Best regards > > Heinrich > > > --- > > board/emulation/qemu-arm/Kconfig | 12 ++ > > board/emulation/qemu-arm/Makefile | 1 + > > board/emulation/qemu-arm/qemu_efi_fmp.c | 210 ++++++++++++++++++++++++ > > 3 files changed, 223 insertions(+) > > create mode 100644 board/emulation/qemu-arm/qemu_efi_fmp.c > > > > diff --git a/board/emulation/qemu-arm/Kconfig > b/board/emulation/qemu-arm/Kconfig > > index 02ae4d9884..f1b2de8e41 100644 > > --- a/board/emulation/qemu-arm/Kconfig > > +++ b/board/emulation/qemu-arm/Kconfig > > @@ -11,3 +11,15 @@ config BOARD_SPECIFIC_OPTIONS # dummy > > imply VIRTIO_BLK > > > > endif > > + > > +if TARGET_QEMU_ARM_64BIT && TFABOOT > > + > > +config EFI_FIRMWARE_MANAGEMENT_PROTOCOL > > + bool "EFI Firmware Management protocol for Qemu arm64 platform" > > + depends on EFI_CAPSULE_ON_DISK > > + default n > > + help > > + Select this option for enabling firmware management protocol > > + for qemu arm64 platform > > + > > +endif > > diff --git a/board/emulation/qemu-arm/Makefile > b/board/emulation/qemu-arm/Makefile > > index a22d1237ff..c95ac6d233 100644 > > --- a/board/emulation/qemu-arm/Makefile > > +++ b/board/emulation/qemu-arm/Makefile > > @@ -1,3 +1,4 @@ > > # SPDX-License-Identifier: GPL-2.0+ > > > > obj-y += qemu-arm.o > > +obj-$(CONFIG_EFI_FIRMWARE_MANAGEMENT_PROTOCOL) += qemu_efi_fmp.o > > diff --git a/board/emulation/qemu-arm/qemu_efi_fmp.c > b/board/emulation/qemu-arm/qemu_efi_fmp.c > > new file mode 100644 > > index 0000000000..9baea94e6c > > --- /dev/null > > +++ b/board/emulation/qemu-arm/qemu_efi_fmp.c > > @@ -0,0 +1,210 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2020, Linaro Limited > > + */ > > + > > +#include <common.h> > > +#include <charset.h> > > +#include <efi_api.h> > > +#include <efi_loader.h> > > +#include <malloc.h> > > +#include <semihosting.h> > > + > > +#define QEMU_UBOOT_IMAGE_INDEX 0x1 > > +#define QEMU_UBOOT_IMAGE 0x1 > > + > > +#define UBOOT_FILE "bl33.bin" > > + > > +#define EFI_FMP_QEMU_ARM64_UBOOT_CAPSULE_ID_GUID \ > > + EFI_GUID(0xfb90808a, 0xba9a, 0x4d42, 0xb9, 0xa2, \ > > + 0xa7, 0xa9, 0x37, 0x14, 0x4a, 0xee) > > + > > +/** > > + * qemu_arm64_fmp_get_image_info() - Implement get_image_info > > + * > > + * @this: instance of the > efi_firmware_management_protocol > > + * @image_info_size: pointer to the size of image_info buffer > > + * @image_info: pointer to buffer which contains > info on the > > + * image > > + * @desc_version: pointer to version number of the > > + * efi_firmware_image_descriptor > > + * @desc_count: pointer to the number of > descriptors of the > > + * firmware images on the device > > + * @desc_size: pointer to the size of an > individual descriptor > > + * @package_version: version for all firmware images on the > device > > + * @package_version_name: string representing the package version > name > > + * > > + * Implement the get_image_info function of the > > + * efi_firmware_management_protocol for the platform. > > + * > > + * Return: status code > > + */ > > +static efi_status_t EFIAPI qemu_arm64_fmp_get_image_info( > > + struct efi_firmware_management_protocol *this, > > + efi_uintn_t *image_info_size, > > + struct efi_firmware_image_descriptor *image_info, > > + u32 *desc_version, u8 *desc_count, > > + efi_uintn_t *desc_size, u32 *package_version, > > + u16 **package_version_name) > > +{ > > + efi_status_t status = EFI_SUCCESS; > > + u16 *image_id_name; > > + const char *image_name = "Qemu Aarch64 U-Boot"; > > + const efi_guid_t image_guid = > EFI_FMP_QEMU_ARM64_UBOOT_CAPSULE_ID_GUID; > > + > > + EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, image_info_size, > > + image_info, desc_version, desc_count, desc_size, > > + package_version, package_version_name); > > + > > + /* Sanity checks */ > > + if (*image_info_size && !image_info) { > > + status = EFI_INVALID_PARAMETER; > > + goto back; > > + } > > + > > + if (*image_info_size && > > + (!desc_version || !desc_count || !desc_size)) { > > + status = EFI_INVALID_PARAMETER; > > + goto back; > > + } > > + > > + if (*image_info_size < sizeof(*image_info)) { > > + *image_info_size = sizeof(*image_info); > > + status = EFI_BUFFER_TOO_SMALL; > > + goto back; > > + } > > + > > + if (desc_version) > > + *desc_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; > > + > > + *desc_count = 0x1; > > + *desc_size = sizeof(*image_info); > > + > > + if (package_version) > > + *package_version = 0xffffffff; > > + > > + if (package_version_name) > > + *package_version_name = NULL; > > + > > + image_info[0].image_type_id = image_guid; > > + image_info[0].image_id = QEMU_UBOOT_IMAGE; > > + > > + image_id_name = malloc(40); > > + utf8_utf16_strcpy(&image_id_name, image_name); > > + image_info[0].image_id_name = image_id_name; > > + > > + /* Todo: Get a mechanism to store version information */ > > + image_info[0]. version = 0x1; > > + image_info[0].version_name = NULL; > > + > > + /* Todo: Need to find a mechanism to get the image size */ > > + image_info[0].size = 0; > > + > > + image_info[0].attributes_supported = > > + EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; > > + image_info[0].attributes_setting = > EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; > > + > > + image_info[0].lowest_supported_image_version = 1; > > + image_info[0].last_attempt_version = 0; > > + image_info[0].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; > > + image_info[0].hardware_instance = 0; > > + > > +back: > > + return EFI_EXIT(status); > > +} > > + > > +/** > > + * qemu_arm64_fmp_set_image() - Implement set_image > > + * > > + * @this: instance of the > efi_firmware_management_protocol > > + * @image_index: a unique number identifying the firmware > image > > + * @image: pointer to the buffer containing the > firmware > > + * image to be updated > > + * @image_size: pointer to size of the firmware > image > > + * @vendor_code: pointer to the vendor specific update > policy > > + * @completion: function pointer that can be > invoked to report > > + * firmware update progress > > + * @abort_reason: string providing details if update is > aborted > > + * > > + * Implement the set_image function of the > efi_firmware_management_protocol > > + * for the platform. This updates the firmware image and authenticates > the > > + * capsule, if authentication is enabled > > + * > > + * Return: status code > > + */ > > +static efi_status_t EFIAPI qemu_arm64_fmp_set_image( > > + struct efi_firmware_management_protocol *this, > > + u8 image_index, const void *image, > > + efi_uintn_t image_size, const void *vendor_code, > > + efi_status_t (*progress)(efi_uintn_t completion), > > + u16 **abort_reason) > > +{ > > + long fd, ret; > > + efi_status_t status = EFI_SUCCESS; > > + char *mode = "w+b"; > > + > > + EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, > > + image_size, vendor_code, progress, abort_reason); > > + > > + /* > > + * Put a hack here to offset the size of > > + * the FMP_PAYLOAD_HEADER that gets added > > + * by the GenerateCapsule script in edk2. > > + */ > > + image += 0x10; > > + image_size -= 0x10; > > + > > + /* Do all the sanity checks first */ > > + if (!image) { > > + status = EFI_INVALID_PARAMETER; > > + goto back; > > + } > > + > > + if (image_size == 0) { > > + status = EFI_INVALID_PARAMETER; > > + goto back; > > + } > > + > > + if (image_index != QEMU_UBOOT_IMAGE_INDEX) { > > + status = EFI_INVALID_PARAMETER; > > + goto back; > > + } > > + > > + /* Do the update */ > > + fd = smh_open(UBOOT_FILE, mode); > > + if (fd == -1) { > > + printf("Unable to open the firmware image for writing\n"); > > + status = EFI_DEVICE_ERROR; > > + goto back; > > + } > > + > > + ret = smh_write(fd, (void *)image, image_size); > > + if (ret == -1) { > > + printf("Error writing to the firmware image!"); > > + smh_close(fd); > > + status = EFI_DEVICE_ERROR; > > + goto back; > > + } > > + > > + printf("Capsule Update Complete\n"); > > + smh_close(fd); > > +back: > > + return EFI_EXIT(status); > > +} > > + > > +const struct efi_firmware_management_protocol efi_qemu_arm64_fmp = { > > + .get_image_info = qemu_arm64_fmp_get_image_info, > > + .set_image = qemu_arm64_fmp_set_image, > > +}; > > + > > +efi_status_t arch_efi_load_capsule_drivers(void) > > +{ > > + efi_status_t ret; > > + > > + ret = EFI_CALL(efi_install_multiple_protocol_interfaces(&efi_root, > > + > &efi_guid_firmware_management_protocol, > > + &efi_qemu_arm64_fmp, > > + NULL)); > > + > > + return ret; > > +} > > > >