This adds a barebox update handler to write a barebox image to the eMMC boot partitions. The image is written to the currently inactive boot partition which is made active after a successful write thus enabling a failsafe update. The update handler expects an image which has the tiboot3.bin right at the start of the image and a FIP image containing the next stages at offset 1MiB. This image can't be generated by barebox itself (as it requires two barebox images built for different architectures). It must be generated by an external build system. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- arch/arm/mach-k3/Makefile | 1 + arch/arm/mach-k3/bbu.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ include/mach/k3/common.h | 13 ++++++++ 3 files changed, 91 insertions(+) diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 8120c6fd35..b1dfb66d74 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -1,6 +1,7 @@ obj-y += common.o obj-pbl-$(CONFIG_MACH_K3_CORTEX_R5) += r5.o obj-pbl-y += ddrss.o +obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o extra-$(CONFIG_MACH_K3_CORTEX_R5) += combined-dm-cfg-am625.k3cfg combined-sysfw-cfg-am625.k3cfg diff --git a/arch/arm/mach-k3/bbu.c b/arch/arm/mach-k3/bbu.c new file mode 100644 index 0000000000..815af086e8 --- /dev/null +++ b/arch/arm/mach-k3/bbu.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) "k3-bbu: " fmt + +#include <bbu.h> +#include <xfuncs.h> +#include <fcntl.h> +#include <filetype.h> +#include <linux/printk.h> +#include <unistd.h> +#include <mach/k3/common.h> +#include <linux/sizes.h> +#include <libfile.h> + +static int k3_bbu_mmc_update(struct bbu_handler *handler, + struct bbu_data *data) +{ + int fd, ret; + enum filetype type; + + if (data->len < K3_EMMC_BOOTPART_TIBOOT3_BIN_SIZE + SZ_1K) { + pr_err("Image is too small\n"); + return -EINVAL; + } + + type = file_detect_type(data->image + K3_EMMC_BOOTPART_TIBOOT3_BIN_SIZE, SZ_1K); + + if (type != filetype_fip) { + pr_err("Cannot find FIP image at offset 1M\n"); + return -EINVAL; + } + + pr_debug("Attempting eMMC boot partition update\n"); + + ret = bbu_confirm(data); + if (ret) + return ret; + + fd = open(data->devicefile, O_RDWR); + if (fd < 0) + return fd; + + ret = pwrite_full(fd, data->image, data->len, 0); + if (ret < 0) + pr_err("writing to %s failed with %pe\n", data->devicefile, ERR_PTR(ret)); + + close(fd); + + return ret < 0 ? ret : 0; +} + +static int k3_bbu_mmc_fip_handler(struct bbu_handler *handler, + struct bbu_data *data) +{ + return bbu_mmcboot_handler(handler, data, k3_bbu_mmc_update); +} + +int k3_bbu_emmc_register(const char *name, + const char *devicefile, + unsigned long flags) +{ + struct bbu_handler *handler; + int ret; + + handler = xzalloc(sizeof(*handler)); + + handler->flags = flags | BBU_HANDLER_FLAG_MMC_BOOT_ACK; + handler->devicefile = devicefile; + handler->name = name; + handler->handler = k3_bbu_mmc_fip_handler; + + ret = bbu_register_handler(handler); + if (ret) + free(handler); + + return ret; +} diff --git a/include/mach/k3/common.h b/include/mach/k3/common.h index 14dfc4a28a..871e9f39e3 100644 --- a/include/mach/k3/common.h +++ b/include/mach/k3/common.h @@ -16,4 +16,17 @@ void am625_enable_32k_crystal(void); #define K3_EMMC_BOOTPART_TIBOOT3_BIN_SIZE SZ_1M +#ifdef CONFIG_BAREBOX_UPDATE +int k3_bbu_emmc_register(const char *name, + const char *devicefile, + unsigned long flags); +#else +static inline int k3_bbu_emmc_register(const char *name, + const char *devicefile, + unsigned long flags) +{ + return 0; +} +#endif + #endif /* __MACH_K3_COMMON_H */ -- 2.39.5