ref: 16a0a1066feea1d71ff4609b9264abfdd3bb31c5
parent: 3ce0347ef33d00b70573faca983f44c07b323b0e
author: Keegan Saunders <keegan@undefinedbehaviour.org>
date: Sun Sep 17 13:35:24 EDT 2023
add aux/aout2efi We use hand-crafted PE headers in assembler, but those are not available on platforms such as arm64 which enforce a 4-byte instruction alignment. Instead, take the same approach as aout2uimage and perform conversion during build time.
--- /dev/null
+++ b/sys/src/cmd/aux/aout2efi.c
@@ -1,0 +1,238 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+#define HDRSZ 0x200 /* EFI header size */
+
+enum {
+ EFI_IMAGE_MACHINE_IA32 = 0x014c,
+ EFI_IMAGE_MACHINE_x64 = 0x8664,
+ EFI_IMAGE_MACHINE_AARCH64 = 0xAA64,
+};
+
+static int is32;
+static int infd, outfd;
+static uchar buf[IOUNIT];
+
+static void
+pack(uchar **pp, char *fmt, ...)
+{
+ va_list args;
+ int c;
+ uchar *p;
+ u32int u;
+ u64int l;
+
+ va_start(args, fmt);
+ for(; *fmt; fmt++){
+ c = *fmt;
+ if(c == 'q' && is32)
+ c = 'l';
+ p = *pp;
+ switch(c){
+ case 'b':
+ p[0] = va_arg(args, int);
+ *pp += 1;
+ break;
+ case 'w':
+ u = va_arg(args, u32int);
+ p[0] = u;
+ p[1] = u>>8;
+ *pp += 2;
+ break;
+ case 'l':
+ u = va_arg(args, u32int);
+ p[0] = u;
+ p[1] = u>>8;
+ p[2] = u>>16;
+ p[3] = u>>24;
+ *pp += 4;
+ break;
+ case 'q':
+ l = va_arg(args, u64int);
+ p[0] = l;
+ p[1] = l>>8;
+ p[2] = l>>16;
+ p[3] = l>>24;
+ p[4] = l>>32;
+ p[5] = l>>40;
+ p[6] = l>>48;
+ p[7] = l>>56;
+ *pp += 8;
+ break;
+ case '0':
+ *pp += va_arg(args, int);
+ break;
+ default:
+ sysfatal("pack: %c", c);
+ }
+ }
+ va_end(args);
+}
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s a.out\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ Fhdr fhdr;
+ u64int kzero;
+ uchar *header;
+ char *ofile, *iname;
+ int arch, chars, relocs;
+ long n, szofdat, szofimage;
+
+ kzero = 0x8000;
+ ofile = nil;
+ relocs = 0;
+ 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");
+ switch(mach->mtype){
+ case MI386:
+ arch = EFI_IMAGE_MACHINE_IA32;
+ is32 = 1;
+ chars = 2103;
+ break;
+ case MAMD64:
+ arch = EFI_IMAGE_MACHINE_x64;
+ chars = 2223;
+ break;
+ case MARM64:
+ arch = EFI_IMAGE_MACHINE_AARCH64;
+ chars = 518;
+ relocs = 1;
+ break;
+ default:
+ SET(arch, chars);
+ sysfatal("archloch");
+ }
+ szofdat = fhdr.txtsz + fhdr.datsz;
+ szofimage = szofdat + fhdr.bsssz + HDRSZ;
+
+ iname = strrchr(argv[0], '/');
+ if(iname != nil)
+ iname++;
+ else
+ iname = argv[0];
+ if(ofile == nil)
+ ofile = smprint("%s.efi", iname);
+ outfd = create(ofile, OWRITE|OTRUNC, 0666);
+ if(outfd < 0)
+ sysfatal("create: %r");
+
+ header = buf;
+
+ /* mzhdr */
+ pack(&header, "bb0l",
+ 'M', 'Z', /* e_magic */
+ 0x3a, /* UNUSED */
+ 0x40); /* e_lfanew */
+
+ /* pehdr */
+ pack(&header, "bbbbwwlllww",
+ 'P', 'E', 0, 0,
+ arch, /* Machine */
+ 1+relocs, /* NumberOfSections */
+ 0, /* TimeDateStamp UNUSED */
+ 0, /* PointerToSymbolTable UNUSED */
+ 0, /* NumberOfSymbols UNUSED */
+ is32 ? 0xE0 : 0xF0, /* SizeOfOptionalHeader */
+ chars); /* Characteristics */
+ pack(&header, "wbblllll",
+ is32 ? 0x10B : 0x20B, /* Magic */
+ 9, /* MajorLinkerVersion UNUSED */
+ 0, /* MinorLinkerVersion UNUSED */
+ 0, /* SizeOfCode UNUSED */
+ 0, /* SizeOfInitializedData UNUSED */
+ 0, /* SizeOfUninitializedData UNUSED */
+ fhdr.entry-kzero, /* AddressOfEntryPoint */
+ 0); /* BaseOfCode UNUSED */
+ if(is32)
+ pack(&header, "l", 0); /* BaseOfData UNUSED */
+ pack(&header, "qllwwwwwwllllwwqqqqll0",
+ kzero, /* ImageBase */
+ HDRSZ, /* SectionAlignment */
+ HDRSZ, /* FileAlignment */
+ 4, /* MajorOperatingSystemVersion UNUSED */
+ 0, /* MinorOperatingSystemVersion UNUSED */
+ 0, /* MajorImageVersion UNUSED */
+ 0, /* MinorImageVersion UNUSED */
+ 4, /* MajorSubsystemVersion */
+ 0, /* MinorSubsystemVersion UNUSED */
+ 0, /* Win32VersionValue UNUSED */
+ szofimage, /* SizeOfImage */
+ HDRSZ, /* SizeOfHeaders */
+ 0, /* CheckSum UNUSED */
+ 10, /* Subsystem (10 = efi application) */
+ 0, /* DllCharacteristics UNUSED */
+ 0, /* SizeOfStackReserve UNUSED */
+ 0, /* SizeOfStackCommit UNUSED */
+ 0, /* SizeOfHeapReserve UNUSED */
+ 0, /* SizeOfHeapCommit UNUSED */
+ 0, /* LoaderFlags UNUSED */
+ 16, /* NumberOfRvaAndSizes UNUSED */
+ 32*4); /* RVA UNUSED */
+ if(relocs)
+ pack(&header, "bbbbbbbbllllllwwl",
+ '.', 'r', 'e', 'l', 'o', 'c', 0, 0,
+ 0, /* VirtualSize */
+ 0, /* VirtualAddress */
+ 0, /* SizeOfData */
+ 0, /* PointerToRawData */
+ 0, /* PointerToRelocations UNUSED */
+ 0, /* PointerToLinenumbers UNUSED */
+ 0, /* NumberOfRelocations UNUSED */
+ 0, /* NumberOfLinenumbers UNUSED */
+ 0x42100040); /* Characteristics (read, discardable) */
+ pack(&header, "bbbbbbbbllllllwwl",
+ '.', 't', 'e', 'x', 't', 0, 0, 0,
+ szofdat, /* VirtualSize */
+ HDRSZ, /* VirtualAddress */
+ szofdat, /* SizeOfData */
+ HDRSZ, /* PointerToRawData */
+ 0, /* PointerToRelocations UNUSED */
+ 0, /* PointerToLinenumbers UNUSED */
+ 0, /* NumberOfRelocations UNUSED */
+ 0, /* NumberOfLinenumbers UNUSED */
+ 0x86000020); /* Characteristics (code, RWX) */
+
+ if(write(outfd, buf, HDRSZ) != HDRSZ)
+ sysfatal("write: %r");
+ if(seek(infd, fhdr.hdrsz, 0) != fhdr.hdrsz)
+ sysfatal("seek: %r");
+ for(;;){
+ n = read(infd, buf, sizeof(buf));
+ if(n < 0)
+ sysfatal("read: %r");
+ if(n == 0)
+ break;
+ if(write(outfd, buf, n) != n)
+ sysfatal("write: %r");
+ }
+
+ exits(nil);
+}
--- a/sys/src/cmd/aux/mkfile
+++ b/sys/src/cmd/aux/mkfile
@@ -6,6 +6,7 @@
accupoint\
acidleak\
acpi\
+ aout2efi\
aout2uimage\
apm\
astarld\