Subversion Repositories livecd

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 beyerle@PS 1
#!/bin/ash
2
#
3
# Functions library :: for Linux Live scripts 5.x.y
4
# Author: Tomas M. <http://www.linux-live.org>
5
#
6
# modified by Urs Beyerle, PSI
7
# - to allow LiveCD mounted over nfs
8
# - add scsi_mod, sd_mod for usb-storage module
9
# - only with boot option "automount", all devices in fstab are rw automounted
10
# - remove detect of CD and Floppy (done by fstab-sync)
11
# - add sr_mod (USB CDROM support)
12
# - add SATA to modprobe_usb_modules -> modprobe_usb_sata_modules
13
#
14
 
15
# ===========================================================
16
# user interface functions
17
# ===========================================================
18
 
19
# echolog
20
# $1 = text to show and to write to /var/log/messages
21
#
22
echolog()
23
{
24
   echo "LIVECD:" "$@" >>/var/log/livedbg
25
   echo "$@"
26
}
27
 
28
# debug
29
# commands executed when debug boot parameter is present
30
#
31
debug()
32
{
33
   echo
34
   echo "====="
35
   echo ": Debugging started. Here is the root shell for you."
36
   echo ": Type your desired command or hit Ctrl+D to continue booting."
37
   echo
38
   ash
39
}
40
 
41
# header
42
# $1 = text to show
43
#
44
header()
45
{
46
   echolog "$1"
47
}
48
 
49
fatal()
50
{
51
   header "Fatal error occured - $1"
52
   echolog "Something went wrong and we can't continue booting :("
53
   echolog "You may explore the system by using simple commands like ls, lsmod, mount, etc."
54
   echolog "You may also try to hit Ctrl+D. Booting will continue. Use at your own risk."
55
   echolog "To be safe, hit Ctrl+Alt+Delete to reboot."
56
   echolog
57
   ash
58
}
59
 
60
# ===========================================================
61
# text processing functions
62
# ===========================================================
63
 
64
# egrep_o is a replacement for "egrep -o". It prints only the last
65
# matching text
66
# $1 = regular expression
67
#
68
egrep_o()
69
{
70
   cat | egrep "$1" | sed -r "s/.*($1).*/\\1/"
71
}
72
 
73
# look into cmdline and echo $1 back if $1 is set
74
# $1 = value name, case sensitive, for example livecd_subdir
75
# $2 = file to use instead /proc/cmdline, optional
76
#
77
cmdline_parameter()
78
{
79
   CMDLINE=/proc/cmdline
80
   if [ "$2" != "" ]; then CMDLINE="$2"; fi
81
   cat "$CMDLINE" | egrep_o "(^|[[:space:]]+)$1(\$|=|[[:space:]]+)" | egrep_o "$1"
82
}
83
 
84
# look into cmdline and echo value of $1 option
85
# $1 = value name, case sensitive, for example livecd_subdir
86
# $2 = file to use instead /proc/cmdline, optional
87
#
88
cmdline_value()
89
{
90
   CMDLINE=/proc/cmdline
91
   if [ "$2" != "" ]; then CMDLINE="$2"; fi
92
   cat "$CMDLINE" | egrep_o "(^|[[:space:]]+)$1=([^[:space:]]+)" | egrep_o "=.*" | cut -b 2- | tail -n 1
93
}
94
 
95
# ===========================================================
96
# system functions
97
# ===========================================================
98
 
99
# modprobe module $1, including all dependencies, suppress all messages
100
# (own function because modprobe in busybox doesn't work with gzipped modules)
101
# $1 = module name, eg. ehci-hcd
102
# $2 = optional argument
103
#
104
modprobe_module()
105
{
106
  if [ "$1" = "" ]; then return 1; fi
107
  PRINTK=`cat /proc/sys/kernel/printk`
108
  echo "0" >/proc/sys/kernel/printk
109
 
110
  KERNEL="`uname -r`"; LSMOD=/tmp/lsmod
111
  MODULEDEPS="`cat /lib/modules/$KERNEL/modules.dep | egrep \"$1\\.ko(\\.gz)?:\"`"
112
 
113
  for MODULE in `echo $MODULEDEPS | cut -d ":" -f 2-` `echo $MODULEDEPS | cut -d ":" -f 1`; do
114
     MODULE=${MODULE%%:};   # remove : at the end, a bug 
115
     TMPMOD="/tmp/`basename $MODULE .gz`";
116
     # if the module is not loaded already
117
     if [ "`cat $LSMOD 2>/dev/null | egrep \"^$TMPMOD\\\$\"`" = "" ]; then
118
        gunzip -c $MODULE 2>/dev/null >$TMPMOD
119
        if [ "$?" -ne 0 ]; then cp $MODULE $TMPMOD; fi # can't gunzip? copy
120
        insmod $TMPMOD $2; err=$?
121
        ### insmod $TMPMOD $2 >/dev/null 2>/dev/null; err=$?
122
        if [ "$err" -eq 0 ]; then echo $TMPMOD >>$LSMOD; fi # module log
123
        rm $TMPMOD
124
     fi
125
  done
126
 
127
  echo "$PRINTK" >/proc/sys/kernel/printk
128
  if [ "$err" -ne 0 ]; then echolog "error inserting module $1 ($err)"; fi
129
  return $err
130
}
131
 
