[zircon] [gn] Build Gigaboot

We support only the Clang build using the direct Windows target support.
The shenanigans to get it built with GCC are quite ugly and fragile.

Bug: BLD-325
Test: gn gen && ninja
Change-Id: I2d4acc6018d349fd1da534d3f7e0913e735079f7
diff --git a/zircon/BUILD.gn b/zircon/BUILD.gn
index 10dde62..749c503 100644
--- a/zircon/BUILD.gn
+++ b/zircon/BUILD.gn
@@ -101,5 +101,8 @@
       "$zx/system/utest",
       "$zx/third_party/uapp",
     ]
+    if (cpu == "x64") {
+      deps += [ "$zx/bootloader" ]
+    }
   }
 }
diff --git a/zircon/bootloader/BUILD.gn b/zircon/bootloader/BUILD.gn
new file mode 100644
index 0000000..4fcab9b
--- /dev/null
+++ b/zircon/bootloader/BUILD.gn
@@ -0,0 +1,80 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("$zx/public/gn/toolchain/environment.gni")
+import("$zx/public/gn/toolchain/environment_redirect.gni")
+
+# Gigaboot gets its own toolchains to build EFI code.
+if (current_toolchain == default_toolchain) {
+  environment("efi") {
+    cpu = "x64"
+    os = "win"
+    globals = {
+      is_kernel = true
+    }
+    configs += standard_fuchsia_configs + [ ":efi_config" ]
+
+    # TODO: harmless, but just to match build.mk
+    configs -= [ "$zx/public/gn/config:default_frame_pointers" ]
+
+    # TODO: strip = true
+
+    # There isn't a GCC toolchain that supports the Windows target directly
+    # the way we use it.
+    exclude_variant_tags = [ "gcc" ]
+  }
+} else if (toolchain.environment == "efi") {
+  # This is the top config for all code in the efi_toolchain.
+  config("efi_config") {
+    configs = [
+      "$zx/kernel:standalone",
+      "$zx/public/gn/config:no_sanitizers",
+
+      # TODO: "$zx/kernel:warnings",
+    ]
+    include_dirs = [ "include" ]
+    cflags = [
+      "-std=c99",
+      "-fshort-wchar",
+    ]
+    if (current_cpu == "x64") {
+      cflags += [ "-mno-red-zone" ]
+    }
+  }
+
+  executable("bootloader") {
+    output_dir = root_out_dir
+    output_name = "boot${current_cpu}"
+    output_extension = "efi"
+    deps = [
+      "lib",
+      "src",
+    ]
+    ldflags = [
+      "-nostdlib",
+      "-Wl,/subsystem:efi_application",
+      "-Wl,/entry:efi_main",
+    ]
+
+    # TODO(mcgrathr): Temporary kludge for legacy Fuchsia GN build integration.
+    metadata = {
+      images = [
+        {
+          name = "bootloader"
+          type = "efi"
+          path = rebase_path("$root_out_dir/$output_name.$output_extension",
+                             root_build_dir)
+        },
+      ]
+    }
+  }
+} else {
+  # In any other toolchain, just redirect to the proper toolchain.
+  environment_redirect("bootloader") {
+    environment_label = ":efi"
+    deps = [
+      ":bootloader",
+    ]
+  }
+}
diff --git a/zircon/bootloader/include/inttypes.h b/zircon/bootloader/include/inttypes.h
index 36ae92d..081e0b7 100644
--- a/zircon/bootloader/include/inttypes.h
+++ b/zircon/bootloader/include/inttypes.h
@@ -20,6 +20,8 @@
 
 #ifdef __clang__
 #define PRIx64 "llx"
+#define PRIu64 "llu"
 #else
 #define PRIx64 "lx"
+#define PRIu64 "lu"
 #endif
diff --git a/zircon/bootloader/lib/BUILD.gn b/zircon/bootloader/lib/BUILD.gn
new file mode 100644
index 0000000..35a6692
--- /dev/null
+++ b/zircon/bootloader/lib/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(toolchain.environment == "efi")
+
+source_set("lib") {
+  sources = [
+    "console-printf.c",
+    "ctype.c",
+    "efi/guids.c",
+    "inet.c",
+    "loadfile.c",
+    "printf.c",
+    "stdlib.c",
+    "string.c",
+    "strings.c",
+    "xefi.c",
+  ]
+}
diff --git a/zircon/bootloader/src/BUILD.gn b/zircon/bootloader/src/BUILD.gn
new file mode 100644
index 0000000..d44af0a
--- /dev/null
+++ b/zircon/bootloader/src/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(toolchain.environment == "efi")
+
+source_set("src") {
+  sources = [
+    "cmdline.c",
+    "device_id.c",
+    "diskio.c",
+    "framebuffer.c",
+    "inet6.c",
+    "misc.c",
+    "netboot.c",
+    "netifc.c",
+    "osboot.c",
+    "pci.c",
+    "zircon.c",
+  ]
+  include_dirs = [ "." ]
+  deps = [
+    "$zx/system/ulib/tftp",
+  ]
+}