x86: Generate EFI grub images
authorDUPONCHEEL Sébastien <sebastien.duponcheel@corp.ovh.com>
Tue, 11 Apr 2017 10:46:44 +0000 (12:46 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 14 Aug 2019 06:09:27 +0000 (08:09 +0200)
Signed-off-by: DUPONCHEEL Sébastien <sebastien.duponcheel@corp.ovh.com>
[fix grub build variant clashes]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
config/Config-images.in
package/base-files/files/lib/upgrade/common.sh
package/boot/grub2/Makefile [deleted file]
package/boot/grub2/common.mk [new file with mode: 0644]
package/boot/grub2/grub2-efi/Makefile [new file with mode: 0644]
package/boot/grub2/grub2/Makefile [new file with mode: 0644]
target/linux/x86/image/Makefile
target/linux/x86/image/gen_image_efi.sh [new file with mode: 0755]

index a3d99288422c022a4faa798416e40bccab44e88d..adbde054498b730329ceabf4132ef528bc4a8b3d 100644 (file)
@@ -195,19 +195,27 @@ menu "Target Images"
                select PACKAGE_grub2
                default y
 
                select PACKAGE_grub2
                default y
 
+       config EFI_IMAGES
+               bool "Build EFI GRUB images (Linux x86 or x86_64 host only)"
+               depends on TARGET_x86
+               depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_ISO || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS
+               select PACKAGE_grub2
+               select PACKAGE_grub2-efi
+               default y
+
        config GRUB_CONSOLE
                bool "Use Console Terminal (in addition to Serial)"
        config GRUB_CONSOLE
                bool "Use Console Terminal (in addition to Serial)"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                default y
 
        config GRUB_SERIAL
                string "Serial port device"
                default y
 
        config GRUB_SERIAL
                string "Serial port device"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                default "ttyS0"
 
        config GRUB_BAUDRATE
                int "Serial port baud rate"
                default "ttyS0"
 
        config GRUB_BAUDRATE
                int "Serial port baud rate"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                default 38400 if TARGET_x86_generic
                default 115200
 
                default 38400 if TARGET_x86_generic
                default 115200
 
@@ -218,13 +226,13 @@ menu "Target Images"
 
        config GRUB_BOOTOPTS
                string "Extra kernel boot options"
 
        config GRUB_BOOTOPTS
                string "Extra kernel boot options"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                help
                  If you don't know, just leave it blank.
 
        config GRUB_TIMEOUT
                string "Seconds to wait before booting the default entry"
                help
                  If you don't know, just leave it blank.
 
        config GRUB_TIMEOUT
                string "Seconds to wait before booting the default entry"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                default "5"
                help
                  If you don't know, 5 seconds is a reasonable default.
                default "5"
                help
                  If you don't know, 5 seconds is a reasonable default.
@@ -240,13 +248,13 @@ menu "Target Images"
        config VDI_IMAGES
                bool "Build VirtualBox image files (VDI)"
                depends on TARGET_x86
        config VDI_IMAGES
                bool "Build VirtualBox image files (VDI)"
                depends on TARGET_x86
-               select GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                select PACKAGE_kmod-e1000
 
        config VMDK_IMAGES
                bool "Build VMware image files (VMDK)"
                depends on TARGET_x86
                select PACKAGE_kmod-e1000
 
        config VMDK_IMAGES
                bool "Build VMware image files (VMDK)"
                depends on TARGET_x86
-               select GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                select PACKAGE_kmod-e1000
 
        config TARGET_IMAGES_GZIP
                select PACKAGE_kmod-e1000
 
        config TARGET_IMAGES_GZIP
@@ -260,21 +268,21 @@ menu "Target Images"
 
        config TARGET_KERNEL_PARTSIZE
                int "Kernel partition size (in MB)"
 
        config TARGET_KERNEL_PARTSIZE
                int "Kernel partition size (in MB)"
-               depends on GRUB_IMAGES || USES_BOOT_PART
+               depends on GRUB_IMAGES || EFI_IMAGES || USES_BOOT_PART
                default 8 if TARGET_apm821xx_sata
                default 64 if TARGET_brcm2708
                default 16
 
        config TARGET_ROOTFS_PARTSIZE
                int "Root filesystem partition size (in MB)"
                default 8 if TARGET_apm821xx_sata
                default 64 if TARGET_brcm2708
                default 16
 
        config TARGET_ROOTFS_PARTSIZE
                int "Root filesystem partition size (in MB)"
-               depends on GRUB_IMAGES || USES_ROOTFS_PART || TARGET_ROOTFS_EXT4FS || TARGET_omap || TARGET_rb532 || TARGET_sunxi || TARGET_uml
+               depends on GRUB_IMAGES || EFI_IMAGES || USES_ROOTFS_PART || TARGET_ROOTFS_EXT4FS || TARGET_omap || TARGET_rb532 || TARGET_sunxi || TARGET_uml
                default 128
                help
                  Select the root filesystem partition size.
 
        config TARGET_ROOTFS_PARTNAME
                string "Root partition on target device"
                default 128
                help
                  Select the root filesystem partition size.
 
        config TARGET_ROOTFS_PARTNAME
                string "Root partition on target device"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                help
                  Override the root partition on the final device. If left empty,
                  it will be mounted by PARTUUID which makes the kernel find the
                help
                  Override the root partition on the final device. If left empty,
                  it will be mounted by PARTUUID which makes the kernel find the
index 2afa0addb46ceda225d365a82df5fcf11a6f1f35..8f0233413703acbc8b90f9d635d2358d514a9599 100644 (file)
@@ -123,6 +123,24 @@ export_bootdevice() {
                esac
 
                case "$rootpart" in
                esac
 
                case "$rootpart" in
+                       PARTUUID=[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]0002)
+                               uuid="${rootpart#PARTUUID=}"
+                               uuid="${uuid%0002}0002"
+                               for blockdev in $(find /dev -type b); do
+                                       set -- $(dd if=$blockdev bs=1 skip=$((2*512+256+128+16)) count=16 2>/dev/null | hexdump -v -e '4/1 "%02x"' | awk '{ \
+                                                       for(i=1;i<9;i=i+2) first=substr($0,i,1) substr($0,i+1,1) first; \
+                                                       for(i=9;i<13;i=i+2) second=substr($0,i,1) substr($0,i+1,1) second; \
+                                                       for(i=13;i<16;i=i+2) third=substr($0,i,1) substr($0,i+1,1) third; \
+                                                       fourth = substr($0,17,4); \
+                                                       five = substr($0,21,12); \
+                                               } END { print toupper(first"-"second"-"third"-"fourth"-"five) }')
+                                       if [ "$1" = "$uuid" ]; then
+                                               uevent="/sys/class/block/${blockdev##*/}/uevent"
+                                               export SAVE_PARTITIONS=0
+                                               break
+                                       fi
+                               done
+                       ;;
                        PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9])
                                uuid="${rootpart#PARTUUID=}"
                                uuid="${uuid%-[a-f0-9][a-f0-9]}"
                        PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9])
                                uuid="${rootpart#PARTUUID=}"
                                uuid="${uuid%-[a-f0-9][a-f0-9]}"
