Bernd Schemmer, May 2008
Contents:
My goal is to create a USB stick for rescue tasks in Linux and in the OpenSolaris Operating System for x86 platforms. Therefore, there must be a bootable OpenSolaris OS and a bootable Linux OS on the USB stick. In addition, because I do not want to reboot my PC every time for adding or changing something on the USB stick, the USB stick must also boot in a virtual PC environment. The virtual PC environment should be available on various operating systems. And the USB stick should also be usable in Microsoft Windows environments to save files on the stick.
All components used must be open source or at least freeware.
After some tests, I haven chosen the following components to implement this solution:
A 2-GB USB stick from the BigAdmin Bucks Program, but this information should work with other USB sticks also ...!
Linux Live CD-ROM DSL (Damn Small Linux) version 4.2.5 for the Linux portion:
DSL is chosen because it's complete, fast, and very small (the ISO image needs only about 50 MB; see the DSL homepage).
MilaX (OpenSolaris Small Live CD, version 0.3) for the OpenSolaris portion:
MilaX is chosen because it's complete, fast, and very small (the ISO image needs only about 100 MB; see the MilaX homepage).
Note: MilaX is based on OpenSolaris build 81.
The virtual machine emulator QEMU version 0.9.1 for the virtual PC environment:
QEMU is chosen because it's fast, small, and available for various operating systems (OpenSolaris, Linux, Microsoft Windows, and so on). QEMU does not need a driver or something like this to run; the binary runs without an installation. And, most important, QEMU supports using real disk devices (disks, CD-ROMs, USB sticks, and so on) in the virtual machines.
QEMU supports an accelerator to improve the performance, but the accelerator is not mandatory. On current CPUs with 2 GHz or more, QEMU runs fast enough even without the accelerator (see the QEMU homepage).
To have more than one OS on the USB stick and also an additional FAT partition for Microsoft Windows usage, the USB stick must be partitioned.
Notes:
/dev/sdb
is the USB stick in the
example. The device name for the USB stick depends on the machine
configuration. Therefore, you should check the device name before
continuing!umount
to unmount all
partitions from the USB stick before creating a new partition table on
the USB stick.The first partition is a FAT-formated partition for the myDSL extension of DSL, the Microsoft Windows data, and the QEMU binaries. The second partition is for Linux boot (DSL), and the third partition is for OpenSolaris boot (MilaX).
To install DSL on the USB stick, either boot the PC from the DSL Live CD-ROM and attach the USB stick or use QEMU for this purpose. The example below uses QEMU to install DSL on the USB stick.
Notes:
dsl-4.2.5.iso
for this task (where 4.2.5
is the version of
DSL). It will not work with the other DSL ISO images for the version
4.2.5 (like dsl-4.2.5-initrd.iso, dsl-4.2.5-syslinux.iso, etc). But it
will work with other versions of the DSL ISO image (like dsl-4.3.iso)./dev/sdb
is the USB stick in the example.### start the DSL ISO image in a QEMU virtual machine
#
root@tp61p:/# /usr/local/bin/qemu -net user -usb \
-usbdevice tablet -L /usr/local/share/qemu -m 512 \
-net nic -redir tcp:1135::22 -name \
"DSL_ISO_image_(user_network)_(ssh_port:_1135)" \
-drive file=/dev/sdb,if=scsi,index=1 \
-cdrom /data/nobackup/iso/dsl-4.2.5.iso -boot d
Notes:
-drive
file=/dev/sdb,if=scsi,index=1
is necessary for this
invocation!ssh
daemon in the virtual machine
and set a password for the user dsl
.DSL/Apps/Tools/USB-HDD
Pendrive Install
to install DSL on the USB stick
(because the script used there repartitions the USB stick).The DSL script to install DSL on a USB stick repartitions the USB stick. Therefore, we must change that script before we can use it:
### create a writable copy of the script
#
root@box:~# cp /usr/sbin/pendrive_usbhdd.sh /tmp/
### edit the writable copy
#
root@box:~# vi /tmp/pendrive_usbhdd.sh
Search the function partition()
and add return 0
as first line of the function, so that it
looks like this:
partition(){
return 0
/sbin/sfdisk /dev/sda << EOF
....
Next search for the line dd if=/dev/zero
of=/dev/sda bs=512 count=1
and comment it out:
# dd if=/dev/zero of=/dev/sda bs=512 count=1
Now you can execute the corrected script to install DSL on the USB stick:
root@box:~# /tmp/pendrive_usbhdd.sh
DSL pendrive GRUB boot USB_HDD install/update.
1. Your BIOS must support USB-HDD booting.
2. Two partitions will be made on device sda,
first larger partition sda1 (vfat)
shared,
second smaller sda2 (ext2) for DSL/GRUB
system.
3. Do not have your pendrive mounted.
No responsibility for data loss or hardware damage!
Verify your USB storage device is sda ? (Y/n): y
List boot options:
Example: vga=normal toram ssh tz=US/Pacific lpd monkey ftp: ssh ftp
Choose language/keyboard if other than english:
Example: cs da de es fr nl it pl ru sk: de
Last chance. Ready to proceed. (y/..)? y
Clearing MBR.
Partitioning.
Setting up GRUB boot loader.
Installation finished. No error reported.
This is the contents of the device map /mnt/sda2/boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.
(hd0) /dev/sda
Setting up system image on /mnt/sda2
Installation Completed.
### Check the results of the script
#
root@box:~# mount /dev/sda1 /mnt/sda1
root@box:~# mount /dev/sda2 /mnt/sda2
root@box:~# ls /mnt/sda1
backup.tar.gz mydsl
root@box:~# ls /mnt/sda2
KNOPPIX
boot
linux24 lost+found minirt24.gz
root@box:~# cat /mnt/sda2/boot/grub/menu.lst
default 0
timeout 10
title DSL
root (hd0,1)
kernel /linux24 ramdisk_size=100000 lang=us quiet vga=791 frugal ssh
ftp lang=de
initrd /minirt24.gz
The DSL partition on the USB stick works in a QEMU virtual machine without changes, so there is nothing more to do here.
It's recommended to check the USB stick now. It should boot DSL on bare metal and in a QEMU virtual machine.
To boot the USB stick in a QEMU virtual machine use this:
root@tp61p:/# /usr/local/bin/qemu -net user -usb \
-usbdevice tablet -L /usr/local/share/qemu -m 512 \
-net nic -redir tcp:1135::22 -name \
"DSL_on_USBstick_(user_network)_(ssh_port:_1135)" \
-hda /dev/sdb -boot c
Download the MilaX USB image from the MilaX homepage, and save it in a location that is also accessible after booting from the MilaX Live CD-ROM.
The usbcopy
script from the MilaX homepage
for installing MilaX on a USB stick is not usable for this purpose,
because the script always creates one big slice on the OpenSolaris
partition. Therefore, we will install MilaX manually on the USB stick.
To install MilaX on the USB stick, boot from the MilaX CD-ROM and attach the USB stick to the PC.
I recommend starting the X server after MilaX is up and running:
(alex@milax) ~ # startx
The first thing to do here is to become root user:
(alex@milax)$ su -
Password:
Sun Microsystems Inc. SunOS 5.11 MilaX_03 April 2008
(alex@milax)#
Note: Be aware that the prompt does not change after switching to the root user! In this example, I changed the prompt manually to reflect the user ID.
Caution: The device name for the USB stick depends on the
configuration of the machine used. Therefore, you should check the device
name for the USB stick by using rmformat
, for
example:
(alex@milax)$ rmformat
Looking for devices...
1. Logical Node: /dev/rdsk/c4t0d0p0
Physical Node: /pci@0,0/pci-ide@1f,1/ide@0/sd@0,0
Connected Device: HL-DT-ST DVDRAM GSA-U10N 1.05
Device Type: CD Reader
Bus: IDE
Size: 107.0 MB
Label: <None>
Access permissions: Medium is not write protected.
2. Logical Node: /dev/rdsk/c3t0d0p0
Physical Node: /pci@0,0/pci17aa,20ab@1d,7/storage@2/disk@0,0
Connected Device: Ut163 USB2FlashStorage 0.00
Device Type: Removable
Bus: USB
Size: 2.0 GB
Label: <None>
Access permissions: Medium is not write protected
In the following examples, c3t0d0
is the USB
stick.
There will be three slices on the OpenSolaris partition:
The first slice, c3t0d0s0
, is used for MilaX.
The second slice, c3t0d0s1
, is reserved for
MilaX ZFS Boot, and the last slice, c3t0d0s3
,
is used for data.
(root@milax)# format -e c3t0d0s0
selecting c3t0d0s0
[disk formatted]
FORMAT MENU:
disk - select a disk
type - select (define) a disk type
partition - select
(define) a partition table
current -
describe the current disk
format - format and analyze the disk
fdisk - run the fdisk program
repair - repair a defective sector
label - write label to the disk
analyze -
surface analysis
defect - defect list management
backup - search for backup labels
verify - read and display labels
save - save new disk/partition
definitions
inquiry -
show vendor, product and revision
scsi - independent SCSI mode selects
cache - enable, disable or query SCSI disk
cache
volname -
set 8-character volume name
!<cmd> - execute <cmd>, then return
quit
format> p
PARTITION MENU:
0 - change `0' partition
1 - change `1' partition
2 - change `2' partition
3 - change `3' partition
4 - change `4' partition
5 - change `5' partition
6 - change `6' partition
7 - change `7' partition
9 - change `9' partition
select - select a predefined
table
modify - modify a predefined
partition table
name - name the
current table
print - display the
current table
label - write partition
map and label to the disk
!<cmd> - execute
<cmd>, then return
quit
partition> p
Current partition table (original):
Total disk cylinders available: 601 + 2 (reserved cylinders)
Part Tag
Flag Cylinders
Size
Blocks
0 unassigned wm
0
0
(0/0/0) 0
1 unassigned wm
0
0
(0/0/0) 0
2 backup
wu 0 - 600
1.17GB (601/0/0) 2461696
3 unassigned wm
0
0
(0/0/0) 0
4 unassigned wm
0
0
(0/0/0) 0
5 unassigned wm
0
0
(0/0/0) 0
6 unassigned wm
0
0
(0/0/0) 0
7 unassigned wm
0
0
(0/0/0) 0
8 boot
wu 0 -
0 2.00MB
(1/0/0) 4096
9 unassigned wm
0
0
(0/0/0) 0
partition> 0
Part Tag
Flag Cylinders
Size
Blocks
0 unassigned wm
0
0
(0/0/0) 0
Enter partition id tag[unassigned]:
Enter partition permission flags[wm]:
Enter new starting cyl[0]: 3
Enter partition size[0b, 0c, 3e, 0.00mb, 0.00gb]: 150mb
partition> p
Current partition table (unnamed):
Total disk cylinders available: 601 + 2 (reserved cylinders)
Part Tag
Flag Cylinders
Size
Blocks
0 unassigned wm 3
- 77 150.00MB
(75/0/0) 307200
1 unassigned wm
0
0
(0/0/0) 0
2 backup
wu 0 - 600
1.17GB (601/0/0) 2461696
3 unassigned wm
0
0
(0/0/0) 0
4 unassigned wm
0
0
(0/0/0) 0
5 unassigned wm
0
0
(0/0/0) 0
6 unassigned wm
0
0
(0/0/0) 0
7 unassigned wm
0
0
(0/0/0) 0
8 boot
wu 0 -
0 2.00MB
(1/0/0) 4096
9 unassigned wm
0
0
(0/0/0) 0
partition> 1
Part Tag
Flag Cylinders
Size
Blocks
1 unassigned wm
0
0
(0/0/0) 0
Enter partition id tag[unassigned]:
Enter partition permission flags[wm]:
Enter new starting cyl[0]: 78
Enter partition size[0b, 0c, 78e, 0.00mb, 0.00gb]: 512mb
partition> p
Current partition table (unnamed):
Total disk cylinders available: 601 + 2 (reserved cylinders)
Part Tag
Flag Cylinders
Size
Blocks
0 unassigned wm 3
- 77 150.00MB
(75/0/0) 307200
1 unassigned wm 78 -
333 512.00MB (256/0/0) 1048576
2 backup
wu 0 - 600
1.17GB (601/0/0) 2461696
3 unassigned wm
0
0
(0/0/0) 0
4 unassigned wm
0
0
(0/0/0) 0
5 unassigned wm
0
0
(0/0/0) 0
6 unassigned wm
0
0
(0/0/0) 0
7 unassigned wm
0
0
(0/0/0) 0
8 boot
wu 0 -
0 2.00MB
(1/0/0) 4096
9 unassigned wm
0
0
(0/0/0) 0
partition> 3
Part Tag
Flag Cylinders
Size
Blocks
3 unassigned wm
0
0
(0/0/0) 0
Enter partition id tag[unassigned]:
Enter partition permission flags[wm]:
Enter new starting cyl[0]: 334
Enter partition size[0b, 0c, 334e, 0.00mb, 0.00gb]: $
partition> p
Current partition table (unnamed):
Total disk cylinders available: 601 + 2 (reserved cylinders)
Part Tag
Flag Cylinders
Size
Blocks
0 unassigned wm 3
- 77 150.00MB
(75/0/0) 307200
1 unassigned wm 78 -
333 512.00MB (256/0/0) 1048576
2 backup
wu 0 - 600
1.17GB (601/0/0) 2461696
3 unassigned wm 334 -
600 534.00MB (267/0/0) 1093632
4 unassigned wm
0
0
(0/0/0) 0
5 unassigned wm
0
0
(0/0/0) 0
6 unassigned wm
0
0
(0/0/0) 0
7 unassigned wm
0
0
(0/0/0) 0
8 boot
wu 0 -
0 2.00MB
(1/0/0) 4096
9 unassigned wm
0
0
(0/0/0) 0
partition> label
[0] SMI Label
[1] EFI Label
Specify Label type[0]: 0
Ready to label disk, continue? y
partition> ^D
The next step is to create a file system on the slice for the data:
(root@milax)# newfs /dev/rdsk/c3t0d0s3
newfs: construct a new file system /dev/rdsk/c3t0d0s3: (y/n)? y
/dev/rdsk/c3t0d0s3: 1093632 sectors in 178 cylinders of 48 tracks,
128 sectors 534.0MB in 14 cyl groups (13 c/g, 39.00MB/g, 18624 i/g)
super-block backups (for fsck -F ufs -o b=#) at:
32, 80032, 160032, 240032, 320032, 400032, 480032, 560032, 640032,
720032, 800032, 880032, 960032, 1040032
Next we copy the MilaX USB image to slice 0 of the OpenSolaris partition.
Now get access to the MilaX USB image; in my tests, I copied the image to
a partition on my hard disk, which I then mounted from within MilaX.
(root@milax)# time dd if=/mnt/solaris0/milax03.usb
of=/dev/rdsk/c3t0d0s0 bs=16384
7744+0 records in
7744+0 records out
real 6m14.385s
user 0m0.007s
sys 0m0.274s
(root@milax)#
### Now mount the slice
#
(root@milax)# mkdir /mnt/usb
(root@milax)# mount /dev/dsk/c3t0d0s0 /mnt/usb
### grow the file system on the slice
### This step is optional but without it there is wasted space on the
slice 0.
#
(root@milax)# df -k /mnt/usb
Filesystem
kbytes used avail capacity Mounted
on
/dev/dsk/c3t0d0s0 116187
85584 18985 82% /mnt/usb
(root@milax)# growfs -M /mnt/usb /dev/rdsk/c3t0d0s0
/dev/rdsk/c3t0d0s0: 307200 sectors in 512
cylinders of 1 tracks, 600 sectors
150.0MB in 32 cyl groups (16
c/g, 4.69MB/g, 2240 i/g)
super-block backups (for fsck -F ufs -o b=#) at:
32, 9632, 19232, 28832, 38432, 48032, 57632, 67232, 76832, 86432,
211232, 220832, 230432, 240032, 249632, 259232, 268832, 278432,
288032, 297632
(root@milax)# df -k /mnt/usb
Filesystem
kbytes used avail capacity Mounted
on
/dev/dsk/c3t0d0s0 144111
85584 46909 65% /mnt/usb
### and install grub
#
(root@milax)# installgrub -mf /boot/grub/stage1 /boot/grub/stage2
/dev/rdsk/c3t0d0s0
stage1 written to partition 2 sector 0 (abs 1539584)
stage2 written to partition 2, 260 sectors starting at 50 (abs 1539634)
stage1 written to master boot sector
The next step is the customization of the GNU GRand Unified Bootloader (GRUB) menu.
You should remove the string $ISADIR
from all
GRUB menu entries, if it exists. $ISADIR
is
only necessary for booting a 64-bit kernel if the hardware supports 64
bits. But there is no 64-bit kernel in the MilaX image, so the $ISADIR
string should be removed. Note that this step is optional for machines
with a 32-bit CPU, but it is mandatory for booting the USB stick on a
machine with a 64-bit CPU.
Next, add the entry for DSL to the end of the GRUB menu:
title DSL root (hd0,1) kernel /linux24 ramdisk_size=100000 lang=us quiet vga=791 frugal ssh ftp lang=de initrd /minirt24.gzNow we must customize the MilaX ramdisk on the USB stick. To do this, first uncompress and mount the MilaX ramdisk.
/mnt/solaris0
is a partition on the internal
hard disk in this example; it can be any file system with enough free
space for the uncompressed ramdisk.
First, we configure the keyboard layout; this is done by editing the file
bootenv.rc
on the USB stick:
(root@milax)# vi /mnt/milax_ramdisk/boot/solaris/bootenv.rc
Change the string unknown
in the line setprop keyboard-layout Unknown
to the appropriate
value; for example, for German keyboards, it should look like this:
setprop keyboard-layout "German"
Use the program kbd
to get a list of the
known keyboard layouts:
(root@milax)# kbd -s
USB keyboard
1. Albanian 22. Latvian
2. Belarusian 23. Macedonian
3. Belgian 24. Malta_UK
4. Bulgarian 25. Malta_US
5. Croatian 26. Norwegian
6. Czech 27. Polish
7. Danish 28. Portuguese
8. Dutch 29. Russian
9. Finnish 30. Serbia-And-Montenegro
10. French 31. Slovenian
11. French-Canadian 32. Slovakian
12. Hungarian 33. Spanish
13. German 34. Swedish
14. Greek 35. Swiss-French
15. Icelandic 36. Swiss-German
16. Italian 37. Taiwanese
17. Japanese-type6 38. TurkishQ
18. Japanese 39. TurkishF
19. Korean 40. UK-English
20. Latin-American 41. US-English
21. Lithuanian
To select the keyboard layout, enter a number [default 41]:
You can also change setprop atapi-cd-dma-enabled 1
to setprop atapi-cd-dma-enabled 0
now if the
primary usage for the image is a QEMU virtual machine.
Now you can save and close the file.
The next change is in the init
script, which
sets the keyboard layout so that it honors the eeprom
variable:
(root@milax)# vi /mnt/milax_ramdisk/lib/svc/method/live-fs-root
Replace the line kdb -s
with this:
CUR_KEYBOARD_LAYOUT=`eeprom keyboard-layout | cut -f 2 -d "=" `
if [ "${CUR_KEYBOARD_LAYOUT}"x = "unknown"x ] ; then
kbd -s
else
kbd -s "${CUR_KEYBOARD_LAYOUT}"
fi
The next change in the file live-fs-root
allows booting the USB image in QEMU.
Search for the line volumeid=`cat /.volumeid`
and insert the following lines after that line:
QEMU_DISK_RAW="/devices/pci@0,0/pci-ide@1,1/ide@0/cmdk@0,0:a,raw"
QEMU_DISK_BLOCK="/devices/pci@0,0/pci-ide@1,1/ide@0/cmdk@0,0:a"
Now replace the line lcmd="/sbin/listusb"
with the following:
lcmd="eval /sbin/listusb ; echo ${QEMU_DISK_BLOCK} ${QEMU_DISK_RAW} "
Now you can save and close the file.
Make sure there is no syntax error in the file now (the warnings can be ignored):
(root@milax)# sh -x -n /mnt/milax_ramdisk/lib/svc/method/live-fs-rootThe next change is necessary to correct the rights of the files in the user home directories.
Edit the file /mnt/milax_ramdisk/lib/svc/method/live-sysidtool-system
:
(root@milax)# vi \
/mnt/milax_ramdisk/lib/svc/method/live-sysidtool-system
Search for the line find . -print | cpio -pmud /root
and insert the following line after that line:
chown -R root /root
Search for the line find . -print | cpio -pmud /alex
and insert the following line after that line:
chown -R alex /alex
Now you can save and close the file.
The next change is necessary to get a correct prompt for the root user:
(root@milax)# vi /mnt/milax_ramdisk/etc/skel/.bashrc
Search for who am I
. Replace the line u=`who am i | cut -f1 -d" "`
with the following:
if [ `id -u` = 0 ] ; then
u="root"
else
u=`who am i | cut -f1 -d" "`
fi
I personally like to have the working directory in the prompt. Therefore,
I change the prompt in the .bashrc
file to
this:
You can also add some code here to set the correct keyboard layout for X
server settings. To do that, add the following lines at the end of the
file .bashrc
:
Change the value of the variable NEW_KB_LAYOUT
in the previous code to the appropriate keyboard layout.
Save the file and exit the editor.
Check the file .bashrc
for syntax errors:
(root@milax)# bash -x -n /mnt/milax_ramdisk/etc/skel/.bashrc
The last step is to copy some more utilities, which are useful if the
mount of /usr
fails, to the ramdisk:
(root@milax)# cp /usr/bin/cat /mnt/milax_ramdisk/usr/bin/
(root@milax)# cp /usr/bin/tail /mnt/milax_ramdisk/usr/bin/
(root@milax)# cp /usr/bin/less /mnt/milax_ramdisk/usr/bin/
(root@milax)# cp /usr/bin/vi /mnt/milax_ramdisk/usr/bin/
(root@milax)# cp /usr/sbin/svcadm /mnt/milax_ramdisk/usr/sbin/
(root@milax)# cp /usr/bin/svcs /mnt/milax_ramdisk/usr/bin
Now unmount the ramdisk image, compress it again, and copy it back to the USB stick:
(root@milax)# umount /mnt/milax_ramdisk/And umount the USB stick:
(root@milax)# umount /mnt/usb
That's it. Now the USB stick is ready to use. The only things missing are the binaries for QEMU.
I leave it as an exercise for the reader to copy the QEMU binaries for Linux, Microsoft Windows, and OpenSolaris to the FAT partition of the USB stick.
Here is the final GRUB menu on the USB stick:
(root@milax) ~ # grep -v "^#" /.cdrom/boot/grub/menu.lst | grep -v "^$"The default network adapter emulated by QEMU is not supported by MilaX. Therefore, you must always specify the network adapter type if you are using QEMU to boot MilaX:
-net nic,model=rtl8139
The QEMU parameter -redir tcp:1135:22
enables
SSH connections from the host running QEMU to the QEMU virtual machine
(see the QEMU documentation for details). To connect using SSH to the
virtual machine, use the following:
xtrnaw7@tp61p:~$ ssh -l alex -p 1135 localhost
Note: 1135
can be any free port
above 1024 but it must the port used for the parameter -redir
tcp:1135::22
while calling QEMU.
Here's a script for booting the USB stick from within Linux:
#!/usr/bin/bashHere's a script for booting the USB stick from within Microsoft Windows:
@ECHO OFFNotes:
\\\\.\\physicaldrive1
depends on the hardware configuration of the PC.