[syslinux] Boot from CD -> system + data on USB storage
Marc Haisenko
haisenko at webport.de
Fri Nov 12 07:35:10 PST 2004
On Friday 12 November 2004 10:48, you wrote:
> Hi,
> I am looking for a solution to boot MY system on any PC.
>
> To store most of the system and all of my data I want to use an USB
> storage (in my case an external USB harddisk (2.0 capable)).
> Since booting off an USB device is not an universal thing I would prefer
> to have a boot disk with a minimal system - just enough to load most
> (all?) of the system from the attached USB device.
>
> Is this an easy thing - are there ready to use solutions out there?
>
> Thanks in advance.
Problem is the USB part... ISOLINUX does not know a thing about USB, AFAIK,
as it would require some drivers to do so (the BIOS does some tricks to boot
from USB, IIRC).
You could do the following: have ISOLINUX, a kernel and an initrd on the CD
and the rest of the system on USB. The kernel could either have USB support
built in or have initrd load the modules. The initrd then searches all SCSI
partitions for your root partition (e.g. by having a file "this_is_my_root"
on that partition, and the initrd searches for a partition that has this file
on it). When you've found the partition you set the device number
in /proc/sys/kernel/real-root-dev.
I've written such an linuxrc in assembler that does just this for IDE. It
probes all IDE partitions until it finds one that has a "/sbin/init" on it
and then sets real-root-dev accordingly. I've attached the source. You
need /dev/console and /dev/hd* to be in the initrd as well and an empty
directory /proc. My source is surely not very efficient but you should be
able to adapt it easily (you only need to change the strings at the top of
the source).
Problem is that if you want to upgrade your kernel you have to burn another
CD.
C'ya,
Marc
--
Marc Haisenko
Systemspezialist
Webport IT-Services GmbH
mailto: haisenko at webport.de
-------------- next part --------------
##############################################
# linuxrc-probeide #
# #
# This is a special linuxrc implementation #
# for initrd's, which tries to find file- #
# systems that we can boot from (that is, #
# that have a /sbin/init file). #
# #
# This program first mounts /proc and then #
# tries to mount every IDE disk and their #
# partitions until it finds a filesystem #
# that has a /sbin/init file. #
# #
# It then writes the device number into the #
# /proc/sys/kernel/real-root-dev file which #
# tells the Linux kernel from which device #
# to boot from. #
##############################################
# (C) 2004 Marc Haisenko <marc at darkdust.net> #
##############################################
.section .data
mountsource: .asciz "none"
mountpoint: .asciz "/proc"
mountpoint2: .asciz "/mnt"
mountfstype: .asciz "proc"
mountfstypeext3: .asciz "ext3"
mountfstypeext2: .asciz "ext2"
mountfstypereiserfs: .asciz "reiserfs"
mountfslist: .long 0
.long 0
.long 0
.long 0
mountoptions: .long 0
stringdisk: .asciz "disk"
errormount: .asciz "Couldn't mount /proc: "
stringfound: .asciz "Found harddisk: "
stringnothd: .asciz "Not a harddisk: "
stringtesting: .asciz "Trying to mount "
stringmounted: .asciz "Successfully mounted "
stringisrootfs: .asciz " is a potential root filesystem !\n"
stringnotrootfs: .asciz " is not a potential root filesystem.\n"
stringcouldntwrite: .asciz "Couldn't write device node nr. into real_root_dev file !\n"
stringsuccess: .asciz "Successfully wrote into real_root_dev.\n"
realrootdevfile: .asciz "/proc/sys/kernel/real-root-dev"
idefile: .ascii "/proc/ide/hd"
idefilechar: .ascii "a"
.asciz "/media"
idedevice: .ascii "/dev/hd"
idedevicechar: .ascii "a"
idedevicepartition: .byte 0,0
buffer: .long 0,0,0,0,0,0,0,0,0
current: .long 0
currentdevice: .long 0
currentdevicepartition: .long 0
finaldevice: .long 0
rootfsfile: .asciz "/mnt/sbin/init" # file which identifies a filesystem as a potential root filesystem
.section .text
.globl _start
.align 4
_start:
movl $mountfstypeext3, (mountfslist) # set up the filesystem list
movl $mountfstypeext2, (mountfslist + 4)
movl $mountfstypereiserfs, (mountfslist + 8)
movl $mountsource, %ebx # mount the proc filesystem
movl $mountpoint, %ecx
movl $mountfstype, %edx
movl $0xc0ed0000, %esi
movl $mountoptions, %edi
movl $21, %eax # syscall mount
int $0x80
cmp $0, %eax # no error ?
jz _probehds # yeah, so check for hda
pushl %eax # save error number
# unhandled error numbers
movl $2, (common_print_fd) # print to stderr
movl $errormount, %eax # print mounterror string
call print_cstring
popl %eax # restore error number
call print_signed_number # print error number
call print_newline # and a newline as well
jmp _exit1 # exit 1
_exit:
movl $mountpoint, %ebx # unmount /proc
movl $22, %eax # syscall umount
int $0x80
xorl %ebx, %ebx # exit 0
movl $1, %eax
int $0x80
_exit1:
movl $mountpoint, %ebx # unmount /proc
movl $22, %eax # syscall umount
int $0x80
movl $1, %ebx # exit 1
movl $1, %eax
int $0x80
### probehds
#
# The main routine
#
_probehds:
_probeide:
movb (idedevicechar), %al # which device are we currently probing ?
cmp $105, %al # if we reached hdi we can stop (since that would be the master of the fifth channel !)
je _exit1
movl $idefile, (current)
movl $idedevice, (currentdevice)
movl $idedevicepartition, (currentdevicepartition)
movl (currentdevicepartition), %eax
movl $0, (%eax)
call _checkide
test %eax, %eax # check whether we found a root filesystem
jz _probeide_writerootfs # we found one, write it into /proc/sys/kernel/real_root_dev
movb (idedevicechar), %al # get current device char
incb %al # increase current device char
movb %al, (idedevicechar) # write it back
movb (idefilechar), %al # same for the file string
incb %al
movb %al, (idefilechar)
movb $0, (idedevicepartition) # also clear the partition character
jmp _probeide # loop
_probeide_writerootfs:
movl (currentdevice), %ebx # get device node nr. of the current device file
movl $buffer, %ecx
movl $106, %eax # syscall stat
int $0x80
movl (buffer), %eax # print device node nr.
call print_unsigned_number
call print_newline
movl $realrootdevfile, %ebx # open /proc/sys/kernel/real_root_dev
movl $0101, %ecx # O_WRONLY | O_CREAT
movl $0644, %edx # -rw-r--r--
movl $5, %eax # syscall open
int $0x80
test %eax, %eax # successful opened ?
js _probeide_couldntwrite # no, say so and exit
movl %eax, (common_print_fd) # print calls now write to that file
movl (buffer), %eax # print device node nr.
call print_unsigned_number
call print_newline
movl $1, (common_print_fd) # print to stdout again
movl (buffer), %ebx # close file
movl $6, %eax # syscall close
int $0x80
movl $stringsuccess, %eax # print that we were successful
call print_cstring
jmp _exit
_probeide_couldntwrite:
movl $stringcouldntwrite, %eax # print that we couldn't write the device nr.
call print_cstring
jmp _exit1
### checkide
#
# Check an IDE disk
#
_checkide:
pushl %ebx # save registers
pushl %ecx
pushl %edx
movl (current), %ebx # open /proc/ide/*/media
xorl %ecx, %ecx # O_RDONLY
movl $5, %eax # syscall open
int $0x80
test %eax, %eax # check return value
js _checkide1 # file not found, return
movl %eax, %ebx # now read the opened file to whether it's a disk or cdrom
movl $buffer, %ecx # read into buffer
movl $4, %edx # the string "disk" is 4 bytes long
movl $3, %eax # syscall read
int $0x80
test %eax, %eax # check return value
js _checkide2
movl $buffer, %eax # compare the read string with "disk"
movl $stringdisk, %ebx
call compare_cstring
test %eax, %eax # check return value
jnz _checkide1 # the read string is not "disk"
call _print_diskfound
call _mountcheck # try to mount and check for /etc
popl %edx # restore registers
popl %ecx
popl %ebx
ret
_checkide1:
call _print_nothd
movl $-1, %eax # no success
popl %edx # restore registers
popl %ecx
popl %ebx
ret
_checkide2:
movl %eax, %ebx # move fd into ebx
movl $6, %eax # syscall close
int $0x80
jmp _checkide1
### print_diskfound
#
# Prints which device we're currently probing
#
_print_diskfound:
pusha
movl $stringfound, %eax
call print_cstring
movl (currentdevice), %eax
call print_cstring
call print_newline
popa
ret
### print_nothd
#
# Prints that the device was not found or is not a hd
#
_print_nothd:
pusha
movl $stringnothd, %eax
call print_cstring
movl (currentdevice), %eax
call print_cstring
call print_newline
popa
ret
### print_testing
#
# Prints which device we're currently trying to mount
#
_print_testing:
pusha
movl $stringtesting, %eax
call print_cstring
movl (currentdevice), %eax
call print_cstring
call print_newline
popa
ret
### print_mounted
#
# Prints which device we've successfully mounted
#
_print_mounted:
pusha
movl $stringmounted, %eax
call print_cstring
movl (currentdevice), %eax
call print_cstring
call print_newline
popa
ret
### print_isrootfs
#
# Prints that the current device is a root filesystem
#
_print_isrootfs:
pusha
movl (currentdevice), %eax
call print_cstring
movl $stringisrootfs, %eax
call print_cstring
popa
ret
### print_notrootfs
#
# Prints that the current device is a not root filesystem
#
_print_notrootfs:
pusha
movl (currentdevice), %eax
call print_cstring
movl $stringnotrootfs, %eax
call print_cstring
popa
ret
### mountcheck
#
# Try to mount a device or a partition on the device
#
_mountcheck:
_mountcheck_mount:
call _print_testing
movl $mountfslist, %ecx
_mountcheck_mount2:
movl (%ecx), %edx
test %edx, %edx
jz _mountcheck_nextdevice # no more filesystems left to check, try next device
movl %esi, (buffer)
movl %edi, (buffer+4)
movl %ecx, (buffer+8)
movl (currentdevice), %ebx # mount source
movl $mountpoint2, %ecx # /mnt
movl $0xce0d0000, %esi
movl $mountoptions, %edi
movl $21, %eax
int $0x80
movl (buffer), %esi
movl (buffer+4), %edi
movl (buffer+8), %ecx
test %eax, %eax # did the mount call succeed ?
js _mountcheck_mount3 # no, try next filesystem
call _print_mounted # we successfully mounted a device
call rootpartitioncheck # check whether the device is a root device
call unmount # unmount the device again
test %eax, %eax
jnz _mountcheck_mount3 # it's not a root device, try next filesystem
ret
_mountcheck_mount3:
addl $4, %ecx # next filesystem string pointer
jmp _mountcheck_mount2 # loop
_mountcheck_nextdevice:
movl (currentdevicepartition), %eax # pointer to pointer
movl (%eax), %ebx
test %ebx, %ebx # test whether we checked whole disk
jz _mountcheck_nextdevice1
incl %ebx # increase device number
movl %ebx, (%eax) # save current partition
cmp $58, %ebx # we only want to check the first 9 partitions
jnb _mountcheck_exit1
jmp _mountcheck_mount # try next partition
_mountcheck_nextdevice1:
movl $49, (%eax) # use ASCII '1' as partition number
jmp _mountcheck_mount
_mountcheck_exit1:
movl $-1, %eax
ret
### unmount
#
# Unmount the mounted device
#
unmount:
pusha # save registers
movl $mountpoint2, %ebx # unmount /mnt
movl $22, %eax # syscall umount
int $0x80
popa # restore registers
ret
### rootpartitioncheck
#
# Check whether the mounted filesystem could serve as a root filesystem
#
rootpartitioncheck:
pushl %ebx # save registers
pushl %ecx
pushl %edx
movl $rootfsfile, %ebx # check whether we find this file
xorl %ecx, %ecx # O_RDONLY
movl $5, %eax # syscall open
int $0x80
test %eax, %eax # check whether we could open that file
js _rootpartitioncheck1
movl %eax, %ebx # close file again
movl $6, %eax # syscall close
int $0x80
call _print_isrootfs
xorl %eax, %eax # yes, it's a rootfs !
popl %edx # restore registers
popl %ecx
popl %ebx
ret # return to caller
_rootpartitioncheck1:
call _print_notrootfs
movl $-1, %eax # it's not a roofs
popl %edx # restore registers
popl %ecx
popl %ebx
ret # return to caller
More information about the Syslinux
mailing list