diff mbox series

[1/7] bootimg_pcbios: support grub hybrid boot

Message ID 20250902015825.2785789-1-vince@underview.tech
State New
Headers show
Series [1/7] bootimg_pcbios: support grub hybrid boot | expand

Commit Message

Vincent Davis Jr Sept. 2, 2025, 1:58 a.m. UTC
If caller wants to primarily leverage
grub as the primary boot loader current
oe-core doesn't support booting grub when
the boot firmware is legacy BIOS based and
the partition table format is GPT based.

Issue GPT header reside where core.img
should be located (at byte 512).

To navigate around issue core.img was
moved to a seperate partition.

If disk is a GPT disk caller must specify
the file system type as none and set the
partition type as BIOS boot. No filesystem
will be created on partition. This also
allows wic plugin to know where to dd
core.img.

Unfortunately No deep dive into grub-install
was perform to know the exact bytes changed
in hybrid boot case. To see the change in
bytes generated boot.img + core.img was compared
to boot.img + core.img after grub-install was
executed using the xxd command.

Signed-off-by: Vincent Davis Jr <vince@underview.tech>
---
 .../lib/wic/plugins/source/bootimg_pcbios.py  | 55 ++++++++++++++++++-
 1 file changed, 53 insertions(+), 2 deletions(-)

Comments

Mathieu Dubois-Briand Sept. 4, 2025, 5:56 a.m. UTC | #1
On Tue Sep 2, 2025 at 3:58 AM CEST, Vincent Davis Jr wrote:
> If caller wants to primarily leverage
> grub as the primary boot loader current
> oe-core doesn't support booting grub when
> the boot firmware is legacy BIOS based and
> the partition table format is GPT based.
>
> Issue GPT header reside where core.img
> should be located (at byte 512).
>
> To navigate around issue core.img was
> moved to a seperate partition.
>
> If disk is a GPT disk caller must specify
> the file system type as none and set the
> partition type as BIOS boot. No filesystem
> will be created on partition. This also
> allows wic plugin to know where to dd
> core.img.
>
> Unfortunately No deep dive into grub-install
> was perform to know the exact bytes changed
> in hybrid boot case. To see the change in
> bytes generated boot.img + core.img was compared
> to boot.img + core.img after grub-install was
> executed using the xxd command.
>
> Signed-off-by: Vincent Davis Jr <vince@underview.tech>
> ---

Hi Vincent,

It looks like this tends to fail some selftest. Autobuilder logs are not
really verbose here, but I can relaunch a build and extract more log
files if you now were you want to look.

