ref: 78eff200d85e0fc2f92622d221c0e3d81aaf9522
dir: /sys/src/9/xen/xenbin.c/
/* * Transform a Plan 9 386 bootable image to make it compatible with * the Xen binary image loader: * * - pad the beginning of the text with zeroes so that the image can be loaded at * guest 'physical' address 0 * - insert a Xen header * - pad the end of the text so that data segment is page-aligned in the file * - adjust the linenumber-pc table so Plan 9 debuggers won't be confused */ #include <u.h> #include <libc.h> #include <bio.h> #include <mach.h> #define PAGE 4096 #define PLAN9HDR 32 #define XENHDR 32 #define KZERO 0x80000000 #define FLAG_VALID (1<<16) #define FLAG_PAE (1<<14) void lput(long n) { char buf[sizeof(long)]; int i; for (i = sizeof(long)-1; i >= 0; i--) { buf[i] = n; n >>= 8; } write(1, buf, sizeof(long)); } void rput(long n) { char buf[sizeof(long)]; int i; for (i = 0; i < sizeof(long); i++) { buf[i] = n; n >>= 8; } write(1, buf, sizeof(long)); } void copy(long n) { char buf[PAGE]; int m; while (n > 0) { m = sizeof buf; if (m > n) m = n; read(0, buf, m); write(1, buf, m); n -= m; } } void pad(int n) { char buf[PAGE]; int m; memset(buf, 0, sizeof buf); while (n > 0) { m = sizeof buf; if (m > n) m = n; write(1, buf, m); n -= m; } } /* * See /sys/src/cmd/8l/span.c:/^asmlc */ void adjustlnpc(int v) { char buf[PAGE]; int n, s; n = 0; while (v) { s = 127; if (v < 127) s = v; buf[n++] = s+128; if (n == sizeof buf) { write(1, buf, n); n = 0; } v -= s; } if (n > 0) write(1, buf, n); } void main(int argc, char **argv) { Fhdr fhdr; long newtxtsz; long newentry; long newlnpcsz; long prepad, postpad; long flags; flags = FLAG_VALID; if (argc > 1 && strcmp(argv[1], "-p") == 0) flags |= FLAG_PAE; crackhdr(0, &fhdr); newtxtsz = ((fhdr.txtsz+PLAN9HDR+PAGE-1)&~(PAGE-1)) - PLAN9HDR; newentry = KZERO+PLAN9HDR; prepad = fhdr.entry - newentry; postpad = newtxtsz - fhdr.txtsz; newtxtsz += prepad; newlnpcsz = fhdr.lnpcsz; if (newlnpcsz) newlnpcsz += (prepad+126)/127; /* plan 9 header */ lput(4*11*11+7); /* magic */ lput(newtxtsz); /* sizes */ lput(fhdr.datsz); lput(fhdr.bsssz); lput(fhdr.symsz); /* nsyms */ lput(newentry); /* va of entry */ lput(fhdr.sppcsz); /* sp offsets */ lput(newlnpcsz); /* line offsets */ /* xen header */ rput(0x336EC578); /* magic */ rput(flags); /* flags */ rput(-(0x336EC578+flags)); /* checksum */ rput(newentry); /* header_addr */ rput(KZERO); /* load_addr */ rput(KZERO+newtxtsz+fhdr.datsz); /* load_end_addr */ rput(KZERO+newtxtsz+fhdr.datsz+fhdr.bsssz); /* bss_end_addr */ rput(fhdr.entry); /* entry_addr */ pad(prepad-XENHDR); seek(0, fhdr.txtoff, 0); copy(fhdr.txtsz); pad(postpad); copy(fhdr.datsz); copy(fhdr.symsz); if (newlnpcsz) { adjustlnpc(prepad); copy(fhdr.lnpcsz); } exits(0); }