diff mbox series

[v2,11/17] efi_loader: add firmware management protocol for FIT image

Message ID 20200617025515.23585-12-takahiro.akashi@linaro.org
State New
Headers show
Series efi_loader: add capsule update support | expand

Commit Message

AKASHI Takahiro June 17, 2020, 2:55 a.m. UTC
In this commit, a very simple firmware management protocol driver
is implemented. It will take a common FIT image firmware in a capsule
file and apply the data using dfu backend storage drivers via
update_fit() interface.

So "dfu_alt_info" variable should be properly set to specify a device
and location to be updated. Please read README.dfu.

Fit image is a common file format for firmware update on U-Boot, and
this protocol works neatly just as a wrapper for one.

Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 include/efi_api.h             |   4 +
 include/efi_loader.h          |   2 +
 lib/efi_loader/Kconfig        |  11 ++
 lib/efi_loader/Makefile       |   1 +
 lib/efi_loader/efi_capsule.c  |  12 +-
 lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
 6 files changed, 282 insertions(+), 1 deletion(-)
 create mode 100644 lib/efi_loader/efi_firmware.c

Comments

Sughosh Ganu June 20, 2020, 6:39 p.m. UTC | #1
On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <takahiro.akashi at linaro.org>
wrote:

> In this commit, a very simple firmware management protocol driver
> is implemented. It will take a common FIT image firmware in a capsule
> file and apply the data using dfu backend storage drivers via
> update_fit() interface.
>
> So "dfu_alt_info" variable should be properly set to specify a device
> and location to be updated. Please read README.dfu.
>
> Fit image is a common file format for firmware update on U-Boot, and
> this protocol works neatly just as a wrapper for one.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> ---
>  include/efi_api.h             |   4 +
>  include/efi_loader.h          |   2 +
>  lib/efi_loader/Kconfig        |  11 ++
>  lib/efi_loader/Makefile       |   1 +
>  lib/efi_loader/efi_capsule.c  |  12 +-
>  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
>  6 files changed, 282 insertions(+), 1 deletion(-)
>  create mode 100644 lib/efi_loader/efi_firmware.c
>

Like we had discussed this offline, I don't think that efi_firmware.c name
accurately represents that the file is implementing the firmware management
protocol. This can be changed to efi_fmp.c, or if you don't prefer
acronyms, efi_firmware_mgmt_protocol.c

-sughosh
Sughosh Ganu June 20, 2020, 6:49 p.m. UTC | #2
On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <takahiro.akashi at linaro.org>
wrote:

