blob: 134bf080e4c38159cfec443412a2e9fd92e86050 [file] [log] [blame] [edit]
#!/bin/bash
# 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 modifies a base image to act as a recovery installer.
# If a developer payload is supplied, it will be used.
# It is very straight forward, top to bottom to show clearly what is
# little is needed to create a developer shim to run a signed script.
# --- BEGIN COMMON.SH BOILERPLATE ---
# Load common CrOS utilities. Inside the chroot this file is installed in
# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
# location.
find_common_sh() {
local common_paths=(/usr/lib/crosutils $(dirname "$(readlink -f "$0")"))
local path
SCRIPT_ROOT=
for path in "${common_paths[@]}"; do
if [ -r "${path}/common.sh" ]; then
SCRIPT_ROOT=${path}
break
fi
done
}
find_common_sh
. "${SCRIPT_ROOT}/common.sh" || (echo "Unable to load common.sh" && exit 1)
# --- END COMMON.SH BOILERPLATE ---
# Need to be inside the chroot to load chromeos-common.sh
assert_inside_chroot
# Load functions and constants for chromeos-install
. "/usr/lib/installer/chromeos-common.sh" || \
die "Unable to load /usr/lib/installer/chromeos-common.sh"
DEFINE_integer statefulfs_size 2 \
"Number of mebibytes to use for the stateful filesystem"
DEFINE_string developer_private_key \
"/usr/share/vboot/devkeys/kernel_data_key.vbprivk" \
"Path to the developer's private key"
DEFINE_string developer_keyblock \
"/usr/share/vboot/devkeys/kernel.keyblock" \
"Path to the developer's keyblock"
DEFINE_string developer_script "" \
"Path to the developer script if desired."
# TODO(wad) wire up support for just swapping a pre-made kernel
# Skips the build steps and just does the kernel swap.
DEFINE_string kernel_image "" \
"Path to a pre-built recovery kernel"
DEFINE_boolean verbose $FLAGS_FALSE \
"Emits stderr too" v
DEFINE_string image "dev_runner_image.bin" \
"Path to output image to"
# Parse command line
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
if [ $FLAGS_verbose -eq $FLAGS_FALSE ]; then
exec 2>/dev/null
fi
set -x # Make debugging with -v easy.
if [ -z "$FLAGS_kernel_image" ]; then
die "--kernel_image with a recovery kernel is needed"
fi
if [ -z "$FLAGS_developer_script" ]; then
die "--developer_script must be supplied."
fi
locate_gpt
set -eu
header_offset=34
stateful_sectors=$(((FLAGS_statefulfs_size * 1024 * 1024) / 512))
stateful_sectors=$(roundup $stateful_sectors)
if [ -b "$FLAGS_image" ]; then
sudo=sudo
else
max_kern_size=32768
dd if=/dev/zero of="${FLAGS_image}" bs=512 count=0 \
seek=$((1 + max_kern_size + (2 * header_offset) + stateful_sectors))
sudo=""
fi
## STATEFUL
stateful_image=$(mktemp)
trap "rm $stateful_image" EXIT
dd if=/dev/zero of="$stateful_image" bs=512 \
seek=$stateful_sectors count=0
/sbin/mkfs.ext3 -F -b 4096 $stateful_image 1>&2
stateful_mnt=$(mktemp -d)
sudo mount -o loop $stateful_image "$stateful_mnt" || exit 1
userdir="$stateful_mnt/userdir"
userfile="$userdir/runme"
sudo mkdir -p "$userdir"
sudo cp "$FLAGS_developer_script" "$userfile"
sudo chmod +x "$userfile"
sudo dev_sign_file --sign "$userfile" \
--keyblock "$FLAGS_developer_keyblock" \
--signprivate "$FLAGS_developer_private_key" \
--vblock "${userfile}.vblock"
sudo umount -d "$stateful_mnt"
rmdir "$stateful_mnt"
## GPT
kernel_bytes=$(stat -c '%s' $FLAGS_kernel_image)
kernel_sectors=$((kernel_bytes / 512))
kernel_sectors=$(roundup $kernel_sectors)
$sudo $GPT create $FLAGS_image
trap "rm $FLAGS_image; echo 'An error occurred! Rerun with -v for details.'" ERR
offset=$header_offset
$sudo $GPT add -b $offset -s $stateful_sectors \
-t data -l "STATE" $FLAGS_image
$sudo dd if=$stateful_image of=$FLAGS_image bs=512 conv=notrunc \
seek=$offset count=$stateful_sectors
offset=$((offset + stateful_sectors))
$sudo $GPT add -b $offset -s $kernel_sectors \
-t kernel -l "KERN-A" -S 0 -T 15 -P 15 $FLAGS_image
$sudo dd if=$FLAGS_kernel_image of=$FLAGS_image bs=512 conv=notrunc \
seek=$offset count=$kernel_sectors
# The kernel will ignore GPT without a legacymbr.
PMBRCODE=$(readlink -f /usr/share/syslinux/gptmbr.bin)
# Have it legacy boot off of stateful, not that it should matter.
$sudo $GPT boot -p -b "$PMBRCODE" -i 1 $FLAGS_image 1>&2
$sudo $GPT show $FLAGS_image
echo "Emitted $FLAGS_image successfully!"