| #!/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. |
| |
| # Utility methods used to resize a stateful partition and update the GPT table |
| |
| # --- 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" |
| |
| locate_gpt |
| |
| umount_from_loop_dev() { |
| local mnt_pt=$1 |
| mount | grep -q " on ${mnt_pt}" && sudo umount -d ${mnt_pt} |
| rmdir ${mnt_pt} |
| } |
| |
| cleanup_loop_dev() { |
| sudo losetup -d ${1} || /bin/true |
| } |
| |
| get_loop_dev() { |
| local loop_dev=$(sudo losetup -f) |
| if [ -z "${loop_dev}" ]; then |
| die "No free loop device. Free up a loop device or reboot. Exiting." |
| fi |
| echo ${loop_dev} |
| } |
| |
| # Resize stateful partition of install shim to hold payload content |
| # Due to this resize, we need to create a new partition table and a new image. |
| # (see update_partition_table() for details) |
| enlarge_partition_image() { |
| local source_part=$1 # source partition |
| local add_num_sectors=$2 # number of 512-byte sectors to be added |
| |
| local source_sectors=$(roundup $(numsectors ${source_part})) |
| info "source partition has ${source_sectors} 512-byte sectors." |
| local resized_sectors=$(roundup $(expr $source_sectors + $add_num_sectors)) |
| info "resized partition has ${resized_sectors} 512-byte sectors." |
| |
| local loop_dev=$(get_loop_dev) |
| trap "cleanup_loop_dev ${loop_dev}" EXIT |
| |
| # Extend the source file size to the new size. |
| dd if=/dev/zero of="${source_part}" bs=1 count=1 \ |
| seek=$((512 * ${resized_sectors} - 1)) &>/dev/null |
| |
| # Resize the partition. |
| sudo losetup "${loop_dev}" "${source_part}" |
| sudo e2fsck -fp "${loop_dev}" &> /dev/null |
| sudo resize2fs "${loop_dev}" &> /dev/null |
| # trap handler will clean up the loop device |
| echo "${resized_sectors}" |
| } |
| |
| # Update partition table with resized stateful partition |
| update_partition_table() { |
| local src_img=$1 # source image |
| local temp_state=$2 # stateful partition image |
| local resized_sectors=$3 # number of sectors in resized stateful partition |
| local temp_img=$4 |
| |
| local kern_a_offset=$(partoffset ${src_img} 2) |
| local kern_a_count=$(partsize ${src_img} 2) |
| local kern_b_offset=$(partoffset ${src_img} 4) |
| local kern_b_count=$(partsize ${src_img} 4) |
| local rootfs_offset=$(partoffset ${src_img} 3) |
| local rootfs_count=$(partsize ${src_img} 3) |
| local oem_offset=$(partoffset ${src_img} 8) |
| local oem_count=$(partsize ${src_img} 8) |
| local esp_offset=$(partoffset ${src_img} 12) |
| local esp_count=$(partsize ${src_img} 12) |
| |
| local temp_pmbr=$(mktemp "/tmp/pmbr.XXXXXX") |
| dd if="${src_img}" of="${temp_pmbr}" bs=512 count=1 &>/dev/null |
| |
| trap "rm -rf \"${temp_pmbr}\"" EXIT |
| # Set up a new partition table |
| install_gpt "${temp_img}" "${rootfs_count}" "${resized_sectors}" \ |
| "${temp_pmbr}" "${esp_count}" false \ |
| $(((rootfs_count * 512)/(1024 * 1024))) |
| |
| # Copy into the partition parts of the file |
| dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_ROOTFS_A}" skip=${rootfs_offset} count=${rootfs_count} |
| dd if="${temp_state}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_STATEFUL}" |
| # Copy the full kernel (i.e. with vboot sections) |
| dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_KERN_A}" skip=${kern_a_offset} count=${kern_a_count} |
| dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_KERN_B}" skip=${kern_b_offset} count=${kern_b_count} |
| dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_OEM}" skip=${oem_offset} count=${oem_count} |
| dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \ |
| seek="${START_ESP}" skip=${esp_offset} count=${esp_count} |
| } |