distro: Add efi pxe boot code
authorAlexander Graf <agraf@suse.de>
Fri, 6 May 2016 19:01:07 +0000 (21:01 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 27 May 2016 19:39:45 +0000 (15:39 -0400)
Now that we can expose network functionality to EFI applications,
the logical next step is to load them via pxe to execute them as
well.

This patch adds the necessary bits to the distro script to automatically
load and execute EFI payloads. It identifies the dhcp client as a uEFI
capable PXE client, hoping the server returns a tftp path to a workable
EFI binary that we can then execute.

To enable boards that don't come with a working device tree preloaded,
this patch also adds support to load a device tree from the /dtb directory
on the remote tftp server.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Tom Rini <trini@konsulko.com>
include/config_distro_bootcmd.h
net/bootp.c

index 5a8d7f270867c8bad06145d6c5f393515060e11d..4db6faa7bb8038535f6ceda1409a545966df5f14 100644 (file)
 #endif
 
 #if defined(CONFIG_CMD_DHCP)
+#if defined(CONFIG_EFI_LOADER)
+#if defined(CONFIG_ARM64)
+#define BOOTENV_EFI_PXE_ARCH "0xb"
+#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00011:UNDI:003000"
+#elif defined(CONFIG_ARM)
+#define BOOTENV_EFI_PXE_ARCH "0xa"
+#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00010:UNDI:003000"
+#elif defined(CONFIG_X86)
+/* Always assume we're running 64bit */
+#define BOOTENV_EFI_PXE_ARCH "0x7"
+#define BOOTENV_EFI_PXE_VCI "PXEClient:Arch:00007:UNDI:003000"
+#else
+#error Please specify an EFI client identifier
+#endif
+
+/*
+ * Ask the dhcp server for an EFI binary. If we get one, check for a
+ * device tree in the same folder. Then boot everything. If the file was
+ * not an EFI binary, we just return from the bootefi command and continue.
+ */
+#define BOOTENV_EFI_RUN_DHCP \
+       "setenv efi_fdtfile ${fdtfile}; "                                 \
+       BOOTENV_EFI_SET_FDTFILE_FALLBACK                                  \
+       "setenv efi_old_vci ${bootp_vci};"                                \
+       "setenv efi_old_arch ${bootp_arch};"                              \
+       "setenv bootp_vci " BOOTENV_EFI_PXE_VCI ";"                       \
+       "setenv bootp_arch " BOOTENV_EFI_PXE_ARCH ";"                     \
+       "if dhcp ${kernel_addr_r}; then "                                 \
+               "tftpboot ${fdt_addr_r} dtb/${efi_fdtfile};"              \
+               "if fdt addr ${fdt_addr_r}; then "                        \
+                       "bootefi ${kernel_addr_r} ${fdt_addr_r}; "        \
+               "else "                                                   \
+                       "bootefi ${kernel_addr_r} ${fdtcontroladdr};"     \
+               "fi;"                                                     \
+       "fi;"                                                             \
+       "setenv bootp_vci ${efi_old_vci};"                                \
+       "setenv bootp_arch ${efi_old_arch};"                              \
+       "setenv efi_fdtfile;"                                             \
+       "setenv efi_old_arch;"                                            \
+       "setenv efi_old_vci;"
+#else
+#define BOOTENV_EFI_RUN_DHCP
+#endif
 #define BOOTENV_DEV_DHCP(devtypeu, devtypel, instance) \
        "bootcmd_dhcp=" \
                BOOTENV_RUN_NET_USB_START \
                BOOTENV_RUN_NET_PCI_ENUM \
                "if dhcp ${scriptaddr} ${boot_script_dhcp}; then " \
                        "source ${scriptaddr}; " \
-               "fi\0"
+               "fi;" \
+               BOOTENV_EFI_RUN_DHCP \
+               "\0"
 #define BOOTENV_DEV_NAME_DHCP(devtypeu, devtypel, instance) \
        "dhcp "
 #else
index d718e35b63ec392e1f9d2df0cf1489df0e000d01..85dc524df4fdd8d3e8549b6bab751ab5aa24d0ff 100644 (file)
@@ -413,12 +413,21 @@ static void bootp_timeout_handler(void)
 
 static u8 *add_vci(u8 *e)
 {
+       char *vci = NULL;
+       char *env_vci = getenv("bootp_vci");
+
 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING)
-       put_vci(e, CONFIG_SPL_NET_VCI_STRING);
+       vci = CONFIG_SPL_NET_VCI_STRING;
 #elif defined(CONFIG_BOOTP_VCI_STRING)
-       put_vci(e, CONFIG_BOOTP_VCI_STRING);
+       vci = CONFIG_BOOTP_VCI_STRING;
 #endif
 
+       if (env_vci)
+               vci = env_vci;
+
+       if (vci)
+               put_vci(e, vci);
+
        return e;
 }