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
 
+       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)"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                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"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                default 38400 if TARGET_x86_generic
                default 115200
 
@@ -218,13 +226,13 @@ menu "Target Images"
 
        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"
-               depends on GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                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
-               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 GRUB_IMAGES
+               depends on GRUB_IMAGES || EFI_IMAGES
                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)"
-               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)"
-               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"
-               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
index 2afa0addb46ceda225d365a82df5fcf11a6f1f35..8f0233413703acbc8b90f9d635d2358d514a9599 100644 (file)
@@ -123,6 +123,24 @@ export_bootdevice() {
                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]}"
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
+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 =
@@ -41,13 +44,14 @@ ifneq ($(GRUB_TERMINALS),)
 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))
 
-ifneq ($(CONFIG_GRUB_IMAGES),)
+ifneq ($(CONFIG_GRUB_IMAGES)$(CONFIG_EFI_IMAGES),)
 
   BOOTOPTS:=$(call qstrip,$(CONFIG_GRUB_BOOTOPTS))
 
@@ -59,6 +63,90 @@ ifneq ($(CONFIG_GRUB_IMAGES),)
     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
@@ -91,6 +179,8 @@ ifneq ($(CONFIG_GRUB_IMAGES),)
                -r "hd0,msdos1" \
                "$(BIN_DIR)/$(IMG_COMBINED)-$(1).img"
   endef
+  endif
+
 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
+  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),)
@@ -135,11 +233,22 @@ ifneq ($(CONFIG_VMDK_IMAGES),)
                $(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
-       gzip -f9n $(BIN_DIR)/$(IMG_COMBINED)-$(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))
@@ -160,8 +269,15 @@ define Image/Build
        $(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))
+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
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"