| #!/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 |