Commit 94a298ea authored by Mike Hibler's avatar Mike Hibler
Browse files

Support for two new "loadinfo" options BIOSDISK and CONSOLE.

BIOSDISK is passed through from the DB bootdisk_bios_id and is used to
set the GRUB root device (in situations where grub disagrees with freebsd
or linux about the primary boot device).

CONSOLE is used to set the console device for an image's boot loader and
kernel. Choices are "null", "vga", "sio", (the historic choices) along
with "vid" (same as vga), "sio1" (same as sio), "sio2", "sio3", and "sio4".
The FreeBSD slicefix script works for FreeBSD 9.x and above as well as
Fedora, Ubuntu and CentOS. It will work with FreeBSD 8.x and earlier if
the in-image /boot/loader is fixed to avoid hanging while polling a UART.

This should be used in conjuction with one of the new
pxeboot.emu-{null,vga,sio1,sio2,sio3,sio4} versions of pxeboot which
will customize the FreeBSD kernel in the frisbee and admin MFSes.

The console can be set via the "console_type" node_ or node_type_attribute
tables in the DB. The "pxe_boot_path" attribute should also be set to
reflect the appropriate /tftpboot/pxeboot.emu-* version for the console type

Note that by default (no console_type or pxe_boot_path), nodes will continue
to use the default /tftpboot/pxeboot.emu which can either be linked to one
of the above new version, or could just be the current pxeboot which will
not mess with the console settings.

