Raul Rangel has uploaded this change for review.

View Change

WIP: Hash RAM contents on S3 entry and verify on S3 resume

I used murmur3 since it's supposed to be fast. Though I don't think the
license is really compatible.

The ram_hash code still needs some refactoring to reduce duplication and
to add the ability to handle unaligned blocks.

BUG=b:159081993
TEST=Boot trembyle and see no verification failures.

Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I6b38facba17bdd57a94987cfb49e71067ff8b769
---
M Makefile.inc
M src/arch/x86/acpi_s3.c
A src/include/murmur3.h
A src/include/ram_hash.h
M src/lib/Makefile.inc
A src/lib/murmur3.c
A src/lib/ram_hash.c
M src/soc/amd/picasso/chip.c
M src/soc/amd/picasso/memlayout.ld
M src/soc/amd/picasso/smihandler.c
10 files changed, 595 insertions(+), 2 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/90/42890/1
diff --git a/Makefile.inc b/Makefile.inc
index 86335d9..b7020e8 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -410,8 +410,8 @@
CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wimplicit-fallthrough
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits -Wvla
CFLAGS_common += -Wlogical-op -Wduplicated-cond -Wdangling-else
-CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
-CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
+CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fmit-frame-pointer
+CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie -Wno-implicit-fallthrough
ifeq ($(CONFIG_COMPILER_GCC),y)
# Don't add these GCC specific flags when running scan-build
ifeq ($(CCC_ANALYZER_OUTPUT_FORMAT),)
diff --git a/src/arch/x86/acpi_s3.c b/src/arch/x86/acpi_s3.c
index d4c697e..9c209b2 100644
--- a/src/arch/x86/acpi_s3.c
+++ b/src/arch/x86/acpi_s3.c
@@ -9,6 +9,7 @@
#include <cpu/x86/smm.h>
#include <fallback.h>
#include <timestamp.h>
+#include <ram_hash.h>
#include <romstage_handoff.h>

#if ENV_RAMSTAGE || ENV_POSTCAR
@@ -70,6 +71,8 @@

timestamp_add_now(TS_ACPI_WAKE_JUMP);

+ verify_ram();
+
acpi_do_wakeup((uintptr_t)vector);
}

diff --git a/src/include/murmur3.h b/src/include/murmur3.h
new file mode 100644
index 0000000..138f87f
--- /dev/null
+++ b/src/include/murmur3.h
@@ -0,0 +1,29 @@
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the
+// public domain. The author hereby disclaims copyright to this source
+// code.
+
+#ifndef _MURMURHASH3_H_
+#define _MURMURHASH3_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, uint32_t *out);
+
+void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out);
+
+void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out);
+
+//-----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _MURMURHASH3_H_
diff --git a/src/include/ram_hash.h b/src/include/ram_hash.h
new file mode 100644
index 0000000..67eaa76
--- /dev/null
+++ b/src/include/ram_hash.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef RAM_HASH_H
+#define RAM_HASH_H
+
+void hash_ram(void);
+void verify_ram(void);
+
+#endif /* RAM_HASH_H */
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index e0003bd..5bf0df2 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -145,6 +145,10 @@
ramstage-y += imd_cbmem.c
ramstage-y += imd.c

