Merge pull request #92 from marineam/images

Lots of image building updates
This commit is contained in:
Michael Marineau 2013-08-21 15:35:34 -07:00
commit 63713f2eee
14 changed files with 150 additions and 475 deletions

View File

@ -95,14 +95,6 @@ DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \
"Default all bootloaders to NOT use kernel-based root fs integrity checking." "Default all bootloaders to NOT use kernel-based root fs integrity checking."
DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \
"Default all bootloaders to NOT use bootcache." "Default all bootloaders to NOT use bootcache."
DEFINE_integer verity_error_behavior 3 \
"Kernel verified boot error behavior (0: I/O errors, 1: reboot, 2: nothing)"
DEFINE_integer verity_max_ios -1 \
"Number of outstanding I/O operations dm-verity caps at."
DEFINE_string verity_algorithm "sha1" \
"Cryptographic hash algorithm used for kernel vboot."
DEFINE_string verity_salt "" \
"Salt for rootfs hash tree."
DEFINE_string keys_dir "/usr/share/vboot/devkeys" \ DEFINE_string keys_dir "/usr/share/vboot/devkeys" \
"Directory containing the signing keys." "Directory containing the signing keys."
@ -141,15 +133,11 @@ DEFINE_boolean enable_squashfs ${FLAGS_FALSE} \
DEFINE_string squash_sort_file "" \ DEFINE_string squash_sort_file "" \
"Specify the priority of files when squashing the rootfs." "Specify the priority of files when squashing the rootfs."
DEFINE_string enable_serial "" \
"Enable serial port for printks. Example values: ttyS0"
# Parse the boot.desc and any overrides # Parse the boot.desc and any overrides
eval set -- "${BOOT_DESC} ${FLAG_OVERRIDES}" eval set -- "${BOOT_DESC} ${FLAG_OVERRIDES}"
FLAGS "${@}" || exit 1 FLAGS "${@}" || exit 1
[ -z "${FLAGS_verity_salt}" ] && FLAGS_verity_salt=$(make_salt)
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1 . "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
# Only now can we die on error. shflags functions leak non-zero error codes, # Only now can we die on error. shflags functions leak non-zero error codes,

View File

@ -29,10 +29,6 @@ DEFINE_string disk_layout "default" \
"The disk layout type to use for this image." "The disk layout type to use for this image."
DEFINE_boolean standard_backdoor ${FLAGS_TRUE} \ DEFINE_boolean standard_backdoor ${FLAGS_TRUE} \
"Install standard backdoor credentials for testing" "Install standard backdoor credentials for testing"
DEFINE_string usb_disk /dev/sdb4 \
"Path syslinux should use to do a usb boot. Default: /dev/sdb4"
DEFINE_string enable_serial "" \
"Enable serial port for printks. Example values: ttyS0"
# include upload options # include upload options
. "${BUILD_LIBRARY_DIR}/release_util.sh" || exit 1 . "${BUILD_LIBRARY_DIR}/release_util.sh" || exit 1

View File

