User:Zucca/initramfs/init scripts

From Gentoo Wiki
Jump to:navigation Jump to:search
Warning
All scripts on this page have not gone trough proper testing. Modification may be required to make them useful on each system.

Fancy ansi logo, rescue shell and hibernaation support

Warning
This init script does have known bugs. Although not serious, it may still contain unknown bugs. Users are highly encouraged to check and modify the script for their specific needs.
FILE init
#!/bin/busybox sh

hdroot='/hdroot'
banner='/images/gentoo_h.ans'
msgque=""

# Source:
# https://github.com/dylanaraps/pure-sh-bible/tree/cd6e426a50eb07497b9c5bf763aec53744410568#check-if-a-number-is-an-integer
is_int() {
    # usage: is_int "number"
    printf %d "$1" >/dev/null 2>&1
}

printc() {
	#TODO: Light/bold colors too?
	if is_int "$1" && [ "${1:0:1}" != "-" ] && [ $1 -lt 255 ]
	then
		local colorcode="$1"
		shift
		printf '\033[38;5;%sm%s\033[m' "$colorcode" "$*"
	else
		#printc 1 "Wrong color code: $1"
		printf '%s' "$*"
	fi
}

settermenv() {
	local ttysize="$(stty size)"
	export xsize="${ttysize#* }"
	export ysize="${ttysize% *}"

	if [ -f "$banner" ]
	then
		export logoheight="$(wc -l < "$banner")"
	else
		export logoheight=$((xsize/2))
	fi
	export msgstartline='5'
	export msglines=$((ysize-logoheight-msgstartline-2))
}

setenv() {
	settermenv
	export PATH="/bin:/sbin:/usr/bin:/usr/sbin"
	export TERM="linux"
	#export MANPAGER="manpager"
	#export PAGER="less"
}


lineclear() {
	# Move cursor to the beginning of the line.
	printf '\33[%d;%dH' "$1" 0
	# Crudely print spaces
	printf "%0${xsize}s"
	#resetcursor
}

nprint() {
	local l line color symbol
	case "$1" in
		W)
			color="5"
			symbol="W"
		;;
		E)
			color="9"
			symbol="!"
		;;
		*)
			color="2"
			symbol="*"
		;;
	esac
	shift
	
	msgque="${msgque}
		$(printf '%s' "$*")"
	local linecount="$(echo -n "$msgque" | wc -l)"

	if [ $linecount -lt $msglines ]
	then
		printxy "4" "$((linecount+msgstartline))" "$(printc "$color" " $symbol ")$*"
	else
		msgque="$(echo "$msgque" | tail -n $msglines)"

		ypos="$msgstartline"
		echo "$msgque" | while read line
		do
			if [ "$line" ]
			then
				lineclear "$ypos"
				printxy "4" "$ypos" "$(printc "$color" " $symbol ")${line}"
				true "$((ypos++))" # Meh. ((ypos++)) does not work.
			fi
		done
		
		for l in $(seq 1 $((msgstartline-1)))
		do
			lineclear "$l"
		done

	fi
	resetcursor
}

msg() {
	nprint OK "$*"
}

warn() {
	nprint W "$*"
}

err() {
	nprint E "$*"
}

disablemount() {
	mount() {
		warn "Disabled mount command: $*"
		return 1
	}
}

pause() {
	# By default we have no pauses.
	return 0
}

resetcursor() {
	printf '\33[%d;%dH' "$ysize" "1"
}

printxy() {
	if is_int "$1" && is_int "$2"
	then
		local xc="$1"
		local yc="$2"
		shift; shift
		printf "\33[%d;%dH%s\33[62;1H" "$yc" "$xc" "$*"
	else
		shift;shift
		printf '%s\n' "$*"
	fi
}

tryresume() {
	msg "Checking if we are waking up from hibernation..."
	if [ -n "$resumedev" ]; then
		# Print the major:minor of the resume device into /sys/power/resume
		if ! echo "$rminmaj" > /sys/power/resume
		then
		  	err "Resuming from hibernation failed."
			disablemount
			warn "By echoing minor:major of ${resumedev} (${rminmaj}) to /sys/power/resume resuming should have started..."
			esh "You may investigate what's wrong."
		fi
		msg "No hibernation image was present. Continuing booting..."
	else
		warn "No hibernation resume device was specified. Ignore this if intended. Continuing booting..."
	fi
}

