IMAGE_ACCEPT_CLEAR,
};
+/**
+ * fwu_bank_accepted() - Has the bank been accepted
+ * @data: Version agnostic FWU metadata information
+ * @bank: Update bank to check
+ *
+ * Check in the given bank if all the images have been accepted.
+ *
+ * Return: true if all images accepted, false otherwise
+ */
+bool fwu_bank_accepted(struct fwu_data *data, uint32_t bank)
+{
+ u32 i;
+ struct fwu_image_entry *img_entry;
+ struct fwu_image_bank_info *img_bank_info;
+
+ img_entry = &data->fwu_images[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 false;
+ }
+
+ return true;
+}
+
static int trial_counter_update(u16 *trial_state_ctr)
{
bool delete;
ret = fwu_revert_boot_index();
if (ret)
log_err("Unable to revert active_index\n");
+
+ trial_counter_update(NULL);
ret = 1;
} else {
log_info("Trial State count: attempt %d out of %d\n",
return 0;
in_trial = in_trial_state();
- if (!in_trial || (ret = fwu_trial_count_update()) > 0)
- ret = trial_counter_update(NULL);
+
+ ret = in_trial ? fwu_trial_count_update() : trial_counter_update(NULL);
if (!ret)
boottime_check = 1;
memcpy(dst_img_info, src_img_info, image_info_size);
}
-static int fwu_trial_state_update(bool trial_state)
+static int fwu_trial_state_update(bool trial_state, uint32_t bank)
{
int ret;
struct fwu_data *data = fwu_get_data();
+ if (!trial_state && !fwu_bank_accepted(data, bank))
+ return 0;
+
if (trial_state) {
ret = fwu_trial_state_ctr_start();
if (ret)
* Return: 0 if OK, -ve on error
*/
int fwu_state_machine_updates(bool trial_state,
- __maybe_unused uint32_t update_index)
+ uint32_t update_index)
{
- return fwu_trial_state_update(trial_state);
+ return fwu_trial_state_update(trial_state, update_index);
}
/**
{
int ret;
uint32_t mdata_size;
+ struct fwu_mdata mdata = {0};
fwu_get_mdata_size(&mdata_size);
* Now read the entire structure, both copies, and
* validate that the copies.
*/
- ret = fwu_get_mdata(NULL);
+ ret = fwu_get_mdata(&mdata);
if (ret)
return ret;
+ if (mdata.version != 0x1) {
+ log_err("FWU metadata version %u. Expected value of %u\n",
+ mdata.version, FWU_MDATA_VERSION);
+ return -EINVAL;
+ }
+
fwu_data_init();
return 0;
#include <linux/types.h>
#define FWU_MDATA_VERSION 0x2U
+#define FWU_IMG_DESC_OFFSET 0x20U
+
+static struct fwu_mdata g_mdata;
static inline struct fwu_fw_store_desc *fwu_get_fw_desc(struct fwu_mdata *mdata)
{
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;
struct fwu_data *data = fwu_get_data();
struct fwu_mdata *mdata = data->fwu_mdata;
+ if (!trial_state && !fwu_bank_accepted(data, bank))
+ return 0;
+
mdata->bank_state[bank] = data->bank_state[bank] = trial_state ?
FWU_BANK_VALID : FWU_BANK_ACCEPTED;
return 0;
}
+static bool fwu_get_mdata_mandatory(uint part)
+{
+ int ret = 0;
+ struct udevice *fwu_dev = fwu_get_dev();
+
+ memset(&g_mdata, 0, sizeof(struct fwu_mdata));
+
+ ret = fwu_read_mdata(fwu_dev, &g_mdata,
+ part == PRIMARY_PART ? true : false,
+ sizeof(struct fwu_mdata));
+ if (ret)
+ return false;
+
+ if (g_mdata.version != FWU_MDATA_VERSION) {
+ log_err("FWU partition %u has metadata version %u. Expected value of %u\n",
+ part, g_mdata.version, FWU_MDATA_VERSION);
+ return false;
+ }
+
+ if (g_mdata.desc_offset != FWU_IMG_DESC_OFFSET) {
+ log_err("Descriptor Offset(0x%x) in the FWU Metadata partition %u not equal to 0x20\n",
+ g_mdata.desc_offset, part);
+ log_err("Image information expected in the metadata\n");
+ return false;
+ }
+
+ return true;
+}
+
/**
* fwu_populate_mdata_image_info() - Populate the image information
* of the metadata
*/
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;
+ *mdata_size = g_mdata.metadata_size;
if (!*mdata_size)
return -EINVAL;
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.
+ * Try reading the first partition first, if
+ * that does not work, try the secondary
+ * partition. The idea is, if one of the
+ * partitions is corrupted, it should be restored
+ * from the intact partition.
*/
- ret = fwu_read_mdata(fwu_dev, &mdata, 1,
- sizeof(struct fwu_mdata));
- if (ret) {
+ if (!fwu_get_mdata_mandatory(PRIMARY_PART) &&
+ !fwu_get_mdata_mandatory(SECONDARY_PART)) {
log_err("FWU metadata read failed\n");
- return ret;
+ return -1;
}
- ret = fwu_mdata_copies_allocate(mdata.metadata_size);
+ ret = fwu_mdata_copies_allocate(g_mdata.metadata_size);
if (ret)
return ret;