WIP get uefi working on ARM

Change-Id: I3429714c6ee87d2c782e75b224190969dd1903bb
diff --git a/bootloader/build.mk b/bootloader/build.mk
index ac7a7ce..fe44e08 100644
--- a/bootloader/build.mk
+++ b/bootloader/build.mk
@@ -73,6 +73,7 @@
 	@$(MKDIR)
 	$(call BUILDECHO,linking $@)
 	$(NOECHO)$(EFI_LD) /out:$@ $(EFI_LDFLAGS) $^
+	$(NOECHO)$(EFI_OBJDUMP) -d $@ > $@.lst
 
 else
 
diff --git a/bootloader/src/netifc.c b/bootloader/src/netifc.c
index abfe8ba..a03613f 100644
--- a/bootloader/src/netifc.c
+++ b/bootloader/src/netifc.c
@@ -286,7 +286,7 @@
 
     ret = snp->ReceiveFilters(snp,
                             EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
-                                EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST,
+                            0, //     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST,
                             0, 0, mcast_filter_count, (void*)mcast_filters);
     if (ret) {
         printf("Failed to install multicast filters %s\n", xefi_strerror(ret));
diff --git a/bootloader/src/osboot.c b/bootloader/src/osboot.c
index 946e308..4435cb1 100644
--- a/bootloader/src/osboot.c
+++ b/bootloader/src/osboot.c
@@ -340,6 +340,9 @@
     xefi_init(img, sys);
     gConOut->ClearScreen(gConOut);
 
+    printf("welcome to gigaboot!\n");
+    printf("gSys %p gImg %p gBS %p gConOut %p\n", gSys, gImg, gBS, gConOut);
+
     uint64_t mmio;
     if (xefi_find_pci_mmio(gBS, 0x0C, 0x03, 0x30, &mmio) == EFI_SUCCESS) {
         char tmp[32];
@@ -377,6 +380,7 @@
                gop->Mode->FrameBufferBase);
     }
 
+#if __x86_64__
     // Set aside space for the kernel down at the 1MB mark up front
     // to avoid other allocations getting in the way.
     // The kernel itself is about 1MB, but we leave generous space
@@ -386,13 +390,22 @@
     // becomes relocatable this won't be an problem. See ZX-2368.
     kernel_zone_base = 0x100000;
     kernel_zone_size = 6 * 1024 * 1024;
+    efi_allocate_type alloc_type = AllocateAddress;
+#else
+    // arm can allocate anywhere in physical memory
+    kernel_zone_base = 0;
+    kernel_zone_size = 16 * 1024 * 1024;
+    efi_allocate_type alloc_type = AllocateAnyPages;
+#endif
 
-    if (gBS->AllocatePages(AllocateAddress, EfiLoaderData,
+    if (gBS->AllocatePages(alloc_type, EfiLoaderData,
                           BYTES_TO_PAGES(kernel_zone_size), &kernel_zone_base)) {
         printf("boot: cannot obtain %zu bytes for kernel @ %p\n", kernel_zone_size,
                (void*) kernel_zone_base);
         kernel_zone_size = 0;
     }
+
+#if __x86_64__
     // HACK: Try again with a smaller size - certain platforms (ex: GCE) are unable
     // to support a large fixed allocation at 0x100000.
     if (kernel_zone_size == 0) {
@@ -407,7 +420,14 @@
             kernel_zone_size = 0;
         }
     }
-    printf("KALLOC DONE\n");
+#endif
+
+#if __aarch64__
+    // align the buffer on at least a 64k boundary
+    kernel_zone_base = ROUNDUP(kernel_zone_base, 1*1024*1024);
+#endif
+
+    printf("Kernel space reserved at %#" PRIx64 ", length %#zx\n", kernel_zone_base, kernel_zone_size);
 
     // Default boot defaults to network
     const char* defboot = cmdline_get("bootloader.default", "network");
diff --git a/bootloader/src/osboot.h b/bootloader/src/osboot.h
index cf49784..d009542 100644
--- a/bootloader/src/osboot.h
+++ b/bootloader/src/osboot.h
@@ -13,6 +13,7 @@
 #define PAGE_MASK (PAGE_SIZE - 1)
 
 #define BYTES_TO_PAGES(n) (((n) + PAGE_MASK) / PAGE_SIZE)
+#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
 
 // Ensure there are some pages preceding the
 // Ramdisk so that the kernel start code can
diff --git a/bootloader/src/zircon.c b/bootloader/src/zircon.c
index 4ac51c6..0ca6aee 100644
--- a/bootloader/src/zircon.c
+++ b/bootloader/src/zircon.c
@@ -38,8 +38,8 @@
 
 static unsigned char scratch[32768];
 
-static void start_zircon(uint64_t entry, void* bootdata) {
 #if __x86_64__
+static void start_zircon(uint64_t entry, void* bootdata) {
     // ebx = 0, ebp = 0, edi = 0, esi = bootdata
     __asm__ __volatile__(
         "movl $0, %%ebp \n"
@@ -47,12 +47,23 @@
         "jmp *%[entry] \n" ::[entry] "a"(entry),
         [bootdata] "S"(bootdata),
         "b"(0), "D"(0));
-#else
-#warning "add code for other arches here"
-#endif
     for (;;)
         ;
 }
+#elif __aarch64__
+static void start_zircon(uint64_t entry, void* bootdata) {
+    __asm__ __volatile__(
+        "mov x16, %0\n"
+        "mov x0, %1\n"
+        "br  x16\n"
+        :
+        : "r" (entry), "r"(bootdata)
+        : "memory"
+    );
+    for (;;)
+        ;
+}
+#endif
 
 static int add_bootdata(void** ptr, size_t* avail,
                         zbi_header_t* bd, void* data) {
@@ -103,7 +114,11 @@
     }
     zircon_kernel_t* kernel = image;
     if ((sz < sizeof(zircon_kernel_t)) ||
+#if __x86_64__
         (kernel->hdr_kernel.type != ZBI_TYPE_KERNEL_X64) ||
+#else
+        (kernel->hdr_kernel.type != ZBI_TYPE_KERNEL_ARM64) ||
+#endif
         ((kernel->hdr_kernel.flags & ZBI_FLAG_VERSION) == 0)) {
         printf("boot: invalid zircon kernel header\n");
         return -1;
@@ -292,6 +307,14 @@
         }
     }
 
+#if __aarch64__
+    // in current ZBI layouts, the arm64 entry point is the offset into the image, not
+    // absolute address. Adjust for this here.
+    entry += kernel_zone_base;
+#endif
+
+    printf("copying kernel image from %p to %p size %zu, entry at %p\n",
+            image, (void *)kernel_zone_base, isz, (void *)entry);
     memcpy((void*)kernel_zone_base, image, isz);
 
     // Obtain the system memory map
@@ -308,6 +331,8 @@
             goto fail;
         }
 
