aboutsummaryrefslogtreecommitdiff
path: root/core
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
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')
-rw-r--r--core/Makefile.inc2
-rw-r--r--core/nvram-format.c149
-rw-r--r--core/nvram.c140
-rw-r--r--core/test/Makefile.check1
-rw-r--r--core/test/run-nvram-format.c31
5 files changed, 190 insertions, 133 deletions
diff --git a/core/Makefile.inc b/core/Makefile.inc
index d808cc9..83370c1 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -5,7 +5,7 @@ CORE_OBJS = relocate.o console.o stack.o init.o chip.o mem_region.o
CORE_OBJS += malloc.o lock.o cpu.o utils.o fdt.o opal.o interrupts.o
CORE_OBJS += timebase.o opal-msg.o pci.o pci-opal.o fast-reboot.o
CORE_OBJS += device.o exceptions.o trace.o affinity.o vpd.o
-CORE_OBJS += hostservices.o platform.o nvram.o hmi.o
+CORE_OBJS += hostservices.o platform.o nvram.o nvram-format.o hmi.o
CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o
CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o
diff --git a/core/nvram-format.c b/core/nvram-format.c
new file mode 100644
index 0000000..3ec0db2
--- /dev/null
+++ b/core/nvram-format.c
@@ -0,0 +1,149 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <skiboot.h>
+#include <nvram-format.h>
+
+/*
+ * NVRAM Format as specified in PAPR
+ */
+
+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;
+}
+
+void nvram_format(void *nvram_image, uint32_t nvram_size)
+{
+ 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);
+}
+
+/*
+ * Check that the nvram partition layout is sane and that it
+ * contains our required partitions. If not, we re-format the
+ * lot of it
+ */
+int nvram_check(void *nvram_image, const uint32_t nvram_size)
+{
+ 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 0;
+ failed:
+ return -1;
+}
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");
diff --git a/core/test/Makefile.check b/core/test/Makefile.check
index 56ce61d..dfe7360 100644
--- a/core/test/Makefile.check
+++ b/core/test/Makefile.check
@@ -8,6 +8,7 @@ CORE_TEST := core/test/run-device \
core/test/run-mem_region_release_unused \
core/test/run-mem_region_release_unused_noalloc \
core/test/run-mem_region_reservations \
+ core/test/run-nvram-format \
core/test/run-trace core/test/run-msg \
core/test/run-pel \
core/test/run-pool \
diff --git a/core/test/run-nvram-format.c b/core/test/run-nvram-format.c
new file mode 100644
index 0000000..7fb4217
--- /dev/null
+++ b/core/test/run-nvram-format.c
@@ -0,0 +1,31 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include "../nvram-format.c"
+
+int main(void)
+{
+ char *nvram_image = malloc(0x100000);
+
+ nvram_format(nvram_image, 0x100000);
+
+ assert(nvram_check(nvram_image, 0x100000) == 0);
+
+ free(nvram_image);
+ return 0;
+}