> In this commit, a very simple firmware management protocol driver
> is implemented. It will take a common FIT image firmware in a capsule
> file and apply the data using dfu backend storage drivers via
> update_fit() interface.
>
> So "dfu_alt_info" variable should be properly set to specify a device
> and location to be updated. Please read README.dfu.
>
> Fit image is a common file format for firmware update on U-Boot, and
> this protocol works neatly just as a wrapper for one.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> ---
>  include/efi_api.h             |   4 +
>  include/efi_loader.h          |   2 +
>  lib/efi_loader/Kconfig        |  11 ++
>  lib/efi_loader/Makefile       |   1 +
>  lib/efi_loader/efi_capsule.c  |  12 +-
>  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
>  6 files changed, 282 insertions(+), 1 deletion(-)
>  create mode 100644 lib/efi_loader/efi_firmware.c
>
> diff --git a/include/efi_api.h b/include/efi_api.h
> index b062720e8220..c3fc4edbedc4 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -1843,6 +1843,10 @@ struct efi_signature_list {
>         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_UPDATABLE            0x1
>  #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED             0x2
>  #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x4
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index bc58c7e3c1d7..5f574533e732 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -787,6 +787,8 @@ bool efi_secure_boot_enabled(void);
>  bool efi_image_parse(void *efi, size_t len, struct efi_image_regions
> **regp,
>                      WIN_CERTIFICATE **auth, size_t *auth_len);
>
> +extern const struct efi_firmware_management_protocol efi_fmp_fit;
> +
>  /* Capsule update */
>  efi_status_t EFIAPI efi_update_capsule(
>                 struct efi_capsule_header **capsule_header_array,
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index e1413c35e33c..305751f4b15c 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -86,6 +86,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
>           Select this option if you want to enable capsule-based
>           firmware update using Firmware Management Protocol.
>
> +config EFI_CAPSULE_FIRMWARE_FIT
> +       bool "FMP driver for FIT image"
> +       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> +       depends on FIT
> +       select UPDATE_FIT
> +       select DFU
> +       default n
> +       help
> +         Select this option if you want to enable firmware management
> protocol
> +         driver for FIT image
> +
>  config EFI_DEVICE_PATH_TO_TEXT
>         bool "Device path to text protocol"
>         default y
> diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> index 67bc5c9c0907..ea1fbc4a9deb 100644
> --- a/lib/efi_loader/Makefile
> +++ b/lib/efi_loader/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
>  obj-y += efi_bootmgr.o
>  obj-y += efi_boottime.o
>  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
> +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
>

Why can we not build this file based on
CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT. That way, we do not have to declare
the CONFIG_EFI_CAPSULE_FIRMWARE symbol on which this file is being built in
a subsequent patch.

-sughosh
AKASHI Takahiro June 22, 2020, 1:03 a.m. UTC | #3
On Sun, Jun 21, 2020 at 12:09:23AM +0530, Sughosh Ganu wrote:
> On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <takahiro.akashi at linaro.org>
> wrote:
> 
> > In this commit, a very simple firmware management protocol driver
> > is implemented. It will take a common FIT image firmware in a capsule
> > file and apply the data using dfu backend storage drivers via
> > update_fit() interface.
> >
> > So "dfu_alt_info" variable should be properly set to specify a device
> > and location to be updated. Please read README.dfu.
> >
> > Fit image is a common file format for firmware update on U-Boot, and
> > this protocol works neatly just as a wrapper for one.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> > ---
> >  include/efi_api.h             |   4 +
> >  include/efi_loader.h          |   2 +
> >  lib/efi_loader/Kconfig        |  11 ++
> >  lib/efi_loader/Makefile       |   1 +
> >  lib/efi_loader/efi_capsule.c  |  12 +-
> >  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
> >  6 files changed, 282 insertions(+), 1 deletion(-)
> >  create mode 100644 lib/efi_loader/efi_firmware.c
> >
> 
> Like we had discussed this offline, I don't think that efi_firmware.c name
> accurately represents that the file is implementing the firmware management
> protocol. This can be changed to efi_fmp.c, or if you don't prefer
> acronyms, efi_firmware_mgmt_protocol.c

I think that efi_firmware is a good prefix without any confusion
given that there is no other features related to "firmware".

-Takahiro Akashi

> 
> -sughosh
AKASHI Takahiro June 22, 2020, 1:09 a.m. UTC | #4
On Sun, Jun 21, 2020 at 12:19:17AM +0530, Sughosh Ganu wrote:
> On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <takahiro.akashi at linaro.org>
> wrote:
> 
> > In this commit, a very simple firmware management protocol driver
> > is implemented. It will take a common FIT image firmware in a capsule
> > file and apply the data using dfu backend storage drivers via
> > update_fit() interface.
> >
> > So "dfu_alt_info" variable should be properly set to specify a device
> > and location to be updated. Please read README.dfu.
> >
> > Fit image is a common file format for firmware update on U-Boot, and
> > this protocol works neatly just as a wrapper for one.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> > ---
> >  include/efi_api.h             |   4 +
> >  include/efi_loader.h          |   2 +
> >  lib/efi_loader/Kconfig        |  11 ++
> >  lib/efi_loader/Makefile       |   1 +
> >  lib/efi_loader/efi_capsule.c  |  12 +-
> >  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
> >  6 files changed, 282 insertions(+), 1 deletion(-)
> >  create mode 100644 lib/efi_loader/efi_firmware.c
> >
> > diff --git a/include/efi_api.h b/include/efi_api.h
> > index b062720e8220..c3fc4edbedc4 100644
> > --- a/include/efi_api.h
> > +++ b/include/efi_api.h
> > @@ -1843,6 +1843,10 @@ struct efi_signature_list {
> >         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_UPDATABLE            0x1
> >  #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED             0x2
> >  #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x4
> > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > index bc58c7e3c1d7..5f574533e732 100644
> > --- a/include/efi_loader.h
> > +++ b/include/efi_loader.h
> > @@ -787,6 +787,8 @@ bool efi_secure_boot_enabled(void);
> >  bool efi_image_parse(void *efi, size_t len, struct efi_image_regions
> > **regp,
> >                      WIN_CERTIFICATE **auth, size_t *auth_len);
> >
> > +extern const struct efi_firmware_management_protocol efi_fmp_fit;
> > +
> >  /* Capsule update */
> >  efi_status_t EFIAPI efi_update_capsule(
> >                 struct efi_capsule_header **capsule_header_array,
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index e1413c35e33c..305751f4b15c 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -86,6 +86,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
> >           Select this option if you want to enable capsule-based
> >           firmware update using Firmware Management Protocol.
> >
> > +config EFI_CAPSULE_FIRMWARE_FIT
> > +       bool "FMP driver for FIT image"
> > +       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > +       depends on FIT
> > +       select UPDATE_FIT
> > +       select DFU
> > +       default n
> > +       help
> > +         Select this option if you want to enable firmware management
> > protocol
> > +         driver for FIT image
> > +
> >  config EFI_DEVICE_PATH_TO_TEXT
> >         bool "Device path to text protocol"
> >         default y
> > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> > index 67bc5c9c0907..ea1fbc4a9deb 100644
> > --- a/lib/efi_loader/Makefile
> > +++ b/lib/efi_loader/Makefile
> > @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
> >  obj-y += efi_bootmgr.o
> >  obj-y += efi_boottime.o
> >  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
> > +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
> >
> 
> Why can we not build this file based on
> CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT. That way, we do not have to declare
> the CONFIG_EFI_CAPSULE_FIRMWARE symbol on which this file is being built in
> a subsequent patch.

That is because, in some cases, efi_firmware.c won't be compiled in
as a specific platform may want to have its own protocol.

-Takahiro Akashi

> -sughosh
Sughosh Ganu June 22, 2020, 7:58 a.m. UTC | #5
On Mon, 22 Jun 2020 at 06:39, AKASHI Takahiro <takahiro.akashi at linaro.org>
wrote:

> On Sun, Jun 21, 2020 at 12:19:17AM +0530, Sughosh Ganu wrote:
> > On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <
> takahiro.akashi at linaro.org>
> > wrote:
> >
> > > In this commit, a very simple firmware management protocol driver
> > > is implemented. It will take a common FIT image firmware in a capsule
> > > file and apply the data using dfu backend storage drivers via
> > > update_fit() interface.
> > >
> > > So "dfu_alt_info" variable should be properly set to specify a device
> > > and location to be updated. Please read README.dfu.
> > >
> > > Fit image is a common file format for firmware update on U-Boot, and
> > > this protocol works neatly just as a wrapper for one.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> > > ---
> > >  include/efi_api.h             |   4 +
> > >  include/efi_loader.h          |   2 +
> > >  lib/efi_loader/Kconfig        |  11 ++
> > >  lib/efi_loader/Makefile       |   1 +
> > >  lib/efi_loader/efi_capsule.c  |  12 +-
> > >  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
> > >  6 files changed, 282 insertions(+), 1 deletion(-)
> > >  create mode 100644 lib/efi_loader/efi_firmware.c
> > >
> > > diff --git a/include/efi_api.h b/include/efi_api.h
> > > index b062720e8220..c3fc4edbedc4 100644
> > > --- a/include/efi_api.h
> > > +++ b/include/efi_api.h
> > > @@ -1843,6 +1843,10 @@ struct efi_signature_list {
> > >         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_UPDATABLE            0x1
> > >  #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED             0x2
> > >  #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x4
> > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > index bc58c7e3c1d7..5f574533e732 100644
> > > --- a/include/efi_loader.h
> > > +++ b/include/efi_loader.h
> > > @@ -787,6 +787,8 @@ bool efi_secure_boot_enabled(void);
> > >  bool efi_image_parse(void *efi, size_t len, struct efi_image_regions
> > > **regp,
> > >                      WIN_CERTIFICATE **auth, size_t *auth_len);
> > >
> > > +extern const struct efi_firmware_management_protocol efi_fmp_fit;
> > > +
> > >  /* Capsule update */
> > >  efi_status_t EFIAPI efi_update_capsule(
> > >                 struct efi_capsule_header **capsule_header_array,
> > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > index e1413c35e33c..305751f4b15c 100644
> > > --- a/lib/efi_loader/Kconfig
> > > +++ b/lib/efi_loader/Kconfig
> > > @@ -86,6 +86,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > >           Select this option if you want to enable capsule-based
> > >           firmware update using Firmware Management Protocol.
> > >
> > > +config EFI_CAPSULE_FIRMWARE_FIT
> > > +       bool "FMP driver for FIT image"
> > > +       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > > +       depends on FIT
> > > +       select UPDATE_FIT
> > > +       select DFU
> > > +       default n
> > > +       help
> > > +         Select this option if you want to enable firmware management
> > > protocol
> > > +         driver for FIT image
> > > +
> > >  config EFI_DEVICE_PATH_TO_TEXT
> > >         bool "Device path to text protocol"
> > >         default y
> > > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> > > index 67bc5c9c0907..ea1fbc4a9deb 100644
> > > --- a/lib/efi_loader/Makefile
> > > +++ b/lib/efi_loader/Makefile
> > > @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
> > >  obj-y += efi_bootmgr.o
> > >  obj-y += efi_boottime.o
> > >  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
> > > +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
> > >
> >
> > Why can we not build this file based on
> > CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT. That way, we do not have to
> declare
> > the CONFIG_EFI_CAPSULE_FIRMWARE symbol on which this file is being built
> in
> > a subsequent patch.
>
> That is because, in some cases, efi_firmware.c won't be compiled in
> as a specific platform may want to have its own protocol.
>

I think the whole point of the review comments from Heinrich to my fmp
implementation for qemu arm64 platform was to have a common fmp
implementation that could be used on all platforms and architectures. Do
you see a case for introducing a platform specific implementation now that
we have support for a generic raw binary image. Any platform specific fixup
if required, can be handled by adding pre-processing/post-processing
functions.

-sughosh
AKASHI Takahiro June 22, 2020, 8:06 a.m. UTC | #6
On Mon, Jun 22, 2020 at 01:28:07PM +0530, Sughosh Ganu wrote:
> On Mon, 22 Jun 2020 at 06:39, AKASHI Takahiro <takahiro.akashi at linaro.org>
> wrote:
> 
> > On Sun, Jun 21, 2020 at 12:19:17AM +0530, Sughosh Ganu wrote:
> > > On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <
> > takahiro.akashi at linaro.org>
> > > wrote:
> > >
> > > > In this commit, a very simple firmware management protocol driver
> > > > is implemented. It will take a common FIT image firmware in a capsule
> > > > file and apply the data using dfu backend storage drivers via
> > > > update_fit() interface.
> > > >
> > > > So "dfu_alt_info" variable should be properly set to specify a device
> > > > and location to be updated. Please read README.dfu.
> > > >
> > > > Fit image is a common file format for firmware update on U-Boot, and
> > > > this protocol works neatly just as a wrapper for one.
> > > >
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> > > > ---
> > > >  include/efi_api.h             |   4 +
> > > >  include/efi_loader.h          |   2 +
> > > >  lib/efi_loader/Kconfig        |  11 ++
> > > >  lib/efi_loader/Makefile       |   1 +
> > > >  lib/efi_loader/efi_capsule.c  |  12 +-
> > > >  lib/efi_loader/efi_firmware.c | 253 ++++++++++++++++++++++++++++++++++
> > > >  6 files changed, 282 insertions(+), 1 deletion(-)
> > > >  create mode 100644 lib/efi_loader/efi_firmware.c
> > > >
> > > > diff --git a/include/efi_api.h b/include/efi_api.h
> > > > index b062720e8220..c3fc4edbedc4 100644
> > > > --- a/include/efi_api.h
> > > > +++ b/include/efi_api.h
> > > > @@ -1843,6 +1843,10 @@ struct efi_signature_list {
> > > >         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_UPDATABLE            0x1
> > > >  #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED             0x2
> > > >  #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x4
> > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > index bc58c7e3c1d7..5f574533e732 100644
> > > > --- a/include/efi_loader.h
> > > > +++ b/include/efi_loader.h
> > > > @@ -787,6 +787,8 @@ bool efi_secure_boot_enabled(void);
> > > >  bool efi_image_parse(void *efi, size_t len, struct efi_image_regions
> > > > **regp,
> > > >                      WIN_CERTIFICATE **auth, size_t *auth_len);
> > > >
> > > > +extern const struct efi_firmware_management_protocol efi_fmp_fit;
> > > > +
> > > >  /* Capsule update */
> > > >  efi_status_t EFIAPI efi_update_capsule(
> > > >                 struct efi_capsule_header **capsule_header_array,
> > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > index e1413c35e33c..305751f4b15c 100644
> > > > --- a/lib/efi_loader/Kconfig
> > > > +++ b/lib/efi_loader/Kconfig
> > > > @@ -86,6 +86,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > > >           Select this option if you want to enable capsule-based
> > > >           firmware update using Firmware Management Protocol.
> > > >
> > > > +config EFI_CAPSULE_FIRMWARE_FIT
> > > > +       bool "FMP driver for FIT image"
> > > > +       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > > > +       depends on FIT
> > > > +       select UPDATE_FIT
> > > > +       select DFU
> > > > +       default n
> > > > +       help
> > > > +         Select this option if you want to enable firmware management
> > > > protocol
> > > > +         driver for FIT image
> > > > +
> > > >  config EFI_DEVICE_PATH_TO_TEXT
> > > >         bool "Device path to text protocol"
> > > >         default y
> > > > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> > > > index 67bc5c9c0907..ea1fbc4a9deb 100644
> > > > --- a/lib/efi_loader/Makefile
> > > > +++ b/lib/efi_loader/Makefile
> > > > @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
> > > >  obj-y += efi_bootmgr.o
> > > >  obj-y += efi_boottime.o
> > > >  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
> > > > +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
> > > >
> > >
> > > Why can we not build this file based on
> > > CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT. That way, we do not have to
> > declare
> > > the CONFIG_EFI_CAPSULE_FIRMWARE symbol on which this file is being built
> > in
> > > a subsequent patch.
> >
> > That is because, in some cases, efi_firmware.c won't be compiled in
> > as a specific platform may want to have its own protocol.
> >
> 
> I think the whole point of the review comments from Heinrich to my fmp
> implementation for qemu arm64 platform was to have a common fmp
> implementation that could be used on all platforms and architectures.

? I believe that my patch meets Heinrich's requirement.

> Do
> you see a case for introducing a platform specific implementation now that
> we have support for a generic raw binary image. Any platform specific fixup
> if required, can be handled by adding pre-processing/post-processing
> functions.

I don't think we should exclude any possibility of adding
platform-specific protocol as long as it doesn't break
UEFI specification. Heinrich sometimes makes similar comments
on different matters.

-Takahiro Akashi


> -sughosh
Sughosh Ganu June 22, 2020, 8:38 a.m. UTC | #7
On Mon, 22 Jun 2020 at 13:37, AKASHI Takahiro <takahiro.akashi at linaro.org>
wrote:

> On Mon, Jun 22, 2020 at 01:28:07PM +0530, Sughosh Ganu wrote:
> > On Mon, 22 Jun 2020 at 06:39, AKASHI Takahiro <
> takahiro.akashi at linaro.org>
> > wrote:
> >
> > > On Sun, Jun 21, 2020 at 12:19:17AM +0530, Sughosh Ganu wrote:
> > > > On Wed, 17 Jun 2020 at 08:26, AKASHI Takahiro <
> > > takahiro.akashi at linaro.org>
> > > > wrote:
> > > >
> > > > > In this commit, a very simple firmware management protocol driver
> > > > > is implemented. It will take a common FIT image firmware in a
> capsule
> > > > > file and apply the data using dfu backend storage drivers via
> > > > > update_fit() interface.
> > > > >
> > > > > So "dfu_alt_info" variable should be properly set to specify a
> device
> > > > > and location to be updated. Please read README.dfu.
> > > > >
> > > > > Fit image is a common file format for firmware update on U-Boot,
> and
> > > > > this protocol works neatly just as a wrapper for one.
> > > > >
> > > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> > > > > ---
> > > > >  include/efi_api.h             |   4 +
> > > > >  include/efi_loader.h          |   2 +
> > > > >  lib/efi_loader/Kconfig        |  11 ++
> > > > >  lib/efi_loader/Makefile       |   1 +
> > > > >  lib/efi_loader/efi_capsule.c  |  12 +-
> > > > >  lib/efi_loader/efi_firmware.c | 253
> ++++++++++++++++++++++++++++++++++
> > > > >  6 files changed, 282 insertions(+), 1 deletion(-)
> > > > >  create mode 100644 lib/efi_loader/efi_firmware.c
> > > > >
> > > > > diff --git a/include/efi_api.h b/include/efi_api.h
> > > > > index b062720e8220..c3fc4edbedc4 100644
> > > > > --- a/include/efi_api.h
> > > > > +++ b/include/efi_api.h
> > > > > @@ -1843,6 +1843,10 @@ struct efi_signature_list {
> > > > >         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_UPDATABLE            0x1
> > > > >  #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED             0x2
> > > > >  #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x4
> > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > index bc58c7e3c1d7..5f574533e732 100644
> > > > > --- a/include/efi_loader.h
> > > > > +++ b/include/efi_loader.h
> > > > > @@ -787,6 +787,8 @@ bool efi_secure_boot_enabled(void);
> > > > >  bool efi_image_parse(void *efi, size_t len, struct
> efi_image_regions
> > > > > **regp,
> > > > >                      WIN_CERTIFICATE **auth, size_t *auth_len);
> > > > >
> > > > > +extern const struct efi_firmware_management_protocol efi_fmp_fit;
> > > > > +
> > > > >  /* Capsule update */
> > > > >  efi_status_t EFIAPI efi_update_capsule(
> > > > >                 struct efi_capsule_header **capsule_header_array,
> > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > index e1413c35e33c..305751f4b15c 100644
> > > > > --- a/lib/efi_loader/Kconfig
> > > > > +++ b/lib/efi_loader/Kconfig
> > > > > @@ -86,6 +86,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > > > >           Select this option if you want to enable capsule-based
> > > > >           firmware update using Firmware Management Protocol.
> > > > >
> > > > > +config EFI_CAPSULE_FIRMWARE_FIT
> > > > > +       bool "FMP driver for FIT image"
> > > > > +       depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
> > > > > +       depends on FIT
> > > > > +       select UPDATE_FIT
> > > > > +       select DFU
> > > > > +       default n
> > > > > +       help
> > > > > +         Select this option if you want to enable firmware
> management
> > > > > protocol
> > > > > +         driver for FIT image
> > > > > +
> > > > >  config EFI_DEVICE_PATH_TO_TEXT
> > > > >         bool "Device path to text protocol"
> > > > >         default y
> > > > > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> > > > > index 67bc5c9c0907..ea1fbc4a9deb 100644
> > > > > --- a/lib/efi_loader/Makefile
> > > > > +++ b/lib/efi_loader/Makefile
> > > > > @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) +=
> helloworld_efi.o
> > > > >  obj-y += efi_bootmgr.o
> > > > >  obj-y += efi_boottime.o
> > > > >  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
> > > > > +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
> > > > >
> > > >
> > > > Why can we not build this file based on
> > > > CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT. That way, we do not have to
> > > declare
> > > > the CONFIG_EFI_CAPSULE_FIRMWARE symbol on which this file is being
> built
> > > in
> > > > a subsequent patch.
> > >
> > > That is because, in some cases, efi_firmware.c won't be compiled in
> > > as a specific platform may want to have its own protocol.
> > >
> >
> > I think the whole point of the review comments from Heinrich to my fmp
> > implementation for qemu arm64 platform was to have a common fmp
> > implementation that could be used on all platforms and architectures.
>
> ? I believe that my patch meets Heinrich's requirement.
>

Yes, and that was my point. About the need for having a platform specific
fmp implementation after having your patch.


>
> > Do
> > you see a case for introducing a platform specific implementation now
> that
> > we have support for a generic raw binary image. Any platform specific
> fixup
> > if required, can be handled by adding pre-processing/post-processing
> > functions.
>
> I don't think we should exclude any possibility of adding
> platform-specific protocol as long as it doesn't break
> UEFI specification. Heinrich sometimes makes similar comments
> on different matters.


Ok. My comments were based on what Heinrich had mentioned as part of
reviewing my fmp patches. In any case, i think there is no harm in building
this with the CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT symbol. If any
platform does add a fmp implementation, that should be a different,
platform specific symbol.

-sughosh
diff mbox series

Patch

diff --git a/include/efi_api.h b/include/efi_api.h
index b062720e8220..c3fc4edbedc4 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1843,6 +1843,10 @@  struct efi_signature_list {
 	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_UPDATABLE		0x1
 #define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED		0x2
 #define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED	0x4
diff --git a/include/efi_loader.h b/include/efi_loader.h
index bc58c7e3c1d7..5f574533e732 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -787,6 +787,8 @@  bool efi_secure_boot_enabled(void);
 bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 		     WIN_CERTIFICATE **auth, size_t *auth_len);
 
+extern const struct efi_firmware_management_protocol efi_fmp_fit;
+
 /* Capsule update */
 efi_status_t EFIAPI efi_update_capsule(
 		struct efi_capsule_header **capsule_header_array,
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e1413c35e33c..305751f4b15c 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -86,6 +86,17 @@  config EFI_CAPSULE_FIRMWARE_MANAGEMENT
 	  Select this option if you want to enable capsule-based
 	  firmware update using Firmware Management Protocol.
 
+config EFI_CAPSULE_FIRMWARE_FIT
+	bool "FMP driver for FIT image"
+	depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+	depends on FIT
+	select UPDATE_FIT
+	select DFU
+	default n
+	help
+	  Select this option if you want to enable firmware management protocol
+	  driver for FIT image
+
 config EFI_DEVICE_PATH_TO_TEXT
 	bool "Device path to text protocol"
 	default y
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 67bc5c9c0907..ea1fbc4a9deb 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -24,6 +24,7 @@  obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_bootmgr.o
 obj-y += efi_boottime.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
+obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o
 obj-y += efi_console.o
 obj-y += efi_device_path.o
 obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 22d15bc4d8cd..c2cd1d23f9ce 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -801,7 +801,17 @@  static void efi_capsule_scan_done(void)
  */
 efi_status_t __weak arch_efi_load_capsule_drivers(void)
 {
-	return EFI_SUCCESS;
+	__maybe_unused efi_handle_t handle;
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)) {
+		handle = NULL;
+		ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
+				&handle, &efi_guid_firmware_management_protocol,
+				&efi_fmp_fit, NULL));
+	}
+
+	return ret;
 }
 
 /**
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
new file mode 100644
index 000000000000..28ce5647a2cc
--- /dev/null
+++ b/lib/efi_loader/efi_firmware.c
@@ -0,0 +1,253 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI Firmware management protocol
+ *
+ *  Copyright (c) 2020 Linaro Limited
+ *			Author: AKASHI Takahiro
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <dfu.h>
+#include <efi_loader.h>
+#include <image.h>
+#include <linux/list.h>
+
+/*
+ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
+ * method with existing FIT image format, and handles
+ *   - multiple regions of firmware via DFU
+ * but doesn't support
+ *   - versioning of firmware image
+ *   - package information
+ */
+const efi_guid_t efi_firmware_image_type_uboot_fit =
+	EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
+
+/**
+ * efi_firmware_fit_get_image_info - return information about the current
+				     firmware image
+ * @this:			Protocol instance
+ * @image_info_size:		Size of @image_info
+ * @image_info:			Image information
+ * @descriptor_version:		Pointer to version number
+ * @descriptor_count:		Pointer to number of descriptors
+ * @descriptor_size:		Pointer to descriptor size
+ * package_version:		Package version
+ * package_version_name:	Package version's name
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ * Each descriptor will be created based on "dfu_alt_info" variable.
+ *
+ * Return		status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_fit_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 *package_version,
+	u16 **package_version_name)
+{
+	struct dfu_entity *dfu;
+	size_t names_len, total_size;
+	int dfu_num, i;
+	u16 *name, *next;
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+		  image_info_size, image_info,
+		  descriptor_version, descriptor_count, descriptor_size,
+		  package_version, package_version_name);
+
+	if (!image_info_size || (*image_info_size && !image_info))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	dfu_init_env_entities(NULL, NULL);
+
+	names_len = 0;
+	dfu_num = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		names_len += (utf8_utf16_strlen(dfu->name) + 1) * 2;
+		dfu_num++;
+	}
+	if (!dfu_num) {
+		EFI_PRINT("Probably dfu_alt_info not defined\n");
+		*image_info_size = 0;
+		dfu_free_entities();
+
+		return EFI_EXIT(EFI_SUCCESS);
+	}
+
+	total_size = sizeof(*image_info) * dfu_num + names_len;
+	/*
+	 * we will assume that sizeof(*image_info) * dfu_name
+	 * is, at least, a multiple of 2. So the start address for
+	 * image_id_name would be aligned with 2 bytes.
+	 */
+	if (*image_info_size < total_size) {
+		*image_info_size = total_size;
+		dfu_free_entities();
+
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+	*image_info_size = total_size;
+
+	if (descriptor_version)
+		*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+	if (descriptor_count)
+		*descriptor_count = dfu_num;
+	if (descriptor_size)
+		*descriptor_size = sizeof(*image_info);
+	if (package_version)
+		*package_version = 0xffffffff; /* not supported */
+	if (package_version_name)
+		*package_version_name = NULL; /* not supported */
+
+	/* DFU alt number should correspond to image_index */
+	i = 0;
+	/* Name area starts just after descriptors */
+	name = (u16 *)((u8 *)image_info + sizeof(*image_info) * dfu_num);
+	next = name;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		image_info[i].image_index = dfu->alt + 1;
+		image_info[i].image_type_id = efi_firmware_image_type_uboot_fit;
+		image_info[i].image_id = dfu->alt;
+
+		/* copy the DFU entity name */
+		utf8_utf16_strcpy(&next, dfu->name);
+		image_info[i].image_id_name = name;
+		name = ++next;
+
+		image_info[i].version = 0; /* not supported */
+		image_info[i].version_name = NULL; /* not supported */
+		image_info[i].size = 0;
+		image_info[i].attributes_supported =
+				EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+		image_info[i].attributes_setting =
+				EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+		image_info[i].lowest_supported_image_version = 0;
+		image_info[i].last_attempt_version = 0;
+		image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+		image_info[i].hardware_instance = 1;
+		image_info[i].dependencies = NULL;
+
+		i++;
+	}
+
+	dfu_free_entities();
+
+	return EFI_EXIT(ret);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	void *image,
+	efi_uintn_t *image_size)
+{
+	EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/**
+ * efi_firmware_fit_set_image - update the firmware image
+ * @this:		Protocol instance
+ * @image_index:	Image index number
+ * @image:		New image
+ * @image_size:		Size of new image
+ * @vendor_code:	Vendor-specific update policy
+ * @progress:		Function to report the progress of update
+ * @abort_reason:	Pointer to string of abort reason
+ *
+ * Update the firmware to new image, using dfu. The new image should
+ * have FIT image format commonly used in U-Boot.
+ * @vendor_code, @progress and @abort_reason are not supported.
+ *
+ * Return:		status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_fit_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)
+{
+	EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image,
+		  image_size, vendor_code, progress, abort_reason);
+
+	if (!image || image_index != 1)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (fit_update(image))
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_check_image_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u8 image_index,
+	const void *image,
+	efi_uintn_t *image_size,
+	u32 *image_updatable)
+{
+	EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
+		  image_updatable);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	u32 *package_version,
+	u16 **package_version_name,
+	u32 *package_version_name_maxlen,
+	u64 *attributes_supported,
+	u64 *attributes_setting)
+{
+	EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
+		  package_version_name, package_version_name_maxlen,
+		  attributes_supported, attributes_setting);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+/* Place holder; not supported */
+static
+efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
+	struct efi_firmware_management_protocol *this,
+	const void *image,
+	efi_uintn_t *image_size,
+	const void *vendor_code,
+	u32 package_version,
+	const u16 *package_version_name)
+{
+	EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
+		  package_version, package_version_name);
+
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+const struct efi_firmware_management_protocol efi_fmp_fit = {
+	.get_image_info = efi_firmware_fit_get_image_info,
+	.get_image = efi_firmware_get_image_unsupported,
+	.set_image = efi_firmware_fit_set_image,
+	.check_image = efi_firmware_check_image_unsupported,
+	.get_package_info = efi_firmware_get_package_info_unsupported,
+	.set_package_info = efi_firmware_set_package_info_unsupported,
+};