diff --git a/package/boot/grub2/Makefile b/package/boot/grub2/Makefile
deleted file mode 100644 (file)
index d6af651..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# Copyright (C) 2006-2015 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-include $(INCLUDE_DIR)/kernel.mk
-
-PKG_NAME:=grub
-PKG_CPE_ID:=cpe:/a:gnu:grub2
-PKG_VERSION:=2.02
-PKG_RELEASE:=3
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
-PKG_SOURCE_URL:=@GNU/grub
-PKG_HASH:=810b3798d316394f94096ec2797909dbf23c858e48f7b3830826b8daa06b7b0f
-
-PKG_FIXUP:=autoreconf
-HOST_BUILD_PARALLEL:=1
-PKG_BUILD_DEPENDS:=grub2/host
-
-PKG_SSP:=0
-
-PKG_FLAGS:=nonshared
-
-include $(INCLUDE_DIR)/host-build.mk
-include $(INCLUDE_DIR)/package.mk
-
-define Package/grub2
-  CATEGORY:=Boot Loaders
-  SECTION:=boot
-  TITLE:=GRand Unified Bootloader
-  URL:=http://www.gnu.org/software/grub/
-  DEPENDS:=@TARGET_x86
-endef
-
-define Package/grub2-editenv
-  CATEGORY:=Utilities
-  SECTION:=utils
-  SUBMENU:=Boot Loaders
-  TITLE:=Grub2 Environment editor
-  URL:=http://www.gnu.org/software/grub/
-  DEPENDS:=@TARGET_x86
-endef
-
-define Package/grub2-editenv/description
-       Edit grub2 environment files.
-endef
-
-HOST_BUILD_PREFIX := $(STAGING_DIR_HOST)
-
-CONFIGURE_VARS += \
-       grub_build_mkfont_excuse="don't want fonts"
-
-CONFIGURE_ARGS += \
-       --target=$(REAL_GNU_TARGET_NAME) \
-       --disable-werror \
-       --disable-nls \
-       --disable-device-mapper \
-       --disable-libzfs \
-       --disable-grub-mkfont \
-       --with-platform=none
-
-HOST_CONFIGURE_VARS += \
-       grub_build_mkfont_excuse="don't want fonts"
-
-HOST_CONFIGURE_ARGS += \
-       --disable-grub-mkfont \
-       --target=$(REAL_GNU_TARGET_NAME) \
-       --sbindir="$(STAGING_DIR_HOST)/bin" \
-       --disable-werror \
-       --disable-libzfs \
-       --disable-nls
-
-HOST_MAKE_FLAGS += \
-       TARGET_RANLIB=$(TARGET_RANLIB) \
-       LIBLZMA=$(STAGING_DIR_HOST)/lib/liblzma.a
-
-define Host/Configure
-       $(SED) 's,(RANLIB),(TARGET_RANLIB),' $(HOST_BUILD_DIR)/grub-core/Makefile.in
-       $(Host/Configure/Default)
-endef
-
-define Package/grub2-editenv/install
-       $(INSTALL_DIR) $(1)/usr/sbin
-       $(INSTALL_BIN) $(PKG_BUILD_DIR)/grub-editenv $(1)/usr/sbin/
-endef
-
-$(eval $(call HostBuild))
-$(eval $(call BuildPackage,grub2))
-$(eval $(call BuildPackage,grub2-editenv))
diff --git a/package/boot/grub2/common.mk b/package/boot/grub2/common.mk
new file mode 100644 (file)
index 0000000..7e8a11c
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_CPE_ID:=cpe:/a:gnu:grub2
+PKG_VERSION:=2.02
+PKG_RELEASE:=3
+
+PKG_SOURCE:=grub-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/grub
+PKG_HASH:=810b3798d316394f94096ec2797909dbf23c858e48f7b3830826b8daa06b7b0f
+
+PKG_FIXUP:=autoreconf
+HOST_BUILD_PARALLEL:=1
+
+PKG_SSP:=0
+
+PKG_FLAGS:=nonshared
+
+PATCH_DIR := ../patches
+HOST_PATCH_DIR := ../patches
+HOST_BUILD_DIR := $(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/grub2/Default
+  CATEGORY:=Boot Loaders
+  SECTION:=boot
+  TITLE:=GRand Unified Bootloader
+  URL:=http://www.gnu.org/software/grub/
+  DEPENDS:=@TARGET_x86
+endef
+
+HOST_BUILD_PREFIX := $(STAGING_DIR_HOST)
+
+CONFIGURE_VARS += \
+       grub_build_mkfont_excuse="don't want fonts"
+
+CONFIGURE_ARGS += \
+       --target=$(REAL_GNU_TARGET_NAME) \
+       --disable-werror \
+       --disable-nls \
+       --disable-device-mapper \
+       --disable-libzfs \
+       --disable-grub-mkfont \
+       --with-platform=none
+
+HOST_CONFIGURE_VARS += \
+       grub_build_mkfont_excuse="don't want fonts"
+
+HOST_CONFIGURE_ARGS += \
+       --disable-grub-mkfont \
+       --target=$(REAL_GNU_TARGET_NAME) \
+       --sbindir="$(STAGING_DIR_HOST)/bin" \
+       --disable-werror \
+       --disable-libzfs \
+       --disable-nls
+
+HOST_MAKE_FLAGS += \
+       TARGET_RANLIB=$(TARGET_RANLIB) \
+       LIBLZMA=$(STAGING_DIR_HOST)/lib/liblzma.a
+
+define Host/Configure
+       $(SED) 's,(RANLIB),(TARGET_RANLIB),' $(HOST_BUILD_DIR)/grub-core/Makefile.in
+       $(Host/Configure/Default)
+endef
+
diff --git a/package/boot/grub2/grub2-efi/Makefile b/package/boot/grub2/grub2-efi/Makefile
new file mode 100644 (file)
index 0000000..035bfc3
--- /dev/null
@@ -0,0 +1,23 @@
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=grub-efi
+
+include ../common.mk
+
+TAR_OPTIONS:= --transform 's/grub-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}/' $(TAR_OPTIONS)
+
+PKG_BUILD_DEPENDS:=grub2-efi/host
+
+CONFIGURE_ARGS += --with-platform=efi
+HOST_CONFIGURE_ARGS += --with-platform=efi --program-suffix=-efi
+HOST_BUILD_DIR := $(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+define Package/grub2-efi
+$(call Package/grub2/Default)
+HIDDEN:=1
+TITLE += (with EFI support)
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,grub2-efi))
diff --git a/package/boot/grub2/grub2/Makefile b/package/boot/grub2/grub2/Makefile
new file mode 100644 (file)
index 0000000..2890761
--- /dev/null
@@ -0,0 +1,33 @@
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=grub
+
+include ../common.mk
+
+PKG_BUILD_DEPENDS:=grub2/host
+
+define Package/grub2
+$(call Package/grub2/Default)
+endef
+
+define Package/grub2-editenv
+  CATEGORY:=Utilities
+  SECTION:=utils
+  TITLE:=Grub2 Environment editor
+  URL:=http://www.gnu.org/software/grub/
+  DEPENDS:=@TARGET_x86
+endef
+
+define Package/grub2-editenv/description
+       Edit grub2 environment files.
+endef
+
+define Package/grub2-editenv/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/grub-editenv $(1)/usr/sbin/
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,grub2))
+$(eval $(call BuildPackage,grub2-editenv))
index 24825f2ba2c25eb471455563154b7c75d4b09559..495be3670fff15a6b111bcfd22cbac73e166eb83 100644 (file)
@@ -10,6 +10,9 @@ include $(INCLUDE_DIR)/image.mk
 export PATH=$(TARGET_PATH):/sbin
 
 GRUB2_MODULES = biosdisk boot chain configfile ext2 linux ls part_msdos reboot serial test vga
 export PATH=$(TARGET_PATH):/sbin
 
 GRUB2_MODULES = biosdisk boot chain configfile ext2 linux ls part_msdos reboot serial test vga
