fix(build_library): Remove GPT writer scripts, call cgpt directly.

This change removes /usr/sbin/write_gpt.sh from images which we have no
use for. This allows us to drop the indirection of writing partition
tables by first writing out a script to call. Now cgpt.py can call cgpt
directly to initialize the partition layout. This opens the way for
further improvements to how disk images are created.
This commit is contained in:
Michael Marineau 2013-08-20 20:57:13 -04:00
parent 1ad0ea2eab
commit 34c324cc3a
6 changed files with 68 additions and 139 deletions

View File

@ -227,12 +227,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)

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
@ -206,61 +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)
disk_block_count = START_SECTOR * config['metadata']['block_size'] disk_block_count = START_SECTOR * config['metadata']['block_size']
for partition in partitions: for partition in partitions:
disk_block_count += partition['blocks'] disk_block_count += partition['blocks']
sfile.write('%s() {\ncreate_image $1 %d %s\n' % ( sector = START_SECTOR
func_name, disk_block_count, Cgpt('create', '-c', '-s', disk_block_count, disk_filename)
config['metadata']['block_size']))
sfile.write('CURR=%d\n' % START_SECTOR)
sfile.write('$GPT create $1\n')
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['blocks']), 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['blocks']) '-i', str(partition['num']), disk_filename])
sfile.write('$GPT show $1\n')
sfile.write('}\n')
def GetPartitionByNumber(partitions, num): def GetPartitionByNumber(partitions, num):
@ -299,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.
@ -498,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

@ -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() {
@ -204,7 +185,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

@ -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() {

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