esh() {
	[ "$1" ] && err "$*"
	msg "Starting emergency shell."
	if ! [ -d /e ] 
	then
		mkdir /e
		if [ "$edev" && "$efstype" ] && mount "$edev" -t "$efstype" -o "${efsflags:+${efsflags},}"ro /e 2> /dev/null
		then
			msg "Emergency partition mounted."

			if [ -f /e/emergency.cpio.gz ]
			then
				msg "Extracting emergency user-space tools..."
				zcat /e/emergency.cpio.gz | cpio -vi 2>&1 | while read k
				do
					true "$((i++))"
					printxy 40 2 "Files: $(printc 82 "$i")"
					#msg "$k"
				done
				printxy 41 3 "$(printc 82 "Done. ")"
				resetcursor
			else
				err "/e/emergency.cpio.gz does not exist."
				warn "Only busybox internals are available."
			fi
		fi
	fi

	if which bash > /dev/null 2>&1
	then
		msg "Starting bash..."
		setsid cttyhack /bin/bash
		umount /e 2> /dev/null
	else
		installenv
		msg "Starting busybox shell..."
		setsid cttyhack sh
	fi
	gentoofetch # Clears the screen after exiting the emergency shell.
}

cpumodel() {
	awk '/^model name[[:space:]]*:/ {sub(/^.*: /,""); print; exit}' /proc/cpuinfo
}
totmem() {
	awk '/^MemTotal:/ {print $2/1024 "MiB"}' /proc/meminfo 
}

gentoofetch() {
	msgque=""
	clear
	resetcursor
	local yoffset="$((ysize-logoheight))"
	cat "${1:-"$banner"}"
	#printxy 2 $((yoffset+32)) "$(printc 13 ".:Gentoo:.")"
	printxy 150 $((yoffset+21)) "$(printc 13 "The choice edition.")"
	printxy 25 $((yoffset+20)) "$(printc 82 "CPU: $(cpumodel)")"
	printxy 22 $((yoffset+22)) "$(printc 82 "RAM: $(totmem)")"
	printxy 30 $((yoffset+2)) "$(printc 82 "Kernel: $(uname -sr)")"
	resetcursor
}

parsecmdline() {
	for arg in  $(cat /proc/cmdline)
	do
		value="${arg#*=}"
		arg="${arg%%=*}"

		case "${arg}" in
			init)
				init="$value"
			;;
			root)
				if rootdev=$(findfs "$value")
				then
					msg "Root device node: ${rootdev}"
				else
					unset rootdev
					err "Unable to find root device. is 'root=${value}' correct?"
				fi
			;;
			rootfstype)
				rootfstype="$value"
				msg "Root filesystem type: $rootfstype"
			;;
			rootfsflags)
				rootfslags="$value"
			;;
			edev)
				if edev=$(findfs "$value")
				then
					msg "Emergency device node: $edev"
				else
					unset edev
					warn "Unable toi find emergency device. Check your settings."
				fi
			;;
			efstype)
				efstype="$value"
				msg "Emergency filesystem type: $efstype"
			;;
			efsflags)
				efsflags="$value"
			;;
			resume)
				if resumedev=$(findfs "$value")
				then
					msg "Hibernation resume device: $resumedev"
					export rminmaj="$(printf '%u:%u\n' $(stat -L -c '0x%t 0x%T' "$resumedev"))"
					msg "min:maj - ${rminmaj}"
				else
					err "Unable to find hibernation resume device! Will NOT automatically mount ANY devices to avoid data loss"
					disablemount
				fi
			;;
			pause)
				msg "Will pause at several points during initramfs phase."
				pause() {
					[ "$1" ] && msg "$(printc 2 "PAUSE:") $*"
					msg "Press enter to continue..."
					read
				}
				pause=true
			;;
			*)
				msg "Found '$arg'. Moving on..."
			;;
		esac
	done
}

installenv() {
	setenv
	mkdir -p /bin /sbin /usr/bin /usr/sbin 2> /dev/null
	/bin/busybox --install
}