132
# Mount device $1 to $2
133
# $1 = /dev device to mount, eg. /dev/hda1
134
# $2 = mountpoint, eg. /mnt/hda1
135
# $3 = mount options, for example "loop", "ro", or "remount,rw"
136
#
137
mount_device()
138
{
139
  mkdir -p $2
140
  if [ "$3" != "" ]; then OPTIONS="-o $3"; else OPTIONS=""; fi
141
 
142
  PRINTK=`cat /proc/sys/kernel/printk`
143
  echo "0" >/proc/sys/kernel/printk
144
 
145
  mount -t auto $1 $2 $OPTIONS >/dev/null 2>/dev/null
146
  err=$?
147
 
148
  if [ "$err" -ne 0 ]; then rmdir $2 2>/dev/null; fi
149
  echo "$PRINTK" >/proc/sys/kernel/printk
150
  return $err
151
}
152
 
153
# ===========================================================
154
# live module functions
155
# ===========================================================
156
 
157
# Create module
158
# call mksquashfs with apropriate arguments
159
# $1 = directory which will be compressed to squashfs module
160
# $2 = output .mo file
161
# $3 = optional -keep-as-directory argument
162
#
163
create_module()
164
{
165
   mksquashfs $1 $2 $3 >/dev/null
166
   if [ $? -ne 0 ]; then return 1; fi
167
   chmod oga-x $2 # remove execute attrib
168
}
169
 
170
# Mount .mo module to destination directory
171
# $1 = path to .mo livecd compressed module
172
# $2 = destination folder
173
#
174
mount_module()
175
{
176
   mount -t squashfs -o loop,ro $1 $2
177
}
178
 
179
# Insert a directory tree $2 to an union specified by $1
180
# Top-level read-write branch is specified by it's index 0
181
# $1 = union absolute path (starting with /)
182
# $2 = path to data directory
183
#
184
union_insert_dir()
185
{
186
   unionctl $1 --add --after 0 --mode ro $2
187
}
188
 
189
# List all modules in all directories (base, modules, optional)
190
# and filter out unneeded optional modules (not specified by load= kernel parameter)
191
# $1 = root directory of mounted DATAdir
192
#
193
list_modules()
194
{
195
   LOAD="`cmdline_value load`"
196
   ls -A1d $1/*.mo $1/*/*.mo 2>/dev/null | while read LINE; do
197
      MODNAME="`basename $LINE .mo`"
198
      if [ "$LOAD" != "*" -a "`echo $LINE | grep optional`" != "" -a "`echo $LOAD | egrep \"(^|,)$MODNAME(\\\$|,)\"`" = "" ]; then continue
199
        else echo $LINE; fi
200
   done
201
}
202
 
203
# Insert one single .mo module to the union
204
# $1 = union absolute path (starting with /)
205
# $2 = module.mo full path
206
# $3 = destination folder, where images will be mounted to
207
#
208
union_insert_module()
209
{
210
   TARGET="$3/`basename $2`"
211
   while [ -e $TARGET ]; do TARGET=$TARGET.X; done
212
   mkdir -p $TARGET
213
   mount_module $2 $TARGET
214
   if [ $? -ne 0 ]; then echo "can't read module data"; return 1; fi
215
   union_insert_dir $1 $TARGET; 
216
}
217
 
218
# Insert all .mo modules, in $2 directory and subdirectories, to the union
219
# $1 = union absolute path (starting with /)
220
# $2 = LiveCD data dir (with directories /base, /modules, etc.)
221
# $3 = destination folder, where images will be mounted to
222
#
223
union_insert_modules()
224
{
225
   list_modules $2 | while read MODULE; do
226
      echo " -> `basename $MODULE`"
227
      union_insert_module $1 $MODULE $3
228
   done
229
}
230
 
