Initial commit
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
#!/bin/sh
|
||||
|
||||
fslist="proc sys dev run"
|
||||
rodir=run/initramfs/ro
|
||||
rwdir=run/initramfs/rw
|
||||
upper=$rwdir/cow
|
||||
work=$rwdir/work
|
||||
|
||||
cd /
|
||||
# shellcheck disable=SC2086
|
||||
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
|
||||
tr '\n\000' '\r\n' < "/dev/$envdev" |
|
||||
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 "$@"
|
||||
|
||||
if ! grep -w enable-initrd-debug-sh "$optfile"
|
||||
then
|
||||
echo "Fatal error, triggering kernel panic!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test -n "$@" && echo 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 ! /bin/sh && ! test -f /takeover
|
||||
do
|
||||
echo /bin/sh failed, retrying
|
||||
done
|
||||
|
||||
# Touch /takeover in the above shell 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
|
||||
if grep -w enable-initrd-debug-sh "$optfile"
|
||||
then
|
||||
debug_takeover "Debug initial shell requested by command line."
|
||||
else
|
||||
echo "Need to also add enable-initrd-debug-sh for debug shell."
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$consider_download_files" = "y" &&
|
||||
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 "$consider_download_tftp" = "y"
|
||||
then
|
||||
try_tftp "$url"
|
||||
else
|
||||
echo "Download failed."
|
||||
fi
|
||||
elif test "$proto" = http://
|
||||
then
|
||||
if test "$consider_download_http" = "y"
|
||||
then
|
||||
try_wget "$url"
|
||||
else
|
||||
echo "Download failed."
|
||||
fi
|
||||
elif test "$proto" = ftp://
|
||||
then
|
||||
if test "$consider_download_ftp" = "y"
|
||||
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 "$flash_images_before_init" = "y"
|
||||
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 "$force_rwfst_jffs2" = "y" -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
|
||||
or perform a factory reset with the clean-rwfs-filesystem option.
|
||||
HERE
|
||||
debug_takeover "$msg"
|
||||
fi
|
||||
|
||||
# Empty workdir; do not remove workdir itself for it will fail to recreate it if
|
||||
# RWFS is full
|
||||
if [ -d $work ]
|
||||
then
|
||||
find $work -maxdepth 1 -mindepth 1 -exec rm -rf '{}' +
|
||||
fi
|
||||
|
||||
mkdir -p $upper $work
|
||||
|
||||
# Opportunisticly set a sane BMC date based on a file that gets
|
||||
# written right before rebooting or powercycling. If none exists,
|
||||
# use the image build date.
|
||||
files="$upper/var/lib/systemd/random-seed $rodir/etc/os-release"
|
||||
# shellcheck disable=SC2086
|
||||
time=$(find $files -exec stat -c %Y {} \; | sort -n | tail -n 1)
|
||||
# Allow RTC coordinated time to supersede this setting
|
||||
if [ "$(date +%s)" -lt "$time" ]; then
|
||||
date -s @$((time + 5)) || true
|
||||
fi
|
||||
|
||||
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!
|
||||
HERE
|
||||
debug_takeover "$msg"
|
||||
done
|
||||
|
||||
for f in $fslist
|
||||
do
|
||||
mount --move "$f" "root/$f"
|
||||
done
|
||||
|
||||
exec switch_root /root $init
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/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
|
||||
awk '/oldroot|mnt/ { print $2 }' < /proc/mounts | sort -r | while IFS= read -r f
|
||||
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}
|
||||
# shellcheck disable=SC2086
|
||||
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
|
||||
@@ -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 "$dosave" = "y"
|
||||
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 -r 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 "$toram" = "y"
|
||||
then
|
||||
mkdir -p $upper
|
||||
cp -rp "$save/." "$upper/"
|
||||
fi
|
||||
|
||||
if test -d "$save" -a "$dorestore" = "y"
|
||||
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 "$doclean" = "y"
|
||||
then
|
||||
rm -rf "$save"
|
||||
fi
|
||||
|
||||
exit
|
||||
@@ -0,0 +1,14 @@
|
||||
/etc/dropbear/dropbear_rsa_host_key
|
||||
/etc/group
|
||||
/etc/gshadow
|
||||
/etc/ipmi_pass
|
||||
/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
|
||||
@@ -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://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
|
||||
PR = "r1"
|
||||
|
||||
SRC_URI += "file://obmc-init.sh"
|
||||
SRC_URI += "file://obmc-shutdown.sh"
|
||||
SRC_URI += "file://obmc-update.sh"
|
||||
SRC_URI += "file://whitelist"
|
||||
|
||||
S = "${WORKDIR}"
|
||||
|
||||
inherit allarch
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
RDEPENDS:${PN} += "${VIRTUAL-RUNTIME_base-utils}"
|
||||
|
||||
FILES:${PN} += " /init /shutdown /update /whitelist /dev "
|
||||
FILES:${PN} += " /init-options /init-download-url "
|
||||
@@ -0,0 +1,30 @@
|
||||
SUMMARY = "Phosphor OpenBMC pre-init scripts for mmc"
|
||||
DESCRIPTION = "Phosphor OpenBMC filesystem mount implementation for mmc."
|
||||
LICENSE = "Apache-2.0"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
|
||||
PR = "r1"
|
||||
|
||||
SRC_URI += "file://mmc-init.sh"
|
||||
|
||||
S = "${WORKDIR}"
|
||||
|
||||
inherit allarch
|
||||
|
||||
do_install() {
|
||||
install -m 0755 ${WORKDIR}/mmc-init.sh ${D}/init
|
||||
install -d ${D}/dev
|
||||
mknod -m 622 ${D}/dev/console c 5 1
|
||||
}
|
||||
|
||||
RDEPENDS:${PN} += " \
|
||||
${@d.getVar('PREFERRED_PROVIDER_u-boot-fw-utils', True) or 'u-boot-fw-utils'} \
|
||||
${VIRTUAL-RUNTIME_base-utils} \
|
||||
e2fsprogs-e2fsck \
|
||||
e2fsprogs-mke2fs \
|
||||
gptfdisk \
|
||||
libgpiod-tools \
|
||||
parted \
|
||||
udev \
|
||||
"
|
||||
|
||||
FILES:${PN} += " /init /dev "
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/bin/sh
|
||||
|
||||
kgetopt ()
|
||||
{
|
||||
_cmdline="$(cat /proc/cmdline)"
|
||||
_optname="$1"
|
||||
_optval="$2"
|
||||
for _opt in $_cmdline
|
||||
do
|
||||
case "$_opt" in
|
||||
"${_optname}"=*)
|
||||
_optval="${_opt##"${_optname}"=}"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
[ -n "$_optval" ] && echo "$_optval"
|
||||
}
|
||||
|
||||
fslist="proc sys dev run"
|
||||
rodir=/mnt/rofs
|
||||
mmcdev="/dev/mmcblk0"
|
||||
rwfsdev="/dev/disk/by-partlabel/rwfs"
|
||||
|
||||
cd /
|
||||
|
||||
# We want to make all the directories in $fslist, not one directory named by
|
||||
# concatonating the names with spaces
|
||||
#
|
||||
# shellcheck disable=SC2086
|
||||
mkdir -p $fslist
|
||||
|
||||
mount dev dev -tdevtmpfs
|
||||
mount sys sys -tsysfs
|
||||
mount proc proc -tproc
|
||||
mount tmpfs run -t tmpfs -o mode=755,nodev
|
||||
|
||||
# Wait up to 5s for the mmc device to appear. Continue even if the count is
|
||||
# exceeded. A failure will be caught later like in the mount command.
|
||||
count=0
|
||||
while [ $count -lt 5 ]; do
|
||||
if [ -e "${mmcdev}" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
count=$((count + 1))
|
||||
done
|
||||
|
||||
# Move the secondary GPT to the end of the device if needed. Look for the GPT
|
||||
# header signature "EFI PART" located 512 bytes from the end of the device.
|
||||
if ! tail -c 512 "${mmcdev}" | hexdump -C -n 8 | grep -q "EFI PART"; then
|
||||
sgdisk -e "${mmcdev}"
|
||||
partprobe
|
||||
fi
|
||||
|
||||
# There eMMC GPT labels for the rootfs are rofs-a and rofs-b, and the label for
|
||||
# the read-write partition is rwfs. Run udev to make the partition labels show
|
||||
# up. Mounting by label allows for partition numbers to change if needed.
|
||||
udevd --daemon
|
||||
udevadm trigger --type=devices --action=add
|
||||
udevadm settle --timeout=10
|
||||
|
||||
mkdir -p $rodir
|
||||
if ! mount /dev/disk/by-partlabel/"$(kgetopt root=PARTLABEL)" $rodir -t ext4 -o ro; then
|
||||
/bin/sh
|
||||
fi
|
||||
|
||||
# Determine if a factory reset has been requested
|
||||
mkdir -p /var/lock
|
||||
resetval=$(fw_printenv -n rwreset 2>/dev/null)
|
||||
if gpiopresent=$(gpiofind factory-reset-toggle) ; then
|
||||
# gpiopresent contains both the gpiochip and line number as
|
||||
# separate words, and gpioget needs to see them as such.
|
||||
# shellcheck disable=SC2086
|
||||
gpioval=$(gpioget $gpiopresent)
|
||||
else
|
||||
gpioval=""
|
||||
fi
|
||||
# Prevent unnecessary resets on first boot
|
||||
if [ -n "$gpioval" ] && [ -z "$resetval" ]; then
|
||||
fw_setenv rwreset "$gpioval"
|
||||
resetval=$gpioval
|
||||
fi
|
||||
if [ "$resetval" = "true" ] || [ -n "$gpioval" ] && [ "$resetval" != "$gpioval" ]; then
|
||||
echo "Factory reset requested."
|
||||
if ! mkfs.ext4 -F "${rwfsdev}"; then
|
||||
echo "Reformat for factory reset failed."
|
||||
/bin/sh
|
||||
else
|
||||
# gpioval will be an empty string if factory-reset-toggle was not found
|
||||
fw_setenv rwreset "$gpioval"
|
||||
echo "rwfs has been formatted."
|
||||
fi
|
||||
fi
|
||||
|
||||
fsck.ext4 -p "${rwfsdev}"
|
||||
if ! mount "${rwfsdev}" $rodir/var -t ext4 -o rw; then
|
||||
/bin/sh
|
||||
fi
|
||||
|
||||
rm -rf $rodir/var/persist/etc-work/
|
||||
mkdir -p $rodir/var/persist/etc $rodir/var/persist/etc-work $rodir/var/persist/home/root
|
||||
mount overlay $rodir/etc -t overlay -o lowerdir=$rodir/etc,upperdir=$rodir/var/persist/etc,workdir=$rodir/var/persist/etc-work
|
||||
|
||||
init="$(kgetopt init /sbin/init)"
|
||||
|
||||
for f in $fslist; do
|
||||
mount --move "$f" "$rodir/$f"
|
||||
done
|
||||
|
||||
exec switch_root $rodir "$init"
|
||||
@@ -0,0 +1,50 @@
|
||||
SUMMARY = "Phosphor OpenBMC pre-init scripts for static-norootfs layout"
|
||||
DESCRIPTION = "Phosphor OpenBMC filesystem mount implementation for static-norootfs"
|
||||
LICENSE = "Apache-2.0"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
|
||||
PR = "r1"
|
||||
|
||||
SOURCE_FILES = "\
|
||||
init \
|
||||
10-early-mounts \
|
||||
20-udev \
|
||||
21-factory-reset \
|
||||
30-ubiattach-or-format \
|
||||
50-mount-persistent \
|
||||
"
|
||||
SRC_URI += "\
|
||||
${@' '.join(\
|
||||
[ 'file://' + x for x in d.getVar('SOURCE_FILES', True).split()])} \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}"
|
||||
|
||||
inherit allarch
|
||||
inherit update-alternatives
|
||||
|
||||
PKG_INSTALL_DIR="${libexecdir}/${BPN}"
|
||||
FILES:${PN} += "${PKG_INSTALL_DIR}"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${PKG_INSTALL_DIR}
|
||||
|
||||
for f in ${SOURCE_FILES} ; do
|
||||
install -m 0755 ${S}/$f ${D}${PKG_INSTALL_DIR}/$f
|
||||
done
|
||||
}
|
||||
|
||||
RDEPENDS:${PN} += " \
|
||||
${@d.getVar('PREFERRED_PROVIDER_u-boot-fw-utils', True) or \
|
||||
'u-boot-fw-utils'} \
|
||||
${VIRTUAL-RUNTIME_base-utils} \
|
||||
mtd-utils-ubifs \
|
||||
udev \
|
||||
"
|
||||
|
||||
ALTERNATIVE_LINK_NAME[init] = "${base_sbindir}/init"
|
||||
# Use a number higher than the systemd init alternative so that
|
||||
# ours is enabled instead.
|
||||
ALTERNATIVE_PRIORITY[init] ?= "400"
|
||||
|
||||
ALTERNATIVE:${PN} = "init"
|
||||
ALTERNATIVE_TARGET[init] = "${PKG_INSTALL_DIR}/init"
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
mount dev dev -tdevtmpfs
|
||||
mount sys sys -tsysfs
|
||||
mount proc proc -tproc
|
||||
mount tmpfs run -t tmpfs -o mode=755,nodev
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# We need to run udevd in order to get the /dev/mtd volumes to show up.
|
||||
if udevd --daemon; then
|
||||
udevadm trigger --type=devices --action=add && \
|
||||
udevadm settle --timeout=10
|
||||
|
||||
udevadm control --exit
|
||||
fi
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -x /sbin/fw_printenv ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Need to create /run/lock so fw_printenv can create lockfile.
|
||||
mkdir /run/lock
|
||||
|
||||
# Check uboot keys for 'factory-reset'
|
||||
if /sbin/fw_printenv openbmcinit openbmconce | grep -q factory-reset ; then
|
||||
echo "factory-reset" >> /run/format-persist
|
||||
fi
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -e /dev/mtd/rwfs ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e /run/format-persist ]; then
|
||||
if ! ubiattach -p /dev/mtd/rwfs > /dev/null ; then
|
||||
echo "unformatted-ubi" >> /run/format-persist
|
||||
fi
|
||||
|
||||
if ! ubinfo /dev/ubi0 -N rwfs > /dev/null ; then
|
||||
# ubi device attached, but volume not exist
|
||||
ubidetach -p /dev/mtd/rwfs
|
||||
echo "missing-ubi-volume" >> /run/format-persist
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e /run/format-persist ]; then
|
||||
echo "Formatting persistent volume: "
|
||||
cat /run/format-persist
|
||||
|
||||
if ! ubiformat --yes /dev/mtd/rwfs ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ubiattach -p /dev/mtd/rwfs ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ubimkvol /dev/ubi0 -N rwfs -m ; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p /run/mnt-persist
|
||||
mount -t ubifs ubi0:rwfs /run/mnt-persist -o sync,compr=zstd
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
PERSIST=/run/mnt-persist
|
||||
|
||||
if [ ! -d $PERSIST ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for m in var etc home/root; do
|
||||
if [ ! -d $PERSIST/$m-data ]; then
|
||||
mkdir -p $PERSIST/$m-data
|
||||
fi
|
||||
|
||||
if [ ! -d $PERSIST/$m-work ]; then
|
||||
mkdir -p $PERSIST/$m-work
|
||||
fi
|
||||
|
||||
mount overlay /$m -t overlay -o \
|
||||
lowerdir=/$m,upperdir=$PERSIST/$m-data,workdir=$PERSIST/$m-work
|
||||
done
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd /
|
||||
|
||||
for f in /usr/libexec/phosphor-static-norootfs-init/*; do
|
||||
if [ "$(basename "$f")" = "init" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
$f
|
||||
done
|
||||
|
||||
exec /lib/systemd/systemd
|
||||
Reference in New Issue
Block a user