diff options
author | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
---|---|---|
committer | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
commit | 5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch) | |
tree | c1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/xenbin.c | |
parent | fa03455b5057675b18d1c87aef2d1071b2088de0 (diff) |
import xen 32 bit paravirtual kernel from /n/sources/xen.
Diffstat (limited to 'sys/src/9/xen/xenbin.c')
-rw-r--r-- | sys/src/9/xen/xenbin.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/sys/src/9/xen/xenbin.c b/sys/src/9/xen/xenbin.c new file mode 100644 index 000000000..1f6844e0e --- /dev/null +++ b/sys/src/9/xen/xenbin.c @@ -0,0 +1,162 @@ +/* + * 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); +} |