231
# Copy modules to RAM directory
232
# $1 = data directory
233
# $2 = target directory in RAM
234
#
235
copy_to_ram()
236
{
237
   cp -R $1/* $2
238
   if [ "$?" -ne 0 ]; then fatal "can't copy to RAM, not enough memory?"; fi
239
}
240
 
241
# Copy content of "rootcopy" directory on the CD to $2 (union, usually)
242
# $1 = source
243
# $2 = destination
244
#
245
copy_rootchanges()
246
{
247
   cp -a $1/rootcopy/* $2 2>/dev/null # could be empty
248
}
249
 
250
# ===========================================================
251
# discovery functions
252
# ===========================================================
253
 
254
# List all CD-ROMs
255
# by using /proc entries
256
#
257
list_cdrom_devices()
258
{
259
   if [ "`cmdline_parameter nocd`" != "" ]; then return 1; fi
260
   for CDDEVICE in `cat /proc/sys/dev/cdrom/info | head -n 3 | tail -n 1 | cut -d ":" -f 2`; do
261
      echo "/dev/$CDDEVICE"
262
   done
263
}
264
 
265
# List all partition devices
266
# take list of all partitions and output unique disks.
267
# Return empty result when nohd parameter was given.
268
#
269
list_partition_devices()
270
{
271
   if [ "`cmdline_parameter nohd`" != "" ]; then return 1; fi
272
   cat /proc/partitions | grep -v loop | sed -r "s/^[0-9[:space:]]+/\/dev\//" | grep /dev/
273
}
274
 
275
# List all disk devices
276
#
277
list_disk_devices()
278
{
279
   list_partition_devices | egrep -v "[0-9]"
280
}
281
 
282
# List all block devices
283
#
284
list_block_devices()
285
{
286
   list_cdrom_devices
287
   list_partition_devices
288
}
289
 
290
# Try to mount all disks, partitions and cdroms and Find where the LiveCD is.
291
# If LiveCD found in the device, echo dirname of it's directory,
292
# and leave the device mounted. Mounting is not ro, but without any argument.
293
# $1 = directory where devices will be mounted
294
# added: mount $NFSROOT to /$1/nfs if NFSROOT is set. and search there for LiveCD
295
#
296
find_live_data_dir()
297
{
298
   if [ "$NFSROOT" != "" ]; then 
299
      DIR="/$1/nfs"
300
      mkdir -p $DIR
301
      mount -t nfs -o nolock,ro,rsize=8192,wsize=8192,hard,intr $NFSROOT $DIR
302
      FOUND=`ls -A1d $DIR/livecd.sgn $DIR/*/livecd.sgn 2>/dev/null | head -n 1`
303
      if [ "$FOUND" != "" ]; then 
304
         dirname "$FOUND"
305
      fi
306
   else
307
      list_block_devices | while read DEVICE; do
308
         DIR="/$1/`basename $DEVICE`"
309
         mount_device $DEVICE $DIR
310
         if [ $? -ne 0 ]; then continue; fi
311
         FOUND=`ls -A1d $DIR/livecd.sgn $DIR/*/livecd.sgn 2>/dev/null | head -n 1`
312
         if [ "$FOUND" = "" ]; then umount $DIR 2>/dev/null; rmdir $DIR 2>/dev/null
313
         else dirname "$FOUND"; return 1; fi
314
      done
315
   fi
316
}
317
 
318
# ===========================================================
319
# hardware preparation functions
320
# ===========================================================
321
 
322
# Create block devices to /dev described by /sys entries
323
#
324
create_block_devices()
325
{
326
   echolog "creating /dev entries for block devices"
327
   ls -A1d /sys/block/*/dev /sys/block/*/*/dev 2>/dev/null | grep -v loop | while read BLOCK; do
328
      DEVICE="/dev/`basename \`dirname $BLOCK\``"
329
      if [ ! -b $DEVICE ]; then
330
         MINORMAJOR="`head -n 1 $BLOCK | tr ':' ' '`"
331
         mknod $DEVICE b $MINORMAJOR
332
      fi
333
   done
334
}
335
 
336
# modprobe kernel modules needed for the LiveCD
337
#
338
modprobe_essential_modules()
339
{
340
   echolog "starting loop device support"
341
   modprobe_module loop max_loop=32
342
   echolog "starting cdrom filesystem support"
343
   modprobe_module isofs
344
   echolog "starting squashfs support"
345
   modprobe_module squashfs
346
   echolog "starting unionfs support"
347
   modprobe_module unionfs
348
   echolog "starting vfat support"
349
   modprobe_module nls_cp437
350
   modprobe_module nls_iso8859-1
351
   modprobe_module nls_iso8859-2
352
   modprobe_module vfat
353
   echolog "starting ntfs support"
354
   modprobe_module ntfs
355
   create_block_devices
356
}
357
 
