On Wed, 16 Sep 2009 14:56:12 +0000, emmel wrote:
> OK, I've managed to shoot myself in the foot. I /accidentally/ run
> mkinitrd with the wrong (read: none) parameters. Problem is that I'm
> running with encrypted file systems, including root.
> So I though I'd boot the system with some rescue system (tried
> an old Knoppix, then used a Slack 12.2 DVD lying around), and rerun
> mkinitrd with the right parameters. Except that it doesn't seem to work.
> The kernel panics, telling me that the VFS couldn't access the root file
> system...
> Call it a hunch, but that might have something to do with the
> error messages mkinitrd threw at me. Something about cp not knowing the
> --parents parameter, which it should according to the man page.
> Any suggestions welcome. I don't really want to have to
> reinstall the system or anything, but at the moment I'm fresh out of
> ideas. Help?
>
> TIA
>
You can make your own initrd, which can function as a more complete
startup environment. The default Slackware initrd implementation is
very lean and minimalist. It is designed to start your system, when it
is not broken. The benefit of a larger initrd is that you can build it
with the fixup tools you might need already installed. I have a "hybrid"
initrd- it uses mainly official slackware packages, but with a few tools
still provided by the busybox toolset. Also, I manually removed some
documentation files (multi-language, IIRC), and that reduced the space
required somewhat.
Recently, I have verified that hibernate/resume is now working correctly,
when system state saved to encrypted swap. IMO, having the ability to
suspend/hibernate is an element for portable systems. Encryption is
also essential, IMO, and that was already working. Now the two are
working together!
The remainder of this post has some technical details...
My initrd, as built for Slackware 12.2 includes these official Slackware
packages:
aaa_base-12.2.0-noarch-1
aaa_elflibs-12.2.0-i486-1
aaa_terminfo-5.6-noarch-1
bash-3.1.017-i486-2
bzip2-1.0.5-i486-1
coreutils-6.12-i486-1
cpio-2.5-i486-3
cryptsetup-1.0.5-i486-4
device-mapper-1.02.28-i486-1
devs-2.3.1-noarch-25
dialog-1.1_20070930-i486-1
e2fsprogs-1.41.3-i486-1
elvis-2.2_0-i486-2
etc-12.2-noarch-1
findutils-4.2.31-i486-1
glibc-solibs-2.7-i486-17
gnupg-1.4.9-i486-1
grep-2.5.3-i486-1
gzip-1.3.12-i486-1
libgcrypt-1.4.0-i486-2
libgpg-error-1.6-i486-3
lvm2-2.02.40-i486-1
mdadm-2.6.4-i486-1
module-init-tools-3.5-i486-1
pkgtools-12.1.0-noarch-7
procps-3.2.7-i486-2
readline-5.2-i486-3
sed-4.1.5-i486-1
tar-1.16.1-i486-1
util-linux-ng-2.14.1-i486-1
which-2.16-i486-1
It includes the busybox toolset (as included with Slackware 12.2's
mkinitrd), provides these commands:
$ find . -type l -printf "%l\t%l\n"
../usr/bin/[[ ../../bin/busybox
../usr/bin/wget ../../bin/busybox
../usr/bin/unzip ../../bin/busybox
../usr/bin/unlzma ../../bin/busybox
../usr/bin/time ../../bin/busybox
../usr/bin/openvt ../../bin/busybox
../usr/bin/lzmacat ../../bin/busybox
../usr/bin/loadfont ../../bin/busybox
../usr/bin/killall ../../bin/busybox
../usr/bin/deallocvt ../../bin/busybox
../usr/bin/cmp ../../bin/busybox
../usr/bin/clear ../../bin/busybox
../usr/bin/chvt ../../bin/busybox
../usr/bin/ar ../../bin/busybox
../bin/pidof busybox
../bin/mktemp busybox
../bin/ping busybox
../bin/chattr busybox
../bin/dumpkmap busybox
../bin/lsattr busybox
../bin/pipe_progress busybox
../bin/usleep busybox
../sbin/watchdog ../bin/busybox
../sbin/syslogd ../bin/busybox
../sbin/switch_root ../bin/busybox
../sbin/route ../bin/busybox
../sbin/reboot ../bin/busybox
../sbin/poweroff ../bin/busybox
../sbin/loadkmap ../bin/busybox
../sbin/klogd ../bin/busybox
../sbin/init ../bin/busybox
../sbin/ifconfig ../bin/busybox
../sbin/halt ../bin/busybox
../sbin/freeramdisk ../bin/busybox
../linuxrc.busybox bin/busybox
And it includes the gzipped kernel modules associated with my kernel
(2.6.30.6):
$ du -sh lib/modules/2.6.30.6-smp-dm-m-1/
32M lib/modules/2.6.30.6-smp-dm-m-1/
And the total size of the initrd is 79M.
The other key component is the startup script, initrd. Here is my startup
script (Note the disclaimers to use at your own risk, per the provisions
of the General Public License, GPL):
<begin source code, file: init):
#!/bin/bash
#
# Project Name: dm-live
#
# Program Name: /init
# File Version: 0.0.1
# First Version: 2007-11-29
# Last Change: 2009-09
# : 2007-12-03
#
# Copyright (C) 2007 Douglas D. Mayne
#
# This program is licensed under the General Public License. See this file
# for terms and conditions:
http://www.gnu.org/licenses/gpl.txt
#
# Purpose: The Linux kernel executes "init" as PID 1 at boot. This "init"
# is designed to be loaded into a ramfs where it will make final preparation
# for the real root filesystem. When the root filesystem is ready, this program
# will transfer control to the "real" init on the root filesystem. The startup
# environment for the initrd (as built by me) includes bash, various utilities,
# associated libraries, and all of the kernel modules (gzipped). This program
# in combination with the working environment will allow the user to setup a
# root file system which uses any of the device mapper kernel modules, etc.
#
# Misc. Notes:
# 1. The working environment can also be used as a standalone minimal
# working environment where various kernel module can be loaded and misc.
# system maintenance tasks can be performed: partitions formatted, disk
# images loaded, etc. To use this environment, append to grub's kernel
# specification with the parameter:
#
# rdinit=/bin/bash
#
# Or provide the parameter as appropriate for the bootloader you use,
# if you are not using the grub loader.
#
# 2. The working environment has the following hardware/platform
# requirements:
#
# Minimum CPU: i686
# Miniman RAM: 128M
#
# 3. I setup the working environment with this kernel and its associated
# modules as shown below:
#
# kernel-generic-smp-2.6.23.9_smp-i686-1.tgz 2007-11-28 (*)
# kernel-modules-2.6.23.9-i486-1.tgz 2007-11-28 (**)
#
# (*) The kernel is loaded by the bootloader. It is not a component
# of the initrd itself.
# (**) The kernel modules were gzipped and module dependancies regenerated
# prior to being moved to the initrd (/lib/modules/2.6.23.9-smp)
#
# End Misc. Notes.
#
# Begin Source Code and Comments --
#
# /init for initrd, using switch_root transfer mechanism
#
REF_DIR=dm-live
PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
export PATH
XDEBUG=0
REAL_INIT=sbin/init
MIN_INIT_MEM_FREE=73728
START_DATE=$( date +"%Y-%m-%d.%H%M%S")
KV=$(uname -r)
#Script to use: Load kernel modules
LKM=/${REF_DIR}/misc/man_modprobe.scr
KM=/modules.init
RKMD=lib/modules/${KV}
USER_VARS=/user.inp
[ -e $USER_VARS ] && . $USER_VARS
#
# Initial assumptions
#
# code construct below is a makeshift "try" block
# continue on loop below indicates an error, break is good
#
[ ${FLAG_CHOWN_INITRD:=0} -ne 0 ] && chown root.root -R /
for TRY1 in 0 1;do
[ $TRY1 -ne 0 ] && continue
#
# Includes
#
EF=0
for i in tmpfile yesno check_rw age_km devname_majmin;do
j=/${REF_DIR}/misc/${i}.bash
if [ ! -e "$j" ];then
echo "Error: $j is a required file and is not found."
echo "- exiting."
EF=1
else
. $j
fi
done
if [ $EF -ne 0 ];then
echo "Error: A required file is not found."
echo "- exiting."
continue
fi
#
# Allocate some temp files for working environment
#
for i in $(seq 0 10);do
T[${i}]=$(tmpfile)
EF=0
[ ! -e ${T[${i}]} ] && EF=1 && break
done
if [ $EF -ne 0 ];then
echo "Error: Temp files cannot be allocated."
echo "- exiting."
continue
else
LOG=${T[0]}
[ $XDEBUG -ne 0 ] && echo "Status: using temp log file: $LOG"
fi
break
done
if [ $TRY1 -ne 0 ];then
echo "Startup failed due to problem with environment."
[ $XDEBUG -ne 0 ] && /bin/bash
echo "Probably press CTL-ALT-DEL to avoid kernel panic."
read
exit 1
fi
#
# Main try loop
#
# code construct below is a makeshift "try" block
# continue on loop below indicates an error, break is good
#
for RV in 0 1;do
[ $RV -ne 0 ] && continue
echo "${START_DATE}: Welcome to dm-live, init by Douglas Mayne" >$LOG
echo "Status: This is version: $(cat ${REF_DIR}/VERSION)" >>$LOG
echo "Status: Using kernel $KV" >>$LOG
#
# Begin by mounting proc
#
[ ! -d /proc ] && mkdir /proc
mount -n proc /proc -t proc
[ ! -d /sys ] && mkdir /sys
mount -n sysfs /sys -t sysfs
echo 0x0100 > /proc/sys/kernel/real-root-dev
[ ! -d /tmpfs ] && mkdir /tmpfs
mount tmpfs /tmpfs -t tmpfs
# mount -n tmpfs /tmpfs -t tmpfs
mkdir tmpfs/rw_dev
mkdir tmpfs/rw_lp
mkdir tmpfs/ro_dev
mkdir tmpfs/ro_lp
mkdir tmpfs/root
#
# Load kernel modules
#
if [ -x $LKM ]; then
echo "Status: Loading kernel modules as specified in file, $KM" | tee -a $LOG
$LKM $KM
[ ${SLEEP_USB:=0} -ne 0 ] && sleep $SLEEP_USB
fi
#
# Make sure device mapper snapshot is loaded, reinit "local" /dev/mapper
#
modprobe dm-snapshot
rm -fr /dev/mapper && mkdir /dev/mapper && dmsetup mknodes
[ ! -e /dev/mapper/control ] && dmsetup ls >/dev/null
if [ -e /dev/mapper/control ];then
echo "Status: /device/mapper/control exists." >>$LOG
else
echo "Error: /device/mapper/control could not initialized. Exiting." | tee -a $LOG
continue
fi
#
# Low memory check
#
# Check memory and get value of available swap...
# swap may be used to increase tmpfs max allocation in future versions of this script
#
T6=${T[6]}
cat /proc/meminfo >$T6
MEM_TOTAL=$(cat $T6 | grep "MemTotal:" | sed -e 's/^.*: *//' -e 's/ kB$//')
INIT_MEM_FREE=$(cat $T6 | grep "MemFree:" | sed -e 's/^.*: *//' -e 's/ kB$//')
SWAP_TOTAL=$(cat $T6 | grep "SwapTotal:" | sed -e 's/^.*: *//' -e 's/ kB$//')
rm $T6
if [ $INIT_MEM_FREE -lt $MIN_INIT_MEM_FREE ];then
clear
head -3 <$LOG
echo "Warning: Your system reports current free memory: " $INIT_MEM_FREE
echo "- that amount is below the minimum tested."
yesno "Proceed anyway, yes or (no) ? " no
if [ $? -eq 0 ];then
echo "Status: User elects to abort startup (low memory)."
continue
else
echo "Status: User elects to continue startup (low memory)." | tee -a $T6
fi
fi
printf "Status: Initial free memory: %d kB\n" $INIT_MEM_FREE | tee -a $T6
# printf "Status: Kernel command line args: %s\n" $(cat /proc/cmdline) | tee -a $T6
#
# Parse kernel command line
#
for CLA in $(cat /proc/cmdline);do
case $CLA in
resume=*) RESUME_DEV=$(echo $CLA | cut -f2 -d=)
;;
esac
done
#
# First Message
#
clear
cat $T6 >>$LOG
cat $LOG
cat /${REF_DIR}/misc/MESSAGE.1
read -n1 -s
#
# hack in GPG based encryption : prelim
# hack script knows what to do to read encrypted messages which explain
# how to setup device mapper objects. If using encrypted root, then
# make sure that variable is set appropriately: ROOT_DEV=/dev/mapper/...
#
if [ $FLAG_USING_ENC -eq 1 ];then
./hack2
if [ $? -eq 0 ];then
printf "Status: Good result from hack script...\n" | tee -a $LOG
else
printf "Check some error entering passphrase, etc.\n"
printf "...dropping to a shell\n"
/bin/bash
fi
else
#
# Allow direct user manipulation of environment (using bash shell from here)
#
/bin/bash
fi
#
# Upon return, accept user input from file
#
[ -e $USER_VARS ] && . $USER_VARS
#
# Resume?
#
if [ ! -z $RESUME_DEV ];then
RD=$(devname_to_majmin $RESUME_DEV)
[ ! -z $RD ] && echo $RD >/sys/power/resume
fi
#
# Defaults
#
ROOT_FS=${ROOT_FS:=xfs}
ROOT_DEV=${ROOT_DEV:=/dev/mapper/top}
ROOT_FMP=${ROOT_FMP:=/tmpfs/root}
mount -o rw -t $ROOT_FS $ROOT_DEV $ROOT_FMP
if [ ! -r ${ROOT_FMP}/${REAL_INIT} ]; then
echo "Error: real init is not found. Exiting."
continue
else
check_rw $ROOT_FMP $REF_DIR $START_DATE
if [ $? -ne 0 ];then
echo "Error: real root filesystem is not RW. Exiting."
continue
fi
fi
#
# Wipe out device mapper at target, then reinitialize with current "local"
#
(cd ${ROOT_FMP}/dev && rm -fr mapper);
(cd /dev/ && tar -cpf - mapper) | (cd ${ROOT_FMP}/dev && tar -xvf -)
#
# Fixup real root's fstab: assume for now that user has already done this to his specs.
#
#
# Save kernel modules
#
yesno "Copy kernel modules to root, (yes) or no ? " yes
if [ $? -ne 0 ];then
[ -e ${ROOT_FMP}/${REF_DIR}/${RKMD} ] && rm -fr ${ROOT_FMP}/${REF_DIR}/${RKMD}
(cd / && tar -cpf - $RKMD) | (cd ${ROOT_FMP}/${REF_DIR} && tar -xvf -)
if [ -e ${ROOT_FMP}/${REF_DIR}/${RKMD} ];then
echo "Status: Saved kernel modules to new root: ${REF_DIR}/${RKMD}" | tee -a $LOG
else
echo "Status: Check some problem saving kernel modules to new root: ${REF_DIR}/${RKMD}" | tee -a $LOG
fi
if [ -e ${ROOT_FMP}/lib/modules ];then
[ -d ${ROOT_FMP}/${RKMD} ] && age_km ${ROOT_FMP}/${RKMD} ${T[6]}
[ -L ${ROOT_FMP}/${RKMD} ] && rm ${ROOT_FMP}/${RKMD}
if [ ! -e ${ROOT_FMP}/${RKMD} ];then
(cd ${ROOT_FMP}/lib/modules && ln -s /${REF_DIR}/${RKMD} $KV)
if [ $? -eq 0 ];then
echo "Status: Created symbolic link to kernel modules on new root." | tee -a $LOG
else
echo "Status: Check some problem creating symbolic link to kernel modules on new root." | tee -a $LOG
fi
fi
else
echo "Status: Check some problem on new root: /lib/modules does not exist" | tee -a $LOG
fi
else
echo "Status: User elects not to save kernel modules at new root." | tee -a $LOG
fi
#
# Make temp log the final log.
# Available at /initrd/tmp/startup.log when boot completes.
#
if [ ${FLAG_SAVE_STARTUP_LOGS:=1} -ne 0 ];then
LOGF=${ROOT_FMP}/${REF_DIR}/${START_DATE}/startup.log
mkdir -p $(dirname $LOGF)
mv $LOG $LOGF
DMESG=${ROOT_FMP}/${REF_DIR}/${START_DATE}/dmesg
dmesg >$DMESG
fi
if [ ${FLAG_SET_REF_PERM:=1} -ne 0 ];then
(cd ${ROOT_FMP}/${REF_DIR} && for i in $(find . -type d);do
chown root:root $i
chmod 755 $i
done)
fi
mount -o remount -o ro -t $ROOT_FS $ROOT_DEV $ROOT_FMP
umount /proc
umount /sys
#
# Remember: There is no need to clean up ourselves. The switch_root function
# deletes everything in ramfs just before the switch. This frees the memory
# buffers, etc.
#
exec switch_root $ROOT_FMP /${REAL_INIT} $@
done
#
# Never get here on good startup
#
if [ $RV -ne 0 ];then
echo "Startup failed..."
[ $XDEBUG -ne 0 ] && /bin/bash
echo "Probably press CTL-ALT-DEL to avoid kernel panic."
read
fi
exit $RV
<end source code>
--
Douglas Mayne