aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2016-09-28 14:56:29 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-10-14 16:41:39 +1100
commita18e2809afa0e649224b40bf5b4bbe1d87193a89 (patch)
treebcaeb8408e51479979290a254aec12aef6fc7d6f /core
parent5a1da9a008724586433107ad9576c4fa0191307e (diff)
downloadskiboot-a18e2809afa0e649224b40bf5b4bbe1d87193a89.zip
skiboot-a18e2809afa0e649224b40bf5b4bbe1d87193a89.tar.gz
skiboot-a18e2809afa0e649224b40bf5b4bbe1d87193a89.tar.bz2
nvram: force re-verification after writing
The running OS is free to re-write the contents of NVRAM. The skiboot NVRAM parser relies on the NVRAM contents being valid so we need to force the NVRAM contents to be revalidated after the host OS has written to it. Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core')
-rw-r--r--core/nvram-format.c23
-rw-r--r--core/nvram.c45
-rw-r--r--core/test/run-nvram-format.c5
3 files changed, 56 insertions, 17 deletions
diff --git a/core/nvram-format.c b/core/nvram-format.c
index 227147e..b98aee1 100644
--- a/core/nvram-format.c
+++ b/core/nvram-format.c
@@ -208,12 +208,27 @@ static const char *find_next_key(const char *start, const char *end)
*/
const char *nvram_query(const char *key)
{
- const char *part_end = (const char *) skiboot_part_hdr +
- skiboot_part_hdr->len * 16 - 1;
- const char *start = (const char *) skiboot_part_hdr +
- sizeof(*skiboot_part_hdr);
+ const char *part_end, *start;
int key_len = strlen(key);
+ /*
+ * The running OS can modify the NVRAM as it pleases so we need to be
+ * a little paranoid and check that it's ok before we try parse it.
+ *
+ * NB: nvram_validate() can update skiboot_part_hdr
+ */
+ if (!nvram_validate()) {
+ prerror("NVRAM: Look up for '%s' failed due to bad format!\n",
+ key);
+ return NULL;
+ }
+
+ part_end = (const char *) skiboot_part_hdr
+ + skiboot_part_hdr->len * 16 - 1;
+
+ start = (const char *) skiboot_part_hdr
+ + sizeof(*skiboot_part_hdr);
+
if (!key_len) {
prlog(PR_WARNING, "NVRAM: search key is empty!\n");
return NULL;
diff --git a/core/nvram.c b/core/nvram.c
index 3ae0f12..2140706 100644
--- a/core/nvram.c
+++ b/core/nvram.c
@@ -24,7 +24,9 @@
static void *nvram_image;
static uint32_t nvram_size;
-static bool nvram_ready;
+
+static bool nvram_ready; /* has the nvram been loaded? */
+static bool nvram_valid; /* is the nvram format ok? */
static int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset)
{
@@ -55,21 +57,37 @@ static int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset)
memcpy(nvram_image + offset, (void *)buffer, size);
if (platform.nvram_write)
platform.nvram_write(offset, nvram_image + offset, size);
+
+ /* The host OS has written to the NVRAM so we can't be sure that it's
+ * well formatted.
+ */
+ nvram_valid = false;
+
return OPAL_SUCCESS;
}
opal_call(OPAL_WRITE_NVRAM, opal_write_nvram, 3);
-static void nvram_validate(void)
+bool nvram_validate(void)
+{
+ if (!nvram_valid)
+ nvram_valid = !nvram_check(nvram_image, nvram_size);
+
+ return nvram_valid;
+}
+
+static void nvram_reformat(void)
{
- /* Check and maybe format nvram */
- if (nvram_check(nvram_image, nvram_size)) {
- if (nvram_format(nvram_image, nvram_size))
- prerror("NVRAM: Failed to format NVRAM!\n");
-
- /* Write the whole thing back */
- if (platform.nvram_write)
- platform.nvram_write(0, nvram_image, nvram_size);
+ if (nvram_format(nvram_image, nvram_size)) {
+ prerror("NVRAM: Failed to format NVRAM!\n");
+ nvram_valid = false;
+ return;
}
+
+ /* Write the whole thing back */
+ if (platform.nvram_write)
+ platform.nvram_write(0, nvram_image, nvram_size);
+
+ nvram_valid = true;
}
void nvram_reinit(void)
@@ -77,8 +95,8 @@ void nvram_reinit(void)
/* It's possible we failed to load nvram at boot. */
if (!nvram_ready)
nvram_init();
- else
- nvram_validate();
+ else if (!nvram_validate())
+ nvram_reformat();
}
void nvram_read_complete(bool success)
@@ -92,7 +110,8 @@ void nvram_read_complete(bool success)
return;
}
- nvram_validate();
+ if (!nvram_validate())
+ nvram_reformat();
/* Add nvram node */
np = dt_new(opal_node, "nvram");
diff --git a/core/test/run-nvram-format.c b/core/test/run-nvram-format.c
index 4bf3ae0..4ca2cde 100644
--- a/core/test/run-nvram-format.c
+++ b/core/test/run-nvram-format.c
@@ -18,6 +18,11 @@
#include "../nvram-format.c"
+bool nvram_validate(void)
+{
+ return true;
+}
+
static char *nvram_reset(void *nvram_image, int size)
{
struct chrp_nvram_hdr *h = nvram_image;