#!/bin/busybox sh
# Bring-up initramfs for Google Pixel 5 (redfin), downstream 4.19 kernel, stage K: like J, but switch_root to an ext4 rootfs on userdata (sda19) when one is present.
# Loads Android's full first-stage module set, then USB gadget + telnet.
# Diagnostics are dumped to the inactive boot_a partition (sda6) before any self-reboot.
/bin/busybox --install -s /bin
/bin/busybox --install -s /sbin
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
mkdir -p /proc /sys /dev /tmp /run
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev 2>/dev/null || mdev -s
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
mount -t configfs configfs /sys/kernel/config 2>/dev/null
mount -t tmpfs tmpfs /tmp
mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null
log() { echo "pmos-redfin: $*" > /dev/kmsg; }
log "init started $(cat /proc/uptime)"
echo 10 > /proc/sys/kernel/panic
[ -e /sys/class/firmware/timeout ] && echo 1 > /sys/class/firmware/timeout
LOGDEV=/dev/sda6
dumpdiag() {
	{
		echo "PMOSLOG1 $(cat /proc/uptime) $1"
		echo "== cmdline"; cat /proc/cmdline
		echo "== version"; cat /proc/version
		echo "== udc"; ls /sys/class/udc 2>&1
		echo "== ssusb mode"; cat /sys/bus/platform/devices/a600000.ssusb/mode 2>&1
		echo "== extcon"; for e in /sys/class/extcon/*; do echo "$e: $(cat $e/name 2>/dev/null) $(cat $e/state 2>/dev/null | tr '\n' ' ')"; done
		echo "== power_supply"; for p in /sys/class/power_supply/*; do echo "$p online=$(cat $p/online 2>/dev/null) present=$(cat $p/present 2>/dev/null) type=$(cat $p/type 2>/dev/null)"; done
		echo "== net"; ls /sys/class/net
		echo "== gadget"; ls -R /sys/kernel/config/usb_gadget 2>&1 | head -40; cat /sys/kernel/config/usb_gadget/g1/UDC 2>&1
		echo "== lsmod"; lsmod
		echo "== dmesg"; dmesg
	} > /tmp/diag.txt 2>&1
	i=0; while [ ! -b $LOGDEV ] && [ $i -lt 30 ]; do i=$((i+1)); sleep 1; done
	if [ -b $LOGDEV ]; then
		dd if=/tmp/diag.txt of=$LOGDEV bs=1M count=8 conv=notrunc 2>/dev/null; sync
		log "diag written to $LOGDEV ($(wc -c < /tmp/diag.txt) bytes)"
	else
		log "no $LOGDEV, diag not saved"
	fi
}
( sleep 300; log "dead-man timer fired"; dumpdiag deadman; sync; sleep 1; echo b > /proc/sysrq-trigger ) &
DEADMAN=$!
REL=$(ls /lib/modules | grep -v '^modules' | head -n1)
# Keep the CPUs out of deep idle states until power management is understood.
for d in /sys/devices/system/cpu/cpu*/cpuidle/state[1-9]*/disable; do echo 1 > $d 2>/dev/null; done
n=0; f=0; : > /tmp/failed.txt
for m in $(cat /lib/modules/modules.early); do
	log "modprobe $m"
	if modprobe "$m" 2>/tmp/modprobe.err; then n=$((n+1)); else f=$((f+1)); echo "$m" >> /tmp/failed.txt; log "modprobe $m failed: $(head -c 160 /tmp/modprobe.err)"; fi
done
log "pass1 loaded=$n failed=$f uptime=$(cut -d' ' -f1 /proc/uptime)"
# Second pass: dependencies that were only probe-deferred the first time (smem/hwspinlock) are up now.
n2=0; f2=0
for m in $(cat /tmp/failed.txt); do
	if modprobe "$m" 2>/tmp/modprobe.err; then n2=$((n2+1)); log "pass2 modprobe $m OK"; else f2=$((f2+1)); log "pass2 modprobe $m failed: $(head -c 160 /tmp/modprobe.err)"; fi
done
log "pass2 loaded=$n2 failed=$f2 uptime=$(cut -d' ' -f1 /proc/uptime)"
[ -e /sys/module/lpm_levels/parameters/sleep_disabled ] && echo Y > /sys/module/lpm_levels/parameters/sleep_disabled
# devtmpfs does not populate here; create nodes and wait for the UFS user partition.
i=0
while [ $i -lt 15 ]; do mdev -s; [ -b /dev/sda19 ] && break; i=$((i+1)); sleep 1; done
log "sda19 present after ${i}s: $([ -b /dev/sda19 ] && echo yes || echo no)"
if [ -b /dev/sda19 ] && ! grep -q pmos.noroot /proc/cmdline; then
	mkdir -p /newroot
	if mount -t ext4 -o rw /dev/sda19 /newroot 2>/tmp/mnt.err && [ -x /newroot/sbin/init ]; then
		log "ext4 rootfs found on sda19, switching root (uptime $(cut -d' ' -f1 /proc/uptime))"
		kill $DEADMAN 2>/dev/null
		mkdir -p /newroot/lib/modules
		[ -d /newroot/lib/modules/$REL ] || cp -a /lib/modules/$REL /newroot/lib/modules/
		mount --move /dev /newroot/dev
		umount /sys/kernel/config 2>/dev/null; umount /sys/kernel/debug 2>/dev/null
		umount /proc; umount /sys; umount /tmp
		exec switch_root /newroot /sbin/init
		log "switch_root failed, staying in initramfs"
		mount -t proc proc /proc; mount -t sysfs sysfs /sys; mount -t tmpfs tmpfs /tmp
	else
		log "no usable ext4 rootfs on sda19: $(head -c 120 /tmp/mnt.err 2>/dev/null)"
		umount /newroot 2>/dev/null
	fi
fi
for d in /sys/devices/system/cpu/cpu*/cpuidle/state[1-9]*/disable; do echo 1 > $d 2>/dev/null; done
[ -e /sys/bus/platform/devices/a600000.ssusb/mode ] && { echo peripheral > /sys/bus/platform/devices/a600000.ssusb/mode; log "ssusb mode -> peripheral"; }
i=0
while [ $i -lt 60 ]; do
	udc=$(ls /sys/class/udc 2>/dev/null | head -n1)
	[ -n "$udc" ] && break
	i=$((i+1)); sleep 1
done
log "udc=$udc after ${i}s"
setup_gadget() {
	G=/sys/kernel/config/usb_gadget/g1
	mkdir -p $G || return 1
	cd $G
	echo 0x18d1 > idVendor
	echo 0x4ee3 > idProduct
	echo 0x0200 > bcdUSB
	mkdir -p strings/0x409
	echo "0123456789" > strings/0x409/serialnumber
	echo "postmarketOS" > strings/0x409/manufacturer
	echo "Pixel 5 redfin pmOS bringup" > strings/0x409/product
	mkdir -p configs/c.1/strings/0x409
	echo "usbnet" > configs/c.1/strings/0x409/configuration
	echo 500 > configs/c.1/MaxPower
	for fn in ncm rndis ecm; do
		modprobe usb_f_$fn 2>/dev/null
		if mkdir functions/$fn.usb0 2>/dev/null; then
			ln -s functions/$fn.usb0 configs/c.1/ && log "gadget function $fn" && break
		fi
	done
	[ -n "$udc" ] || return 1
	echo "$udc" > UDC || { log "writing UDC failed"; return 1; }
	cd /
}
setup_gadget || log "gadget setup FAILED"
i=0
while [ $i -lt 30 ]; do
	[ -d /sys/class/net/usb0 ] && break
	i=$((i+1)); sleep 1
done
if [ ! -d /sys/class/net/usb0 ]; then
	log "no usb0 after ${i}s, dumping diag and rebooting"
	dumpdiag nousb0; sync; sleep 1; echo b > /proc/sysrq-trigger
fi
ip link set usb0 up 2>/dev/null || ifconfig usb0 up
ip addr add 172.16.42.1/24 dev usb0 2>/dev/null || ifconfig usb0 172.16.42.1 netmask 255.255.255.0
log "usb0 configured, uptime $(cut -d' ' -f1 /proc/uptime)"
# Several independent ways in, so one broken applet does not leave us blind.
mkdir -p /www/cgi-bin
ln -s /tmp /www/tmp
cat > /www/cgi-bin/run <<'CGI'
#!/bin/sh
echo "Content-Type: text/plain"; echo
cmd=$(httpd -d "${QUERY_STRING#cmd=}")
eval "$cmd" 2>&1
CGI
cat > /www/cgi-bin/reboot <<'CGI'
#!/bin/sh
echo "Content-Type: text/plain"; echo; echo rebooting
sync; (sleep 1; echo b > /proc/sysrq-trigger) &
CGI
chmod 755 /www/cgi-bin/run /www/cgi-bin/reboot
httpd -p 80 -h /www; log "httpd rc=$?"
telnetd -l /bin/sh -p 23 -b 172.16.42.1; log "telnetd rc=$?"
telnetd -F -l /bin/sh -p 2300 2>/tmp/telnetd.err &
(while true; do nc -ll -p 2323 -e /bin/sh 2>/tmp/nc.err; sleep 1; done) &
kill $DEADMAN 2>/dev/null
log "servers started, dead-man timer cancelled"
dumpdiag telnetup
while true; do dmesg > /tmp/dmesg.txt 2>/dev/null; sleep 10; done
