summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2019-01-28 17:22:22 +0800
committerPatrick Georgi <pgeorgi@google.com>2019-01-30 11:04:49 +0000
commit05532260aee0302e43a4935a402c7b9268036267 (patch)
treef8d94e47280d41f0cc1b612975c0754dc625c056 /src/lib
parentab92f26a13f4656821f9dff93f180cb1a33c1c3e (diff)
selfload: check target memory type in selfload_check
Currently, selflock_check() verifies that the binary is loaded in an usable RAM area. Extend its functionality so we can also check that BL31 is loaded in a manually reserved area, and fail early if the range is not protected. Change-Id: Iecdeedd9e8da67f73ac47d2a82e85b306469a626 Signed-off-by: Ting Shen <phoenixshen@google.com> Reviewed-on: https://review.coreboot.org/c/31122 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/bootmem.c18
-rw-r--r--src/lib/prog_loaders.c2
-rw-r--r--src/lib/selfboot.c23
3 files changed, 19 insertions, 24 deletions
diff --git a/src/lib/bootmem.c b/src/lib/bootmem.c
index 2f9b5dc0b1..c804df5973 100644
--- a/src/lib/bootmem.c
+++ b/src/lib/bootmem.c
@@ -201,33 +201,25 @@ bool bootmem_walk(range_action_t action, void *arg)
return false;
}
-static int bootmem_region_targets_ram(uint64_t start, uint64_t end,
- struct memranges *bm)
+int bootmem_region_targets_type(uint64_t start, uint64_t size,
+ enum bootmem_type dest_type)
{
const struct range_entry *r;
+ uint64_t end = start + size;
- memranges_each_entry(r, bm) {
+ memranges_each_entry(r, &bootmem) {
/* All further bootmem entries are beyond this range. */
if (end <= range_entry_base(r))
break;
if (start >= range_entry_base(r) && end <= range_entry_end(r)) {
- if (range_entry_tag(r) == BM_MEM_RAM)
+ if (range_entry_tag(r) == dest_type)
return 1;
}
}
return 0;
}
-/* Common testcase for loading any segments to bootmem.
- * Returns 1 if the requested memory range is all tagged as type BM_MEM_RAM.
- * Otherwise returns 0.
- */
-int bootmem_region_targets_usable_ram(uint64_t start, uint64_t size)
-{
- return bootmem_region_targets_ram(start, start + size, &bootmem);
-}
-
void *bootmem_allocate_buffer(size_t size)
{
const struct range_entry *r;
diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c
index ac80a62c9d..70ea7efe66 100644
--- a/src/lib/prog_loaders.c
+++ b/src/lib/prog_loaders.c
@@ -182,7 +182,7 @@ void payload_load(void)
switch (prog_cbfs_type(payload)) {
case CBFS_TYPE_SELF: /* Simple ELF */
- selfload_check(payload);
+ selfload_check(payload, BM_MEM_RAM);
break;
case CBFS_TYPE_FIT: /* Flattened image tree */
if (IS_ENABLED(CONFIG_PAYLOAD_FIT_SUPPORT)) {
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index 9c52cd6bef..9aa47413c5 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -30,7 +30,7 @@
#include <cbmem.h>
/* The type syntax for C is essentially unparsable. -- Rob Pike */
-typedef int (*checker_t)(struct cbfs_payload_segment *cbfssegs);
+typedef int (*checker_t)(struct cbfs_payload_segment *cbfssegs, void *args);
/* Decode a serialized cbfs payload segment
* from memory into native endianness.
@@ -46,10 +46,11 @@ static void cbfs_decode_payload_segment(struct cbfs_payload_segment *segment,
segment->mem_len = read_be32(&src->mem_len);
}
-static int segment_targets_usable_ram(void *dest, unsigned long memsz)
+static int segment_targets_type(void *dest, unsigned long memsz,
+ enum bootmem_type dest_type)
{
uintptr_t d = (uintptr_t) dest;
- if (bootmem_region_targets_usable_ram(d, memsz))
+ if (bootmem_region_targets_type(d, memsz, dest_type))
return 1;
if (payload_arch_usable_ram_quirk(d, memsz))
@@ -140,11 +141,13 @@ static int last_loadable_segment(struct cbfs_payload_segment *seg)
return read_be32(&(seg + 1)->type) == PAYLOAD_SEGMENT_ENTRY;
}
-static int check_payload_segments(struct cbfs_payload_segment *cbfssegs)
+static int check_payload_segments(struct cbfs_payload_segment *cbfssegs,
+ void *args)
{
uint8_t *dest;
size_t memsz;
struct cbfs_payload_segment *first_segment, *seg, segment;
+ enum bootmem_type dest_type = *(enum bootmem_type *)args;
for (first_segment = seg = cbfssegs;; ++seg) {
printk(BIOS_DEBUG, "Checking segment from ROM address 0x%p\n", seg);
@@ -153,7 +156,7 @@ static int check_payload_segments(struct cbfs_payload_segment *cbfssegs)
memsz = segment.mem_len;
if (segment.type == PAYLOAD_SEGMENT_ENTRY)
break;
- if (!segment_targets_usable_ram(dest, memsz))
+ if (!segment_targets_type(dest, memsz, dest_type))
return -1;
}
return 0;
@@ -244,7 +247,7 @@ static void *selfprepare(struct prog *payload)
return data;
}
-static bool _selfload(struct prog *payload, checker_t f)
+static bool _selfload(struct prog *payload, checker_t f, void *args)
{
uintptr_t entry = 0;
struct cbfs_payload_segment *cbfssegs;
@@ -256,7 +259,7 @@ static bool _selfload(struct prog *payload, checker_t f)
cbfssegs = &((struct cbfs_payload *)data)->segments;
- if (f && f(cbfssegs))
+ if (f && f(cbfssegs, args))
goto out;
if (load_payload_segments(cbfssegs, &entry))
@@ -275,12 +278,12 @@ out:
return false;
}
-bool selfload_check(struct prog *payload)
+bool selfload_check(struct prog *payload, enum bootmem_type dest_type)
{
- return _selfload(payload, check_payload_segments);
+ return _selfload(payload, check_payload_segments, &dest_type);
}
bool selfload(struct prog *payload)
{
- return _selfload(payload, NULL);
+ return _selfload(payload, NULL, 0);
}