diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2018-09-18 15:49:53 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-09-20 14:30:51 +1000 |
commit | 2649d663ede62c993fb433a04053770a9c6a49b9 (patch) | |
tree | f76f4ad4e137f66457c9ebb11a566fd0bb8d0f71 /core | |
parent | 5118fc7fb0ea0bdc4cbb5a286b38cfc259aa0de4 (diff) | |
download | skiboot-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.c | 5 | ||||
-rw-r--r-- | core/init.c | 47 |
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); } |