aboutsummaryrefslogtreecommitdiff
path: root/core/nvram.c
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2015-06-24 17:02:50 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-06-24 17:02:50 +1000
commite3e38fcc77e49378db230f06b5f38e3814229aae (patch)
treef8f807f23a40801b9ae46cb59569cd3b3f737679 /core/nvram.c
parente5b053749e75e959aa5cafc875327b66f571e73a (diff)
downloadskiboot-e3e38fcc77e49378db230f06b5f38e3814229aae.zip
skiboot-e3e38fcc77e49378db230f06b5f38e3814229aae.tar.gz
skiboot-e3e38fcc77e49378db230f06b5f38e3814229aae.tar.bz2
Move NVRAM format/check code out into separate file to unit test
We (slightly) change the internal API so that we operate on parameters rather than globals, this means it's easier to unit test too. Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/nvram.c')
-rw-r--r--core/nvram.c140
1 files changed, 8 insertions, 132 deletions
diff --git a/core/nvram.c b/core/nvram.c
index f25d6aa..bde2dce 100644
--- a/core/nvram.c
+++ b/core/nvram.c
@@ -20,6 +20,7 @@
#include <lock.h>
#include <device.h>
#include <platform.h>
+#include <nvram-format.h>
static void *nvram_image;
static uint32_t nvram_size;
@@ -50,137 +51,6 @@ static int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset)
}
opal_call(OPAL_WRITE_NVRAM, opal_write_nvram, 3);
-struct chrp_nvram_hdr {
- uint8_t sig;
- uint8_t cksum;
- uint16_t len;
- char name[12];
-};
-
-#define NVRAM_SIG_FW_PRIV 0x51
-#define NVRAM_SIG_SYSTEM 0x70
-#define NVRAM_SIG_FREE 0x7f
-
-#define NVRAM_NAME_COMMON "common"
-#define NVRAM_NAME_FW_PRIV "ibm,skiboot"
-#define NVRAM_NAME_FREE "wwwwwwwwwwww"
-
-/* 64k should be enough, famous last words... */
-#define NVRAM_SIZE_COMMON 0x10000
-
-/* 4k should be enough, famous last words... */
-#define NVRAM_SIZE_FW_PRIV 0x1000
-
-static uint8_t chrp_nv_cksum(struct chrp_nvram_hdr *hdr)
-{
- struct chrp_nvram_hdr h_copy = *hdr;
- uint8_t b_data, i_sum, c_sum;
- uint8_t *p = (uint8_t *)&h_copy;
- unsigned int nbytes = sizeof(h_copy);
-
- h_copy.cksum = 0;
- for (c_sum = 0; nbytes; nbytes--) {
- b_data = *(p++);
- i_sum = c_sum + b_data;
- if (i_sum < c_sum)
- i_sum++;
- c_sum = i_sum;
- }
- return c_sum;
-}
-
-static void nvram_format(void)
-{
- struct chrp_nvram_hdr *h;
- unsigned int offset = 0;
-
- prerror("NVRAM: Re-initializing\n");
- memset(nvram_image, 0, nvram_size);
-
- /* Create private partition */
- h = nvram_image + offset;
- h->sig = NVRAM_SIG_FW_PRIV;
- h->len = NVRAM_SIZE_FW_PRIV >> 4;
- strcpy(h->name, NVRAM_NAME_FW_PRIV);
- h->cksum = chrp_nv_cksum(h);
- offset += NVRAM_SIZE_FW_PRIV;
-
- /* Create common partition */
- h = nvram_image + offset;
- h->sig = NVRAM_SIG_SYSTEM;
- h->len = NVRAM_SIZE_COMMON >> 4;
- strcpy(h->name, NVRAM_NAME_COMMON);
- h->cksum = chrp_nv_cksum(h);
- offset += NVRAM_SIZE_COMMON;
-
- /* Create free space partition */
- h = nvram_image + offset;
- h->sig = NVRAM_SIG_FREE;
- h->len = (nvram_size - offset) >> 4;
- strncpy(h->name, NVRAM_NAME_FREE, 12);
- h->cksum = chrp_nv_cksum(h);
-
- /* Write the whole thing back */
- if (platform.nvram_write)
- platform.nvram_write(0, nvram_image, nvram_size);
-}
-
-/*
- * Check that the nvram partition layout is sane and that it
- * contains our required partitions. If not, we re-format the
- * lot of it
- */
-static void nvram_check(void)
-{
- unsigned int offset = 0;
- bool found_common = false;
- bool found_skiboot = false;
-
- while (offset + sizeof(struct chrp_nvram_hdr) < nvram_size) {
- struct chrp_nvram_hdr *h = nvram_image + offset;
-
- if (chrp_nv_cksum(h) != h->cksum) {
- prerror("NVRAM: Partition at offset 0x%x"
- " has bad checksum\n", offset);
- goto failed;
- }
- if (h->len < 1) {
- prerror("NVRAM: Partition at offset 0x%x"
- " has incorrect 0 length\n", offset);
- goto failed;
- }
-
- if (h->sig == NVRAM_SIG_SYSTEM &&
- strcmp(h->name, NVRAM_NAME_COMMON) == 0)
- found_common = true;
-
- if (h->sig == NVRAM_SIG_FW_PRIV &&
- strcmp(h->name, NVRAM_NAME_FW_PRIV) == 0)
- found_skiboot = true;
-
- offset += h->len << 4;
- if (offset > nvram_size) {
- prerror("NVRAM: Partition at offset 0x%x"
- " extends beyond end of nvram !\n", offset);
- goto failed;
- }
- }
- if (!found_common) {
- prerror("NVRAM: Common partition not found !\n");
- goto failed;
- }
- if (!found_skiboot) {
- prerror("NVRAM: Skiboot private partition "
- "not found !\n");
- goto failed;
- }
-
- prerror("NVRAM: Layout appears sane\n");
- return;
- failed:
- nvram_format();
-}
-
void nvram_read_complete(bool success)
{
struct dt_node *np;
@@ -193,7 +63,13 @@ void nvram_read_complete(bool success)
}
/* Check and maybe format nvram */
- nvram_check();
+ if (nvram_check(nvram_image, nvram_size)) {
+ nvram_format(nvram_image, nvram_size);
+
+ /* Write the whole thing back */
+ if (platform.nvram_write)
+ platform.nvram_write(0, nvram_image, nvram_size);
+ }
/* Add nvram node */
np = dt_new(opal_node, "nvram");