summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_capsule.c11
-rw-r--r--lib/fwu_updates/Kconfig1
-rw-r--r--lib/fwu_updates/fwu.c31
-rw-r--r--lib/fwu_updates/fwu_v1.c18
-rw-r--r--lib/fwu_updates/fwu_v2.c81
5 files changed, 97 insertions, 45 deletions
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index a4ea2873038..f8a4a7c6ef4 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -564,9 +564,14 @@ static efi_status_t efi_capsule_update_firmware(
bool fw_accept_os;
if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
- if (fwu_empty_capsule_checks_pass() &&
- fwu_empty_capsule(capsule_data))
- return fwu_empty_capsule_process(capsule_data);
+ if (fwu_empty_capsule(capsule_data)) {
+ if (fwu_empty_capsule_checks_pass()) {
+ return fwu_empty_capsule_process(capsule_data);
+ } else {
+ log_err("FWU empty capsule checks failed. Cannot start update\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ }
if (!fwu_update_checks_pass()) {
log_err("FWU checks failed. Cannot start update\n");
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
index 51b7fbbefd3..a722107c129 100644
--- a/lib/fwu_updates/Kconfig
+++ b/lib/fwu_updates/Kconfig
@@ -40,6 +40,7 @@ config FWU_MDATA_V1
config FWU_MDATA_V2
bool "Enable support FWU Metadata version 2"
+ depends on !FWU_MDATA_V1
help
The FWU specification supports two versions of the
metadata structure. This option enables support for FWU
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index c7fc8987beb..7f085a0211f 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -28,6 +28,31 @@ enum {
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;
@@ -88,6 +113,8 @@ static int fwu_trial_count_update(void)
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",
@@ -737,8 +764,8 @@ static int fwu_boottime_checks(void)
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;
diff --git a/lib/fwu_updates/fwu_v1.c b/lib/fwu_updates/fwu_v1.c
index efb8d515008..c311a8857a6 100644
--- a/lib/fwu_updates/fwu_v1.c
+++ b/lib/fwu_updates/fwu_v1.c
@@ -52,11 +52,14 @@ static void fwu_data_init(void)
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)
@@ -112,9 +115,9 @@ void fwu_populate_mdata_image_info(struct fwu_data *data)
* 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);
}
/**
@@ -146,6 +149,7 @@ int fwu_init(void)
{
int ret;
uint32_t mdata_size;
+ struct fwu_mdata mdata = {0};
fwu_get_mdata_size(&mdata_size);
@@ -157,10 +161,16 @@ int fwu_init(void)
* 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;
diff --git a/lib/fwu_updates/fwu_v2.c b/lib/fwu_updates/fwu_v2.c
index 108bc9bb4ac..ce46904ff2e 100644
--- a/lib/fwu_updates/fwu_v2.c
+++ b/lib/fwu_updates/fwu_v2.c
@@ -10,6 +10,9 @@
#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)
{
@@ -58,24 +61,6 @@ static int fwu_mdata_sanity_checks(void)
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;
@@ -100,6 +85,9 @@ static int fwu_bank_state_update(bool trial_state, uint32_t bank)
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;
@@ -127,6 +115,35 @@ static int fwu_trial_state_start(uint update_index)
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
@@ -187,24 +204,14 @@ int fwu_state_machine_updates(bool trial_state, uint32_t update_index)
*/
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;
@@ -224,21 +231,23 @@ int fwu_get_mdata_size(uint32_t *mdata_size)
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;