Consolidate all multiple segment handling into lib/lar.c:load_file_segments() and greatly simplify arch/x86/stage1.c code as a result. While I'm at it, improve the LAR segmentation abstraction. Stage 1 code should not have to care about internal representation of segments, that knowledge belongs into lib/lar.c. Constification of most function parameters in lib/lar.c led to a few other now obvious code removals.
Build tested and runtime tested in Qemu.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: LinuxBIOSv3-betterlarsegments/include/lar.h =================================================================== --- LinuxBIOSv3-betterlarsegments/include/lar.h (Revision 529) +++ LinuxBIOSv3-betterlarsegments/include/lar.h (Arbeitskopie) @@ -82,10 +82,11 @@ };
/* Prototypes. */ -int find_file(struct mem_file *archive, const char *filename, struct mem_file *result); -int copy_file(struct mem_file *archive, const char *filename, void *where); -int run_file(struct mem_file *archive, const char *filename, void *where); -int execute_in_place(struct mem_file *archive, const char *filename); +int find_file(const struct mem_file *archive, const char *filename, struct mem_file *result); +int copy_file(const struct mem_file *archive, const char *filename, void *where); +int run_file(const struct mem_file *archive, const char *filename, void *where); +int execute_in_place(const struct mem_file *archive, const char *filename); int run_address(void *f); -void *load_file(struct mem_file *archive, const char *filename); +void *load_file(const struct mem_file *archive, const char *filename); +void *load_file_segments(const struct mem_file *archive, const char *filename); #endif /* LAR_H */ Index: LinuxBIOSv3-betterlarsegments/lib/lar.c =================================================================== --- LinuxBIOSv3-betterlarsegments/lib/lar.c (Revision 529) +++ LinuxBIOSv3-betterlarsegments/lib/lar.c (Arbeitskopie) @@ -56,7 +56,7 @@ * returns 0 on success, -1 otherwise */
-int find_file(struct mem_file *archive, const char *filename, struct mem_file *result) +int find_file(const struct mem_file *archive, const char *filename, struct mem_file *result) { char *walk, *fullname; struct lar_header *header; @@ -145,7 +145,7 @@ return 1; }
-static int process_file(struct mem_file *archive, void *where) +static int process_file(const struct mem_file *archive, void *where) { printk(BIOS_SPEW, "LAR: Compression algorithm #%i used\n", archive->compression); /* no compression */ @@ -175,6 +175,37 @@ }
/** + * Given a file name, search the LAR for all segments of it, and load them + * into memory, using the loadaddress pointer in the mem_file struct. + * @param archive A descriptor for current archive. + * @param filename filename to find + * returns entry on success, (void*)-1 otherwise + * FIXME: Look for a cmdline as well. + */ +void *load_file_segments(const struct mem_file *archive, const char *filename) +{ + void *entry = NULL; + void *newentry; + int i; + char tmpname[64]; + + for(i = 0, entry = (void *)0; ;i++) { + sprintf(tmpname, "%s/segment%d", filename, i); + newentry = load_file(archive, tmpname); + if (newentry == (void *)-1) + break; + if (!entry) + entry = newentry; + } + if (!entry) { + printk(BIOS_INFO, "LAR: load_file_segments: Failed for %s\n", filename); + return (void *)-1; + } + printk(BIOS_SPEW, "LAR: load_file_segments: All loaded, entry %p\n", entry); + return entry; +} + +/** * Given a file name in the LAR , search for it, and load it into memory, using * the loadaddress pointer in the mem_file struct. * @param archive A descriptor for current archive. @@ -182,7 +213,7 @@ * returns entry on success, (void*)-1 otherwise */
-void *load_file(struct mem_file *archive, const char *filename) +void *load_file(const struct mem_file *archive, const char *filename) { int ret; struct mem_file result; @@ -212,7 +243,7 @@ * @param where pointer to where to load the data * returns 0 on success, -1 otherwise */ -int copy_file(struct mem_file *archive, const char *filename, void *where) +int copy_file(const struct mem_file *archive, const char *filename, void *where) { int ret; struct mem_file result; @@ -229,55 +260,30 @@
/** - * Given a file name in the LAR , search for it, and load it into memory, - * using the passed-in pointer as the address; jump to the file. - * If the passed-in pointer is (void *)-1, then execute the file in place. + * Given a file name in the LAR , search for it, and execute it in place. * @param archive A descriptor for current archive. * @param filename filename to find - * @param where pointer to where to load the data * returns 0 on success, -1 otherwise */ -int run_file(struct mem_file *archive, const char *filename, void *where) +int execute_in_place(const struct mem_file *archive, const char *filename) { struct mem_file result; int ret; + void *where;
- if ((u32) where != 0xFFFFFFFF) { - if (copy_file(archive, filename, where)) { - printk(BIOS_INFO, - "LAR: Run file %s failed: No such file.\n", - filename); - return 1; - } - } else { /* XIP */ - if (find_file(archive, filename, &result)) { - printk(BIOS_INFO, - "LAR: Run file %s failed: No such file.\n", - filename); - return 1; - } - if (result.compression != 0) { - printk(BIOS_INFO, - "LAR: Run file %s failed: Compressed file" - " not supported for in-place execution\n", - filename); - return 1; - } - where = result.start + (u32)result.entry; + if (find_file(archive, filename, &result)) { + printk(BIOS_INFO, "LAR: Run file %s failed: No such file.\n", + filename); + return 1; } + if (result.compression != 0) { + printk(BIOS_INFO, "LAR: Run file %s failed: Compressed file" + " not supported for in-place execution\n", filename); + return 1; + } + where = result.start + (u32)result.entry; printk(BIOS_SPEW, "Entry point is %p\n", where); ret = run_address(where); printk(BIOS_SPEW, "run_file returns with %d\n", ret); return ret; } - -/** - * Given a file name in the LAR , search for it, and execute it in place. - * @param archive A descriptor for current archive. - * @param filename filename to find - * returns 0 on success, -1 otherwise - */ -int execute_in_place(struct mem_file *archive, const char *filename) -{ - return run_file(archive, filename, (void *) 0xFFFFFFFF); -} Index: LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c =================================================================== --- LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c (Revision 529) +++ LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c (Arbeitskopie) @@ -77,7 +77,6 @@ struct mem_file archive, result; int elfboot_mem(struct lb_memory *mem, void *where, int size); void *entry; - int i;
/* we can't statically init this hack. */ unsigned char faker[64]; @@ -161,11 +160,9 @@ /* Turn off Cache-As-Ram */ disable_car();
- entry = load_file(&archive, "normal/stage2.o/segment0"); + entry = load_file_segments(&archive, "normal/stage2.o"); if (entry == (void *)-1) - die("FATAL: Failed loading stage2 segment0."); - if (load_file(&archive, "normal/stage2.o/segment1") == (void *)-1) - die("FATAL: Failed loading stage2 segment1."); + die("FATAL: Failed loading stage2."); ret = run_address(entry); if (ret) die("FATAL: Failed in stage2 code."); @@ -176,26 +173,8 @@ if (! ret) legacy(&archive, "normal/payload", (void *)UNCOMPRESS_AREA, mem);
- - /* new style lar boot. Install all the files in memory. - * By convention we take the entry point from the first - * one. Look for a cmdline as well. - */ - for(i = 0, entry = (void *)0; ;i++) { - char filename[64]; - void *newentry; - sprintf(filename, "normal/payload/segment%d", i); - archive.len = *(u32 *)0xfffffff4; - archive.start =(void *)(0UL-archive.len); - newentry = load_file(&archive, filename); - printk(BIOS_SPEW, "newentry is %p\n", newentry); - if (newentry == (void *)-1) - break; - if (! entry) - entry = newentry; - } - printk(BIOS_SPEW, "all loaded, entry %p\n", entry); - if (entry) + entry = load_file_segments(&archive, "normal/payload"); + if (entry != (void*)-1) run_address(entry);
die("FATAL: No usable payload found.\n");
On 28.11.2007 23:23, ron minnich wrote:
Acked-by: Ronald G. Minnich rminnich@gmail.com
Thanks, that was on my list.
Thanks, r530.
Regards, Carl-Daniel
* Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net [071128 00:52]:
Consolidate all multiple segment handling into lib/lar.c:load_file_segments() and greatly simplify arch/x86/stage1.c code as a result. While I'm at it, improve the LAR segmentation abstraction. Stage 1 code should not have to care about internal representation of segments, that knowledge belongs into lib/lar.c. Constification of most function parameters in lib/lar.c led to a few other now obvious code removals.
Build tested and runtime tested in Qemu.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c
=================================================================== --- LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c (Revision 529) +++ LinuxBIOSv3-betterlarsegments/arch/x86/stage1.c (Arbeitskopie) @@ -161,11 +160,9 @@ /* Turn off Cache-As-Ram */ disable_car();
- entry = load_file(&archive, "normal/stage2.o/segment0");
- entry = load_file_segments(&archive, "normal/stage2.o");
please remove ".o" -- these are NOT .o files.
Remove ".o" suffix from parsed ELF files in the LAR.
Build tested and runtime tested in Qemu.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: LinuxBIOSv3-betterparsedelfnaming/lib/lar.c =================================================================== --- LinuxBIOSv3-betterparsedelfnaming/lib/lar.c (Revision 532) +++ LinuxBIOSv3-betterparsedelfnaming/lib/lar.c (Arbeitskopie) @@ -141,7 +141,7 @@ walk += (ntohl(header->offset) + ntohl(header->len) - 1) & 0xfffffff0; } - printk(BIOS_SPEW, "LAR: NO FILE FOUND!\n"); + printk(BIOS_SPEW, "LAR: File not found!\n"); return 1; }
Index: LinuxBIOSv3-betterparsedelfnaming/util/lar/stream.c =================================================================== --- LinuxBIOSv3-betterparsedelfnaming/util/lar/stream.c (Revision 532) +++ LinuxBIOSv3-betterparsedelfnaming/util/lar/stream.c (Arbeitskopie) @@ -63,7 +63,7 @@
/** * Output all the ELF segments for a given file - * @param lar The LAR Archoe + * @param lar The LAR archive * @param name The LAR name * @param filebuf The ELF file * @param filelen Size of the ELF file @@ -82,15 +82,20 @@ int segment = 0; char *header; char ename[64]; + char *strippedname; int headers; char *temp; enum compalgo thisalgo; u32 complen;
/* Allocate a temporary buffer to compress into - this is unavoidable, - because we need to make sure that the compressed data will fit in - the LAR, and we won't know the size of the compressed data until - we actually compress it */ + * because we need to make sure that the compressed data will fit in + * the LAR, and we won't know the size of the compressed data until + * we actually compress it. + * FIXME: In case the compressed file is bigger than the original, + * we corrupt memory. Compute maximum size increase and allocate that + * on top of the file length. + */
temp = calloc(filelen, 1);
@@ -99,6 +104,15 @@ return -1; }
+ strippedname = strdup(name); + if (strippedname == NULL) { + err("Out of memory.\n"); + return -1; + } + /* Check if name ends in ".o" and strip that. */ + if (!strcmp(strippedname + strlen(strippedname) - 2, ".o")) + strippedname[strlen(strippedname) - 2] = '\0'; + /* validate elf header */ ehdr = (Elf32_Ehdr *)filebuf; headers = ehdr->e_phnum; @@ -154,13 +168,15 @@ entry, phdr[i].p_paddr); } /* ok, copy it out */ - sprintf(ename, "%s/segment%d", name, segment++); + sprintf(ename, "%s/segment%d", strippedname, segment++); complen = lar_compress(&header[phdr[i].p_offset], size, temp, &thisalgo); ret = lar_add_entry(lar, ename, temp, complen, size, phdr[i].p_paddr, entry, thisalgo); } + free(strippedname); return 0; out: + free(strippedname); return -1; }
Index: LinuxBIOSv3-betterparsedelfnaming/arch/x86/stage1.c =================================================================== --- LinuxBIOSv3-betterparsedelfnaming/arch/x86/stage1.c (Revision 532) +++ LinuxBIOSv3-betterparsedelfnaming/arch/x86/stage1.c (Arbeitskopie) @@ -137,17 +137,17 @@ // find first initram if (check_normal_boot_flag()) { printk(BIOS_DEBUG, "Choosing normal boot.\n"); - ret = execute_in_place(&archive, "normal/initram.o/segment0"); + ret = execute_in_place(&archive, "normal/initram/segment0"); } else { printk(BIOS_DEBUG, "Choosing fallback boot.\n"); - ret = execute_in_place(&archive, "fallback/initram.o/segment0"); + ret = execute_in_place(&archive, "fallback/initram/segment0"); /* Try a normal boot if fallback doesn't exist in the lar. * TODO: There are other ways to do this. * It could be ifdef or the boot flag could be forced. */ if (ret) { printk(BIOS_DEBUG, "Fallback failed. Try normal boot\n"); - ret = execute_in_place(&archive, "normal/initram.o/segment0"); + ret = execute_in_place(&archive, "normal/initram/segment0"); } }
@@ -160,7 +160,7 @@ /* Turn off Cache-As-Ram */ disable_car();
- entry = load_file_segments(&archive, "normal/stage2.o"); + entry = load_file_segments(&archive, "normal/stage2"); if (entry == (void *)-1) die("FATAL: Failed loading stage2."); ret = run_address(entry);