Finally, note that I made the changes to linux/slicefix, but they are only
for FreeBSD images and are untested. The Linux grub-based pxeboot as well
as linux_slicefix would still need to be changed for this to work under the
"Linux MFS". Task for another day as I already spent waaaaay to long on this.
parent 18eed50a
......@@ -169,6 +169,7 @@ loadone() {
PART=""
PARTOS=""
DISK=""
BIOSDISK=""
ZFILL=""
ACPI=""
ASF=""
......@@ -178,6 +179,7 @@ loadone() {
VGAONLY=""
IMAGEID=""
KEEPALIVE=""
CONSOLE=""
for parm in $_LOADINFO; do
case $parm in
......@@ -186,6 +188,7 @@ loadone() {
PARTOS=*|\
SERVER=*|\
DISK=*|\
BIOSDISK=*|\
ZFILL=*|\
ACPI=*|\
NOCLFLUSH=*|\
......@@ -194,7 +197,8 @@ loadone() {
PREPARE=*|\
VGAONLY=*|\
IMAGEID=*|\
KEEPALIVE=*)
KEEPALIVE=*|\
CONSOLE=*)
# XXX need to parse better, eval is dangerous!
eval $parm
;;
......@@ -218,6 +222,7 @@ loadone() {
VGAONLY=${VGAONLY:-'unknown'}
MBRVERS=${MBRVERS:-'1'}
PREPARE=${PREPARE:-'0'}
CONSOLE=${CONSOLE:-'unknown'}
#
# XXX If KEEPALIVE is not explicitly set, attempt to intuit a value.
......@@ -478,6 +483,8 @@ loadone() {
export SLICEFIX_ASF=$ASF
export SLICEFIX_NOCLFLUSH=$NOCLFLUSH
export SLICEFIX_VGAONLY=$VGAONLY
export SLICEFIX_CONSOLE=$CONSOLE
export SLICEFIX_BIOSDISK=$BIOSDISK
$BINDIR/slicefix $PART $DISK
echo "`date`: Image #$_NUM load complete"
return 0
......
#!/bin/sh
#
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# Copyright (c) 2000-2013 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -58,6 +58,10 @@ esac
#
# Handle pseudo arguments in the environment.
#
#
# Explicitly enable/disable ACPI (BSD only)
#
ACPI=${SLICEFIX_ACPI:-'unknown'}
case $ACPI in
0|no|NO)
......@@ -71,6 +75,9 @@ case $ACPI in
;;
esac
#
# Explicitly enable/disable ASF management on Broadcom (BSD only)
#
ASF=${SLICEFIX_ASF:-'unknown'}
case $ASF in
0|no|NO)
......@@ -84,6 +91,9 @@ case $ASF in
;;
esac
#
# Explicitly enable/disable use of clflush instruction (BSD only)
#
NOCLFLUSH=${SLICEFIX_NOCLFLUSH:-'unknown'}
case $NOCLFLUSH in
0|no|NO)
......@@ -97,26 +107,65 @@ case $NOCLFLUSH in
;;
esac
VGAONLY=${SLICEFIX_VGAONLY:-'unknown'}
case $VGAONLY in
0|no|NO)
VGAONLY=no
#
# Explicitly set the BIOS boot ID for Grub (Linux only)
#
BIOSDISK=$SLICEFIX_BIOSDISK
if [ -n "$BIOSDISK" ]; then
case $BIOSDISK in
0x8[0123456789])
;;
*)
echo "WARNING: unknown BIOS disk setting \"$BIOSDISK\" ignored"
BIOSDISK=
;;
esac
fi
#
# Find out what our console should be:
# if $CONSOLE is set and valid, use that
# ow if $VGAONLY is set, console is "vga"
# ow console is "sio1"
# NOTE: we change "sio" to "sio1" and "vga" to "vid" for convenience later
#
CONSOLE=${SLICEFIX_CONSOLE:-'unknown'}
case $CONSOLE in
sio)
CONSOLE=sio1
;;
1|yes|YES)
VGAONLY=yes
vga)
CONSOLE=vid
;;
sio1|sio2|sio3|sio4|null|unknown)
;;
*)
# XXX check the MFS filesystem
if [ -r $ETCDIR/isvgaonly ]; then
VGAONLY=yes
else
VGAONLY=unknown
fi
echo "WARNING: unknown console type \"$CONSOLE\", assuming \"sio1\""
CONSOLE=sio1
;;
esac
if [ $CONSOLE = "unknown" ]; then
VGAONLY=${SLICEFIX_VGAONLY:-'unknown'}
case $VGAONLY in
0|no|NO)
;;
1|yes|YES)
CONSOLE=vid
;;
*)
if [ -r $ETCDIR/isvgaonly ]; then
CONSOLE=vid
fi
;;
esac
fi
if [ $CONSOLE = "unknown" ]; then
echo "WARNING: console type not set, assuming \"sio1\""
CONSOLE=sio1
fi
#
# ...or the filesystem
# Handle pseudo-arguments in the filesystem
#
if [ -r $ETCDIR/isflash ]; then
FLASHBOOT=1
......@@ -142,6 +191,19 @@ islocalized() {
return 1;
}
#
# Get the last setting of a loader variable from the list of standard files
#
getloadervar() {
_var=$1
_mnt=$2
_flist="$_mnt/boot/defaults/loader.conf $_mnt/boot/device.hints $_mnt/boot/loader.conf $_mnt/boot/loader.conf.local"
_last=`grep "^${_var}=" $_flist 2>/dev/null | tail -1`
_val=`echo ${_last#*=} | sed -e 's/^"//' -e 's/"$//'`
echo $_val
}
dofreebsd() {
#
# ARGH! FreeBSD 5, which primarily uses UFS2, internally converts
......@@ -310,19 +372,35 @@ dofreebsd() {
fi
#
# If node doesn't have a serial port, make sure comconsole is not set!
# See if we need to fix console related settings.
#
if [ $VGAONLY = "yes" ]; then
grep "^console=\"comconsole\"" /mnt/boot/loader.conf >/dev/null 2>&1
case $? in
0)
curconsole=`getloadervar console /mnt`
case $CONSOLE in
null|vid)
if [ "$curconsole" != "${CONSOLE}console" ]; then
changecons=1
fixit=1
;;
*)
;;
esac
fi
fi
;;
sio*)
if [ "$curconsole" != "comconsole" ]; then
# not comconsole, fix it
changecons=1
fixit=1
else
# see if the com port has changed
unit=`expr ${CONSOLE#sio} - 1`
flags=`getloadervar hint.uart.$unit.flags /mnt`
if [ -z "$flags" ]; then
flags=`getloadervar hint.sio.$unit.flags /mnt`
fi
if [ "$flags" != "0x10" ]; then
changecons=1
fixit=1
fi
fi
;;
esac
# check to see if we need to download any postconfig scripts:
doosconfig=0
......@@ -448,7 +526,7 @@ dofreebsd() {
on="en"
fi
echo " ${on}abling ACPI"
sed -E -i $lcbak -e "/[Aa][Cc][Pp][Ii]/d" /mnt/boot/loader.conf || {
sed -E -i "$lcbak" -e "/[Aa][Cc][Pp][Ii]/d" /mnt/boot/loader.conf || {
echo "Failed to update /boot/loader.conf"
umount $rootdev
return 1
......@@ -477,7 +555,7 @@ EOF2
on="en"
fi
echo " ${on}abling ASF"
sed -E -i $lcbak -e "/[Aa][Ss][Ff]/d" /mnt/boot/loader.conf || {
sed -E -i "$lcbak" -e "/[Aa][Ss][Ff]/d" /mnt/boot/loader.conf || {
echo "Failed to update /boot/loader.conf"
umount $rootdev
return 1
......@@ -497,16 +575,101 @@ EOF2
fi
#
# Remove console="comconsole"
# Fix up console.
# null and vga are easy, just set console={null,vid}console
# Serial port requires tweaking/adding hints.
#
if [ $changecons -eq 1 ]; then
echo " disabling comconsole"
sed -E -i $lcbak -e "/^console=\"comconsole\"/d" /mnt/boot/loader.conf || {
echo " setting console to $CONSOLE"
# get rid of any existing console setting
sed -E -i "$lcbak" -e "/^console=/d" /mnt/boot/loader.conf || {
echo "Failed to update /boot/loader.conf"
umount $rootdev
return 1
}
lcbak=""
case $CONSOLE in
null|vid)
cname="${CONSOLE}console"
;;
sio1)
cname="comconsole"
unit=0
port=0x3F8
irq=4
;;
sio2)
cname="comconsole"
unit=1
port=0x2F8
irq=3
;;
sio3)
cname="comconsole"
unit=2
port=0x3E8
irq=5
;;
sio4)
cname="comconsole"
unit=3
port=0x2E8
irq=9
;;
esac
# spit out the name
cat <<EOF1 >>/mnt/boot/loader.conf
console="$cname"
EOF1
# get rid of any comconsole excesses
if [ "$curconsole" = "comconsole" ]; then
sed -E -i "$lcbak" -e "/^comconsole/d" -e "/^hint.$drv./d" /mnt/boot/loader.conf
fi
# now deal with comconsole settings
if [ "$cname" = "comconsole" ]; then
#
# Determine driver name:
# if /boot/device.hints does not exist, assume "sio" (pre 5?)
# ow, if hint.uart.0.at exists, it is "uart" (8+)
# ow, if hint.sio.0.at exists, it is "sio" (5-7)
#
drv=none
at=`getloadervar hint.uart.0.at /mnt`
if [ -n "$at" ]; then
drv=uart
else
at=`getloadervar hint.sio.0.at /mnt`
if [ -n "$at" ]; then
drv=sio
fi
fi
# XXX should be passed in
speed=115200
# only change things if there were hints found
if [ $drv != "none" ]; then
# put in the new info
cat <<EOF2 >>/mnt/boot/loader.conf
comconsole_port="$port"
comconsole_speed="$speed"
hint.$drv.0.flags="0x0"
hint.$drv.1.flags="0x0"
hint.$drv.2.flags="0x0"
hint.$drv.3.flags="0x0"
hint.$drv.$unit.at="isa"
hint.$drv.$unit.port="$port"
hint.$drv.$unit.irq="$irq"
hint.$drv.$unit.flags="0x10"
hint.$drv.$unit.disabled="0"
EOF2
fi
fi
fi
#
......@@ -520,7 +683,7 @@ EOF2
on="en"
fi
echo " ${on}abling use of CLFLUSH"
sed -E -i $lcbak -e "/clflush_disable/d" /mnt/boot/loader.conf || {
sed -E -i "$lcbak" -e "/clflush_disable/d" /mnt/boot/loader.conf || {
echo "Failed to update /boot/loader.conf"
umount $rootdev
return 1
......@@ -790,95 +953,145 @@ dolinux() {
cp $gconf $tgconf || {
echo "Cannot copy $fgconf, will change in place"
cp -p $gconf $gconf.preemulab
# XXX only do this if it appears that selinux is installed
if [ -e /mnt/etc/selinux/config ]; then
needfsck=1
fi
needfsck=1
tgconf=gconf
}
sed -i '' -e "s;\([br]oot=/dev\)/[hs]d.[0-7];\1/${ldisk}${part};" $tgconf || {
echo "Failed to update $fgconf"
}
# fix any (non-commented) boot=/root= lines
if grep -q '^[^#].*[br]oot=/dev' $tgconf 2>/dev/null; then
echo " fixing root (dev)"
sed -i '' -e "s;\([br]oot=/dev\)/[hs]d.[0-7];\1/${ldisk}${part};" $tgconf
fi
#
# Again, replace UUID if we have one and grub conf uses it already.
#
if [ -n "$RUUID" ]; then
sed -i '' -e "s;\([br]oot=\)UUID=[^ ]* ;\1UUID=$RUUID ;" $tgconf || {
echo "Failed to update UUIDs in $fgconf"
}
# Ditto for UUID if we have one and grub conf uses it
if [ -n "$RUUID" ] && \
grep -q '[br]oot=\)UUID=[^ ]* ' $tgconf 2>/dev/null; then
echo " fixing root (UUID)"
sed -i '' -e "s;\([br]oot=\)UUID=[^ ]* ;\1UUID=$RUUID ;" $tgconf
fi
#
# Tweak grub's notion of root.
# Note that grub's partition numbering is zero-based.
#
gdisk=`echo $dunit | sed -e 'y/abcdefgh/01234567/'`
gpart=`expr $part - 1`
#
# If we booted from a flash device we also have to further tweak
# grub's notion of root disk since the flash device will be "hd0".
# It appears that we do NOT have to update Linux's drive mapping.
# If BIOSDISK is set, we prefer that.
# Otherwise (for compat), we check FLASHBOOT.
# Otherwise, map from DISK.
#
if [ $FLASHBOOT -eq 1 ]; then
gdisk=`expr $gdisk + 1`
if [ -n "$BIOSDISK" ]; then
gdisk=`echo $BIOSDISK | sed -e 's/0x8\([0-9]\)/\1/'`
else
gdisk=`echo $dunit | sed -e 'y/abcdefghij/0123456789/'`
#
# If we booted from a flash device we also have to further
# tweak grub's notion of root disk since the flash device
# will be "hd0". It appears that we do NOT have to update
# Linux's drive mapping.
#
if [ $FLASHBOOT -eq 1 ]; then
gdisk=`expr $gdisk + 1`
fi
fi
# grub's partition numbering is zero-based.
gpart=`expr $part - 1`
# grub1
sed -i '' -e "s;root (hd[0-9],[0-9]);root (hd${gdisk},${gpart});" $tgconf || {
echo "Failed to update root in $fgconf"
}
if grep -q '^[^#].*root (hd[0-9],[0-9])' $tgconf 2>/dev/null; then
echo " fixing grub1 root"
sed -i '' -e "s;root (hd[0-9],[0-9]);root (hd${gdisk},${gpart});" $tgconf
fi
# grub2 (note 'part' and not 'gpart'; no -1 in grub2)
sed -i '' -e "s;set root='(hd[0-9],[^)]*)';set root='(hd${gdisk},${part})';" $tgconf || {
echo "Failed to update root in $fgconf"
}
if grep -q "^[^#].*set root='(hd[0-9],[^)]*)'" $tgconf 2>/dev/null; then
echo " fixing grub2 root"
sed -i '' -e "s;set root='(hd[0-9],[^)]*)';set root='(hd${gdisk},${part})';" $tgconf
fi
#
# Console. If there is no serial console, need to modify the
# grub config to use the vga only.
# Console.
# For vid or null, comment out terminal/serial lines.
# For sio[1-3], add:
# terminal --dumb --timeout=0 serial console
# serial --unit=N --speed=S
#
if [ $VGAONLY = "yes" ]; then
grep -E '^terminal.*serial' $tgconf >/dev/null 2>&1
case $? in
0)
echo " changing grub terminal to console"
sed -i '' -e "s;^terminal;#terminal;" $tgconf || {
echo "Failed to update terminal line in $fgconf"
}
echo "terminal --timeout=5 console" >> $tgconf
;;
*)
;;
esac
# Added by Hussam to disable the serial line defination
grep -E '^serial.*--speed' $tgconf >/dev/null 2>&1
case $? in
0)
echo " disabling serial line config in grub"
sed -i '' -e "s;^serial;#serial;" $tgconf || {
echo "Failed to update serial line in $fgconf"
}
;;
*)
;;
esac
echo " setting console to $CONSOLE"
case $CONSOLE in
null|vid)
# comment out any "serial" line
if grep -q '^serial' $tgconf 2>/dev/null; then
sed -i '' -e 's;^serial;#serial;' $tgconf
fi
# make sure the "terminal" line is correct
if grep -q '^terminal' $tgconf 2>/dev/null; then
tstr="terminal --timeout=5 console"
sed -i '' -e "s;^terminal.*;$tstr;" $tgconf
fi
# and fixup kernel/initrd command lines
if grep -q 'console=tty0 ' $tgconf 2>/dev/null; then
# already have console=tty0, get rid of any console=ttyS? clauses
sed -E -i '' -e 's;console=ttyS[^ ]+;;' $tgconf
else
# otherwise, replace any console=ttyS? clauses
sed -E -i '' -e 's;console=ttyS[^ ]+;console=tty0;' $tgconf
fi
grep -E "console=ttyS" $tgconf >/dev/null 2>&1
case $? in
0)
echo " changing grub kernel command to console"
sed -i '' -e 's;ttyS[^ ]*;tty0;' $tgconf || {
echo "Failed to update console in $fgconf"
}
;;
*)
;;
esac
fi
# take care of upstart getty process
# XXX cannot use .override as old version don't support it
getty="/mnt/etc/init/ttyS0"
if [ -e "$getty.conf" ]; then
mv $getty.conf $getty.conf.preemulab
fi
# or inittab
getty="/mnt/etc/inittab"
if [ -e "$getty" ]; then
cp -p $getty $getty.preemulab
sed -i '' -e 's/^S0/#S0/' $getty
fi
;;
sio*)
u=`expr ${CONSOLE#sio} - 1`
# XXX should be passed in
s=115200
# put back the "serial" line
sstr="serial --unit=$u --speed=$s"
if ! grep -q -- "^$sstr" $tgconf 2>/dev/null; then
sed -E -i '' -e "s;^#?serial.*;$sstr;" $tgconf
fi
# make sure the "terminal" line is correct
if grep -q '^terminal' $tgconf 2>/dev/null; then
tstr="terminal --dumb --timeout=0 serial console"
sed -i '' -e "s;^terminal.*;$tstr;" $tgconf
fi
# and fixup kernel/initrd command lines
if grep -q "console=ttyS[^ ]" $tgconf 2>/dev/null; then
# already have console=ttyS?, make sure it is correct
sed -E -i '' -e "s;console=ttyS[^ ]+;console=ttyS$u,$s;" $tgconf
# and remove console=tty0
sed -i '' -e 's;console=tty0;;' $tgconf
else
# otherwise, replace console=tty0
sed -i '' -e "s;console=tty0;console=ttyS$u,$s;" $tgconf
fi
# take care of upstart getty process
getty="/mnt/etc/init/ttyS0"
if [ -e "$getty.conf" ]; then
cp -p $getty.conf $getty.conf.preemulab
sed -E -i '' -e "s/ttyS. [0-9]+/ttyS$u $s/" $getty.conf
elif [ -e "$getty.conf.preemulab" ]; then
# we previously moved it out of the way
cp -p $getty.conf.preemulab $getty.conf
sed -E -i '' -e "s/ttyS. [0-9]+/ttyS$u $s/" $getty.conf
fi
# or inittab
getty="/mnt/etc/inittab"
if [ -e "$getty" ]; then
cp -p $getty $getty.preemulab
sed -E -i '' -e 's/^#S0/S0/' -e "s/ttyS. [0-9]+/ttyS$u $s/" $getty
fi
;;
esac
#
# If we had to change something, then move the new version into
......@@ -892,10 +1105,7 @@ dolinux() {
echo "Failed to update $fgconf"
mv $gconf.preemulab $gconf
}
# XXX only do this if it appears that selinux is installed
if [ -e /mnt/etc/selinux/config ]; then
needfsck=1
fi
needfsck=1
fi
rm -f $tgconf
fi
......@@ -1078,7 +1288,7 @@ dolinux() {
# the FS in an inconsistent state. So if we changed grub.conf,
# we must fsck the filesystem to clean up.
#
if [ $needfsck -ne 0 ]; then
if [ $needfsck -ne 0 -a -e /mnt/etc/selinux/config ]; then
echo -n " ensuring FS is consistent..."
e2fsck -yf $rootdev >/dev/null 2>&1
if [ $? -ne 0 ]; then
......
#!/bin/sh
#
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# Copyright (c) 2000-2013 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -72,6 +72,10 @@ fi
#
# Handle pseudo arguments in the environment.
#
#
# Explicitly enable/disable ACPI (BSD only)
#
ACPI=${SLICEFIX_ACPI:-'unknown'}
case $ACPI in
0|no|NO)
......@@ -85,6 +89,9 @@ case $ACPI in
;;
esac
#
# Explicitly enable/disable ASF management on Broadcom (BSD only)
#
ASF=${SLICEFIX_ASF:-'unknown'}
case $ASF in
0|no|NO)
......@@ -98,6 +105,9 @@ case $ASF in