+bootblock-y += ram_hash.c crc32.c murmur3.c
+ramstage-y += ram_hash.c crc32.c murmur3.c
+smm-y += ram_hash.c crc32.c murmur3.c
+
postcar-$(CONFIG_VENDOR_EMULATION) += ramdetect.c
postcar-y += cbmem_common.c
postcar-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
diff --git a/src/lib/murmur3.c b/src/lib/murmur3.c
new file mode 100644
index 0000000..f2b6b18
--- /dev/null
+++ b/src/lib/murmur3.c
@@ -0,0 +1,314 @@
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+// Note - The x86 and x64 versions do _not_ produce the same results, as the
+// algorithms are optimized for their respective platforms. You can still
+// compile and run any of them on any platform, but your performance with the
+// non-native version will be less than optimal.
+
+#include "murmur3.h"
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+#ifdef __GNUC__
+#define FORCE_INLINE __attribute__((always_inline)) inline
+#else
+#define FORCE_INLINE inline
+#endif
+
+static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
+{
+ return (x << r) | (x >> (64 - r));
+}
+
+#define ROTL32(x,y) rotl32(x,y)
+#define ROTL64(x,y) rotl64(x,y)
+
+#define BIG_CONSTANT(x) (x##LLU)
+
+//-----------------------------------------------------------------------------
+// Block read - if your platform needs to do endian-swapping or can only
+// handle aligned reads, do the conversion here
+
+#define getblock(p, i) (p[i])
+
+//-----------------------------------------------------------------------------
+// Finalization mix - force all bits of a hash block to avalanche
+
+static FORCE_INLINE uint32_t fmix32 ( uint32_t h )
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+//----------
+
+static FORCE_INLINE uint64_t fmix64 ( uint64_t k )
+{
+ k ^= k >> 33;
+ k *= BIG_CONSTANT(0xff51afd7ed558ccd);
+ k ^= k >> 33;
+ k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
+ k ^= k >> 33;
+
+ return k;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 ( const void * key, int len,
+ uint32_t seed, uint32_t * out )
+{
+ const uint8_t * data = (const uint8_t*)key;
+ const int nblocks = len / 4;
+ int i;
+
+ uint32_t h1 = seed;
+
+ uint32_t c1 = 0xcc9e2d51;
+ uint32_t c2 = 0x1b873593;
+
+ //----------
+ // body
+
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
+
+ for(i = -nblocks; i; i++)
+ {
+ uint32_t k1 = getblock(blocks,i);
+
+ k1 *= c1;
+ k1 = ROTL32(k1,15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = ROTL32(h1,13);
+ h1 = h1*5+0xe6546b64;
+ }
+
+ //----------
+ // tail
+
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
+
+ uint32_t k1 = 0;
+
+ switch(len & 3)
+ {
+ case 3: k1 ^= tail[2] << 16;
+ case 2: k1 ^= tail[1] << 8;
+ case 1: k1 ^= tail[0];
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+ };
+
+ //----------
+ // finalization
+
+ h1 ^= len;
+
+ h1 = fmix32(h1);
+
+ *(uint32_t*)out = h1;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_128 ( const void * key, const int len,
+ uint32_t seed, void * out )
+{
+ const uint8_t * data = (const uint8_t*)key;
+ const int nblocks = len / 16;
+ int i;
+
+ uint32_t h1 = seed;
+ uint32_t h2 = seed;
+ uint32_t h3 = seed;
+ uint32_t h4 = seed;
+
+ uint32_t c1 = 0x239b961b;
+ uint32_t c2 = 0xab0e9789;
+ uint32_t c3 = 0x38b34ae5;
+ uint32_t c4 = 0xa1e38b93;
+
+ //----------
+ // body
+
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
+
+ for(i = -nblocks; i; i++)
+ {
+ uint32_t k1 = getblock(blocks,i*4+0);
+ uint32_t k2 = getblock(blocks,i*4+1);
+ uint32_t k3 = getblock(blocks,i*4+2);
+ uint32_t k4 = getblock(blocks,i*4+3);
+
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+
+ h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
+
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+
+ h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
+
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+
+ h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
+
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+
+ h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
+ }
+
+ //----------
+ // tail
+
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+ uint32_t k1 = 0;
+ uint32_t k2 = 0;
+ uint32_t k3 = 0;
+ uint32_t k4 = 0;
+
+ switch(len & 15)
+ {
+ case 15: k4 ^= tail[14] << 16;
+ case 14: k4 ^= tail[13] << 8;
+ case 13: k4 ^= tail[12] << 0;
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+
+ case 12: k3 ^= tail[11] << 24;
+ case 11: k3 ^= tail[10] << 16;
+ case 10: k3 ^= tail[ 9] << 8;
+ case 9: k3 ^= tail[ 8] << 0;
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+
+ case 8: k2 ^= tail[ 7] << 24;
+ case 7: k2 ^= tail[ 6] << 16;
+ case 6: k2 ^= tail[ 5] << 8;
+ case 5: k2 ^= tail[ 4] << 0;
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+
+ case 4: k1 ^= tail[ 3] << 24;
+ case 3: k1 ^= tail[ 2] << 16;
+ case 2: k1 ^= tail[ 1] << 8;
+ case 1: k1 ^= tail[ 0] << 0;
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+ };
+
+ //----------
+ // finalization
+
+ h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
+
+ h1 += h2; h1 += h3; h1 += h4;
+ h2 += h1; h3 += h1; h4 += h1;
+
+ h1 = fmix32(h1);
+ h2 = fmix32(h2);
+ h3 = fmix32(h3);
+ h4 = fmix32(h4);
+
+ h1 += h2; h1 += h3; h1 += h4;
+ h2 += h1; h3 += h1; h4 += h1;
+
+ ((uint32_t*)out)[0] = h1;
+ ((uint32_t*)out)[1] = h2;
+ ((uint32_t*)out)[2] = h3;
+ ((uint32_t*)out)[3] = h4;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x64_128 ( const void * key, const int len,
+ const uint32_t seed, void * out )
+{
+ const uint8_t * data = (const uint8_t*)key;
+ const int nblocks = len / 16;
+ int i;
+
+ uint64_t h1 = seed;
+ uint64_t h2 = seed;
+
+ uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
+ uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
+
+ //----------
+ // body
+
+ const uint64_t * blocks = (const uint64_t *)(data);
+
+ for(i = 0; i < nblocks; i++)
+ {
+ uint64_t k1 = getblock(blocks,i*2+0);
+ uint64_t k2 = getblock(blocks,i*2+1);
+
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+
+ h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
+
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+
+ h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
+ }
+
+ //----------
+ // tail
+
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+ uint64_t k1 = 0;
+ uint64_t k2 = 0;
+
+ switch(len & 15)
+ {
+ case 15: k2 ^= (uint64_t)(tail[14]) << 48;
+ case 14: k2 ^= (uint64_t)(tail[13]) << 40;
+ case 13: k2 ^= (uint64_t)(tail[12]) << 32;
+ case 12: k2 ^= (uint64_t)(tail[11]) << 24;
+ case 11: k2 ^= (uint64_t)(tail[10]) << 16;
+ case 10: k2 ^= (uint64_t)(tail[ 9]) << 8;
+ case 9: k2 ^= (uint64_t)(tail[ 8]) << 0;
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+
+ case 8: k1 ^= (uint64_t)(tail[ 7]) << 56;
+ case 7: k1 ^= (uint64_t)(tail[ 6]) << 48;
+ case 6: k1 ^= (uint64_t)(tail[ 5]) << 40;
+ case 5: k1 ^= (uint64_t)(tail[ 4]) << 32;
+ case 4: k1 ^= (uint64_t)(tail[ 3]) << 24;
+ case 3: k1 ^= (uint64_t)(tail[ 2]) << 16;
+ case 2: k1 ^= (uint64_t)(tail[ 1]) << 8;
+ case 1: k1 ^= (uint64_t)(tail[ 0]) << 0;
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+ };
+
+ //----------
+ // finalization
+
+ h1 ^= len; h2 ^= len;
+
+ h1 += h2;
+ h2 += h1;
+
+ h1 = fmix64(h1);
+ h2 = fmix64(h2);
+
+ h1 += h2;
+ h2 += h1;
+
+ ((uint64_t*)out)[0] = h1;
+ ((uint64_t*)out)[1] = h2;
+}
+
+//-----------------------------------------------------------------------------
diff --git a/src/lib/ram_hash.c b/src/lib/ram_hash.c
new file mode 100644
index 0000000..9f07183
--- /dev/null
+++ b/src/lib/ram_hash.c
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <murmur3.h>
+#include <ram_hash.h>
+#include <string.h>
+#include <lib.h>
+#include <console/console.h>
+#include <commonlib/bsd/helpers.h>
+
+#define HASH_BUFFER 0x2BD000
+#define EHASH_BUFFER 0x3BD000
+// extern char HASH_BUFFER[];
+// extern char EHASH_BUFFER[];
+
+struct hash_range {
+ uintptr_t start;
+ uintptr_t end;
+ unsigned int block_size;
+ unsigned int diff;
+};
+
+struct hash_entry {
+ uint32_t hash;
+ uint32_t data[];
+};
+
+struct hash_range mem_layout[] = {
+ {
+ .start = 0x1000,
+ .end = 0xa0000,
+ .block_size = 1 * KiB,
+ .diff = 1
+ },
+ {
+ .start = 0x3bd000,
+ .end = 0x3c0000,
+ .block_size = 4 * KiB,
+ .diff = 0
+ },
+ {
+ .start = 0x3c0000,
+ .end = 0xcc4c0000,
+ .block_size = 256 * KiB,
+ .diff = 0
+ },
+ {
+ .start = 0xcc4c0000,
+ .end = 0xcc51c000,
+ .block_size = 4 * KiB,
+ .diff = 0
+ },
+};
+
+static struct hash_entry *hash_range(const struct hash_range *range, struct hash_entry *entry,
+ size_t buffer_size)
+{
+ unsigned int total_blocks = (range->end - range->start) / range->block_size;
+ void *current;
+ unsigned int i;
+
+ for (i = 0; i < total_blocks; ++i) {
+ current = (void *)(range->start + i * range->block_size);
+
+ if (!(i % 256))
+ printk(BIOS_DEBUG, "%s: block %u/%u @ %p\n", __func__, i, total_blocks,
+ current);
+
+ // printk(BIOS_ERR, "%s: buffer_size: %zd\n", __func__, buffer_size);
+
+ if (buffer_size < sizeof(*entry)) {
+ printk(BIOS_ERR, "%s: Hash buffer is too small for entry\n", __func__);
+ return NULL;
+ }
+
+ // printk(BIOS_ERR, "%s: current: %p\n", __func__, current);
+ // printk(BIOS_ERR, "%s: current_entry: %p\n", __func__, entry);
+
+ /* Allocate one entry in the buffer */
+ buffer_size -= sizeof(*entry);
+
+ MurmurHash3_x86_32(current, range->block_size, 0xDEADBEEF, &entry->hash);
+ // printk(BIOS_ERR, "%s: crc: %#x\n", __func__, entry->hash);
+
+ if (range->diff) {
+ if (buffer_size < range->block_size) {
+ printk(BIOS_DEBUG, "%s: Hash buffer is too small for data\n",
+ __func__);
+ return NULL;
+ }
+
+ /* Allocate diff size in buffer */
+ buffer_size -= range->block_size;
+ memcpy(entry->data, current, range->block_size);
+
+ entry = (struct hash_entry *)((uintptr_t)(entry + 1)
+ + range->block_size);
+ } else {
+ entry++;
+ }
+ // printk(BIOS_ERR, "%s: next_entry: %p\n", __func__, entry);
+ }
+
+ return entry;
+}
+
+void hash_ram(void)
+{
+ struct hash_entry *current_entry = (struct hash_entry *)HASH_BUFFER;
+ struct hash_range *range;
+ unsigned int i;
+
+ printk(BIOS_INFO, "%s: Start: HASH_BUFFER: %#x, EHASH_BUFFER: %#x\n", __func__,
+ HASH_BUFFER, EHASH_BUFFER);
+
+ for (i = 0; i < ARRAY_SIZE(mem_layout); ++i) {
+ range = &mem_layout[i];
+ printk(BIOS_DEBUG, "%s: Hashing range %p -> %p\n", __func__,
+ (void *)range->start, (void *)range->end);
+ current_entry =
+ hash_range(range, current_entry,
+ ((uintptr_t)EHASH_BUFFER - (uintptr_t)current_entry));
+
+ if (!current_entry) {
+ printk(BIOS_ERR, "%s: Hash buffer is too small\n", __func__);
+ break;
+ }
+ }
+
+ printk(BIOS_INFO, "%s: Done\n", __func__);
+}
+
+static struct hash_entry *verify_range(const struct hash_range *range, struct hash_entry *entry,
+ size_t buffer_size)
+{
+ unsigned int total_blocks = (range->end - range->start) / range->block_size;
+ void *current;
+ unsigned int i;
+ uint32_t crc;
+
+ for (i = 0; i < total_blocks; ++i) {
+ current = (void *)(range->start + i * range->block_size);
+
+ if (!(i % 256))
+ printk(BIOS_DEBUG, "%s: block %u/%u @ %p\n", __func__, i, total_blocks,
+ current);
+
+ // printk(BIOS_ERR, "%s: buffer_size: %zd\n", __func__, buffer_size);
+
+ if (buffer_size < sizeof(*entry)) {
+ printk(BIOS_ERR, "%s: Hash buffer is too small for entry\n", __func__);
+ return NULL;
+ }
+
+ // printk(BIOS_ERR, "%s: current: %p\n", __func__, current);
+ // printk(BIOS_ERR, "%s: current_entry: %p\n", __func__, entry);
+
+ /* Allocate one entry in the buffer */
+ buffer_size -= sizeof(*entry);
+
+ MurmurHash3_x86_32(current, range->block_size, 0xDEADBEEF, &crc);
+ // printk(BIOS_ERR, "%s: crc: %#x\n", __func__, entry->hash);
+
+ if (crc != entry->hash) {
+ printk(BIOS_ERR, "%s: crc error at %p. %x != %x\n", __func__, current,
+ crc, entry->hash);
+ }
+
+ if (range->diff) {
+ if (buffer_size < range->block_size) {
+ printk(BIOS_DEBUG, "%s: Hash buffer is too small for data\n",
+ __func__);
+ return NULL;
+ }
+
+ /* Allocate diff size in buffer */
+ buffer_size -= range->block_size;
+
+ if (crc != entry->hash) {
+
+ printk(BIOS_ERR, "Expected:\n");
+ hexdump(entry->data, range->block_size);
+
+ printk(BIOS_ERR, "Actual:\n");
+ hexdump(current, range->block_size);
+ }
+
+ entry = (struct hash_entry *)((uintptr_t)(entry + 1)
+ + range->block_size);
+ } else {
+ entry++;
+ }
+ // printk(BIOS_ERR, "%s: next_entry: %p\n", __func__, entry);
+ }
+
+ return entry;
+}
+
+void verify_ram()
+{
+ struct hash_entry *current_entry = (struct hash_entry *)HASH_BUFFER;
+ struct hash_range *range;
+ unsigned int i;
+
+ printk(BIOS_INFO, "%s: Start: HASH_BUFFER: %#x, EHASH_BUFFER: %#x\n", __func__,
+ HASH_BUFFER, EHASH_BUFFER);
+
+ for (i = 0; i < ARRAY_SIZE(mem_layout); ++i) {
+ range = &mem_layout[i];
+ printk(BIOS_DEBUG, "%s: Verifying range %p -> %p\n", __func__,
+ (void *)range->start, (void *)range->end);
+ current_entry =
+ verify_range(range, current_entry,
+ ((uintptr_t)EHASH_BUFFER - (uintptr_t)current_entry));
+
+ if (!current_entry) {
+ printk(BIOS_ERR, "%s: Hash buffer is too small\n", __func__);
+ break;
+ }
+ }
+
+ printk(BIOS_INFO, "%s: Done\n", __func__);
+}
diff --git a/src/soc/amd/picasso/chip.c b/src/soc/amd/picasso/chip.c
index 2abe54e..678ce03 100644
--- a/src/soc/amd/picasso/chip.c
+++ b/src/soc/amd/picasso/chip.c
@@ -14,6 +14,7 @@
#include <soc/southbridge.h>
#include "chip.h"
#include <fsp/api.h>
+#include <ram_hash.h>

/* Supplied by i2c.c */
extern struct device_operations picasso_i2c_mmio_ops;
@@ -184,6 +185,7 @@
static void picasso_os_entry(void *unused)
{
picasso_disable_paging(NULL);
+ verify_ram();
}

struct chip_operations soc_amd_picasso_ops = {
diff --git a/src/soc/amd/picasso/memlayout.ld b/src/soc/amd/picasso/memlayout.ld
index 27c72a2..a128019 100644
--- a/src/soc/amd/picasso/memlayout.ld
+++ b/src/soc/amd/picasso/memlayout.ld
@@ -92,6 +92,7 @@
REGION(pagetables, CONFIG_PAGE_TABLE_ADDR, 4096 * 12, 8)
REGION(pdpt, ., 32, 32)

+ REGION(hash_buffer, 0x2BD000, 1M, 4)
EARLY_RESERVED_DRAM_END(.)

RAMSTAGE(CONFIG_RAMBASE, 8M)
diff --git a/src/soc/amd/picasso/smihandler.c b/src/soc/amd/picasso/smihandler.c
index 992dc2b..616f116 100644
--- a/src/soc/amd/picasso/smihandler.c
+++ b/src/soc/amd/picasso/smihandler.c
@@ -3,6 +3,7 @@
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
+#include <ram_hash.h>
#include <cpu/x86/cache.h>
#include <cpu/amd/amd64_save_state.h>
#include <acpi/acpi.h>
@@ -144,6 +145,13 @@
printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt);
slp_typ = acpi_sleep_from_pm1(pm1cnt);

+ /*
+ * Hash RAM as soon as we know we are entering S3 to catch any problems
+ * caused by the SMM handler, PSP, or SMU.
+ */
+ if (slp_typ == ACPI_S3)
+ hash_ram();
+
/* Do any mainboard sleep handling */
mainboard_smi_sleep(slp_typ);


To view, visit change 42890. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I6b38facba17bdd57a94987cfb49e71067ff8b769
Gerrit-Change-Number: 42890
Gerrit-PatchSet: 1
Gerrit-Owner: Raul Rangel <rrangel@chromium.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange