site  contact  subhomenews

Redesign of init script in initrd

October 10, 2025 — BarryK

This is a complete refactoring of the init script. Have been wanting to do this for a long time, as the init script is monolithic and becoming increasingly difficult to edit and understand. There are so many if-else constructs to handle special cases. The script is 2,957 lines, file size 137KB.

What I have done is modularize it, taken out blocks of code, so that the main init script is small. It is now 418 lines, file size 17KB. I can now follow the logic of it much more easily. Here it is:

#!/bin/sh
#(c) Copyright Barry Kauler, 2025. Licence: GPL v3 (/usr/share/doc/legal).
#20251010 complete modular rewrite.

#PM bit0=1 copy sfs to ram
#PM bit1=1 session in ram

###preliminary###
###############################################################################
export LANG=C
. /build-choices #create-initrd in woofq2 copies it here.
#...has EOS_TOP_LEVEL_ZRAM, EOS_SUPPORT_CONTAINERS
export EOS_TOP_LEVEL_ZRAM EOS_SUPPORT_CONTAINERS

#create-initrd in woofq2 copied this into initrd...
sed -e 's%^DISTRO_%INIT_DISTRO_%' /etc/DISTRO_SPECS > /INIT_DISTRO_SPECS
. /INIT_DISTRO_SPECS
export INIT_DISTRO_VERSION INIT_DISTRO_BINARY_COMPAT INIT_DISTRO_COMPAT_VERSION INIT_DISTRO_TARGETARCH INIT_DISTRO_VERSION

mount -o hidepid=1,gid=118 -t proc none /proc
mount -t sysfs none /sys
mount -t rootfs -o remount,rw rootfs /
ln -s /proc/mounts /etc/mtab 2> /dev/null
export PATH="/bin:/sbin"
mount -t devtmpfs devtmpfs /dev

export TZ='XXX-23' #imaginary place right around the world east of Greenwich.
#...i think that this will give the most delayed time, so any file operations
#will not result in a future date after the correct time is set in the main f.s.
#ref: http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html

KERNVER="$(uname -r)"
export KERNVER
CR='
'
SALT="aprilandvincent"
Lm="${S002:-Line}:"
PM=0
BROKENVID=0
LAYERFS='overlay'

cat /sys/class/zram-control/hot_add >/dev/null #creates /dev/zram1
cat /sys/class/zram-control/hot_add >/dev/null #creates /dev/zram2

. /inc/00functions
#...has: create_top_level_zram1_func, exit_to_initrd_func, err_exit_func,
#   ask_kb_func, menu_func, menu_delay_func, ask_root_pw_func, ask_pw_func,
#   cp_verify_func, mnt_wkg_ext4_func, countdown_func

#only allow drop CAP_SYS_ADMIN if have CAP_SYS_MOUNT patch
CSAdrop=0
capsh --supports=cap_sys_mount 2>/dev/null
if $? -eq ];then #kernel has cap_sys_mount separated from cap_sys_admin
 CSAdrop=1
fi

#display info
loadfont < /lib/consolefonts/zap-ext-vga16.psfu
echo -n -e "\\033[1;32m${INIT_DISTRO_NAME_LONG}, version ${INIT_DISTRO_VERSION}\\033[0;39m\n" #bright green
echo

###read kernel params###
###############################################################################
-n "$wkg_dev" ] && WKG_DEV="$wkg_dev"
-n "$wkg_uuid" ] && WKG_UUID="$wkg_uuid"
-n "$wkg_label" ] && WKG_LABEL="$wkg_label"
-n "$wkg_dir" ] && WKG_DIR="$wkg_dir"
-n "$WKG_DIR" ] && [ -n "${WKG_DIR##*/}" ] && WKG_DIR="${WKG_DIR}/" #must have trailing slash.
-n "$WKG_DIR" ] && [ "${WKG_DIR:0:1}" == "/" ] && WKG_DIR="${WKG_DIR:1:99}" #remove a leading slash.