case "${0##*/}" in
	sh|*su)
		clear
		if [ $1 ]
		then
			export banner="$1"
			settermenv
			gentoofetch
		fi
		msg "We're being sourced."
		msg "We'll only give the functions to play with."
	;;
	*)
		# Populate
		for dir in /proc /sys /dev
		do
			[ ! -d "$dir" ] && mkdir "$dir"
		done

		mount -t proc none /proc
		mount -t sysfs none /sys
		mount -t devtmpfs none /dev

		settermenv
		gentoofetch
		parsecmdline

		# Resume from hibernation if possible.
		pause "Resuming from hibernate if possible."
		tryresume

		# Create the directory for real root.
		if ! errmsg=$(mkdir "$hdroot" 2>&1)
		then
			until [ -d "$hdroot" ]
			do
				err "$errmsg"
				msg "Create directory '${hdroot}' manually."
				esh
			done
		fi
		
		if [ "$pause" ]
		then
			msg "Pausing before mounting root. Dropping to a shell."
			esh
		fi

		if [ ! -z "$rootdev" ]
		then
			if ! errmsg=$(mount -o "$rootfsflags",ro "$rootdev" "$hdroot" 2>&1)
			then
				warn "Failed to mount root filesystem into '${hdroot}'."
				warn "$errmsg"
				msg "You have to mount it manually."
				esh
				until mountpoint "${hdroot}"
				do
					esh "'${hdroot}' is not a mountpoint."
				done
			fi

			if [ -f "hdroot/${init#/}" ]
			then
				umount /dev
				umount /sys
				umount /proc
				msg "Say goodbye to initramfs. Switching to real root."
				pause "Last pause."
				exec switch_root "$hdroot" "$init"
			else
				warn "Didn't find ${init} under '${hdroot}'."
				msg "You may try to work your way to booting the system manually."
				esh
				while :
				do
					esh "You're still inside initramfs."
				done
			fi
		else
			err "Didn't found 'root=' on kernel command line."
			msg "You need to mount root and switch init."
			while :
			do
				esh "You are on your own."
			done
		fi
		err "init is about to be killed. This is bad!"
	;;
esac

