Sunday, 20 December 2015

Boot from a linux disk image with grub4dos\Easy2Boot

I came across the HDDGURU wipemydisks disk image yesterday (wipemydisks1.1.img). This is a complete linux disk image with a bootable MBR and partition table and was designed to be written to a USB drive using dd or a disk imaging program (e.g. RMPrepUSB - File -> Disk).

I wanted to try to add this to Easy2Boot and so experimented with a way of booting to it.



The non-compressed image file contained an MBR with just one entry in the partition table:

Partition 1   SIZE=800MiB   Type: 83   *ACTIVE*
START POS   = CYL:0 HD:32 SEC:33       END POS = CYL:102 HD:28 SEC:54
START (LBA) = 2,048 (00000800) SIZE (LBA) = 1,638,400 (00190000) [End=1,640,447]

I thought that I could use the grub4dos partnew command to 'move' the partition to (hd0,3) and then boot to it. I eventually ended up adding the grub4dos code shown below to the Easy2Boot QRUN.g4b batch file:

:.imghdlinux
set PT=0x83

#generic entry point to boot any disk image if PT is set in hex type - e.g. set PT=0x83
:.imghdPT
# Change ISOC to defragged file if %ISOC% was fragmented
call :.contigfix
if not exist CD partnew (%E2BDEV%,3) %PT% %ISOC% || echo && call echo -e %emsg% && pause Press a key... && configfile (md)0xa000+0x50

dd if=(%E2BDEV%)0+1 of=(md)0x300+1 > nul
# get length
read 0x601fa > nul
set /A LEN=%@retval%&0xffffffff > nul
#echo ***** LEN=%LEN%
map --read-only %ISOC% (hd15) > nul
map --hook
dd if=(hd15)0+1 of=(md)0x300+1 > nul
# check for valid MBR
read 0x601fe > nul
set /A MAGIC=%@retval%&0xffff > nul
if /i not "%MAGIC%"=="0xaa55" echo -e SORRY: %ISOC% is not a decompressed whole-disk image file.\nUse WinRar or 7Zip to extract the .hfs file and use that instead! && pause && partnew (%E2BDEV%,3) 0 0 0 && configfile (md)0xa000+0x50
set MAGIC=
# find partition
set STOFF=
set /A TYP=*0x601c2 & 0xff > nul
if /i "%PT%"=="%TYP%" && set STOFF=0x601c6 && echo Found %PT% partition in PTN 1 of %ISOC% %redir%
set /A TYP=*0x601d2 & 0xff > nul
if /i "%PT%"=="%TYP%" && set STOFF=0x601d6 && echo Found %PT%partition in PTN 2 of %ISOC% %redir%
set /A TYP=*0x601e2 & 0xff > nul
if /i "%PT%"=="%TYP%" && set STOFF=0x601e6 && echo Found %PT%partition in PTN 3 of %ISOC% %redir%
set /A TYP=*0x601f2 & 0xff > nul
if /i "%PT%"=="%TYP%" && set STOFF=0x601f6 && echo Found %PT%partition in PTN 4 of %ISOC% %redir%
if "%STOFF%"=="" pause SORRY: Cannot find a type %PT% partition in the image! && partnew (%E2BDEV%,3) 0 0 0 && configfile (md)0xA000+0x50
set TYP=
# get start PBR inside image
read %STOFF% > nul
set /A OFFSTART=%@retval%&0xffffffff > nul
#echo ***** OFFSTART=%OFFSTART%
set /A L=%LEN%-%OFFSTART% > nul
#echo **** L=%L% OFFSTART=%OFFSTART%
echo Creating new partition 4 on %E2BDEV% using command: partnew (%E2BDEV%,3) %PT% (%E2BDEV%,3)%OFFSTART%+%L% %redir%
partnew (%E2BDEV%,3) %PT%  (%E2BDEV%,3)%OFFSTART%+%L%

errorcheck off
echo
ls (hd0,3)/
echo
# remove part type now before we map hd0
parttype (hd0,3) 0
errorcheck on
echo
# unmap file
map --unmap=0x8f
#map whole disk image to hd0
map --heads=0 --sectors-per-track=0 %ISOC% (hd0) > nul || map --mem --heads=0 --sectors-per-track=0 %ISOC% (hd0)
map --hook
root (hd0,0) || rootnoverify (hd0,0)
chainloader (hd0)+1 || chainloader (hd0,0)+1 || chainloader (hd0,3)+1
rootnoverify (hd0,0)
set STOFF=
set L=
set OFFSTART=
set LEN=
boot

The way it works is to first find where the partition begins in the .img file and then permanently set the last partition on the USB drive (hd0,3) to point to that section of the .img file. Then I map the whole hd0 USB drive to the .img file and boot to (hd0). The first 'real-mode' part of linux will boot and then switch to protected mode, at which point all the BIOS mapping done by grub4dos for hd0 will be lost and the (hd0,3) partition will be mounted by linux and used for the 2nd stage boot process. I also reset the partition type of (hd0,3) to 0 just before booting so that E2B\Windows will not see a partition at (hd0,3) when we reboot.

This worked well for the wipemydisks1.1.img file, however, because the wipemydisks script did not recognise the USB disk as the correct UUID for (hd0,0) (I am guessing???), instead of ignoring the USB boot disk, it wanted to wipe it too!

Wipemydisks will ignore the boot disk if the disk image is directly written to the USB drive.

When booted using E2B from the .imghdlinux file however, it wants to wipe the USB drive too!  :-(


So this turned out to be a futile exercise, at least for the wipemydisks image!

However, I have added in support for a .imghdlinux  file extension into E2B v1.76BetaC, so that we will be able to boot similar linux single-partition disk image files just by changing the file extension.