Add support for Das U-Boot boot images Notes: Wed Mar 20 18:07:44 EDT 2013 geoff Do you really need u-boot-format images? What's wrong with ELF? There are other changes to the loaders in progress. This will have to wait until those are published in any case. Wed Mar 20 19:27:22 PDT 2013 stallion uImages are the preferred header when using U-Boot (even Linux has added support for uImages). The format is simpler than ELF and has some nice relocation properties that does away with the usual jump-around-the-header dance at boot. I have submitted a patch upstream to the U-Boot folks to treat Plan 9 as a first-class citizen: http://patchwork.ozlabs.org/patch/229459/ I don't mind waiting; I've already sent a message to Charles mentioning the work. Hopefully others find this useful. Tue Apr 2 23:10:12 PDT 2013 stallion Merged with latest ELF changes. Thu Jul 4 22:34:14 PDT 2013 stallion Genericized support for u-boot images in libmach. Reference: /n/sources/patch/maybe/arm-uboot Date: Sun Mar 17 08:36:06 CET 2013 Signed-off-by: sstallion@gmail.com Reviewed-by: geoff --- /sys/include/bootexec.h Fri Jul 5 06:47:36 2013 +++ /sys/include/bootexec.h Fri Jul 5 07:30:21 2013 @@ -135,3 +135,19 @@ struct coffsect ibsss; struct coffsect icomments; }; + +struct ubootexec +{ + ulong umagic; /* image magic */ + ulong hcrc; /* header checksum */ + ulong time; /* timestamp */ + ulong size; /* data size */ + ulong load; /* load address */ + ulong ep; /* entry point */ + ulong dcrc; /* data checksum */ + uchar os; /* operating system */ + uchar arch; /* architecture */ + uchar type; /* image type */ + uchar comp; /* compression */ + uchar name[32]; /* image name */ +}; --- /sys/src/cmd/5l/asm.c Fri Jul 5 06:52:02 2013 +++ /sys/src/cmd/5l/asm.c Fri Jul 5 07:30:32 2013 @@ -1,9 +1,43 @@ #include "l.h" +#include long OFFSET; static Prog *PP; +ulong +crc32(char *name, int len, vlong off) +{ + uchar buf[MAXIO]; + int fd, n; + ulong crc; + static ulong *crctab; + + if(crctab == nil) + crctab = mkcrctab(0xedb88320); + fd = open(name, OREAD); + if(fd < 0) { + diag("cannot open %s: %r", name); + errorexit(); + } + seek(fd, off, 0); + crc = 0; + while(len > 0) { + n = len; + if(n > sizeof buf) + n = sizeof buf; + n = read(fd, buf, n); + if(n < 0) { + diag("cannot read %s: %r", name); + errorexit(); + } + crc = blockcrc(crctab, crc, buf, n); + len -= n; + } + close(fd); + return crc; +} + long entryvalue(void) { @@ -89,6 +123,10 @@ OFFSET = rnd(HEADR+textsize, 4096); seek(cout, OFFSET, 0); break; + case 8: + OFFSET = rnd(textsize, INITRND)+HEADR; + seek(cout, OFFSET, 0); + break; } if(dlm){ char buf[8]; @@ -114,6 +152,7 @@ case 1: case 4: case 5: + case 8: debug['s'] = 1; break; case 2: @@ -218,6 +257,33 @@ case 7: /* elf */ debug['S'] = 1; /* symbol table */ elf32(ARM, ELFDATA2LSB, 0, nil); + break; + case 8: /* u-boot image */ + t = rnd(textsize, INITRND)+datsize; + lput(0x27051956); /* image magic */ + lput(0); /* header checksum */ + lput(time(nil)); /* timestamp */ + lput(t); /* data size */ + lput(INITTEXT); /* load address */ + lput(entryvalue()); /* entry point */ + lput(0); /* data checksum */ + cput(23); /* os = Plan 9 */ + cput(2); /* arch = ARM */ + cput(2); /* type = OS Kernel Image */ + cput(0); /* compression = none */ + strnput(outfile, 32); /* image name */ + cflush(); + + /* calculate data checksum */ + OFFSET = 24; + seek(cout, OFFSET, 0); + lput(crc32(outfile, t, HEADR)); + cflush(); + + /* calculate header checksum */ + OFFSET = 4; + seek(cout, OFFSET, 0); + lput(crc32(outfile, HEADR, 0)); break; } cflush(); --- /sys/src/cmd/5l/obj.c Fri Jul 5 06:51:11 2013 +++ /sys/src/cmd/5l/obj.c Fri Jul 5 06:51:13 2013 @@ -24,6 +24,7 @@ * -H5 -T0xC0008010 -R1024 is ipaq * -H6 -R4096 no header with segments padded to pages * -H7 is elf + * -H8 is u-boot image */ void @@ -222,6 +223,15 @@ if(INITRND == -1) INITRND = 4; break; + case 8: /* u-boot image */ + HEADR = 64L; + if(INITTEXT == -1) + INITTEXT = 0; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 4; + break; } if (INITTEXTP == -1) INITTEXTP = INITTEXT; --- /sys/src/libmach/executable.c Fri Jul 5 06:48:10 2013 +++ /sys/src/libmach/executable.c Fri Jul 5 06:49:46 2013 @@ -22,6 +22,7 @@ struct mips4kexec; /* bootexec.h */ struct sparcexec; /* bootexec.h */ struct nextexec; /* bootexec.h */ + struct ubootexec; /* bootexec.h */ } e; long dummy; /* padding to ensure extra long */ } ExecHdr; @@ -35,6 +36,7 @@ static int adotout(int, Fhdr*, ExecHdr*); static int elfdotout(int, Fhdr*, ExecHdr*); static int armdotout(int, Fhdr*, ExecHdr*); +static int uboot(int, Fhdr*, ExecHdr*); static void setsym(Fhdr*, long, long, long, vlong); static void setdata(Fhdr*, uvlong, long, vlong, long); static void settext(Fhdr*, uvlong, uvlong, long, vlong); @@ -234,6 +236,15 @@ sizeof(Exec), leswal, armdotout }, + { 0x27051956, /* any u-boot image */ + "u-boot image", + nil, + FNONE, + 0, + nil, + sizeof(struct ubootexec), + beswal, + uboot }, { L_MAGIC, /* alpha 7.out */ "alpha plan 9 executable", "alpha plan 9 dlm", @@ -871,6 +882,62 @@ return 1; } +/* + * u-boot bootable image + */ +static int +uboot(int, Fhdr *fp, ExecHdr *hp) +{ + fp->txtaddr = hp->e.load; + fp->txtsz = hp->e.size; + switch(hp->e.arch) { + case 1: + mach = &malpha; + fp->type = FALPHA; + fp->name = "alpha u-boot image"; + break; + case 2: + mach = &marm; + fp->type = FARM; + fp->name = "ARM u-boot image"; + break; + case 3: + mach = &mi386; + fp->type = FI386; + fp->name = "386 u-boot image"; + break; + case 5: + mach = &mmips; + fp->type = FMIPS; + fp->name = "mips u-boot image"; + break; + case 7: + mach = &mpower; + fp->type = FPOWER; + fp->name = "power u-boot image"; + break; + case 10: + mach = &msparc; + fp->type = FSPARC; + fp->name = "sparc u-boot image"; + break; + case 11: + mach = &msparc64; + fp->type = FSPARC64; + fp->name = "sparc64 u-boot image"; + break; + case 12: + mach = &m68020; + fp->type = F68020; + fp->name = "68020 u-boot image"; + break; + default: + return 0; + } + fp->hdrsz = 0; /* header stripped */ + return 1; +} + static void settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) { @@ -899,7 +966,6 @@ fp->lnpcsz = lnpcsz; fp->lnpcoff = fp->sppcoff+fp->sppcsz; } - static uvlong _round(uvlong a, ulong b)