msg "EOF"
FILE gentoo_h.ansansi logo
FC2S77IERAOVWABWLVARJMCX3LAAVJDGBBNWMG6S2QEMHUXMA4DQIQYAHAADQADJGYZ7PO7KH5RHRKDN
DTX6L4UIIPUFESB4WAYFRVMPNCDMAAYSIMGI6EJ47YQNJEEDAIRIBAEDD2CKGAQPOGRQ5CHAQI4OUQJA
XABHDQKAEAUT4WOBGSYSNLDCCDR2IYANRC5KCEEJ2GW5HDSVMVNVPN4TILM3JHLJYXUGDNEFMRNAQZS6
3PUXYBADKF54YHYSSFKGONVN5OVFZRAO76VKVSKL3J2I57MZUUJYGX4YG44VNPYVUWHDPQS4HG43UXTH
FGBNAJZHTQLCVWPF5XXINACEJZTSYN3DPUKVURGGGSX5AZZWDU53HPLVKNZUTXKPB6ONZYQUV62HE5VU
WQZVVXOLJNTN5GONZQMP5LMUCTGJGGR23K3AJBE7VAR6ZZREAUUQYB7TIAMAQFEMIXC6ESNZXA7CGUCA
EA4BACCOAQB4FAPQBKQAQICQCCBEBPECAYQUAEB2EEGJSFNMDMVRPSAIA7C2SEMGP4SGWSTSY5ICFFH2
3BUIXUMWRLW3ZK25U6WUAP7HKMRMPOVFVKZOT43Q4JJP7VHI3SAVGIHIAZMPIQIL5XMQAPF5L4MV47MO
T6Z53EQZGPQDYGGPCHXAHE3CCRQEJ7XQM3LXVQPFJYZBKDUFJYQIOESJH2TGYHBOABVWFYWCQ6LLCUQK
JA5Q7T3KTQU7LNGQOI4WYBPR7HPN5YGXKYXDOHCLEH5VNVSYAFUGJNP2IQCAJTZXMOMTNWJZONDVSANE
FH4Y6QOAPZEHAVTVGSPOJMWA2STNMVCJE72LTFRS4ALKJZ6DGZ3UVJYWGSAJQRHLEWWHSDJJUVMGRJYU
2CJRKQJE3WCS5XKHCQCSDRW3PHHE5ICQ7LYYVJO7F2UNWQ67XBTS3SU6ILIFXFZOBN3FCXIHLQ5VZEYS
CM4ULXGDHOPOH4IFSNL7W5TYQ7RQC7VLGZPIVKQXZIAR4CXT3TE7YZ4Y2M2GSB5CJYDHG2P6J2HCNLS5
Q3MGT7NSAZ53W6JVAUW3FJ27HYUSBXMUEJC65THSAWP7XNXR2QUXL6R3QEJIKDJQLTOJFXV5WVOJ4E5H
LMGNCA5LRIM67ZVPYHGNGS36WZPU66I2DCBMUXHKNGV4PUUCY4LEQ5GHWHOHI4SAS5FYPBACT46SJISR
U45XB7UP2SYZJL3ME2XWE2VUISHLWKEJKX3X3XKID3BHVVQ4LEMLQ3J4ZVDGIA32UOZ2CHVGPRQINT4G
UD43RPAFBQI5PHBW7PDNDPPLG6GHLMYSGG5XDRD7H3A4Y7FND5KDAF7AP4QO6E6CBASEIIGR2UGYCIOR
BZCNIG7MHXIKZRLT2QNOVWHI47GJIC7DUOJIMO6QZLCPUVHOWTQCYG6NQY4B2JFVERU64HPGVL64JI22
OZMDUA56O2JROOFMW2YKDU2Z6ODJ3HE3PL5NG6KII7OKWCTNVZQAUOFZFZYFE7KLMZ7VLKVH4SHD4SDM
ZHPENH5AB7G4P57OC4LWLT67TNSVKEFFLGJV66EIE3YRHIGCPCR6QDGRJ7G4VRLR5LZMG4JVMRIRFIZU
AJ2HLVYGY6PK5GM4M74IXSNDPR6T4U3MRTCWZT3SS62BRIOFWFVDHSOLYMXQEA6SMNMHXBZXVVILOUMY
JCQSNJG5UTXHFLZI2ZRGN37GTBAAGDV24K7PQAKWT2CW3KOYBUXSRY47VJZ3HTQ4UMTGMFQJOIGCVVNT
MHXDND4WODAWVP2BYRJDATOU5BPFKFQCEE55URC6NCVX2AD34WNDZHSYIQDNWHVYZ77IU6KS5FUI423G
Y3AREYCDCORYLVE3JYXNEBRFEGSD72VWVVN2UXN33K777QGAJQVXOIR3I6OWTWSQT3YMA7WQF5YWDBVJ
2NC74NZ2C4J3FH5BI4WVDON4KYB2IK4IALD5KU25VUEBWYR26VNLVUM5FEC7IWIEPTLOFNCDRUVCGT57
LXUUMOZZ52FTOLLXBVLEHHF3QNKWGXLMQGYDHR46OKZSCLAURW2GHWUM4ADWU7LQNFAXYILNI4VYDMVI
BC5FX7XBALRPZ6JH3INRURQ4GCMM3ULJ56CATGMPIOHWGECCMLFBJZBYBJFTYCX7RE4ODZ64VK567GBK
ZX3S7JC6HD6B7IZPVILTSBVYLNJFUORM4LTO5PWOSBB23BPI6GDCCUEEJCHGDB5QEGIAQ4UQREPELGYB
UWMR7VLNQIGFH22XZHEVMLPA6ARYWCRWVAJUH4ZYJFAIP5TDZRGE6OWVTGZIC6EAPIU57YDQUVDFSLPX
OHMYDV6SFPONN5RTZQPRYEQYG42CL37AZPOTP5VROO57G2GWFGJ3A4TUV5SNJC4O5CKAM6HE6XNYGKDC
R7EBXIEFM2WNWF36HHKWWDKEOWTZ3KCSNHOUBY2QS7H75B7AXBJMQOUXOP6OO7WPRSSNCMQNPMXXG7OE
RWCUZPRJNG573B3UVCSCYCJTLDPYBWQKYUZTW7KTKNQNL6QQZA2S5PWD7BAVLHLSJTS7KHB4HVBA4S75
XBVSGN67OM53IZDM7SITEZRPOV4G42RH7FO6XVFPARN3JZ4J5MJ3IBWUWE7BGTLQPJET6643P644NDBU
CN4MXZGKRTNB3BIJVDXFOAHXHFQ4EKAB4UL57B5EACRKIMG6WEMWATFRL3MNT6I7ZHQEJFKCMKYKZWQ2
CJC4AJQOTXVPUAW5LY2P4DTXWQ35DDZZGJZPB4EXGKKWMPUIIGTWXJOW63FOWI6EJL55YP3VFAMPQHZO
FDS4FZCPHA5JK6I75K4YVW55LD7653HJSDPQU3RB67HO6XECRBTIN4UXSJIAV6U5HYRR2YEBX32QJ6HM
6UUULYX7IJIT7FI27YLQFZYATU5WGVCCQETWUSBF3SQG7GF4KO74SYAWZQTT6BHRB4L7TNIDMGFXCFGC
BYZGKJ2RQXX43LZ3UZQJK4Q5K6UH6EBCMN7TET3B7ITWMM24CAQ5RWOJJF2YHZAMBJMNXH4NMC36YC3H
WDJFMKU3YE4ECQRDQAYJ7KFENPJ6GAEHM5A7BAXLQBRLF5RCJT3IRAZOSAGVD4IO6KUHM4KQBHCNR3II
6LHQEVILJGFTIIOHENF2F4ECH27K3QURQOCJWFVT6L7ETTJ2WN3RTWWMUGGAMY76L762COMR65RJZYXP
7CQVY2A2BXPXGZEEKVHUEDBL7WCQ7C4ZH7H2AODUUS4YCGEPQHJMLMKFTXGWRLV6EIF5JAECZYMQYLLK
TB2DS4APBXCV2SZ3BLMD6PDRO5Y5WTXHDZ6SSWTTM6ALVWOCP75N6CUTHPEX3V3ZY3EQDR6WHUI6RG7D
RDGDLR6LMIMJNZHF64PNOWGI6BC4G2RQT7L7WHTWMBOYINU2FKKUE2PAV7TIHR7BVUUE32G5H34ODRWU
6VUQOFRGQARKOWL4HELKAB76XYATEKDCNZR6ZL3WVMAX6S7UQVLFVIMRKMACIVPAL3PSEPG7YI2WT33O
7HJDNDY3EHMUHKUXQUNYPEDQ6JDAQZYQCGGHTPED7FIU2YCTPFCPMDIBYCQE7AM277ZYDNHYTK7A3DGV
GRI2W4PVFWR2T24FFIQVTQHPZMCSKS5TKFI65BBKYROM5AUZ7X6DO7KRZJXISBDMK6TT4T7GTZQOPAIB
I4MXXQQEYIPHMAQFNVGDJRRVJHQ6RJUH7KNV35XOVNGLMVSVDVRO4IUWVMXY3NQBDR6XUJ77JWHIRSTN
IRYASXIAX3NGAVQPMZWLMPWACFW3D3G6E3COSWL543JHD2R7X33SQ7DSAJPXR7YZMHN6GRDYCXILXW3T
ROVSLTWORHCPGHTLKB6DDHBVOW4XUM2RYL477RLCGDADEQFY2FXBBCG7D2DZAJWLAOYXKNZ73MOEAPT6
SNBNTEFVVOYC7266AHRNSLT4S3EAK2O6SLQX2V6YCVAMHWKJ32TWUFKZQG4IKP5DQZYB6BHMDICI44KE
UA5XBHETDFL75UCQULXVVGVJOBOYZBJB33FGWKV5RXMAJEA4NDWLWUKPWT7GQ7LYMEUMWC32M6D6E4ES
RLA52LNAGXWPCIU2U7X4ESL5DH2PD37JECY3LSVNSUHCZE3KJ3BCUIEDGQMQ4YDZIHV3N3TFUUCAYIXG
Y2TSCYVYE522E5HBCXKQWRWT2IVDIKJNJOV4HAQFOURGDDAHUANKZTTLCBA7ATFNKSJ27X4KGCXGRXGJ
F5JQ4TQFHKAFKZ67JJ2QED7UMGVHNSA2CQO3YQZMSFRMNTSEIXZVJJMHLZW2PZE27HFX5BUWPLRPYC5D
WGYSKSWIAU5Q3IIWRCYNDFQ7OOVFEN5NMOQT3NYY2FDNLMG5HBQZJWWRKBLZQGNBXRI27GD2C4SACTSW
RIBE4CUJTQIYOFODSRJOKPZYEFZ7XUKJERB3PJESQEXR5U4FVQDHLGB54NBPEBTOU5ASXAFN6RFEPOPG
EE5QJQA7C6KDDEW6NSN32GOOMGCWIDJXXGQ2DR7H5GAKP3H43IAVLNQLN5IF7CNSZIDI6F7P7QFBMRUQ
7FURTKR32UR6RUZVDOU3C7CTGPFC2XLBLOCNDKPNKDGAHQQZ2TZZEFDADKG5E74CYNPAETH3UHNBI5N7
KOYIJKCSUJYUN55QIN4D4BR2QQE3RULW3AKXAEPXRBNOK===

Uncompress with base32 -d gentoo_h.ans | zstd -d