[coreboot-gerrit] Patch set updated for coreboot: 7c8db1f Re-structuring Payload loading
Naman Govil (namangov@gmail.com)
gerrit at coreboot.org
Fri Jul 18 13:05:49 CEST 2014
Naman Govil (namangov at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6303
-gerrit
commit 7c8db1ff993ad1f699a52ff0557803c79b44ad2a
Author: Naman Govil <namangov at gmail.com>
Date: Fri Jul 18 16:20:38 2014 +0530
Re-structuring Payload loading
Removing dependency for mapping entire segments for
payload loading by segragating segments by reading metadata and
then processing them.
Change-Id: I87a52cca7f0270cf7575d2bf5133e17fbb6c9470
Signed-off-by: Naman Govil <namangov at gmail.com>
---
src/include/payload_loader.h | 4 +
src/lib/loaders/cbfs_payload_loader.c | 24 +++--
src/lib/loaders/load_and_run_payload.c | 3 -
src/lib/selfboot.c | 166 +++++++++++++++++++++------------
4 files changed, 127 insertions(+), 70 deletions(-)
diff --git a/src/include/payload_loader.h b/src/include/payload_loader.h
index 7a3f045..cac7d27 100644
--- a/src/include/payload_loader.h
+++ b/src/include/payload_loader.h
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2014 Naman Govil <namangov at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +22,7 @@
#include <stdint.h>
#include <stddef.h>
+#include <cbfs_core.h>
struct buffer_area {
void *data;
@@ -32,6 +34,8 @@ struct payload {
struct buffer_area backing_store;
/* Used when payload wants memory coreboot ramstage is running at. */
struct buffer_area bounce;
+ struct cbfs_media *media;
+ struct cbfs_file_handle f;
void *entry;
};
diff --git a/src/lib/loaders/cbfs_payload_loader.c b/src/lib/loaders/cbfs_payload_loader.c
index 2c1d179..42f9f33 100644
--- a/src/lib/loaders/cbfs_payload_loader.c
+++ b/src/lib/loaders/cbfs_payload_loader.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2014 Naman Govil <namangov at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,21 +20,30 @@
#include <cbfs.h>
#include <payload_loader.h>
+#include <cbfs_core.h>
static int cbfs_locate_payload(struct payload *payload)
{
- void *buffer;
- size_t size;
const int type = CBFS_TYPE_PAYLOAD;
+ struct cbfs_media default_media, *m;
+ struct cbfs_file_handle fh;
+ int c;
+ m = CBFS_DEFAULT_MEDIA;
- buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name,
- type, &size);
+ if (m == CBFS_DEFAULT_MEDIA) {
+ m = &default_media;
+ if(init_default_cbfs_media(m) != 0)
+ return -1;
+ }
- if (buffer == NULL)
+ c = cbfs_find_file(m, &fh, payload->name, type);
+
+ if (c < 0)
return -1;
- payload->backing_store.data = buffer;
- payload->backing_store.size = size;
+
+ payload->media = CBFS_DEFAULT_MEDIA;
+ payload->f = fh;
return 0;
}
diff --git a/src/lib/loaders/load_and_run_payload.c b/src/lib/loaders/load_and_run_payload.c
index 2204090..0dcecfb 100644
--- a/src/lib/loaders/load_and_run_payload.c
+++ b/src/lib/loaders/load_and_run_payload.c
@@ -58,9 +58,6 @@ struct payload *payload_load(void)
ops->name);
continue;
}
- printk(BIOS_DEBUG, "%s: located payload @ %p, %zu bytes.\n",
- ops->name, payload->backing_store.data,
- payload->backing_store.size);
break;
}
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index 8e9e0de..ed03b0e 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2003 Eric W. Biederman <ebiederm at xmission.com>
* Copyright (C) 2009 Ron Minnich <rminnich at gmail.com>
+ * Copyright (C) 2014 Naman Govil <namangov at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +29,7 @@
#include <lib.h>
#include <bootmem.h>
#include <payload_loader.h>
+#include <cbfs_core.h>
/* from ramstage.ld: */
extern unsigned char _ram_seg;
@@ -40,9 +42,9 @@ struct segment {
struct segment *next;
struct segment *prev;
unsigned long s_dstaddr;
- unsigned long s_srcaddr;
unsigned long s_memsz;
unsigned long s_filesz;
+ unsigned long s_offset;
int compression;
};
@@ -140,7 +142,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
new->s_memsz = len;
seg->s_memsz -= len;
seg->s_dstaddr += len;
- seg->s_srcaddr += len;
+ seg->s_offset += len;
if (seg->s_filesz > len) {
new->s_filesz = len;
seg->s_filesz -= len;
@@ -176,7 +178,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
seg->s_memsz = len;
new->s_memsz -= len;
new->s_dstaddr += len;
- new->s_srcaddr += len;
+ new->s_offset += len;
if (seg->s_filesz > len) {
seg->s_filesz = len;
new->s_filesz -= len;
@@ -217,63 +219,83 @@ static int build_self_segment_list(
struct payload *payload, uintptr_t *entry)
{
struct segment *new;
- struct segment *ptr;
- struct cbfs_payload_segment *segment, *first_segment;
- struct cbfs_payload *cbfs_payload;
- cbfs_payload = payload->backing_store.data;
+ struct cbfs_payload_segment segment;
+ struct cbfs_media default_media, *media;
+ unsigned long current_offset;
+
+ media = payload->media;
+
+ if (media == CBFS_DEFAULT_MEDIA) {
+ media = &default_media
+ if (init_default_cbfs_media(media) != 0) {
+ printk(BIOS_ERR, "Failed to initialize media\n");
+ return -1;
+ }
+ }
+
memset(head, 0, sizeof(*head));
head->next = head->prev = head;
- first_segment = segment = &cbfs_payload->segments;
- while(1) {
- printk(BIOS_DEBUG, "Loading segment from rom address 0x%p\n", segment);
- switch(segment->type) {
+ current_offset = payload->f.data_offset;
+ media->open(media);
+
+ while(media->read(media, &segment, current_offset, sizeof(segment))
+ == sizeof(segment)) {
+ //reading metadata for each payload segment
+ printk(BIOS_DEBUG, "Forming self_segment_list\n");
+ printk(BIOS_DEBUG, "Loading segment from rom address 0x%p\n", &segment);
+
+ segment.compression = ntohl(segment.compression);
+ segment.offset = ntohl(segment.offset);
+ segment.load_addr = ntohll(segment.load_addr);
+ segment.mem_len = ntohl(segment.mem_len);
+ segment.len = ntohl(segment.len);
+
+ switch(segment.type) {
case PAYLOAD_SEGMENT_PARAMS:
printk(BIOS_DEBUG, " parameter section (skipped)\n");
- segment++;
+ current_offset += sizeof(segment);
+ //going for next segment
continue;
case PAYLOAD_SEGMENT_CODE:
case PAYLOAD_SEGMENT_DATA:
printk(BIOS_DEBUG, " %s (compression=%x)\n",
- segment->type == PAYLOAD_SEGMENT_CODE ? "code" : "data",
- ntohl(segment->compression));
+ segment.type == PAYLOAD_SEGMENT_CODE ? "code" : "data",
+ segment.compression);
new = malloc(sizeof(*new));
- new->s_dstaddr = ntohll(segment->load_addr);
- new->s_memsz = ntohl(segment->mem_len);
- new->compression = ntohl(segment->compression);
-
- new->s_srcaddr = (uintptr_t)
- ((unsigned char *)first_segment)
- + ntohl(segment->offset);
- new->s_filesz = ntohl(segment->len);
- printk(BIOS_DEBUG, " New segment dstaddr 0x%lx memsize 0x%lx srcaddr 0x%lx filesize 0x%lx\n",
- new->s_dstaddr, new->s_memsz, new->s_srcaddr, new->s_filesz);
+ new->s_dstaddr = segment.load_addr;
+ new->s_memsz = segment.mem_len;
+ new->compression = segment.compression;
+ new->s_filesz = segment.len;
+ new->s_offset = segment.offset;
+
+ printk(BIOS_DEBUG, " New segment dstaddr 0x%lx memsize 0x%lx
+ src_offset 0x%lx filesize 0x%lx\n",
+ new->s_dstaddr, new->s_memsz, new->s_offset, new->s_filesz);
/* Clean up the values */
if (new->s_filesz > new->s_memsz) {
new->s_filesz = new->s_memsz;
}
- printk(BIOS_DEBUG, " (cleaned up) New segment addr 0x%lx size 0x%lx offset 0x%lx filesize 0x%lx\n",
- new->s_dstaddr, new->s_memsz, new->s_srcaddr, new->s_filesz);
+ printk(BIOS_DEBUG, " (cleaned up) New segment addr 0x%lx size 0x%lx
+ src_offset 0x%lx filesize 0x%lx\n",
+ new->s_dstaddr, new->s_memsz, new->s_offset, new->s_filesz);
break;
case PAYLOAD_SEGMENT_BSS:
- printk(BIOS_DEBUG, " BSS 0x%p (%d byte)\n", (void *)
- (intptr_t)ntohll(segment->load_addr),
- ntohl(segment->mem_len));
+ printk(BIOS_DEBUG, " BSS 0x%p (%d byte)\n",
+ (void *)(intptr_t)segment.load_addr, segment.mem_len);
new = malloc(sizeof(*new));
new->s_filesz = 0;
- new->s_srcaddr = (uintptr_t)
- ((unsigned char *)first_segment)
- + ntohl(segment->offset);
- new->s_dstaddr = ntohll(segment->load_addr);
- new->s_memsz = ntohl(segment->mem_len);
+ new->s_offset = segment.offset;
+ new->s_dstaddr = segment.load_addr;
+ new->s_memsz = segment.mem_len;
break;
case PAYLOAD_SEGMENT_ENTRY:
printk(BIOS_DEBUG, " Entry Point 0x%p\n",
- (void *)(intptr_t)ntohll(segment->load_addr));
- *entry = ntohll(segment->load_addr);
+ (void *)(intptr_t)segment.load_addr);
+ *entry = segment->load_addr;
/* Per definition, a payload always has the entry point
* as last segment. Thus, we use the occurrence of the
* entry point as break condition for the loop.
@@ -290,21 +312,17 @@ static int build_self_segment_list(
}
/* We have found another CODE, DATA or BSS segment */
- segment++;
-
- /* Find place where to insert our segment */
- for(ptr = head->next; ptr != head; ptr = ptr->next) {
- if (new->s_srcaddr < ntohll(segment->load_addr))
- break;
- }
-
- /* Order by stream offset */
- new->next = ptr;
- new->prev = ptr->prev;
- ptr->prev->next = new;
- ptr->prev = new;
+ /* Everything is accessed in terms of offsets since it is
+ * not memory mapped */
+ current_offset += sizeof(segment);
+
+ /* Insert to the end of the list */
+ new->next = head;
+ new->prev = head->prev;
+ head->prev->next = new;
+ head->prev = new;
}
-
+ media->close(media);
return 1;
}
@@ -313,8 +331,18 @@ static int load_self_segments(
struct payload *payload)
{
struct segment *ptr;
+ struct cbfs_media default_media, *media;
const unsigned long one_meg = (1UL << 20);
unsigned long bounce_high = lb_end;
+ media = payload->media;
+
+ if (media == CBFS_DEFAULT_MEDIA) {
+ media = &default_media;
+ if (init_default_cbfs_media(media) != 0) {
+ printk(BIOS_ERR, "Failed to initialize media\n");
+ return -1;
+ }
+ }
for(ptr = head->next; ptr != head; ptr = ptr->next) {
if (bootmem_region_targets_usable_ram(ptr->s_dstaddr,
@@ -362,8 +390,9 @@ static int load_self_segments(
payload->bounce.size = bounce_size;
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",
+ unsigned char *dest;
+ printk(BIOS_DEBUG, "Loading Segment: addr: 0x%016lx memsz: 0x%016lx
+ filesz: 0x%016lx\n",
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
/* Modify the segment to load onto the bounce_buffer if necessary.
@@ -373,12 +402,14 @@ static int load_self_segments(
continue;
}
- printk(BIOS_DEBUG, "Post relocation: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
+ printk(BIOS_DEBUG, "Post relocation: addr: 0x%016lx memsz: 0x%016lx
+ filesz: 0x%016lx\n",
ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
/* Compute the boundaries of the segment */
dest = (unsigned char *)(ptr->s_dstaddr);
- src = (unsigned char *)(ptr->s_srcaddr);
+ int v_read;
+ void *v_map;
/* Copy data from the initial buffer */
if (ptr->s_filesz) {
@@ -388,14 +419,30 @@ static int load_self_segments(
switch(ptr->compression) {
case CBFS_COMPRESS_LZMA: {
printk(BIOS_DEBUG, "using LZMA\n");
- len = ulzma(src, dest);
+ printk(BIOS_DEBUG, "need to map first\n");
+ media->open(media);
+ v_map = media->map(media, payload->f.data_offset + ptr->s_offset,
+ len);
+ if (v_map == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+ printk(BIOS_ERR, "Failed to map\n");
+ return -1;
+ }
+ len = ulzma(v_map, dest);
+ media->close(media);
if (!len) /* Decompression Error. */
return 0;
break;
}
case CBFS_COMPRESS_NONE: {
- printk(BIOS_DEBUG, "it's not compressed!\n");
- memcpy(dest, src, len);
+ printk(BIOS_DEBUG, "it's not compressed! hence read directly\n");
+ media->open(media);
+ v_read = media->read(media, dest, payload->f.data_offset + ptr->s_offset,
+ len);
+ if (v_read != len) {
+ printk(BIOS_ERR, "Reading of uncompressed segments not successful\n");
+ return -1;
+ }
+ media->close(media);
break;
}
default:
@@ -404,11 +451,10 @@ static int load_self_segments(
}
end = dest + ptr->s_memsz;
middle = dest + len;
- printk(BIOS_SPEW, "[ 0x%08lx, %08lx, 0x%08lx) <- %08lx\n",
+ printk(BIOS_SPEW, "[ 0x%08lx, %08lx, 0x%08lx ]\n",
(unsigned long)dest,
(unsigned long)middle,
- (unsigned long)end,
- (unsigned long)src);
+ (unsigned long)end);
/* Zero the extra bytes between middle & end */
if (middle < end) {
More information about the coreboot-gerrit
mailing list