blob: 3630e41c2d935d1251591b85c185eaa45b99e866 [file] [log] [blame]
# 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.
CGPT_PY="${BUILD_LIBRARY_DIR}/cgpt.py"
PARTITION_SCRIPT_PATH="usr/sbin/write_gpt.sh"
get_disk_layout_path() {
DISK_LAYOUT_PATH="${BUILD_LIBRARY_DIR}/legacy_disk_layout.json"
local partition_script_path=$(tempfile)
for overlay in $(cros_overlay_list --board "$BOARD"); do
local disk_layout="${overlay}/scripts/disk_layout.json"
if [[ -e ${disk_layout} ]]; then
DISK_LAYOUT_PATH=${disk_layout}
fi
done
}
write_partition_script() {
local image_type=$1
local partition_script_path=$2
get_disk_layout_path
sudo mkdir -p "$(dirname "${partition_script_path}")"
sudo "${BUILD_LIBRARY_DIR}/cgpt.py" "write" \
"${image_type}" "${DISK_LAYOUT_PATH}" "${partition_script_path}"
}
run_partition_script() {
local outdev=$1
local root_fs_img=$2
local pmbr_img
case ${ARCH} in
arm)
pmbr_img=/dev/zero
;;
amd64|x86)
pmbr_img=$(readlink -f /usr/share/syslinux/gptmbr.bin)
;;
*)
error "Unknown architecture: $ARCH"
return 1
;;
esac
sudo mount -o loop "${root_fs_img}" "${root_fs_dir}"
. "${root_fs_dir}/${PARTITION_SCRIPT_PATH}"
write_partition_table "${outdev}" "${pmbr_img}"
sudo umount "${root_fs_dir}"
}
get_fs_block_size() {
get_disk_layout_path
echo $(${CGPT_PY} readfsblocksize ${DISK_LAYOUT_PATH})
}
get_block_size() {
get_disk_layout_path
echo $(${CGPT_PY} readblocksize ${DISK_LAYOUT_PATH})
}
get_partition_size() {
local image_type=$1
local part_id=$2
get_disk_layout_path
echo $(${CGPT_PY} readpartsize ${image_type} ${DISK_LAYOUT_PATH} ${part_id})
}
get_filesystem_size() {
local image_type=$1
local part_id=$2
get_disk_layout_path
echo $(${CGPT_PY} readfssize ${image_type} ${DISK_LAYOUT_PATH} ${part_id})
}
get_label() {
local image_type=$1
local part_id=$2
get_disk_layout_path
echo $(${CGPT_PY} readlabel ${image_type} ${DISK_LAYOUT_PATH} ${part_id})
}
get_disk_layout_type() {
DISK_LAYOUT_TYPE="base"
if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
DISK_LAYOUT_TYPE="factory_install"
fi
}
emit_gpt_scripts() {
local image="$1"
local dir="$2"
local pack="${dir}/pack_partitions.sh"
local unpack="${dir}/unpack_partitions.sh"
local mount="${dir}/mount_image.sh"
local umount="${dir}/umount_image.sh"
local start size part x
cat >"${unpack}" <<EOF
#!/bin/bash -eu
# File automatically generated. Do not edit.
TARGET=\${1:-}
if [[ -z \${TARGET} ]]; then
echo "Usage: \$0 <image>" 1>&2
echo "Example: \$0 chromiumos_image.bin" 1>&2
exit 1
fi
set -x
$(${GPT} show "${image}" | sed -e 's/^/# /')
EOF
for x in "${pack}" "${mount}" "${umount}"; do
cp "${unpack}" "${x}"
done
while read start size part x; do
local file="part_${part}"
local dir="dir_${part}"
local target='"${TARGET}"'
local dd_args="bs=512 count=${size}"
local start_b=$(( start * 512 ))
local size_b=$(( size * 512 ))
echo "dd if=${target} of=${file} ${dd_args} skip=${start}" >>"${unpack}"
echo "dd if=${file} of=${target} ${dd_args} seek=${start} conv=notrunc" \
>>"${pack}"
if [[ ${size} -gt 1 ]]; then
cat <<-EOF >>"${mount}"
mkdir -p ${dir}
sudo mount -o loop,offset=${start_b},sizelimit=${size_b} ${target} ${dir} || \
rmdir ${dir}
EOF
cat <<-EOF >>"${umount}"
if [[ -d ${dir} ]]; then
sudo umount ${dir} || :
rmdir ${dir}
fi
EOF
fi
done < <(${GPT} show -q "${image}")
chmod +x "${unpack}" "${pack}" "${mount}" "${umount}"
}
build_gpt() {
local outdev="$1"
local rootfs_img="$2"
local stateful_img="$3"
local esp_img="$4"
local oem_img="$5"
get_disk_layout_type
run_partition_script "${outdev}" "${rootfs_img}"
local sudo=
if [ ! -w "$outdev" ] ; then
# use sudo when writing to a block device.
sudo=sudo
fi
# Now populate the partitions.
info "Copying stateful partition..."
$sudo dd if="$stateful_img" of="$outdev" conv=notrunc bs=512 \
seek=$(partoffset ${outdev} 1)
info "Copying rootfs..."
$sudo dd if="$rootfs_img" of="$outdev" conv=notrunc bs=512 \
seek=$(partoffset ${outdev} 3)
info "Copying EFI system partition..."
$sudo dd if="$esp_img" of="$outdev" conv=notrunc bs=512 \
seek=$(partoffset ${outdev} 12)
info "Copying OEM partition..."
$sudo dd if="$oem_img" of="$outdev" conv=notrunc bs=512 \
seek=$(partoffset ${outdev} 8)
# Pre-set "sucessful" bit in gpt, so we will never mark-for-death
# a partition on an SDCard/USB stick.
cgpt add -i 2 -S 1 "$outdev"
}
# Rebuild an image's partition table with new stateful size.
# $1: source image filename
# $2: source stateful partition image filename
# $3: number of sectors to allocate to the new stateful partition
# $4: destination image filename
# Used by dev/host/tests/mod_recovery_for_decryption.sh and
# mod_image_for_recovery.sh.
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 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
rm -f "${temp_img}"
PARTITION_SCRIPT_PATH=$( tempfile )
write_partition_script "recovery" "${PARTITION_SCRIPT_PATH}"
. "${PARTITION_SCRIPT_PATH}"
write_partition_table "${temp_img}" "${temp_pmbr}"
echo "${PARTITION_SCRIPT_PATH}"
local kern_a_dst_offset=$(partoffset ${temp_img} 2)
local kern_a_src_offset=$(partoffset ${src_img} 2)
local kern_a_count=$(partsize ${src_img} 2)
local kern_b_dst_offset=$(partoffset ${temp_img} 4)
local kern_b_src_offset=$(partoffset ${src_img} 4)
local kern_b_count=$(partsize ${src_img} 4)
local rootfs_dst_offset=$(partoffset ${temp_img} 3)
local rootfs_src_offset=$(partoffset ${src_img} 3)
local rootfs_count=$(partsize ${src_img} 3)
local oem_dst_offset=$(partoffset ${temp_img} 8)
local oem_src_offset=$(partoffset ${src_img} 8)
local oem_count=$(partsize ${src_img} 8)
local esp_dst_offset=$(partoffset ${temp_img} 12)
local esp_src_offset=$(partoffset ${src_img} 12)
local esp_count=$(partsize ${src_img} 12)
local state_dst_offset=$(partoffset ${temp_img} 1)
# Copy into the partition parts of the file
dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \
seek=${rootfs_dst_offset} skip=${rootfs_src_offset} count=${rootfs_count}
dd if="${temp_state}" of="${temp_img}" conv=notrunc bs=512 \
seek=${state_dst_offset}
# Copy the full kernel (i.e. with vboot sections)
dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \
seek=${kern_a_dst_offset} skip=${kern_a_src_offset} count=${kern_a_count}
dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \
seek=${kern_b_dst_offset} skip=${kern_b_src_offset} count=${kern_b_count}
dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \
seek=${oem_dst_offset} skip=${oem_src_offset} count=${oem_count}
dd if="${src_img}" of="${temp_img}" conv=notrunc bs=512 \
seek=${esp_dst_offset} skip=${esp_src_offset} count=${esp_count}
}