Naman Govil (namangov@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6303
-gerrit
commit c4f9ed7c5516f62ba4fcb8bfcc56aa82f280e8c0 Author: Naman Govil namangov@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@gmail.com --- src/include/payload_loader.h | 4 + src/lib/loaders/cbfs_payload_loader.c | 18 ++-- src/lib/loaders/load_and_run_payload.c | 3 - src/lib/selfboot.c | 155 ++++++++++++++++++++------------- 4 files changed, 111 insertions(+), 69 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@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..eccf307 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@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,24 @@
#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; + int c;
- buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name, - type, &size); + m = &default_media; + if(init_default_cbfs_media(m) != 0) + return -1; + + c = cbfs_find_file(m, &payload->f, payload->name, type);
- if (buffer == NULL) + if (c < 0) return -1;
- payload->backing_store.data = buffer; - payload->backing_store.size = size; + payload->media = CBFS_DEFAULT_MEDIA;
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..7ff65ec 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003 Eric W. Biederman ebiederm@xmission.com * Copyright (C) 2009 Ron Minnich rminnich@gmail.com - * + * Copyright (C) 2014 Naman Govil namangov@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 * the Free Software Foundation; version 2 of the License. @@ -28,6 +28,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 +41,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 +141,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 +177,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 +218,78 @@ 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)) { + + printk(BIOS_DEBUG, "Reading segment from offset 0x%lx\n", current_offset); + 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); 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. @@ -285,26 +301,20 @@ static int build_self_segment_list( /* We found something that we don't know about. Throw * hands into the sky and run away! */ - printk(BIOS_EMERG, "Bad segment type %x\n", segment->type); + printk(BIOS_EMERG, "Bad segment type %x\n", segment.type); return -1; }
/* 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; - } + current_offset += sizeof(segment);
- /* Order by stream offset */ - new->next = ptr; - new->prev = ptr->prev; - ptr->prev->next = new; - ptr->prev = new; + /* 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 +323,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,7 +382,7 @@ static int load_self_segments( payload->bounce.size = bounce_size;
for(ptr = head->next; ptr != head; ptr = ptr->next) { - unsigned char *dest, *src; + 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);
@@ -378,7 +398,8 @@ static int load_self_segments(
/* Compute the boundaries of the segment */ dest = (unsigned char *)(ptr->s_dstaddr); - src = (unsigned char *)(ptr->s_srcaddr); + size_t v_read; + void *v_map;
/* Copy data from the initial buffer */ if (ptr->s_filesz) { @@ -388,14 +409,31 @@ 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); + + media->close(media); + if (v_map == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + printk(BIOS_ERR, "Failed to map\n"); + return -1; + } + len = ulzma(v_map, dest); 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); + media->close(media); + if (v_read != len) { + printk(BIOS_ERR, "Reading of uncompressed segments not successful\n"); + return -1; + } break; } default: @@ -404,11 +442,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) {