#BOOT_* if vmlinuz & initrd not in wkg-partition...
-n "$boot_dev" ] && BOOT_DEV="$boot_dev"
-n "$boot_dir" ] && BOOT_DIR="$boot_dir"
-n "$boot_uuid" ] && BOOT_UUID="$boot_uuid"
-n "$boot_label" ] && BOOT_LABEL="$boot_label"

#note: no longer support "qfix=" kernel parameter.

###find out working partition###
###############################################################################
echo -n -e "\\033[1;35m${S100:-Finding drives}\\033[0;39m\n " #purple
CNT=0
-e /dev/scd0 ] && rm -f /dev/scd#static dev nodes, these duplicate sr* nodes.
-n "$WKG_DEV" ] && xWKG_DEV="$WKG_DEV" #passed kernel param.
WKG_DEV=''
while $CNT -lt 20 ];do #drives may take couple seconds to become available.
 sleep 1
 echo -n '.'
 CNT=$(($CNT+1))
 BLKIDS="$(blkid | grep -v '[a-z]: ')"
 #...ex line: /dev/sda2: LABEL="intern1p2" UUID="cd5ef69b-883d-4744-bc1d-551154131db2" TYPE="ext4"
 -n "$xWKG_DEV" ] && WKG_DEV="$(echo "${BLKIDS}" | grep "/${xWKG_DEV}:" | cut -f 1 -d ':' | cut -f 3 -d '/')"
 -z "$WKG_DEV" ] && WKG_DEV="$(echo "${BLKIDS}" | grep -E "\"${WKG_UUID}\"|\"${WKG_LABEL}\"" | cut -f 1 -d ':' | cut -f 3 -d '/')"
 -n "$WKG_DEV" ] && break
done
-z "$WKG_DEV" ] && err_exit_func "Line:${LINENO} Failed to find working-partition"
WKG_FS="$(echo "${BLKIDS}" | grep "^/dev/${WKG_DEV}:" | tr ' ' '\n' | grep '^TYPE=' | cut -f 2 -d '"')"

if "$WKG_FS" != "ext4" ];then
 err_exit_func "Line:${LINENO} Sorry, the working-partition is required to be ext4"
fi

#determine working-drive...
Pw=0
WKG_PARTNUM="${WKG_DEV/*[a-z]/}"
WKG_DRV="${WKG_DEV%[0-9]}"
WKG_DRV="${WKG_DRV%[0-9]}"
"${WKG_DRV:0:3}" == "mmc" ] && Pw=1
"${WKG_DRV:0:3}" == "nvm" ] && Pw=1
$Pw -eq ] && WKG_DRV="${WKG_DRV%p}"

#BOOT_DEV/BOOT_UUID/BOOT_LABEL may have been passed on kernel cmdline
if -n "$BOOT_UUID" -o -n "$BOOT_LABEL" -o -n "$BOOT_DEV" ];then
 -n "$BOOT_DEV" ] && xBOOT_DEV="$BOOT_DEV" #passed kernel param.
 BOOT_DEV=''
 while $CNT -lt 22 ];do #allow a bit more time.
  sleep 1
  echo -n '.'
  CNT=$(($CNT+1))
  BLKIDS="$(blkid | grep -v '[a-z]: ')"
  #...ex line: /dev/sda2: LABEL="intern1p2" UUID="cd5ef69b-883d-4744-bc1d-551154131db2" TYPE="ext4"
  -n "$xBOOT_DEV" ] && BOOT_DEV="$(echo "${BLKIDS}" | grep "/${xBOOT_DEV}:" | cut -f 1 -d ':' | cut -f 3 -d '/')"
  -z "$BOOT_DEV" ] && BOOT_DEV="$(echo "${BLKIDS}" | grep -E "\"${BOOT_UUID}\"|\"${BOOT_LABEL}\"" | cut -f 1 -d ':' | cut -f 3 -d '/')"
  -n "$BOOT_DEV" ] && break
 done
 -z "$BOOT_DEV" ] && err_exit_func "Line:${LINENO} Failed to find boot-partition"
 BOOT_FS="$(echo "${BLKIDS}" | grep "^/dev/${BOOT_DEV}:" | tr ' ' '\n' | grep '^TYPE=' | cut -f 2 -d '"')"
 Pw=0
 BOOT_PARTNUM="${BOOT_DEV/*[a-z]/}"
 BOOT_DRV="${BOOT_DEV%[0-9]}"
 BOOT_DRV="${BOOT_DRV%[0-9]}"
 "${BOOT_DRV:0:3}" == "mmc" ] && Pw=1
 "${BOOT_DRV:0:3}" == "nvm" ] && Pw=1
 $Pw -eq ] && BOOT_DRV="${BOOT_DRV%p}"