+GRUB2_MODULES_LEGACY = $(GRUB2_MODULES)
+GRUB2_MODULES_LEGACY += part_gpt search fat exfat
+GRUB2_MODULES_EFI = boot chain configfile ext2 linux ls part_msdos reboot serial part_gpt part_msdos search fat exfat ext2 efi_gop efi_uga gfxterm
 GRUB2_MODULES_ISO = biosdisk boot chain configfile iso9660 linux ls part_msdos reboot serial test vga
 GRUB_TERMINALS =
 GRUB_SERIAL_CONFIG =
 GRUB2_MODULES_ISO = biosdisk boot chain configfile iso9660 linux ls part_msdos reboot serial test vga
 GRUB_TERMINALS =
 GRUB_SERIAL_CONFIG =
@@ -41,13 +44,14 @@ ifneq ($(GRUB_TERMINALS),)
 endif
 
 SIGNATURE:=$(shell perl -e 'printf("%08x", rand(0xFFFFFFFF))')
 endif
 
 SIGNATURE:=$(shell perl -e 'printf("%08x", rand(0xFFFFFFFF))')
+EFI_SIGNATURE:=$(strip $(shell uuidgen | sed "s/[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]$$/0002/" | tr '[a-z]' '[A-Z]'))
 ROOTPART:=$(call qstrip,$(CONFIG_TARGET_ROOTFS_PARTNAME))
 ROOTPART:=$(if $(ROOTPART),$(ROOTPART),PARTUUID=$(SIGNATURE)-02)
 
 GRUB_TIMEOUT:=$(call qstrip,$(CONFIG_GRUB_TIMEOUT))
 GRUB_TITLE:=$(call qstrip,$(CONFIG_GRUB_TITLE))
 
 ROOTPART:=$(call qstrip,$(CONFIG_TARGET_ROOTFS_PARTNAME))
 ROOTPART:=$(if $(ROOTPART),$(ROOTPART),PARTUUID=$(SIGNATURE)-02)
 
 GRUB_TIMEOUT:=$(call qstrip,$(CONFIG_GRUB_TIMEOUT))
 GRUB_TITLE:=$(call qstrip,$(CONFIG_GRUB_TITLE))
 
