diff options
author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2018-08-31 13:25:51 +0300 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2018-09-06 14:44:12 +0300 |
commit | ff075f6ee795a590b244d70a90cc312ba1f2d83d (patch) | |
tree | a617790bdbfdeef960665ba0242e1f0c93e5301a /meta-phosphor/recipes-phosphor/initrdscripts | |
parent | 3e4da38c127bb7e7641adc2fc41f4c33744cb918 (diff) | |
download | openbmc-ff075f6ee795a590b244d70a90cc312ba1f2d83d.tar.xz |
meta-phosphor: Move layer content from common/
Adopt a more conventional directory hierarchy. meta-phosphor is still
a _long_ way from suitable for hosting on yoctoproject.org but things
like this don't help.
(From meta-phosphor rev: 471cfcefa74b8c7ceb704cb670e6d915cf27c63b)
Change-Id: I3f106b2f6cdc6cec734be28a6090800546f362eb
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Diffstat (limited to 'meta-phosphor/recipes-phosphor/initrdscripts')
5 files changed, 850 insertions, 0 deletions
diff --git a/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-init.sh b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-init.sh new file mode 100644 index 000000000..62be89f03 --- /dev/null +++ b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-init.sh @@ -0,0 +1,426 @@ +#!/bin/sh + +fslist="proc sys dev run" +rodir=run/initramfs/ro +rwdir=run/initramfs/rw +upper=$rwdir/cow +work=$rwdir/work + +cd / +mkdir -p $fslist +mount dev dev -tdevtmpfs +mount sys sys -tsysfs +mount proc proc -tproc +if ! grep run proc/mounts +then + mount tmpfs run -t tmpfs -o mode=755,nodev +fi + +mkdir -p $rodir $rwdir + +cp -rp init shutdown update whitelist bin sbin usr lib etc var run/initramfs + +# To start a interactive shell with job control at this point, run +# getty 38400 ttyS4 + +findmtd() { + m=$(grep -xl "$1" /sys/class/mtd/*/name) + m=${m%/name} + m=${m##*/} + echo $m +} + +blkid_fs_type() { + # Emulate util-linux's `blkid -s TYPE -o value $1` + # Example busybox blkid output: + # # blkid /dev/mtdblock5 + # /dev/mtdblock5: TYPE="squashfs" + # Process output to extract TYPE value "squashfs". + blkid $1 | sed -e 's/^.*TYPE="//' -e 's/".*$//' +} + +probe_fs_type() { + fst=$(blkid_fs_type $1) + echo ${fst:=jffs2} +} + +# This fw_get_env_var is a possibly broken version of fw_printenv that +# does not check the crc or flag byte. +# The u-boot environment starts with a crc32, followed by a flag byte +# when a redundannt environment is configured, followed by var=value\0 sets. +# The flag byte for nand is a 1 byte counter; for nor it is a 1 or 0 byte. + +get_fw_env_var() { + # do we have 1 or 2 copies of the environment? + # count non-blank non-comment lines + # copies=$(grep -v ^# /etc/fw_env.config | grep -c [::alnum::]) + # ... we could if we had the fw_env.config in the initramfs + copies=2 + + # * Change \n to \r and \0 to \n + # * Skip to the 5th byte to skip over crc + # * then skip to the first or 2nd byte to skip over flag if it exists + # * stop parsing at first empty line corresponding to the + # double \0 at the end of the environment. + # * print the value of the variable name passed as argument + + envdev=$(findmtd u-boot-env) + if test -n $envdev + then + cat /dev/$envdev | + tr '\n\000' '\r\n' | + tail -c +5 | tail -c +${copies-1} | + sed -ne '/^$/,$d' -e "s/^$1=//p" + fi +} + +setup_resolv() { + runresolv=/run/systemd/resolve/resolv.conf + etcresolv=/etc/resolv.conf + + if test ! -e $etcresolv -a ! -L $etcresolv + then + mkdir -p ${runresolv%/*} + ln -s $runresolv $etcresolv + fi + if test ! -f $runresolv + then + cat /proc/net/pnp > $runresolv + fi + + return 0 +} + +try_tftp() { + # split into tftp:// host:port/ path/on/remote + # then spilt off / and then :port from the end of host:port/ + # and : from the beginning of port + + rest="${1#tftp://}" + path=${rest#*/} + host=${rest%$path} + host="${host%/}" + port="${host#${host%:*}}" + host="${host%$port}" + port="${port#:}" + + setup_resolv + + if test -z "$host" -o -z "$path" + then + debug_takeover "Invalid tftp download url '$url'." + elif echo "Downloading '$url' from $host ..." && + ! tftp -g -r "$path" -l /run/image-rofs "$host" ${port+"$port"} + then + debug_takeover "Download of '$url' failed." + fi +} + +try_wget() { + setup_resolv + + echo "Downloading '$1' ..." + if ! wget -O /run/image-rofs "$1" + then + debug_takeover "Download of '$url' failed." + fi +} + +debug_takeover() { + echo "$@" + test -n "$@" && echo Enter password to try to manually fix. + cat << HERE +After fixing run exit to continue this script, or reboot -f to retry, or +touch /takeover and exit to become PID 1 allowing editing of this script. +HERE + + while ! sulogin && ! test -f /takeover + do + echo getty failed, retrying + done + + # Touch /takeover in the above getty to become pid 1 + if test -e /takeover + then + cat << HERE + +Takeover of init requested. Executing /bin/sh as PID 1. +When finished exec new init or cleanup and run reboot -f. + +Warning: No job control! Shell exit will panic the system! +HERE + export PS1=init#\ + exec /bin/sh + fi +} + +rofs=$(findmtd rofs) +rwfs=$(findmtd rwfs) + +rodev=/dev/mtdblock${rofs#mtd} +rwdev=/dev/mtdblock${rwfs#mtd} + +# Set to y for yes, anything else for no. +force_rwfst_jffs2=y +flash_images_before_init=n +consider_download_files=y +consider_download_tftp=y +consider_download_http=y +consider_download_ftp=y + +rofst=squashfs +rwfst=$(probe_fs_type $rwdev) +roopts=ro +rwopts=rw + +image=/run/initramfs/image- +trigger=${image}rwfs + +init=/sbin/init +fsckbase=/sbin/fsck. +fsck=$fsckbase$rwfst +fsckopts=-a +optfile=/run/initramfs/init-options +optbase=/run/initramfs/init-options-base +urlfile=/run/initramfs/init-download-url +update=/run/initramfs/update + +if test -e /${optfile##*/} +then + cp /${optfile##*/} $optfile +fi + +if test -e /${optbase##*/} +then + cp /${optbase##*/} $optbase +else + touch $optbase +fi + +if test ! -f $optfile +then + cat /proc/cmdline $optbase > $optfile + get_fw_env_var openbmcinit >> $optfile + get_fw_env_var openbmconce >> $optfile +fi + +echo rofs = $rofs $rofst rwfs = $rwfs $rwfst + +if grep -w debug-init-sh $optfile +then + debug_takeover "Debug initial shell requested by command line." +fi + +if test "x$consider_download_files" = xy && + grep -w openbmc-init-download-files $optfile +then + if test -f ${urlfile##*/} + then + cp ${urlfile##*/} $urlfile + fi + if test ! -f $urlfile + then + get_fw_env_var openbmcinitdownloadurl > $urlfile + fi + url="$(cat $urlfile)" + rest="${url#*://}" + proto="${url%$rest}" + + if test -z "$url" + then + echo "Download url empty. Ignoring download request." + elif test -z "$proto" + then + echo "Download failed." + elif test "$proto" = tftp:// + then + if test "x$consider_download_tftp" = xy + then + try_tftp "$url" + else + echo "Download failed." + fi + elif test "$proto" = http:// + then + if test "x$consider_download_http" = xy + then + try_wget "$url" + else + echo "Download failed." + fi + elif test "$proto" = ftp:// + then + if test "x$consider_download_ftp" = xy + then + try_wget "$url" + else + echo "Download failed." + fi + else + echo "Download failed." + fi +fi + +# If there are images in root move them to /run/initramfs/ or /run/ now. +imagebasename=${image##*/} +if test -n "${imagebasename}" && ls /${imagebasename}* > /dev/null 2>&1 +then + if test "x$flash_images_before_init" = xy + then + echo "Flash images found, will update before starting init." + mv /${imagebasename}* ${image%$imagebasename} + else + echo "Flash images found, will use but deferring flash update." + mv /${imagebasename}* /run/ + fi +fi + +if grep -w clean-rwfs-filesystem $optfile +then + echo "Cleaning of read-write overlay filesystem requested." + touch $trigger +fi + +if grep -w factory-reset $optfile +then + echo "Factory reset requested." + touch $trigger + do_save=--no-save-files +else + do_save=--save-files +fi + +if test "x$force_rwfst_jffs2" = xy -a $rwfst != jffs2 -a ! -f $trigger +then + echo "Converting read-write overlay filesystem to jffs2 forced." + touch $trigger +fi + +if ls $image* > /dev/null 2>&1 +then + if ! test -x $update + then + debug_takeover "Flash update requested but $update missing!" + elif test -f $trigger -a ! -s $trigger + then + if [ $do_save = "--save-files" ] + then + echo "Saving selected files from read-write overlay filesystem." + else + echo "No files will be selected for save." + fi + $update --no-restore-files $do_save + echo "Clearing read-write overlay filesystem." + flash_eraseall /dev/$rwfs + echo "Restoring saved files to read-write overlay filesystem." + touch $trigger + $update --no-save-files --clean-saved-files + else + $update --clean-saved-files $do_save + fi + + rwfst=$(probe_fs_type $rwdev) + fsck=$fsckbase$rwfst +fi + +if grep -w overlay-filesystem-in-ram $optfile +then + rwfst=none +fi + +copyfiles= +if grep -w copy-files-to-ram $optfile +then + rwfst=none + copyfiles=y +fi + +# It would be nice to do this after fsck but that mean rofs is mounted +# which triggers the mtd is mounted check +if test "$rwfst$copyfiles" = noney +then + touch $trigger + $update --copy-files --clean-saved-files --no-restore-files +fi + +if grep -w copy-base-filesystem-to-ram $optfile && + test ! -e /run/image-rofs && ! cp $rodev /run/image-rofs +then + # Remove any partial copy to avoid attempted usage later + if test -e /run/image-rofs + then + ls -l /run/image-rofs + rm -f /run/image-rofs + fi + debug_takeover "Copying $rodev to /run/image-rofs failed." +fi + +if test -s /run/image-rofs +then + rodev=/run/image-rofs + roopts=$roopts,loop +fi + +mount $rodev $rodir -t $rofst -o $roopts + +if test -x $rodir$fsck +then + for fs in $fslist + do + mount --bind $fs $rodir/$fs + done + chroot $rodir $fsck $fsckopts $rwdev + rc=$? + for fs in $fslist + do + umount $rodir/$fs + done + if test $rc -gt 1 + then + debug_takeover "fsck of read-write fs on $rwdev failed (rc=$rc)" + fi +elif test "$rwfst" != jffs2 -a "$rwfst" != none +then + echo "No '$fsck' in read only fs, skipping fsck." +fi + +if test "$rwfst" = none +then + echo "Running with read-write overlay in RAM for this boot." + echo "No state will be preserved unless flash update performed." +elif ! mount $rwdev $rwdir -t $rwfst -o $rwopts +then + msg="$(cat)" << HERE + +Mounting read-write $rwdev filesystem failed. Please fix and run + mount $rwdev $rwdir -t $rwfst -o $rwopts +to to continue, or do change nothing to run from RAM for this boot. +HERE + debug_takeover "$msg" +fi + +rm -rf $work +mkdir -p $upper $work + +mount -t overlay -o lowerdir=$rodir,upperdir=$upper,workdir=$work cow /root + +while ! chroot /root /bin/sh -c "test -x '$init' -a -s '$init'" +do + msg="$(cat)" << HERE + +Unable to confirm /sbin/init is an executable non-empty file +in merged file system mounted at /root. + +Change Root test failed! Invoking emergency shell. +HERE + debug_takeover "$msg" +done + +for f in $fslist +do + mount --move $f root/$f +done + +# switch_root /root $init +exec chroot /root $init + diff --git a/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-shutdown.sh b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-shutdown.sh new file mode 100644 index 000000000..d3c883595 --- /dev/null +++ b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-shutdown.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +echo shutdown: "$@" + +export PS1=shutdown-sh#\ +# exec bin/sh + +cd / +if [ ! -e /proc/mounts ] +then + mkdir -p /proc + mount proc /proc -tproc + umount_proc=1 +else + umount_proc= +fi + +# Remove an empty oldroot, that means we are not invoked from systemd-shutdown +rmdir /oldroot 2>/dev/null + +# Move /oldroot/run to /mnt in case it has the underlying rofs loop mounted. +# Ordered before /oldroot the overlay is unmounted before the loop mount +mkdir -p /mnt +mount --move /oldroot/run /mnt + +set -x +for f in $( awk '/oldroot|mnt/ { print $2 }' < /proc/mounts | sort -r ) +do + umount $f +done +set +x + +update=/run/initramfs/update +image=/run/initramfs/image- + +wdt="-t 1 -T 5" +wdrst="-T 15" + +if ls $image* > /dev/null 2>&1 +then + if test -x $update + then + if test -c /dev/watchdog + then + echo Pinging watchdog ${wdt+with args $wdt} + watchdog $wdt -F /dev/watchdog & + wd=$! + else + wd= + fi + $update --clean-saved-files + remaining=$(ls $image*) + if test -n "$remaining" + then + echo 1>&2 "Flash update failed to flash these images:" + echo 1>&2 "$remaining" + else + echo "Flash update completed." + fi + + if test -n "$wd" + then + kill -9 $wd + if test -n "$wdrst" + then + echo Resetting watchdog timeouts to $wdrst + watchdog $wdrst -F /dev/watchdog & + sleep 1 + # Kill the watchdog daemon, setting a timeout + # for the remaining shutdown work + kill -9 $! + fi + fi + else + echo 1>&2 "Flash update requested but $update program missing!" + fi +fi + +echo Remaining mounts: +cat /proc/mounts + +test "$umount_proc" && umount /proc && rmdir /proc + +# tcsattr(tty, TIOCDRAIN, mode) to drain tty messages to console +test -t 1 && stty cooked 0<&1 + +# Execute the command systemd told us to ... +if test -d /oldroot && test "$1" +then + if test "$1" = kexec + then + $1 -f -e + else + $1 -f + fi +fi + + +echo "Execute ${1-reboot} -f if all unmounted ok, or exec /init" + +export PS1=shutdown-sh#\ +exec /bin/sh diff --git a/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-update.sh b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-update.sh new file mode 100755 index 000000000..278cd41d7 --- /dev/null +++ b/meta-phosphor/recipes-phosphor/initrdscripts/files/obmc-update.sh @@ -0,0 +1,274 @@ +#!/bin/sh + +echo update: "$@" + +echoerr() { + echo 1>&2 "ERROR: $@" +} + +cd / +if ! test -r /proc/mounts || ! test -f /proc/mounts +then + mkdir -p /proc + mount -t proc proc proc +fi +if ! test -d /sys/class +then + mkdir -p /sys + mount -t sysfs sys sys +fi +if ! test -c /dev/null +then + mkdir -p /dev + mount -t devtmpfs dev dev +fi + +# mtd number N with mtd name Name can be mounted via mtdN, or mtd:Name +# (with a mtd aware fs) or by /dev/mtdblockN (with a mtd or block fs). +mtdismounted() { + m=${1##mtd} + if grep -s "mtdblock$m " /proc/mounts || grep -s "mtd$m " /proc/mounts + then + return 0 + fi + n=$(cat /sys/class/mtd/mtd$m/name) + if test -n "$n" && grep -s "mtd:$n " /proc/mounts + then + return 0 + fi + return 1 +} + +# Detect child partitions when the whole flash is to be updated. +# Ignore mtdNro and mtdblockN names in the class subsystem directory. +childmtds() { + for m in /sys/class/mtd/$1/mtd* + do + m=${m##*/} + if test "${m%ro}" = "${m#mtdblock}" + then + echo $m + fi + done +} + +toobig() { + if test $(stat -L -c "%s" "$1") -gt $(cat /sys/class/mtd/"$2"/size) + then + return 0 + fi + return 1 +} + +findmtd() { + m=$(grep -xl "$1" /sys/class/mtd/*/name) + m=${m%/name} + m=${m##*/} + echo $m +} + +blkid_fs_type() { + # Emulate util-linux's `blkid -s TYPE -o value $1` + # Example busybox blkid output: + # # blkid /dev/mtdblock5 + # /dev/mtdblock5: TYPE="squashfs" + # Process output to extract TYPE value "squashfs". + blkid $1 | sed -e 's/^.*TYPE="//' -e 's/".*$//' +} + +probe_fs_type() { + fst=$(blkid_fs_type $1) + echo ${fst:=jffs2} +} + +rwfs=$(findmtd rwfs) + +rwdev=/dev/mtdblock${rwfs#mtd} +rwopts=rw +rorwopts=ro${rwopts#rw} + +rwdir=/run/initramfs/rw +upper=$rwdir/cow +save=/run/save/${upper##*/} + +mounted= +doflash=y +doclean= +dosave=y +dorestore=y +toram= +checksize=y +checkmount=y + +whitelist=/run/initramfs/whitelist +image=/run/initramfs/image- +imglist= + +while test "$1" != "${1#-}" +do + case "$1" in + --help) + cat <<HERE +Usage: $0 [options] -- Write images in /run/initramfs to flash (/dev/mtd*) + --help Show this message + --no-flash Don't attempt to write images to flash + --ignore-size Don't compare image size to mtd device size + --ignore-mount Don't check if destination is mounted + --save-files Copy whitelisted files to save directory in RAM + --no-save-files Don't copy whitelisted files to save directory + --copy-files Copy files from save directory to rwfs mountpoint + --restore-files Restore files from save directory to rwfs layer + --no-restore-files Don't restore saved files from ram to rwfs layer + --clean-saved-files Delete saved whitelisted files from RAM + --no-clean-saved-files Retain saved whitelisted files in RAM +HERE + + exit 0 ;; + + --no-clean-saved-files) + doclean= + shift ;; + --clean-saved-files) + doclean=y + shift ;; + --no-save-files) + dosave= + shift ;; + --save-files) + dosave=y + shift ;; + --no-restore-files) + dorestore= + shift ;; + --restore-files) + dorestore=y + shift ;; + --no-flash) + doflash= + shift ;; + --ignore-size) + checksize= + shift ;; + --ignore-mount) + checkmount= + doflash= + shift ;; + --copy-files) + toram=y + shift ;; + *) + echoerr "Unknown option $1. Try $0 --help." + exit 1 ;; + esac +done + +if test "x$dosave" = xy +then + if test ! -d $upper -a -n "$rwfs" + then + mkdir -p $rwdir + mount $rwdev $rwdir -t $(probe_fs_type $rwdev) -o $rorwopts + mounted=$rwdir + fi + + while read f + do + # Entries shall start with /, no trailing /.. or embedded /../ + if test "/${f#/}" != "$f" -o "${f%/..}" != "${f#*/../}" + then + echo 1>&2 "WARNING: Skipping bad whitelist entry $f." + continue + fi + if ! test -e "$upper/$f" + then + continue + fi + d="$save/$f" + while test "${d%/}" != "${d%/.}" + do + d="${d%/.}" + d="${d%/}" + done + mkdir -p "${d%/*}" + cp -rp "$upper/$f" "${d%/*}/" + done < $whitelist + + if test -n "$mounted" + then + umount $mounted + fi +fi + +imglist=$(echo $image*) +if test "$imglist" = "$image*" -a ! -e "$imglist" +then + # shell didn't expand the wildcard, so no files exist + echo "No images found to update." + imglist= +fi + +for f in $imglist +do + m=$(findmtd ${f#$image}) + if test -z "$m" + then + echoerr "Unable to find mtd partition for ${f##*/}." + exit 1 + fi + if test -n "$checksize" && toobig "$f" "$m" + then + echoerr "Image ${f##*/} too big for $m." + exit 1 + fi + for s in $m $(childmtds $m) + do + if test -n "$checkmount" && mtdismounted $s + then + echoerr "Device $s is mounted, ${f##*/} is busy." + exit 1 + fi + done +done + +if test -n "$doflash" +then + for f in $imglist + do + if test ! -s $f + then + echo "Skipping empty update of ${f#$image}." + rm $f + continue + fi + m=$(findmtd ${f#$image}) + echo "Updating ${f#$image}..." + flashcp -v $f /dev/$m && rm $f + done +fi + +if test -d $save -a "x$toram" = xy +then + mkdir -p $upper + cp -rp $save/. $upper/ +fi + +if test -d $save -a "x$dorestore" = xy +then + odir=$rwdir + rwdir=/run/rw + upper=$rwdir${upper#$odir} + + mkdir -p $rwdir + mount $rwdev $rwdir -t $(probe_fs_type $rwdev) -o $rwopts + mkdir -p $upper + cp -rp $save/. $upper/ + umount $rwdir + rmdir $rwdir +fi + +if test "x$doclean" = xy +then + rm -rf $save +fi + +exit diff --git a/meta-phosphor/recipes-phosphor/initrdscripts/files/whitelist b/meta-phosphor/recipes-phosphor/initrdscripts/files/whitelist new file mode 100644 index 000000000..20f1ec2a6 --- /dev/null +++ b/meta-phosphor/recipes-phosphor/initrdscripts/files/whitelist @@ -0,0 +1,13 @@ +/etc/dropbear/dropbear_rsa_host_key +/etc/group +/etc/gshadow +/etc/machine-id +/etc/passwd +/etc/resolv.conf +/etc/shadow +/etc/systemd/network +/var/cache/obmc +/var/lib/obmc +/var/lib/phosphor-inventory-manager +/var/lib/phosphor-settings-manager +/var/lib/phosphor-state-manager diff --git a/meta-phosphor/recipes-phosphor/initrdscripts/obmc-phosphor-initfs.bb b/meta-phosphor/recipes-phosphor/initrdscripts/obmc-phosphor-initfs.bb new file mode 100644 index 000000000..ab2c38e90 --- /dev/null +++ b/meta-phosphor/recipes-phosphor/initrdscripts/obmc-phosphor-initfs.bb @@ -0,0 +1,35 @@ +SUMMARY = "Phosphor OpenBMC pre-init scripts" +DESCRIPTION = "Phosphor OpenBMC filesystem mount reference implementation." +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${PHOSPHORBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658" + +PR = "r1" + +inherit allarch + +RDEPENDS_${PN} += "${VIRTUAL-RUNTIME_base-utils}" + +S = "${WORKDIR}" +SRC_URI += "file://obmc-init.sh" +SRC_URI += "file://obmc-shutdown.sh" +SRC_URI += "file://obmc-update.sh" +SRC_URI += "file://whitelist" + +do_install() { + for f in init-download-url init-options + do + if test -e $f + then + install -m 0755 ${WORKDIR}/$f ${D}/$f + fi + done + install -m 0755 ${WORKDIR}/obmc-init.sh ${D}/init + install -m 0755 ${WORKDIR}/obmc-shutdown.sh ${D}/shutdown + install -m 0755 ${WORKDIR}/obmc-update.sh ${D}/update + install -m 0644 ${WORKDIR}/whitelist ${D}/whitelist + install -d ${D}/dev + mknod -m 622 ${D}/dev/console c 5 1 +} + +FILES_${PN} += " /init /shutdown /update /whitelist /dev " +FILES_${PN} += " /init-options /init-download-url " |