blob: b9df2250d7ceed35964dcd58a08b860fe2e95dca [file] [log] [blame]
#!/bin/sh
#
# You can run this script in case you boot with rdinit=/bin/sh and want to
# quickly mount the basic kernel filesystems. It mounts them, but doesn't
# switch_root.
#
. /helpers.sh
# Finds the *last* /dev/mtd* device with the given realname
find_mtd()
{
local result=
while IFS=" :" read dev size erasesize name; do
name=${name#\"}
name=${name%\"}
if [ "$name" = "$1" ]; then
result=${dev#mtd}
# fall through in case there's a subsequent device with same name
fi
done </proc/mtd
[ -n "$result" ] && echo "$result"
}
find_mmc()
{
local result=
sgdisk -p /dev/mmcblk0 >/tmp/mmcpart 2>/dev/null
while read number start end size unit code name; do
if [ "$name" = "$1" ]; then
result=$number
fi
done </tmp/mmcpart
rm -f /tmp/mmcpart
[ -n "$result" ] && echo "$result"
}
read_cmdline
# NOTE on ubi.mtd= vs. root=
#
# Previously, we relied on the installer+bootloader to set ubi.mtd=xxx, and
# then root=mtdblock:rootfs. The problem with that is it depends on the
# installer/bootloader understanding about UBI devices, which means the
# installer for a *previous* version needs to understand the format of kernel
# parameters for the *next* (newly-installed) version. That can make future
# upgrades more complicated.
#
# So what we do now is provide root=xxx, where xxx is the name of the mtd
# partition where the rootfs is installed (either rootfs0 or rootfs1). It's
# the responsibility of the installed image, ie. this script, to know whether
# the stuff in rootfs0/rootfs1 is UBI or not.
#
# However, for backward compatibility, we still need to support kernel options
# of the form
# ubi.mtd=rootfs0 root=mtdblock:rootfs
# which we treat as the new-style
# root=rootfs0
# ubi.mtd= only overrides root= if root= is old-style.
if [ -n "$UBI_MTD" ]; then
if [ -z "$ROOTDEV" -o "${ROOTDEV%%:*}" = "mtdblock" ]; then
ROOTDEV=$UBI_MTD
fi
fi
replacefirst() {
local left right
# same as sed -e 's/$2/$3/' $1
right=${1#*$2}
left=${1%%$2*}
echo "$left$3$right"
}
# Returns true if the string $1 starts with the string $2.
startswith() {
[ "${1#$2}" != "$1" ]
}
# host:path format in root= means we should do an NFS root
if [ "${ROOTDEV#*:/}" != "$ROOTDEV" ]; then
NFSROOT=$ROOTDEV
fi
if [ -n "$NFSROOT" ]; then
log "Mounting nfs: '$NFSROOT'"
if [ -n "$IP" ]; then
# Can't necessarily count on the kernel to do this, in case our
# ethernet driver is a kernel module instead of built-in.
log " IP initialization: '$IP'"
echo "$IP" | {
IFS=: read client_ip server_ip gw_ip netmask hostname device \
autoconf dns0_ip dns1_ip junk
[ -z "$device" ] && device=eth0
if [ "$ip" != "auto" ]; then
ifconfig "$device" "$client_ip"
fi
}
fi
NFSADDR=${NFSROOT%:*}
NFSOPTS="nolock,proto=tcp,mountproto=tcp,vers=3,mountvers=3,addr=$NFSADDR"
# 7429 internal PHY takes >1 second to get link.
# If the NFS mount fails, wait a while and try again.
for s in 2 2 2 0; do \
mount -o $NFSOPTS -t nfs "$NFSROOT" /rootfs && break
log "NFS mount failed, sleeping"
sleep $s
false
done || die "NFS mount failed"
log "Mounted nfsroot='$NFSROOT'"
elif [ -n "$ROOTDEV" ]; then
if startswith "$ROOTDEV" /dev; then
mount -o ro -t squashfs "$ROOTDEV" /rootfs ||
die "root='$ROOTDEV' mount failed"
log "Mounted root='$ROOTDEV'"
elif startswith "$ROOTDEV" 9p:; then
fsdev="${ROOTDEV#9p:}"
mount -t 9p -o trans=virtio,version=9p2000.L "$fsdev" /rootfs ||
die "root='$fsdev' (9p) mount failed"
log "Mounted root='$fsdev' (9p)"
else
for s in 1 1 0; do
KERNELNAME=$(replacefirst $ROOTDEV rootfs kernel)
mtd=/dev/mtd$(find_mtd "$ROOTDEV")
mmcraw=/dev/mmcblk0p$(find_mmc "$ROOTDEV")
IMAGENAME=$(replacefirst $ROOTDEV rootfs image)
mmcvfat=/dev/mmcblk0p$(find_mmc "$IMAGENAME")
[ -e "$mtd" -o -e "$mmcraw" -o -e "$mmcvfat" -o -e $ROOTDEV ] && break
log "No rootfs found, sleeping"
# eMMC is sometimes slow to appear; try again.
sleep $s
false
done
if [ -e "$mtd" ]; then
log "Found root='$ROOTDEV': $mtd"
# In this build, the rootdev mtd is always an UBI device.
ubidetach -p "$mtd" # Just in case kernel automounted it somewhere
ubiattach -p "${mtd}ro"
# In this build, the newly-found mtd is always named 'rootfs'
ubi_mtd=$(find_mtd "rootfs")
[ -n "$ubi_mtd" ] || (cat /proc/mtd; die "no mtd named 'rootfs'")
ROOTDEV=/dev/mtdblock$ubi_mtd
KERNELDEV=/dev/mtdblock$(find_mtd "$KERNELNAME")
elif [ -e "$mmcraw" ]; then
log "Found root='$ROOTDEV': $mmcraw"
ROOTDEV=$mmcraw
KERNELDEV=/dev/mmcblk0p$(find_mmc "$KERNELNAME")
elif [ -e "$mmcvfat" ]; then
log "Found root='$ROOTDEV': $mmcvfat"
mount -t vfat -o ro,nodev,noexec,nosuid "$mmcvfat" /vfat
KERNELDEV=/dev/loop0
ROOTDEV=/dev/loop1
losetup $KERNELDEV /vfat/vmlinuz.img
losetup $ROOTDEV /vfat/rootfs.img
else
cat /proc/mtd
log "root='$ROOTDEV' is not an mtd device."
fi
args=$(readverity $KERNELDEV)
args=$(replacefirst "$args" ROOT_DEV "$ROOTDEV")
args=$(replacefirst "$args" HASH_DEV "$KERNELDEV")
if ! dmsetup create -r vroot --table "$args"; then
veritynote=
# TODO(apenwarr): fix uboot, then remove special case for armplatform.
read x y armplatform platform junk </proc/cpuinfo
if [ "$platform" = "BCM7425B0" \
-o "$platform" = "BCM7429B0" \
-o "$armplatform" = "ARMv7" ]; then
log 'dmsetup failed: platform is unsigned device, continuing anyway.'
SQUASHFS=$ROOTDEV
else
die "dmsetup failed"
fi
else
SQUASHFS="/dev/mapper/vroot"
veritynote="(verity)"
fi
mount -o ro -t squashfs "$SQUASHFS" /rootfs ||
die "root='$ROOTDEV' mount failed $veritynote"
log "Mounted root='$ROOTDEV' $veritynote"
fi
else
die "No root= or nfsroot= provided."
fi
mount -t tmpfs none /rootfs/tmp
#TODO(apenwarr): network setup code depends on this file, but it shouldn't.
# It should just always refuse to touch the network if the network was already
# set up.
[ -n "$NFSROOT" ] && echo NFS >/rootfs/tmp/NFS
[ -n "$DEBUG" ] && echo DEBUG >/rootfs/tmp/DEBUG
exit 0