[coreboot-gerrit] Patch set updated for coreboot: lib/selfboot: Replace rdev_mmap_full()
Antonello Dettori (dev@dettori.io)
gerrit at coreboot.org
Fri Jul 1 15:20:41 CEST 2016
Antonello Dettori (dev at dettori.io) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15525
-gerrit
commit 1ed31510ce76d091a8dbc6c94f6d0b7b25c1c8dd
Author: Antonello Dettori <dev at dettori.io>
Date: Fri Jul 1 14:28:17 2016 +0200
lib/selfboot: Replace rdev_mmap_full()
Avoid loading the entire payload into memory, instead read each segment
when it is required.
If the segment is uncompressed rdev_readat() it into memory,
otherwise rdev_mmap() the segment and uncompress it.
Change-Id: I27cd4358a1747a65a79995114df23e296d1410fd
Signed-off-by: Antonello Dettori <dev at dettori.io>
---
src/lib/selfboot.c | 106 +++++++++++++++++++++++++++++++----------------------
1 file changed, 62 insertions(+), 44 deletions(-)
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index 75d6725..226ad99 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -36,9 +36,10 @@ struct segment {
struct segment *next;
struct segment *prev;
unsigned long s_dstaddr;
- unsigned long s_srcaddr;
unsigned long s_memsz;
- unsigned long s_filesz;
+ /* src->offset is the distance from the beginning of the boot_device.
+ * src->size is the filesize of the boot_device. */
+ struct region src;
int compression;
};
@@ -121,7 +122,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
die ("bounce buffer not supported");
start = seg->s_dstaddr;
- middle = start + seg->s_filesz;
+ middle = start + seg->src.size;
end = start + seg->s_memsz;
printk(BIOS_SPEW, "segment: [0x%016lx, 0x%016lx, 0x%016lx)\n",
@@ -139,12 +140,12 @@ 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;
- if (seg->s_filesz > len) {
- new->s_filesz = len;
- seg->s_filesz -= len;
+ seg->src.offset += len;
+ if (seg->src.size > len) {
+ new->src.size = len;
+ seg->src.size -= len;
} else {
- seg->s_filesz = 0;
+ seg->src.size = 0;
}
/* Order by stream offset */
@@ -158,7 +159,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
printk(BIOS_SPEW, " early: [0x%016lx, 0x%016lx, 0x%016lx)\n",
new->s_dstaddr,
- new->s_dstaddr + new->s_filesz,
+ new->s_dstaddr + new->src.size,
new->s_dstaddr + new->s_memsz);
ret = 1;
@@ -175,12 +176,12 @@ 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;
- if (seg->s_filesz > len) {
- seg->s_filesz = len;
- new->s_filesz -= len;
+ new->src.offset += len;
+ if (seg->src.size > len) {
+ seg->src.size = len;
+ new->src.size -= len;
} else {
- new->s_filesz = 0;
+ new->src.size = 0;
}
/* Order by stream offset */
new->next = seg->next;
@@ -190,7 +191,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
printk(BIOS_SPEW, " late: [0x%016lx, 0x%016lx, 0x%016lx)\n",
new->s_dstaddr,
- new->s_dstaddr + new->s_filesz,
+ new->s_dstaddr + new->src.size,
new->s_dstaddr + new->s_memsz);
}
}
@@ -204,7 +205,7 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
printk(BIOS_SPEW, " bounce: [0x%016lx, 0x%016lx, 0x%016lx)\n",
seg->s_dstaddr,
- seg->s_dstaddr + seg->s_filesz,
+ seg->s_dstaddr + seg->src.size,
seg->s_dstaddr + seg->s_memsz);
return ret;
@@ -226,17 +227,27 @@ static void cbfs_decode_payload_segment(struct cbfs_payload_segment *segment,
static int build_self_segment_list(
struct segment *head,
- struct cbfs_payload *cbfs_payload, uintptr_t *entry)
+ struct region_device *cbfs_payload, uintptr_t *entry)
{
struct segment *new;
struct cbfs_payload_segment *current_segment, *first_segment, segment;
+ size_t offset = 0;
memset(head, 0, sizeof(*head));
head->next = head->prev = head;
- first_segment = &cbfs_payload->segments;
+ first_segment = malloc(sizeof(struct cbfs_payload_segment));
+ current_segment = malloc(sizeof(struct cbfs_payload_segment));
- for (current_segment = first_segment;; ++current_segment) {
+ rdev_readat(cbfs_payload, first_segment, 0,
+ sizeof(struct cbfs_payload_segment));
+ memcpy(current_segment, first_segment,
+ sizeof(struct cbfs_payload_segment));
+
+ if (first_segment == NULL || current_segment == NULL)
+ return -1;
+
+ while (true) {
printk(BIOS_DEBUG,
"Loading segment from rom address 0x%p\n",
current_segment);
@@ -258,20 +269,19 @@ static int build_self_segment_list(
new->s_dstaddr = segment.load_addr;
new->s_memsz = segment.mem_len;
new->compression = segment.compression;
- new->s_srcaddr = (uintptr_t)
- ((unsigned char *)first_segment)
- + segment.offset;
- new->s_filesz = segment.len;
+ new->src.size = segment.len;
+ new->src.offset = segment.offset;
- 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);
+ printk(BIOS_DEBUG, " New segment dstaddr 0x%lx memsize 0x%lx offset 0x%lx filesize 0x%lx\n",
+ new->s_dstaddr, new->s_memsz, new->src.offset,
+ new->src.size);
/* Clean up the values */
- if (new->s_filesz > new->s_memsz) {
- new->s_filesz = new->s_memsz;
+ if (new->src.size > new->s_memsz) {
+ new->src.size = new->s_memsz;
printk(BIOS_DEBUG,
" cleaned up filesize 0x%lx\n",
- new->s_filesz);
+ new->src.size);
}
break;
@@ -280,12 +290,10 @@ static int build_self_segment_list(
(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)
- + segment.offset;
new->s_dstaddr = segment.load_addr;
new->s_memsz = segment.mem_len;
+ new->src.size = 0;
+ new->src.offset = segment.offset;
break;
case PAYLOAD_SEGMENT_ENTRY:
@@ -315,8 +323,15 @@ static int build_self_segment_list(
new->prev = head->prev;
head->prev->next = new;
head->prev = new;
+
+ rdev_readat(cbfs_payload, current_segment, offset,
+ sizeof(struct cbfs_payload_segment));
+ offset += sizeof(struct cbfs_payload_segment);
}
+ free(first_segment);
+ free(current_segment);
+
return 1;
}
@@ -332,7 +347,7 @@ static int load_self_segments(
/* Determine last non-empty loaded segment. */
last_non_empty = NULL;
for(ptr = head->next; ptr != head; ptr = ptr->next)
- if (ptr->s_filesz != 0)
+ if (ptr->src.size != 0)
last_non_empty = ptr;
for(ptr = head->next; ptr != head; ptr = ptr->next) {
@@ -379,7 +394,7 @@ static int load_self_segments(
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);
+ ptr->s_dstaddr, ptr->s_memsz, ptr->src.size);
/* Modify the segment to load onto the bounce_buffer if necessary.
*/
@@ -389,21 +404,24 @@ static int load_self_segments(
}
printk(BIOS_DEBUG, "Post relocation: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
- ptr->s_dstaddr, ptr->s_memsz, ptr->s_filesz);
+ ptr->s_dstaddr, ptr->s_memsz, ptr->src.size);
/* Compute the boundaries of the segment */
dest = (unsigned char *)(ptr->s_dstaddr);
- src = (unsigned char *)(ptr->s_srcaddr);
+ src = NULL;
/* Copy data from the initial buffer */
- if (ptr->s_filesz) {
+ if (ptr->src.size) {
unsigned char *middle, *end;
- size_t len = ptr->s_filesz;
+ size_t len = ptr->src.size;
size_t memsz = ptr->s_memsz;
+ size_t offset = ptr->src.offset;
switch(ptr->compression) {
case CBFS_COMPRESS_LZMA: {
printk(BIOS_DEBUG, "using LZMA\n");
timestamp_add_now(TS_START_ULZMA);
+ src = rdev_mmap(prog_rdev(payload),
+ offset, len);
len = ulzman(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZMA);
if (!len) /* Decompression Error. */
@@ -413,6 +431,8 @@ static int load_self_segments(
case CBFS_COMPRESS_LZ4: {
printk(BIOS_DEBUG, "using LZ4\n");
timestamp_add_now(TS_START_ULZ4F);
+ src = rdev_mmap(prog_rdev(payload),
+ offset, len);
len = ulz4fn(src, len, dest, memsz);
timestamp_add_now(TS_END_ULZ4F);
if (!len) /* Decompression Error. */
@@ -421,7 +441,8 @@ static int load_self_segments(
}
case CBFS_COMPRESS_NONE: {
printk(BIOS_DEBUG, "it's not compressed!\n");
- memcpy(dest, src, len);
+ rdev_readat(prog_rdev(payload), dest,
+ offset, len);
break;
}
default:
@@ -479,9 +500,9 @@ void *selfload(struct prog *payload)
{
uintptr_t entry = 0;
struct segment head;
- void *data;
+ struct region_device *data;
- data = rdev_mmap_full(prog_rdev(payload));
+ data = prog_rdev(payload);
if (data == NULL)
return NULL;
@@ -496,8 +517,6 @@ void *selfload(struct prog *payload)
printk(BIOS_SPEW, "Loaded segments\n");
- rdev_munmap(prog_rdev(payload), data);
-
/* Update the payload's area with the bounce buffer information. */
prog_set_area(payload, (void *)(uintptr_t)bounce_buffer, bounce_size);
@@ -507,6 +526,5 @@ void *selfload(struct prog *payload)
return (void *)entry;
out:
- rdev_munmap(prog_rdev(payload), data);
return NULL;
}
More information about the coreboot-gerrit
mailing list