common: update: add a generic interface for FIT image

The main purpose of this patch is to separate a generic interface for
updating firmware using DFU drivers from "auto-update" via tftp.

This function will also be used in implementing UEFI capsule update
in a later commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
AKASHI Takahiro 2020-10-29 13:47:43 +09:00 committed by Heinrich Schuchardt
parent 1c2d1293f6
commit 3149e524fc
5 changed files with 100 additions and 2 deletions

View file

@ -599,9 +599,15 @@ endmenu
menu "Update support" menu "Update support"
config UPDATE_COMMON
bool
default n
select DFU_WRITE_ALT
config UPDATE_TFTP config UPDATE_TFTP
bool "Auto-update using fitImage via TFTP" bool "Auto-update using fitImage via TFTP"
depends on FIT depends on FIT
select UPDATE_COMMON
help help
This option allows performing update of NOR with data in fitImage This option allows performing update of NOR with data in fitImage
sent via TFTP boot. sent via TFTP boot.
@ -616,6 +622,15 @@ config UPDATE_TFTP_MSEC_MAX
default 100 default 100
depends on UPDATE_TFTP depends on UPDATE_TFTP
config UPDATE_FIT
bool "Firmware update using fitImage"
depends on FIT
depends on DFU
select UPDATE_COMMON
help
This option allows performing update of DFU-capable storage with
data in fitImage.
config ANDROID_AB config ANDROID_AB
bool "Android A/B updates" bool "Android A/B updates"
default n default n

View file

@ -53,8 +53,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o
obj-$(CONFIG_MENU) += menu.o obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_UPDATE_COMMON) += update.o
obj-$(CONFIG_DFU_TFTP) += update.o
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o

View file

@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#include <mtd/cfi_flash.h> #include <mtd/cfi_flash.h>
#ifdef CONFIG_DFU_TFTP
/* env variable holding the location of the update file */ /* env variable holding the location of the update file */
#define UPDATE_FILE_ENV "updatefile" #define UPDATE_FILE_ENV "updatefile"
@ -98,6 +99,7 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
return rv; return rv;
} }
#endif /* CONFIG_DFU_TFTP */
#ifdef CONFIG_MTD_NOR_FLASH #ifdef CONFIG_MTD_NOR_FLASH
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last) static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
@ -231,6 +233,7 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
return 0; return 0;
} }
#ifdef CONFIG_DFU_TFTP
int update_tftp(ulong addr, char *interface, char *devstring) int update_tftp(ulong addr, char *interface, char *devstring)
{ {
char *filename, *env_addr, *fit_image_name; char *filename, *env_addr, *fit_image_name;
@ -337,3 +340,71 @@ next_node:
return ret; return ret;
} }
#endif /* CONFIG_DFU_UPDATE */
#ifdef CONFIG_UPDATE_FIT
/**
* fit_update - update storage with FIT image
* @fit: Pointer to FIT image
*
* Update firmware on storage using FIT image as input.
* The storage area to be update will be identified by the name
* in FIT and matching it to "dfu_alt_info" variable.
*
* Return: 0 - on success, non-zero - otherwise
*/
int fit_update(const void *fit)
{
char *fit_image_name;
ulong update_addr, update_fladdr, update_size;
int images_noffset, ndepth, noffset;
int ret = 0;
if (!fit)
return -EINVAL;
if (!fit_check_format((void *)fit)) {
printf("Bad FIT format of the update file, aborting auto-update\n");
return -EINVAL;
}
/* process updates */
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
ndepth = 0;
noffset = fdt_next_node(fit, images_noffset, &ndepth);
while (noffset >= 0 && ndepth > 0) {
if (ndepth != 1)
goto next_node;
fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) {
printf("Error: invalid update hash, aborting\n");
ret = 1;
goto next_node;
}
printf("\n");
if (update_fit_getparams(fit, noffset, &update_addr,
&update_fladdr, &update_size)) {
printf("Error: can't get update parameters, aborting\n");
ret = 1;
goto next_node;
}
if (fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE)) {
ret = dfu_write_by_name(fit_image_name,
(void *)update_addr,
update_size, NULL, NULL);
if (ret)
return ret;
}
next_node:
noffset = fdt_next_node(fit, noffset, &ndepth);
}
return ret;
}
#endif /* CONFIG_UPDATE_FIT */

View file

@ -22,6 +22,7 @@ config DFU_TFTP
bool "DFU via TFTP" bool "DFU via TFTP"
select DFU_WRITE_ALT select DFU_WRITE_ALT
select DFU_OVER_TFTP select DFU_OVER_TFTP
select UPDATE_COMMON
help help
This option allows performing update of DFU-managed medium with data This option allows performing update of DFU-managed medium with data
sent via TFTP boot. sent via TFTP boot.

View file

@ -1602,4 +1602,16 @@ struct fit_loadable_tbl {
.handler = _handler, \ .handler = _handler, \
} }
/**
* fit_update - update storage with FIT image
* @fit: Pointer to FIT image
*
* Update firmware on storage using FIT image as input.
* The storage area to be update will be identified by the name
* in FIT and matching it to "dfu_alt_info" variable.
*
* Return: 0 on success, non-zero otherwise
*/
int fit_update(const void *fit);
#endif /* __IMAGE_H__ */ #endif /* __IMAGE_H__ */