358
 
359
# modprobe kernel modules needed for USB masstorage devices
360
#
361
modprobe_usb_sata_modules()
362
{
363
   echolog "starting USB and SATA support"
364
   modprobe_module ehci-hcd
365
   modprobe_module ohci-hcd
366
   modprobe_module uhci-hcd
367
   modprobe_module scsi_mod
368
 
369
   modprobe_module libata
370
   modprobe_module ahci
371
 
372
   modprobe_module sd_mod
373
   modprobe_module sr_mod
374
   modprobe_module usb-storage
375
   echolog "waiting for USB devices, max 9 seconds"
376
   sleep 9
377
   create_block_devices
378
}
379
 
380
# modprobe nfs kernel modules
381
# sunrpc.o needed?
382
#
383
modprobe_nfs_modules()
384
{
385
   echolog "starting nfs support"
386
   modprobe_module lockd
387
   modprobe_module nfs_acl
388
   modprobe_module nfs
389
}
390
 
391
# enable/disable CD autoejecting when unmounted
392
# $1 = 1|0 ... enable|disable
393
#
394
cd_autoeject()
395
{
396
   echo $1 >/proc/sys/dev/cdrom/autoeject
397
}
398
 
399
# Disable DMA if nodma boot parameter is present
400
#
401
setup_dma()
402
{
403
   if [ ! "`cmdline_parameter nodma`" = "" ]; then
404
      for DEVICE in `list_cdrom_devices` `list_disk_devices`; do
405
         echolog "setting DMA support off for $DEVICE"
406
         hdparm -d 0 $DEVICE
407
      done
408
   fi
409
}
410
 
411
# create correct fstab file in $1/etc/fstab and create apropriate
412
# mount directories in $1
413
# $1 = root directory (union)
414
#
415
activate_fstab()
416
{
417
   mkdir -p $1/etc
418
   FSTAB="$1/etc/fstab"
419
   echo "tmpfs            /                tmpfs       defaults         0   0" >$FSTAB
420
   echo "devpts           /dev/pts         devpts      gid=5,mode=620   0   0" >>$FSTAB
421
   echo "proc             /proc            proc        defaults         0   0" >>$FSTAB
422
 
423
   # now done by fstab-sync
424
   # list_cdrom_devices | while read DEVICE; do
425
   #   MOUNTDIR="/mnt/`basename $DEVICE`_cdrom"
426
   #   mkdir -p $1/$MOUNTDIR
427
   #   echo "$DEVICE $MOUNTDIR iso9660 noauto,users,exec 0 0" >>$FSTAB
428
   # done
429
 
430
   # now done in runlast
431
   # # should we auto mount all found devices?
432
   # if [ "`cmdline_parameter automount`" ]; then
433
   #    MOUNTOPT="auto,users"
434
   # else
435
   #    MOUNTOPT="noauto,users,ro"
436
   # fi
437
 
438
   # list_partition_devices | while read DEVICE; do
439
   #    unset REMOVABLE; DEV="`basename $DEVICE`"; DEV0="`echo $DEV | cut -b 1-3`"
440
   #    if [ "`cat /sys/block/$DEV0/removable`" != "0" ]; then
441
   #      REMOVABLE="_removable"
442
   #   fi
443
 
444
   #   # skip this device if mountpoint exists
445
   #   MOUNTDIR="/mnt/$DEV$REMOVABLE"
446
   #   if [ -d "$1/$MOUNTDIR" ]; then continue; fi
447
 
448
   #   # try to mount the device and unmount it. If OK, we can add it to fstab
449
   #   mount_device "$DEVICE" "$1/$MOUNTDIR"
450
   #   umount "$1/$MOUNTDIR" 2>/dev/null
451
   #   if [ $? -eq 0 ]; then
452
   #      # noauto,nousers (default)
453
   #      echo "$DEVICE $MOUNTDIR auto $MOUNTOPT,suid,dev,exec 0 0" >>$FSTAB
454
   #   else # remove empty directory
455
   #      rmdir "$1/$MOUNTDIR" 2>/dev/null
456
   #   fi
457
   # done
458
 
459
   # search for SWAP done later in /etc/rc.sysinit
460
   # fdisk -l 2>/dev/null | grep -i "Linux swap" | egrep "^/dev/" \
461
   #   | cut -f 1 -d " " | sed -r "s/(.+)/\\1 swap swap defaults 0 0/" >>$FSTAB
462
 
463
   # now done by fstab-sync
464
   # echo "/dev/fd0 /mnt/floppy auto noauto,users,suid,dev,exec 0 0" >>$FSTAB
465
   # mkdir -p $1/mnt/floppy
466
}