summaryrefslogtreecommitdiff
path: root/src/lib/selfboot.c
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2014-02-25 00:21:10 -0600
committerAaron Durbin <adurbin@google.com>2014-03-03 21:47:40 +0100
commitceebc0503f15788604d31e16ac391ce8f99ca32e (patch)
treedb46eafa691835178b4ed84a3e45b9e6eb37be98 /src/lib/selfboot.c
parent4904802efc8eee37f95163f60823509e2a208af4 (diff)
selfboot: use bootmem infrastructure
Instead of packing and unpacking entries in lb_mem use the bootmem infrastructure for performing sanity checks during payload loading. Change-Id: Ica2bee7ebb0f6bf9ded31deac8cb700aa387bc7a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5303 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com> Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Diffstat (limited to 'src/lib/selfboot.c')
-rw-r--r--src/lib/selfboot.c151
1 files changed, 42 insertions, 109 deletions
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index 6dc3a75374..dff66e5019 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -21,19 +21,14 @@
#include <arch/byteorder.h>
#include <console/console.h>
#include <cpu/cpu.h>
-#include <boot/coreboot_tables.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cbfs.h>
#include <lib.h>
+#include <bootmem.h>
#include <payload_loader.h>
-/* Maximum physical address we can use for the coreboot bounce buffer. */
-#ifndef MAX_ADDR
-#define MAX_ADDR -1UL
-#endif
-
/* from coreboot_ram.ld: */
extern unsigned char _ram_seg;
extern unsigned char _eram_seg;
@@ -73,12 +68,10 @@ struct segment {
static unsigned long bounce_size, bounce_buffer;
-static void get_bounce_buffer(struct lb_memory *mem, unsigned long req_size)
+static void get_bounce_buffer(unsigned long req_size)
{
unsigned long lb_size;
- unsigned long mem_entries;
- unsigned long buffer;
- int i;
+ void *buffer;
/* When the ramstage is relocatable there is no need for a bounce
* buffer. All payloads should not overlap the ramstage.
@@ -94,93 +87,15 @@ static void get_bounce_buffer(struct lb_memory *mem, unsigned long req_size)
* to place a copy to return to.
*/
lb_size = req_size + lb_size;
- mem_entries = (mem->size - sizeof(*mem)) / sizeof(mem->map[0]);
- buffer = 0;
- for(i = 0; i < mem_entries; i++) {
- unsigned long mstart, mend;
- unsigned long msize;
- unsigned long tbuffer;
- if (mem->map[i].type != LB_MEM_RAM)
- continue;
- if (unpack_lb64(mem->map[i].start) > MAX_ADDR)
- continue;
- if (unpack_lb64(mem->map[i].size) < lb_size)
- continue;
- mstart = unpack_lb64(mem->map[i].start);
- msize = MAX_ADDR - mstart +1;
- if (msize > unpack_lb64(mem->map[i].size))
- msize = unpack_lb64(mem->map[i].size);
- mend = mstart + msize;
- tbuffer = mend - lb_size;
- if (tbuffer < buffer)
- continue;
- buffer = tbuffer;
- }
- bounce_buffer = buffer;
- bounce_size = req_size;
-}
-
-static int valid_area(struct lb_memory *mem, unsigned long buffer,
- unsigned long start, unsigned long len)
-{
- /* Check through all of the memory segments and ensure
- * the segment that was passed in is completely contained
- * in RAM.
- */
- int i;
- unsigned long end = start + len;
- unsigned long mem_entries = (mem->size - sizeof(*mem)) /
- sizeof(mem->map[0]);
- /* See if I conflict with the bounce buffer */
- if (end >= buffer) {
- return 0;
- }
+ buffer = bootmem_allocate_buffer(lb_size);
- /* Walk through the table of valid memory ranges and see if I
- * have a match.
- */
- for(i = 0; i < mem_entries; i++) {
- uint64_t mstart, mend;
- uint32_t mtype;
- mtype = mem->map[i].type;
- mstart = unpack_lb64(mem->map[i].start);
- mend = mstart + unpack_lb64(mem->map[i].size);
- if ((mtype == LB_MEM_RAM) && (start >= mstart) && (end < mend)) {
- break;
- }
- if ((mtype == LB_MEM_TABLE) && (start >= mstart) && (end < mend)) {
- printk(BIOS_ERR, "Payload is overwriting coreboot tables.\n");
- break;
- }
- }
- if (i == mem_entries) {
- if (start < (1024*1024) && end <=(1024*1024)) {
- printk(BIOS_DEBUG, "Payload (probably SeaBIOS) loaded"
- " into a reserved area in the lower 1MB\n");
- return 1;
- }
- printk(BIOS_ERR, "No matching ram area found for range:\n");
- printk(BIOS_ERR, " [0x%016lx, 0x%016lx)\n", start, end);
- printk(BIOS_ERR, "Ram areas\n");
- for(i = 0; i < mem_entries; i++) {
- uint64_t mstart, mend;
- uint32_t mtype;
- mtype = mem->map[i].type;
- mstart = unpack_lb64(mem->map[i].start);
- mend = mstart + unpack_lb64(mem->map[i].size);
- printk(BIOS_ERR, " [0x%016lx, 0x%016lx) %s\n",
- (unsigned long)mstart,
- (unsigned long)mend,
- (mtype == LB_MEM_RAM)?"RAM":"Reserved");
+ printk(BIOS_SPEW, "Bounce Buffer at %p, %lu bytes\n", buffer, lb_size);
- }
- return 0;
- }
- return 1;
+ bounce_buffer = (uintptr_t)buffer;
+ bounce_size = req_size;
}
-
static int overlaps_coreboot(struct segment *seg)
{
unsigned long start, end;
@@ -299,7 +214,6 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
static int build_self_segment_list(
struct segment *head,
- struct lb_memory *mem,
struct payload *payload, uintptr_t *entry)
{
struct segment *new;
@@ -393,24 +307,48 @@ static int build_self_segment_list(
static int load_self_segments(
struct segment *head,
- struct lb_memory *mem,
struct payload *payload)
{
struct segment *ptr;
-
+ const unsigned long one_meg = (1UL << 20);
unsigned long bounce_high = lb_end;
+
for(ptr = head->next; ptr != head; ptr = ptr->next) {
- if (!overlaps_coreboot(ptr))
+ if (bootmem_region_targets_usable_ram(ptr->s_dstaddr,
+ ptr->s_memsz))
continue;
-#if CONFIG_RELOCATABLE_RAMSTAGE
- /* payloads are required to not overlap ramstage. */
+
+ if (ptr->s_dstaddr < one_meg &&
+ (ptr->s_dstaddr + ptr->s_memsz) <= one_meg) {
+ printk(BIOS_DEBUG,
+ "Payload being loaded below 1MiB "
+ "without region being marked as RAM usable.\n");
+ continue;
+ }
+
+ /* Payload segment not targeting RAM. */
+ printk(BIOS_ERR, "SELF Payload doesn't target RAM:\n");
+ printk(BIOS_ERR, "Failed Segment: 0x%lx, %lu bytes\n",
+ ptr->s_dstaddr, ptr->s_memsz);
+ bootmem_dump_ranges();
return 0;
-#else
+ }
+
+ for(ptr = head->next; ptr != head; ptr = ptr->next) {
+ /*
+ * Add segments to bootmem memory map before a bounce buffer is
+ * allocated so that there aren't conflicts with the actual
+ * payload.
+ */
+ bootmem_add_range(ptr->s_dstaddr, ptr->s_memsz,
+ LB_MEM_UNUSABLE);
+
+ if (!overlaps_coreboot(ptr))
+ continue;
if (ptr->s_dstaddr + ptr->s_memsz > bounce_high)
bounce_high = ptr->s_dstaddr + ptr->s_memsz;
-#endif
}
- get_bounce_buffer(mem, bounce_high - lb_start);
+ get_bounce_buffer(bounce_high - lb_start);
if (!bounce_buffer) {
printk(BIOS_ERR, "Could not find a bounce buffer...\n");
return 0;
@@ -421,11 +359,6 @@ static int load_self_segments(
payload->bounce.size = bounce_size;
for(ptr = head->next; ptr != head; ptr = ptr->next) {
- /* Verify the memory addresses in the segment are valid */
- if (!valid_area(mem, bounce_buffer, ptr->s_dstaddr, ptr->s_memsz))
- return 0;
- }
- for(ptr = head->next; ptr != head; ptr = ptr->next) {
unsigned char *dest, *src;
printk(BIOS_DEBUG, "Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
@@ -505,17 +438,17 @@ static int load_self_segments(
return 1;
}
-void *selfload(struct lb_memory *mem, struct payload *payload)
+void *selfload(struct payload *payload)
{
uintptr_t entry = 0;
struct segment head;
/* Preprocess the self segments */
- if (!build_self_segment_list(&head, mem, payload, &entry))
+ if (!build_self_segment_list(&head, payload, &entry))
goto out;
/* Load the segments */
- if (!load_self_segments(&head, mem, payload))
+ if (!load_self_segments(&head, payload))
goto out;
printk(BIOS_SPEW, "Loaded segments\n");