fi

export WKG_DEV WKG_DIR WKG_FS

###resize wkg-partition###
###############################################################################
#maybe resize working partition to fill drive...
#note, woofq2 will edit these when creating initrd in drive-image file...
P2S='98304' #start of 2nd partition in 512-byte sectors (1MiB + 47MiB)
P2M='1044'  #size of 2nd partition in MiB
. /inc/01resize-wkg

###speed test###
###############################################################################
#note: dd in coreutils has different output, "s" instead of "seconds"...
TIMEs="$(dd if=/dev/${WKG_DRV} of=/dev/null bs=1024 count=64 iflag=skip_bytes skip=1610612736 2>&1 | grep -o '[0-9.]* [second]*s,' | cut -f 1 -d ' ')" #read speed.
#...sata hdd: 0.018864, usb3.0 ssd: 0.003258, pcie nvme ssd: 0.001403, cheap emtec usb2 flash stick: 0.013006, sandisk ultra usb3.0 flash stick: 0.004393, usb3.0 hdd: 0.035629
TIME10k=$(dc -e"${TIMEs} 10000 * p" | cut -f 1 -d '.') #cheap flash stick: usb2=140 usb3=77, be usb3=41, sandisk-extreme usb3=42, internal eMMC: 
echo "Working drive read speed test (lower the better): ${TIME10k}"


###read info from wkg-part###
###############################################################################
mkdir -p /mnt/${WKG_DEV}
mnt_wkg_ext4_func
$? -ne ] && err_exit_func "Line:${LINENO} Failed mount working-partition"

#reads .lockdown.flg, .debug.flg, .zramtl.flg, .qlang, .trim-wkg, .trim-not-wkg
#sets: LOCKDOWN, CAPS_DROP, DROPOUT, EOS_TOP_LEVEL_ZRAM, QLANG, /TRIMwkg, /TRIMnotwkg
. /inc/02read-wkg

#[ $EOS_TOP_LEVEL_ZRAM -eq 1 ] && PM=2 #bit1=1 run in ram, indirect-save.
$EOS_TOP_LEVEL_ZRAM -eq ] && PM=$((${PM}|2)) #binary-or, set bit1 run in ram indirect-save

#[ "$DROPOUT" == "1" ] && exit_to_initrd_func "Line:${LINENO} Exited from init script, wkg partition mounted."

###handle 1st or subsequent bootup###
###############################################################################
#keyboard hardware profile, as need to detect if kb changed...
#keyboard detection based upon existence of *::capslock folder...
NEW_KB_HW_PROFILE="$(ls -1 -d /sys/class/input/*/*::capslock 2>/dev/null | cut -f 1-5 -d '/' | xargs -I XXX cat XXX/name | tr -d '\n'| sed -e 's%[^0-9a-zA-Z]%%g' | cut -c 1-60)"
PW=''ALLOW_ASK_PW=''

if [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}.session ];then
 
 #ask populates wkg-part, kb-layout, password, encrypts folders
 #also optional display a menu (see menu_func in /inc/00functions)
 #sets: KEYMAP, PW, /mnt/${WKG_DEV}/${WKG_DIR}sfs/settings/initrd/CONFIG
 . /inc/03first-boot-kb-pw
 
