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 \