There is another method to mount rootfs on SSD in JetPack 4.4. Now initrd is located with kernel image in /boot/ folder on /dev/mmcblk0p1. Loaded initrd is set in INITRD initrd_file
line in /boot/extlinux/extlinux.conf on /dev/mmcblk0p1.
LABEL primary
MENU LABEL primary kernel
LINUX /boot/Image
INITRD /boot/initrd
It’s possible to unpack initrd:
#!/bin/bash
sudo mkdir newinitrd
cd newinitrd
sudo cp /boot/initrd …/initrd
gzip -cd …/initrd | cpio -imd
Now we can change script init
to change variable rootdev
.
My test variant of init
:
#!/bin/bash
initrd_dir=/mnt/initrd;
dhclient_flag=“true”;
count=0;
echo “Starting L4T initial RAM disk” > /dev/kmsg;
#Mount procfs, devfs, sysfs and debugfs
mount -t proc proc /proc
if [ $? -ne 0 ]; then
echo “ERROR: mounting proc fail…” > /dev/kmsg;
exec /bin/bash;
fi;
mount -t devtmpfs none /dev
if [ $? -ne 0 ]; then
echo “ERROR: mounting dev fail…” > /dev/kmsg;
exec /bin/bash;
fi;
mount -t sysfs sysfs /sys
if [ $? -ne 0 ]; then
echo “ERROR: mounting sys fail…” > /dev/kmsg;
exec /bin/bash;
fi;
mount -t debugfs none /sys/kernel/debug/
if [ $? -ne 0 ]; then
echo “ERROR: mounting debugfs fail…” > /dev/kmsg;
exec /bin/bash;
fi;
create reboot command based on sysrq-trigger
if [ -e “/proc/sysrq-trigger” ]; then
echo -e “#!/bin/bash \necho b > /proc/sysrq-trigger;” > /sbin/reboot;
chmod 755 /sbin/reboot;
fi;
ssdroot parameter at extlinux.conf
rootdev=“$(sed -ne ‘s/.\bssdroot=/dev/([abcdefklmnps0-9])\b.*/\1/p’ < /proc/cmdline)”
if [ “${rootdev}” != “” ]; then
echo “Root from sddroot parameter found: ${rootdev}” > /dev/kmsg;
fi
if [ “${rootdev}” == “” ]; then
real root parameter
rootdev=“$(sed -ne 's/.\broot=/dev/([abcdefklmnps0-9])\b./\1/p’ < /proc/cmdline)"
fi
if [ “${rootdev}” == “” ]; then
uuid_regex=‘[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}’
rootdev="$(sed -ne "s/.\broot=(PARTUUID=${uuid_regex})\b.*/\1/p” < /proc/cmdline)"
fi
if [ “${rootdev}” != “” ]; then
echo “Root device found: ${rootdev}” > /dev/kmsg;
fi
added branch for nvme
if [[ “${rootdev}” == nvme* ]]; then
if [ ! -e “/dev/${rootdev}” ]; then
count=0;
while [ ${count} -lt 50 ]
do
sleep 0.2;
count=expr $count + 1
;
if [ -e “/dev/${rootdev}” ]; then
break;
fi
done
fi
if [ -e “/dev/${rootdev}” ]; then
echo “Found dev node: /dev/${rootdev}” > /dev/kmsg;
else
echo “ERROR: ${rootdev} not found” > /dev/kmsg;
exec /bin/bash;
fi
mount /dev/${rootdev} /mnt/;
if [ $? -ne 0 ]; then
echo “ERROR: ${rootdev} mount fail…” > /dev/kmsg;
exec /bin/bash;
fi;
elif [[ “${rootdev}” == PARTUUID* ]]; then
count=0;
while [ ${count} -lt 50 ]; do
sleep 0.2;
count=“$(expr ${count} + 1)”
mount "${rootdev}" /mnt/;
if [ $? -eq 0 ]; then
break;
fi
done
mountpoint /mnt/;
if [ $? -ne 0 ]; then
echo “ERROR: ${rootdev} mount fail…” > /dev/kmsg;
exec /bin/bash;
fi;
elif [[ “${rootdev}” == mmcblk* ]]; then
if [ ! -e “/dev/${rootdev}” ]; then
count=0;
while [ ${count} -lt 50 ]
do
sleep 0.2;
count=expr $count + 1
;
if [ -e “/dev/${rootdev}” ]; then
break;
fi
done
fi
if [ -e “/dev/${rootdev}” ]; then
echo “Found dev node: /dev/${rootdev}” > /dev/kmsg;
else
echo “ERROR: ${rootdev} not found” > /dev/kmsg;
exec /bin/bash;
fi
mount /dev/${rootdev} /mnt/;
if [ $? -ne 0 ]; then
echo “ERROR: ${rootdev} mount fail…” > /dev/kmsg;
exec /bin/bash;
fi;
elif [[ “${rootdev}” == sd* ]]; then
if [ ! -e “/dev/${rootdev}” ]; then
while [ ${count} -lt 50 ]
do
sleep 0.2;
count=expr $count + 1
;
if [ -e “/dev/${rootdev}” ]; then
break;
fi
done
fi
if [ -e “/dev/${rootdev}” ]; then
echo “Found dev node: /dev/${rootdev}” > /dev/kmsg;
else
echo “ERROR: ${rootdev} not found” > /dev/kmsg;
exec /bin/bash;
fi
mount /dev/${rootdev} /mnt/;
if [ $? -ne 0 ]; then
echo “ERROR: ${rootdev} mount fail…” > /dev/kmsg;
exec /bin/bash;
fi;
elif [[ “${rootdev}” == “nfs” ]]; then
eth=cat /proc/cmdline | sed 's/.* ip=\([a-z0-9.:]*\) .*/\1/' | awk -F ":" '{print $6}'
;
echo “Ethernet interface: $eth” > /dev/kmsg;
ipaddr=ifconfig "$eth" | grep -A1 "$eth" | grep "inet addr" | sed 's/.*addr:\([0-9\.]*\) .*/\1/'
;
if [[ “$ipaddr” =~ [0-9].[0-9].[0-9].[0-9] ]]; then
echo “IP Address: $ipaddr” > /dev/kmsg;
dhclient_flag=“false”;
else
while [ ${count} -lt 50 ]
do
sleep 0.2;
ipaddr=ifconfig "$eth" | grep -A1 "$eth" | grep "inet addr" | sed 's/.*addr:\([0-9\.]*\) .*/\1/'
;
if [[ “$ipaddr” =~ [0-9].[0-9].[0-9].[0-9] ]]; then
echo “IP Address: $ipaddr” > /dev/kmsg;
dhclient_flag=“false”;
break;
fi
count=expr $count + 1
;
done
fi
if [ “$dhclient_flag” == “true” ]; then
timeout 8s /sbin/dhclient $eth;
if [ $? -ne 0 ]; then
echo “ERROR: dhclient fail…” > /dev/kmsg;
exec /bin/bash;
fi;
fi;
nfsroot_path=“cat /proc/cmdline | sed -e 's/.*nfsroot=\([^ ,]*\)[ ,].*/\1 /'
”;
nfsroot_opts=“cat /proc/cmdline | sed -ne 's/.*nfsroot=\([^ ,]*\),\([^ ]*\).*/\2 /p'
”;
if [[ “${nfsroot_opts}” == “” ]]; then
nfsroot_opts=“nolock”
fi
mount -t nfs -o ${nfsroot_opts} ${nfsroot_path} /mnt/ &>/dev/kmsg;
if [ $? -ne 0 ]; then
echo “ERROR: NFS mount fail…” > /dev/kmsg;
exec /bin/bash;
fi;
else
echo “No root-device: Mount failed” > /dev/kmsg;
exec /bin/bash;
fi
echo “Rootfs mounted over ${rootdev}” > /dev/kmsg;
mount -o bind /proc /mnt/proc;
mount -o bind /sys /mnt/sys;
mount -o bind /dev/ /mnt/dev;
cd /mnt;
cp /etc/resolv.conf etc/resolv.conf
echo “Switching from initrd to actual rootfs” > /dev/kmsg;
mount --move . /
exec chroot . /sbin/init 2;
And repack initrd:
#!/bin/bash
find . -print0 | cpio --null --quiet -H newc -o | gzip -9 -n > …/initrdtossd
sudo cp …/initrdtossd /boot/initrdtossd
Now we need to change extlinux.conf to primary boot option and create secondary!!! (uncomment at end of the file).
LABEL primary
MENU LABEL primary kernel
LINUX /boot/Image
INITRD /boot/initrdtossd
APPEND {bootargs} ssdroot=/dev/nvme0n1p1
!!!
This method is only propoused. I couldn’t make it work yet.
rootdev
variable is empty at highlighted line from init
, while /proc/cmdline
consists string ssdroot=/dev/nvme0n1p1
and /dev/nvme0n1p1
is visible when system boot is stopped in initrd:
rootdev=“$(sed -ne ‘s/.\bssdroot=/dev/([abcdefklmnps0-9])\b.*/\1/p’ < /proc/cmdline)”
Any advice?