+        printf("got memory map, attempt %d\n", attempts);
+
         r = sys->BootServices->ExitBootServices(img, mkey);
         if (r == EFI_SUCCESS) {
             break;
@@ -327,6 +352,8 @@
     }
     memcpy(scratch, &dsize, sizeof(uint64_t));
 
+    // jump to the kernel
+
     // install memory map
     hdr.type = ZBI_TYPE_EFI_MEMORY_MAP;
     hdr.length = msize + sizeof(uint64_t);
@@ -351,7 +378,6 @@
     hdr.flags = ZBI_FLAG_VERSION;
     memcpy(bptr, &hdr, sizeof(hdr));
 
-    // jump to the kernel
     start_zircon(entry, ramdisk - FRONT_BYTES);
 
 fail:
diff --git a/make/engine.mk b/make/engine.mk
index 444eb5b..cdb742f 100644
--- a/make/engine.mk
+++ b/make/engine.mk
@@ -806,12 +806,14 @@
 EFI_CC := $(CLANG_TOOLCHAIN_PREFIX)clang
 EFI_CXX := $(CLANG_TOOLCHAIN_PREFIX)clang++
 EFI_LD := $(CLANG_TOOLCHAIN_PREFIX)lld-link
+EFI_OBJDUMP := $(CLANG_TOOLCHAIN_PREFIX)llvm-objdump
 EFI_COMPILEFLAGS := --target=$(EFI_ARCH)-windows-msvc
 else
 EFI_AR := $(TOOLCHAIN_PREFIX)ar
 EFI_CC := $(TOOLCHAIN_PREFIX)gcc
 EFI_CXX := $(TOOLCHAIN_PREFIX)g++
 EFI_LD := $(TOOLCHAIN_PREFIX)ld
+EFI_OBJDUMP := $(TOOLCHAIN_PREFIX)objdump
 EFI_COMPILEFLAGS := -fPIE
 endif
 
diff --git a/scripts/build-zircon b/scripts/build-zircon
index a2397ca..dcb38ad 100755
--- a/scripts/build-zircon
+++ b/scripts/build-zircon
@@ -52,4 +52,4 @@
     HELP
 fi
 
-exec ${DIR}/make-parallel ${ARCH} ${ARGS} "$@"
+exec ${DIR}/make-parallel PROJECT=${ARCH} ${ARGS} "$@"
diff --git a/uefi b/uefi
new file mode 100755
index 0000000..a826007
--- /dev/null
+++ b/uefi
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+
+BUILDDIR=build-arm64
+KERNEL=$BUILDDIR/qemu-boot-shim.bin
+INITRD=$BUILDDIR/zircon.zbi
+GIGABOOT=build-arm64-clang/bootloader/bootaa64.efi
+UEFI=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd
+
+./scripts/build-zircon -a arm64
+./scripts/build-zircon -a arm64 -C -- gigaboot
+
+exec ./prebuilt/downloads/qemu/bin/qemu-system-aarch64 \
+    -m 2048 -smp 4 -machine virtualization=true -cpu cortex-a53 -machine virt,gic_version=3 \
+    -nographic \
+    -drive file=blk.bin,format=raw,if=none,id=mydisk -device virtio-blk-pci,drive=mydisk \
+    -netdev type=tap,ifname=qemu,script=no,downscript=no,id=net0 -device virtio-net-pci,netdev=net0,mac=52:54:00:63:5e:7a \
+    -bios $UEFI \
+    -kernel $GIGABOOT \
+    -append 'TERM=xterm-256color kernel.entropy-mixin=dcf7d1a283377ddddaabae2f7021b4b22850ab03b44dc1a9f1861a9ee87dcd0c kernel.halt-on-panic=true '
+
+    #-initrd $INITRD \
+ #-serial stdio -vga none -device virtio-gpu-pci \
+ #-netdev type=user,hostname=qemu,id=net0 -device virtio-net-pci,netdev=net0 \