blob: 8c2cf74549660d30dc5cd9d89e5f6fe5a40354ad [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script can be called during startup to trash the stateful partition
# and possibly reset the other root filesystem
. /usr/sbin/chromeos-common.sh
SCRIPT="$0"
# stateful partition isn't around for logging, so dump to the screen:
set -x
if [ $(id -u) -ne 0 ]; then
echo 'You must run this as root'
exit 1
fi
# Run "clobber-state fast" to clobber the state quickly but unsecurely.
FACTORY_WIPE=$(echo "$@" | grep -sq factory && echo "factory")
FAST_WIPE=$(echo "$@" | grep -sq fast && echo "fast")
KEEPIMG=$(echo "$@" | grep -sq keepimg && echo "keepimg")
FACTORY_WIPE_FIRMWARE_PID=""
wipedev() {
DEV="$1"
# Wipe the filesystem size if we can determine it. Full partition wipe
# takes a long time on 16G SSD or rotating media.
if dumpe2fs ${DEV} ; then
FS_BLOCKS=$(dumpe2fs -h ${DEV} | grep "Block count" | sed "s/^.*:\W*//")
FS_BLOCKSIZE=$(dumpe2fs -h ${DEV} | grep "Block size" | sed "s/^.*:\W*//")
else
FS_BLOCKS=$(numsectors ${DEV})
FS_BLOCKSIZE=512
fi
BLOCKS_4M=$((4 * 1024 * 1024 / $FS_BLOCKSIZE)) # 4MiB in sectors
FULL_BLKS=$(($FS_BLOCKS / $BLOCKS_4M))
REMAINDER_SECTORS=$(($FS_BLOCKS % $BLOCKS_4M))
if type pv; then
pv -etp -s $((4 * 1024 * 1024 * ${FULL_BLKS})) </dev/zero 2>/dev/tty1 |
dd of=${DEV} bs=4M count=${FULL_BLKS} iflag=fullblock oflag=sync
else
dd if=/dev/zero of=${DEV} bs=4M count=${FULL_BLKS}
fi
dd if=/dev/zero of=${DEV} bs=${FS_BLOCKSIZE} count=${REMAINDER_SECTORS} \
seek=$(($FULL_BLKS * $BLOCKS_4M))
}
# Wipe (developer) firmware if running in factory wiping mode.
factory_wipe_firmware() {
if [ -n "$FACTORY_WIPE_FIRMWARE_PID" ]; then
# wiping already in progress; wait for complete.
wait "$FACTORY_WIPE_FIRMWARE_PID" || return $?
return 0
fi
local wipe_script='/usr/sbin/firmware-factory-wipe'
# Factory wipe doesn't occur in developer mode w.r.t firmware wiping.
if crossystem "devsw_boot?1" || [ ! -x "${wipe_script}" ]; then
return 0
fi
if [ "$FAST_WIPE" = "fast" ]; then
echo "Starting to wipe firmware in parallel..."
"${wipe_script}" & FACTORY_WIPE_FIRMWARE_PID="$!"
else
echo "Starting to wipe firmware..."
"${wipe_script}"
fi
}
# Root devs are sda3, sda5.
# Kernel devs to go along with these are sda2, sda4 respectively.
ROOT_DEV=$(rootdev -s)
STATE_DEV=${ROOT_DEV%[0-9]*}1
OTHER_ROOT_DEV=$(echo $ROOT_DEV | tr '35' '53')
KERNEL_DEV=$(echo $ROOT_DEV | tr '35' '24')
OTHER_KERNEL_DEV=$(echo $OTHER_ROOT_DEV | tr '35' '24')
WIPE_PART_NUM=${OTHER_ROOT_DEV##[/a-z]*[/a-z]}
if [ "$WIPE_PART_NUM" != "3" ] && [ "$WIPE_PART_NUM" != "5" ]
then
echo "Invalid partition to wipe, $WIPE_PART_NUM (${OTHER_ROOT_DEV})"
exit 1
fi
# Preserve the log file
clobber-log --preserve "$SCRIPT" "$@"
umount /mnt/stateful_partition
if [ "$FAST_WIPE" = "fast" ]; then
# factory_wipe_firmware can be executed in parallel.
if [ "$FACTORY_WIPE" = "factory" ]; then
factory_wipe_firmware
fi
# Just wipe the start of the partition and remake the fs on
# the stateful partition.
dd bs=4M count=1 if=/dev/zero of=${STATE_DEV}
if [ -z "${KEEPIMG}" ]; then
dd bs=4M count=1 if=/dev/zero of=${OTHER_ROOT_DEV}
dd bs=4M count=1 if=/dev/zero of=${OTHER_KERNEL_DEV}
fi
/sbin/mkfs.ext3 "$STATE_DEV"
else
if [ -z "${KEEPIMG}" ]; then
wipedev ${OTHER_ROOT_DEV}
wipedev ${OTHER_KERNEL_DEV}
fi
# Wipe everything on the stateful partition.
wipedev ${STATE_DEV}
/sbin/mkfs.ext3 "$STATE_DEV"
# TODO(wad) tune2fs.
fi
# Mount the fresh image for last minute additions.
mount -n -t ext3 "${STATE_DEV}" /mnt/stateful_partition
# Restore the log file
clobber-log --restore "$SCRIPT" "$@"
# Tag that we're in developer mode otherwise we may get wiped again.
if crossystem devsw_boot?1 recoverysw_boot?0; then
touch /mnt/stateful_partition/.developer_mode
fi
# Flush linux caches.
sync
echo 3 > /proc/sys/vm/drop_caches
# Do any board specific wiping here.
# board_factory_wipe.sh will be installed by the board overlay if necessary.
if [ "$FACTORY_WIPE" = "factory" ]; then
factory_wipe_firmware
BOARD_WIPE=/usr/sbin/board_factory_wipe.sh
if [ -x "${BOARD_WIPE}" ]; then
${BOARD_WIPE}
fi
fi
/sbin/shutdown -r now
sleep 1d # Wait for shutdown