else
 
 #subsequent bootups, ask kb if hw change, ask pw, decrypt folders.
 #also optional display a menu (see menu_func in /inc/00functions)
 #sets: /mnt/${WKG_DEV}/${WKG_DIR}sfs/settings/initrd/CONFIG
 . /inc/04next-boot-kb-pw
 
fi

#current distro specs...
if [ ! -e /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS ];then
 . /DISTRO_SPECS #use internal in initrd.
else
 . /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS
fi
export DISTRO_VERSION DISTRO_BINARY_COMPAT DISTRO_COMPAT_VERSION DISTRO_TARGETARCH

"$DROPOUT" == "1" ] && exit_to_initrd_func "Line:${LINENO} Exited from init script, after password and menu."

###first boot extra####
###############################################################################
#after 1st bootup, set a few extra things...

#set root pw, gnupg
. /inc/05first-boot-extra

###deferred session-save###
###############################################################################
#session save deferred. see: /usr/sbin/ask-save-zram1
if -d /mnt/${WKG_DEV}/${WKG_DIR}.session-transit ];then
 echo -e "\\033[1;35m${S147:-Deferred saving last session, please wait...}\\033[0;39m\n " #purple
 /sbin/rw-merge "$WKG_DEV" "$WKG_DIR"
fi

###hardware setup###
###############################################################################
#set: timezone, clock, test ssd trim capable, run fstrim
. /inc/06hardware-setup


###process menu requests###
###############################################################################
if -s /mnt/${WKG_DEV}/${WKG_DIR}.rollback.flg ];then
 export MENUVAR #in 'functions'
 /sbin/rollback "${WKG_DRV}" "${WKG_DEV}" "${WKG_DIR}"
 if -s /backVER ];then
  INIT_DISTRO_VERSION=$(cat /backVER) #have rolled back/forward to a different version.
  if "$MENUVAR" == "RBPREVVER" ];then
   #chose to rollback to previous version from initrd menu.
   #let's be pre-emptive and fix DISTRO_SPECS. have not yet loaded easy.sfs, so do a hack...
   sed -i -e "s%^DISTRO_VERSION=.*%DISTRO_VERSION=${INIT_DISTRO_VERSION}%" /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/DISTRO_SPECS
   sync
   umount /mnt/${WKG_DEV}
   #currently booting with the wrong kernel. have to change kernels!
   echo -e "\\033[1;35m" #purple
   echo "${S460:-You have chosen to rollback to the previous version via the initrd menu. However, the current Linux kernel is loaded. It is required to change to the kernel of the previous version. To achieve this, hold down the power button to power-off the computer. Then start it up again, this time just accept the normal bootup. Do not choose any options from the initrd menu. Then you should be in the previous version after bootup.}" fold -s -w 69
   echo -n -e "\\033[0;39m"
   echo -n "${S461:-Waiting for you to power-off the computer...}"
   sleep infinity
  fi
 fi
fi

if -s /mnt/${WKG_DEV}/${WKG_DIR}.fsckme.flg ];then
 /sbin/fscheck "${WKG_DRV}" "${WKG_DEV}" "${WKG_DIR}" "${WKG_FS}" #ex: improper shutdown
 $? -ne ] && err_exit "${Lm}${LINENO} ${S160:-Fatal error when filesystem check}"
fi

"$DROPOUT" == "2" ] && exit_to_initrd_func "Line:${LINENO} Exited from init script, after hw setup and processed menu choice."

###version control###
###############################################################################
prevVER=""
prevCOMPAT=''
if [ ! -d /mnt/${WKG_DEV}/${WKG_DIR}releases/easy-${INIT_DISTRO_VERSION} ];then
 
 #setup new version, populates above folder.
 #sets: prevVER, prevCOMPAT
 . /inc/07new-version
 
