On 27.08.2007 19:25, ron minnich wrote:
- 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",
} // skip file walk += (ntohl(header->len) + ntohl(header->offset) - 1) & 0xfffffff0; }result->start, result->len, result->reallen, result->compression, result->entry, result->loadaddress); return 0;
- 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) \
$(Q)printf " OBJCOPY $(subst $(shell pwd)/,,$(@))\n" $(Q)$(OBJCOPY) -O binary $(obj)/linuxbios.initram.o \ $(obj)/linuxbios.initram--entry=main -R $(obj)/stage0.o -o $(obj)/linuxbios.initram.o
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'},
{"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'},{"parseelf", 1, 0, 'p'},
@@ -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;
case 'x': larmode = EXTRACT; break;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