diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch deleted file mode 100644 index 392acb9ad..000000000 --- a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch +++ /dev/null @@ -1,530 +0,0 @@ -From bd0d8af493387ab1602a0a40b4a548981c1e4d00 Mon Sep 17 00:00:00 2001 -From: AppaRao Puli <apparao.puli@linux.intel.com> -Date: Wed, 24 Jul 2019 20:11:30 +0530 -Subject: [PATCH] PFR FW update and checkpoint support in u-boot - -1) Added firmware update ipmi commands support -for PFR images. This enables PFR based firmware -updates for components BMC, BIOS and CPLD during -FFUJ mode. - -2) Added two PFR boot flow checkpoint in u-boot - - Set the booting starts checkpoint(0x01) - - Set FFUJ checkpoint(0x07) when jumper on. - -Tested: - -Tested: -1) Using debug fwpiaupd.efi utility, validated the PFR -BMC image update via KCS ( In FFUJ mode). -2) Loaded the image, dumped all cpld registers and -cross verified the check-points properly set or not. - -Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> -Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com> ---- - board/aspeed/ast-g5/Makefile | 1 + - board/aspeed/ast-g5/ast-g5-intel.c | 10 +++ - board/aspeed/ast-g5/fw-update.c | 112 +++++++++++++++-------------- - board/aspeed/ast-g5/fw-update.h | 7 ++ - board/aspeed/ast-g5/ipmi-fwupd.c | 37 ++++++++++ - board/aspeed/ast-g5/ipmi-fwupd.h | 6 -- - board/aspeed/ast-g5/pfr-mgr.c | 73 +++++++++++++++++++ - board/aspeed/ast-g5/pfr-mgr.h | 73 +++++++++++++++++++ - 8 files changed, 258 insertions(+), 61 deletions(-) - create mode 100644 board/aspeed/ast-g5/pfr-mgr.c - create mode 100644 board/aspeed/ast-g5/pfr-mgr.h - -diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile -index 0b2d936c23..9021d7fc08 100644 ---- a/board/aspeed/ast-g5/Makefile -+++ b/board/aspeed/ast-g5/Makefile -@@ -8,3 +8,4 @@ obj-y += ast-g5-kcs.o - obj-y += ipmi-handler.o - obj-y += ipmi-fwupd.o - obj-y += fw-update.o -+obj-y += pfr-mgr.o -diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c -index dde5adbc70..6ef3ca9f73 100644 ---- a/board/aspeed/ast-g5/ast-g5-intel.c -+++ b/board/aspeed/ast-g5/ast-g5-intel.c -@@ -16,6 +16,7 @@ - #include "ast-g5.h" - #include "ast-g5-gpio.h" - #include "ast-g5-timer.h" -+#include "pfr-mgr.h" - - /* Names to match the GPIOs */ - enum gpio_names { -@@ -634,6 +635,10 @@ void ast_g5_intel(void) - ast_scu_write(ast_scu_read(AST_SCU_MISC1_CTRL) | - SCU_MISC_UART_DEBUG_DIS, AST_SCU_MISC1_CTRL); - -+ /* To notify the CPLD about the start of bootloader -+ * and hardware initialization */ -+ set_cpld_reg(PFR_CPLD_BOOT_CHECKPOINT_REG, PFR_CPLD_CHKPOINT_START); -+ - uart_init(); - pwm_init(); - gpio_init(gpio_table, ARRAY_SIZE(gpio_table)); -@@ -649,6 +654,11 @@ void ast_g5_intel(void) - kcs_init(); - if (intel_get_platform_id() == COOPER_CITY_BOARD_ID) - set_pwm_duty_cycle(ELEVATED_PWM_DUTY_VALUE); -+ /* Notify CPLD about FFUJ jumper set and pause -+ * of booting for indefinitely time. It will be -+ * resumed once reset is done. */ -+ set_cpld_reg(PFR_CPLD_BOOT_CHECKPOINT_REG, -+ PFR_CPLD_CHKPOINT_FFUJ); - /* TODO: need to stop the booting here. */ - } - } -diff --git a/board/aspeed/ast-g5/fw-update.c b/board/aspeed/ast-g5/fw-update.c -index 99239938b5..89fe5fd4fd 100644 ---- a/board/aspeed/ast-g5/fw-update.c -+++ b/board/aspeed/ast-g5/fw-update.c -@@ -6,6 +6,7 @@ - #include <flash.h> - - #include "fw-update.h" -+#include "pfr-mgr.h" - - #define BOOTCMD_BOOTM_STR "bootm " - #define RANDOM_NUM_TIMEOUT 30 /* in seconds */ -@@ -15,7 +16,7 @@ - #define PROTECT_ON 1 - - extern struct fwupd_global_setting g_fwupd_settings; --extern u32 g_write_addr; -+extern struct fwupd_image_info g_img_info; - - bool g_fwupd_settings_lock = false; - unsigned long long etime; -@@ -36,16 +37,8 @@ void fwupd_settings_unlock(void) - - u8 get_active_boot_image(void) - { -- char *bootcmd = getenv("bootcmd"); -- char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR); -+ /* For PFR, its always active region */ - 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; - } - -@@ -318,45 +311,22 @@ static int erase_flash_sector(ulong addr_first, ulong addr_last) - return rcode; - } - --static int verify_image(void) -+static int verify_image(ulong src_addr, ulong img_length) - { -- 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; -- } -- -+ /* TODO: Verify the hash alone here.*/ -+ /* Full image verification is done in CPLD. */ - return 0; - } - --static int flash_image(void) -+static int flash_image(ulong src_addr, ulong addr_first, ulong max_size, -+ ulong img_length) - { - 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)) { -+ if ((img_length > max_size) || (img_length == 0)) { - printf("ERROR: %s(): Invalid file uploaded. filesize(0x%08x)\n", -- __func__, g_write_addr); -+ __func__, img_length); - return -1; - } - -@@ -398,7 +368,7 @@ static int flash_image(void) - - /* write to flash area */ - printf("Copy to Flash... "); -- rcode = flash_write((char *)src_addr, addr_first, g_write_addr * 1); -+ rcode = flash_write((char *)src_addr, addr_first, img_length); - if (rcode != 0) { - printf("%s(): Flash copy failed(%d).\n", __func__, rcode); - flash_perror(rcode); -@@ -430,10 +400,27 @@ void start_fw_update_loop(void) - } - - if (g_fwupd_settings.start_update) { -+ printf("Starting image copy to staging area.....\n"); - update_processing_status(IMG_VALIDATING, 0); -- -- rc = verify_image(); -+ u8 update_intent = 0x00; -+ if ((g_fwupd_settings.options_mask & -+ g_fwupd_settings.options_value) & DEFER_BMC_RESET) -+ update_intent |= DEFER_UPDATES_TO_RESET; -+ -+ ulong offset = -+ get_flash_region_offset(g_img_info.img_type); -+ ulong max_size = -+ get_image_max_size(g_img_info.img_type); -+ ulong src_addr = IMAGE_LOAD_RAM_ADDR; -+ ulong flash_addr = PFR_IMAGE_STAGING_BASE_ADDR + offset; -+ -+ debug("FWUPD: offset:0x%08lx, max_size:0x%08lx, " -+ "src_addr:0x%08lx, flash_addr:0x%08lx\n", -+ offset, max_size, src_addr, flash_addr); -+ -+ rc = verify_image(src_addr, g_img_info.img_length); - if (rc != 0) { -+ printf("Image verification failed.\n"); - update_processing_status(UPDATE_ERROR, 100); - /* Adding delay to make consumer gets status */ - mdelay(WAIT_STATE_TIMEOUT); -@@ -441,31 +428,46 @@ void start_fw_update_loop(void) - reset_all_settings(); - continue; - } -+ printf("Image verification success.\n"); - - update_processing_status(IMG_PROGRAMMING, 10); - -- rc = flash_image(); -+ rc = flash_image(src_addr, flash_addr, max_size, -+ g_img_info.img_length); - 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(IMG_PROGRAMMING, 90); -+ } else { -+ update_processing_status(UPDATE_ERROR, 100); -+ } - -+ printf("Image copy to staging area %s.\n", -+ ((rc == 0) ? "successful" : "failed")); -+ -+ /* Set the BMC update intent BIT to CPLD register */ -+ update_intent != get_update_intent(g_img_info.img_type); -+ -+ /* TODO: We ned a way to protect the staging area from -+ * next write data. After setting cpld intent bit, CPLD -+ * read the stagging region for associated image types -+ * and update active/recovery area. During this stage, -+ * staging area should be protected from next write. -+ * Working with CPLD team for identifying this state. */ -+ if (0 != set_cpld_reg(PFR_CPLD_BMC_UPDATE_INTENT_REG, -+ update_intent)) { -+ update_processing_status(UPDATE_ERROR, 100); -+ } else { -+ printf("CPLD: Update intent set successfully.\n"); - update_processing_status(UPDATE_SUCCESSFUL, - 100); -- } else { -- update_processing_status(UPDATE_ERROR, 100); -+ -+ if (update_intent & DEFER_UPDATES_TO_RESET) -+ printf("CPLD: Update defered to next reset.\n"); - } - - /* 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); - } -diff --git a/board/aspeed/ast-g5/fw-update.h b/board/aspeed/ast-g5/fw-update.h -index ed033adfed..45e46ba596 100644 ---- a/board/aspeed/ast-g5/fw-update.h -+++ b/board/aspeed/ast-g5/fw-update.h -@@ -28,6 +28,12 @@ enum update_status { - UPDATE_FORBIDDEN = 0x80, - AC_CYCLE_REQUIRED = 0x83 - }; -+enum update_options { -+ NO_DOWN_REVISION = BIT(0), -+ DEFER_BMC_RESET = BIT(1), -+ SHA32_INTEGRITY_CHECK = BIT(2), -+ CRC32_INTEGRITY_CHECK = BIT(3) -+}; - - struct fwupd_global_setting { - bool fwupd_mode_active; -@@ -48,3 +54,4 @@ 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 -index 3eba056e7f..6afc8d66b7 100644 ---- a/board/aspeed/ast-g5/ipmi-fwupd.c -+++ b/board/aspeed/ast-g5/ipmi-fwupd.c -@@ -2,10 +2,14 @@ - // Copyright (c) 2018-2019 Intel Corporation - - #include "ipmi-fwupd.h" -+#include "pfr-mgr.h" - - struct fwupd_global_setting g_fwupd_settings; - u32 g_write_addr = 0; - -+struct fwupd_image_info g_img_info; -+static bool block0_mapped = false; -+ - u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res) - { - int booting_image = 0x01; -@@ -395,6 +399,39 @@ u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res) - memcpy(mem_addr, req, req_len); - g_write_addr += req_len; - -+ /* Get the PFR block 0 data and read the uploaded image -+ * information( Image type, length, hash etc) */ -+ if ((g_write_addr >= sizeof(struct pfr_image_block0)) && -+ (!block0_mapped)) { -+ struct pfr_image_block0 *block0_data = -+ (struct pfr_image_block0 *)IMAGE_LOAD_RAM_ADDR; -+ u32 magic_num = (u32)((*block0_data->tag) | -+ LSH(*(block0_data->tag + 1), 8) | -+ LSH(*(block0_data->tag + 2), 16) | -+ LSH(*(block0_data->tag + 3), 24)); -+ /* Validate the magic number */ -+ if (magic_num != PFR_BLOCK0_MAGIC_NUM) { -+ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; -+ return sizeof(result->completion_code); -+ } -+ -+ /* Fill the image info structure for later use */ -+ g_img_info.magic_num = magic_num; -+ g_img_info.img_length = -+ (u32)((*block0_data->pc_length) | -+ LSH(*(block0_data->pc_length + 1), 8) | -+ LSH(*(block0_data->pc_length + 2), 16) | -+ LSH(*(block0_data->pc_length + 3), 24)); -+ g_img_info.img_type = -+ (u32)((*block0_data->pc_type) | -+ LSH(*(block0_data->pc_type + 1), 8) | -+ LSH(*(block0_data->pc_type + 2), 16) | -+ LSH(*(block0_data->pc_type + 3), 24)); -+ /* Add Authentication data struct length for full image */ -+ g_img_info.img_length += PFR_AUTH_DATA_STRUCT_LEN; -+ block0_mapped = true; -+ } -+ - result->completion_code = IPMI_CC_OK; - result->no_of_bytes_written = (u8)req_len; - -diff --git a/board/aspeed/ast-g5/ipmi-fwupd.h b/board/aspeed/ast-g5/ipmi-fwupd.h -index e490f6b527..7409d2e2f9 100644 ---- a/board/aspeed/ast-g5/ipmi-fwupd.h -+++ b/board/aspeed/ast-g5/ipmi-fwupd.h -@@ -19,12 +19,6 @@ enum control_state_bit { - 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; -diff --git a/board/aspeed/ast-g5/pfr-mgr.c b/board/aspeed/ast-g5/pfr-mgr.c -new file mode 100644 -index 0000000000..77131688e7 ---- /dev/null -+++ b/board/aspeed/ast-g5/pfr-mgr.c -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include "pfr-mgr.h" -+ -+int set_cpld_reg(u8 reg_addr, u8 value) -+{ -+ int ret = 0; -+ int chip = (PFR_CPLD_SLAVE_ADDR >> 1); -+ -+ /* Get current I2C bus number to restore later. */ -+ int current_bus_no = i2c_get_bus_num(); -+ -+ /* Set I2C bus number to PFR CPLD I2C bus. */ -+ ret = i2c_set_bus_num(PFR_CPLD_I2C_BUSNO); -+ if (ret) { -+ printf("Failed to change I2C bus number (%d)\n", ret); -+ goto done; -+ } -+ -+ ret = i2c_write(chip, reg_addr, 1, &value, 1); -+ if (ret) { -+ printf("Error writing the chip: %d\n", ret); -+ goto done; -+ } -+ -+done: -+ /* Restore I2C bus number */ -+ if (i2c_set_bus_num(current_bus_no)) -+ printf("Failed to restore I2C bus number.\n"); -+ -+ return ret; -+} -+ -+ulong get_update_intent(u32 type) -+{ -+ ulong intent = 0; -+ if (type == PFR_CPLD_UPDATE_CAPSULE) -+ intent = CPLD_IMAGE_UPDATE; -+ else if (type == PFR_PCH_UPDATE_CAPSULE) -+ intent = PCH_SPI_FLASH_ACTIVE; -+ else if (type == PFR_BMC_UPDATE_CAPSULE) -+ intent = BMC_SPI_FLASH_ACTIVE; -+ -+ return intent; -+} -+ -+ulong get_image_max_size(u32 type) -+{ -+ ulong max_size = MAX_BMC_IMAGE_SIZE; -+ if (type == PFR_CPLD_UPDATE_CAPSULE) -+ max_size = MAX_CPLD_IMAGE_SIZE; -+ else if (type == PFR_PCH_UPDATE_CAPSULE) -+ max_size = MAX_BIOS_IMAGE_SIZE; -+ else if (type == PFR_BMC_UPDATE_CAPSULE) -+ max_size = MAX_BMC_IMAGE_SIZE; -+ -+ return max_size; -+} -+ -+ulong get_flash_region_offset(u32 type) -+{ -+ ulong offset = 0; -+ if (type == PFR_CPLD_UPDATE_CAPSULE) -+ offset = PFR_CPLD_IMAGE_REGION_OFFSET; -+ else if (type == PFR_PCH_UPDATE_CAPSULE) -+ offset = PFR_BIOS_IMAGE_REGION_OFFSET; -+ else if (type == PFR_BMC_UPDATE_CAPSULE) -+ offset = PFR_BMC_IMAGE_REGION_OFFSET; -+ -+ return offset; -+} -+ -diff --git a/board/aspeed/ast-g5/pfr-mgr.h b/board/aspeed/ast-g5/pfr-mgr.h -new file mode 100644 -index 0000000000..5c5b98bbe0 ---- /dev/null -+++ b/board/aspeed/ast-g5/pfr-mgr.h -@@ -0,0 +1,73 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// Copyright (c) 2018-2019 Intel Corporation -+ -+#include <common.h> -+ -+/* CPLD I2C device defines */ -+#define PFR_CPLD_I2C_BUSNO 4 -+#define PFR_CPLD_SLAVE_ADDR 0x70 -+ -+/* CPLD registers */ -+#define PFR_CPLD_BOOT_CHECKPOINT_REG 0x0F -+#define PFR_CPLD_BMC_UPDATE_INTENT_REG 0x13 -+ -+/* PFR checkpoints */ -+#define PFR_CPLD_CHKPOINT_START 0x01 -+#define PFR_CPLD_CHKPOINT_FFUJ 0x07 -+#define PFR_CPLD_CHKPOINT_FINISHED 0x09 -+ -+#define PFR_BLOCK0_MAGIC_NUM 0xB6EAFD19 -+#define PFR_AUTH_DATA_STRUCT_LEN 1024 /* Block0 & Block1 */ -+ -+/* SPI Flash MAP */ -+#define PFR_IMAGE_STAGING_BASE_ADDR 0x24A00000 /* 54MB */ -+#define MAX_BMC_IMAGE_SIZE 0x2000000 /* 32MB */ -+#define MAX_BIOS_IMAGE_SIZE 0x1000000 /* 16MB */ -+#define MAX_CPLD_IMAGE_SIZE 0x400000 /* 4MB */ -+#define PFR_BMC_IMAGE_REGION_OFFSET 0 -+#define PFR_BIOS_IMAGE_REGION_OFFSET \ -+ (PFR_BMC_IMAGE_REGION_OFFSET + MAX_BMC_IMAGE_SIZE) -+#define PFR_CPLD_IMAGE_REGION_OFFSET \ -+ (PFR_BIOS_IMAGE_REGION_OFFSET + MAX_BIOS_IMAGE_SIZE) -+ -+#define LSH(data, num) ((data) << (num)) -+ -+/* Bit mapping for CPLD 'BMC update intent' */ -+enum cpld_update_intent { -+ PCH_SPI_FLASH_ACTIVE = BIT(0), -+ PCH_SPI_FLASH_RECOVERY = BIT(1), -+ CPLD_IMAGE_UPDATE = BIT(2), -+ BMC_SPI_FLASH_ACTIVE = BIT(3), -+ BMC_SPI_FLASH_RECOVERY = BIT(4), -+ DEFER_UPDATES_TO_RESET = BIT(7) -+}; -+ -+enum pfr_block0_pc_type { -+ PFR_CPLD_UPDATE_CAPSULE = 0x00, -+ PFR_PCH_PFM = 0x01, -+ PFR_PCH_UPDATE_CAPSULE = 0x02, -+ PFR_BMC_PFM = 0x03, -+ PFR_BMC_UPDATE_CAPSULE = 0x04 -+}; -+ -+/* PFR image block 0 - As defined in HAS */ -+struct pfr_image_block0 { -+ u8 tag[4]; -+ u8 pc_length[4]; -+ u8 pc_type[4]; -+ u8 reserved_1[4]; -+ u8 hash_256[32]; -+ u8 hash_384[48]; -+ u8 reserved_2[32]; -+}; -+ -+struct fwupd_image_info { -+ u32 magic_num; -+ u32 img_length; -+ u32 img_type; -+}; -+ -+int set_cpld_reg(u8 reg_addr, u8 value); -+ulong get_update_intent(u32 type); -+ulong get_flash_region_offset(u32 type); -+ulong get_image_max_size(u32 type); --- -2.17.1 - |