-ifneq ($(CONFIG_GRUB_IMAGES),)
+ifneq ($(CONFIG_GRUB_IMAGES)$(CONFIG_EFI_IMAGES),)
 
   BOOTOPTS:=$(call qstrip,$(CONFIG_GRUB_BOOTOPTS))
 
 
   BOOTOPTS:=$(call qstrip,$(CONFIG_GRUB_BOOTOPTS))
 
@@ -59,6 +63,90 @@ ifneq ($(CONFIG_GRUB_IMAGES),)
     root=$(ROOTPART) rootfstype=squashfs rootwait
   endef
 
     root=$(ROOTPART) rootfstype=squashfs rootwait
   endef
 
+  ifneq ($(CONFIG_EFI_IMAGES),)
+
+  define Image/cmdline/efi
+    $(subst $(SIGNATURE)-02,$2,$(call Image/cmdline/$(1)))
+  endef
+
+  define Image/Build/efi
+       # left here because the image builder doesnt need these
+       rm -rf $(KDIR)/root.grub/ || true
+       $(INSTALL_DIR) $(KDIR)/root.grub/boot/grub $(KDIR)/grub2
+       $(CP) $(KDIR)/bzImage $(KDIR)/root.grub/boot/vmlinuz
+       echo '(hd0) $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img' > $(KDIR)/grub2/device.map
+       sed \
+               -e 's#@SERIAL_CONFIG@#$(strip $(GRUB_SERIAL_CONFIG))#g' \
+               -e 's#@TERMINAL_CONFIG@#$(strip $(GRUB_TERMINAL_CONFIG))#g' \
+               -e 's#@CMDLINE@#$(strip $(call Image/cmdline/efi,$(1),$(EFI_SIGNATURE)) $(BOOTOPTS) $(GRUB_CONSOLE_CMDLINE))#g' \
+               -e 's#@TIMEOUT@#$(GRUB_TIMEOUT)#g' \
+               -e 's#set root.*#search --file /boot/grub/$(SIGNATURE).cfg --set=root#g' \
+               ./grub.cfg > $(KDIR)/root.grub/boot/grub/grub.cfg
+       $(CP) $(KDIR)/root.grub/boot/grub/grub.cfg $(KDIR)/root.grub/boot/grub/$(SIGNATURE).cfg
+       grub-mkimage \
+               -d $(STAGING_DIR_HOST)/lib/grub/i386-pc \
+               -o $(KDIR)/grub2/core.img \
+               -O i386-pc \
+               -p '(hd0,gpt1)/boot/grub' \
+               -c $(KDIR)/root.grub/boot/grub/grub.cfg \
+               $(GRUB2_MODULES_LEGACY)
+       $(CP) $(STAGING_DIR_HOST)/lib/grub/i386-pc/*.img $(KDIR)/grub2/
+
+       # Build the efi grub version
+       rm -rf $(KDIR)/grub2.efi/ || true
+       $(INSTALL_DIR) $(KDIR)/grub2.efi/efi/boot/
+
+       # Generate the grub search root config (grub will search for the $(SIGNATURE).cfg file placed on the boot partition as grub does not support search of GPT UUID yet)
+       echo "search --file /boot/grub/$(SIGNATURE).cfg --set=root" > $(KDIR)/grub2.efi/efi/boot/grub.cfg
+       echo "configfile /boot/grub/grub.cfg" >> $(KDIR)/grub2.efi/efi/boot/grub.cfg
+
+       # Create the EFI grub binary
+       grub-mkimage-efi \
+               -d $(STAGING_DIR_HOST)/lib/grub/x86_64-efi \
+               -o $(KDIR)/grub2.efi/efi/boot/bootx64.efi \
+               -O x86_64-efi \
+               -p /efi/boot \
+               -c $(KDIR)/grub2.efi/efi/boot/grub.cfg \
+               $(GRUB2_MODULES_EFI)
+
+       # Generate the EFI VFAT bootfs
+       rm $(KDIR)/kernel.efi || true
+       mkfs.fat -C $(KDIR)/kernel.efi -S 512 1024
+       mcopy -s -i "$(KDIR)/kernel.efi" $(KDIR)/grub2.efi/* ::/
+
+       SIGNATURE="$(SIGNATURE)" PATH="$(TARGET_PATH)" ./gen_image_efi.sh \
+               $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \
+               $(CONFIG_TARGET_KERNEL_PARTSIZE) $(KDIR)/root.grub \
+               1 $(KDIR)/kernel.efi \
+               1 \
+               $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(KDIR)/root.$(1) \
+               256
+
+       # Setup legacy bios for hybrid MBR (optional)
+       grub-bios-setup \
+               --device-map="$(KDIR)/grub2/device.map" \
+               -d "$(KDIR)/grub2" \
+               -r "hd0,msdos1" \
+               "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+
+       # Convert the MBR partition to GPT and set EFI ROOTFS signature
+       dd if=/dev/zero of="$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" bs=512 count=33 conv=notrunc oflag=append
+       sgdisk -g "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+       sgdisk -t 2:EF00 "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+       sgdisk -t 3:EF02 "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+       sgdisk -u 4:$(EFI_SIGNATURE) "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+       sgdisk -h "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+
+       # Setup EFI grub
+       grub-bios-setup-efi \
+               --device-map="$(KDIR)/grub2/device.map" \
+               -d "$(KDIR)/grub2" \
+               -r "hd0,gpt1" \
+               "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img"
+  endef
+  endif
+
+  ifneq ($(CONFIG_GRUB_IMAGES),)
   define Image/Build/grub2
        # left here because the image builder doesnt need these
        $(INSTALL_DIR) $(KDIR)/root.grub/boot/grub $(KDIR)/grub2
   define Image/Build/grub2
        # left here because the image builder doesnt need these
        $(INSTALL_DIR) $(KDIR)/root.grub/boot/grub $(KDIR)/grub2
@@ -91,6 +179,8 @@ ifneq ($(CONFIG_GRUB_IMAGES),)
                -r "hd0,msdos1" \
                "$(BIN_DIR)/$(IMG_COMBINED)-$(1).img"
   endef
                -r "hd0,msdos1" \
                "$(BIN_DIR)/$(IMG_COMBINED)-$(1).img"
   endef
+  endif
+
 endif
 
 define Image/Build/iso
 endif
 
 define Image/Build/iso
@@ -126,6 +216,14 @@ ifneq ($(CONFIG_VDI_IMAGES),)
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).img \
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).vdi
   endef
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).img \
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).vdi
   endef
+  define Image/Build/vdi_efi
+       rm $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi || true
+       qemu-img convert -f raw -O vdi \
+               $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \
+               $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi
+       # XXX: VBoxManage insists on setting perms to 0600
+       chmod 0644 $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi
+  endef
 endif
 
 ifneq ($(CONFIG_VMDK_IMAGES),)
 endif
 
 ifneq ($(CONFIG_VMDK_IMAGES),)
@@ -135,11 +233,22 @@ ifneq ($(CONFIG_VMDK_IMAGES),)
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).img \
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).vmdk
   endef
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).img \
                $(BIN_DIR)/$(IMG_COMBINED)-$(1).vmdk
   endef
+  define Image/Build/vmdk_efi
+       rm $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vmdk || true
+       qemu-img convert -f raw -O vmdk \
+               $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \
+               $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vmdk
+  endef
 endif
 
 define Image/Build/gzip
 endif
 
 define Image/Build/gzip
-       gzip -f9n $(BIN_DIR)/$(IMG_COMBINED)-$(1).img
        gzip -f9n $(BIN_DIR)/$(IMG_ROOTFS)-$(1).img
        gzip -f9n $(BIN_DIR)/$(IMG_ROOTFS)-$(1).img
+ifneq ($(CONFIG_GRUB_IMAGES),)
+       gzip -f9n $(BIN_DIR)/$(IMG_COMBINED)-$(1).img
+endif
+ifneq ($(CONFIG_EFI_IMAGES),)
+       gzip -f9n $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img
+endif
 endef
 
 $(eval $(call Image/gzip-ext4-padded-squashfs))
 endef
 
 $(eval $(call Image/gzip-ext4-padded-squashfs))
@@ -160,8 +269,15 @@ define Image/Build
        $(call Image/Build/$(1))
   ifneq ($(1),iso)
        $(call Image/Build/grub2,$(1))
        $(call Image/Build/$(1))
   ifneq ($(1),iso)
        $(call Image/Build/grub2,$(1))
+       $(call Image/Build/efi,$(1))
+ifneq ($(CONFIG_GRUB_IMAGES),)
        $(call Image/Build/vdi,$(1))
        $(call Image/Build/vmdk,$(1))
        $(call Image/Build/vdi,$(1))
        $(call Image/Build/vmdk,$(1))
+endif
+ifneq ($(CONFIG_EFI_IMAGES),)
+       $(call Image/Build/vdi_efi,$(1))
+       $(call Image/Build/vmdk_efi,$(1))
+endif
        $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_ROOTFS)-$(1).img
   else
        $(CP) $(KDIR)/root.iso $(BIN_DIR)/$(IMG_PREFIX).iso
        $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_ROOTFS)-$(1).img
   else
        $(CP) $(KDIR)/root.iso $(BIN_DIR)/$(IMG_PREFIX).iso
diff --git a/target/linux/x86/image/gen_image_efi.sh b/target/linux/x86/image/gen_image_efi.sh
new file mode 100755 (executable)
index 0000000..3ecb25f
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+set -x
+[ $# == 8 -o $# == 9 ] || {
+    echo "SYNTAX: $0 <file> <kernel size> <kernel directory> <efi size> <efi image> <efigrubmodule size> <rootfs size> <rootfs image> [<align>]"
+    exit 1
+}
+
+OUTPUT="$1"
+KERNELSIZE="$2"
+KERNELDIR="$3"
+EFISIZE="$4"
+EFIIMAGE="$5"
+EFIGRUBSIZE="$6"
+ROOTFSSIZE="$7"
+ROOTFSIMAGE="$8"
+ALIGN="$9"
+
+rm -f "$OUTPUT"
+
+head=16
+sect=63
+cyl=$(( ($KERNELSIZE + $EFISIZE + $EFIGRUBSIZE + $ROOTFSSIZE) * 1024 * 1024 / ($head * $sect * 512) ))
+
+# create partition table
+set `ptgen -o "$OUTPUT" -h $head -s $sect -p ${KERNELSIZE}m -p ${EFISIZE}m -p ${EFIGRUBSIZE}m -p ${ROOTFSSIZE}m ${ALIGN:+-l $ALIGN} ${SIGNATURE:+-S 0x$SIGNATURE}`
+
+KERNELOFFSET="$(($1 / 512))"
+KERNELSIZE="$2"
+EFIOFFSET="$(($3 / 512))"
+EFISIZE="$(($4 / 512))"
+EFIGRUBOFFSET="$(($5 / 512))"
+EFIGRUBSIZE="$(($6 / 512))"
+ROOTFSOFFSET="$(($7 / 512))"
+ROOTFSSIZE="$(($8 / 512))"
+
+dd if=/dev/zero of="$OUTPUT" bs=512 seek="$ROOTFSOFFSET" conv=notrunc count="$ROOTFSSIZE"
+dd if="$ROOTFSIMAGE" of="$OUTPUT" bs=512 seek="$ROOTFSOFFSET" conv=notrunc
+dd if="$EFIIMAGE" of="$OUTPUT" bs=512 seek="$EFIOFFSET" conv=notrunc
+
+[ -n "$NOGRUB" ] && exit 0
+
+make_ext4fs -J -l "$KERNELSIZE" "$OUTPUT.kernel" "$KERNELDIR"
+dd if="$OUTPUT.kernel" of="$OUTPUT" bs=512 seek="$KERNELOFFSET" conv=notrunc
+rm -f "$OUTPUT.kernel"