50 - Prepare a bootable USB drive using linux commands

Unique hits hit counter for tumblr

Here are two scripts from two different authors, to partition and format a USB drive under linux. I have not tested these myself.

Method 1 (by David Mathog)


We have a lot of computers with a broken Award BIOS (version F9 for the Gigabyte MA785GMT-UD2H) that is insanely picky about what must be on a USB key if it is going to boot. 

For instance, the BIOS compatibility (memtest86+) test at http://www.pendrivelinux.com/testin...atibility/ not only didn't run, it wasn't even displayed as an option in the HDD list! I tried a bunch of USB installers (some from the pendrivelinux site) and USB how to's, including the ones about how to make the USB look like a zip drive, and the only success was by installing syslinux with RMPrepUSB on Windows. By essentially working backwards from the USB stick it produced, and with a lot of help from the author of that package, I finally came up with a series of more or less standard linux commands that would generate a bootable USB stick for this BIOS. Hopefully the next person who runs into this BIOS issue will find this post and can save themselves a lot of time and effort.

The USB stick used is a SanDisk Cruzer Blade 4GB. Using a different stick would only change the number of Cylinders in the following (to adjust to the size of that disk). 
The device on this machine is /dev/sdb, use what is appropriate on your machine or this could munch other disks!!!

#wipe the beginning of the disk. Here the first 4M.
dd if=/dev/zero of=/dev/sdb bs=4k count=1k

# partition the USB stick so that H=255,Sec=63, and C*H*S is
# the size of the disk (or slightly smaller). This is KEY.
# I used the grub4dos installer option in RMPrepUSB to see
# what geometry the BIOS would accept. It turned out that if
# a second partition was created, or the ends of this one
# changed around, the linux kernel would use its own logical
# geometry information for the drive, which would then be used
# in turn by mkfs.vfat. That is, even if it was set to the CHS
# I wanted with fdisk or sfdisk, if there was any inconsistency,
# the kernel would fall back to its own representation instead
# of using the CHS specified. Note the math for the values
# below: 489*255*63= 7855785, 7855785 = 7855722+63
# The partition starts at sector 63 since that worked in the one
# produced by RMprepUSB, and there was no good reason to change it.
#
# create a text file
#

cat >sfdisk.in <<EOD
unit: sectors

/dev/sdb1 : start= 63, size= 7855722, Id= c, bootable
/dev/sdb2 : start= 0, size= 0, Id= 0
/dev/sdb3 : start= 0, size= 0, Id= 0
/dev/sdb4 : start= 0, size= 0, Id= 0
EOD

sfdisk -f -C489 -H255 -S63 /dev/sdb <sfdisk.in

#
# Install fat32 in the one partition.
# Install master and partition boot blocks.
# ms-sys is from http://ms-sys.sourceforge.net/
#
mkfs.vfat -F 32 -n Test /dev/sdb1
./ms-sys -H 255 -w /dev/sdb
./ms-sys -p -H 255 -w /dev/sdb1
sync

#
# at this point for some odd reason syslinux tends to go nuts if run
# immediately, looping like crazy on
# file is read only, overwrite anyway (y/n) ?
# so unplug the drive, plug it in again, wait for it to automount
# then do:
#
umount /dev/sdb1
syslinux /dev/sdb1


Test with:

qemu /dev/sdb

and it boots into syslinux. Test by booting on the target machine and:

1. it shows up in the HDD list (after pressing F12 to get to the boot list)
2. it does not stop with a "boot error"
3. it does not stop with an "operating system not found"
4. it ends up with the expected syslinux text on the screen

That is all as it should be, since there is nothing else on the disk for syslinux to transfer control to.

