aboutsummaryrefslogtreecommitdiff
path: root/util/cbfstool/cbfs-mkstage.c
diff options
context:
space:
mode:
authorPatrick Georgi <patrick.georgi@coresystems.de>2009-09-14 13:29:27 +0000
committerPatrick Georgi <patrick.georgi@coresystems.de>2009-09-14 13:29:27 +0000
commitb7b56dd8fbe123958e196f396dab5ff3000b68dd (patch)
tree19972cda7bd87504eeea26ed90535e4aa7585da4 /util/cbfstool/cbfs-mkstage.c
parentc8d4a05f8f5df06bd98f8ee7d5ef46e61986e6b0 (diff)
New cbfstool. Works without mmap or fork/exec and
supports fixed location files. Some parts are salvaged from the pre-commit version (esp. stage and payload creation), others are completely rewritten (eg. the main loop that handles file addition) Also adapt newconfig (we don't need cbfs/tools anymore) and fix some minor issues in the cbfstool-README. Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4630 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'util/cbfstool/cbfs-mkstage.c')
-rw-r--r--util/cbfstool/cbfs-mkstage.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c
new file mode 100644
index 0000000000..693d7cc099
--- /dev/null
+++ b/util/cbfstool/cbfs-mkstage.c
@@ -0,0 +1,171 @@
+/*
+ * cbfs-mkstage
+ *
+ * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
+ * 2009 coresystems GmbH
+ * written by Patrick Georgi <patrick.georgi@coresystems.de>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "elf.h"
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include "common.h"
+#include "cbfs.h"
+
+unsigned int idemp(unsigned int x)
+{
+ return x;
+}
+
+unsigned int swap32(unsigned int x)
+{
+ return ((x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) |
+ (x << 24));
+}
+
+unsigned int (*elf32_to_native) (unsigned int) = idemp;
+
+/* returns size of result, or -1 if error */
+int parse_elf_to_stage(unsigned char *input, unsigned char **output,
+ comp_algo algo, uint32_t * location)
+{
+ Elf32_Phdr *phdr;
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input;
+ char *header, *buffer;
+ unsigned char *out;
+
+ int headers;
+ int i;
+ struct cbfs_stage *stage;
+ unsigned int data_start, data_end, mem_end;
+
+ int elf_bigendian = 0;
+ int host_bigendian = 0;
+
+ comp_func_ptr compress = compression_function(algo);
+ if (!compress)
+ return -1;
+
+ if (!iself(input)) {
+ fprintf(stderr, "E: The incoming file is not an ELF\n");
+ return -1;
+ }
+
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
+ elf_bigendian = 1;
+ }
+ char test[4] = "1234";
+ uint32_t inttest = *(uint32_t *) test;
+ if (inttest == 0x31323334) {
+ host_bigendian = 1;
+ }
+ if (elf_bigendian != host_bigendian) {
+ elf32_to_native = swap32;
+ }
+
+ headers = ehdr->e_phnum;
+ header = (char *)ehdr;
+
+ phdr = (Elf32_Phdr *) & header[elf32_to_native(ehdr->e_phoff)];
+
+ /* Now, regular headers - we only care about PT_LOAD headers,
+ * because thats what we're actually going to load
+ */
+
+ data_start = 0xFFFFFFFF;
+ data_end = 0;
+ mem_end = 0;
+
+ for (i = 0; i < headers; i++) {
+ unsigned int start, mend, rend;
+
+ if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
+ continue;
+
+ /* Empty segments are never interesting */
+ if (elf32_to_native(phdr[i].p_memsz) == 0)
+ continue;
+
+ /* BSS */
+
+ start = elf32_to_native(phdr[i].p_paddr);
+
+ mend = start + elf32_to_native(phdr[i].p_memsz);
+ rend = start + elf32_to_native(phdr[i].p_filesz);
+
+ if (start < data_start)
+ data_start = start;
+
+ if (rend > data_end)
+ data_end = rend;
+
+ if (mend > mem_end)
+ mem_end = mend;
+ }
+
+ /* allocate an intermediate buffer for the data */
+ buffer = calloc(data_end - data_start, 1);
+
+ if (buffer == NULL) {
+ fprintf(stderr, "E: Unable to allocate memory: %m\n");
+ return -1;
+ }
+
+ /* Copy the file data into the buffer */
+
+ for (i = 0; i < headers; i++) {
+
+ if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
+ continue;
+
+ if (elf32_to_native(phdr[i].p_memsz) == 0)
+ continue;
+
+ memcpy(buffer + (elf32_to_native(phdr[i].p_paddr) - data_start),
+ &header[elf32_to_native(phdr[i].p_offset)],
+ elf32_to_native(phdr[i].p_filesz));
+ }
+
+ /* Now make the output buffer */
+ out = calloc(sizeof(struct cbfs_stage) + data_end - data_start, 1);
+
+ if (out == NULL) {
+ fprintf(stderr, "E: Unable to allocate memory: %m\n");
+ return -1;
+ }
+
+ stage = (struct cbfs_stage *)out;
+
+ stage->load = data_start;
+ stage->memlen = mem_end - data_start;
+ stage->compression = algo;
+ stage->entry = ehdr->e_entry;
+
+ compress(buffer, data_end - data_start,
+ (char *)(out + sizeof(struct cbfs_stage)), (int *)&stage->len);
+
+ *output = out;
+
+ if (*location)
+ *location -= sizeof(struct cbfs_stage);
+ return sizeof(struct cbfs_stage) + stage->len;
+}