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