At this point one can install whatever linux distro or other tools are desired on the USB stick. Since mine was for recovery purposes, I used
PLD Rescue (http://rescuecd.pld-linux.org/). usb.zip (see below) is from that site too.

cd /tmp
mkdir foo
mkdir usb
umount /dev/sdb1
mount /dev/sdb1 /tmp/usb
mount -o loop,exec /tmp/RCDx86_11_02.iso /tmp/foo
cd usb
unzip /tmp/usb.zip
cd ../foo
cp rescue.cpi ../usb
cd boot/isolinux
cp initrd.ide vmlinuz memtest /tmp/usb
umount /dev/sdb1

This USB Flash key was displayed in the HDD boot menu and booted into PLD on the target machines, despite everything that Award BIOS put in the way to prevent it.


The following variant also creates an extra small empty partition which may help to increase success with some BIOSes.

cat >sfdisk.in <<EOD
unit: sectors

/dev/sdb1 : start= 63, size= 7855596, Id= c, bootable
/dev/sdb2 : start= 7855659, size= 126, Id!
/dev/sdb3 : start= 0, size= 0, Id= 0
/dev/sdb4 : start= 0, size= 0, Id= 0
EOD


Regards,

David Mathog



Method 2 (by Bogdan Koval)

Here is another script sent in from Bogdan Koval. Bogdan says this make a USB drive that boots on more systems.

The two files required, mbr.bin and fat.bin, are attached to the bottom of this page. Set the flash and part variables to the device name of your USB drive.

I'm creating a script to create a bootable USB Flash. Our company only uses Linux. Our task was to find a solution which would work under Linux.
The first version was grub4dos to the MBR. On some motherboards will not boot. Error - no GRLDR.
Then I created a flash drive in Linux-based ISOLINUX in the PBR. I use many different tools - Unetbootion, Gparted, parted, ant etc. The same does not boot on some motherboards.
It also created a flash drive in Windows using fat32format or RMPREPUSB. All was well.
I found your article - http://www.rmprepusb.com/tutorials/usbpreplinux
USB Flash is already loaded on more motherboards, but still some do not load.
Spent a week and found the following solution, which is largely complementary to your article.


flash=/dev/sdb
part=/dev/sdb1
umount $part
#erase mbr
echo Erase mbr
dd if=/dev/zero of=$flash bs=1024 count=1024
#calculate sectors, cylinders   
size=`fdisk -l $flash | grep $flash | awk '{print $5}'`
echo disk size - $size bytes
cylinders=`echo $size/255/63/512 | bc`
echo cylinders - $cylinders
sectors=`echo $cylinders*255*63 | bc`
echo sectors - $sectors
sizesectors=`echo $sectors-63 | bc`
cat >sfdisk.in <<EOF
unit: sectors

/dev/sdb1 : start= 63, size= $sizesectors, Id= c, bootable
/dev/sdb2 : start= 0, size= 0, Id= 0
/dev/sdb3 : start= 0, size= 0, Id= 0
/dev/sdb4 : start= 0, size= 0, Id= 0
EOF
#create partition table and partition
echo Create partition table
sfdisk -f -C$cylinders -H255 -S63 /dev/sdb <sfdisk.in
#format partition
echo Format Partition
mkfs.vfat -F 32 -n label $part
./ms-sys -H 255 -w $flash
./ms-sys -p -H 255 -w $part
sync
partprobe -s $flash
#modify flash sectors
#erase 65 sector (strange data is here)
echo Correct FAT boot sectors
dd if=/dev/zero of=$flash bs=512 count=1 seek=65
#extract 63 sector and parse
dd if=$flash of=63.sec bs=512 count=1 skip=63
#find start sector of partition (63)
startsector=`echo "ibase=16; $(od -t x2 --skip-bytes=28 --read-bytes=2 63.sec | awk '{print $2; exit}' | tr [:lower:] [:upper:])"|bc`
#find number of hidden sectors (32)
hiddensectors=`echo "ibase=16; $(od -t x2 --skip-bytes=14 --read-bytes=2 63.sec | awk '{print $2; exit}' | tr [:lower:] [:upper:])"|bc`
#find size of FAT   
fatsize=`echo "ibase=16; $(od -t x2 --skip-bytes=36 --read-bytes=2 63.sec | awk '{print $2; exit}' | tr [:lower:] [:upper:])"|bc`
#find start sectors of each FAT
fat1startsector=`echo $startsector+$hiddensectors | bc`
echo Start sector of 1st FAT: $fat1startsector
fat2startsector=`echo $startsector+$hiddensectors+$fatsize | bc`
echo Start sector of 2nd FAT: $fat2startsector
#modify 1st sectors of FATs
dd if=fat.bin of=$flash bs=16 count=1 seek=$fat1startsector
dd if=fat.bin of=$flash bs=16 count=1 seek=$fat2startsector
#extract 64 sector and copy them to 70 sector (missing fsinfo backup)
dd if=$flash of=64.sec bs=512 count=1 skip=64
dd if=64.sec of=$flash bs=512 count=1 seek=70
#install syslinux
echo Install Syslinux
./syslinux -i $part
#write syslinux MBR
dd if=mbr.bin of=$flash bs=446 count=1


ċ
fat.bin
(0k)
Steve Si,
27 Mar 2012 01:48
ċ
mbr.bin
(0k)
Steve Si,
27 Mar 2012 01:50