runqemu - INFO - Running /srv/pokybuild/yocto-worker/oe-selftest-debian/build/build-st-2799227/tmp/work/x86_64-linux/qemu-helper-native/1.0/recipe-sysroot-native/usr/bin/qemu-system-x86_64 -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:02 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0 -drive if=none,id=hd,file=/home/pokybuild/tmp/core-image-minimal-qemux86-64.rootfs.wic.510160,format=raw -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd -usb -device usb-tablet -usb -device usb-kbd   -cpu Skylake-Client -machine q35,i8042=off -smp 4 -enable-kvm -m 256 -serial tcp:127.0.0.1:42697,nodelay=on -serial tcp:127.0.0.1:54201,nodelay=on  -pidfile /srv/pokybuild/yocto-worker/oe-selftest-debian/build/build-st-2799227/pidfile_2799227  -S -qmp unix:./.6pnxdkdq,server,wait -qmp unix:./.p0gm_1m0,server,nowait -nographic
...
Target didn't reach login banner in 1000 seconds (09/02/25 18:40:59)
Last 25 lines of all logging (308):
c[?7l[2J[0mSeaBIOS (version rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org)


iPXE (http://ipxe.org) 00:02.0 CA00 PCI2.10 PnP PMM+0EFC6560+0EF26560 CA00
Press Ctrl-B to configure iPXE (PCI 00:02.0)...



Booting from Hard Disk..
...
RuntimeError: core-image-minimal - FAILED to start qemu - check the task log and the boot log
...
2025-09-03 00:41:04,380 - oe-selftest - INFO - ERROR: wic.Wic2.test_grub_install_biosplusefi_qemu (subunit.RemotedTestCase)

https://autobuilder.yoctoproject.org/valkyrie/#/builders/35/builds/2256

Can you have a look at the issue please?

Thanks,
Mathieu
Vincent Davis Jr Sept. 4, 2025, 12:47 p.m. UTC | #2
O Yeah,

Have a good idea of what the issue is..
Thought I had that fixed on my end.

Vincent

On Thu, Sep 4, 2025, 1:56 AM Mathieu Dubois-Briand <
mathieu.dubois-briand@bootlin.com> wrote:

> On Tue Sep 2, 2025 at 3:58 AM CEST, Vincent Davis Jr wrote:
> > If caller wants to primarily leverage
> > grub as the primary boot loader current
> > oe-core doesn't support booting grub when
> > the boot firmware is legacy BIOS based and
> > the partition table format is GPT based.
> >
> > Issue GPT header reside where core.img
> > should be located (at byte 512).
> >
> > To navigate around issue core.img was
> > moved to a seperate partition.
> >
> > If disk is a GPT disk caller must specify
> > the file system type as none and set the
> > partition type as BIOS boot. No filesystem
> > will be created on partition. This also
> > allows wic plugin to know where to dd
> > core.img.
> >
> > Unfortunately No deep dive into grub-install
> > was perform to know the exact bytes changed
> > in hybrid boot case. To see the change in
> > bytes generated boot.img + core.img was compared
> > to boot.img + core.img after grub-install was
> > executed using the xxd command.
> >
> > Signed-off-by: Vincent Davis Jr <vince@underview.tech>
> > ---
>
> Hi Vincent,
>
> It looks like this tends to fail some selftest. Autobuilder logs are not
> really verbose here, but I can relaunch a build and extract more log
> files if you now were you want to look.
>
> runqemu - INFO - Running
> /srv/pokybuild/yocto-worker/oe-selftest-debian/build/build-st-2799227/tmp/work/x86_64-linux/qemu-helper-native/1.0/recipe-sysroot-native/usr/bin/qemu-system-x86_64
> -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:02 -netdev
> tap,id=net0,ifname=tap0,script=no,downscript=no -object
> rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0
> -drive
> if=none,id=hd,file=/home/pokybuild/tmp/core-image-minimal-qemux86-64.rootfs.wic.510160,format=raw
> -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd -usb -device
> usb-tablet -usb -device usb-kbd   -cpu Skylake-Client -machine
> q35,i8042=off -smp 4 -enable-kvm -m 256 -serial tcp:127.0.0.1:42697,nodelay=on
> -serial tcp:127.0.0.1:54201,nodelay=on  -pidfile
> /srv/pokybuild/yocto-worker/oe-selftest-debian/build/build-st-2799227/pidfile_2799227
> -S -qmp unix:./.6pnxdkdq,server,wait -qmp unix:./.p0gm_1m0,server,nowait
> -nographic
> ...
> Target didn't reach login banner in 1000 seconds (09/02/25 18:40:59)
> Last 25 lines of all logging (308):
> c[?7l[2J[0mSeaBIOS (version rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org)
>
>
> iPXE (http://ipxe.org) 00:02.0 CA00 PCI2.10 PnP PMM+0EFC6560+0EF26560 CA00
> Press Ctrl-B to configure iPXE (PCI 00:02.0)...
>
>
>
> Booting from Hard Disk..
> ...
> RuntimeError: core-image-minimal - FAILED to start qemu - check the task
> log and the boot log
> ...
> 2025-09-03 00:41:04,380 - oe-selftest - INFO - ERROR:
> wic.Wic2.test_grub_install_biosplusefi_qemu (subunit.RemotedTestCase)
>
> https://autobuilder.yoctoproject.org/valkyrie/#/builders/35/builds/2256
>
> Can you have a look at the issue please?
>
> Thanks,
> Mathieu
>
> --
> Mathieu Dubois-Briand, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>
>
diff mbox series

Patch

diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
index caabda6318..a7fb2eca4e 100644
--- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
+++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
@@ -101,7 +101,7 @@  class BootimgPcbiosPlugin(SourcePlugin):
                      disk_name, full_path, disk.min_size)
 
         if cls.loader == 'grub':
-            cls._do_install_grub(creator, kernel_dir,
+            cls._do_install_grub(disk, creator, kernel_dir,
                             native_sysroot, full_path)
         elif cls.loader == 'syslinux':
             cls._do_install_syslinux(creator, bootimg_dir,
@@ -340,6 +340,12 @@  class BootimgPcbiosPlugin(SourcePlugin):
 
     @classmethod
     def _do_configure_grub(cls, part, creator, cr_workdir):
+        # If partition type is either EFI System or
+        # BIOS boot no need to generate/copy grub config.
+        if part.part_type == '21686148-6449-6E6F-744E-656564454649' or \
+           part.part_type == 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B':
+            return 0
+
         hdddir = "%s/hdd" % cr_workdir
         bootloader = creator.ks.bootloader
 
@@ -438,6 +444,12 @@  class BootimgPcbiosPlugin(SourcePlugin):
          grub_mods_path, core_img, builtin_modules)
         exec_native_cmd(grub_mkimage, native_sysroot)
 
+        # If partition type is either EFI System or
+        # BIOS boot no need to copy in grub modules.
+        if part.part_type == '21686148-6449-6E6F-744E-656564454649' or \
+           part.part_type == 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B':
+            return 0
+
         # Copy grub modules
         install_dir = '%s/%s/%s' % (hdddir, grub_prefix_path, grub_format)
         os.makedirs(install_dir, exist_ok=True)
@@ -454,7 +466,7 @@  class BootimgPcbiosPlugin(SourcePlugin):
                             native_sysroot, False)
 
     @classmethod
-    def _do_install_grub(cls, creator, kernel_dir,
+    def _do_install_grub(cls, disk, creator, kernel_dir,
                          native_sysroot, full_path):
         core_img = '%s/grub-bios-core.img' % (kernel_dir)
 
@@ -478,6 +490,45 @@  class BootimgPcbiosPlugin(SourcePlugin):
             # Install core.img or grub stage 1.5
             dd_cmd = "dd if=%s of=%s conv=notrunc bs=1 seek=512" % (core_img, full_path)
             exec_cmd(dd_cmd, native_sysroot)
+        elif creator.ptable_format == 'gpt':
+            # Issue GPT headers reside where core.img should be (at byte 512).
+            # To navigate around issue core.img was moved to a seperate partition.
+            #
+            # If disk is a GPT disk caller must specify the file system
+            # type as none. As no filesystem may be created. Caller must
+            # also set the partition type to BIOS boot. So, the plugin
+            # may embed core.img there.
+
+            # Replicates what grub-install does to boot.img
+            # Found by comparing xxd output of generated boot.img
+            # to boot.img after grub-install.
+            dd_cmd = "echo -ne '\\x00\\x08' | dd of=%s conv=notrunc bs=1 count=2 seek=92" % (full_path)
+            exec_native_cmd(dd_cmd, native_sysroot)
+
+            dd_cmd = "echo -ne '\\x90\\x90' | dd of=%s conv=notrunc bs=1 count=2 seek=102" % (full_path)
+            exec_native_cmd(dd_cmd, native_sysroot)
+
+            for part in creator.parts:
+                if part.part_type == '21686148-6449-6E6F-744E-656564454649':
+                    part_start_byte = part.start * disk.sector_size
+
+                    # Install core.img or grub stage 1.5
+                    dd_cmd = "dd if=%s of=%s conv=notrunc bs=1 seek=%s" % \
+                        (core_img, full_path, part_start_byte)
+                    exec_cmd(dd_cmd, native_sysroot)
+
+                    # Replicates what grub-install does to core.img
+                    # Found by comparing xxd output of generated
+                    # core.img to core.img ater grub install.
+                    dd_cmd = "echo -ne '\\x01\\x08' | dd of=%s conv=notrunc bs=1 count=2 seek=%d" % \
+                            (full_path, part_start_byte + 500)
+                    exec_native_cmd(dd_cmd, native_sysroot)
+
+                    dd_cmd = "echo -ne '\\x2f\\x02' | dd of=%s conv=notrunc bs=1 count=2 seek=%d" % \
+                            (full_path, part_start_byte + 508)
+                    exec_native_cmd(dd_cmd, native_sysroot)
+
+                    break
         else:
             raise WicError("Unsupported partition table: %s" %
                            creator.ptable_format)