else
 if -f /mnt/${WKG_DEV}/${WKG_DIR}easy.sfs ];then
  #should only exist when do update, and easy.sfs gets moved into releases folder.
  echo -e "\\033[1;31m/mnt/${WKG_DEV}/${WKG_DIR}easy.sfs ${S180:-Why does this file exist? Removing it.}\\033[0;39m" #red
  rm -f /mnt/${WKG_DEV}/${WKG_DIR}easy.sfs
 fi
fi

###fix layers change###
###############################################################################

#if version change, attempt to carry-over loaded sfs's to new version...
if -n "$prevVER" ];then
 . /inc/08carry-over-extrasfs
fi

#load extra sfs in /sbin/extrasfs, via /sbin/layer*, but do a dummy detect here...
EXTRASFS=""NEWEXTRASFSLIST=""
#sets NEWEXTRASFSLIST, EXTRASFS, /EXTRASFS
. /inc/09dummy-extrasfs

OLDEXTRASFSLIST="$(grep '^EXTRASFSLIST=' /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/rc.d/PUPSTATE 2>/dev/null | cut -f 2 -d "'")"
if -s /mnt/${WKG_DEV}/${WKG_DIR}.session/etc/rc.d/PUPSTATE ];then
 if "$NEWEXTRASFSLIST" != "$OLDEXTRASFSLIST" -o "$prevVER" != "" ];then
  /sbin/fixlayers "${WKG_DRV}" "${WKG_DEV}" "${NEWEXTRASFSLIST}" "${prevVER}" "${WKG_DIR}" "${prevCOMPAT}"
 fi
fi

###decide copy sfs to ram###
###############################################################################
FREEK=$(grep '^MemFree:' /proc/meminfo | tr -s ' ' | cut -f 2 -d ' ')

#sets: CPYflg
#also creates a tmpfs on /easy_ro, big enough to hold the sfs's.
. ./inc/10decide-copy-sfs-ram
#CPYflg=$(cat /CPYflg) #=1 if copy to ram.
PM=$((${PM}|${CPYflg})) #binary-or, set bit0 if copy sfs to ram.

###hardware profiling###
###############################################################################
#see also KB_HW_PROFILE set in *-boot-kb-pw above.
. /inc/11hardware-profiling

###broken video###
###############################################################################

. /inc/12broken-video

"$DROPOUT" == "3" ] && exit_to_initrd_func "Line:${LINENO} Exited from init script, after hardware setup."

###decide lockdown###
###############################################################################
if -n "$LOCKDOWN" ];then
 #creates /dev/zram0 ext4 on /xram
 #pre-populates it
 #sets: EOS_TOP_LEVEL_ZRAM=0, EOS_SUPPORT_CONTAINERS=0, SESSIONHOME
 . /inc/13setup-lockdown
fi
if -z "$LOCKDOWN" ];then
 SESSIONHOME="/mnt/${WKG_DEV}/${WKG_DIR}.session"
 ln -snf /mnt/${WKG_DEV}/${WKG_DIR}files ${SESSIONHOME}/files
fi

###container cleanup###
###############################################################################
. /inc/14container-cleanup

###create zram1###
###############################################################################
if $EOS_TOP_LEVEL_ZRAM -eq ];then
 create_top_level_zram1_func
 mount -t ext4 /dev/zram1 /easy_rw
 mkdir /easy_rw/mainrw #mainrw will be the rw top-level layer.
 if "$EOS_SUPPORT_CONTAINERS" != "0" ];then
  #these will be the rw layer for containers...
  mkdir /easy_rw/www
  mkdir /easy_rw/console
  mkdir /easy_rw/ssh0
  mkdir /easy_rw/${INIT_DISTRO_COMPAT_VERSION} #ex: dunfell, bookworm, excalibur
  mkdir /easy_rw/x2
  mkdir /easy_rw/x3
  mkdir /easy_rw/devx
 fi
 rmdir /easy_rw/lost+found
fi

"$DROPOUT" == "4" ] && exit_to_initrd_func "Line:${LINENO} Exited from init script, just before creating overlay."

###setup overlay###
###############################################################################
if -n "$LOCKDOWN" ];then
 . /inc/layer-lockdown
