[coreboot-gerrit] Patch set updated for coreboot: 75bd2ad Re-structuring Payload loading

Naman Govil (namangov@gmail.com) gerrit at coreboot.org
Thu Jul 31 13:53:12 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 75bd2ad21a4b990ab5cb40a04e3447b08f30bafc
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  |  15 +-
 src/lib/loaders/load_and_run_payload.c |   3 -
 src/lib/selfboot.c                     | 275 ++++++++++++++++++++++++++-------
 4 files changed, 228 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 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..f0b5bbc 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,21 @@
 
 #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;
 
-	buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name,
-					type, &size);
+	m = &default_media;
+	if (init_default_cbfs_media(m) != 0)
+		return -1;
 
-	if (buffer == NULL)
+	if (cbfs_find_file(m, &payload->f, payload->name, type) < 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..ac092d1 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -3,7 +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
  * 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;
 };
 
@@ -66,6 +67,102 @@ struct segment {
  *   and much simpler than the general case implemented in kexec.
  */
 
+struct sb_helper {
+	int (*init)(struct sb_helper *sbh, struct payload *payload);
+	int (*open)(struct payload *payload);
+	int (*close)(struct payload *payload);
+	size_t (*read)(struct payload *payload, void *dest, size_t offset, size_t size);
+	void *(*map)(struct payload *payload, size_t offset, size_t size);
+	void *sb_media;
+};
+
+static struct cbfs_media default_media;
+
+static int init_cbfs(struct sb_helper *sbh, struct payload *payload)
+{
+	/*Backing store is in use hence no loading via cbfs
+	*/
+	if (payload->backing_store.data != NULL)
+		return 0;
+	if (payload->media == CBFS_DEFAULT_MEDIA) {
+		sbh->sb_media = &default_media;
+		if (init_default_cbfs_media(payload->media) != 0) {
+			printk(BIOS_ERR, "Failed to initialize media\n");
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static size_t cbfs_read(struct payload *payload, void *dest, size_t offset, size_t size)
+{
+	return payload->media->read(payload->media, dest, offset, size);
+}
+
+static void *cbfs_map(struct payload *payload, size_t offset, size_t size)
+{
+	return payload->media->map(payload->media, offset, size);
+}
+
+static int cbfs_open(struct payload *payload)
+{
+	payload->media->open(payload->media);
+	return 0;
+}
+
+static int cbfs_close(struct payload *payload)
+{
+	payload->media->close(payload->media);
+	return 0;
+}
+
+static int init_backing_store(struct sb_helper *sbh, struct payload *payload)
+{
+	if (payload->backing_store.data != NULL)
+		return 1;
+	else
+		return 0;
+}
+
+static size_t backing_store_read(struct payload *payload, void *dest, size_t offset, size_t size)
+{
+	memcpy(dest, (void *)payload->backing_store.data + offset, size);
+	return size;
+}
+
+static void *backing_store_map(struct payload *payload, size_t offset, size_t size)
+{
+	return (void *)payload->backing_store.data + offset;
+}
+
+static int backing_store_open(struct payload *payload)
+{
+	return 0;
+}
+
+static int backing_store_close(struct payload *payload)
+{
+	return 0;
+}
+
+struct sb_helper cbfs_helper = {
+	.init = init_cbfs,
+	.open = cbfs_open,
+	.close = cbfs_close,
+	.read = cbfs_read,
+	.map = cbfs_map,
+	.sb_media = &default_media,
+};
+
+struct sb_helper backing_store_helper = {
+	.init = init_backing_store,
+	.open = backing_store_open,
+	.close = backing_store_close,
+	.read = backing_store_read,
+	.map = backing_store_map,
+	.sb_media = NULL,
+};
+
 static unsigned long bounce_size, bounce_buffer;
 
 static void get_bounce_buffer(unsigned long req_size)
@@ -140,7 +237,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 +273,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;
@@ -212,68 +309,95 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
 }
 
 
+static struct sb_helper *get_selfboot_method(struct payload *payload)
+{
+	struct sb_helper sbh;
+	if (cbfs_helper.init(&sbh, payload))
+		return &cbfs_helper;
+	if (backing_store_helper.init(&sbh, payload))
+		return &backing_store_helper;
+	return NULL;
+}
+
 static int build_self_segment_list(
 	struct segment *head,
 	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;
+	unsigned long current_offset;
+	struct sb_helper *sbh;
+
+	if (payload->media == CBFS_DEFAULT_MEDIA) {
+		payload->media = &default_media;
+		if (init_default_cbfs_media(payload->media) != 0) {
+			printk(BIOS_ERR, "Failed to initialize media\n");
+			return -1;
+		}
+	}
+
+	sbh = get_selfboot_method(payload);
+
+	if (sbh != NULL) {
+
 	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;
+	sbh->open(payload);
+
+	while(sbh->read(payload, &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,27 +409,26 @@ 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++;
+		current_offset += sizeof(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;
+		/* Insert to the end of the list */
+		new->next = head;
+		new->prev = head->prev;
+		head->prev->next = new;
+		head->prev = new;
 	}
-
+	sbh->close(payload);
 	return 1;
+	}
+	else {
+		printk(BIOS_ERR, "Failed to build self_segments\n");
+		return -1;
+	}
 }
 
 static int load_self_segments(
@@ -315,6 +438,18 @@ static int load_self_segments(
 	struct segment *ptr;
 	const unsigned long one_meg = (1UL << 20);
 	unsigned long bounce_high = lb_end;
+	struct sb_helper *sbh;
+
+	if (payload->media == CBFS_DEFAULT_MEDIA) {
+		payload->media = &default_media;
+		if (init_default_cbfs_media(payload->media) != 0) {
+			printk(BIOS_ERR, "Failed to initialize media\n");
+			return -1;
+		}
+	}
+
+	sbh = get_selfboot_method(payload);
+	if (sbh != NULL) {
 
 	for(ptr = head->next; ptr != head; ptr = ptr->next) {
 		if (bootmem_region_targets_usable_ram(ptr->s_dstaddr,
@@ -362,7 +497,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 +513,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 +524,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");
+					sbh->open(payload);
+					v_map = sbh->map(payload, payload->f.data_offset + ptr->s_offset,
+							len);
+
+					sbh->close(payload);
+					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");
+					sbh->open(payload);
+					v_read = sbh->read(payload, dest, payload->f.data_offset + ptr->s_offset,
+							len);
+					sbh->close(payload);
+					if (v_read != len) {
+						printk(BIOS_ERR, "Reading of uncompressed segments not successful\n");
+						return -1;
+					}
 					break;
 				}
 				default:
@@ -404,11 +557,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) {
@@ -439,6 +591,11 @@ static int load_self_segments(
 		}
 	}
 	return 1;
+	}
+	else {
+		printk(BIOS_ERR, "Failed to load self_segments\n");
+		return -1;
+	}
 }
 
 void *selfload(struct payload *payload)



More information about the coreboot-gerrit mailing list