diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-05-06 01:31:17 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-05-14 21:54:34 +0300 |
commit | eda2c7c523d858d25fe25052254a7f393767310b (patch) | |
tree | 7c14ec3de42b7fc6c86bc3b0f9ecb4b9f21a5d14 /meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch | |
parent | 794d26fa53ad7e8cb54a3a5773436b1d8e813f35 (diff) | |
download | openbmc-eda2c7c523d858d25fe25052254a7f393767310b.tar.xz |
Update to internal 0.53
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch | 1273 |
1 files changed, 0 insertions, 1273 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch deleted file mode 100644 index 3c21a7c0a..000000000 --- a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch +++ /dev/null @@ -1,1273 +0,0 @@ -From 0f64b0e0c0a122ce23b5ccc518f514ec296bc7f5 Mon Sep 17 00:00:00 2001 -From: AppaRao Puli <apparao.puli@linux.intel.com> -Date: Tue, 21 May 2019 00:53:04 +0530 -Subject: [PATCH] FFUJ: FW IPMI commands and flash support in u-boot - -Firmware update and OEM ipmi commands implementation -for supporting Force Firmware Update Jumper(FFUJ) -mode. Also added support to update the fit images -in FFUJ mode. - -Firmware update commands: -1) Get BMC Execution Context(0x23) -2) Get Firmware Update Random Number(0x26) -3) Set Firmware Update Mode(0x27) -4) Exit Firmware Update Mode(0x28) -5) Set/Get Firmware Update Control(0x29) -6) Get Firmware Update status(0x2A) -7) Set Firmware Update Options(0x2B) -8) Firmware Image Write(0x2C) - -OEM Commands: -1) Get Buffer Size(0x66) - -Tested: - - Used cmdtool.efi to test the individual commands - implementation and negative cases. - - Used debug fwpiaupd.efi tool for validating Firmware - image transfer via KCS and flashing. - -Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> ---- - arch/arm/include/asm/arch-aspeed/ast-g5-intel.h | 1 + - board/aspeed/ast-g5/Makefile | 2 + - board/aspeed/ast-g5/fw-update.c | 486 ++++++++++++++++++++++++ - board/aspeed/ast-g5/fw-update.h | 50 +++ - board/aspeed/ast-g5/ipmi-fwupd.c | 402 ++++++++++++++++++++ - board/aspeed/ast-g5/ipmi-fwupd.h | 81 ++++ - board/aspeed/ast-g5/ipmi-handler.c | 66 +++- - board/aspeed/ast-g5/ipmi-handler.h | 3 +- - common/autoboot.c | 13 + - configs/ast_g5_phy_defconfig | 1 + - 10 files changed, 1093 insertions(+), 12 deletions(-) - create mode 100644 board/aspeed/ast-g5/fw-update.c - create mode 100644 board/aspeed/ast-g5/fw-update.h - create mode 100644 board/aspeed/ast-g5/ipmi-fwupd.c - create mode 100644 board/aspeed/ast-g5/ipmi-fwupd.h - -diff --git a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h -index cd9a099..a88521a 100644 ---- a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h -+++ b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h -@@ -14,6 +14,7 @@ - - #ifndef __ASSEMBLY__ - int intel_force_firmware_jumper_enabled(void); -+void start_fw_update_loop(void); - #endif - - #endif /* __AST_INTEL_G5_H__ */ -diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile -index f28fcfe..0b2d936 100644 ---- a/board/aspeed/ast-g5/Makefile -+++ b/board/aspeed/ast-g5/Makefile -@@ -6,3 +6,5 @@ obj-y += ast-g5-gpio.o - obj-y += ast-g5-timer.o - obj-y += ast-g5-kcs.o - obj-y += ipmi-handler.o -+obj-y += ipmi-fwupd.o -+obj-y += fw-update.o -diff --git a/board/aspeed/ast-g5/fw-update.c b/board/aspeed/ast-g5/fw-update.c -new file mode 100644 -index 0000000..9923993 ---- /dev/null -+++ b/board/aspeed/ast-g5/fw-update.c -@@ -0,0 +1,486 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include <common.h> -+#include <cli.h> -+#include <flash.h> -+ -+#include "fw-update.h" -+ -+#define BOOTCMD_BOOTM_STR "bootm " -+#define RANDOM_NUM_TIMEOUT 30 /* in seconds */ -+#define WAIT_STATE_TIMEOUT 10000 /* 10 seconds */ -+ -+#define PROTECT_OFF 0 -+#define PROTECT_ON 1 -+ -+extern struct fwupd_global_setting g_fwupd_settings; -+extern u32 g_write_addr; -+ -+bool g_fwupd_settings_lock = false; -+unsigned long long etime; -+ -+bool fwupd_settings_trylock(void) -+{ -+ if (g_fwupd_settings_lock) -+ return false; -+ -+ g_fwupd_settings_lock = true; -+ return g_fwupd_settings_lock; -+} -+ -+void fwupd_settings_unlock(void) -+{ -+ g_fwupd_settings_lock = false; -+} -+ -+u8 get_active_boot_image(void) -+{ -+ char *bootcmd = getenv("bootcmd"); -+ char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR); -+ u8 boot_image = PRIMARY_IMAGE; -+ -+ if (start) { -+ ulong boot_addr = simple_strtoul( -+ (start + strlen(BOOTCMD_BOOTM_STR)), NULL, 16); -+ if (boot_addr == SECONDARY_FITIMAGE_START_ADDR) -+ return SECONDARY_IMAGE; -+ } -+ return boot_image; -+} -+ -+static ulong get_flash_image_address(void) -+{ -+ char *bootcmd = getenv("bootcmd"); -+ char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR); -+ ulong boot_addr = PRIMARY_FITIMAGE_START_ADDR; -+ -+ if (start) { -+ boot_addr = simple_strtoul((start + strlen(BOOTCMD_BOOTM_STR)), -+ NULL, 16); -+ /* We update in backup region and set the bootcmd accordingly */ -+ if (boot_addr == PRIMARY_FITIMAGE_START_ADDR) -+ boot_addr = SECONDARY_FITIMAGE_START_ADDR; -+ else -+ boot_addr = PRIMARY_FITIMAGE_START_ADDR; -+ } -+ -+ return boot_addr; -+} -+ -+static void update_processing_status(u8 status, u8 percent) -+{ -+ if (!fwupd_settings_trylock()) -+ return; -+ -+ g_fwupd_settings.processing_status = status; -+ g_fwupd_settings.percentage_completion = percent; -+ -+ fwupd_settings_unlock(); -+ return; -+} -+ -+static void reset_all_settings(void) -+{ -+ if (!fwupd_settings_trylock()) -+ return; -+ -+ memset(&g_fwupd_settings, 0, sizeof(g_fwupd_settings)); -+ g_fwupd_settings.fwupd_mode_active = false; -+ g_fwupd_settings.start_update = false; -+ -+ fwupd_settings_unlock(); -+} -+ -+unsigned int get_seed(void) -+{ -+ char seed_str[] = { "INTEL" }; -+ unsigned int seed; -+ -+ for (int i = 0; i < strlen(seed_str); i++) -+ seed += (seed_str[i] << (i * 8)); -+ -+ return seed; -+} -+ -+int generate_random_number(void) -+{ -+ srand(get_seed()); -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ return -1; -+ } -+ for (int i = 0; i < RAND_NUMBER_SIZE; i++) -+ g_fwupd_settings.rand_num[i] = (u8)(rand() & 0xFF); -+ -+ g_fwupd_settings.random_number_valid = true; -+ -+ fwupd_settings_unlock(); -+ -+ /* Random number should be cleared after 30sec timeout */ -+ etime = endtick(RANDOM_NUM_TIMEOUT); -+ -+ return 0; -+} -+ -+static int sect_roundb(ulong *addr) -+{ -+ flash_info_t *info; -+ ulong bank, sector_end_addr; -+ char found; -+ int i; -+ -+ /* find the end addr of the sector where the *addr is */ -+ found = 0; -+ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS && !found; ++bank) { -+ info = &flash_info[bank]; -+ for (i = 0; i < info->sector_count && !found; ++i) { -+ /* get the end address of the sector */ -+ if (i == info->sector_count - 1) { -+ sector_end_addr = -+ info->start[0] + info->size - 1; -+ } else { -+ sector_end_addr = info->start[i + 1] - 1; -+ } -+ -+ if (*addr <= sector_end_addr && -+ *addr >= info->start[i]) { -+ found = 1; -+ /* adjust *addr if necessary */ -+ if (*addr < sector_end_addr) -+ *addr = sector_end_addr; -+ } /* sector */ -+ } /* bank */ -+ } -+ if (!found) { -+ /* error, address not in flash */ -+ printf("Error: end address (0x%08lx) not in flash!\n", *addr); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int fill_flash_sect_ranges(ulong addr_first, ulong addr_last, -+ int *s_first, int *s_last, int *s_count) -+{ -+ flash_info_t *info; -+ ulong bank; -+ int rcode = 0; -+ -+ *s_count = 0; -+ -+ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) { -+ s_first[bank] = -1; /* first sector to erase */ -+ s_last[bank] = -1; /* last sector to erase */ -+ } -+ -+ for (bank = 0, info = &flash_info[0]; -+ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (addr_first <= addr_last); -+ ++bank, ++info) { -+ ulong b_end; -+ int sect; -+ short s_end; -+ -+ if (info->flash_id == FLASH_UNKNOWN) -+ continue; -+ -+ b_end = info->start[0] + info->size - 1; /* bank end addr */ -+ s_end = info->sector_count - 1; /* last sector */ -+ -+ for (sect = 0; sect < info->sector_count; ++sect) { -+ ulong end; /* last address in current sect */ -+ -+ end = (sect == s_end) ? b_end : -+ info->start[sect + 1] - 1; -+ -+ if (addr_first > end) -+ continue; -+ if (addr_last < info->start[sect]) -+ continue; -+ -+ if (addr_first == info->start[sect]) -+ s_first[bank] = sect; -+ if (addr_last == end) -+ s_last[bank] = sect; -+ } -+ if (s_first[bank] >= 0) { -+ if (s_last[bank] < 0) { -+ if (addr_last > b_end) { -+ s_last[bank] = s_end; -+ } else { -+ printf("Error: end address not on sector boundary\n"); -+ rcode = 1; -+ break; -+ } -+ } -+ if (s_last[bank] < s_first[bank]) { -+ printf("Error: end sector precedes start sector\n"); -+ rcode = 1; -+ break; -+ } -+ sect = s_last[bank]; -+ addr_first = (sect == s_end) ? b_end + 1 : -+ info->start[sect + 1]; -+ (*s_count) += s_last[bank] - s_first[bank] + 1; -+ } else if (addr_first >= info->start[0] && addr_first < b_end) { -+ printf("Error: start address not on sector boundary\n"); -+ rcode = 1; -+ break; -+ } else if (s_last[bank] >= 0) { -+ printf("Error: cannot span across banks when they are mapped in reverse order\n"); -+ rcode = 1; -+ break; -+ } -+ } -+ -+ return rcode; -+} -+ -+static int protect_flash_sector(int state, ulong addr_first, ulong addr_last) -+{ -+ flash_info_t *info; -+ ulong bank; -+ int s_first[CONFIG_SYS_MAX_FLASH_BANKS], -+ s_last[CONFIG_SYS_MAX_FLASH_BANKS]; -+ int protected = 0; -+ int planned; -+ int rcode, i; -+ -+ rcode = fill_flash_sect_ranges(addr_first, addr_last, s_first, s_last, -+ &planned); -+ -+ if (planned && (rcode == 0)) { -+ for (bank = 0, info = &flash_info[0]; -+ bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) { -+ if (info->flash_id == FLASH_UNKNOWN) -+ continue; -+ -+ if (s_first[bank] >= 0 && -+ s_first[bank] <= s_last[bank]) { -+ debug("%sProtecting sectors %d..%d in bank %ld\n", -+ state ? "" : "Un-", s_first[bank], -+ s_last[bank], bank + 1); -+ protected -+ += s_last[bank] - s_first[bank] + 1; -+ for (i = s_first[bank]; i <= s_last[bank]; ++i) -+ info->protect[i] = state; -+ } -+ } -+ printf("%sProtected %d sectors\n", state ? "" : "Un-", -+ protected); -+ } else if (rcode == 0) { -+ printf("Error: start and/or end address not on sector boundary\n"); -+ rcode = 1; -+ } -+ -+ return rcode; -+} -+ -+static int erase_flash_sector(ulong addr_first, ulong addr_last) -+{ -+ flash_info_t *info; -+ ulong bank; -+ int s_first[CONFIG_SYS_MAX_FLASH_BANKS]; -+ int s_last[CONFIG_SYS_MAX_FLASH_BANKS]; -+ int erased = 0; -+ int planned; -+ int rcode = 0; -+ -+ rcode = fill_flash_sect_ranges(addr_first, addr_last, s_first, s_last, -+ &planned); -+ -+ if (planned && (rcode == 0)) { -+ for (bank = 0, info = &flash_info[0]; -+ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (rcode == 0); -+ ++bank, ++info) { -+ if (s_first[bank] >= 0) { -+ erased += s_last[bank] - s_first[bank] + 1; -+ debug("Erase Flash from 0x%08lx to 0x%08lx " -+ "in Bank # %ld ", -+ info->start[s_first[bank]], -+ (s_last[bank] == info->sector_count) ? -+ info->start[0] + info->size - 1 : -+ info->start[s_last[bank] + 1] - 1, -+ bank + 1); -+ rcode = flash_erase(info, s_first[bank], -+ s_last[bank]); -+ } -+ } -+ if (rcode == 0) -+ printf("Erased %d sectors\n", erased); -+ } else if (rcode == 0) { -+ printf("Error: start and/or end address not on sector boundary\n"); -+ rcode = 1; -+ } -+ -+ return rcode; -+} -+ -+static int verify_image(void) -+{ -+ ulong src_addr = IMAGE_LOAD_RAM_ADDR; -+ void *hdr = (void *)src_addr; -+ -+ printf("\n## Checking Image at 0x%08lx ...\n", src_addr); -+ /* AT the moment, we only support FIT image flash */ -+ switch (genimg_get_format(hdr)) { -+ case IMAGE_FORMAT_FIT: -+ printf(" FIT image found\n"); -+ if (!fit_check_format(hdr)) { -+ printf("Bad FIT image format!\n"); -+ return -1; -+ } -+ -+ if (!fit_all_image_verify(hdr)) { -+ printf("Bad hash in FIT image!\n"); -+ return -1; -+ } -+ break; -+ default: -+ printf("Unknown image format!\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int flash_image(void) -+{ -+ int rcode; -+ ulong max_size = MAX_FITIMAGE_SIZE; -+ ulong src_addr = IMAGE_LOAD_RAM_ADDR; -+ ulong addr_first = get_flash_image_address(); -+ ulong addr_last = addr_first + max_size - 1; -+ -+ if ((g_write_addr > max_size) || (g_write_addr == 0)) { -+ printf("ERROR: %s(): Invalid file uploaded. filesize(0x%08x)\n", -+ __func__, g_write_addr); -+ return -1; -+ } -+ -+ if (sect_roundb(&addr_last) > 0) { -+ printf("ERROR: %s(): sect_roundb failed\n", __func__); -+ return -1; -+ } -+ -+ if (addr_first >= addr_last) { -+ printf("ERROR: %s(): addr_first(0x%08lx) >= addr_last(0x%08lx)\n", -+ __func__, addr_first, addr_last); -+ return -1; -+ } -+ -+ /* Hack: To update the percentage update, -+ * treat logical division as below. -+ * Image verify - 10% -+ * Unprotecting flash sectors - 10% -+ * Erase flash sectors - 40% -+ * Copy to flash - 40% */ -+ -+ /* Unprotect the flash sectors */ -+ rcode = protect_flash_sector(PROTECT_OFF, addr_first, addr_last); -+ if (rcode != 0) { -+ printf("%s(): Protecting flash sector failed(%d).\n", __func__, -+ rcode); -+ return -1; -+ } -+ update_processing_status(IMG_PROGRAMMING, 20); -+ -+ /* erase flash sectors */ -+ rcode = erase_flash_sector(addr_first, addr_last); -+ if (rcode != 0) { -+ printf("%s(): Erasing flash sector failed(%d).\n", __func__, -+ rcode); -+ return -1; -+ } -+ update_processing_status(IMG_PROGRAMMING, 60); -+ -+ /* write to flash area */ -+ printf("Copy to Flash... "); -+ rcode = flash_write((char *)src_addr, addr_first, g_write_addr * 1); -+ if (rcode != 0) { -+ printf("%s(): Flash copy failed(%d).\n", __func__, rcode); -+ flash_perror(rcode); -+ return -1; -+ } -+ printf("done\n"); -+ return 0; -+} -+ -+void start_fw_update_loop(void) -+{ -+ int rc; -+ ulong boot_addr; -+ char boot_cmd[20]; -+ -+ while (1) { -+ if (g_fwupd_settings.random_number_valid) { -+ /* Random number should be cleared after 30seconds */ -+ if (get_ticks() >= etime) { -+ printf("Clearing random number\n"); -+ -+ if (!fwupd_settings_trylock()) -+ continue; -+ memcpy(g_fwupd_settings.rand_num, 0, -+ RAND_NUMBER_SIZE); -+ g_fwupd_settings.random_number_valid = false; -+ fwupd_settings_unlock(); -+ } -+ } -+ -+ if (g_fwupd_settings.start_update) { -+ update_processing_status(IMG_VALIDATING, 0); -+ -+ rc = verify_image(); -+ if (rc != 0) { -+ update_processing_status(UPDATE_ERROR, 100); -+ /* Adding delay to make consumer gets status */ -+ mdelay(WAIT_STATE_TIMEOUT); -+ -+ reset_all_settings(); -+ continue; -+ } -+ -+ update_processing_status(IMG_PROGRAMMING, 10); -+ -+ rc = flash_image(); -+ if (rc == 0) { -+ /* Update successful, change the boot command */ -+ boot_addr = get_flash_image_address(); -+ snprintf(boot_cmd, sizeof(boot_cmd), -+ "bootm %08x", boot_addr); -+ setenv("bootcmd", boot_cmd); -+ saveenv(); -+ -+ update_processing_status(UPDATE_SUCCESSFUL, -+ 100); -+ } else { -+ update_processing_status(UPDATE_ERROR, 100); -+ } -+ -+ /* Adding delay to make sure consumer gets status */ -+ mdelay(WAIT_STATE_TIMEOUT); -+ -+ reset_all_settings(); -+ -+ /* Reset BMC */ -+ do_reset(NULL, 0, 0, NULL); -+ } -+ mdelay(WAIT_STATE_TIMEOUT); -+ } -+ -+ return; -+} -+ -+#if 1 /* Debug purpose */ -+int do_fwupd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -+{ -+ if (argc != 1) -+ return 1; -+ -+ start_fw_update_loop(); -+ return 0; -+} -+U_BOOT_CMD(fwupd, 1, 0, do_fwupd, "Start Firmware update process", ""); -+#endif -diff --git a/board/aspeed/ast-g5/fw-update.h b/board/aspeed/ast-g5/fw-update.h -new file mode 100644 -index 0000000..ed033ad ---- /dev/null -+++ b/board/aspeed/ast-g5/fw-update.h -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include <common.h> -+ -+/* SPI flash map */ -+#define MAX_FITIMAGE_SIZE 0x1B80000 -+#define PRIMARY_FITIMAGE_START_ADDR 0x20080000 -+#define SECONDARY_FITIMAGE_START_ADDR 0x22480000 -+#define IMAGE_LOAD_RAM_ADDR 0x83000000 -+ -+#define MAX_FILENAME_LENGTH 256 -+#define RAND_NUMBER_SIZE 8 -+ -+enum boot_image { -+ PRIMARY_IMAGE = 0x01, -+ SECONDARY_IMAGE = 0x02 -+}; -+ -+enum update_status { -+ INITIALIZING = 0, -+ IDLE, -+ IMG_DOWNLOADING, -+ IMG_VALIDATING, -+ IMG_PROGRAMMING, -+ UPDATE_SUCCESSFUL, -+ UPDATE_ERROR = 0x0F, -+ UPDATE_FORBIDDEN = 0x80, -+ AC_CYCLE_REQUIRED = 0x83 -+}; -+ -+struct fwupd_global_setting { -+ bool fwupd_mode_active; -+ bool start_update; -+ bool random_number_valid; -+ u8 ctrl_state; -+ u8 options_mask; -+ u8 options_value; -+ u8 processing_status; -+ u8 percentage_completion; -+ u8 integrity_check_status; -+ u8 filename_len; -+ u8 filename[MAX_FILENAME_LENGTH]; -+ u8 rand_num[RAND_NUMBER_SIZE]; -+}; -+ -+bool fwupd_settings_trylock(void); -+void fwupd_settings_unlock(void); -+u8 get_active_boot_image(void); -+int generate_random_number(void); -diff --git a/board/aspeed/ast-g5/ipmi-fwupd.c b/board/aspeed/ast-g5/ipmi-fwupd.c -new file mode 100644 -index 0000000..3eba056 ---- /dev/null -+++ b/board/aspeed/ast-g5/ipmi-fwupd.c -@@ -0,0 +1,402 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include "ipmi-fwupd.h" -+ -+struct fwupd_global_setting g_fwupd_settings; -+u32 g_write_addr = 0; -+ -+u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res) -+{ -+ int booting_image = 0x01; -+ struct fwupd_get_exe_ctx_res *result = -+ (struct fwupd_get_exe_ctx_res *)res; -+ -+ /* Get active image location(primary/secondary) */ -+ booting_image = get_active_boot_image(); -+ result->patition_ptr = booting_image; -+ result->exection_ctx = 0x11; /* Forced Firmware Update mode */ -+ -+ result->completion_code = IPMI_CC_OK; -+ return sizeof(struct fwupd_get_exe_ctx_res); -+} -+u16 fwupd_get_rand_number(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_rand_num_res *result = (struct fwupd_rand_num_res *)res; -+ -+ if (req_len != 0) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is critical operation is going on */ -+ if (g_fwupd_settings.start_update) { -+ printf("%s(): Update in progress.\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is it already in fwupdate mode */ -+ if (g_fwupd_settings.fwupd_mode_active) { -+ printf("%s(): Already in firmware update mode\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ if (generate_random_number() != 0) { -+ printf("%s(): Random number generation failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ result->completion_code = IPMI_CC_OK; -+ memcpy(result->rand_num, g_fwupd_settings.rand_num, RAND_NUMBER_SIZE); -+ -+ return sizeof(struct fwupd_rand_num_res); -+} -+ -+u16 fwupd_enter_update_mode(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_set_update_mode_res *result = -+ (struct fwupd_set_update_mode_res *)res; -+ -+ if (req_len != RAND_NUMBER_SIZE) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is critical operation is going on */ -+ if (g_fwupd_settings.start_update) { -+ printf("%s(): Update in progress.\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is it already in fwupdate mode */ -+ if (g_fwupd_settings.fwupd_mode_active) { -+ printf("%s(): Already in firmware update mode\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ /* This command should excute within 30 seconds -+ * after random number generation. */ -+ if (!g_fwupd_settings.random_number_valid) { -+ printf("%s(): No valid random number exist.\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_CODE; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Validate the key to enter this mode */ -+ for (int i = 0; i < RAND_NUMBER_SIZE; i++) { -+ if (req[i] != g_fwupd_settings.rand_num[i]) { -+ printf("%s(): Invalid key entered\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_CODE; -+ return sizeof(result->completion_code); -+ } -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ /* Reset all the settings */ -+ memset(&g_fwupd_settings, 0, sizeof(g_fwupd_settings)); -+ g_fwupd_settings.fwupd_mode_active = true; -+ fwupd_settings_unlock(); -+ -+ result->completion_code = IPMI_CC_OK; -+ -+ return sizeof(struct fwupd_set_update_mode_res); -+} -+ -+u16 fwupd_exit_update_mode(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_exit_update_mode_res *result = -+ (struct fwupd_exit_update_mode_res *)res; -+ -+ if (req_len != 0) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!g_fwupd_settings.fwupd_mode_active) { -+ printf("%s(): Invalid command entered\n", __func__); -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.fwupd_mode_active = false; -+ fwupd_settings_unlock(); -+ -+ result->completion_code = IPMI_CC_OK; -+ -+ return sizeof(struct fwupd_exit_update_mode_res); -+} -+u16 fwupd_set_options(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_options_req *options_req = (struct fwupd_options_req *)req; -+ struct fwupd_options_res *result = (struct fwupd_options_res *)res; -+ -+ if (req_len < 2) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is critical operation is going on */ -+ if (g_fwupd_settings.start_update) { -+ printf("%s(): Update in progress.\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Setting any reserved bits will result the command being rejected */ -+ if (((options_req->options_mask & 0xF0) != 0) || -+ ((options_req->options_value & 0xF0) != 0)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_FIELD; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.options_mask = options_req->options_mask; -+ g_fwupd_settings.options_value = options_req->options_value; -+ fwupd_settings_unlock(); -+ -+ result->completion_code = IPMI_CC_OK; -+ result->options_value = (g_fwupd_settings.options_mask & -+ g_fwupd_settings.options_value); -+ -+ return sizeof(struct fwupd_options_res); -+} -+ -+u16 fwupd_set_get_control(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_control_req *ctrl_req = (struct fwupd_control_req *)req; -+ struct fwupd_control_res *result = (struct fwupd_control_res *)res; -+ -+ if (req_len < 1) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is critical operation is going on */ -+ if (g_fwupd_settings.start_update) { -+ printf("%s(): Update in progress.\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ if ((ctrl_req->ctrl_state == SET_FW_FILENAME) && (req_len < 3)) { -+ printf("%s(): Invalid request data\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } else if ((ctrl_req->ctrl_state != SET_FW_FILENAME) && -+ (req_len != 1)) { -+ printf("%s(): Invalid request data\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ if ((!g_fwupd_settings.fwupd_mode_active) && -+ (ctrl_req->ctrl_state != GET_CTRL_STATE)) { -+ printf("%s(): Invalid request. Control State: %d.\n", __func__, -+ ctrl_req->ctrl_state); -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ switch (ctrl_req->ctrl_state) { -+ case GET_CTRL_STATE: -+ break; -+ case IMG_TRANSFER_START: -+ if ((g_fwupd_settings.ctrl_state & -+ IMG_TRANSFER_CTRL_BIT_START)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = -+ IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.processing_status = IMG_DOWNLOADING; -+ /* Reset control state during start */ -+ g_fwupd_settings.ctrl_state = 0x00; -+ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_START; -+ /* Set current write address to ZERO */ -+ g_write_addr = 0x00; -+ fwupd_settings_unlock(); -+ break; -+ case IMG_TRANSFER_END: -+ if (!(g_fwupd_settings.ctrl_state & -+ IMG_TRANSFER_CTRL_BIT_START)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = -+ IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.start_update = true; -+ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_END; -+ -+ g_fwupd_settings.ctrl_state &= ~(IMG_TRANSFER_CTRL_BIT_START | -+ IMG_TRANSFER_CTRL_BIT_ABORT); -+ fwupd_settings_unlock(); -+ break; -+ case IMG_TRANSFER_ABORT: -+ if (!(g_fwupd_settings.ctrl_state & -+ IMG_TRANSFER_CTRL_BIT_START)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = -+ IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.processing_status = UPDATE_ERROR; -+ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_ABORT; -+ g_fwupd_settings.ctrl_state &= ~(IMG_TRANSFER_CTRL_BIT_START | -+ IMG_TRANSFER_CTRL_BIT_END); -+ fwupd_settings_unlock(); -+ break; -+ case SET_FW_FILENAME: -+ /* Not supporting now */ -+ if (ctrl_req->filename_len > sizeof(ctrl_req->filename)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_FIELD; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!(g_fwupd_settings.ctrl_state & -+ IMG_TRANSFER_CTRL_BIT_START)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = -+ IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!fwupd_settings_trylock()) { -+ printf("%s(): Lock failed\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ g_fwupd_settings.filename_len = ctrl_req->filename_len; -+ strncpy(g_fwupd_settings.filename, ctrl_req->filename, -+ ctrl_req->filename_len); -+ fwupd_settings_unlock(); -+ /* TODO: Used for TFTP update but not implemented yet. */ -+ /* TODO: Verify image and write to flash */ -+ break; -+ case USB_DEV_ATTACH: -+ /* Not supporting now */ -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ case USB_DEV_DETACH: -+ /* Not supporting now */ -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ break; -+ default: -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_FIELD; -+ return sizeof(result->completion_code); -+ } -+ -+ result->completion_code = IPMI_CC_OK; -+ result->curr_state = g_fwupd_settings.ctrl_state; -+ return sizeof(struct fwupd_control_res); -+} -+u16 fwupd_get_update_status(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_get_update_status_res *result = -+ (struct fwupd_get_update_status_res *)res; -+ -+ if (req_len != 0) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ result->processing_status = g_fwupd_settings.processing_status; -+ result->percent_completion = g_fwupd_settings.percentage_completion; -+ result->check_status = 0; -+ /* We don't support error code messages cmd(0x0EH) in uboot.*/ -+ result->error_code = 0; -+ -+ result->completion_code = IPMI_CC_OK; -+ -+ return sizeof(struct fwupd_get_update_status_res); -+} -+ -+u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res) -+{ -+ struct fwupd_image_write_res *result = -+ (struct fwupd_image_write_res *)res; -+ -+ if (req_len < 1) { -+ printf("%s(): Invalid request length\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Check is critical operation is going on */ -+ if (g_fwupd_settings.start_update) { -+ printf("%s(): Update in progress.\n", __func__); -+ result->completion_code = IPMI_CC_NODE_BUSY; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!g_fwupd_settings.fwupd_mode_active) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if (!(g_fwupd_settings.ctrl_state & IMG_TRANSFER_CTRL_BIT_START)) { -+ printf("%s(): Invalid request\n", __func__); -+ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE; -+ return sizeof(result->completion_code); -+ } -+ -+ if ((g_write_addr + req_len) > MAX_FITIMAGE_SIZE) { -+ printf("%s(): Request length exceeded max size\n", __func__); -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ u8 *mem_addr = (u8 *)((u32)IMAGE_LOAD_RAM_ADDR + g_write_addr); -+ -+ memcpy(mem_addr, req, req_len); -+ g_write_addr += req_len; -+ -+ result->completion_code = IPMI_CC_OK; -+ result->no_of_bytes_written = (u8)req_len; -+ -+ return sizeof(struct fwupd_image_write_res); -+} -diff --git a/board/aspeed/ast-g5/ipmi-fwupd.h b/board/aspeed/ast-g5/ipmi-fwupd.h -new file mode 100644 -index 0000000..e490f6b ---- /dev/null -+++ b/board/aspeed/ast-g5/ipmi-fwupd.h -@@ -0,0 +1,81 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include "ipmi-handler.h" -+#include "fw-update.h" -+ -+enum control_state { -+ GET_CTRL_STATE = 0, -+ IMG_TRANSFER_START, -+ IMG_TRANSFER_END, -+ IMG_TRANSFER_ABORT, -+ SET_FW_FILENAME, -+ USB_DEV_ATTACH, -+ USB_DEV_DETACH -+}; -+enum control_state_bit { -+ IMG_TRANSFER_CTRL_BIT_START = (0x01 << 0), -+ IMG_TRANSFER_CTRL_BIT_END = (0x01 << 1), -+ IMG_TRANSFER_CTRL_BIT_ABORT = (0x01 << 2), -+ USB_CTRL_BIT_ATTACH = (0x01 << 3) -+}; -+enum update_options_bit { -+ NO_DOWN_REVISION = 0, -+ DEFER_BMC_RESET = 1, -+ SHA32_INTEGRITY_CHECK = 2, -+ CRC32_INTEGRITY_CHECK = 3 -+}; -+ -+struct fwupd_get_exe_ctx_res { -+ u8 completion_code; -+ u8 exection_ctx; -+ u8 patition_ptr; -+}; -+struct fwupd_rand_num_res { -+ u8 completion_code; -+ u8 rand_num[RAND_NUMBER_SIZE]; -+}; -+struct fwupd_set_update_mode_res { -+ u8 completion_code; -+}; -+struct fwupd_exit_update_mode_res { -+ u8 completion_code; -+}; -+struct fwupd_options_req { -+ u8 options_mask; -+ u8 options_value; -+ u8 integrity_check_value[32]; -+}; -+struct fwupd_options_res { -+ u8 completion_code; -+ u8 options_value; -+}; -+struct fwupd_control_req { -+ u8 ctrl_state; -+ u8 filename_len; -+ u8 filename[MAX_FILENAME_LENGTH]; -+}; -+struct fwupd_control_res { -+ u8 completion_code; -+ u8 curr_state; -+}; -+struct fwupd_get_update_status_res { -+ u8 completion_code; -+ u8 processing_status; -+ u8 percent_completion; -+ u8 check_status; -+ u8 error_code; -+}; -+struct fwupd_image_write_res { -+ u8 completion_code; -+ u8 no_of_bytes_written; -+}; -+ -+u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_get_rand_number(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_enter_update_mode(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_exit_update_mode(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_set_options(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_set_get_control(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_get_update_status(u8 *req, u16 req_len, u8 *res); -+u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res); -diff --git a/board/aspeed/ast-g5/ipmi-handler.c b/board/aspeed/ast-g5/ipmi-handler.c -index 9cccee9..5e78546 100644 ---- a/board/aspeed/ast-g5/ipmi-handler.c -+++ b/board/aspeed/ast-g5/ipmi-handler.c -@@ -1,18 +1,37 @@ -- - // SPDX-License-Identifier: GPL-2.0 - // Copyright (c) 2018-2019 Intel Corporation - --#include "ipmi-handler.h" -+#include "ipmi-fwupd.h" - - /* IPMI network function codes */ - #define NETFN_APP 0x06 -+#define NETFN_FIRMWARE 0x08 -+#define NETFN_INTEL_OEM 0x30 - - /* IPMI command codes */ --#define CMD_GET_DEV_ID 0x01 --#define CMD_GET_SELF_TEST_RESULTS 0x04 -+#define CMD_APP_GET_DEV_ID 0x01 -+#define CMD_APP_GET_SELF_TEST_RESULTS 0x04 -+#define CMD_FWUPD_GET_EXECUTION_CTX 0x23 -+#define CMD_FWUPD_GET_RANDOM_NUMBER 0x26 -+#define CMD_FWUPD_SET_UPDATE_MODE 0x27 -+#define CMD_FWUPD_EXIT_UPDATE_MODE 0x28 -+#define CMD_FWUPD_CONTROL_GET_SET 0x29 -+#define CMD_FWUPD_GET_UPDATE_STATUS 0x2A -+#define CMD_FWUPD_SET_OPTIONS 0x2B -+#define CMD_FWUPD_IMAGE_WRITE 0x2C -+#define CMD_INTL_OEM_GET_BUFFER_SIZE 0x66 -+ -+#define MAX_KCS_BUF_SIZE 1020 /* (0xFF * 4) */ -+#define MAX_IPMB_BUF_SIZE 1020 /* (0xFF * 4) */ - - typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res); - -+struct ipmi_cmd_table { -+ u8 net_fun; -+ u8 cmd; -+ fun_handler process_cmd; -+}; -+ - struct get_dev_id { - u8 completion_code; - u8 dev_id; -@@ -29,11 +48,10 @@ struct self_test_res { - u8 completion_code; - u8 res_byte[2]; - }; -- --struct ipmi_cmd_table { -- u8 net_fun; -- u8 cmd; -- fun_handler process_cmd; -+struct intc_get_buf_size_res { -+ u8 completion_code; -+ u8 kcs_size; -+ u8 ipmb_size; - }; - - static u16 get_device_id(u8 *req, u16 req_len, u8 *res) -@@ -84,10 +102,36 @@ static u16 get_self_test_result(u8 *req, u16 req_len, u8 *res) - - return sizeof(struct self_test_res); - } -+static u16 intel_get_buffer_size(u8 *req, u16 req_len, u8 *res) -+{ -+ struct intc_get_buf_size_res *result = -+ (struct intc_get_buf_size_res *)res; -+ -+ if (req_len != 0) { -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Size is multiples of four bytes */ -+ result->completion_code = IPMI_CC_OK; -+ result->kcs_size = MAX_KCS_BUF_SIZE / 4; -+ result->ipmb_size = MAX_IPMB_BUF_SIZE / 4; -+ -+ return sizeof(struct intc_get_buf_size_res); -+} - - const struct ipmi_cmd_table cmd_info[] = { -- { NETFN_APP, CMD_GET_DEV_ID, get_device_id }, -- { NETFN_APP, CMD_GET_SELF_TEST_RESULTS, get_self_test_result } -+ { NETFN_APP, CMD_APP_GET_DEV_ID, get_device_id }, -+ { NETFN_APP, CMD_APP_GET_SELF_TEST_RESULTS, get_self_test_result }, -+ { NETFN_FIRMWARE, CMD_FWUPD_GET_EXECUTION_CTX, fwupd_get_execution_ctx }, -+ { NETFN_FIRMWARE, CMD_FWUPD_GET_RANDOM_NUMBER, fwupd_get_rand_number }, -+ { NETFN_FIRMWARE, CMD_FWUPD_SET_UPDATE_MODE, fwupd_enter_update_mode }, -+ { NETFN_FIRMWARE, CMD_FWUPD_EXIT_UPDATE_MODE, fwupd_exit_update_mode }, -+ { NETFN_FIRMWARE, CMD_FWUPD_CONTROL_GET_SET, fwupd_set_get_control }, -+ { NETFN_FIRMWARE, CMD_FWUPD_GET_UPDATE_STATUS, fwupd_get_update_status }, -+ { NETFN_FIRMWARE, CMD_FWUPD_SET_OPTIONS, fwupd_set_options }, -+ { NETFN_FIRMWARE, CMD_FWUPD_IMAGE_WRITE, fwupd_image_write }, -+ { NETFN_INTEL_OEM, CMD_INTL_OEM_GET_BUFFER_SIZE, intel_get_buffer_size } - }; - - #define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info) -diff --git a/board/aspeed/ast-g5/ipmi-handler.h b/board/aspeed/ast-g5/ipmi-handler.h -index 9d46d9b..8eea930 100644 ---- a/board/aspeed/ast-g5/ipmi-handler.h -+++ b/board/aspeed/ast-g5/ipmi-handler.h -@@ -1,4 +1,3 @@ -- - /* SPDX-License-Identifier: GPL-2.0 */ - /* Copyright (c) 2018-2019 Intel Corporation */ - -@@ -6,12 +5,14 @@ - - /* IPMI completion codes */ - #define IPMI_CC_OK 0x00 -+#define IPMI_CC_INVALID_CODE 0x80 - #define IPMI_CC_NODE_BUSY 0xC0 - #define IPMI_CC_INVALID_CMD 0xC1 - #define IPMI_CC_INVALID_CMD_LUN 0xC2 - #define IPMI_CC_OUT_OF_SPACE 0xC4 - #define IPMI_CC_INVALID_DATA_LENGTH 0xC7 - #define IPMI_CC_INVALID_DATA_FIELD 0xCC -+#define IPMI_CC_NOT_SUPPORTED_IN_STATE 0xD5 - #define IPMI_CC_UNSPECIFIED 0xFF - - /* BMC IPMB LUNs */ -diff --git a/common/autoboot.c b/common/autoboot.c -index d66c0fa..3647d5f 100644 ---- a/common/autoboot.c -+++ b/common/autoboot.c -@@ -349,6 +349,19 @@ void autoboot_command(const char *s) - { - debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); - -+#ifdef AST_G5_INTEL -+ /* TODO: Make run_command_list as non-blocking(blocked by getc()) -+ * and make main u-boot loop to check both keyboard inputs as well -+ * as start_update firmware flags during FFUJ. -+ * This will make sure debug mode intact during FFUJ. -+ */ -+ if (intel_force_firmware_jumper_enabled()) { -+ printf("#### Force firmware update mode is enabled, " -+ "Serial console is disabled. ####\n"); -+ start_fw_update_loop(); -+ } -+#endif -+ - if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) { - #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) - int prev = disable_ctrlc(1); /* disable Control C checking */ -diff --git a/configs/ast_g5_phy_defconfig b/configs/ast_g5_phy_defconfig -index 1b96ab7..5965a9b 100644 ---- a/configs/ast_g5_phy_defconfig -+++ b/configs/ast_g5_phy_defconfig -@@ -15,3 +15,4 @@ CONFIG_SYS_NS16550=y - CONFIG_USE_IRQ=y - CONFIG_CMD_I2C=y - CONFIG_SYS_I2C_AST=y -+CONFIG_LIB_RAND=y --- -2.7.4 - |