50 - Prepare a bootable USB drive using linux commands

hit counter for tumblr

Unique hits

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

Tip: For best boot compatibility, two primary partitions should be created, even if the second one is very small.

Method 1 (by David Mathog)

The following is taken from a post by David Mathog at http://us.generation-nt.com/answer/bootable-usb-stick-broken-bios-help-204344491.html

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