From fba5b3fa7c473fb356ce206ad2dbfe1c3917edfa Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:20 +0530 Subject: fwu: metadata: add functions for handling version specific metadata fields Support is being added in U-Boot for version 2 of the FWU metadata. Support for this version is to co-exist with version 1 support. To achieve this, a common, version agnostic structure has been added to keep information provided by the FWU metadata structure. Add API's to handle the version specific FWU metadata fields. The version agnostic structure gets initialized at boot by reading the FWU metadata. Updates to the FWU metadata result in the API's getting called to populate the version specific fields of the strucure, before the metadata gets written to the storage media. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_v1.c | 167 ++++++++++++++++++++++++++++++ lib/fwu_updates/fwu_v2.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 427 insertions(+) create mode 100644 lib/fwu_updates/fwu_v1.c create mode 100644 lib/fwu_updates/fwu_v2.c (limited to 'lib') diff --git a/lib/fwu_updates/fwu_v1.c b/lib/fwu_updates/fwu_v1.c new file mode 100644 index 00000000000..efb8d515008 --- /dev/null +++ b/lib/fwu_updates/fwu_v1.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include + +#include + +#define FWU_MDATA_VERSION 0x1U + +static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) +{ + u32 i; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + img_entry = &mdata->img_entry[0]; + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + img_bank_info = &img_entry[i].img_bank_info[bank]; + if (!img_bank_info->accepted) { + return 1; + } + } + + return 0; +} + +static void fwu_data_init(void) +{ + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + data->crc32 = mdata->crc32; + data->version = mdata->version; + data->active_index = mdata->active_index; + data->previous_active_index = mdata->previous_active_index; + + data->metadata_size = sizeof(struct fwu_mdata); + data->num_banks = CONFIG_FWU_NUM_BANKS; + data->num_images = CONFIG_FWU_NUM_IMAGES_PER_BANK; + fwu_plat_get_bootidx(&data->boot_index); + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); + + src_img_info = &mdata->img_entry[0]; + dst_img_info = &data->fwu_images[0]; + image_info_size = sizeof(data->fwu_images); + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +static int fwu_trial_state_update(bool trial_state) +{ + int ret; + struct fwu_data *data = fwu_get_data(); + + if (trial_state) { + ret = fwu_trial_state_ctr_start(); + if (ret) + return ret; + } + + data->trial_state = trial_state; + + return 0; +} + +/** + * fwu_populate_mdata_image_info() - Populate the image information + * of the metadata + * @data: Version agnostic FWU metadata information + * + * Populate the image information in the FWU metadata by copying it + * from the version agnostic structure. This is done before the + * metadata gets written to the storage media. + * + * Return: None + */ +void fwu_populate_mdata_image_info(struct fwu_data *data) +{ + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_mdata *mdata = data->fwu_mdata; + + image_info_size = sizeof(data->fwu_images); + dst_img_info = &mdata->img_entry[0]; + src_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +/** + * fwu_state_machine_updates() - Update FWU state of the platform + * @trial_state: Is platform transitioning into Trial State + * @update_index: Bank number to which images have been updated + * + * On successful completion of updates, transition the platform to + * either Trial State or Regular State. + * + * To transition the platform to Trial State, start the + * TrialStateCtr counter, followed by setting the value of bank_state + * field of the metadata to Valid state(applicable only in version 2 + * of metadata). + * + * In case, the platform is to transition directly to Regular State, + * update the bank_state field of the metadata to Accepted + * state(applicable only in version 2 of metadata). + * + * Return: 0 if OK, -ve on error + */ +int fwu_state_machine_updates(bool trial_state, + __maybe_unused uint32_t update_index) +{ + return fwu_trial_state_update(trial_state); +} + +/** + * fwu_get_mdata_size() - Get the FWU metadata size + * @mdata_size: Size of the metadata structure + * + * Get the size of the FWU metadata. + * + * Return: 0 if OK, -ve on error + */ +int fwu_get_mdata_size(uint32_t *mdata_size) +{ + *mdata_size = sizeof(struct fwu_mdata); + + return 0; +} + +/** + * fwu_init() - FWU specific initialisations + * + * Carry out some FWU specific initialisations including allocation + * of memory for the metadata copies, and reading the FWU metadata + * copies into the allocated memory. The metadata fields are then + * copied into a version agnostic structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_init(void) +{ + int ret; + uint32_t mdata_size; + + fwu_get_mdata_size(&mdata_size); + + ret = fwu_mdata_copies_allocate(mdata_size); + if (ret) + return ret; + + /* + * Now read the entire structure, both copies, and + * validate that the copies. + */ + ret = fwu_get_mdata(NULL); + if (ret) + return ret; + + fwu_data_init(); + + return 0; +} diff --git a/lib/fwu_updates/fwu_v2.c b/lib/fwu_updates/fwu_v2.c new file mode 100644 index 00000000000..108bc9bb4ac --- /dev/null +++ b/lib/fwu_updates/fwu_v2.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include +#include + +#include + +#define FWU_MDATA_VERSION 0x2U + +static inline struct fwu_fw_store_desc *fwu_get_fw_desc(struct fwu_mdata *mdata) +{ + return (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata)); +} + +static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) +{ + return mdata->bank_state[bank] == FWU_BANK_VALID ? 1 : 0; +} + +static void fwu_data_init(void) +{ + int i; + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + data->crc32 = mdata->crc32; + data->version = mdata->version; + data->active_index = mdata->active_index; + data->previous_active_index = mdata->previous_active_index; + data->metadata_size = mdata->metadata_size; + fwu_plat_get_bootidx(&data->boot_index); + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); + + data->num_banks = fwu_get_fw_desc(mdata)->num_banks; + data->num_images = fwu_get_fw_desc(mdata)->num_images; + + for (i = 0; i < 4; i++) { + data->bank_state[i] = mdata->bank_state[i]; + } + + image_info_size = sizeof(data->fwu_images); + src_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; + dst_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +static int fwu_mdata_sanity_checks(void) +{ + uint8_t num_banks; + uint16_t num_images; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + if (mdata->version != FWU_MDATA_VERSION) { + log_err("FWU metadata version %u. Expected value of %u\n", + mdata->version, FWU_MDATA_VERSION); + return -EINVAL; + } + + if (!mdata->desc_offset) { + log_err("No image information provided with the Metadata. "); + log_err("Image information expected in the metadata\n"); + return -EINVAL; + } + + if (mdata->desc_offset != 0x20) { + log_err("Descriptor Offset(0x%x) in the FWU Metadata not equal to 0x20\n", + mdata->desc_offset); + return -EINVAL; + } + + num_banks = fwu_get_fw_desc(mdata)->num_banks; + num_images = fwu_get_fw_desc(mdata)->num_images; + + if (num_banks != CONFIG_FWU_NUM_BANKS) { + log_err("Number of Banks(%u) in FWU Metadata different from the configured value(%d)", + num_banks, CONFIG_FWU_NUM_BANKS); + return -EINVAL; + } + + if (num_images != CONFIG_FWU_NUM_IMAGES_PER_BANK) { + log_err("Number of Images(%u) in FWU Metadata different from the configured value(%d)", + num_images, CONFIG_FWU_NUM_IMAGES_PER_BANK); + return -EINVAL; + } + + return 0; +} + +static int fwu_bank_state_update(bool trial_state, uint32_t bank) +{ + int ret; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + mdata->bank_state[bank] = data->bank_state[bank] = trial_state ? + FWU_BANK_VALID : FWU_BANK_ACCEPTED; + + ret = fwu_sync_mdata(mdata, BOTH_PARTS); + if (ret) + log_err("Unable to set bank_state for bank %u\n", bank); + else + data->trial_state = trial_state; + + return ret; +} + +static int fwu_trial_state_start(uint update_index) +{ + int ret; + + ret = fwu_trial_state_ctr_start(); + if (ret) + return ret; + + ret = fwu_bank_state_update(1, update_index); + if (ret) + return ret; + + return 0; +} + +/** + * fwu_populate_mdata_image_info() - Populate the image information + * of the metadata + * @data: Version agnostic FWU metadata information + * + * Populate the image information in the FWU metadata by copying it + * from the version agnostic structure. This is done before the + * metadata gets written to the storage media. + * + * Return: None + */ +void fwu_populate_mdata_image_info(struct fwu_data *data) +{ + size_t image_info_size; + struct fwu_mdata *mdata = data->fwu_mdata; + void *dst_img_info, *src_img_info; + + image_info_size = sizeof(data->fwu_images); + dst_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; + src_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +/** + * fwu_state_machine_updates() - Update FWU state of the platform + * @trial_state: Is platform transitioning into Trial State + * @update_index: Bank number to which images have been updated + * + * On successful completion of updates, transition the platform to + * either Trial State or Regular State. + * + * To transition the platform to Trial State, start the + * TrialStateCtr counter, followed by setting the value of bank_state + * field of the metadata to Valid state(applicable only in version 2 + * of metadata). + * + * In case, the platform is to transition directly to Regular State, + * update the bank_state field of the metadata to Accepted + * state(applicable only in version 2 of metadata). + * + * Return: 0 if OK, -ve on error + */ +int fwu_state_machine_updates(bool trial_state, uint32_t update_index) +{ + return trial_state ? fwu_trial_state_start(update_index) : + fwu_bank_state_update(0, update_index); +} + +/** + * fwu_get_mdata_size() - Get the FWU metadata size + * @mdata_size: Size of the metadata structure + * + * Get the size of the FWU metadata from the structure. This is later used + * to allocate memory for the structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_get_mdata_size(uint32_t *mdata_size) +{ + int ret = 0; + struct fwu_mdata mdata = { 0 }; + struct fwu_data *data = fwu_get_data(); + struct udevice *fwu_dev = fwu_get_dev(); + + if (data->metadata_size) { + *mdata_size = data->metadata_size; + return 0; + } + + ret = fwu_read_mdata(fwu_dev, &mdata, 1, + sizeof(struct fwu_mdata)); + if (ret) { + log_err("FWU metadata read failed\n"); + return ret; + } + + *mdata_size = mdata.metadata_size; + if (!*mdata_size) + return -EINVAL; + + return 0; +} + +/** + * fwu_init() - FWU specific initialisations + * + * Carry out some FWU specific initialisations including allocation + * of memory for the metadata copies, and reading the FWU metadata + * copies into the allocated memory. The metadata fields are then + * copied into a version agnostic structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_init(void) +{ + int ret; + struct fwu_mdata mdata = { 0 }; + struct udevice *fwu_dev = fwu_get_dev(); + + /* + * First we read only the top level structure + * and get the size of the complete structure. + */ + ret = fwu_read_mdata(fwu_dev, &mdata, 1, + sizeof(struct fwu_mdata)); + if (ret) { + log_err("FWU metadata read failed\n"); + return ret; + } + + ret = fwu_mdata_copies_allocate(mdata.metadata_size); + if (ret) + return ret; + + /* + * Now read the entire structure, both copies, and + * validate that the copies. + */ + ret = fwu_get_mdata(NULL); + if (ret) + return ret; + + ret = fwu_mdata_sanity_checks(); + if (ret) + return ret; + + fwu_data_init(); + + return 0; +} -- cgit v1.2.3 From ac62e0b62e02be0bb8c5f0d0dd49fa9bda91d5c5 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:21 +0530 Subject: fwu: make changes to access version agnostic structure fields With addition of support for version 2 of the FWU metadata structure, the metadata information is collected into a version agnostic structure. Make changes to the FWU functions so that the information that was earlier obtained by reading the metadata structure is now obtained through this version agnostic structure. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu.c | 204 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 66 deletions(-) (limited to 'lib') diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c index 86518108c2d..5dfea2a4d8d 100644 --- a/lib/fwu_updates/fwu.c +++ b/lib/fwu_updates/fwu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,7 @@ #include -static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid */ +struct fwu_data g_fwu_data; static struct udevice *g_dev; static u8 in_trial; static u8 boottime_check; @@ -27,12 +28,6 @@ enum { IMAGE_ACCEPT_CLEAR, }; -enum { - PRIMARY_PART = 1, - SECONDARY_PART, - BOTH_PARTS, -}; - static int trial_counter_update(u16 *trial_state_ctr) { bool delete; @@ -106,23 +101,9 @@ out: return ret; } -static int in_trial_state(struct fwu_mdata *mdata) +static u32 in_trial_state(void) { - u32 i, active_bank; - struct fwu_image_entry *img_entry; - struct fwu_image_bank_info *img_bank_info; - - active_bank = mdata->active_index; - img_entry = &mdata->img_entry[0]; - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - img_bank_info = &img_entry[i].img_bank_info[active_bank]; - if (!img_bank_info->accepted) { - log_info("System booting in Trial State\n"); - return 1; - } - } - - return 0; + return g_fwu_data.trial_state; } static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id) @@ -141,17 +122,70 @@ static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id) return -ENOENT; } +static int mdata_crc_check(struct fwu_mdata *mdata) +{ + int ret; + u32 calc_crc32; + uint32_t mdata_size; + void *buf = &mdata->version; + + ret = fwu_get_mdata_size(&mdata_size); + if (ret) + return ret; + + calc_crc32 = crc32(0, buf, mdata_size - sizeof(u32)); + return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; +} + +static void fwu_data_crc_update(uint32_t crc32) +{ + g_fwu_data.crc32 = crc32; +} + +/** + * fwu_get_data() - Return the version agnostic FWU structure + * + * Return the pointer to the version agnostic FWU structure. + * + * Return: Pointer to the FWU data structure + */ +struct fwu_data *fwu_get_data(void) +{ + return &g_fwu_data; +} + +static void fwu_populate_mdata_bank_index(struct fwu_data *fwu_data) +{ + struct fwu_mdata *mdata = fwu_data->fwu_mdata; + + mdata->active_index = fwu_data->active_index; + mdata->previous_active_index = fwu_data->previous_active_index; +} + +/** + * fwu_get_dev() - Return the FWU metadata device + * + * Return the pointer to the FWU metadata device. + * + * Return: Pointer to the FWU metadata dev + */ +struct udevice *fwu_get_dev(void) +{ + return g_dev; +} + /** * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided - * @mdata: FWU metadata structure + * @data: FWU Data structure * @part: Bitmask of FWU metadata partitions to be written to * * Return: 0 if OK, -ve on error */ -static int fwu_sync_mdata(struct fwu_mdata *mdata, int part) +int fwu_sync_mdata(struct fwu_mdata *mdata, int part) { - void *buf = &mdata->version; int err; + uint mdata_size; + void *buf = &mdata->version; if (part == BOTH_PARTS) { err = fwu_sync_mdata(mdata, SECONDARY_PART); @@ -160,32 +194,53 @@ static int fwu_sync_mdata(struct fwu_mdata *mdata, int part) part = PRIMARY_PART; } + err = fwu_get_mdata_size(&mdata_size); + if (err) + return err; + /* * Calculate the crc32 for the updated FWU metadata * and put the updated value in the FWU metadata crc32 * field */ - mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + mdata->crc32 = crc32(0, buf, mdata_size - sizeof(u32)); + fwu_data_crc_update(mdata->crc32); - err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART); + err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART, mdata_size); if (err) { log_err("Unable to write %s mdata\n", part == PRIMARY_PART ? "primary" : "secondary"); return err; } - /* update the cached copy of meta-data */ - memcpy(&g_mdata, mdata, sizeof(struct fwu_mdata)); - return 0; } -static inline int mdata_crc_check(struct fwu_mdata *mdata) +/** + * fwu_mdata_copies_allocate() - Allocate memory for metadata + * @mdata_size: Size of the metadata structure + * + * Allocate memory for storing both the copies of the FWU metadata. The + * copies are then used as a cache for storing FWU metadata contents. + * + * Return: 0 if OK, -ve on error + */ +int fwu_mdata_copies_allocate(u32 mdata_size) { - void *buf = &mdata->version; - u32 calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + if (g_fwu_data.fwu_mdata) + return 0; - return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; + /* + * Allocate the total memory that would be needed for both + * the copies. + */ + g_fwu_data.fwu_mdata = calloc(2, mdata_size); + if (!g_fwu_data.fwu_mdata) { + log_err("Unable to allocate space for FWU metadata\n"); + return -ENOMEM; + } + + return 0; } /** @@ -201,21 +256,33 @@ static inline int mdata_crc_check(struct fwu_mdata *mdata) int fwu_get_mdata(struct fwu_mdata *mdata) { int err; + uint32_t mdata_size; bool parts_ok[2] = { false }; - struct fwu_mdata s, *parts_mdata[2]; + struct fwu_mdata *parts_mdata[2]; - parts_mdata[0] = &g_mdata; - parts_mdata[1] = &s; + err = fwu_get_mdata_size(&mdata_size); + if (err) + return err; + + parts_mdata[0] = g_fwu_data.fwu_mdata; + if (!parts_mdata[0]) { + log_err("Memory not allocated for the FWU Metadata copies\n"); + return -ENOMEM; + } + + parts_mdata[1] = (struct fwu_mdata *)((char *)parts_mdata[0] + + mdata_size); /* if mdata already read and ready */ err = mdata_crc_check(parts_mdata[0]); if (!err) goto ret_mdata; - /* else read, verify and, if needed, fix mdata */ + + /* else read, verify and, if needed, fix mdata */ for (int i = 0; i < 2; i++) { parts_ok[i] = false; - err = fwu_read_mdata(g_dev, parts_mdata[i], !i); + err = fwu_read_mdata(g_dev, parts_mdata[i], !i, mdata_size); if (!err) { err = mdata_crc_check(parts_mdata[i]); if (!err) @@ -230,7 +297,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) * Before returning, check that both the * FWU metadata copies are the same. */ - err = memcmp(parts_mdata[0], parts_mdata[1], sizeof(struct fwu_mdata)); + err = memcmp(parts_mdata[0], parts_mdata[1], mdata_size); if (!err) goto ret_mdata; @@ -247,7 +314,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) if (parts_ok[i]) continue; - memcpy(parts_mdata[i], parts_mdata[1 - i], sizeof(struct fwu_mdata)); + memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size); err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART); if (err) { log_debug("mdata : %s write failed\n", i ? "secondary" : "primary"); @@ -257,7 +324,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) ret_mdata: if (!err && mdata) - memcpy(mdata, parts_mdata[0], sizeof(struct fwu_mdata)); + memcpy(mdata, parts_mdata[0], mdata_size); return err; } @@ -275,13 +342,13 @@ ret_mdata: int fwu_get_active_index(uint *active_idx) { int ret = 0; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; /* * Found the FWU metadata partition, now read the active_index * value */ - *active_idx = mdata->active_index; + *active_idx = data->active_index; if (*active_idx >= CONFIG_FWU_NUM_BANKS) { log_debug("Active index value read is incorrect\n"); ret = -EINVAL; @@ -302,7 +369,7 @@ int fwu_get_active_index(uint *active_idx) int fwu_set_active_index(uint active_idx) { int ret; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; if (active_idx >= CONFIG_FWU_NUM_BANKS) { log_debug("Invalid active index value\n"); @@ -313,14 +380,16 @@ int fwu_set_active_index(uint active_idx) * Update the active index and previous_active_index fields * in the FWU metadata */ - mdata->previous_active_index = mdata->active_index; - mdata->active_index = active_idx; + data->previous_active_index = data->active_index; + data->active_index = active_idx; + + fwu_populate_mdata_bank_index(data); /* * Now write this updated FWU metadata to both the * FWU metadata partitions */ - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); if (ret) { log_debug("Failed to update FWU metadata partitions\n"); ret = -EIO; @@ -346,7 +415,7 @@ int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num) int ret, i; uint update_bank; efi_guid_t *image_guid, image_type_id; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; struct fwu_image_entry *img_entry; struct fwu_image_bank_info *img_bank_info; @@ -365,15 +434,15 @@ int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num) ret = -EINVAL; /* - * The FWU metadata has been read. Now get the image_uuid for the + * The FWU metadata has been read. Now get the image_guid for the * image with the update_bank. */ for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { if (!guidcmp(&image_type_id, - &mdata->img_entry[i].image_type_uuid)) { - img_entry = &mdata->img_entry[i]; + &data->fwu_images[i].image_type_guid)) { + img_entry = &data->fwu_images[i]; img_bank_info = &img_entry->img_bank_info[update_bank]; - image_guid = &img_bank_info->image_uuid; + image_guid = &img_bank_info->image_guid; ret = fwu_plat_get_alt_num(g_dev, image_guid, alt_num); if (ret) log_debug("alt_num not found for partition with GUID %pUs\n", @@ -407,21 +476,23 @@ int fwu_revert_boot_index(void) { int ret; u32 cur_active_index; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; /* * Swap the active index and previous_active_index fields * in the FWU metadata */ - cur_active_index = mdata->active_index; - mdata->active_index = mdata->previous_active_index; - mdata->previous_active_index = cur_active_index; + cur_active_index = data->active_index; + data->active_index = data->previous_active_index; + data->previous_active_index = cur_active_index; + + fwu_populate_mdata_bank_index(data); /* * Now write this updated FWU metadata to both the * FWU metadata partitions */ - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); if (ret) { log_debug("Failed to update FWU metadata partitions\n"); ret = -EIO; @@ -448,20 +519,21 @@ int fwu_revert_boot_index(void) static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action) { int ret, i; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; struct fwu_image_entry *img_entry; struct fwu_image_bank_info *img_bank_info; - img_entry = &mdata->img_entry[0]; + img_entry = &data->fwu_images[0]; for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) { + if (!guidcmp(&img_entry[i].image_type_guid, img_type_id)) { img_bank_info = &img_entry[i].img_bank_info[bank]; if (action == IMAGE_ACCEPT_SET) img_bank_info->accepted |= FWU_IMAGE_ACCEPTED; else img_bank_info->accepted = 0; - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + fwu_populate_mdata_image_info(data); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); goto out; } } @@ -627,9 +699,9 @@ static int fwu_boottime_checks(void) return 0; } - ret = fwu_get_mdata(NULL); + ret = fwu_init(); if (ret) { - log_debug("Unable to read meta-data\n"); + log_debug("fwu_init() failed\n"); return ret; } @@ -665,7 +737,7 @@ static int fwu_boottime_checks(void) if (efi_init_obj_list() != EFI_SUCCESS) return 0; - in_trial = in_trial_state(&g_mdata); + in_trial = in_trial_state(); if (!in_trial || (ret = fwu_trial_count_update()) > 0) ret = trial_counter_update(NULL); -- cgit v1.2.3 From 5a5c4dedd3b15f75f3dae490c79b1691adc085e4 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:22 +0530 Subject: capsule: fwu: transition the platform state on a successful update Transition the platform to either Trial State or Regular State on a successful update. Do this by calling the fwu_state_machine_updates() API function. For version 1 of the FWU metadata, the transition to Trial State is done by starting the Trial State counter, while for version 2, in addition to the counter, the bank_state field of the FWU metadata is also updated to Valid. For transitioning the platform to Regular State, no action is needed with version 1 of the FWU metadata structure, while for version 2, the bank_state field is set to Accepted. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/efi_loader/efi_capsule.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index de0d49ebebd..0937800e588 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -480,6 +480,11 @@ static __maybe_unused efi_status_t fwu_empty_capsule_process( if (ret != EFI_SUCCESS) log_err("Unable to set the Accept bit for the image %pUs\n", image_guid); + + status = fwu_state_machine_updates(0, active_idx); + if (status < 0) + ret = EFI_DEVICE_ERROR; + } return ret; @@ -521,11 +526,10 @@ static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os) log_err("Failed to update FWU metadata index values\n"); } else { log_debug("Successfully updated the active_index\n"); - if (fw_accept_os) { - status = fwu_trial_state_ctr_start(); - if (status < 0) - ret = EFI_DEVICE_ERROR; - } + status = fwu_state_machine_updates(fw_accept_os ? 1 : 0, + update_index); + if (status < 0) + ret = EFI_DEVICE_ERROR; } return ret; -- cgit v1.2.3 From 222cd230e1644b8d327f921b820964e74ba0f1a4 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:23 +0530 Subject: fwu: add config symbols for enabling FWU metadata versions Support has been added for version 2 of the FWU metadata structure. Add config symbols to enable either of the two versions. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/Kconfig | 14 ++++++++++++++ lib/fwu_updates/Makefile | 2 ++ 2 files changed, 16 insertions(+) (limited to 'lib') diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index d35247d0e5d..51b7fbbefd3 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -31,4 +31,18 @@ config FWU_TRIAL_STATE_CNT the platform is allowed to boot in Trial State after an update. +config FWU_MDATA_V1 + bool "Enable support FWU Metadata version 1" + help + The FWU specification supports two versions of the + metadata structure. This option enables support for FWU + Metadata version 1 access. + +config FWU_MDATA_V2 + bool "Enable support FWU Metadata version 2" + help + The FWU specification supports two versions of the + metadata structure. This option enables support for FWU + Metadata version 2 access. + endif diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile index c9e3c06b489..3681bef46cd 100644 --- a/lib/fwu_updates/Makefile +++ b/lib/fwu_updates/Makefile @@ -6,3 +6,5 @@ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o +obj-$(CONFIG_FWU_MDATA_V1) += fwu_v1.o +obj-$(CONFIG_FWU_MDATA_V2) += fwu_v2.o -- cgit v1.2.3 From 840afae16f10a6f440b70488fdbf7ab59bf5686d Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:24 +0530 Subject: fwu: mtd: remove unused argument from function call The third argument passed to the function gen_image_alt_info() is not used and is superfluous. Remove this unused argument from the function call. Fixes: 4898679e190 (FWU: Add FWU metadata access driver for MTD storage regions) Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index 69cd3d7001f..d48de19009b 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -107,7 +107,7 @@ __weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_id, return fwu_mtd_get_alt_num(image_id, alt_num, "nor1"); } -static int gen_image_alt_info(char *buf, size_t len, int sidx, +static int gen_image_alt_info(char *buf, size_t len, struct fwu_image_entry *img, struct mtd_info *mtd) { char *p = buf, *end = buf + len; @@ -168,8 +168,7 @@ int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) } for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - ret = gen_image_alt_info(buf, len, i * CONFIG_FWU_NUM_BANKS, - &mdata.img_entry[i], mtd); + ret = gen_image_alt_info(buf, len, &mdata.img_entry[i], mtd); if (ret) break; -- cgit v1.2.3 From 1bef7198cd8f747ccd91cc103613afde96d4199f Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:25 +0530 Subject: fwu: mtd: get MTD partition specific info from driver Information about FWU images on MTD partitions is now stored with the corresponding driver instead of a global variable. Get this information from the driver. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index d48de19009b..f4e0e3107be 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -15,16 +15,21 @@ #include -struct fwu_mtd_image_info -fwu_mtd_images[CONFIG_FWU_NUM_BANKS * CONFIG_FWU_NUM_IMAGES_PER_BANK]; - static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf) { - int num_images = ARRAY_SIZE(fwu_mtd_images); + int num_images; + struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(fwu_get_dev()); + struct fwu_mtd_image_info *image_info = mtd_priv->fwu_mtd_images; + + if (!image_info) + return NULL; + + num_images = CONFIG_FWU_NUM_BANKS * + CONFIG_FWU_NUM_IMAGES_PER_BANK; for (int i = 0; i < num_images; i++) - if (!strcmp(uuidbuf, fwu_mtd_images[i].uuidbuf)) - return &fwu_mtd_images[i]; + if (!strcmp(uuidbuf, image_info[i].uuidbuf)) + return &image_info[i]; return NULL; } -- cgit v1.2.3 From 8ee8b9c900e350464ab2337ce0b0a7b2aa71f0f3 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:26 +0530 Subject: fwu: mtd: obtain image information from version agnostic structure Make changes to the functions used for generating the DFU's alt variable so that the FWU image information is obtained from the common version agnostic structure instead of reading the metadata. While here, also update the name of the field used for storing the image GUID in the FWU metadata. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index f4e0e3107be..e8211dd5baf 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -136,7 +136,7 @@ static int gen_image_alt_info(char *buf, size_t len, /* Query a partition by image UUID */ bank = &img->img_bank_info[i]; - uuid_bin_to_str(bank->image_uuid.b, uuidbuf, UUID_STR_FORMAT_STD); + uuid_bin_to_str(bank->image_guid.b, uuidbuf, UUID_STR_FORMAT_STD); mtd_img_info = mtd_img_by_uuid(uuidbuf); if (!mtd_img_info) { @@ -163,17 +163,13 @@ static int gen_image_alt_info(char *buf, size_t len, int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) { - struct fwu_mdata mdata; int i, l, ret; - - ret = fwu_get_mdata(&mdata); - if (ret < 0) { - log_err("Failed to get the FWU mdata.\n"); - return ret; - } + struct fwu_data *data = fwu_get_data(); + struct fwu_image_entry *img_entry; for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - ret = gen_image_alt_info(buf, len, &mdata.img_entry[i], mtd); + img_entry = &data->fwu_images[i]; + ret = gen_image_alt_info(buf, len, img_entry, mtd); if (ret) break; -- cgit v1.2.3