@ -4,7 +4,7 @@
. "${SRC_ROOT}/platform/dev/toolchain_utils.sh" || exit 1 . "${SRC_ROOT}/platform/dev/toolchain_utils.sh" || exit 1
# Overlays are parts of the disk that live on the stateful partition # Overlays are parts of the disk that live on the state partition
ROOT_OVERLAYS=(var opt srv home usr/local) ROOT_OVERLAYS=(var opt srv home usr/local)
cleanup_mounts() { cleanup_mounts() {
@ -28,10 +28,15 @@ cleanup_mounts() {
echo "Cleaning up mounts" echo "Cleaning up mounts"
safe_umount_tree "${root_fs_dir}" safe_umount_tree "${root_fs_dir}"
safe_umount_tree "${stateful_fs_dir}" safe_umount_tree "${state_fs_dir}"
safe_umount_tree "${esp_fs_dir}" safe_umount_tree "${esp_fs_dir}"
safe_umount_tree "${oem_fs_dir}" safe_umount_tree "${oem_fs_dir}"
if [[ -n "${loop_dev}" ]]; then
sudo losetup -d "${loop_dev}"
loop_dev=
fi
# Turn die on error back on. # Turn die on error back on.
set -e set -e
} }
@ -40,14 +45,10 @@ create_base_image() {
local image_name=$1 local image_name=$1
local rootfs_verification_enabled=$2 local rootfs_verification_enabled=$2
local bootcache_enabled=$3 local bootcache_enabled=$3
local image_type="usb" local image_type="base"
if [[ "${FLAGS_disk_layout}" != "default" ]]; then if [[ "${FLAGS_disk_layout}" != "default" ]]; then
image_type="${FLAGS_disk_layout}" image_type="${FLAGS_disk_layout}"
else
if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
image_type="factory_install"
fi
fi fi
check_valid_layout "base" check_valid_layout "base"
@ -56,43 +57,40 @@ create_base_image() {
info "Using image type ${image_type}" info "Using image type ${image_type}"
root_fs_dir="${BUILD_DIR}/rootfs" root_fs_dir="${BUILD_DIR}/rootfs"
stateful_fs_dir="${BUILD_DIR}/stateful" state_fs_dir="${BUILD_DIR}/state"
esp_fs_dir="${BUILD_DIR}/esp" esp_fs_dir="${BUILD_DIR}/esp"
oem_fs_dir="${BUILD_DIR}/oem" oem_fs_dir="${BUILD_DIR}/oem"
trap "cleanup_mounts && delete_prompt" EXIT trap "cleanup_mounts && delete_prompt" EXIT
cleanup_mounts &> /dev/null cleanup_mounts &> /dev/null
local root_fs_label="ROOT-A" write_partition_table "${image_type}" "${BUILD_DIR}/${image_name}"
local root_fs_num=$(get_num ${image_type} ${root_fs_label}) loop_dev=$(sudo losetup -P -f --show "${BUILD_DIR}/${image_name}")
local root_fs_img="${BUILD_DIR}/rootfs.image"
local root_fs_bytes=$(get_filesystem_size ${image_type} ${root_fs_num})
local stateful_fs_label="STATE"
local stateful_fs_num=$(get_num ${image_type} ${stateful_fs_label})
local stateful_fs_img="${BUILD_DIR}/stateful.image"
local stateful_fs_bytes=$(get_filesystem_size ${image_type} ${stateful_fs_num})
local stateful_fs_uuid=$(uuidgen)
local esp_fs_label="EFI-SYSTEM"
local esp_fs_num=$(get_num ${image_type} ${esp_fs_label})
local esp_fs_img="${BUILD_DIR}/esp.image"
local esp_fs_bytes=$(get_filesystem_size ${image_type} ${esp_fs_num})
local oem_fs_label="OEM"
local oem_fs_num=$(get_num ${image_type} ${oem_fs_label})
local oem_fs_img="${BUILD_DIR}/oem.image"
local oem_fs_bytes=$(get_filesystem_size ${image_type} ${oem_fs_num})
local oem_fs_uuid=$(uuidgen)
local fs_block_size=$(get_fs_block_size) local fs_block_size=$(get_fs_block_size)
local root_fs_label="ROOT-A"
local root_fs_num=$(get_num ${image_type} ${root_fs_label})
local root_fs_dev="${loop_dev}p${root_fs_num}"
local root_fs_bytes=$(get_filesystem_size ${image_type} ${root_fs_num})
local root_fs_blocks=$((root_fs_bytes / fs_block_size))
local state_fs_label="STATE"
local state_fs_num=$(get_num ${image_type} ${state_fs_label})
local state_fs_dev="${loop_dev}p${state_fs_num}"
local esp_fs_label="EFI-SYSTEM"
local esp_fs_num=$(get_num ${image_type} ${esp_fs_label})
local esp_fs_dev="${loop_dev}p${esp_fs_num}"
local oem_fs_label="OEM"
local oem_fs_num=$(get_num ${image_type} ${oem_fs_label})
local oem_fs_dev="${loop_dev}p${oem_fs_num}"
# Build root FS image. # Build root FS image.
info "Building ${root_fs_img}" info "Building ROOT filesystem"
truncate --size="${root_fs_bytes}" "${root_fs_img}" sudo mkfs.ext2 -F -q -b ${fs_block_size} "${root_fs_dev}" "${root_fs_blocks}"
/sbin/mkfs.ext2 -F -q -b ${fs_block_size} "${root_fs_img}" \ sudo tune2fs -L "${root_fs_label}" \
"$((root_fs_bytes / fs_block_size))"
/sbin/tune2fs -L "${root_fs_label}" \
-U clear \ -U clear \
-T 20091119110000 \ -T 20091119110000 \
-c 0 \ -c 0 \
@ -100,57 +98,56 @@ create_base_image() {
-m 0 \ -m 0 \
-r 0 \ -r 0 \
-e remount-ro \ -e remount-ro \
"${root_fs_img}" "${root_fs_dev}"
mkdir -p "${root_fs_dir}" mkdir -p "${root_fs_dir}"
sudo mount -o loop "${root_fs_img}" "${root_fs_dir}" sudo mount "${root_fs_dev}" "${root_fs_dir}"
df -h "${root_fs_dir}" # Build state FS disk image.
info "Building STATE filesystem"
# Build stateful FS disk image. sudo mkfs.ext4 -F -q "${state_fs_dev}"
info "Building ${stateful_fs_img}" sudo tune2fs -L "${state_fs_label}" \
truncate --size="${stateful_fs_bytes}" "${stateful_fs_img}" -c 0 \
/sbin/mkfs.ext4 -F -q "${stateful_fs_img}" -i 0 \
/sbin/tune2fs -L "${stateful_fs_label}" -U "${stateful_fs_uuid}" \ "${state_fs_dev}"
-c 0 -i 0 "${stateful_fs_img}" mkdir -p "${state_fs_dir}"
mkdir -p "${stateful_fs_dir}" sudo mount "${state_fs_dev}" "${state_fs_dir}"
sudo mount -o loop "${stateful_fs_img}" "${stateful_fs_dir}"
# Build ESP disk image. # Build ESP disk image.
info "Building ${esp_fs_img}" info "Building ESP filesystem"
truncate --size="${esp_fs_bytes}" "${esp_fs_img}" sudo mkfs.vfat "${esp_fs_dev}"
/usr/sbin/mkfs.vfat "${esp_fs_img}"
# Build OEM FS disk image. # Build OEM FS disk image.
info "Building ${oem_fs_img}" info "Building OEM filesystem"
truncate --size="${oem_fs_bytes}" "${oem_fs_img}" sudo mkfs.ext4 -F -q "${oem_fs_dev}"
/sbin/mkfs.ext4 -F -q "${oem_fs_img}" sudo tune2fs -L "${oem_fs_label}" \
/sbin/tune2fs -L "${oem_fs_label}" -U "${oem_fs_uuid}" \ -c 0 \
-c 0 -i 0 "${oem_fs_img}" -i 0 \
"${oem_fs_dev}"
mkdir -p "${oem_fs_dir}" mkdir -p "${oem_fs_dir}"
sudo mount -o loop "${oem_fs_img}" "${oem_fs_dir}" sudo mount "${oem_fs_dev}" "${oem_fs_dir}"
# Prepare stateful partition with some pre-created directories. # Prepare state partition with some pre-created directories.
for i in ${ROOT_OVERLAYS}; do for i in ${ROOT_OVERLAYS}; do
sudo mkdir -p "${stateful_fs_dir}/overlays/$i" sudo mkdir -p "${state_fs_dir}/overlays/$i"
sudo mkdir -p "${root_fs_dir}/$i" sudo mkdir -p "${root_fs_dir}/$i"
sudo mount --bind "${stateful_fs_dir}/overlays/$i" "${root_fs_dir}/$i" sudo mount --bind "${state_fs_dir}/overlays/$i" "${root_fs_dir}/$i"
done done
sudo mkdir -p "${stateful_fs_dir}/overlays/usr/local" sudo mkdir -p "${state_fs_dir}/overlays/usr/local"
# Create symlinks so that /usr/local/usr based directories are symlinked to # Create symlinks so that /usr/local/usr based directories are symlinked to
# /usr/local/ directories e.g. /usr/local/usr/bin -> /usr/local/bin, etc. # /usr/local/ directories e.g. /usr/local/usr/bin -> /usr/local/bin, etc.
setup_symlinks_on_root "${stateful_fs_dir}/overlays/usr/local" \ setup_symlinks_on_root "${state_fs_dir}/overlays/usr/local" \
"${stateful_fs_dir}/overlays/var" \ "${state_fs_dir}/overlays/var" \
"${stateful_fs_dir}" "${state_fs_dir}"
# Perform binding rather than symlinking because directories must exist # Perform binding rather than symlinking because directories must exist
# on rootfs so that we can bind at run-time since rootfs is read-only. # on rootfs so that we can bind at run-time since rootfs is read-only.
info "Binding directories from stateful partition onto the rootfs" info "Binding directories from state partition onto the rootfs"
# Setup the dev image for developer tools # Setup the dev image for developer tools
sudo mkdir -p "${root_fs_dir}/usr/local" sudo mkdir -p "${root_fs_dir}/usr/local"
sudo mount --bind "${stateful_fs_dir}/overlays/usr/local" "${root_fs_dir}/usr/local" sudo mount --bind "${state_fs_dir}/overlays/usr/local" "${root_fs_dir}/usr/local"
# TODO(bp): remove these temporary fixes for /mnt/stateful_partition going moving # TODO(bp): remove these temporary fixes for /mnt/stateful_partition going moving
sudo mkdir -p "${root_fs_dir}/mnt/stateful_partition/" sudo mkdir -p "${root_fs_dir}/mnt/stateful_partition/"
@ -212,10 +209,11 @@ create_base_image() {
# trim the image size as much as possible. # trim the image size as much as possible.
emerge_to_image --root="${root_fs_dir}" ${BASE_PACKAGE} emerge_to_image --root="${root_fs_dir}" ${BASE_PACKAGE}
# Record directories installed to the stateful partition. # Record directories installed to the state partition.
sudo "${SCRIPTS_DIR}/gen_tmpfiles.py" --root="${root_fs_dir}" \ # Ignore /var/tmp, systemd covers this entry.
sudo "${BUILD_LIBRARY_DIR}/gen_tmpfiles.py" --root="${root_fs_dir}" \
--output="${root_fs_dir}/usr/lib/tmpfiles.d/base_image.conf" \ --output="${root_fs_dir}/usr/lib/tmpfiles.d/base_image.conf" \
"${root_fs_dir}/var" --ignore=/var/tmp "${root_fs_dir}/var"
# Set /etc/lsb-release on the image. # Set /etc/lsb-release on the image.
"${BUILD_LIBRARY_DIR}/set_lsb_release" \ "${BUILD_LIBRARY_DIR}/set_lsb_release" \
@ -227,12 +225,6 @@ create_base_image() {
# cros_make_image_bootable. # cros_make_image_bootable.
create_boot_desc "${image_type}" create_boot_desc "${image_type}"
# Write out the GPT creation script.
# This MUST be done before writing bootloader templates else we'll break
# the hash on the root FS.
write_partition_script "${image_type}" \
"${root_fs_dir}/${PARTITION_SCRIPT_PATH}"
# Populates the root filesystem with legacy bootloader templates # Populates the root filesystem with legacy bootloader templates
# appropriate for the platform. The autoupdater and installer will # appropriate for the platform. The autoupdater and installer will
# use those templates to update the legacy boot partition (12/ESP) # use those templates to update the legacy boot partition (12/ESP)
@ -268,25 +260,15 @@ create_base_image() {
# Clean up symlinks so they work on a running target rooted at "/". # Clean up symlinks so they work on a running target rooted at "/".
# Here development packages are rooted at /usr/local. However, do not # Here development packages are rooted at /usr/local. However, do not
# create /usr/local or /var on host (already exist on target). # create /usr/local or /var on host (already exist on target).
setup_symlinks_on_root "/usr/local" "/var" "${stateful_fs_dir}" setup_symlinks_on_root "/usr/local" "/var" "${state_fs_dir}"
# Zero all fs free space to make it more compressible so auto-update # Zero all fs free space to make it more compressible so auto-update
# payloads become smaller, not fatal since it won't work on linux < 3.2 # payloads become smaller, not fatal since it won't work on linux < 3.2
sudo fstrim "${root_fs_dir}" || true sudo fstrim "${root_fs_dir}" || true
sudo fstrim "${stateful_fs_dir}" || true sudo fstrim "${state_fs_dir}" || true
cleanup_mounts cleanup_mounts
# Create the GPT-formatted image.
build_gpt "${BUILD_DIR}/${image_name}" \
"${root_fs_img}" \
"${stateful_fs_img}" \
"${esp_fs_img}" \
"${oem_fs_img}"
# Clean up temporary files.
rm -f "${root_fs_img}" "${stateful_fs_img}" "${esp_fs_img}" "{oem_fs_img}"
# Emit helpful scripts for testers, etc. # Emit helpful scripts for testers, etc.
emit_gpt_scripts "${BUILD_DIR}/${image_name}" "${BUILD_DIR}" emit_gpt_scripts "${BUILD_DIR}/${image_name}" "${BUILD_DIR}"

View File

@ -104,7 +104,6 @@ create_boot_desc() {
enable_bootcache_flag=--enable_bootcache enable_bootcache_flag=--enable_bootcache
fi fi
[ -z "${FLAGS_verity_salt}" ] && FLAGS_verity_salt=$(make_salt)
cat <<EOF > ${BUILD_DIR}/boot.desc cat <<EOF > ${BUILD_DIR}/boot.desc
--board=${BOARD} --board=${BOARD}
--image_type=${image_type} --image_type=${image_type}
@ -112,8 +111,6 @@ create_boot_desc() {
--keys_dir="${DEVKEYSDIR}" --keys_dir="${DEVKEYSDIR}"
--boot_args="${FLAGS_boot_args}" --boot_args="${FLAGS_boot_args}"
--nocleanup_dirs --nocleanup_dirs
--verity_algorithm=sha1
--enable_serial="${FLAGS_enable_serial}"
${enable_rootfs_verification_flag} ${enable_rootfs_verification_flag}
${enable_bootcache_flag} ${enable_bootcache_flag}
EOF EOF

View File

@ -3,10 +3,10 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import copy
import json import json
import os import os
import re import re
import subprocess
import sys import sys
import uuid import uuid
from optparse import OptionParser from optparse import OptionParser
@ -93,41 +93,6 @@ def LoadPartitionConfig(filename):
return config return config
def GetTableTotals(config, partitions):
"""Calculates total sizes/counts for a partition table.
Args:
config: Partition configuration file object
partitions: List of partitions to process
Returns:
Dict containing totals data
"""
ret = {
'expand_count': 0,
'expand_min': 0,
'block_count': START_SECTOR * config['metadata']['block_size']
}
# Total up the size of all non-expanding partitions to get the minimum
# required disk size.
for partition in partitions:
if 'features' in partition and 'expand' in partition['features']:
ret['expand_count'] += 1
ret['expand_min'] += partition['blocks']
else:
ret['block_count'] += partition['blocks']
# At present, only one expanding partition is permitted.
# Whilst it'd be possible to have two, we don't need this yet
# and it complicates things, so it's been left out for now.
if ret['expand_count'] > 1:
raise InvalidLayout('1 expand partition allowed, %d requested'
% ret['expand_count'])
ret['min_disk_size'] = ret['block_count'] + ret['expand_min']
return ret
def GetPartitionTable(options, config, image_type): def GetPartitionTable(options, config, image_type):
@ -241,77 +206,72 @@ def GetPartitionTableFromConfig(options, layout_filename, image_type):
return partitions return partitions
def GetScriptShell():
"""Loads and returns the skeleton script for our output script.
Returns: def WritePartitionTable(options, image_type, layout_filename, disk_filename):
A string containg the skeleton script """Writes the given partition table to a disk image or device.
"""
script_shell_path = os.path.join(os.path.dirname(__file__), 'cgpt_shell.sh')
with open(script_shell_path, 'r') as f:
script_shell = ''.join(f.readlines())
# Before we return, insert the path to this tool so somebody reading the
# script later can tell where it was generated.
script_shell = script_shell.replace('@SCRIPT_GENERATOR@', script_shell_path)
return script_shell
def WriteLayoutFunction(options, sfile, func_name, image_type, config):
"""Writes a shell script function to write out a given partition table.
Args: Args:
options: Flags passed to the script options: Flags passed to the script
sfile: File handle we're writing to
func_name: Function name to write out for specified layout
image_type: Type of image eg base/test/dev/factory_install image_type: Type of image eg base/test/dev/factory_install
config: Partition configuration file object layout_filename: Path to partition configuration file
disk_filename: Path to disk image or device file
""" """
def Cgpt(*args):
subprocess.check_call(['cgpt'] + [str(a) for a in args])
config = LoadPartitionConfig(layout_filename)
partitions = GetPartitionTable(options, config, image_type) partitions = GetPartitionTable(options, config, image_type)
partition_totals = GetTableTotals(config, partitions) disk_block_count = START_SECTOR * config['metadata']['block_size']
sfile.write('%s() {\ncreate_image $1 %d %s\n' % (
func_name, partition_totals['min_disk_size'],
config['metadata']['block_size']))
sfile.write('CURR=%d\n' % START_SECTOR)
sfile.write('$GPT create $1\n')
# Pass 1: Set up the expanding partition size.
for partition in partitions: for partition in partitions:
partition['var'] = partition['blocks'] disk_block_count += partition['blocks']
if partition['type'] != 'blank': sector = START_SECTOR
if partition['num'] == 1: Cgpt('create', '-c', '-s', disk_block_count, disk_filename)
if 'features' in partition and 'expand' in partition['features']:
sfile.write('if [ -b $1 ]; then\n')
sfile.write('STATEFUL_SIZE=$(( $(numsectors $1) - %d))\n' %
partition_totals['block_count'])
sfile.write('else\n')
sfile.write('STATEFUL_SIZE=%s\n' % partition['blocks'])
sfile.write('fi\n')
partition['var'] = '$STATEFUL_SIZE'
sfile.write('STATEFUL_SIZE=$((STATEFUL_SIZE-(STATEFUL_SIZE %% %d)))\n' %
config['metadata']['fs_block_size'])
# Pass 2: Write out all the cgpt add commands.
for partition in partitions: for partition in partitions:
if partition['type'] != 'blank': if partition['type'] != 'blank':
sfile.write('$GPT add -i %d -b $CURR -s %s -t %s -l %s -u %s $1 && ' % ( Cgpt('add', '-i', partition['num'],
partition['num'], str(partition['var']), partition['type'], '-b', sector,
partition['label'], partition['uuid'])) '-s', partition['blocks'],
'-t', partition['type'],
'-l', partition['label'],
'-u', partition['uuid'],
disk_filename)
sector += partition['blocks']
Cgpt('show', disk_filename)
def WriteMbrBoot(options, image_type, layout_filename,
disk_filename, mbr_filename):
"""Writes the protective MBR with the given boot code.
The EFI System Partition will be marked as the 'boot' partition.
Args:
options: Flags passed to the script
image_type: Type of image eg base/test/dev/factory_install
layout_filename: Path to partition configuration file
disk_filename: Path to disk image or device file
mbr_filename: Path to boot code, usually gptmbr.bin from syslinux.
"""
config = LoadPartitionConfig(layout_filename)
partitions = GetPartitionTable(options, config, image_type)
esp_number = None
for partition in partitions:
if partition['type'] == 'efi': if partition['type'] == 'efi':
sfile.write('$GPT boot -p -b $2 -i %d $1\n' % partition['num']) esp_number = partition['num']
break
if esp_number is None:
raise InvalidLayout('Table does not include an EFI partition.')
# Increment the CURR counter ready for the next partition. subprocess.check_call(['cgpt', 'boot', '-p', '-b', mbr_filename,
sfile.write('CURR=$(( $CURR + %s ))\n' % partition['var']) '-i', str(partition['num']), disk_filename])
sfile.write('$GPT show $1\n')
sfile.write('}\n')
def GetPartitionByNumber(partitions, num): def GetPartitionByNumber(partitions, num):
@ -350,26 +310,6 @@ def GetPartitionByLabel(partitions, label):
raise PartitionNotFound('Partition not found') raise PartitionNotFound('Partition not found')
def WritePartitionScript(options, image_type, layout_filename, sfilename):
"""Writes a shell script with functions for the base and requested layouts.
Args:
options: Flags passed to the script
image_type: Type of image eg base/test/dev/factory_install
layout_filename: Path to partition configuration file
sfilename: Filename to write the finished script to
"""
config = LoadPartitionConfig(layout_filename)
with open(sfilename, 'w') as f:
script_shell = GetScriptShell()
f.write(script_shell)
WriteLayoutFunction(options, f, 'write_base_table', 'base', config)
WriteLayoutFunction(options, f, 'write_partition_table', image_type, config)
def GetBlockSize(options, layout_filename): def GetBlockSize(options, layout_filename):
"""Returns the partition table block size. """Returns the partition table block size.
@ -549,9 +489,14 @@ def DoParseOnly(options, image_type, layout_filename):
def main(argv): def main(argv):
action_map = { action_map = {
'write': { 'write_gpt': {
'usage': ['<image_type>', '<partition_config_file>', '<script_file>'], 'usage': ['<image_type>', '<partition_config_file>', '<disk_image>'],
'func': WritePartitionScript, 'func': WritePartitionTable,
},
'write_mbr': {
'usage': ['<image_type>', '<partition_config_file>', '<disk_image>',
'<mbr_boot_code>'],
'func': WriteMbrBoot,
}, },
'readblocksize': { 'readblocksize': {
'usage': ['<partition_config_file>'], 'usage': ['<partition_config_file>'],

View File

@ -1,38 +0,0 @@
#!/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 is automatically generated by @SCRIPT_GENERATOR@
# Do not edit!
if ! type numsectors >/dev/null 2>&1; then
if [ -f "/usr/sbin/chromeos-common.sh" ]; then
. "/usr/sbin/chromeos-common.sh"
else
echo "Can't load chromeos-common.sh, dying!" 1>&2
exit 1
fi
fi
locate_gpt
# Usage: create_image <device> <min_disk_size> <block_size>
# If <device> is a block device, wipes out the GPT
# If it's not, it creates a new file of the requested size
create_image() {
local dev=$1
local min_disk_size=$2
local block_size=$3
if [ -b "${dev}" ]; then
# Zap any old partitions (otherwise gpt complains).
dd if=/dev/zero of="${dev}" conv=notrunc bs=512 count=32
dd if=/dev/zero of="${dev}" conv=notrunc bs=512 \
seek=$((${min_disk_size} - 1 - 33)) count=33
else
if [ ! -e "${dev}" ]; then
dd if=/dev/zero of="${dev}" bs=${block_size} count=1 \
seek=$((${min_disk_size} - 1))
fi
fi
}

View File

@ -18,19 +18,12 @@ DEFINE_string arch "x86" \
"The boot architecture: arm or x86. (Default: x86)" "The boot architecture: arm or x86. (Default: x86)"
DEFINE_string to "/tmp/boot" \ DEFINE_string to "/tmp/boot" \
"Path to populate with bootloader templates (Default: /tmp/boot)" "Path to populate with bootloader templates (Default: /tmp/boot)"
DEFINE_string usb_disk /dev/sdb3 \
"Path syslinux should use to do a usb boot. Default: /dev/sdb3"
DEFINE_string boot_args "" \ DEFINE_string boot_args "" \
"Additional boot arguments to pass to the commandline (Default: '')" "Additional boot arguments to pass to the commandline (Default: '')"
DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \
"Default all bootloaders to NOT use boot cache." "Default all bootloaders to NOT use boot cache."
DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \ DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \
"Controls if verity is used for root filesystem checking (Default: false)" "Controls if verity is used for root filesystem checking (Default: false)"
DEFINE_integer verity_error_behavior 3 \
"Verified boot error behavior [0: I/O errors, 1: reboot, 2: nothing] \
(Default: 3)"
DEFINE_integer verity_max_ios -1 \
"Optional number of outstanding I/O operations. (Default: 1024)"
# Parse flags # Parse flags
FLAGS "$@" || exit 1 FLAGS "$@" || exit 1

View File

@ -17,7 +17,7 @@ install_dev_packages() {
trap "unmount_image ; delete_prompt" EXIT trap "unmount_image ; delete_prompt" EXIT
mount_image "${BUILD_DIR}/${image_name}" "${root_fs_dir}" \ mount_image "${BUILD_DIR}/${image_name}" "${root_fs_dir}" \
"${stateful_fs_dir}" "${esp_fs_dir}" "${state_fs_dir}" "${esp_fs_dir}"
# Determine the root dir for developer packages. # Determine the root dir for developer packages.
local root_dev_dir="${root_fs_dir}/usr/local" local root_dev_dir="${root_fs_dir}/usr/local"
@ -90,7 +90,7 @@ EOF
# Zero all fs free space, not fatal since it won't work on linux < 3.2 # Zero all fs free space, not fatal since it won't work on linux < 3.2
sudo fstrim "${root_fs_dir}" || true sudo fstrim "${root_fs_dir}" || true
sudo fstrim "${stateful_fs_dir}" || true sudo fstrim "${state_fs_dir}" || true
info "Developer image built and stored at ${image_name}" info "Developer image built and stored at ${image_name}"

View File

@ -3,7 +3,6 @@
# found in the LICENSE file. # found in the LICENSE file.
CGPT_PY="${BUILD_LIBRARY_DIR}/cgpt.py" CGPT_PY="${BUILD_LIBRARY_DIR}/cgpt.py"
PARTITION_SCRIPT_PATH="usr/sbin/write_gpt.sh"
cgpt_py() { cgpt_py() {
if [[ -n "${FLAGS_adjust_part-}" ]]; then if [[ -n "${FLAGS_adjust_part-}" ]]; then
@ -20,7 +19,6 @@ cgpt_py() {
get_disk_layout_path() { get_disk_layout_path() {
DISK_LAYOUT_PATH="${BUILD_LIBRARY_DIR}/legacy_disk_layout.json" DISK_LAYOUT_PATH="${BUILD_LIBRARY_DIR}/legacy_disk_layout.json"
local partition_script_path=$(tempfile)
for overlay in $(cros_list_overlays --board "$BOARD"); do for overlay in $(cros_list_overlays --board "$BOARD"); do
local disk_layout="${overlay}/scripts/disk_layout.json" local disk_layout="${overlay}/scripts/disk_layout.json"
if [[ -e ${disk_layout} ]]; then if [[ -e ${disk_layout} ]]; then
@ -29,23 +27,9 @@ get_disk_layout_path() {
done done
} }
write_partition_script() { write_partition_table() {
local image_type=$1 local image_type=$1
local partition_script_path=$2 local outdev=$2
get_disk_layout_path
local temp_script_file=$(mktemp)
sudo mkdir -p "$(dirname "${partition_script_path}")"
cgpt_py write "${image_type}" "${DISK_LAYOUT_PATH}" \
"${temp_script_file}"
sudo mv "${temp_script_file}" "${partition_script_path}"
}
run_partition_script() {
local outdev=$1
local root_fs_img=$2
local pmbr_img local pmbr_img
case ${ARCH} in case ${ARCH} in
@ -61,13 +45,10 @@ run_partition_script() {
;; ;;
esac esac
if is_mounted "${root_fs_dir}"; then get_disk_layout_path
safe_umount "${root_fs_dir}" cgpt_py write_gpt "${image_type}" "${DISK_LAYOUT_PATH}" "${outdev}"
fi cgpt_py write_mbr \
sudo mount -o loop "${root_fs_img}" "${root_fs_dir}" "${image_type}" "${DISK_LAYOUT_PATH}" "${outdev}" "${pmbr_img}"
. "${root_fs_dir}/${PARTITION_SCRIPT_PATH}"
write_partition_table "${outdev}" "${pmbr_img}"
safe_umount "${root_fs_dir}"
} }
get_fs_block_size() { get_fs_block_size() {
@ -131,9 +112,6 @@ check_valid_layout() {
get_disk_layout_type() { get_disk_layout_type() {
DISK_LAYOUT_TYPE="base" DISK_LAYOUT_TYPE="base"
if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
DISK_LAYOUT_TYPE="factory_install"
fi
} }
emit_gpt_scripts() { emit_gpt_scripts() {
@ -204,7 +182,7 @@ build_gpt() {
local oem_img="$5" local oem_img="$5"
get_disk_layout_type get_disk_layout_type
run_partition_script "${outdev}" "${rootfs_img}" write_partition_table "${DISK_LAYOUT_TYPE}" "${outdev}"
local sudo= local sudo=
if [ ! -w "$outdev" ] ; then if [ ! -w "$outdev" ] ; then

View File

@ -1,7 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
'''Scan an existing directory tree and record installed directories. '''Scan an existing directory tree and record installed directories.
During build a number of directories under /var are created in the stateful During build a number of directories under /var are created in the state
partition. We want to make sure that those are always there so create a record partition. We want to make sure that those are always there so create a record
of them using systemd's tempfiles config format so they are recreated during of them using systemd's tempfiles config format so they are recreated during
boot if they go missing for any reason. boot if they go missing for any reason.
@ -19,6 +19,8 @@ def main():
parser = optparse.OptionParser(description=__doc__) parser = optparse.OptionParser(description=__doc__)
parser.add_option('--root', help='Remove root prefix from output') parser.add_option('--root', help='Remove root prefix from output')
parser.add_option('--output', help='Write output to the given file') parser.add_option('--output', help='Write output to the given file')
parser.add_option('--ignore', action='append', default=[],
help='Ignore one or more paths (use multiple times)')
opts, args = parser.parse_args() opts, args = parser.parse_args()
if opts.root: if opts.root:
@ -56,6 +58,9 @@ def main():
else: else:
stripped = path stripped = path
if stripped in opts.ignore:
continue
info = os.stat(path) info = os.stat(path)
assert stat.S_ISDIR(info.st_mode) assert stat.S_ISDIR(info.st_mode)
mode = stat.S_IMODE(info.st_mode) mode = stat.S_IMODE(info.st_mode)

View File

@ -23,7 +23,7 @@
"label":"ROOT-A", "label":"ROOT-A",
"uuid":"7130c94a-213a-4e5a-8e26-6cce9662f132", "uuid":"7130c94a-213a-4e5a-8e26-6cce9662f132",
"type":"coreos-rootfs", "type":"coreos-rootfs",
"blocks":"4194304", "blocks":"2097152",
"fs_blocks":"262144" "fs_blocks":"262144"
}, },
{ {
@ -31,7 +31,7 @@
"label":"ROOT-B", "label":"ROOT-B",
"uuid":"e03dd35c-7c2d-4a47-b3fe-27f15780a57c", "uuid":"e03dd35c-7c2d-4a47-b3fe-27f15780a57c",
"type":"coreos-rootfs", "type":"coreos-rootfs",
"blocks":"4194304", "blocks":"2097152",
"fs_blocks":"262144" "fs_blocks":"262144"
}, },
{ {
@ -63,73 +63,10 @@
"num": 9, "num": 9,
"label":"STATE", "label":"STATE",
"type":"data", "type":"data",
"blocks":"2097152", "blocks":"2097152"
"features":["expand"]
}
],
"usb": [
{
"num": 3,
"label":"ROOT-A",
"uuid":"7130c94a-213a-4e5a-8e26-6cce9662f132",
"type":"coreos-rootfs",
"blocks":"2539520",
"fs_blocks":"262144"
},
{
"num": 4,
"label":"ROOT-B",
"uuid":"e03dd35c-7c2d-4a47-b3fe-27f15780a57c",
"type":"coreos-rootfs",
"blocks":"1"
}
],
"factory_install": [
{
"num": 1,
"label":"EFI-SYSTEM",
"type":"efi",
"blocks":"65536"
},
{
"num": 3,
"label":"ROOT-A",
"uuid":"7130c94a-213a-4e5a-8e26-6cce9662f132",
"type":"coreos-rootfs",
"blocks":"860160",
"fs_blocks":"102400"
},
{
"num": 4,
"label":"ROOT-B",
"uuid":"e03dd35c-7c2d-4a47-b3fe-27f15780a57c",
"type":"coreos-rootfs",
"blocks":"1"
},
{
"num": 9,
"label":"STATE",
"type":"data",
"blocks":"286720"
} }
], ],
"vm": [ "vm": [
{
"num": 3,
"label":"ROOT-A",
"uuid":"7130c94a-213a-4e5a-8e26-6cce9662f132",
"type":"coreos-rootfs",
"blocks":"2097152",
"fs_blocks":"262144"
},
{
"num": 4,
"label":"ROOT-B",
"uuid":"e03dd35c-7c2d-4a47-b3fe-27f15780a57c",
"type":"coreos-rootfs",
"blocks":"2097152",
"fs_blocks":"262144"
},
{ {
"num": 9, "num": 9,
"label":"STATE", "label":"STATE",

View File

@ -180,14 +180,8 @@ unpack_source_disk() {
cp --sparse=always "${alternate_state_image}" "${TEMP_STATE}" cp --sparse=always "${alternate_state_image}" "${TEMP_STATE}"
fi fi
TEMP_PMBR="${VM_TMP_DIR}"/pmbr
dd if="${VM_SRC_IMG}" of="${TEMP_PMBR}" bs=512 count=1
info "Initializing new partition table..." info "Initializing new partition table..."
TEMP_PARTITION_SCRIPT="${VM_TMP_DIR}/partition_script.sh" write_partition_table "${disk_layout}" "${VM_TMP_IMG}"
write_partition_script "${disk_layout}" "${TEMP_PARTITION_SCRIPT}"
. "${TEMP_PARTITION_SCRIPT}"
write_partition_table "${VM_TMP_IMG}" "${TEMP_PMBR}"
} }
resize_state_partition() { resize_state_partition() {
@ -197,10 +191,10 @@ resize_state_partition() {
local original_size=$(stat -c%s "${TEMP_STATE}") local original_size=$(stat -c%s "${TEMP_STATE}")
if [[ "${original_size}" -gt "${size_in_bytes}" ]]; then if [[ "${original_size}" -gt "${size_in_bytes}" ]]; then
die "Cannot resize stateful image to smaller than original." die "Cannot resize state image to smaller than original."
fi fi
info "Resizing stateful partition to ${size_in_mb}MB" info "Resizing state partition to ${size_in_mb}MB"
/sbin/e2fsck -pf "${TEMP_STATE}" /sbin/e2fsck -pf "${TEMP_STATE}"
/sbin/resize2fs "${TEMP_STATE}" "${size_in_sectors}s" /sbin/resize2fs "${TEMP_STATE}" "${size_in_sectors}s"
} }

View File

@ -68,7 +68,9 @@ if [ -z "${FLAGS_board}" ] ; then
die_notrace "--board is required." die_notrace "--board is required."
fi fi
BOARD="$FLAGS_board" # Loaded after flags are parsed because board_options depends on --board
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
IMAGES_DIR="${DEFAULT_BUILD_ROOT}/images/${FLAGS_board}" IMAGES_DIR="${DEFAULT_BUILD_ROOT}/images/${FLAGS_board}"
# Default to the most recent image # Default to the most recent image

View File

@ -1,104 +0,0 @@
#!/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.
# Script to verify integrity of root file system for a GPT-based image
SCRIPT_ROOT=$(dirname $(readlink -f "$0"))
. "${SCRIPT_ROOT}/common.sh" || exit 1
# Load functions and constants for chromeos-install
[ -f /usr/lib/installer/chromeos-common.sh ] && \
INSTALLER_ROOT=/usr/lib/installer || \
INSTALLER_ROOT=$(dirname "$(readlink -f "$0")")
. "${INSTALLER_ROOT}/chromeos-common.sh" || exit 1
# Needed for partoffset and partsize calls
locate_gpt
# Script must be run inside the chroot.
restart_in_chroot_if_needed "$@"
DEFINE_string image "" "Device or an image path. Default: (empty)."
# Parse command line.
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
if [ -z $FLAGS_image ] ; then
die_notrace "Use --image to specify a device or an image file."
fi
# Turn path into an absolute path.
FLAGS_image=$(eval readlink -f ${FLAGS_image})
# Abort early if we can't find the image
if [ ! -b ${FLAGS_image} ] && [ ! -f $FLAGS_image ] ; then
die_notrace "No image found at $FLAGS_image"
fi
switch_to_strict_mode
get_partitions() {
if [ -b ${FLAGS_image} ] ; then
KERNEL_IMG=$(make_partition_dev "${FLAGS_image}" 2)
ROOTFS_IMG=$(make_partition_dev "${FLAGS_image}" 3)
return
fi
KERNEL_IMG=$(mktemp)
ROOTFS_IMG=$(mktemp)
local kernel_offset=$(partoffset "${FLAGS_image}" 2)
local kernel_count=$(partsize "${FLAGS_image}" 2)
local rootfs_offset=$(partoffset "${FLAGS_image}" 3)
local rootfs_count=$(partsize "${FLAGS_image}" 3)
# TODO(tgao): use loop device to save 1GB in temp space
dd if="${FLAGS_image}" of=${KERNEL_IMG} bs=512 skip=${kernel_offset} \
count=${kernel_count} &>/dev/null
dd if="${FLAGS_image}" of=${ROOTFS_IMG} bs=512 skip=${rootfs_offset} \
count=${rootfs_count} &>/dev/null
}
cleanup() {
for i in ${KERNEL_IMG} ${ROOTFS_IMG}; do
if [ ! -b ${i} ]; then
rm -f ${i}
fi
done
}
get_partitions
# Logic below extracted from src/platform/installer/chromeos-setimage
DUMP_KERNEL_CONFIG=/usr/bin/dump_kernel_config
KERNEL_CONFIG=$(sudo "${DUMP_KERNEL_CONFIG}" "${KERNEL_IMG}")
kernel_cfg="$(echo "${KERNEL_CONFIG}" | sed -e 's/.*dm="\([^"]*\)".*/\1/g' |
cut -f2- -d,)"
rootfs_sectors=$(echo ${kernel_cfg} | cut -f2 -d' ')
verity_algorithm=$(echo ${kernel_cfg} | cut -f8 -d' ')
# Compute the rootfs hash tree
VERITY=/bin/verity
# First argument to verity is reserved/unused and MUST be 0
table="vroot none ro,"$(sudo "${VERITY}" create 0 \
"${verity_algorithm}" \
"${ROOTFS_IMG}" \
$((rootfs_sectors / 8)) \
/dev/null)
expected_hash=$(echo ${kernel_cfg} | cut -f9 -d' ')
generated_hash=$(echo ${table} | cut -f2- -d, | cut -f9 -d' ')
cleanup
if [ "${expected_hash}" != "${generated_hash}" ]; then
warn "expected hash = ${expected_hash}"
warn "actual hash = ${generated_hash}"
die_notrace "Root filesystem has been modified unexpectedly!"
else
info "Root filesystem checksum match!"
fi