168 lines
3.3 KiB
C
168 lines
3.3 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
#include <mach.h>
|
|
#include <flate.h>
|
|
|
|
int infd, outfd;
|
|
ulong dcrc;
|
|
ulong *tab;
|
|
uchar buf[65536];
|
|
|
|
enum {
|
|
IH_ARCH_INVALID = 0,
|
|
IH_ARCH_ALPHA,
|
|
IH_ARCH_ARM,
|
|
IH_ARCH_I386,
|
|
IH_ARCH_IA64,
|
|
IH_ARCH_MIPS,
|
|
IH_ARCH_MIPS64,
|
|
IH_ARCH_PPC,
|
|
IH_ARCH_S390,
|
|
IH_ARCH_SH,
|
|
IH_ARCH_SPARC,
|
|
IH_ARCH_SPARC64,
|
|
IH_ARCH_M68K,
|
|
IH_ARCH_NIOS,
|
|
IH_ARCH_MICROBLAZE,
|
|
IH_ARCH_NIOS2,
|
|
IH_ARCH_BLACKFIN,
|
|
IH_ARCH_AVR32,
|
|
IH_ARCH_ST200,
|
|
IH_ARCH_SANDBOX,
|
|
IH_ARCH_NDS32,
|
|
IH_ARCH_OPENRISC,
|
|
IH_ARCH_ARM64,
|
|
IH_ARCH_ARC,
|
|
IH_ARCH_X86_64,
|
|
IH_ARCH_XTENSA,
|
|
IH_ARCH_RISCV,
|
|
};
|
|
|
|
uchar archtab[] = {
|
|
[MMIPS] IH_ARCH_MIPS,
|
|
[MSPARC] IH_ARCH_SPARC,
|
|
[MI386] IH_ARCH_I386,
|
|
[MMIPS2] IH_ARCH_MIPS,
|
|
[NMIPS2] IH_ARCH_MIPS,
|
|
[MARM] IH_ARCH_ARM,
|
|
[MPOWER] IH_ARCH_PPC,
|
|
[MALPHA] IH_ARCH_ALPHA,
|
|
[NMIPS] IH_ARCH_MIPS,
|
|
[MSPARC64] IH_ARCH_SPARC64,
|
|
[MAMD64] IH_ARCH_X86_64,
|
|
[MPOWER64] IH_ARCH_PPC,
|
|
[MARM64] IH_ARCH_ARM64,
|
|
};
|
|
|
|
void
|
|
put(uchar *p, u32int v)
|
|
{
|
|
*p++ = v >> 24;
|
|
*p++ = v >> 16;
|
|
*p++ = v >> 8;
|
|
*p = v;
|
|
}
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
fprint(2, "usage: %s a.out\n", argv0);
|
|
exits("usage");
|
|
}
|
|
|
|
void
|
|
block(int n)
|
|
{
|
|
int rc;
|
|
|
|
rc = readn(infd, buf, n);
|
|
if(rc < 0) sysfatal("read: %r");
|
|
if(rc < n) sysfatal("input file truncated");
|
|
if(write(outfd, buf, n) < 0) sysfatal("write error");
|
|
dcrc = blockcrc(tab, dcrc, buf, n);
|
|
}
|
|
|
|
void
|
|
copy(int n)
|
|
{
|
|
int i;
|
|
|
|
for(i = sizeof(buf) - 1; i < n; i += sizeof(buf))
|
|
block(sizeof(buf));
|
|
i = n & sizeof(buf) - 1;
|
|
if(i > 0)
|
|
block(i);
|
|
}
|
|
|
|
void
|
|
main(int argc, char **argv)
|
|
{
|
|
Fhdr fhdr;
|
|
u64int kzero;
|
|
uchar header[64];
|
|
char *ofile, *iname;
|
|
int n, arch;
|
|
|
|
kzero = 0xF0000000;
|
|
ofile = nil;
|
|
ARGBEGIN {
|
|
case 'Z': kzero = strtoull(EARGF(usage()), 0, 0); break;
|
|
case 'o': ofile = strdup(EARGF(usage())); break;
|
|
default: usage();
|
|
} ARGEND;
|
|
|
|
if(argc != 1) usage();
|
|
infd = open(argv[0], OREAD);
|
|
if(infd < 0) sysfatal("infd: %r");
|
|
if(crackhdr(infd, &fhdr) == 0) sysfatal("crackhdr: %r");
|
|
|
|
iname = strrchr(argv[0], '/');
|
|
if(iname != nil)
|
|
iname++;
|
|
else
|
|
iname = argv[0];
|
|
if(ofile == nil) ofile = smprint("%s.u", iname);
|
|
outfd = create(ofile, OWRITE|OTRUNC, 0666);
|
|
if(outfd < 0) sysfatal("create: %r");
|
|
|
|
tab = mkcrctab(0xEDB88320);
|
|
assert(sizeof(buf) >= mach->pgsize);
|
|
seek(infd, 0, 0);
|
|
seek(outfd, sizeof(header), 0);
|
|
dcrc = 0;
|
|
|
|
copy(fhdr.hdrsz + fhdr.txtsz);
|
|
n = -(fhdr.hdrsz + fhdr.txtsz) & mach->pgsize - 1;
|
|
if(n > 0){
|
|
memset(buf, 0, n);
|
|
if(write(outfd, buf, n) < 0) sysfatal("write: %r");
|
|
dcrc = blockcrc(tab, dcrc, buf, n);
|
|
}
|
|
copy(fhdr.datsz);
|
|
|
|
if((uint)mach->mtype >= nelem(archtab) || archtab[mach->mtype] == 0)
|
|
sysfatal("archloch");
|
|
arch = archtab[mach->mtype];
|
|
|
|
memset(header, 0, sizeof(header));
|
|
put(&header[0], 0x27051956); /* magic */
|
|
put(&header[8], time(0)); /* time */
|
|
put(&header[12], -(-(fhdr.hdrsz + fhdr.txtsz) & -mach->pgsize) + fhdr.datsz); /* image size */
|
|
put(&header[16], fhdr.txtaddr - fhdr.hdrsz - kzero); /* load address */
|
|
put(&header[20], fhdr.entry - kzero); /* entry point */
|
|
put(&header[24], dcrc); /* data crc */
|
|
header[28] = 23; /* os = plan 9 */
|
|
header[29] = arch;
|
|
header[30] = 2; /* type = kernel */
|
|
header[31] = 0; /* compressed = no */
|
|
|
|
strncpy((char*)&header[32], iname, sizeof(header)-32);
|
|
put(&header[4], blockcrc(tab, 0, header, sizeof(header)));
|
|
|
|
seek(outfd, 0, 0);
|
|
if(write(outfd, header, sizeof(header)) < sizeof(header)) sysfatal("write: %r");
|
|
|
|
exits(nil);
|
|
}
|