Qemu Direct Kernel Boot without bootloader(Grub)

On 2015/12/12 at 19:28

Recently, I was doing a project on Android x86 and I found the image created by Android x86 livecd using NTFS file system format cannot be booted by Qemu.

> $ qemu-system-x86_64 -hda base.img --enable-kvm -serial stdio \
-m 4G -smp 4 \
-net nic,vlan=0 \
-net user,hostfwd=tcp:127.0.0.1:8001-:8001,hostfwd=tcp:127.0.0.1:5555-:5555 \
-soundhw all \
-vga std

And I suspected the problem may be caused by the grub bootloader can not be executed correctly. So I tried extracting the kernel and initrd(it is initramfs actually) and passed it to Qemu directly. And it just booted successfully :). Following is my steps:

1. Check the length of the bootloader (The first 63 sectors)

> $ fdisk -lu 
Disk base.img: 5 GiB, 5368709120 bytes, 10485760 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device     Boot Start      End  Sectors Size Id Type
base.img1          63 10474379 10474317   5G 83 Linux

> $ python -c "print 63*512"
32256

2. Mount the images with offset 32256 bytes

> $ mkdir test
> $ sudo mount -o loop,offset=32256 base.img test
> $ cd test; tree                                                                                                                                                                            
.
├── android-2015-12-07
│   ├── data.img
│   ├── initrd.img
│   ├── kernel
│   ├── ramdisk.img
│   └── system.img
├── efi
│   └── boot
│       ├── bootia32.efi
│       ├── bootx64.efi
│       └── grub.cfg
└── grub
    ├── android-x86.xpm.gz
    ├── device.map
    ├── e2fs_stage1_5
    ├── fat_stage1_5
    ├── iso9660_stage1_5
    ├── menu.lst
    ├── ntfs_stage1_5
    ├── stage1
    ├── stage2
    └── stage2_eltorito

4 directories, 18 files

3. Check the grub kernel options

> $ cat grub/menu.lst                                                                                                                                                                        
default=0
timeout=6
splashimage=/grub/android-x86.xpm.gz
root (hd0,0)

title Android-x86 2015-12-07
        kernel /android-2015-12-07/kernel quiet root=/dev/ram0 androidboot.hardware=sense_svmp SRC=/android-2015-12-07
        initrd /android-2015-12-07/initrd.img

title Android-x86 2015-12-07 (Debug mode)
        kernel /android-2015-12-07/kernel root=/dev/ram0 androidboot.hardware=sense_svmp DEBUG=2 SRC=/android-2015-12-07
        initrd /android-2015-12-07/initrd.img

title Android-x86 2015-12-07 (Debug nomodeset)
        kernel /android-2015-12-07/kernel nomodeset root=/dev/ram0 androidboot.hardware=sense_svmp DEBUG=2 SRC=/android-2015-12-07
        initrd /android-2015-12-07/initrd.img

title Android-x86 2015-12-07 (Debug video=LVDS-1:d)
        kernel /android-2015-12-07/kernel video=LVDS-1:d root=/dev/ram0 androidboot.hardware=sense_svmp DEBUG=2 SRC=/android-2015-12-07
        initrd /android-2015-12-07/initrd.img

4. Pass the parameter and boot it!

> $ qemu-system-x86_64 -hda base.img --enable-kvm \
-kernel kernel -initrd initrd.img \
-append "root=/dev/ram0 androidboot.hardware=sense_svmp SRC=android-2015-12-07" \
-serial stdio \
-m 4G -smp 4 \
-net nic,vlan=0 \
-net user,hostfwd=tcp:127.0.0.1:8001-:8001,hostfwd=tcp:127.0.0.1:5555-:5555 \
-soundhw all \
-vga std

Result

Comments