[LinuxBIOS] patch: extending LAR, and removing elf from linuxbios (it is not needed)
Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006 at gmx.net
Tue Aug 28 01:54:41 CEST 2007
On 27.08.2007 19:25, ron minnich wrote:
> 7. Since we have a load address, we can create this lar entry:
> normal/cmdline
> and specify that it be loaded at a place where linux will find it as
> the cmdline.
>
> The change is simple. Add a load address and entry point to the lar
> header. Extend the lar tool to parse the elf file and create multiple
> lar segments. It looks like this:
> normal/payload0 (33192 bytes, lzma compressed to 18088 bytes @0x38
> load @0x100000, entry 0x105258)
> normal/payload1 (72 bytes, lzma compressed to 47 bytes @0x4718 load
> @0x1225a0, entry 0x105258)
> normal/option_table (932 bytes @0x4798 load @0, entry 0)
> normal/stage2 (33308 bytes, lzma compressed to 15474 bytes @0x4b78
> load @0, entry 0)
> normal/initram (4208 bytes @0x8828 load @0, entry 0)
> linuxbios.bootblock (16384 bytes @0xfc000 load @0, entry 0)
>
> note that the payload is now payload0, payload1, etc. I've extended
> linuxbios to look for these. Note that you can now see all the things
> that get loaded ;they're no longer hidden in an ELF header somewhere.
> Elf failures are gone!
What about creating directories for each payload so we can differentiate
between multiple payloads (in the original sense)?
normal/payload0/segment0 (33192 bytes, lzma compressed to 18088 bytes
@0x38 load @0x100000, entry 0x105258)
normal/payload0/segment1 (72 bytes, lzma compressed to 47 bytes
@0x4718 load @0x1225a0, entry 0x105258)
normal/payload1/segment0 (xxx bytes, lzma compressed to yyy bytes
@0xfoo load @0xbar, entry 0xbaz)
normal/option_table (932 bytes @0x4798 load @0, entry 0)
normal/stage2 (33308 bytes, lzma compressed to 15474 bytes @0x4b78
load @0, entry 0)
normal/initram (4208 bytes @0x8828 load @0, entry 0)
linuxbios.bootblock (16384 bytes @0xfc000 load @0, entry 0)
The normal/payload0/ directory would contain the ELF segments of the
first payload etc. The mapping between your proposal and mine would be:
Yours <-> Mine
normal/payload0 normal/payload0/segment0
normal/payload1 normal/payload0/segment1
N/A normal/payload1/segment0
What do you think?
Comments about the patch:
> --- include/lar.h (revision 464)
This is against an old tree. lar has changed in between.
> +++ include/lar.h (working copy)
> @@ -54,7 +54,7 @@
>
> #define MAGIC "LARCHIVE"
> #define MAX_PATHLEN 1024
> -
> +/* NOTE -- This and the user-mode lar.h are NOT IN SYNC. Be careful. */
Maybe also mention util/lar/README which is even less in sync.
> struct lar_header {
> char magic[8];
> u32 len;
> @@ -62,6 +62,13 @@
> u32 checksum;
> u32 compchecksum;
> u32 offset;
> + u32 entry; /* we might need to make this u64 */
> + u32 loadaddress; /* ditto */
> + /* Compression:
> + * 0 = no compression
> + * 1 = lzma
> + * 2 = nrv2b
> + */
> u32 compression;
> };
>
Maybe we should introduce a major/minor version in the LAR header? Or a
different magic string for each revision?
Do we also need an alignment parameter in the header (like "free
placement, but please align to xx")?
> @@ -69,6 +76,8 @@
> void *start;
> int len;
> u32 reallen;
> + void * entry;
> + void * loadaddress;
void *entry;
void *loadaddress;
> u32 compression;
> };
>
> @@ -77,5 +86,6 @@
> int copy_file(struct mem_file *archive, char *filename, void *where);
> int run_file(struct mem_file *archive, char *filename, void *where);
> int execute_in_place(struct mem_file *archive, char *filename);
> -
> +int run_address(void *f);
> +void * load_file(struct mem_file *archive, char *filename);
void *load_file(...)
> #endif /* LAR_H */
> --- lib/lar.c (revision 464)
> +++ lib/lar.c (working copy)
> @@ -52,19 +59,69 @@
> // FIXME: check checksum
>
> if (strcmp(fullname, filename) == 0) {
> + printk(BIOS_SPEW, "LAR: it matches %s @ %p\n", fullname, header);
> result->start = walk + ntohl(header->offset);
> result->len = ntohl(header->len);
> result->reallen = ntohl(header->reallen);
> result->compression = ntohl(header->compression);
> + result->entry = (void *)ntohl(header->entry);
> + result->loadaddress = (void *)ntohl(header->loadaddress);
> + printk(BIOS_SPEW, "start %p len %d reallen %d compression %x entry %p loadaddress %p\n",
> + result->start, result->len, result->reallen, result->compression, result->entry, result->loadaddress);
> return 0;
> }
> // skip file
> walk += (ntohl(header->len) + ntohl(header->offset) -
> 1) & 0xfffffff0;
> }
> + printk(BIOS_SPEW, "NO FILE FOUND\n");
> return 1;
> }
>
> +
> +void * load_file(struct mem_file *archive, char *filename)
void *load_file(...)
> +{
> + int ret;
> + struct mem_file result;
> + void *where;
> + void *entry;
> +
> + ret = find_file(archive, filename, &result);
> + if (ret) {
> + printk(BIOS_INFO, "LAR: load_file: No such file '%s'\n",
> + filename);
> + return (void *)-1;
> + }
> + entry = result.entry;
> + where = result.loadaddress;
> + printk(BIOS_SPEW, "LAR: Compression algorithm #%i used\n", result.compression);
> + /* no compression */
> + if (result.compression == 0) {
> + memcpy(where, result.start, result.len);
> + return entry;
> + }
> +#ifdef CONFIG_COMPRESSION_LZMA
> + /* lzma */
> + unsigned long ulzma(unsigned char * src, unsigned char * dst);
dito.
> + if (result.compression == 1) {
> + ulzma(result.start, where);
> + return entry;
> + }
> +#endif
> +#ifdef CONFIG_COMPRESSION_NRV2B
> + /* nrv2b */
> + unsigned long unrv2b(u8 * src, u8 * dst, unsigned long *ilen_p);
dito.
> + if (result.compression == 2) {
> + int tmp;
> + unrv2b(result.start, where, &tmp);
> + return entry;
> + }
> +#endif
> + printk(BIOS_INFO, "LAR: Compression algorithm #%i not supported!\n", result.compression);
> + return (void *)-1;
> +}
> +
> --- mainboard/emulation/qemu-x86/initram.c (revision 464)
> +++ mainboard/emulation/qemu-x86/initram.c (working copy)
> @@ -19,10 +19,12 @@
>
> #include <console.h>
>
> +int (*pk)(int msg_level, const char *fmt, ...) = printk;
> +
> int main(void)
> {
> - printk(BIOS_INFO, "RAM init code started.\n");
> - printk(BIOS_INFO, "Nothing to do.\n");
> + pk(BIOS_INFO, "RAM init code started.\n");
> + pk(BIOS_INFO, "Nothing to do.\n");
>
> return 0;
> }
My eyes!
> --- mainboard/emulation/qemu-x86/Makefile (revision 464)
> +++ mainboard/emulation/qemu-x86/Makefile (working copy)
> @@ -41,14 +41,17 @@
> #
>
> INITRAM_OBJ = $(obj)/mainboard/$(MAINBOARDDIR)/initram.o
> +$(obj)/mainboard/$(MAINBOARDDIR)/initram.o: $(src)/mainboard/$(MAINBOARDDIR)/initram.c
> + cc -c $(INITCFLAGS) -fPIE $(src)/mainboard/$(MAINBOARDDIR)/initram.c -o $(obj)/mainboard/$(MAINBOARDDIR)/initram.o
> +
> # These are possibly not permanent
> -INITRAM_OBJ += $(obj)/lib/console.o $(obj)/lib/vtxprintf.o $(obj)/lib/uart8250.o $(obj)/arch/x86/post_code.o
> +#INITRAM_OBJ += $(obj)/lib/console.o $(obj)/lib/vtxprintf.o $(obj)/lib/uart8250.o $(obj)/arch/x86/post_code.o
>
> $(obj)/linuxbios.initram: $(obj)/stage0.init $(obj)/stage0.o $(INITRAM_OBJ)
> $(Q)# initram links against stage0
> $(Q)printf " LD $(subst $(shell pwd)/,,$(@))\n"
> - $(Q)$(LD) -Ttext 0x80000 $(INITRAM_OBJ) \
> - --entry=main -o $(obj)/linuxbios.initram.o
> + $(Q)$(LD) $(INITRAM_OBJ) \
> + --entry=main -R $(obj)/stage0.o -o $(obj)/linuxbios.initram.o
> $(Q)printf " OBJCOPY $(subst $(shell pwd)/,,$(@))\n"
> $(Q)$(OBJCOPY) -O binary $(obj)/linuxbios.initram.o \
> $(obj)/linuxbios.initram
Could you explain that one?
> Index: arch/x86/stage1.c
> ===================================================================
> --- arch/x86/stage1.c (revision 464)
> +++ arch/x86/stage1.c (working copy)
> @@ -144,20 +168,32 @@
> printk(BIOS_DEBUG, "Stage2 code done.\n");
>
> ret = find_file(&archive, "normal/payload", &result);
> - if (ret) {
> - printk(BIOS_ERR, "No such file '%s'.\n", "normal/payload");
> - die("FATAL: No payload found.\n");
> + 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
Needs real documentation (LAR README maybe?), not just a code comment.
> + * one. Look for a cmdline as well.
dito.
> + */
> + for(i = 0, entry = (void *)0; ;i++) {
> + char filename[64];
> + void *newentry;
> + sprintf(filename, "normal/payload%d", i);
> + archive.len = *(u32 *)0xfffffff4;
> + archive.start =(void *)(0UL-archive.len);
> + newentry = load_file(&archive, filename);
> + printk("newentry is %p\n", newentry);
> + if (newentry == (void *)-1)
> + break;
> + if (! entry)
> + entry = newentry;
> }
> - ret = copy_file(&archive, "normal/payload", (void *)UNCOMPRESS_AREA);
> - if (ret) {
> - printk(BIOS_ERR, "'%s' found, but could not load it.\n", "normal/payload");
> - die("FATAL: No usable payload found.\n");
> - }
> + printk(BIOS_SPEW, "all loaded, entry %p\n", entry);
> + run_address(entry);
>
> - ret = elfboot_mem(mem, (void *)UNCOMPRESS_AREA, result.reallen);
> + die("FATAL: No usable payload found.\n");
>
> - printk(BIOS_ERR, "elfboot_mem returns %d\n", ret);
> -
> die ("FATAL: Last stage returned to LinuxBIOS.\n");
> }
>
> Index: arch/x86/Makefile
> ===================================================================
> --- arch/x86/Makefile (revision 464)
> +++ arch/x86/Makefile (working copy)
> @@ -22,7 +22,7 @@
> ifeq ($(CONFIG_ARCH_X86),y)
>
> INITCFLAGS := $(CFLAGS) -I$(src)/include/arch/x86 -I$(src)/include \
> - -I$(obj) -fno-builtin
> + -I$(obj) -fno-builtin
Superfluous whitespace introduction.
> SILENT := >/dev/null 2>&1
>
> @@ -77,7 +77,7 @@
> fi
> endif
> $(Q)printf " LAR $(subst $(shell pwd)/,,$(@))\n"
> - $(Q)cd $(obj)/lar.tmp && ../util/lar/lar $(COMPRESSFLAG) -c \
> + $(Q)cd $(obj)/lar.tmp && ../util/lar/lar -p $(COMPRESSFLAG) -c \
lar -p option is not mentioned in the lar help message.
> ../linuxbios.rom \
> $(LARFILES) \
> -s $(ROM_SIZE) -b $(obj)/linuxbios.bootblock
> @@ -142,6 +142,9 @@
> $(Q)printf " OBJCOPY $(subst $(shell pwd)/,,$(@))\n"
> $(Q)$(OBJCOPY) -O binary $(obj)/stage0.o $(obj)/stage0.init
>
> + $(Q)printf " OBJCOPY (stage0 link) $(subst $(shell pwd)/,,$(@))\n"
> + $(Q)$(OBJCOPY) --prefix-symbols=stage0 $(obj)/stage0.o $(obj)/stage0_link.o
> +
> $(Q)printf " TEST $(subst $(shell pwd)/,,$(@))\n"
> $(Q)test `wc -c < $(obj)/stage0.init` -gt 16128 && \
> printf "Error. Bootblock got too big.\n" || true
Please explain.
> --- util/lar/lar.c (revision 464)
old revision, you will have to make sure the merge won't kill the
changes since 464.
> +++ util/lar/lar.c (working copy)
> @@ -37,6 +37,7 @@
> #define COPYRIGHT "Copyright (C) 2006-2007 coresystems GmbH"
>
> static int isverbose = 0;
> +static int isparseelf = 0;
> static long larsize = 0;
> static char *bootblock = NULL;
> enum compalgo algo = none;
> @@ -44,9 +45,14 @@
> static void usage(char *name)
> {
> printf("\nLAR - the LinuxBIOS Archiver " VERSION "\n" COPYRIGHT "\n\n"
> - "Usage: %s [-cxl] archive.lar [[[file1] file2] ...]\n\n", name);
> + "Usage: %s [-ecxl] archive.lar [[[file1] file2] ...]\n\n", name);
ecxl is missing a few options, among them p.
> }
>
> +int parseelf(void)
> +{
> + return isparseelf;
> +}
> +
> int verbose(void)
> {
> return isverbose;
> @@ -78,6 +84,7 @@
> {"list", 0, 0, 'l'},
> {"size", 1, 0, 's'},
> {"bootblock", 1, 0, 'b'},
> + {"parseelf", 1, 0, 'p'},
> {"verbose", 0, 0, 'v'},
> {"version", 0, 0, 'V'},
> {"help", 0, 0, 'h'},
> @@ -89,7 +96,7 @@
> exit(1);
> }
>
> - while ((opt = getopt_long(argc, argv, "cC:xls:b:vVh?",
> + while ((opt = getopt_long(argc, argv, "cC:xlps:b:vVh?",
> long_options, &option_index)) != EOF) {
> switch (opt) {
> case 'c':
> @@ -106,6 +113,9 @@
> case 'l':
> larmode = LIST;
> break;
> + case 'p':
> + isparseelf = 1;
> + break;
> case 'x':
> larmode = EXTRACT;
> break;
> --- util/lar/create.c (revision 464)
> +++ util/lar/create.c (working copy)
> @@ -49,6 +49,201 @@
> out_len[0] = in_len;
> }
>
> +char *readfile(char *name, int *plen)
> +{
> + int ret, filelen;
> + FILE *source;
> + char *filebuf;
> + struct stat statbuf;
> + *plen = -1;
> + ret = stat(name, &statbuf);
> + if (ret) {
> + fprintf(stderr, "No such file %s\n", name);
> + exit(1);
> + }
> + filelen = statbuf.st_size;
> + /* Read file into memory. */
> + filebuf = malloc(filelen);
> + source = fopen(name, "r");
> + if (!source) {
> + fprintf(stderr, "No such file %s\n", name);
> + exit(1);
> + }
> + fread(filebuf, filelen, 1, source);
> + fclose(source);
> + *plen = filelen;
> + return filebuf;
> +}
> +
> +/* given an output file name, with data pointed to by filebuf, of size filelen,
> + * output it to the lar define by FILE *lar
> + */
> +int
> +outputfile(char *name, char *filebuf, int filelen, enum compalgo algo, FILE *archive, u32 entry, u32 loadaddress)
int outputfile(...
> +{
> + char *pathname;
> + int i, ret;
> + int diff = 0;
> + int bb_header_len = 0;
> + FILE *source;
> + char *filetarget;
> + u32 *walk;
> + u32 csum;
> + int pathlen, entrylen;
> + u32 compfilelen;
> + long currentsize = 0;
> + struct lar_header *header;
> + enum compalgo thisalgo;
> + char *tempmem;
> + thisalgo = algo;
> + int tempsize = sizeof(struct lar_header) + MAX_PATHLEN + filelen + 16;
> + tempmem = malloc(tempsize);
> + if (!tempmem) {
> + fprintf(stderr, "Out of memory.\n");
> + return (-1);
> + }
> + memset(tempmem, 0, tempsize);
> + header = (struct lar_header *)tempmem;
> + pathname = tempmem + sizeof(struct lar_header);
> + pathlen = snprintf(pathname, MAX_PATHLEN - 1, name) + 1;
> + pathlen = (pathlen + 15) & 0xfffffff0; /* Align to 16 bytes. */
> +
> + filetarget = pathname + pathlen;
> + compress_functions[thisalgo](filebuf, filelen, filetarget,
> + &compfilelen);
> + if ((compfilelen >= filelen) && (thisalgo != none)) {
> + thisalgo = none;
> + compress_functions[thisalgo](filebuf, filelen,
> + filetarget, &compfilelen);
> + }
> +
> + /* Create correct header. */
> + memcpy(header, MAGIC, 8);
> + header->compression = htonl(thisalgo);
> + header->entry = htonl(entry);
> + header->loadaddress = htonl(loadaddress);
> + header->reallen = htonl(filelen);
> + header->len = htonl(compfilelen);
> + header->offset = htonl(sizeof(struct lar_header) + pathlen);
> + /* Calculate checksum. */
> + csum = 0;
> + for (walk = (u32 *) tempmem;
> + walk < (u32 *) (tempmem + compfilelen +
> + sizeof(struct lar_header) + pathlen);
> + walk++) {
> + csum += ntohl(*walk);
> + }
> + header->checksum = htonl(csum);
> + /* Write out entry to archive. */
> + entrylen = (compfilelen + pathlen + sizeof(struct lar_header) +
> + 15) & 0xfffffff0;
> +
> + fwrite(tempmem, entrylen, 1, archive);
> + free(tempmem);
> + return entrylen;
> +}
> [...]
> +
> +int
> +outputelf(char *name, char *filebuf, int filelen, enum compalgo algo, FILE *archive)
dito.
> +{
> + int index;
> --- util/lar/Makefile (revision 464)
> +++ util/lar/Makefile (working copy)
> @@ -33,14 +34,15 @@
> endif
>
> LAROBJ_ABS := $(patsubst %,$(obj)/util/lar/%,$(LAROBJ))
> -
> +HOSTCFLAGS+=-g
> +HOSTCXXFLAGS+=-g
> lardir:
> $(Q)printf " BUILD LAR\n"
> $(Q)mkdir -p $(obj)/util/lar
>
> $(obj)/util/lar/lar: $(LARDIR) $(LAROBJ_ABS) $(COMPRESSOR)
> $(Q)printf " HOSTCXX $(subst $(shell pwd)/,,$(@))\n"
> - $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ $(LAROBJ_ABS) $(COMPRESSOR)
> + $(Q)$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ $(LAROBJ_ABS) $(COMPRESSOR)
Superfluous whitespace.
>
> $(obj)/util/lar/%.o: $(src)/util/lar/%.c
> $(Q)printf " HOSTCC $(subst $(shell pwd)/,,$(@))\n"
>
>
Regards,
Carl-Daniel
More information about the coreboot
mailing list