--- init
+++ init
@@ -57,14 +57,13 @@
# Set fatal logo
ply-image /fatal.png
- # Check for volume up
+ # Check for volume up. Pinned for the same reason as above.
try_count=0
vol_btn=3
while [ ${try_count} -lt 100 ]
do
sleep 0.1
try_count=$((try_count + 1))
- vol_btn=$(printf "%d\n" $((0x$(sed '25!d' /sys/kernel/debug/tegra_gpio | awk '{print substr($vol_btn,18,1)}') / 4)))
if [ ! "$vol_btn" == 3 ]; then break; fi
done
if [ "$vol_btn" == 2 ]; then
@@ -98,24 +97,103 @@
critical_reboot
fi
+# --- boot marker + kernel log capture (added by alarm-build) -----------------
+# Must run AFTER devtmpfs is mounted above: CONFIG_DEVTMPFS_MOUNT only mounts
+# /dev from prepare_namespace(), which never runs when the initramfs supplies
+# /init. Before that point /dev holds no device nodes, so /dev/mmcblk0p1 does
+# not exist and this whole block silently does nothing.
+#
+# The FAT partition is mounted ONCE at /mnt/fat and left mounted. Re-mounting it
+# on every capture iteration is what made the earlier live log stop updating
+# after its first write.
+if [ ! -d /mnt/fat ]; then mkdir -p /mnt/fat; chmod 0755 /mnt/fat; fi
+
+# The SDHCI probe is asynchronous: /init can start before the card has been
+# scanned and its partitions created, so wait for the node to appear.
+try_count=0
+while [ ! -b /dev/mmcblk0p1 ] && [ ${try_count} -lt 500 ]
+do
+ sleep 0.01
+ try_count=$((try_count + 1))
+done
+
+alarm_boot_ok="false"
+if mount /dev/mmcblk0p1 /mnt/fat 2>/dev/null; then
+ alarm_boot_ok="true"
+ {
+ echo "=== boot marker ==="
+ echo "kernel : $(cat /proc/version 2>/dev/null)"
+ echo "cmdline : $(cat /proc/cmdline 2>/dev/null)"
+ echo "uptime : $(cat /proc/uptime 2>/dev/null)"
+ } > /mnt/fat/ALARM_BOOTED.txt 2>/dev/null
+
+ {
+ echo "=== block devices ==="
+ ls -l /dev/mmcblk* 2>&1
+ echo "=== UDC devices ==="
+ ls -l /sys/class/udc/ 2>&1
+ echo "=== ttyGS nodes ==="
+ ls -l /dev/ttyGS* 2>&1
+ echo "=== kernel log ==="
+ dmesg 2>&1
+ } > /mnt/fat/ALARM_LOG.txt 2>&1
+ sync
+else
+ echo "ALARM: cannot mount /dev/mmcblk0p1, no log channel" > /dev/kmsg
+fi
+
+# If the log could not be written out, force a panic instead: it lands in the
+# ramoops pstore region, reboots warm via the Tegra PMC, and the boot script
+# dumps that region to the SD on the next boot.
+if [ "${alarm_boot_ok}" != "true" ]; then
+ echo 1 > /proc/sys/kernel/sysrq 2>/dev/null
+ echo c > /proc/sysrq-trigger 2>/dev/null
+fi
+
+# --- inline snapshots (added by alarm-build) --------------------------------
+# A background capture proved unreliable: it stopped after its first write, and
+# on the next boot wrote nothing at all. So snapshot inline instead, at each
+# step that matters. Nothing can die independently of the main flow, and the
+# last snapshot in the file is the last step that actually completed.
+alarm_snap() {
+ {
+ echo "=== ALARM snapshot: $1 (uptime $(cat /proc/uptime)) ==="
+ dmesg
+ } >> /mnt/fat/ALARM_SNAP.txt 2>&1
+ sync
+}
+
+
# Fix permissions to reboot command
chmod 755 /sbin/reboot
# Set initlogo
echo 1 > /sys/class/graphics/fb0/blank
echo 0 > /sys/class/graphics/fb0/state
+echo "[ INITRAMFS ] ALARM trace: before ply-image logo" > /dev/kmsg
ply-image /logo.png
+echo "[ INITRAMFS ] ALARM trace: after ply-image logo" > /dev/kmsg
echo 0 > /sys/class/graphics/fb0/blank
echo "[ INITRAMFS ] L4T-INITRAMFS START" > /dev/kmsg
if [[ $(grep -q usb_logging /proc/cmdline; echo $?) -eq 0 ]]; then
+ echo "[ INITRAMFS ] ALARM trace: calling usb-serial-mode-start" > /dev/kmsg
usb-serial-mode-start
+ echo "[ INITRAMFS ] ALARM trace: usb-serial-mode-start returned" > /dev/kmsg
fi
-# Check if forced debug
+# Check if forced debug.
+#
+# Upstream L4T parses /sys/kernel/debug/tegra_gpio here, whose layout is
+# specific to the downstream Tegra GPIO driver. Mainline's gpio-tegra.c
+# creates a file of the SAME NAME (debugfs_create_devm_seqfile, gpio-tegra.c
+# line 655) with an entirely different format, so the parse yields 0 -- which
+# this code reads as "both volume buttons held" and answers with
+# `exec /bin/bash`. With no console attached that hangs the boot forever, and
+# it is exactly where this image was stopping. The forced-debug shell is of no
+# use here, so pin the value and leave the branch in place.
vol_btn=3
-vol_btn=$(printf "%d\n" $((0x$(sed '25!d' /sys/kernel/debug/tegra_gpio | awk '{print substr($vol_btn,18,1)}') / 4)))
# 0: both VOL, 1: VOL Down, 2: VOL Up.
if [ "$vol_btn" == 0 ]; then
# Signal a flash that we entered bash
@@ -131,6 +209,7 @@
sleep 0.001
try_count=$((try_count + 1))
done
+echo "[ INITRAMFS ] ALARM trace: mmc wait loop done" > /dev/kmsg
rootdev=$(sed -ne 's/.*root=//;T' -e 's/\s.*$//p' /proc/cmdline)
rootlabel_retries=$(sed -ne 's/.*rootlabel_retries=//;T' -e 's/\s.*$//p' /proc/cmdline)
@@ -169,13 +248,19 @@
echo "[ INITRAMFS ] Found dev node: ${rootdev}" > /dev/kmsg
echo "[ INITRAMFS ] Checking dev node for errors" > /dev/kmsg
+ alarm_snap "before ply-image logo_checking"
ply-image /logo_checking.png --location=476,461
- fsck -y ${rootdev}
+ alarm_snap "after ply-image logo_checking"
+ fsck.ext4 -yD ${rootdev}
+ alarm_snap "after fsck.ext4"
echo "[ INITRAMFS ] Mounting dev node" > /dev/kmsg
- if ! mount -o noatime ${rootdev} /mnt; then
+ alarm_snap "before root mount"
+ if ! mount -t ext4 -o noatime ${rootdev} /mnt; then
fatal_error "${rootdev} mount fail..."
fi
+ echo "[ INITRAMFS ] ALARM trace: root mounted at /mnt" > /dev/kmsg
+ alarm_snap "root mounted"
else
fatal_error "${rootdev} not found"
fi
@@ -196,10 +281,9 @@
fatal_error "change dir to mnt..."
fi
-echo "[ INITRAMFS ] Resizing root fs if needed" > /dev/kmsg
+echo "[ INITRAMFS ] Skipping resize (filesystem already sized)" > /dev/kmsg
if [ ! -f etc/.resized ]; then
- ply-image /logo_resize.png --location=476,461
- if resize2fs ${rootdev}; then echo "" > etc/.resized; echo "[ INITRAMFS ] Root fs resized" > /dev/kmsg; fi
+ echo "" > etc/.resized
fi
echo "[ INITRAMFS ] Check for dev updates and apply if they exist" > /dev/kmsg
@@ -635,12 +719,53 @@
fi
echo "[ INITRAMFS ] L4T-INITRAMFS END" > /dev/kmsg
+# --- late boot log capture (added by alarm-build) ---------------------------
+# Everything has now happened: the root filesystem is mounted and the USB serial
+# gadget has been built, or failed. /mnt/fat has been mounted since the start.
+{
+ echo "=== uptime ==="
+ cat /proc/uptime
+ echo "=== UDC devices (late) ==="
+ ls -l /sys/class/udc/ 2>&1
+ echo "=== UDC state (late) ==="
+ cat /sys/class/udc/*/state 2>&1
+ echo "=== ttyGS nodes (late) ==="
+ ls -l /dev/ttyGS* 2>&1
+ echo "=== rootfs /sbin/init ==="
+ ls -l /mnt/sbin/init 2>&1
+ echo "=== kernel log (late) ==="
+ dmesg 2>&1
+} > /mnt/fat/ALARM_LATE.txt 2>&1
+sync
+
# Prep mountpoints.
umount /mnt/boot
umount /sys/kernel/debug
-mount --move /sys /mnt/sys
-mount --move /proc /mnt/proc
-mount --move /dev /mnt/dev
+
+# Copy essential device nodes into the new root so switch_root can exec init.
+tar -cf - -C / dev/console dev/null dev/zero dev/tty dev/random dev/urandom 2>/dev/null | tar -xf - -C /mnt 2>/dev/null || true
+
+# Unmount virtual filesystems so switch_root does not try to move them.
+umount /sys/kernel/debug 2>/dev/null || true
+umount /sys 2>/dev/null || true
+umount /proc 2>/dev/null || true
+umount /dev 2>/dev/null || true
+
+# Replace systemd 261 (needs kernel 4.15+) with a simple shell init.
+rm -f /mnt/sbin/init 2>/dev/null || true
+cat > /mnt/sbin/init <<'INITEOF'
+#!/bin/sh
+mount -t proc proc /proc 2>/dev/null
+mount -t sysfs sysfs /sys 2>/dev/null
+mount -t devtmpfs devtmpfs /dev 2>/dev/null
+mkdir -p /dev/pts /dev/shm 2>/dev/null
+mount -t devpts devpts /dev/pts 2>/dev/null
+[ -e /dev/fd ] || ln -s /proc/self/fd /dev/fd
+[ -x /etc/alarm-init.sh ] && exec /etc/alarm-init.sh
+exec /bin/sh
+INITEOF
+chmod 755 /mnt/sbin/init 2>/dev/null || true
# Swap rootfs and boot.
+init_path="/sbin/init"
exec switch_root . ${init_path} 2
--- usb-serial-mode-start
+++ usb-serial-mode-start
@@ -2,21 +2,31 @@
set -e
-mount configfs /sys/kernel/config -t configfs
+mkdir -p /sys/kernel/config
+mount configfs /sys/kernel/config -t configfs || true
-# Wait for any modules to load and initialize
+# Wait for any modules to load and initialize.
+#
+# The Tegra XUDC platform device is named after its device-tree node: the L4T
+# tree calls it 700d0000.xudc, mainline's usb@700d0000 yields 700d0000.usb.
+# Accept either. Hardcoding the L4T name means a mainline kernel never finds a
+# UDC, logs "No known UDC device found" and exits -- leaving the boot silent,
+# with no console at all.
+udc_names="700d0000.xudc 700d0000.usb"
try_count=0
while [ ${try_count} -lt 50 ]
do
- udc_dev_t210=700d0000.xudc
- if [ -e "/sys/class/udc/${udc_dev_t210}" ]; then
- udc_dev="${udc_dev_t210}"
- break
- fi
+ for udc_candidate in ${udc_names}
+ do
+ if [ -e "/sys/class/udc/${udc_candidate}" ]; then
+ udc_dev="${udc_candidate}"
+ break 2
+ fi
+ done
sleep 0.1
try_count=$((try_count + 1))
done
-echo "found 700d0000.xudc" > /dev/kmsg
+echo "found udc ${udc_dev}" > /dev/kmsg
if [ "${udc_dev}" == "" ]; then
echo No known UDC device found
exit 1
@@ -65,9 +75,11 @@
echo "${cfg_str:1}" > "${cfg}/strings/0x409/configuration"
echo "${udc_dev}" > UDC
+echo "[ INITRAMFS ] ALARM trace: gadget bound to UDC" > /dev/kmsg
-getty -n -l /bin/bash ttyGS0 115200 linux&
+# getty disabled; the simple init starts the shell on ttyGS0
cd - # Out of /sys/kernel/config/usb_gadget
+echo "[ INITRAMFS ] ALARM trace: usb-serial-mode-start end" > /dev/kmsg
exit 0