else
 . /inc/layer${PM}
fi
TOPdir="$(cat /TOPdir)"

###prepare to switch###
###############################################################################
#write to $TOPdir
. /inc/15prepare-switch

if -n "$LOCKDOWN" ];then
 mkdir -p ${TOPdir}/mnt/zram0
 mount -o move /xram ${TOPdir}/mnt/zram0
 . /inc/16prepare-switch-lockdown
else
 mkdir -p ${TOPdir}/mnt/${WKG_DEV}
 mount -o move /mnt/${WKG_DEV} ${TOPdir}/mnt/${WKG_DEV}
fi

"$DROPOUT" == "5" ] && exit_to_initrd_func "${Lm}${LINENO} ${S222:-Exited from init script, before moving mount points to wkg f.s.}"

#move mount-points to $TOPdir...
mount -o move /dev ${TOPdir}/dev
#in lockdown #2 cannot create device nodes, so make them here...
[ ! -e ${TOPdir}/dev/ppp ] && mknod ${TOPdir}/dev/ppp c 108 0 #jafadmin: gpptp needs /dev/ppp

mount -o move /sys ${TOPdir}/sys
mount -o move /proc ${TOPdir}/proc

SECFSflg=0
if -e ${TOPdir}/sys/kernel/security ];then #20201206 have compiled 4.19.161 without CONFIG_SECURITYFS
 mount -t securityfs securityfs ${TOPdir}/sys/kernel/security #200820
 $? -eq ] && SECFSflg=1
fi
mkdir -p ${TOPdir}/dev/pts
mount -t devpts devpts ${TOPdir}/dev/pts
HALFK=$(($FREEK/2))
QTRK=$(($FREEK/4))
mkdir -p ${TOPdir}/dev/shm
mount -t tmpfs -o size=${QTRK}k shmfs ${TOPdir}/dev/shm
if -z "$LOCKDOWN" -a "$EOS_TOP_LEVEL_ZRAM" != "1" ];then #don't bother if will be running in zram.
 mount -t tmpfs -o size=${HALFK}k tmpfs ${TOPdir}/tmp
fi

"$DROPOUT" == "6" ] && exit_to_initrd_func "${Lm}${LINENO} ${S232:-Exited from init script, just before switch_root.}"


###switch_root###
###############################################################################
if -z "$CAPS_DROP" ];then
  exec switch_root ${TOPdir} /sbin/init
else
 if $SECFSflg -eq ];then #note, lockdown only works 5.4+ kernels.
  echo confidentiality ${TOPdir}/sys/kernel/security/lockdown #200820 instead of "lockdown=confidentiality" boot param.
 fi
 #drop capbilities when switch_root...
 #capsh --drop=cap_sys_mount -- -c "exec switch_root ${TOPdir} /sbin/init"
 #this is another way of doing it...
 exec switch_root ${TOPdir} /sbin/capsh --drop=${CAPS_DROP} -- -c "exec /sbin/init"
fi
###end###

Here are the modules that will also be in the initrd, in the /inc folder:

img1

What prompted me recently to do this refactoring, was having difficulty getting direct-save of session to the working-partition, that is, not run with the session in RAM; which also requires saving of the session, whereas direct-save does not.

I have created  "EOSMODE" (just "PM" in above code) which is kind of like the Puppy PUPMODE, but only two bits. Bit0=1 if easy.sfs is copied to RAM, and bit1=1 if the session is in RAM. There is also "LOCKDOWN" mode, which is treated as a separate special case. The refactoring has separated each of these modes as modules 'layer0', 'layer1', 'layer2', layer3' and 'layer-lockdown' (see above), which makes it much clearer to handle each case.

There have been simplifications, and some things removed. Such as:

  1. Overlay only, no aufs
  2. Kernel boot parameter "qfix=..." is gone.
  3. init script supported a save-file, but it was never used, so gone.

Not fully debugged yet; have only tested the normal default of copy easy.sfs to RAM and run session in RAM.  

Tags: easy