summaryrefslogtreecommitdiff
path: root/sys/src/9/xen/xenbin.c
diff options
context:
space:
mode:
authormischief <mischief@offblast.org>2014-06-24 18:02:25 -0700
committermischief <mischief@offblast.org>2014-06-24 18:02:25 -0700
commit5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch)
treec1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/xenbin.c
parentfa03455b5057675b18d1c87aef2d1071b2088de0 (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.c162
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);
+}