aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2018-09-18 15:49:53 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-09-20 14:30:51 +1000
commit2649d663ede62c993fb433a04053770a9c6a49b9 (patch)
treef76f4ad4e137f66457c9ebb11a566fd0bb8d0f71 /core
parent5118fc7fb0ea0bdc4cbb5a286b38cfc259aa0de4 (diff)
downloadskiboot-2649d663ede62c993fb433a04053770a9c6a49b9.zip
skiboot-2649d663ede62c993fb433a04053770a9c6a49b9.tar.gz
skiboot-2649d663ede62c993fb433a04053770a9c6a49b9.tar.bz2
fast-reboot: verify firmware "romem" checksum
This takes a checksum of skiboot memory after boot that should be unchanged during OS operation, and verifies it before allowing a fast reboot. This is not read-only memory from skiboot's point of view, beause it includes things like the opal branch table that gets populated during boot. This helps to improve the integrity of firmware against host and runtime firmware memory scribble bugs. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'core')
-rw-r--r--core/fast-reboot.c5
-rw-r--r--core/init.c47
2 files changed, 52 insertions, 0 deletions
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index 2d8dc02..8e95d83 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -100,6 +100,11 @@ static bool fast_reboot_sanity_check(void)
return false;
}
+ if (!verify_romem()) {
+ disable_fast_reboot("Inconsistent firmware romem checksum");
+ return false;
+ }
+
return true;
}
diff --git a/core/init.c b/core/init.c
index 8d092dd..a7e70c9 100644
--- a/core/init.c
+++ b/core/init.c
@@ -816,6 +816,51 @@ static void pci_nvram_init(void)
}
}
+static uint32_t mem_csum(void *_p, void *_e)
+{
+ size_t len = _e - _p;
+ uint32_t *p = _p;
+ uint32_t v1 = 0, v2 = 0;
+ uint32_t csum;
+ unsigned int i;
+
+ for (i = 0; i < len; i += 4) {
+ uint32_t v = *p++;
+ v1 += v;
+ v2 += v1;
+ }
+
+ csum = v1 ^ v2;
+
+ return csum;
+}
+
+static uint32_t romem_csum;
+
+static void checksum_romem(void)
+{
+ uint32_t csum;
+
+ romem_csum = 0;
+
+ csum = mem_csum(_start, _romem_end);
+ romem_csum ^= csum;
+ csum = mem_csum(__builtin_kernel_start, __builtin_kernel_end);
+ romem_csum ^= csum;
+}
+
+bool verify_romem(void)
+{
+ uint32_t old = romem_csum;
+ checksum_romem();
+ if (old != romem_csum) {
+ romem_csum = old;
+ prlog(PR_NOTICE, "OPAL checksums did not match\n");
+ return false;
+ }
+ return true;
+}
+
/* Called from head.S, thus no prototype. */
void main_cpu_entry(const void *fdt);
@@ -1177,6 +1222,8 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
/* On P9, switch to radix mode by default */
cpu_set_radix_mode();
+ checksum_romem();
+
load_and_boot_kernel(false);
}