[bootloader] Retry fixed allocation at 100000h w/ smaller size

Gigaboot allocates a fixed region at 10_0000h for the kernel text and
rodata/bss. By default it did a 6 MiB allocation, but certain platforms
(ex: GCE) were unable to allocate 6 contiguous megabytes.

Try a 6 MB allocation; if it fails, retry a 3 MB allocation at
the same fixed address. This allows 'fx gce' to work. This should
be safe for GCE builds -- 3 MiB runs from 10_0000h to 40_0000h.
A build of zircon.elf at head with gcc:

 13 .bss          00083510  ffffffff80231000  ffffffff80231000  00131f50  2**12
size
... bss 537872

 So BSS runs from 23_1000h - 2b_4510h, which fits within the 3 MB allocation.

A clang build of zx:
  [14] .bss              NOBITS           ffffffff80251000  001515d0

BSS runs from 25_1000h to 2d_6000h, which also fits fine within the
3 MB alloc.

This will no longer be necessary when the kernel is relocatable.

Tested:
GCE: fx gce create-fuchsia-image instance && fx gce create instance;
tested that zx booted to shell.
...
Description: efi\boot\bootx64.efi
FilePath: efi\boot\bootx64.efi
OptionNumber: 0.
handle 0
boot: cannot obtain 6291456 bytes for kernel @ 0x100000
KALLOC DONE
...

NUC(NUC7i3BNH): Tested that was able to load gigaboot from the EFI
shell, kernel fixed allocation succeeds when bootx64.efi is run from
EFI (but not from GRUB), tested that zircon.elf / image were loadable.
https://screenshot.googleplex.com/gwddVFusYNR (with BSS size)

Acer Switch SA5-271: Tested that the updated loader can run from EFI
(no EFI shell available), can load zircon.elf / zircon.zbi from a GPT
formatted USB key.

Change-Id: Ie57e428a17a99951aaec9658830ae5feeca4ba54
diff --git a/bootloader/src/osboot.c b/bootloader/src/osboot.c
index df762d4..946e308 100644
--- a/bootloader/src/osboot.c
+++ b/bootloader/src/osboot.c
@@ -389,9 +389,24 @@
 
     if (gBS->AllocatePages(AllocateAddress, EfiLoaderData,
                           BYTES_TO_PAGES(kernel_zone_size), &kernel_zone_base)) {
-        printf("boot: cannot obtain memory for kernel @ %p\n", (void*) kernel_zone_base);
+        printf("boot: cannot obtain %zu bytes for kernel @ %p\n", kernel_zone_size,
+               (void*) kernel_zone_base);
         kernel_zone_size = 0;
     }
+    // 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) {
+        kernel_zone_size = 3 * 1024 * 1024;
+        efi_status status = gBS->AllocatePages(AllocateAddress, EfiLoaderData,
+                                               BYTES_TO_PAGES(kernel_zone_size),
+                                               &kernel_zone_base);
+        if (status) {
+            printf("boot: cannot obtain %zu bytes for kernel @ %p\n",
+                   kernel_zone_size,
+                   (void*) kernel_zone_base);
+            kernel_zone_size = 0;
+        }
+    }
     printf("KALLOC DONE\n");
 
     // Default boot defaults to network