Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Unified Diff: src/platform/installer/chromeos_install_functions.sh

Issue 445002: Switch to GPT partition format.
Patch Set: Address adlr comment Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/platform/installer/chromeos_install_functions.sh
diff --git a/src/platform/installer/chromeos_install_functions.sh b/src/platform/installer/chromeos_install_functions.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c88a5dd12e2099568b2cfa4e8c8061177da227f4
--- /dev/null
+++ b/src/platform/installer/chromeos_install_functions.sh
@@ -0,0 +1,269 @@
+#!/bin/sh
+
+# Copyright (c) 2009 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.
+
+# Shell functions to help create a bootable image or install to a hard disk.
+# NOTE: Please keep this file dash and busybox compliant.
+
+# Variables that affect the install process. Set these as desired before
+# sourcing this file.
+MBR=${MBR:-/tmp/gpt.mbr}
+GPT=${GPT:-gpt}
+STATEFUL_PART_SIZE=${STATEFUL_PART_SIZE:-} # Defaults to automatic computation.
+SWAP_PART_SIZE=${SWAP_PART_SIZE:-$((1024 * 1024 * 1024))}
+DEFAULT_STATEFUL_PART_SIZE=${DEFAULT_STATEFUL_PART_SIZE:-$((512 * 1024 * 1024))}
+
+# Given a path, return the size of the file or device at that path. This
+# fills in the GET_SIZE_RESULT variable.
+GET_SIZE_RESULT=
+get_size() {
+ local path="$1"
+
+ GET_SIZE_RESULT=0
+ if [ -b "$path" ] ; then
+ local device="${path#/dev/}"
+ if [ -f "/sys/block/${device}/size" ] ; then
+ # device must be like 'sdb'
+ GET_SIZE_RESULT=$(cat "/sys/block/${device}/size")
+ else
+ # device must be like 'sdb3'
+ local part="$device"
+ local len=${#part}
+ device=$(printf "%0.$((len - 1))s" $part)
+ GET_SIZE_RESULT=$(cat "/sys/block/${device}/${part}/size")
+ fi
+ GET_SIZE_RESULT=$((GET_SIZE_RESULT * 512))
+ else
+ GET_SIZE_RESULT=$(stat -c%s "$path") # Bytes
+ fi
+}
+
+# A dd equivalent that tries to use a large block size.
+do_copy() {
+ local in="$1" # Input file
+ local out="$2" # Output file
+ local seek_offset="$3" # Offset where to write the data, in bytes.
+ local skip_offset="$4" # Offset from where to read the data, in bytes.
+
+ # We use a 4M output block size
+ local bs=$((4 * 1024 * 1024))
+
+ local skip_count=$((skip_offset / 512))
+
+ # How much initial non-aligned data do we need to copy?
+ local begin_size=$((bs - (seek_offset % bs)))
+ local count=$((begin_size / 512))
+ local seek=$((seek_offset / 512))
+ sudo dd if="$in" of="$out" bs=512 \
+ skip=$skip_count seek=$seek count=$count conv=notrunc
+
+ # Now copy the rest of the data with output aligned at $bs
+ seek=$(( (seek_offset + begin_size) / bs ))
+ sudo dd if="$in" of="$out" ibs=512 obs=$bs \
+ skip=$((skip_count + count)) seek=$seek conv=notrunc
+}
+
+# Computes the required install size for the system. This does not include
+# the stateful partition. The call fills in the SYSTEM_INSTALL_SIZE variable.
+SYSTEM_INSTALL_SIZE=
+get_system_install_size() {
+ local rootfs=$1
+ local type=$2 # Either 'minimal' or 'full'
+
+ # Approx space for GPT metadata
+ local gpt_size=$((34 * 1024))
+
+ # Determine the size of one rootfs partition.
+ get_size "$rootfs"
+ local root_size=$GET_SIZE_RESULT
+
+ # A minimal install has just the stateful and system partitions.
+ SYSTEM_INSTALL_SIZE=$((gpt_size + root_size))
+ if [ "$type" = "full" ] ; then
+ # A full install also includes a secondary system partition and swap.
+ SYSTEM_INSTALL_SIZE=$((SYSTEM_INSTALL_SIZE + root_size))
+ SYSTEM_INSTALL_SIZE=$((SYSTEM_INSTALL_SIZE + SWAP_PART_SIZE))
+ fi
+}
+
+# Computes the size of the stateful partition. If the STATEFUL_PART_SIZE is
+# already set then we'll use that, otherwise it will default to the free
+# space on a block device or a default value if output is to a file.
+get_stateful_part_size() {
+ local rootfs=$1
+ local dest=$2
+ local type=$3
+
+ if [ -n "$STATEFUL_PART_SIZE" ] ; then
+ return; # Already computed or they set an override value.
+ fi
+ if [ -b "$dest" ] ; then
+ # For a block device, we'll default to using up all free space.
+ get_system_install_size "$rootfs" "$type"
+ get_size "$dest"
+ STATEFUL_PART_SIZE=$((GET_SIZE_RESULT - SYSTEM_INSTALL_SIZE))
+ else
+ # We'll use a default stateful part size.
+ STATEFUL_PART_SIZE=$((DEFAULT_STATEFUL_PART_SIZE))
+ fi
+}
+
+# Verifies that it is really OK to install to the destination.
+do_verify() {
+ local rootfs=$1 # Path to file/device containing the system rootfs
+ local dest=$2 # Path to file/device on which the install will happen
+ local type=$3 # Either 'minimal' or 'full'
+
+ if [ -e "$dest" ] ; then
+ echo "This will erase all data at this destination: $dest"
+ read -p "Are you sure (y/N)? " SURE
+ if [ "$SURE" != "y" ] ; then
+ echo "Ok, better safe than sorry; you answered '$SURE'."
+ exit 1
+ fi
+
+ if [ -b "$dest" ] ; then
+ # Do we have enough room to install on the block device?
+ get_system_install_size "$rootfs" "$type"
+ get_stateful_part_size "$rootfs" "$dest" "$type"
+ local size_needed=$((SYSTEM_INSTALL_SIZE + STATEFUL_PART_SIZE))
+
+ get_size "$dest"
+ local dest_size=$GET_SIZE_RESULT
+ if [ $dest_size -lt $size_needed ] ; then
+ echo "Error: Destination device '$dest' is too small:"
+ echo " ($dest_size vs $size_needed)"
+ exit 1
+ fi
+ fi
+ fi
+}
+
+do_cleanup() {
+ sudo losetup -d "$LOOP_DEV"
+}
+
+# Given a rootfs, sets up the destination to boot it with proper partitions.
+install_chromeos() {
+ local rootfs=$1 # Path to file/device containing the system rootfs
+ local dest=$2 # Path to file/device on which to create a bootable install
+ local label_prefix=$3 # Prefix character to use for file system labels
+ local type=$4 # Either 'minimal' or 'full'
+
+ # How big are each of our partitions?
+ get_size "$rootfs"
+ local system_part_size=$GET_SIZE_RESULT # bytes
+ get_stateful_part_size "$rootfs" "$dest" "$type"
+ local stateful_part_size=$STATEFUL_PART_SIZE
+ local swap_part_size=$SWAP_PART_SIZE
+
+ # If we output to a file, then create/truncate it to the proper length.
+ if [ ! -b "$dest" ] ; then
+ get_system_install_size "$rootfs" "$type"
+ local dest_size=$((SYSTEM_INSTALL_SIZE + stateful_part_size))
+ dd if=/dev/zero of="$dest" bs=1 count=1 seek=$((dest_size - 1))
+ fi
+
+ # -- Partitions --
+
+ # What partition should we make bootable by default?
+ local boot_part=
+
+ # Set up GPT partition format
+ sudo dd if=/dev/zero of="$dest" bs=1M count=1 conv=notrunc
+ sudo $GPT create -f "$dest"
+
+ # Add and label all partitions. The current partitioning scheme(s) are very
+ # likely to change. NOTE: The label is not the same as the file system label.
+ if [ "$type" = "minimal" ] ; then
+ # Part Label FS Usage
+ # 1 User Data (ext3/4) Statefule partition
+ # 2 System (ext3/4) Root file system
+ sudo $GPT add -i 1 -s $((stateful_part_size / 512)) -t linux "$dest"
+ sudo $GPT add -i 2 -s $((system_part_size / 512)) -t linux "$dest"
+
+ sudo $GPT label -i 1 -l "User Data" "$dest"
+ sudo $GPT label -i 2 -l "System" "$dest"
+
+ boot_part=2
+ else
+ # Part Label FS Usage
+ # 1 User Data (ext3/4) Statefule partition
+ # 2 Swap swap May be used for swap
+ # 3 System (ext3/4) Root file system
+ # 4 System2 (ext3/4) Root file system (alternate)
+ sudo $GPT add -i 1 -s $((stateful_part_size / 512)) -t linux "$dest"
+ sudo $GPT add -i 2 -s $((swap_size / 512)) -t linux-swap "$dest"
+ sudo $GPT add -i 3 -s $((system_part_size / 512)) -t linux "$dest"
+ sudo $GPT add -i 4 -s $((system_part_size / 512)) -t linux "$dest"
+
+ sudo $GPT label -i 1 -l "User Data" "$dest"
+ sudo $GPT label -i 2 -l "Swap" "$dest"
+ sudo $GPT label -i 3 -l "System" "$dest"
+ sudo $GPT label -i 4 -l "System2" "$dest"
+
+ boot_part=3
+ fi
+
+ # Set up a boot MBR for booting on legacy devices.
+ sudo $GPT boot -b "$MBR" -i $boot_part "$dest"
+
+ # -- System Image --
+
+ # We copy the system image a bit strangely here because we have observed
+ # cases in install to hard disk where people ctrl-c the operation and then
+ # are not longer able to properly boot a USB image. This is because when
+ # booting from USB we set the root device by LABEL, so if you partially
+ # copy the FS here without updating the label then a subsequent USB boot
+ # may try to use the wrong device and fail.
+
+ echo "Copying the system image. This might take a while..."
+ local offset_sectors=$(sudo $GPT -r show -l "$dest" | grep "\"System\"" \
+ | awk '{ print $1 }')
+
+ # Copy first 2 kibibytes of the root image to a temp file, set the label,
+ # and then copy it to the dest.
+ # NOTE: This hack won't work if we stop using an ext based FS
+ local superblock_offset=1024
+ local label_field_offset=120
+ local label_field_length=16
+ local tmp=$(mktemp)
+ sudo dd if="$rootfs" of="$tmp" bs=1024 count=2
+ sudo dd if=/dev/zero of="$tmp" bs=1 \
+ seek=$((superblock_offset + label_field_offset)) \
+ count=$label_field_length conv=notrunc
+ echo -n "${label_prefix}-ROOT" | sudo dd of="$tmp" \
+ seek=$((superblock_offset + label_field_offset)) \
+ bs=1 count=$((label_field_length - 1)) conv=notrunc
+ sudo dd if="$tmp" of="$dest" bs=512 seek=$offset_sectors conv=notrunc
+ rm "$tmp"
+
+ # Copy all but the first 2 kibibytes to the destination now.
+ do_copy "$rootfs" "$dest" $(( (offset_sectors * 512) + 2048)) 2048
+
+ # -- Stateful Partition --
+
+ echo "Formatting the user data partition..."
+ offset=$(sudo $GPT -r show -l "$dest" | grep "\"User Data\"" \
+ | awk '{ print $1 }')
+ LOOP_DEV=$(sudo losetup -f)
+ if [ -z "$LOOP_DEV" ]
+ then
+ echo "No free loop device. Free up a loop device or reboot. exiting."
+ exit 1
+ fi
+
+ trap do_cleanup EXIT
+
+ echo "Creating stateful partition..."
+ sudo losetup -o $((offset * 512)) "$LOOP_DEV" "$dest"
+ sudo mkfs.ext3 -F -b 4096 -L "${label_prefix}-STATE" \
+ "$LOOP_DEV" $((stateful_part_size / 4096))
+ sync
+ sudo losetup -d "$LOOP_DEV"
+ sync
+
+ trap - EXIT
+}

Powered by Google App Engine
This is Rietveld 408576698