| #!/bin/sh |
| |
| # Copyright (c) 2012 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 maintain a log file across stateful partition wiping |
| # transition. |
| |
| SCRIPT="$0" |
| CLOBBER_LOG_FILE="clobber.log" |
| |
| # Temp folder is always accessible (by tmpfs), but stateful partition may be not |
| # available. To verify that, check the existence of STATEFUL_LOG_FOLDER. |
| STATEFUL_LOG_FOLDER="/mnt/stateful_partition/unencrypted/" |
| STATEFUL_LOG_PATH="$STATEFUL_LOG_FOLDER/$CLOBBER_LOG_FILE" |
| TMP_LOG_PATH="/tmp/$CLOBBER_LOG_FILE" |
| PSTORE_PATH="/sys/fs/pstore" |
| RAMOOPS_LOG="${PSTORE_PATH}/console-ramoops" |
| MAX_KEEP_LOG_LINES=1024 |
| RAMOOPS_DUMP_LINES=128 |
| BLOCK_DUMP_LINES=64 |
| |
| mount_pstore() { |
| # Copied from pstore.conf. clobber-state is always executed before |
| # boot-services so pstore.conf won't be ready at that time and we have to |
| # mount now. |
| if ! mountpoint -q "${PSTORE_PATH}"; then |
| mount -n -t pstore -o nodev,nosuid,noexec pstore "${PSTORE_PATH}" || true |
| fi |
| } |
| |
| log_prefix() { |
| echo "$(date --utc '+%Y/%m/%d %H:%M:%S') UTC" |
| } |
| |
| preserve_log() { |
| # Try to copy log from stateful partition to tmp. |
| local source_path="$STATEFUL_LOG_PATH" |
| local dest_path="$TMP_LOG_PATH" |
| |
| # TODO(hungte) store log in some special place, like last sector of stateful |
| # partition so that logs won't be lost if user interrupts during wiping. |
| |
| if [ -s "$source_path" ]; then |
| tail -n $MAX_KEEP_LOG_LINES "$source_path" >"$dest_path" |
| fi |
| echo "$(log_prefix) (preserve log): $@" >>"$dest_path" |
| } |
| |
| restore_log() { |
| # Try to copy log from tmp back to stateful partition. |
| local source_path="$TMP_LOG_PATH" |
| local dest_path="$STATEFUL_LOG_PATH" |
| # the mode should be matched to chromeos_startup. |
| mkdir -p -m 0755 "$STATEFUL_LOG_FOLDER" |
| if [ -s "$source_path" ]; then |
| cp "$source_path" "$dest_path" |
| fi |
| echo "$(log_prefix) (restore log): $@" >>"$dest_path" |
| } |
| |
| find_log_path() { |
| # Always use log in stateful partition, otherwise create in temp. |
| local dest_path="$STATEFUL_LOG_PATH" |
| if [ ! -d "$STATEFUL_LOG_FOLDER" ]; then |
| dest_path="$TMP_LOG_PATH" |
| fi |
| echo "$dest_path" |
| } |
| |
| append_log() { |
| # Add one line of log into the clobber log file. |
| local dest_path="$(find_log_path)" |
| echo "$(log_prefix) $@" >>"$dest_path" |
| } |
| |
| repair_log() { |
| # Report detail messages for the status of stateful partition. |
| local dest_path="$TMP_LOG_PATH" |
| |
| # TODO(hungte) try to recover logs from some where - see preserve_log. |
| |
| if [ ! -b "$1" ]; then |
| echo "$(log_prefix) repair: $1: invalid device file." >>"$dest_path" |
| return |
| fi |
| |
| echo "$(log_prefix) (repair): $@" >>"$dest_path" |
| # "fsck -n" and "mount -v" may also help. |
| dumpe2fs -fh "$1" >>"$dest_path" 2>&1 |
| |
| mount_pstore |
| echo "-- Ramoops (logs from last boot):" >>"${dest_path}" |
| # There might be more than one record, so grab them all with a glob. |
| # Plus, for <linux-3.19, it's named "console-ramoops", but for newer |
| # versions, it's named "console-ramoops-#". |
| local ramoops |
| for ramoops in "${RAMOOPS_LOG}"*; do |
| if [ -f "${ramoops}" ]; then |
| echo "${ramoops}" |
| tail -n ${RAMOOPS_DUMP_LINES} "${ramoops}" >>"${dest_path}" 2>/dev/null |
| else |
| echo "(No ramoops found, sorry)" >>"${dest_path}" |
| fi |
| done |
| |
| # try to dump first several blocks |
| echo "-- File system $1 block data (gz+base64):" >>"$dest_path" |
| dd if="$1" bs=1M count=1 | gzip -c | base64 | |
| head -n $BLOCK_DUMP_LINES >>"$dest_path" 2>/dev/null |
| echo "-- File system $1 block data dump complete." >>"$dest_path" |
| # to read back the block data, extract to a file and do |
| # cat block | base64 -d | gunzip -c -d > block.bin |
| } |
| |
| # Process the very limited commands |
| case "$1" in |
| --preserve ) |
| shift |
| preserve_log "$@" |
| ;; |
| --restore ) |
| shift |
| restore_log "$@" |
| ;; |
| --repair ) |
| shift |
| repair_log "$@" |
| ;; |
| -- ) |
| shift |
| append_log "$@" |
| ;; |
| * ) |
| append_log "$@" |
| ;; |
| esac |