Patrick Georgi merged this change.

View Change

Approvals: build bot (Jenkins): Verified Julius Werner: Looks good to me, approved
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>
---
M src/arch/arm64/arm_tf.c
M src/include/bootmem.h
M src/include/program_loading.h
M src/lib/bootmem.c
M src/lib/prog_loaders.c
M src/lib/selfboot.c
6 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/src/arch/arm64/arm_tf.c b/src/arch/arm64/arm_tf.c
index eaf8739..c0526e0 100644
--- a/src/arch/arm64/arm_tf.c
+++ b/src/arch/arm64/arm_tf.c
@@ -19,6 +19,7 @@
#include <arch/transition.h>
#include <arm_tf.h>
#include <assert.h>
+#include <bootmem.h>
#include <cbfs.h>
#include <program_loading.h>

diff --git a/src/include/bootmem.h b/src/include/bootmem.h
index 0a960c9..4652d08 100644
--- a/src/include/bootmem.h
+++ b/src/include/bootmem.h
@@ -94,8 +94,11 @@
*/
bool bootmem_walk(range_action_t action, void *arg);

-/* Return 1 if region targets usable RAM, 0 otherwise. */
-int bootmem_region_targets_usable_ram(uint64_t start, uint64_t size);
+/* Returns 1 if the requested memory range is all tagged as type dest_type.
+ * Otherwise returns 0.
+ */
+int bootmem_region_targets_type(uint64_t start, uint64_t size,
+ enum bootmem_type dest_type);

/* Allocate a temporary buffer from the unused RAM areas. */
void *bootmem_allocate_buffer(size_t size);
diff --git a/src/include/program_loading.h b/src/include/program_loading.h
index 468f0b3..7be59e2 100644
--- a/src/include/program_loading.h
+++ b/src/include/program_loading.h
@@ -16,6 +16,7 @@
#ifndef PROGRAM_LOADING_H
#define PROGRAM_LOADING_H

+#include <bootmem.h>
#include <commonlib/region.h>
#include <stdint.h>
#include <stddef.h>
@@ -206,7 +207,7 @@
*
* Defined in src/lib/selfboot.c
*/
-bool selfload_check(struct prog *payload);
+bool selfload_check(struct prog *payload, enum bootmem_type dest_type);
bool selfload(struct prog *payload);

#endif /* PROGRAM_LOADING_H */
diff --git a/src/lib/bootmem.c b/src/lib/bootmem.c
index 2f9b5dc..c804df5 100644
--- a/src/lib/bootmem.c
+++ b/src/lib/bootmem.c
@@ -201,33 +201,25 @@
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 ac80a62..70ea7ef 100644
--- a/src/lib/prog_loaders.c
+++ b/src/lib/prog_loaders.c
@@ -182,7 +182,7 @@

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 9c52cd6..9aa4741 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 @@
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 @@
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 @@
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 @@
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 @@

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 @@
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);
}

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Iecdeedd9e8da67f73ac47d2a82e85b306469a626
Gerrit-Change-Number: 31122
Gerrit-PatchSet: 7
Gerrit-Owner: Ting Shen <phoenixshen@google.com>
Gerrit-Reviewer: Hung-Te Lin <hungte@chromium.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Ting Shen <phoenixshen@google.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-CC: Paul Menzel <paulepanter@users.sourceforge.net>
Gerrit-MessageType: merged