Move factory_setup to factory repo.
BUG=None
CQ-DEPEND=CL:38634,CL:38635,CL:38636,CL:38638,CL:38639,CL:38641
TEST=buildbot
Change-Id: Ic0e429df4db4a35fd597aa0d5945660ef8c996a2
(cherry picked from commit d8cbbddde48dbc9735480d8efc472d657923fd33)
Reviewed-on: https://gerrit.chromium.org/gerrit/38636
Commit-Ready: Jon Salz <jsalz@chromium.org>
Reviewed-by: Jon Salz <jsalz@chromium.org>
Tested-by: Jon Salz <jsalz@chromium.org>
diff --git a/README.factory_setup b/README.factory_setup
new file mode 100644
index 0000000..4f6d2fd
--- /dev/null
+++ b/README.factory_setup
@@ -0,0 +1,2 @@
+The factory_setup directory has been moved to the platform/factory
+repository.
\ No newline at end of file
diff --git a/factory_setup/README.txt b/factory_setup/README.txt
deleted file mode 100644
index 5d51fb1..0000000
--- a/factory_setup/README.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Factory setup scripts
-
-This folder contains scripts for factory flow setup. All scripts here may be
-executed in different environments:
-
- - Inside chroot of cros_sdk
- - Outside chroot but still with complete source tree
- - Inside a factory bundle running on arbitrary Linux device
-
-So all scripts must use only the libraries in same folder and not relying on any
-files in cros source tree (except chromeos-common.sh).
-
-Shopfloor scripts have been moved to ../shopfloor in the factory bundle;
-source code is located in the platform/factory repository.
diff --git a/factory_setup/extract_firmware_updater.sh b/factory_setup/extract_firmware_updater.sh
deleted file mode 100755
index 6d1e086..0000000
--- a/factory_setup/extract_firmware_updater.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2011 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 extract a firmware updater (and firmware blobs) from a signed
-# recovery image.
-
-. "$(dirname "$(readlink -f "$0")")/factory_common.sh" || exit 1
-
-# Flags
-DEFINE_string image "" \
- "Path to release image: /path/chromiumos_image.bin" "i"
-DEFINE_string output_dir "." "Directory to save output file(s)." "o"
-
-# Parse command line
-FLAGS "$@" || exit 1
-ORIGINAL_PARAMS="$@"
-eval set -- "${FLAGS_ARGV}"
-
-on_exit() {
- image_clean_temp
-}
-
-# Param checking and validation
-check_file_param() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- [ -n "$param_value" ] ||
- die "You must assign a file for --$param_name $msg"
- [ -f "$param_value" ] ||
- die "Cannot find file: $param_value"
-}
-
-check_parameters() {
- check_file_param FLAGS_image ""
-}
-
-# Extracts firmware updater from specified disk image file.
-extract_firmware_updater() {
- local image="$(readlink -f "$1")"
- local output_dir="$(readlink -f "$2")"
-
- local fwupdater="$output_dir/chromeos-firmwareupdate"
- local temp_mount="$(mktemp -d --tmpdir)"
- local updater_path="/usr/sbin/chromeos-firmwareupdate"
- local src_file="$temp_mount$updater_path"
- image_add_temp "$temp_mount"
-
- # 'ext2' is required to prevent accidentally modifying image
- image_mount_partition "$image" "3" "$temp_mount" "ro" "-t ext2" ||
- die "Cannot mount partition #3 (rootfs) in release image: $image"
- [ -f "$src_file" ] ||
- die "No firmware updater in release image: $image"
- cp -f "$src_file" "$fwupdater" ||
- die "Failed to copy file from release image $image to $fwupdater."
- image_umount_partition "$temp_mount"
- info "Firmware updater saved in: $fwupdater"
-}
-
-main() {
- set -e
- trap on_exit EXIT
- if [ "$#" != 0 ]; then
- flags_help
- exit 1
- fi
-
- check_parameters
- # Check required tools.
- if ! image_has_part_tools; then
- die "Missing partition tools. Please install cgpt/parted, or run in chroot."
- fi
-
- extract_firmware_updater "$FLAGS_image" "$FLAGS_output_dir"
-}
-
-main "$@"
diff --git a/factory_setup/factory_common.sh b/factory_setup/factory_common.sh
deleted file mode 100644
index 0d9e9c0..0000000
--- a/factory_setup/factory_common.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2011 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.
-
-# Common script utilities loader for factor scripts
-
-SCRIPT="$(readlink -f "$0")"
-SCRIPT_DIR="$(dirname "$SCRIPT")"
-
-# Loads script libraries.
-. "$SCRIPT_DIR/lib/shflags" || exit 1
-. "$SCRIPT_DIR/lib/cros_image_common.sh" || exit 1
-. "$SCRIPT_DIR/lib/chromeos-common.sh" || exit 1
-
-# Finds binary utilities if available.
-image_find_tool "cgpt" "$SCRIPT_DIR/bin"
-image_find_tool "cgpt" "$SCRIPT_DIR/lib"
-
-# Redirects tput to stderr, and drop any error messages.
-tput2() {
- tput "$@" 1>&2 2>/dev/null || true
-}
-
-error() {
- tput2 bold && tput2 setaf 1
- echo "ERROR: $*" >&2
- tput2 sgr0
-}
-
-
-info() {
- tput2 bold && tput2 setaf 2
- echo "INFO: $*" >&2
- tput2 sgr0
-}
-
-warn() {
- tput2 bold && tput2 setaf 3
- echo "WARNING: $*" >&2
- tput2 sgr0
-}
-
-die() {
- [ -z "$*" ] || error "$@"
- exit 1
-}
diff --git a/factory_setup/lib/chromeos-common.sh b/factory_setup/lib/chromeos-common.sh
deleted file mode 120000
index ec9010a..0000000
--- a/factory_setup/lib/chromeos-common.sh
+++ /dev/null
@@ -1 +0,0 @@
-../../../installer/chromeos-common.sh
\ No newline at end of file
diff --git a/factory_setup/lib/cros_image_common.sh b/factory_setup/lib/cros_image_common.sh
deleted file mode 100644
index 06897d9..0000000
--- a/factory_setup/lib/cros_image_common.sh
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2011 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 contains common utility function to deal with disk images,
-# especially for being redistributed into platforms without complete Chromium OS
-# developing environment.
-
-# Checks if given command is available in current system
-image_has_command() {
- type "$1" >/dev/null 2>&1
-}
-
-# Prints error message and exit as 1 (error)
-image_die() {
- echo "ERROR: $@" >&2
- exit 1
-}
-
-# Finds the best gzip compressor and invoke it
-image_gzip_compress() {
- if image_has_command pigz; then
- # echo " ** Using parallel gzip **" >&2
- # Tested with -b 32, 64, 128(default), 256, 1024, 16384, and -b 32 (max
- # window size of Deflate) seems to be the best in output size.
- pigz -b 32 "$@"
- else
- gzip "$@"
- fi
-}
-
-# Finds the best bzip2 compressor and invoke it
-image_bzip2_compress() {
- if image_has_command pbzip2; then
- pbzip2 "$@"
- else
- bzip2 "$@"
- fi
-}
-
-# Finds if current system has tools for part_* commands
-image_has_part_tools() {
- image_has_command cgpt || image_has_command parted
-}
-
-# Finds if specified tool can be found by current path; updates system path if
-# the tool is available in given folder.
-image_find_tool() {
- local tool="$1"
- local alternative_folder="$(readlink -f "$2")"
- if ! image_has_command "$tool" && [ -x "$alternative_folder/$tool" ]; then
- PATH="$alternative_folder:$PATH"; export PATH
- fi
-}
-
-# Finds the best partition tool and print partition offset
-image_part_offset() {
- local file="$1"
- local partno="$2"
- local unpack_file="$(dirname "$file")/unpack_partitions.sh"
-
- # TODO parted is available on most Linux so we may deprecate other code path
- if image_has_command cgpt; then
- cgpt show -b -i "$partno" "$file"
- elif image_has_command parted; then
- # First trial-run to make sure image is valid (because awk always return 0)
- parted -m "$file" unit s print | grep -qs "^$partno:" || exit 1
- parted -m "$file" unit s print | awk -F ':' "/^$partno:/ { print int(\$2) }"
- elif [ -f "$unpack_file" ]; then
- awk "/ $partno *Label:/ { print \$2 }" "$unpack_file"
- else
- exit 1
- fi
-}
-
-# Finds the best partition tool and print partition size
-image_part_size() {
- local file="$1"
- local partno="$2"
- local unpack_file="$(dirname "$file")/unpack_partitions.sh"
-
- # TODO parted is available on most Linux so we may deprecate other code path
- if image_has_command cgpt; then
- cgpt show -s -i "$partno" "$file"
- elif image_has_command parted; then
- # First trial-run to make sure image is valid (because awk always return 0)
- parted -m "$file" unit s print | grep -qs "^$partno:" || exit 1
- parted -m "$file" unit s print | awk -F ':' "/^$partno:/ { print int(\$4) }"
- elif [ -s "$unpack_file" ]; then
- awk "/ $partno *Label:/ { print \$3 }" "$unpack_file"
- else
- exit 1
- fi
-}
-
-# Dumps a file by given offset and size (in sectors)
-image_dump_partial_file() {
- local file="$1"
- local offset="$2"
- local sectors="$3"
- local bs=512
-
- # Increase buffer size as much as possible until 8M
- while [ $((bs < (8 * 1024 * 1024) && sectors > 0 &&
- offset % 2 == 0 && sectors % 2 == 0)) = "1" ]; do
- bs=$((bs * 2))
- offset=$((offset / 2))
- sectors=$((sectors / 2))
- done
-
- if image_has_command pv; then
- dd if="$file" bs=$bs skip="$offset" count="$sectors" \
- oflag=sync status=noxfer 2>/dev/null |
- pv -ptreb -B $bs -s $((sectors * bs))
- else
- dd if="$file" bs=$bs skip="$offset" count="$sectors" \
- oflag=sync status=noxfer 2>/dev/null
- fi
-}
-
-# Dumps a specific partition from given image file
-image_dump_partition() {
- local file="$1"
- local part_num="$2"
- local offset="$(image_part_offset "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
- local size="$(image_part_size "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
-
- image_dump_partial_file "$file" "$offset" "$size"
-}
-
-# Updates a file (from stdin) by given offset and size (in sectors)
-image_update_partial_file() {
- local file="$1"
- local offset="$2"
- local sectors="$3"
- local bs=512
- local oflag="oflag=dsync"
-
- # Improve performance if we're not updating block (Ex, USB) devices
- [ -b "$file" ] || oflag=""
-
- # Increase buffer size as much as possible until 8M
- while [ $((bs < (8 * 1024 * 1024) && sectors > 0 &&
- offset % 2 == 0 && sectors % 2 == 0)) = "1" ]; do
- bs=$((bs * 2))
- offset=$((offset / 2))
- sectors=$((sectors / 2))
- done
-
- if image_has_command pv; then
- pv -ptreb -B $bs -s $((sectors * bs)) |
- dd of="$file" bs=$bs seek="$offset" count="$sectors" \
- iflag=fullblock $oflag conv=notrunc status=noxfer 2>/dev/null
- else
- dd of="$file" bs=$bs seek="$offset" count="$sectors" \
- iflag=fullblock $oflag conv=notrunc status=noxfer 2>/dev/null
- fi
-}
-
-# Updates a specific partition in given image file (from stdin)
-image_update_partition() {
- local file="$1"
- local part_num="$2"
- local offset="$(image_part_offset "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
- local size="$(image_part_size "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
-
- image_update_partial_file "$file" "$offset" "$size"
-}
-
-# Maps a specific partition from given image file to a loop device
-image_map_partition() {
- local file="$1"
- local part_num="$2"
- local offset="$(image_part_offset "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
- local size="$(image_part_size "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
-
- sudo losetup --offset $((offset * 512)) --sizelimit=$((size * 512)) \
- -f --show "$file"
-}
-
-# Unmaps a loop device created by image_map_partition
-image_unmap_partition() {
- local map_point="$1"
-
- sudo losetup -d "$map_point"
-}
-
-# Mounts a specific partition inside a given image file
-image_mount_partition() {
- local file="$1"
- local part_num="$2"
- local mount_point="$3"
- local mount_opt="$4"
- local mount_ext="$5"
- local offset="$(image_part_offset "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
- local size="$(image_part_size "$file" "$part_num")" ||
- image_die "failed to find partition #$part_num from: $file"
-
- if [ -z "$mount_opt" ]; then
- # by default, mount as read-only.
- mount_opt=",ro"
- else
- mount_opt=",$mount_opt"
- fi
-
- sudo mount \
- -o "loop,offset=$((offset * 512)),sizelimit=$((size * 512))$mount_opt" \
- $mount_ext \
- "$file" \
- "$mount_point"
-}
-
-# Unmounts a partition mount point by mount_partition
-image_umount_partition() {
- local mount_point="$1"
-
- sudo umount "$mount_point"
-}
-
-# Copy a partition from one image to another (size must be equal)
-image_partition_copy() {
- local src="$1" src_part="$2" dst="$3" dst_part="$4"
- local size1="$(image_part_size "$src" "$src_part")"
- local size2="$(image_part_size "$dst" "$dst_part")"
- if [ "$size1" != "$size2" ]; then
- die "Partition size different: ($size1 != $size2)"
- fi
- image_dump_partition "$src" "$src_part" 2>/dev/null |
- image_update_partition "$dst" "$dst_part"
-}
-
-# Copy a partition from one image to another (source <= dest)
-image_partition_overwrite() {
- local src="$1" src_part="$2" dst="$3" dst_part="$4"
- local size1="$(image_part_size "$src" "$src_part")"
- local size2="$(image_part_size "$dst" "$dst_part")"
- if [ "$size1" -gt "$size2" ]; then
- die "Destination is too small: ($size1 > $size2)"
- fi
- image_dump_partition "$src" "$src_part" 2>/dev/null |
- image_update_partition "$dst" "$dst_part"
-}
-
-# Copy a partition image from file to a full disk image.
-image_partition_copy_from_file() {
- local src="$1" dst="$2" dst_part="$3"
- local size1="$(($(stat -c"%s" "$src") / 512))"
- local size2="$(image_part_size "$dst" "$dst_part")"
- if [ "$size1" != "$size2" ]; then
- die "Partition size different: ($size1 != $size2)"
- fi
- image_update_partition "$dst" "$dst_part" <"$src"
-}
-
-# Temporary object management
-_IMAGE_TEMP_OBJECTS=""
-
-# Add a temporary object (by mktemp) into list for image_clean_temp to clean
-image_add_temp() {
- _IMAGE_TEMP_OBJECTS="$_IMAGE_TEMP_OBJECTS $*"
-}
-
-# Cleans objects tracked by image_add_temp.
-image_clean_temp() {
- local temp_list="$_IMAGE_TEMP_OBJECTS"
- local object
- _IMAGE_TEMP_OBJECTS=""
-
- for object in $temp_list; do
- if [ -d "$object" ]; then
- sudo umount "$object" >/dev/null 2>&1 || true
- sudo rmdir "$object" >/dev/null 2>&1 || true
- else
- rm -f "$object" >/dev/null 2>&1 || true
- fi
- done
-}
-
-# Determines the boot type of a ChromeOS kernel partition.
-# Prints "recovery", "ssd", "usb", "factory_install", "invalid", or "unknown".
-image_cros_kernel_boot_type() {
- local keyblock="$1"
- local magic flag skip kernel_config
-
- # TODO(hungte) use vbutil_keyblock if available
-
- # Reference: firmware/include/vboot_struct.h
- local KEY_BLOCK_FLAG_DEVELOPER_0=1 # Developer switch off
- local KEY_BLOCK_FLAG_DEVELOPER_1=2 # Developer switch on
- local KEY_BLOCK_FLAG_RECOVERY_0=4 # Not recovery mode
- local KEY_BLOCK_FLAG_RECOVERY_1=8 # Recovery mode
- local KEY_BLOCK_MAGIC="CHROMEOS"
- local KEY_BLOCK_MAGIC_SIZE=8
- local KEY_BLOCK_FLAG_OFFSET=72 # magic:8 major:4 minor:4 size:8 2*(sig:8*3)
-
- magic="$(dd if="$keyblock" bs=$KEY_BLOCK_MAGIC_SIZE count=1 2>/dev/null)"
- if [ "$magic" != "$KEY_BLOCK_MAGIC" ]; then
- echo "invalid"
- return
- fi
- skip="$KEY_BLOCK_FLAG_OFFSET"
- flag="$(dd if="$keyblock" bs=1 count=1 skip="$skip" 2>/dev/null |
- od -t u1 -A n)"
- if [ "$((flag & KEY_BLOCK_FLAG_RECOVERY_0))" != 0 ]; then
- echo "ssd"
- elif [ "$((flag & KEY_BLOCK_FLAG_RECOVERY_1))" != 0 ]; then
- if [ "$((flag & KEY_BLOCK_FLAG_DEVELOPER_0))" = 0 ]; then
- echo "factory_install"
- else
- # Recovery or USB. Check "cros_recovery" in kernel config.
- if image_has_command dump_kernel_config; then
- kernel_config="$(dump_kernel_config "$keyblock")"
- else
- # strings is less secure than dump_kernel_config, so let's try more
- # keywords
- kernel_config="$(strings "$keyblock" |
- grep -w "root=" | grep -w "cros_recovery")"
- fi
- if (echo "$kernel_config" | grep -qw "cros_recovery") &&
- (echo "$kernel_config" | grep -qw "kern_b_hash"); then
- echo "recovery"
- else
- echo "usb"
- fi
- fi
- else
- echo "unknown"
- fi
-}
diff --git a/factory_setup/lib/shflags b/factory_setup/lib/shflags
deleted file mode 100644
index 773e0f3..0000000
--- a/factory_setup/lib/shflags
+++ /dev/null
@@ -1,1009 +0,0 @@
-# $Id: shflags 133 2009-05-10 18:04:51Z kate.ward@forestent.com $
-# vim:et:ft=sh:sts=2:sw=2
-#
-# Copyright 2008 Kate Ward. All Rights Reserved.
-# Released under the LGPL (GNU Lesser General Public License)
-#
-# shFlags -- Advanced command-line flag library for Unix shell scripts.
-# http://code.google.com/p/shflags/
-#
-# Author: kate.ward@forestent.com (Kate Ward)
-#
-# This module implements something like the google-gflags library available
-# from http://code.google.com/p/google-gflags/.
-#
-# FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All flags take
-# a name, default value, help-string, and optional 'short' name (one-letter
-# name). Some flags have other arguments, which are described with the flag.
-#
-# DEFINE_string: takes any input, and intreprets it as a string.
-#
-# DEFINE_boolean: typically does not take any argument: say --myflag to set
-# FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
-# Alternately, you can say
-# --myflag=true or --myflag=t or --myflag=0 or
-# --myflag=false or --myflag=f or --myflag=1
-# Passing an option has the same affect as passing the option once.
-#
-# DEFINE_float: takes an input and intreprets it as a floating point number. As
-# shell does not support floats per-se, the input is merely validated as
-# being a valid floating point value.
-#
-# DEFINE_integer: takes an input and intreprets it as an integer.
-#
-# SPECIAL FLAGS: There are a few flags that have special meaning:
-# --help (or -?) prints a list of all the flags in a human-readable fashion
-# --flagfile=foo read flags from foo. (not implemented yet)
-# -- as in getopt(), terminates flag-processing
-#
-# EXAMPLE USAGE:
-#
-# -- begin hello.sh --
-# #! /bin/sh
-# . ./shflags
-# DEFINE_string name 'world' "somebody's name" n
-# FLAGS "$@" || exit $?
-# eval set -- "${FLAGS_ARGV}"
-# echo "Hello, ${FLAGS_name}."
-# -- end hello.sh --
-#
-# $ ./hello.sh -n Kate
-# Hello, Kate.
-#
-# NOTE: Not all systems include a getopt version that supports long flags. On
-# these systems, only short flags are recognized.
-
-#==============================================================================
-# shFlags
-#
-# Shared attributes:
-# flags_error: last error message
-# flags_return: last return value
-#
-# __flags_longNames: list of long names for all flags
-# __flags_shortNames: list of short names for all flags
-# __flags_boolNames: list of boolean flag names
-#
-# __flags_opts: options parsed by getopt
-#
-# Per-flag attributes:
-# FLAGS_<flag_name>: contains value of flag named 'flag_name'
-# __flags_<flag_name>_default: the default flag value
-# __flags_<flag_name>_help: the flag help string
-# __flags_<flag_name>_short: the flag short name
-# __flags_<flag_name>_type: the flag type
-#
-# Notes:
-# - lists of strings are space separated, and a null value is the '~' char.
-
-# return if FLAGS already loaded
-[ -n "${FLAGS_VERSION:-}" ] && return 0
-FLAGS_VERSION='1.0.3'
-
-# return values
-FLAGS_TRUE=0
-FLAGS_FALSE=1
-FLAGS_ERROR=2
-
-# reserved flag names
-FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
-
-_flags_debug() { echo "flags:DEBUG $@" >&2; }
-_flags_warn() { echo "flags:WARN $@" >&2; }
-_flags_error() { echo "flags:ERROR $@" >&2; }
-_flags_fatal() { echo "flags:FATAL $@" >&2; }
-
-# specific shell checks
-if [ -n "${ZSH_VERSION:-}" ]; then
- setopt |grep "^shwordsplit$" >/dev/null
- if [ $? -ne ${FLAGS_TRUE} ]; then
- _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
- exit ${FLAGS_ERROR}
- fi
- if [ -z "${FLAGS_PARENT:-}" ]; then
- _flags_fatal "zsh does not pass \$0 through properly. please declare' \
-\"FLAGS_PARENT=\$0\" before calling shFlags"
- exit ${FLAGS_ERROR}
- fi
-fi
-
-#
-# constants
-#
-
-# getopt version
-__FLAGS_GETOPT_VERS_STD=0
-__FLAGS_GETOPT_VERS_ENH=1
-__FLAGS_GETOPT_VERS_BSD=2
-
-getopt >/dev/null 2>&1
-case $? in
- 0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;; # bsd getopt
- 2)
- # TODO(kward): look into '-T' option to test the internal getopt() version
- if [ "`getopt --version`" = '-- ' ]; then
- __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
- else
- __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
- fi
- ;;
- *)
- _flags_fatal 'unable to determine getopt version'
- exit ${FLAGS_ERROR}
- ;;
-esac
-
-# getopt optstring lengths
-__FLAGS_OPTSTR_SHORT=0
-__FLAGS_OPTSTR_LONG=1
-
-__FLAGS_NULL='~'
-
-# flag info strings
-__FLAGS_INFO_DEFAULT='default'
-__FLAGS_INFO_HELP='help'
-__FLAGS_INFO_SHORT='short'
-__FLAGS_INFO_TYPE='type'
-
-# flag lengths
-__FLAGS_LEN_SHORT=0
-__FLAGS_LEN_LONG=1
-
-# flag types
-__FLAGS_TYPE_NONE=0
-__FLAGS_TYPE_BOOLEAN=1
-__FLAGS_TYPE_FLOAT=2
-__FLAGS_TYPE_INTEGER=3
-__FLAGS_TYPE_STRING=4
-
-# set the constants readonly
-__flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
-for __flags_const in ${__flags_constants}; do
- # skip certain flags
- case ${__flags_const} in
- FLAGS_HELP) continue ;;
- FLAGS_PARENT) continue ;;
- esac
- # set flag readonly
- if [ -z "${ZSH_VERSION:-}" ]; then
- readonly ${__flags_const}
- else # handle zsh
- case ${ZSH_VERSION} in
- [123].*) readonly ${__flags_const} ;;
- *) readonly -g ${__flags_const} ;; # declare readonly constants globally
- esac
- fi
-done
-unset __flags_const __flags_constants
-
-#
-# internal variables
-#
-
-__flags_boolNames=' ' # space separated list of boolean flag names
-__flags_longNames=' ' # space separated list of long flag names
-__flags_shortNames=' ' # space separated list of short flag names
-
-__flags_columns='' # screen width in columns
-__flags_opts='' # temporary storage for parsed getopt flags
-
-#------------------------------------------------------------------------------
-# private functions
-#
-
-# Define a flag.
-#
-# Calling this function will define the following info variables for the
-# specified flag:
-# FLAGS_flagname - the name for this flag (based upon the long flag name)
-# __flags_<flag_name>_default - the default value
-# __flags_flagname_help - the help string
-# __flags_flagname_short - the single letter alias
-# __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
-#
-# Args:
-# _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
-# _flags__name: string: long flag name
-# _flags__default: default flag value
-# _flags__help: string: help string
-# _flags__short: string: (optional) short flag name
-# Returns:
-# integer: success of operation, or error
-_flags_define()
-{
- if [ $# -lt 4 ]; then
- flags_error='DEFINE error: too few arguments'
- flags_return=${FLAGS_ERROR}
- _flags_error "${flags_error}"
- return ${flags_return}
- fi
-
- _flags_type_=$1
- _flags_name_=$2
- _flags_default_=$3
- _flags_help_=$4
- _flags_short_=${5:-${__FLAGS_NULL}}
-
- _flags_return_=${FLAGS_TRUE}
-
- # TODO(kward): check for validity of the flag name (e.g. dashes)
-
- # check whether the flag name is reserved
- echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
- if [ $? -eq 0 ]; then
- flags_error="flag name (${_flags_name_}) is reserved"
- _flags_return_=${FLAGS_ERROR}
- fi
-
- # require short option for getopt that don't support long options
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
- -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
- -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
- then
- flags_error="short flag required for (${_flags_name_}) on this platform"
- _flags_return_=${FLAGS_ERROR}
- fi
-
- # check for existing long name definition
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
- if _flags_itemInList "${_flags_name_}" \
- ${__flags_longNames} ${__flags_boolNames}
- then
- flags_error="flag name ([no]${_flags_name_}) already defined"
- _flags_warn "${flags_error}"
- _flags_return_=${FLAGS_FALSE}
- fi
- fi
-
- # check for existing short name definition
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
- -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
- then
- if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
- flags_error="flag short name (${_flags_short_}) already defined"
- _flags_warn "${flags_error}"
- _flags_return_=${FLAGS_FALSE}
- fi
- fi
-
- # handle default value. note, on several occasions the 'if' portion of an
- # if/then/else contains just a ':' which does nothing. a binary reversal via
- # '!' is not done because it does not work on all shells.
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
- case ${_flags_type_} in
- ${__FLAGS_TYPE_BOOLEAN})
- if _flags_validateBoolean "${_flags_default_}"; then
- case ${_flags_default_} in
- true|t|0) _flags_default_=${FLAGS_TRUE} ;;
- false|f|1) _flags_default_=${FLAGS_FALSE} ;;
- esac
- else
- flags_error="invalid default flag value '${_flags_default_}'"
- _flags_return_=${FLAGS_ERROR}
- fi
- ;;
-
- ${__FLAGS_TYPE_FLOAT})
- if _flags_validateFloat "${_flags_default_}"; then
- :
- else
- flags_error="invalid default flag value '${_flags_default_}'"
- _flags_return_=${FLAGS_ERROR}
- fi
- ;;
-
- ${__FLAGS_TYPE_INTEGER})
- if _flags_validateInteger "${_flags_default_}"; then
- :
- else
- flags_error="invalid default flag value '${_flags_default_}'"
- _flags_return_=${FLAGS_ERROR}
- fi
- ;;
-
- ${__FLAGS_TYPE_STRING}) ;; # everything in shell is a valid string
-
- *)
- flags_error="unrecognized flag type '${_flags_type_}'"
- _flags_return_=${FLAGS_ERROR}
- ;;
- esac
- fi
-
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
- # store flag information
- eval "FLAGS_${_flags_name_}='${_flags_default_}'"
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
-\"${_flags_default_}\""
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
-
- # append flag name(s) to list of names
- __flags_longNames="${__flags_longNames}${_flags_name_} "
- __flags_shortNames="${__flags_shortNames}${_flags_short_} "
- [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
- __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
- fi
-
- flags_return=${_flags_return_}
- unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
- _flags_type_
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
- return ${flags_return}
-}
-
-# Return valid getopt options using currently defined list of long options.
-#
-# This function builds a proper getopt option string for short (and long)
-# options, using the current list of long options for reference.
-#
-# Args:
-# _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
-# Output:
-# string: generated option string for getopt
-# Returns:
-# boolean: success of operation (always returns True)
-_flags_genOptStr()
-{
- _flags_optStrType_=$1
-
- _flags_opts_=''
-
- for _flags_flag_ in ${__flags_longNames}; do
- _flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
- case ${_flags_optStrType_} in
- ${__FLAGS_OPTSTR_SHORT})
- _flags_shortName_=`_flags_getFlagInfo \
- ${_flags_flag_} ${__FLAGS_INFO_SHORT}`
- if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
- _flags_opts_="${_flags_opts_}${_flags_shortName_}"
- # getopt needs a trailing ':' to indicate a required argument
- [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
- _flags_opts_="${_flags_opts_}:"
- fi
- ;;
-
- ${__FLAGS_OPTSTR_LONG})
- _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
- # getopt needs a trailing ':' to indicate a required argument
- [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
- _flags_opts_="${_flags_opts_}:"
- ;;
- esac
- done
-
- echo "${_flags_opts_}"
- unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
- _flags_type_
- return ${FLAGS_TRUE}
-}
-
-# Returns flag details based on a flag name and flag info.
-#
-# Args:
-# string: long flag name
-# string: flag info (see the _flags_define function for valid info types)
-# Output:
-# string: value of dereferenced flag variable
-# Returns:
-# integer: one of FLAGS_{TRUE|FALSE|ERROR}
-_flags_getFlagInfo()
-{
- _flags_name_=$1
- _flags_info_=$2
-
- _flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
- _flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
- eval "${_flags_strToEval_}"
- if [ -n "${_flags_value_}" ]; then
- flags_return=${FLAGS_TRUE}
- else
- # see if the _flags_name_ variable is a string as strings can be empty...
- # note: the DRY principle would say to have this function call itself for
- # the next three lines, but doing so results in an infinite loop as an
- # invalid _flags_name_ will also not have the associated _type variable.
- # Because it doesn't (it will evaluate to an empty string) the logic will
- # try to find the _type variable of the _type variable, and so on. Not so
- # good ;-)
- _flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
- _flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
- eval "${_flags_strToEval_}"
- if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
- flags_return=${FLAGS_TRUE}
- else
- flags_return=${FLAGS_ERROR}
- flags_error="invalid flag name (${_flags_nameVar_})"
- fi
- fi
-
- echo "${_flags_value_}"
- unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
- _flags_nameVar_ _flags_typeVar_
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
- return ${flags_return}
-}
-
-# check for presense of item in a list. passed a string (e.g. 'abc'), this
-# function will determine if the string is present in the list of strings (e.g.
-# ' foo bar abc ').
-#
-# Args:
-# _flags__str: string: string to search for in a list of strings
-# unnamed: list: list of strings
-# Returns:
-# boolean: true if item is in the list
-_flags_itemInList()
-{
- _flags_str_=$1
- shift
-
- echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
- if [ $? -eq 0 ]; then
- flags_return=${FLAGS_TRUE}
- else
- flags_return=${FLAGS_FALSE}
- fi
-
- unset _flags_str_
- return ${flags_return}
-}
-
-# Returns the width of the current screen.
-#
-# Output:
-# integer: width in columns of the current screen.
-_flags_columns()
-{
- if [ -z "${__flags_columns}" ]; then
- # determine the value and store it
- if eval stty size >/dev/null 2>&1; then
- # stty size worked :-)
- set -- `stty size`
- __flags_columns=$2
- elif eval tput cols >/dev/null 2>&1; then
- set -- `tput cols`
- __flags_columns=$1
- else
- __flags_columns=80 # default terminal width
- fi
- fi
- echo ${__flags_columns}
-}
-
-# Validate a boolean.
-#
-# Args:
-# _flags__bool: boolean: value to validate
-# Returns:
-# bool: true if the value is a valid boolean
-_flags_validateBoolean()
-{
- _flags_bool_=$1
-
- flags_return=${FLAGS_TRUE}
- case "${_flags_bool_}" in
- true|t|0) ;;
- false|f|1) ;;
- *) flags_return=${FLAGS_FALSE} ;;
- esac
-
- unset _flags_bool_
- return ${flags_return}
-}
-
-# Validate a float.
-#
-# Args:
-# _flags__float: float: value to validate
-# Returns:
-# bool: true if the value is a valid float
-_flags_validateFloat()
-{
- _flags_float_=$1
-
- if _flags_validateInteger ${_flags_float_}; then
- flags_return=${FLAGS_TRUE}
- else
- flags_return=${FLAGS_TRUE}
- case ${_flags_float_} in
- -*) # negative floats
- _flags_test_=`expr "${_flags_float_}" : '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
- ;;
- *) # positive floats
- _flags_test_=`expr "${_flags_float_}" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
- ;;
- esac
- [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
- fi
-
- unset _flags_float_ _flags_test_
- return ${flags_return}
-}
-
-# Validate an integer.
-#
-# Args:
-# _flags__integer: interger: value to validate
-# Returns:
-# bool: true if the value is a valid integer
-_flags_validateInteger()
-{
- _flags_int_=$1
-
- flags_return=${FLAGS_TRUE}
- case ${_flags_int_} in
- -*) # negative ints
- _flags_test_=`expr "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
- ;;
- *) # positive ints
- _flags_test_=`expr "${_flags_int_}" : '\([0-9][0-9]*\)'`
- ;;
- esac
- [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
-
- unset _flags_int_ _flags_test_
- return ${flags_return}
-}
-
-# Parse command-line options using the standard getopt.
-#
-# Note: the flag options are passed around in the global __flags_opts so that
-# the formatting is not lost due to shell parsing and such.
-#
-# Args:
-# @: varies: command-line options to parse
-# Returns:
-# integer: a FLAGS success condition
-_flags_getoptStandard()
-{
- flags_return=${FLAGS_TRUE}
- _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
-
- # check for spaces in passed options
- for _flags_opt_ in "$@"; do
- # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
- _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
- if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
- flags_error='the available getopt does not support spaces in options'
- flags_return=${FLAGS_ERROR}
- break
- fi
- done
-
- if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
- __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
- _flags_rtrn_=$?
- if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
- _flags_warn "${__flags_opts}"
- flags_error='unable to parse provided options with getopt.'
- flags_return=${FLAGS_ERROR}
- fi
- fi
-
- unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
- return ${flags_return}
-}
-
-# Parse command-line options using the enhanced getopt.
-#
-# Note: the flag options are passed around in the global __flags_opts so that
-# the formatting is not lost due to shell parsing and such.
-#
-# Args:
-# @: varies: command-line options to parse
-# Returns:
-# integer: a FLAGS success condition
-_flags_getoptEnhanced()
-{
- flags_return=${FLAGS_TRUE}
- _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
- _flags_boolOpts_=`echo "${__flags_boolNames}" \
- |sed 's/^ *//;s/ *$//;s/ /,/g'`
- _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
-
- __flags_opts=`getopt \
- -o ${_flags_shortOpts_} \
- -l "${_flags_longOpts_},${_flags_boolOpts_}" \
- -- "$@" 2>&1`
- _flags_rtrn_=$?
- if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
- _flags_warn "${__flags_opts}"
- flags_error='unable to parse provided options with getopt.'
- flags_return=${FLAGS_ERROR}
- fi
-
- unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
- return ${flags_return}
-}
-
-# Dynamically parse a getopt result and set appropriate variables.
-#
-# This function does the actual conversion of getopt output and runs it through
-# the standard case structure for parsing. The case structure is actually quite
-# dynamic to support any number of flags.
-#
-# Args:
-# argc: int: original command-line argument count
-# @: varies: output from getopt parsing
-# Returns:
-# integer: a FLAGS success condition
-_flags_parseGetopt()
-{
- _flags_argc_=$1
- shift
-
- flags_return=${FLAGS_TRUE}
-
- if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
- set -- $@
- else
- # note the quotes around the `$@' -- they are essential!
- eval set -- "$@"
- fi
-
- # provide user with number of arguments to shift by later
- # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
- # properly give user access to non-flag arguments mixed in between flag
- # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
- # for backwards compatibility reasons.
- FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
-
- # handle options. note options with values must do an additional shift
- while true; do
- _flags_opt_=$1
- _flags_arg_=${2:-}
- _flags_type_=${__FLAGS_TYPE_NONE}
- _flags_name_=''
-
- # determine long flag name
- case "${_flags_opt_}" in
- --) shift; break ;; # discontinue option parsing
-
- --*) # long option
- _flags_opt_=`expr "${_flags_opt_}" : '--\(.*\)'`
- _flags_len_=${__FLAGS_LEN_LONG}
- if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
- _flags_name_=${_flags_opt_}
- else
- # check for negated long boolean version
- if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
- _flags_name_=`expr "${_flags_opt_}" : 'no\(.*\)'`
- _flags_type_=${__FLAGS_TYPE_BOOLEAN}
- _flags_arg_=${__FLAGS_NULL}
- fi
- fi
- ;;
-
- -*) # short option
- _flags_opt_=`expr "${_flags_opt_}" : '-\(.*\)'`
- _flags_len_=${__FLAGS_LEN_SHORT}
- if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
- # yes. match short name to long name. note purposeful off-by-one
- # (too high) with awk calculations.
- _flags_pos_=`echo "${__flags_shortNames}" \
- |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
- e=${_flags_opt_}`
- _flags_name_=`echo "${__flags_longNames}" \
- |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
- fi
- ;;
- esac
-
- # die if the flag was unrecognized
- if [ -z "${_flags_name_}" ]; then
- flags_error="unrecognized option (${_flags_opt_})"
- flags_return=${FLAGS_ERROR}
- break
- fi
-
- # set new flag value
- [ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
- _flags_type_=`_flags_getFlagInfo \
- "${_flags_name_}" ${__FLAGS_INFO_TYPE}`
- case ${_flags_type_} in
- ${__FLAGS_TYPE_BOOLEAN})
- if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
- if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
- eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
- else
- eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
- fi
- else
- _flags_strToEval_="_flags_val_=\
-\${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
- eval "${_flags_strToEval_}"
- if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
- eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
- else
- eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
- fi
- fi
- ;;
-
- ${__FLAGS_TYPE_FLOAT})
- if _flags_validateFloat "${_flags_arg_}"; then
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
- else
- flags_error="invalid float value (${_flags_arg_})"
- flags_return=${FLAGS_ERROR}
- break
- fi
- ;;
-
- ${__FLAGS_TYPE_INTEGER})
- if _flags_validateInteger "${_flags_arg_}"; then
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
- else
- flags_error="invalid integer value (${_flags_arg_})"
- flags_return=${FLAGS_ERROR}
- break
- fi
- ;;
-
- ${__FLAGS_TYPE_STRING})
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
- ;;
- esac
-
- # handle special case help flag
- if [ "${_flags_name_}" = 'help' ]; then
- if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
- flags_help
- flags_error='help requested'
- flags_return=${FLAGS_FALSE}
- break
- fi
- fi
-
- # shift the option and non-boolean arguements out.
- shift
- [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} ] && shift
- done
-
- # give user back non-flag arguments
- FLAGS_ARGV=''
- while [ $# -gt 0 ]; do
- FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
- shift
- done
-
- unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
- _flags_strToEval_ _flags_type_ _flags_val_
- return ${flags_return}
-}
-
-#------------------------------------------------------------------------------
-# public functions
-#
-
-# A basic boolean flag. Boolean flags do not take any arguments, and their
-# value is either 1 (false) or 0 (true). For long flags, the false value is
-# specified on the command line by prepending the word 'no'. With short flags,
-# the presense of the flag toggles the current value between true and false.
-# Specifying a short boolean flag twice on the command results in returning the
-# value back to the default value.
-#
-# A default value is required for boolean flags.
-#
-# For example, lets say a Boolean flag was created whose long name was 'update'
-# and whose short name was 'x', and the default value was 'false'. This flag
-# could be explicitly set to 'true' with '--update' or by '-x', and it could be
-# explicitly set to 'false' with '--noupdate'.
-DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
-
-# Other basic flags.
-DEFINE_float() { _flags_define ${__FLAGS_TYPE_FLOAT} "$@"; }
-DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
-DEFINE_string() { _flags_define ${__FLAGS_TYPE_STRING} "$@"; }
-
-# Parse the flags.
-#
-# Args:
-# unnamed: list: command-line flags to parse
-# Returns:
-# integer: success of operation, or error
-FLAGS()
-{
- # define a standard 'help' flag if one isn't already defined
- [ -z "${__flags_help_type:-}" ] && \
- DEFINE_boolean 'help' false 'show this help' 'h'
-
- # parse options
- if [ $# -gt 0 ]; then
- if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
- _flags_getoptStandard "$@"
- else
- _flags_getoptEnhanced "$@"
- fi
- flags_return=$?
- else
- # nothing passed; won't bother running getopt
- __flags_opts='--'
- flags_return=${FLAGS_TRUE}
- fi
-
- if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
- _flags_parseGetopt $# "${__flags_opts}"
- flags_return=$?
- fi
-
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
- return ${flags_return}
-}
-
-# This is a helper function for determining the `getopt` version for platforms
-# where the detection isn't working. It simply outputs debug information that
-# can be included in a bug report.
-#
-# Args:
-# none
-# Output:
-# debug info that can be included in a bug report
-# Returns:
-# nothing
-flags_getoptInfo()
-{
- # platform info
- _flags_debug "uname -a: `uname -a`"
- _flags_debug "PATH: ${PATH}"
-
- # shell info
- if [ -n "${BASH_VERSION:-}" ]; then
- _flags_debug 'shell: bash'
- _flags_debug "BASH_VERSION: ${BASH_VERSION}"
- elif [ -n "${ZSH_VERSION:-}" ]; then
- _flags_debug 'shell: zsh'
- _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
- fi
-
- # getopt info
- getopt >/dev/null
- _flags_getoptReturn=$?
- _flags_debug "getopt return: ${_flags_getoptReturn}"
- _flags_debug "getopt --version: `getopt --version 2>&1`"
-
- unset _flags_getoptReturn
-}
-
-# Returns whether the detected getopt version is the enhanced version.
-#
-# Args:
-# none
-# Output:
-# none
-# Returns:
-# bool: true if getopt is the enhanced version
-flags_getoptIsEnh()
-{
- test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
-}
-
-# Returns whether the detected getopt version is the standard version.
-#
-# Args:
-# none
-# Returns:
-# bool: true if getopt is the standard version
-flags_getoptIsStd()
-{
- test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
-}
-
-# This is effectively a 'usage()' function. It prints usage information and
-# exits the program with ${FLAGS_FALSE} if it is ever found in the command line
-# arguments. Note this function can be overridden so other apps can define
-# their own --help flag, replacing this one, if they want.
-#
-# Args:
-# none
-# Returns:
-# integer: success of operation (always returns true)
-flags_help()
-{
- if [ -n "${FLAGS_HELP:-}" ]; then
- echo "${FLAGS_HELP}" >&2
- else
- echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
- fi
- if [ -n "${__flags_longNames}" ]; then
- echo 'flags:' >&2
- for flags_name_ in ${__flags_longNames}; do
- flags_flagStr_=''
- flags_boolStr_=''
-
- flags_default_=`_flags_getFlagInfo \
- "${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
- flags_help_=`_flags_getFlagInfo \
- "${flags_name_}" ${__FLAGS_INFO_HELP}`
- flags_short_=`_flags_getFlagInfo \
- "${flags_name_}" ${__FLAGS_INFO_SHORT}`
- flags_type_=`_flags_getFlagInfo \
- "${flags_name_}" ${__FLAGS_INFO_TYPE}`
-
- [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
- && flags_flagStr_="-${flags_short_}"
-
- if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
- [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
- && flags_flagStr_="${flags_flagStr_},"
- [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
- && flags_boolStr_='[no]'
- flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
- fi
-
- case ${flags_type_} in
- ${__FLAGS_TYPE_BOOLEAN})
- if [ ${flags_default_} -eq ${FLAGS_TRUE} ]; then
- flags_defaultStr_='true'
- else
- flags_defaultStr_='false'
- fi
- ;;
- ${__FLAGS_TYPE_FLOAT}|${__FLAGS_TYPE_INTEGER})
- flags_defaultStr_=${flags_default_} ;;
- ${__FLAGS_TYPE_STRING}) flags_defaultStr_="'${flags_default_}'" ;;
- esac
- flags_defaultStr_="(default: ${flags_defaultStr_})"
-
- flags_helpStr_=" ${flags_flagStr_} ${flags_help_} ${flags_defaultStr_}"
- flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
- flags_columns_=`_flags_columns`
- if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
- echo "${flags_helpStr_}" >&2
- else
- echo " ${flags_flagStr_} ${flags_help_}" >&2
- # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
- # because it doesn't like empty strings when used in this manner.
- flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
- |awk '{printf "%"length($0)-2"s", ""}'`"
- flags_helpStr_=" ${flags_emptyStr_} ${flags_defaultStr_}"
- flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
- if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
- -o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
- # indented to match help string
- echo "${flags_helpStr_}" >&2
- else
- # indented four from left to allow for longer defaults as long flag
- # names might be used too, making things too long
- echo " ${flags_defaultStr_}" >&2
- fi
- fi
- done
- fi
-
- unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
- flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
- flags_columns_ flags_short_ flags_type_
- return ${FLAGS_TRUE}
-}
-
-# Reset shflags back to an uninitialized state.
-#
-# Args:
-# none
-# Returns:
-# nothing
-flags_reset()
-{
- for flags_name_ in ${__flags_longNames}; do
- flags_strToEval_="unset FLAGS_${flags_name_}"
- for flags_type_ in \
- ${__FLAGS_INFO_DEFAULT} \
- ${__FLAGS_INFO_HELP} \
- ${__FLAGS_INFO_SHORT} \
- ${__FLAGS_INFO_TYPE}
- do
- flags_strToEval_=\
-"${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
- done
- eval ${flags_strToEval_}
- done
-
- # reset internal variables
- __flags_boolNames=' '
- __flags_longNames=' '
- __flags_shortNames=' '
-
- unset flags_name_ flags_type_ flags_strToEval_
-}
diff --git a/factory_setup/make_factory_package.sh b/factory_setup/make_factory_package.sh
deleted file mode 100755
index dbfae7c..0000000
--- a/factory_setup/make_factory_package.sh
+++ /dev/null
@@ -1,828 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2011 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 generate a factory install partition set and miniomaha.conf
-# file from a release image and a factory image. This creates a server
-# configuration that can be installed using a factory install shim.
-#
-# miniomaha lives in "." and miniomaha partition sets live in "./static".
-#
-# All internal environment variables used by this script are prefixed with
-# "MFP_". Please avoid using them for other purposes.
-# "MFP_CONFIG_"* are shell variables that can be used in config file (--config)
-
-. "$(dirname "$(readlink -f "$0")")/factory_common.sh" || exit 1
-
-# Detects environment in in cros source tree, chroot, or extracted bundle.
-setup_cros_sdk_environment() {
- local crosutils_path="$SCRIPT_DIR/../../../scripts"
- if [ -f "$crosutils_path/.default_board" ]; then
- DEFAULT_BOARD="$(cat "$crosutils_path/.default_board")"
- fi
-
- # Detect whether we're inside a chroot or not
- INSIDE_CHROOT=0
- [ -e /etc/debian_chroot ] && INSIDE_CHROOT=1
-}
-
-setup_cros_sdk_environment
-FLAGS_NONE='none'
-
-# Flags
-DEFINE_string board "${DEFAULT_BOARD}" "Board for which the image was built"
-DEFINE_string factory "" \
- "Directory and file containing factory image: /path/chromiumos_test_image.bin"
-DEFINE_string firmware_updater "" \
- "Firmware updater (shellball) into the server configuration,"\
-" or leave empty (default) for the updater in release image (--release), "\
-" or '$FLAGS_NONE' to prevent running firmware updater."
-DEFINE_string hwid_updater "" \
- "The component list updater for HWID validation,"\
-" or '$FLAGS_NONE' to prevent updating the component list files."
-DEFINE_string complete_script "" \
- "If set, include the script for the last-step execution of factory install"
-DEFINE_string release "" \
- "Directory and file containing release image: /path/chromiumos_image.bin"
-DEFINE_string subfolder "" \
- "If set, the name of the subfolder to put the payload items inside"
-DEFINE_string usbimg "" \
- "If set, the name of the USB installation disk image file to output"
-DEFINE_string install_shim "" \
- "Directory and file containing factory install shim for --usbimg"
-DEFINE_string diskimg "" \
- "If set, the name of the diskimage file to output"
-DEFINE_boolean preserve ${FLAGS_FALSE} \
- "If set, reuse the diskimage file, if available"
-DEFINE_integer sectors 31277232 "Size of image in sectors"
-DEFINE_boolean detect_release_image ${FLAGS_TRUE} \
- "If set, try to auto-detect the type of release image and convert if required"
-DEFINE_string config "" \
- 'Configuration file where parameters are read from. You can use '\
-'\$MFP_CONFIG_PATH and \$MFP_CONFIG_DIR (path and directory to the '\
-'config file itself) in config file to use relative path'
-DEFINE_boolean run_omaha ${FLAGS_FALSE} \
- "Run mini-omaha server after factory package setup completed."
-
-# Usage Help
-FLAGS_HELP="Prepares factory resources (mini-omaha server, RMA/usb/disk images)
-
-USAGE: $0 [flags] args
-Note environment variables with prefix MFP_ are for reserved for internal use.
-"
-
-# Internal variables
-ENABLE_FIRMWARE_UPDATER=$FLAGS_TRUE
-
-# Parse command line
-FLAGS "$@" || exit 1
-ORIGINAL_PARAMS="$@"
-eval set -- "${FLAGS_ARGV}"
-
-on_exit() {
- image_clean_temp
-}
-
-# Param checking and validation
-check_file_param() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- [ -n "$param_value" ] ||
- die "You must assign a file for --$param_name $msg"
- [ -f "$param_value" ] ||
- die "Cannot find file: $param_value"
-}
-
-check_file_param_or_none() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- if [ "$param_value" = "$FLAGS_NONE" ]; then
- eval "$param=''"
- return
- fi
- [ -n "$param_value" ] ||
- die "You must assign either a file or 'none' for --$param_name $msg"
- [ -f "$param_value" ] ||
- die "Cannot find file: $param_value"
-}
-
-check_optional_file_param() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- if [ -n "$param_value" ] && [ ! -f "$param_value" ]; then
- die "Cannot find file: $param_value"
- fi
-}
-
-check_empty_param() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- [ -z "$param_value" ] || die "Parameter --$param_name is not supported $msg"
-}
-
-check_false_param() {
- local param="$1"
- local msg="$2"
- local param_name="${param#FLAGS_}"
- local param_value="$(eval echo \$$1)"
-
- [ "$param_value" = $FLAGS_FALSE ] ||
- die "Parameter --$param_name is not supported $msg"
-}
-
-check_parameters() {
- check_file_param FLAGS_release ""
- check_file_param FLAGS_factory ""
-
- # Pre-parse parameter default values
- case "${FLAGS_firmware_updater}" in
- $FLAGS_NONE )
- ENABLE_FIRMWARE_UPDATER=$FLAGS_FALSE
- ;;
- "" )
- # Empty value means "enable updater from rootfs" for all modes except
- # --diskimg mode.
- if [ -n "${FLAGS_diskimg}" ]; then
- ENABLE_FIRMWARE_UPDATER=$FLAGS_FALSE
- else
- FLAGS_firmware_updater=$FLAGS_NONE
- fi
- ;;
- esac
-
- # All remaining parameters must be checked:
- # install_shim, firmware, hwid_updater, complete_script.
-
- if [ -n "${FLAGS_usbimg}" ]; then
- [ -z "${FLAGS_diskimg}" ] ||
- die "--usbimg and --diskimg cannot be used at the same time."
- check_file_param_or_none FLAGS_firmware_updater "in --usbimg mode"
- check_file_param_or_none FLAGS_hwid_updater "in --usbimg mode"
- check_empty_param FLAGS_complete_script "in --usbimg mode"
- check_file_param FLAGS_install_shim "in --usbimg mode"
- check_false_param FLAGS_run_omaha "in --usbimg mode"
- elif [ -n "${FLAGS_diskimg}" ]; then
- check_empty_param FLAGS_firmware_updater "in --diskimg mode"
- check_file_param_or_none FLAGS_hwid_updater "in --diskimg mode"
- check_empty_param FLAGS_complete_script "in --diskimg mode"
- check_empty_param FLAGS_install_shim "in --diskimg mode"
- check_false_param FLAGS_run_omaha "in --diskimg mode"
- if [ -b "${FLAGS_diskimg}" -a ! -w "${FLAGS_diskimg}" ] &&
- [ -z "$MFP_SUDO" -a "$(id -u)" != "0" ]; then
- # Restart the command with original parameters with sudo for writing to
- # block device that needs root permission.
- # MFP_SUDO is a internal flag to prevent unexpected recursion.
- MFP_SUDO=TRUE exec sudo "$0" $ORIGINAL_PARAMS
- fi
- else
- check_file_param_or_none FLAGS_firmware_updater "in mini-omaha mode"
- check_file_param_or_none FLAGS_hwid_updater "in mini-omaha mode"
- check_optional_file_param FLAGS_complete_script "in mini-omaha mode"
- check_empty_param FLAGS_install_shim "in mini-omaha mode"
- fi
-}
-
-find_omaha() {
- OMAHA_DIR="$(readlink -f "${SCRIPT_DIR}")"
- OMAHA_PROGRAM="${OMAHA_DIR}/miniomaha.py"
- OMAHA_CONF="${OMAHA_DIR}/miniomaha.conf"
-
- [ -f "${OMAHA_PROGRAM}" ] ||
- die "Cannot find mini-omaha server program: $OMAHA_PROGRAM"
-}
-
-setup_environment() {
- # Convert args to paths. Need eval to un-quote the string so that shell
- # chars like ~ are processed; just doing FOO=`readlink -f ${FOO}` won't work.
-
- find_omaha
- OMAHA_DATA_DIR="${OMAHA_DIR}/static/"
-
- # Note: The subfolder flag can only append configs. That means you will need
- # to have unique board IDs for every time you run. If you delete
- # miniomaha.conf you can still use this flag and it will start fresh.
- if [ -n "${FLAGS_subfolder}" ]; then
- OMAHA_DATA_DIR="${OMAHA_DATA_DIR}${FLAGS_subfolder}/"
- fi
-
- # When "sudo -v" is executed inside chroot, it prompts for password; however
- # the user account inside chroot may be using a different password (ex,
- # "chronos") from the same account outside chroot. The /etc/sudoers file
- # inside chroot has explicitly specified "userid ALL=NOPASSWD: ALL" for the
- # account, so we should do nothing inside chroot.
- if [ ${INSIDE_CHROOT} -eq 0 ]; then
- echo "Caching sudo authentication"
- sudo -v
- echo "Done"
- fi
-
- # Use this image as the source image to copy
- RELEASE_DIR="$(dirname "${FLAGS_release}")"
- FACTORY_DIR="$(dirname "${FLAGS_factory}")"
- RELEASE_IMAGE="$(basename "${FLAGS_release}")"
- FACTORY_IMAGE="$(basename "${FLAGS_factory}")"
-
- # Override this with path to modified kernel (for non-SSD images)
- RELEASE_KERNEL=""
-
- # Check required tools.
- if ! image_has_part_tools; then
- die "Missing partition tools. Please install cgpt/parted, or run in chroot."
- fi
-}
-
-# Prepares release image source by checking image type, and creates modified
-# partition blob in RELEASE_KERNEL if required.
-prepare_release_image() {
- local image="$(readlink -f "$1")"
- local kernel="$(mktemp --tmpdir)"
- image_add_temp "$kernel"
-
- # Image Types:
- # - recovery: kernel in #4 and vmlinuz_hd.vblock in #1
- # - usb: kernel in #2 and vmlinuz_hd.vblock in #1
- # - ssd: kernel in #2, no need to change
- image_dump_partition "$image" "2" >"$kernel" 2>/dev/null ||
- die "Cannot extract kernel partition from image: $image"
-
- local image_type="$(image_cros_kernel_boot_type "$kernel")"
- local need_vmlinuz_hd=""
- info "Image type is [$image_type]: $image"
-
- case "$image_type" in
- "ssd" )
- true
- ;;
- "usb" )
- RELEASE_KERNEL="$kernel"
- need_vmlinuz_hd="TRUE"
- ;;
- "recovery" )
- RELEASE_KERNEL="$kernel"
- image_dump_partition "$image" "4" >"$kernel" 2>/dev/null ||
- die "Cannot extract real kernel for recovery image: $image"
- need_vmlinuz_hd="TRUE"
- ;;
- * )
- die "Unexpected release image type: $image_type."
- ;;
- esac
-
- if [ -n "$need_vmlinuz_hd" ]; then
- local temp_mount="$(mktemp -d --tmpdir)"
- local vmlinuz_hd_file="vmlinuz_hd.vblock"
- image_add_temp "$temp_mount"
- image_mount_partition "$image" "1" "$temp_mount" "ro" ||
- die "No stateful partition in $image."
- [ -s "$temp_mount/$vmlinuz_hd_file" ] ||
- die "Missing $vmlinuz_hd_file in stateful partition: $image"
- sudo dd if="$temp_mount/$vmlinuz_hd_file" of="$kernel" \
- bs=512 conv=notrunc >/dev/null 2>&1 ||
- die "Cannot update kernel with $vmlinuz_hd_file"
- image_umount_partition "$temp_mount"
- fi
-}
-
-# Prepares firmware updater from specified file source or release rootfs.
-prepare_firmware_updater() {
- local image="$(readlink -f "$1")"
- if [ -f "$FLAGS_firmware_updater" ]; then
- return
- fi
-
- local fwupdater="$(mktemp --tmpdir)"
- local temp_mount="$(mktemp -d --tmpdir)"
- local updater_path="/usr/sbin/chromeos-firmwareupdate"
- local src_file="$temp_mount$updater_path"
- image_add_temp "$fwupdater"
- image_add_temp "$temp_mount"
-
- # 'ext2' is required to prevent accidentally modifying image
- image_mount_partition "$image" "3" "$temp_mount" "ro" "-t ext2" ||
- die "Cannot mount partition #3 (rootfs) in release image: $image"
- [ -f "$src_file" ] ||
- die "No firmware updater in release image: $image"
- cp "$src_file" "$fwupdater" ||
- die "Failed to copy firmware updater from release image $image."
- image_umount_partition "$temp_mount"
- info "Prepared firmware updater from release image: $image:3#$updater_path"
- FLAGS_firmware_updater="$fwupdater"
-}
-
-prepare_img() {
- local outdev="$(readlink -f "$FLAGS_diskimg")"
- local sectors="$FLAGS_sectors"
- local force_full="true"
-
- # We'll need some code to put in the PMBR, for booting on legacy BIOS.
- echo "Fetch PMBR"
- local pmbrcode="$(mktemp --tmpdir)"
- image_add_temp "$pmbrcode"
- sudo dd bs=512 count=1 if="${FLAGS_release}" of="${pmbrcode}" status=noxfer
-
- echo "Prepare base disk image"
- # Create an output file if requested, or if none exists.
- if [ -b "${outdev}" ] ; then
- echo "Using block device ${outdev}"
- elif [ ! -e "${outdev}" -o \
- "$(stat -c %s ${outdev})" != "$(( ${sectors} * 512 ))" -o \
- "$FLAGS_preserve" = "$FLAGS_FALSE" ]; then
- echo "Generating empty image file"
- truncate -s "0" "$outdev"
- truncate -s "$((sectors * 512))" "$outdev"
- else
- echo "Reusing $outdev"
- fi
-
- # Create GPT partition table.
- locate_gpt
- install_gpt "${outdev}" 0 0 "${pmbrcode}" 0 "${force_full}"
- # Activate the correct partition.
- sudo "${GPT}" add -i 2 -S 1 -P 1 "${outdev}"
-}
-
-prepare_dir() {
- local dir="$1"
-
- # TODO(hungte) the three files were created as root by old mk_memento_images;
- # we can prevent the sudo in future.
- sudo rm -f "${dir}/rootfs-test.gz"
- sudo rm -f "${dir}/rootfs-release.gz"
- sudo rm -f "${dir}/update.gz"
- for filename in efi oem state hwid firmware; do
- rm -f "${dir}/${filename}.gz"
- done
- if [ ! -d "${dir}" ]; then
- mkdir -p "${dir}"
- fi
-}
-
-# Compresses kernel and rootfs of an imge file, and output its hash.
-# Usage:compress_and_hash_memento_image kernel rootfs output_file
-# Please see "mk_memento_images --help" for detail of parameter syntax
-compress_and_hash_memento_image() {
- local kernel="$1"
- local rootfs="$2"
- local output_file="$3"
- [ "$#" = "3" ] || die "Internal error: compress_and_hash_memento_image $*"
-
- "${SCRIPT_DIR}/mk_memento_images.sh" "$kernel" "$rootfs" "$output_file" |
- grep hash |
- awk '{print $4}'
-}
-
-compress_and_hash_file() {
- local input_file="$1"
- local output_file="$2"
-
- if [ -z "$input_file" ]; then
- # Runs as a pipe processor
- image_gzip_compress -c -9 |
- tee "$output_file" |
- openssl sha1 -binary |
- openssl base64
- else
- image_gzip_compress -c -9 "$input_file" |
- tee "$output_file" |
- openssl sha1 -binary |
- openssl base64
- fi
-}
-
-compress_and_hash_partition() {
- local input_file="$1"
- local part_num="$2"
- local output_file="$3"
-
- image_dump_partition "$input_file" "$part_num" |
- compress_and_hash_file "" "$output_file"
-}
-
-# Applies HWID component list files updater into stateful partition
-apply_hwid_updater() {
- local hwid_updater="$1"
- local outdev="$2"
- local hwid_result="0"
-
- if [ -n "$hwid_updater" ]; then
- local state_dev="$(image_map_partition "${outdev}" 1)"
- sudo sh "$hwid_updater" "$state_dev" || hwid_result="$?"
- image_unmap_partition "$state_dev" || true
- [ $hwid_result = "0" ] || die "Failed to update HWID ($hwid_result). abort."
- fi
-}
-
-generate_usbimg() {
- if ! type cgpt >/dev/null 2>&1; then
- die "Missing 'cgpt'. Please install cgpt, or run inside chroot."
- fi
- local builder="$(dirname "$SCRIPT")/make_universal_factory_shim.sh"
- local release_file="$FLAGS_release"
-
- if [ -n "$RELEASE_KERNEL" ]; then
- # TODO(hungte) Improve make_universal_factory_shim to support assigning
- # a modified kernel to prevent creating temporary image here
- info "Creating temporary SSD-type release image, please wait..."
- release_file="$(mktemp --tmpdir)"
- image_add_temp "${release_file}"
- if image_has_part_tools pv; then
- pv -B 16M "${FLAGS_release}" >"${release_file}"
- else
- cp -f "${FLAGS_release}" "${release_file}"
- fi
- image_partition_copy_from_file "${RELEASE_KERNEL}" "${release_file}" 2
- fi
-
- "$builder" -m "${FLAGS_factory}" -f "${FLAGS_usbimg}" \
- "${FLAGS_install_shim}" "${FLAGS_factory}" "${release_file}"
- apply_hwid_updater "${FLAGS_hwid_updater}" "${FLAGS_usbimg}"
-
- # Extract and modify lsb-factory from original install shim
- local lsb_path="/dev_image/etc/lsb-factory"
- local src_dir="$(mktemp -d --tmpdir)"
- local src_lsb="${src_dir}${lsb_path}"
- local new_dir="$(mktemp -d --tmpdir)"
- local new_lsb="${new_dir}${lsb_path}"
- image_add_temp "$src_dir" "$new_dir"
- image_mount_partition "${FLAGS_install_shim}" 1 "${src_dir}" ""
- image_mount_partition "${FLAGS_usbimg}" 1 "${new_dir}" "rw"
- # Copy firmware updater, if available
- local updater_settings=""
- if [ -n "${FLAGS_firmware_updater}" ]; then
- local updater_new_path="${new_dir}/chromeos-firmwareupdate"
- sudo cp -f "${FLAGS_firmware_updater}" "${updater_new_path}"
- sudo chmod a+rx "${updater_new_path}"
- updater_settings="FACTORY_INSTALL_FIRMWARE=/mnt/stateful_partition"
- updater_settings="$updater_settings/$(basename $updater_new_path)"
- fi
- # We put the install shim kernel and rootfs into partition #2 and #3, so
- # the factory and release image partitions must be moved to +2 location.
- # USB_OFFSET=2 tells factory_installer/factory_install.sh this information.
- (cat "$src_lsb" &&
- echo "FACTORY_INSTALL_FROM_USB=1" &&
- echo "FACTORY_INSTALL_USB_OFFSET=2" &&
- echo "$updater_settings") |
- sudo dd of="${new_lsb}"
- image_umount_partition "$new_dir"
- image_umount_partition "$src_dir"
-
- # Deactivate all kernel partitions except installer slot
- local i=""
- for i in 4 5 6 7; do
- cgpt add -P 0 -T 0 -S 0 -t data -i "$i" "${FLAGS_usbimg}"
- done
-
- info "Generated Image at ${FLAGS_usbimg}."
- info "Done"
-}
-
-generate_img() {
- local outdev="$(readlink -f "$FLAGS_diskimg")"
- local sectors="$FLAGS_sectors"
- local hwid_updater="${FLAGS_hwid_updater}"
-
- if [ -n "${FLAGS_hwid_updater}" ]; then
- hwid_updater="$(readlink -f "$FLAGS_hwid_updater")"
- fi
-
- prepare_img
-
- # Get the release image.
- local release_image="${RELEASE_DIR}/${RELEASE_IMAGE}"
- echo "Release Kernel"
- if [ -n "$RELEASE_KERNEL" ]; then
- image_partition_copy_from_file "${RELEASE_KERNEL}" "${outdev}" 4
- else
- image_partition_copy "${release_image}" 2 "${outdev}" 4
- fi
- echo "Release Rootfs"
- image_partition_overwrite "${release_image}" 3 "${outdev}" 5
- echo "OEM parition"
- image_partition_overwrite "${release_image}" 8 "${outdev}" 8
-
- # Go to retrieve the factory test image.
- local factory_image="${FACTORY_DIR}/${FACTORY_IMAGE}"
- echo "Factory Kernel"
- image_partition_copy "${factory_image}" 2 "${outdev}" 2
- echo "Factory Rootfs"
- image_partition_overwrite "${factory_image}" 3 "${outdev}" 3
- echo "Factory Stateful"
- image_partition_overwrite "${factory_image}" 1 "${outdev}" 1
- echo "EFI Partition"
- image_partition_copy "${factory_image}" 12 "${outdev}" 12
- apply_hwid_updater "${hwid_updater}" "${outdev}"
-
- # TODO(nsanders, wad): consolidate this code into some common code
- # when cleaning up kernel commandlines. There is code that touches
- # this in postint/chromeos-setimage and build_image. However none
- # of the preexisting code actually does what we want here.
- local tmpesp="$(mktemp -d --tmpdir)"
- image_add_temp "$tmpesp"
- image_mount_partition "${outdev}" 12 "$tmpesp" "rw"
-
- # Edit boot device default for legacy boot loaders, if available.
- if [ -d "${tmpesp}/syslinux" ]; then
- # Support both vboot and regular boot.
- sudo sed -i "s/chromeos-usb.A/chromeos-hd.A/" \
- "${tmpesp}"/syslinux/default.cfg
- sudo sed -i "s/chromeos-vusb.A/chromeos-vhd.A/" \
- "${tmpesp}"/syslinux/default.cfg
- # Edit root fs default for legacy.
- # Since legacy loader currently exists only on x86 platforms, we can assume
- # the rootfs is always sda3.
- sudo sed -i "s'HDROOTA'/dev/sda3'g" \
- "${tmpesp}"/syslinux/root.A.cfg
- fi
-
- image_umount_partition "$tmpesp"
- echo "Generated Image at $outdev."
- echo "Done"
-}
-
-generate_omaha() {
- local kernel rootfs
- [ -n "$FLAGS_board" ] || die "Need --board parameter for mini-omaha server."
- # Clean up stale config and data files.
- prepare_dir "${OMAHA_DATA_DIR}"
-
- echo "Generating omaha release image from ${FLAGS_release}"
- echo "Generating omaha factory image from ${FLAGS_factory}"
- echo "Output omaha image to ${OMAHA_DATA_DIR}"
- echo "Output omaha config to ${OMAHA_CONF}"
-
- kernel="${RELEASE_KERNEL:-${FLAGS_release}:2}"
- rootfs="${FLAGS_release}:3"
- release_hash="$(compress_and_hash_memento_image "$kernel" "$rootfs" \
- "${OMAHA_DATA_DIR}/rootfs-release.gz")"
- echo "release: ${release_hash}"
-
- oem_hash="$(compress_and_hash_partition "${FLAGS_release}" 8 \
- "${OMAHA_DATA_DIR}/oem.gz")"
- echo "oem: ${oem_hash}"
-
- kernel="${FLAGS_factory}:2"
- rootfs="${FLAGS_factory}:3"
- test_hash="$(compress_and_hash_memento_image "$kernel" "$rootfs" \
- "${OMAHA_DATA_DIR}/rootfs-test.gz")"
- echo "test: ${test_hash}"
-
- state_hash="$(compress_and_hash_partition "${FLAGS_factory}" 1 \
- "${OMAHA_DATA_DIR}/state.gz")"
- echo "state: ${state_hash}"
-
- efi_hash="$(compress_and_hash_partition "${FLAGS_factory}" 12 \
- "${OMAHA_DATA_DIR}/efi.gz")"
- echo "efi: ${efi_hash}"
-
- if [ -n "${FLAGS_firmware_updater}" ]; then
- firmware_hash="$(compress_and_hash_file "${FLAGS_firmware_updater}" \
- "${OMAHA_DATA_DIR}/firmware.gz")"
- echo "firmware: ${firmware_hash}"
- fi
-
- if [ -n "${FLAGS_hwid_updater}" ]; then
- hwid_hash="$(compress_and_hash_file "${FLAGS_hwid_updater}" \
- "${OMAHA_DATA_DIR}/hwid.gz")"
- echo "hwid: ${hwid_hash}"
- fi
-
- if [ -n "${FLAGS_complete_script}" ]; then
- complete_hash="$(compress_and_hash_file "${FLAGS_complete_script}" \
- "${OMAHA_DATA_DIR}/complete.gz")"
- echo "complete: ${complete_hash}"
- fi
-
- # If the file does exist and we are using the subfolder flag we are going to
- # append another config.
- if [ -n "${FLAGS_subfolder}" ] &&
- [ -f "${OMAHA_CONF}" ]; then
- # Remove the ']' from the last line of the file
- # so we can add another config.
- while [ -s "${OMAHA_CONF}" ]; do
- # If the last line is null
- if [ -z "$(tail -1 "${OMAHA_CONF}")" ]; then
- sed -i '$d' "${OMAHA_CONF}"
- elif [ "$(tail -1 "${OMAHA_CONF}")" != ']' ]; then
- sed -i '$d' "${OMAHA_CONF}"
- else
- break
- fi
- done
-
- # Remove the last ]
- if [ "$(tail -1 "${OMAHA_CONF}")" = ']' ]; then
- sed -i '$d' "${OMAHA_CONF}"
- fi
-
- # If the file is empty, create it from scratch
- if [ ! -s "${OMAHA_CONF}" ]; then
- echo "config = [" >"${OMAHA_CONF}"
- fi
- else
- echo "config = [" >"${OMAHA_CONF}"
- fi
-
- if [ -n "${FLAGS_subfolder}" ]; then
- subfolder="${FLAGS_subfolder}/"
- fi
-
- echo -n "{
- 'qual_ids': set([\"${FLAGS_board}\"]),
- 'factory_image': '${subfolder}rootfs-test.gz',
- 'factory_checksum': '${test_hash}',
- 'release_image': '${subfolder}rootfs-release.gz',
- 'release_checksum': '${release_hash}',
- 'oempartitionimg_image': '${subfolder}oem.gz',
- 'oempartitionimg_checksum': '${oem_hash}',
- 'efipartitionimg_image': '${subfolder}efi.gz',
- 'efipartitionimg_checksum': '${efi_hash}',
- 'stateimg_image': '${subfolder}state.gz',
- 'stateimg_checksum': '${state_hash}'," >>"${OMAHA_CONF}"
-
- if [ -n "${FLAGS_firmware_updater}" ] ; then
- echo -n "
- 'firmware_image': '${subfolder}firmware.gz',
- 'firmware_checksum': '${firmware_hash}'," >>"${OMAHA_CONF}"
- fi
-
- if [ -n "${FLAGS_hwid_updater}" ] ; then
- echo -n "
- 'hwid_image': '${subfolder}hwid.gz',
- 'hwid_checksum': '${hwid_hash}'," >>"${OMAHA_CONF}"
- fi
-
- if [ -n "${FLAGS_complete_script}" ] ; then
- echo -n "
- 'complete_image': '${subfolder}complete.gz',
- 'complete_checksum': '${complete_hash}'," >>"${OMAHA_CONF}"
- fi
-
- echo -n "
- },
-]
-" >>"${OMAHA_CONF}"
-
- local program="$(basename "${OMAHA_PROGRAM}")"
- local config="$(basename "${OMAHA_CONF}")"
-
- info "The miniomaha server lives in: $OMAHA_DIR
- To validate the configutarion, run:
- python2.6 $program --factory_config $config --validate_factory_config
- To run the server:
- python2.6 $program --factory_config $config"
-}
-
-check_cherrypy3() {
- local version="$("$1" -c 'import cherrypy as c;print c.__version__' || true)"
- local version_major="${version%%.*}"
-
- if [ -n "$version_major" ] && [ "$version_major" -ge 3 ]; then
- return $FLAGS_TRUE
- fi
- # Check how to install cherrypy3
- local install_command=""
- if image_has_command apt-get; then
- install_command="by 'sudo apt-get install python-cherrypy3'"
- elif image_has_command emerge; then
- install_command="by 'sudo emerge dev-python/cherrypy'"
- fi
- die "Please install cherrypy 3.0 or later $install_command"
-}
-
-run_omaha() {
- local python="python2.6"
- image_has_command "$python" || python="python"
- image_has_command "$python" || die "Please install Python in your system."
- check_cherrypy3 "$python"
-
- find_omaha
-
- info "Running mini-omaha in $OMAHA_DIR..."
- (set -e
- cd "$OMAHA_DIR"
- info "Validating factory config..."
- "$python" "${OMAHA_PROGRAM}" --factory_config "${OMAHA_CONF}" \
- --validate_factory_config
- info "Starting mini-omaha..."
- "$python" "${OMAHA_PROGRAM}" --factory_config "${OMAHA_CONF}"
- )
-}
-
-parse_and_run_config() {
- # This function parses parameters from config file. Parameters can be put
- # in sections and sections of parameters will be run in turn.
- #
- # Config file format:
- # [section1]
- # --param value
- # --another_param # comment
- #
- # # some more comment
- # [section2]
- # --yet_another_param
- #
- # Note that a section header must start at the beginning of a line.
- # And it's not allowed to read from config file recursively.
-
- local config_file="$1"
- local -a cmds
- local cmd=""
- local line
-
- echo "Read parameters from: $config_file"
- while read line; do
- if [[ "$line" =~ ^\[.*] ]]; then
- if [ -n "$cmd" ]; then
- cmds+=("$cmd")
- cmd=""
- fi
- continue
- fi
- line="${line%%#*}"
- cmd="$cmd $line"
- done < "$config_file"
- if [ -n "$cmd" ]; then
- cmds+=("$cmd")
- fi
-
- for cmd in "${cmds[@]}"
- do
- info "Executing: $0 $cmd"
- # Sets internal environment variable MFP_SUBPROCESS to prevent unexpected
- # recursion.
- eval "MFP_SUBPROCESS=1 $0 $cmd"
- done
-}
-
-# Checks if normal parameters are all empty.
-check_empty_normal_params() {
- local param
- local mode="$1"
- local param_list="release factory firmware_updater hwid_updater install_shim
- complete_script usb_img disk_img subfolder"
- for param in $param_list; do
- check_empty_param FLAGS_$param "$mode"
- done
-}
-
-main() {
- set -e
- trap on_exit EXIT
- if [ "$#" != 0 ]; then
- flags_help
- exit 1
- fi
-
- if [ -n "$FLAGS_config" ]; then
- [ -z "$MFP_SUBPROCESS" ] ||
- die "Recursively reading from config file is not allowed"
-
- check_file_param FLAGS_config ""
- check_empty_normal_params "when using config file"
-
- # Make the path and folder of config file available when parsing config.
- # These MFP_CONFIG_* are special shell variables (not environment variables)
- # that a config file (by --config) can use them.
- MFP_CONFIG_PATH="$(readlink -f "$FLAGS_config")"
- MFP_CONFIG_DIR="$(dirname "$MFP_CONFIG_PATH")"
-
- parse_and_run_config "$FLAGS_config"
- [ "$FLAGS_run_omaha" = $FLAGS_FALSE ] || run_omaha
- exit
- fi
-
- check_parameters
- setup_environment
-
- if [ "$FLAGS_detect_release_image" = $FLAGS_TRUE ]; then
- prepare_release_image "$FLAGS_release"
- fi
- if [ "$ENABLE_FIRMWARE_UPDATER" = $FLAGS_TRUE ]; then
- prepare_firmware_updater "$FLAGS_release"
- fi
-
- if [ -n "$FLAGS_usbimg" ]; then
- generate_usbimg
- elif [ -n "$FLAGS_diskimg" ]; then
- generate_img
- else
- generate_omaha
- [ "$FLAGS_run_omaha" = $FLAGS_FALSE ] || run_omaha
- fi
-}
-
-main "$@"
diff --git a/factory_setup/make_universal_factory_shim.sh b/factory_setup/make_universal_factory_shim.sh
deleted file mode 100755
index de7f456..0000000
--- a/factory_setup/make_universal_factory_shim.sh
+++ /dev/null
@@ -1,288 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2011 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 generate an universal factory install shim image, by merging
-# multiple images signed by different keys.
-# CAUTION: Recovery shim images are not supported yet because they require the
-# kernel partitions to be laid out in a special way
-
-. "$(dirname "$(readlink -f "$0")")/factory_common.sh" || exit 1
-
-# CGPT Header: PMBR, header, table; sec_table, sec_header
-CGPT_START_SIZE=$((1 + 1 + 32))
-CGPT_END_SIZE=$((32 + 1))
-CGPT_BS="512"
-
-# Alignment of partition sectors
-PARTITION_SECTOR_ALIGNMENT=256
-
-LAYOUT_FILE="$(mktemp --tmpdir)"
-
-RESERVED_PARTITION="10"
-LEGACY_PARTITIONS="10 11 12" # RESERVED, RWFW, EFI
-MAX_INPUT_SOURCES=4 # (2~9) / 2
-
-alert() {
- echo "$*" >&2
-}
-
-die() {
- alert "ERROR: $*"
- exit 1
-}
-
-on_exit() {
- rm -f "$LAYOUT_FILE"
-}
-
-# Returns offset aligned to alignment.
-# If size is given, only align if size >= alignment.
-image_alignment() {
- local offset="$1"
- local alignment="$2"
- local size="$3"
-
- # If size is assigned, align only if the new size is larger then alignment.
- if [ "$((offset % alignment))" != "0" ]; then
- if [ -z "$size" -o "$size" -ge "$alignment" ]; then
- offset=$((offset + alignment - (offset % alignment)))
- fi
- fi
- echo "$((offset))"
-}
-
-# Processes a logical disk image layout description file.
-# Each entry in layout is a "file:partnum" entry (:partnum is optional),
-# referring to the #partnum partition in file.
-# The index starts at one, referring to the first partition in layout.
-image_process_layout() {
- local layout_file="$1"
- local callback="$2"
- shift
- shift
- local param="$@"
- local index=0
-
- while read layout; do
- local image_file="${layout%:*}"
- local part_num="${layout#*:}"
- index="$((index + 1))"
- [ "$image_file" != "$layout" ] || part_num=""
-
- "$callback" "$image_file" "$part_num" "$index" "$param"
- done <"$layout_file"
-}
-
-# Processes a list of disk geometry sectors into aligned (offset, sectors) form.
-# The index starts at zero, referring to the partition table object itself.
-image_process_geometry() {
- local sectors_list="$1"
- local callback="$2"
- shift
- shift
- local param="$@"
- local offset=0 sectors
- local index=0
-
- for sectors in $sectors_list; do
- offset="$(image_alignment $offset $PARTITION_SECTOR_ALIGNMENT $sectors)"
- "$callback" "$offset" "$sectors" "$index" "$param"
- offset="$((offset + sectors))"
- index="$((index + 1))"
- done
-}
-
-# Callback of image_process_layout. Returns the size (in sectors) of given
-# object (partition in image or file).
-layout_get_sectors() {
- local image_file="$1"
- local part_num="$2"
-
- if [ -n "$part_num" ]; then
- image_part_size "$image_file" "$part_num"
- else
- image_alignment "$(stat -c"%s" "$image_file")" $CGPT_BS ""
- fi
-}
-
-# Callback of image_process_layout. Copies an input source object (file or
-# partition) into specified partition on output file.
-layout_copy_partition() {
- local input_file="$1"
- local input_part="$2"
- local output_part="$3"
- local output_file="$4"
- alert "$(basename "$input_file"):$input_part =>" \
- "$(basename "$output_file"):$output_part"
-
- if [ -n "$input_part" ]; then
- image_partition_copy "$input_file" "$input_part" \
- "$output_file" "$output_part"
- # Update partition type information
- local partition_type="$(cgpt show -q -n -t -i "$input_part" "$input_file")"
- local partition_attr="$(cgpt show -q -n -A -i "$input_part" "$input_file")"
- local partition_label="$(cgpt show -q -n -l -i "$input_part" "$input_file")"
- cgpt add -t "$partition_type" -l "$partition_label" -A "$partition_attr" \
- -i "$output_part" "$output_file"
- else
- image_update_partition "$output_file" "$output_part" <"$input_file"
- fi
-}
-
-
-# Callback of image_process_geometry. Creates a partition by give offset,
-# size(sectors), and index.
-geometry_create_partition() {
- local offset="$1"
- local sectors="$2"
- local index="$3"
- local output_file="$4"
-
- if [ "$offset" = "0" ]; then
- # first entry is CGPT; ignore.
- return
- fi
- cgpt add -b $offset -s $sectors -i $index -t reserved "$output_file"
-}
-
-# Callback of image_process_geometry. Prints the proper offset of current
-# partition by give offset and size.
-geometry_get_partition_offset() {
- local offset="$1"
- local sectors="$2"
- local index="$3"
-
- image_alignment "$offset" "$PARTITION_SECTOR_ALIGNMENT" "$sectors"
-}
-
-build_image_file() {
- local layout_file="$1"
- local output_file="$2"
- local output_file_size=0
- local sectors_list partition_offsets
-
- # Check and obtain size information from input sources
- sectors_list="$(image_process_layout "$layout_file" layout_get_sectors)"
-
- # Calculate output image file size
- partition_offsets="$(image_process_geometry \
- "$CGPT_START_SIZE $sectors_list $CGPT_END_SIZE 1" \
- geometry_get_partition_offset)"
- output_file_size="$(echo "$partition_offsets" | tail -n 1)"
-
- # Create empty image file
- truncate -s "0" "$output_file" # starting with a new file is much faster.
- truncate -s "$((output_file_size * CGPT_BS))" "$output_file"
-
- # Initialize partition table (GPT)
- cgpt create "$output_file"
- cgpt boot -p "$output_file" >/dev/null
-
- # Create partition tables
- image_process_geometry "$CGPT_START_SIZE $sectors_list" \
- geometry_create_partition \
- "$output_file"
- # Copy partitions content
- image_process_layout "$layout_file" layout_copy_partition "$output_file"
-}
-
-# Creates standard multiple image layout
-create_standard_layout() {
- local main_source="$1"
- local layout_file="$2"
- local image index
- shift
- shift
-
- for image in "$main_source" "$@"; do
- if [ ! -f "$image" ]; then
- die "Cannot find input file $image."
- fi
- done
-
- echo "$main_source:1" >>"$layout_file" # stateful partition
- for index in $(seq 1 $MAX_INPUT_SOURCES); do
- local kernel_source="$main_source:$RESERVED_PARTITION"
- local rootfs_source="$main_source:$RESERVED_PARTITION"
- if [ "$#" -gt 0 ]; then
- # TODO(hungte) detect if input source is a recovery/USB image
- kernel_source="$1:2"
- rootfs_source="$1:3"
- shift
- fi
- echo "$kernel_source" >>"$layout_file"
- echo "$rootfs_source" >>"$layout_file"
- done
- for index in $LEGACY_PARTITIONS; do
- echo "$main_source:$index" >>"$LAYOUT_FILE"
- done
-}
-
-usage_die() {
- alert "Usage: $SCRIPT [-m master] [-f] output shim1 [shim2 ... shim4]"
- alert " or $SCRIPT -l layout [-f] output"
- exit 1
-}
-
-main() {
- local force=""
- local image=""
- local output=""
- local main_source=""
- local index=""
- local slots="0"
- local layout_mode=""
-
- while [ "$#" -gt 1 ]; do
- case "$1" in
- "-f" )
- force="True"
- shift
- ;;
- "-m" )
- main_source="$2"
- shift
- shift
- ;;
- "-l" )
- cat "$2" >"$LAYOUT_FILE"
- layout_mode="TRUE"
- shift
- shift
- ;;
- * )
- break
- esac
- done
-
- if [ -n "$layout_mode" ]; then
- [ "$#" = 1 ] || usage_die
- elif [ "$#" -lt 2 -o "$#" -gt "$((MAX_INPUT_SOURCES + 1))" ]; then
- alert "ERROR: invalid number of parameters ($#)."
- usage_die
- fi
-
- if [ -z "$main_source" ]; then
- main_source="$2"
- fi
- output="$1"
- shift
-
- if [ -f "$output" -a -z "$force" ]; then
- die "Output file $output already exists. To overwrite the file, add -f."
- fi
-
- if [ -z "$layout_mode" ]; then
- create_standard_layout "$main_source" "$LAYOUT_FILE" "$@"
- fi
- build_image_file "$LAYOUT_FILE" "$output"
- echo ""
- echo "Image created: $output"
-}
-
-set -e
-trap on_exit EXIT
-main "$@"
diff --git a/factory_setup/miniomaha.py b/factory_setup/miniomaha.py
deleted file mode 100755
index ed721d2..0000000
--- a/factory_setup/miniomaha.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2009-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.
-
-"""A CherryPy-based webserver to host factory installation."""
-
-# This a special fork from devserver for serving factory and may be executed in
-# a very limited environment without full CrOS source tree.
-
-import cherrypy
-import optparse
-import os
-import subprocess
-import sys
-
-import miniomaha_engine
-
-CACHED_ENTRIES = 12
-
-# Sets up global to share between classes.
-global updater
-updater = None
-
-def _GetConfig(options):
- """Returns the configuration for the miniomaha."""
- base_config = { 'global':
- { 'server.log_request_headers': True,
- 'server.protocol_version': 'HTTP/1.1',
- 'server.socket_host': '::',
- 'server.socket_port': int(options.port),
- 'server.socket_timeout': 6000,
- 'response.timeout': 6000,
- 'tools.staticdir.root':
- os.path.dirname(os.path.abspath(sys.argv[0])),
- },
- '/api':
- {
- # Gets rid of cherrypy parsing post file for args.
- 'request.process_request_body': False,
- },
- '/update':
- {
- # Gets rid of cherrypy parsing post file for args.
- 'request.process_request_body': False,
- 'response.timeout': 10000,
- },
- # Sets up the static dir for file hosting.
- '/static':
- { 'tools.staticdir.dir': 'static',
- 'tools.staticdir.on': True,
- 'response.timeout': 10000,
- },
- }
-
- return base_config
-
-
-class ApiRoot(object):
- """RESTful API for Dev Server information."""
- exposed = True
-
- @cherrypy.expose
- def hostinfo(self, ip):
- """Returns a JSON dictionary containing information about the given ip.
-
- Not all information may be known at the time the request is made. The
- possible keys are:
-
- last_event_type: int
- Last update event type received.
-
- last_event_status: int
- Last update event status received.
-
- last_known_version: string
- Last known version recieved for update ping.
-
- forced_update_label: string
- Update label to force next update ping to use. Set by setnextupdate.
-
- See the OmahaEvent class in update_engine/omaha_request_action.h for status
- code definitions. If the ip does not exist an empty string is returned."""
- return updater.HandleHostInfoPing(ip)
-
- @cherrypy.expose
- def setnextupdate(self, ip):
- """Allows the response to the next update ping from a host to be set.
-
- Takes the IP of the host and an update label as normally provided to the
- /update command."""
- body_length = int(cherrypy.request.headers['Content-Length'])
- label = cherrypy.request.rfile.read(body_length)
-
- if label:
- label = label.strip()
- if label:
- return updater.HandleSetUpdatePing(ip, label)
- raise cherrypy.HTTPError(400, 'No label provided.')
-
-
-class DevServerRoot(object):
- """The Root Class for the Dev Server.
-
- CherryPy works as follows:
- For each method in this class, cherrpy interprets root/path
- as a call to an instance of DevServerRoot->method_name. For example,
- a call to http://myhost/build will call build. CherryPy automatically
- parses http args and places them as keyword arguments in each method.
- For paths http://myhost/update/dir1/dir2, you can use *args so that
- cherrypy uses the update method and puts the extra paths in args.
- """
- api = ApiRoot()
-
- @cherrypy.expose
- def index(self):
- return 'Welcome to the Dev Server!'
-
- @cherrypy.expose
- def update(self, *args):
- label = '/'.join(args)
- body_length = int(cherrypy.request.headers['Content-Length'])
- data = cherrypy.request.rfile.read(body_length)
- return updater.HandleUpdatePing(data, label)
-
-
-if __name__ == '__main__':
- base_path = os.path.dirname(os.path.abspath(sys.argv[0]))
- usage = 'usage: %prog [options]'
- parser = optparse.OptionParser(usage)
- parser.add_option('--data_dir', dest='data_dir',
- help='Writable directory where static lives',
- default=base_path)
- parser.add_option('--factory_config', dest='factory_config',
- help='Config file for serving images from factory floor.',
- default=base_path + "/miniomaha.conf")
- parser.add_option('--port', default=8080,
- help='Port for the dev server to use.')
- parser.add_option('--proxy_port', default=None,
- help='Port to have the client connect to (testing support)')
- parser.add_option('--validate_factory_config', action="store_true",
- dest='validate_factory_config',
- help='Validate factory config file, then exit.')
- parser.set_usage(parser.format_help())
- (options, _) = parser.parse_args()
-
- static_dir = os.path.realpath('%s/static' % options.data_dir)
- os.system('mkdir -p %s' % static_dir)
-
- cherrypy.log('Data dir is %s' % options.data_dir, 'DEVSERVER')
- cherrypy.log('Serving from %s' % static_dir, 'DEVSERVER')
-
- updater = miniomaha_engine.ServerEngine(
- static_dir=static_dir,
- factory_config_path=options.factory_config,
- port=options.port,
- proxy_port=options.proxy_port,
- )
-
- # Sanity-check for use of validate_factory_config.
- if not options.factory_config:
- parser.error('factory_config must be assigned.')
-
- updater.ImportFactoryConfigFile(options.factory_config,
- options.validate_factory_config)
- if not options.validate_factory_config:
- cherrypy.quickstart(DevServerRoot(), config=_GetConfig(options))
diff --git a/factory_setup/miniomaha_engine.py b/factory_setup/miniomaha_engine.py
deleted file mode 100644
index d273e2d..0000000
--- a/factory_setup/miniomaha_engine.py
+++ /dev/null
@@ -1,310 +0,0 @@
-# Copyright (c) 2011 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.
-
-from xml.dom import minidom
-
-import cherrypy
-import json
-import os
-import time
-import urlparse
-
-
-def _LogMessage(message):
- cherrypy.log(message, 'UPDATE')
-
-def _ChangeUrlPort(url, new_port):
- """Return the URL passed in with a different port"""
- scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
- host_port = netloc.split(':')
-
- if len(host_port) == 1:
- host_port.append(new_port)
- else:
- host_port[1] = new_port
-
- print host_port
- netloc = "%s:%s" % tuple(host_port)
-
- return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
-
-
-class ServerEngine(object):
- """Class that contains functionality that handles Chrome OS update pings.
-
- Members:
- factory_config_path: Path to the factory config file if handling factory
- requests.
- static_dir: Path to store installation packages.
- port: port to host miniomaha
- proxy_port: port of local proxy to tell client to connect to you through.
- """
-
- def __init__(self, static_dir,
- factory_config_path=None,
- port=8080, proxy_port=None,
- *args, **kwargs):
- self.app_id = '87efface-864d-49a5-9bb3-4b050a7c227a'
- self.static_dir = static_dir
- self.factory_config = factory_config_path
- self.proxy_port = proxy_port
-
- # Initialize empty host info cache. Used to keep track of various bits of
- # information about a given host.
- self.host_info = {}
-
- def _GetSecondsSinceMidnight(self):
- """Returns the seconds since midnight as a decimal value."""
- now = time.localtime()
- return now[3] * 3600 + now[4] * 60 + now[5]
-
- def _GetSize(self, update_path):
- """Returns the size of the file given."""
- return os.path.getsize(update_path)
-
- def _GetHash(self, update_path):
- """Returns the sha1 of the file given."""
- cmd = ('cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';'
- % update_path)
- return os.popen(cmd).read().rstrip()
-
- def _IsDeltaFormatFile(self, filename):
- try:
- file_handle = open(filename, 'r')
- delta_magic = 'CrAU'
- magic = file_handle.read(len(delta_magic))
- return magic == delta_magic
- except Exception:
- return False
-
- # TODO(petkov): Consider optimizing getting both SHA-1 and SHA-256 so that
- # it takes advantage of reduced I/O and multiple processors. Something like:
- # % tee < FILE > /dev/null \
- # >( openssl dgst -sha256 -binary | openssl base64 ) \
- # >( openssl sha1 -binary | openssl base64 )
- def _GetSHA256(self, update_path):
- """Returns the sha256 of the file given."""
- cmd = ('cat %s | openssl dgst -sha256 -binary | openssl base64' %
- update_path)
- return os.popen(cmd).read().rstrip()
-
- def _GetMd5(self, update_path):
- """Returns the md5 checksum of the file given."""
- cmd = ("md5sum %s | awk '{print $1}'" % update_path)
- return os.popen(cmd).read().rstrip()
-
- def GetUpdatePayload(self, hash, sha256, size, url, is_delta_format):
- """Returns a payload to the client corresponding to a new update.
-
- Args:
- hash: hash of update blob
- sha256: SHA-256 hash of update blob
- size: size of update blob
- url: where to find update blob
- Returns:
- Xml string to be passed back to client.
- """
- delta = 'false'
- if is_delta_format:
- delta = 'true'
- payload = """<?xml version="1.0" encoding="UTF-8"?>
- <gupdate xmlns="http://www.google.com/update2/response" protocol="2.0">
- <daystart elapsed_seconds="%s"/>
- <app appid="{%s}" status="ok">
- <ping status="ok"/>
- <updatecheck
- codebase="%s"
- hash="%s"
- sha256="%s"
- needsadmin="false"
- size="%s"
- IsDelta="%s"
- status="ok"/>
- </app>
- </gupdate>
- """
- return payload % (self._GetSecondsSinceMidnight(),
- self.app_id, url, hash, sha256, size, delta)
-
- def GetNoUpdatePayload(self):
- """Returns a payload to the client corresponding to no update."""
- payload = """<?xml version="1.0" encoding="UTF-8"?>
- <gupdate xmlns="http://www.google.com/update2/response" protocol="2.0">
- <daystart elapsed_seconds="%s"/>
- <app appid="{%s}" status="ok">
- <ping status="ok"/>
- <updatecheck status="noupdate"/>
- </app>
- </gupdate>
- """
- return payload % (self._GetSecondsSinceMidnight(), self.app_id)
-
- def ImportFactoryConfigFile(self, filename, validate_checksums=False):
- """Imports a factory-floor server configuration file. The file should
- be in this format:
- config = [
- {
- 'qual_ids': set([1, 2, 3, "x86-generic"]),
- 'factory_image': 'generic-factory.gz',
- 'factory_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'release_image': 'generic-release.gz',
- 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'oempartitionimg_image': 'generic-oem.gz',
- 'oempartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'efipartitionimg_image': 'generic-efi.gz',
- 'efipartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'stateimg_image': 'generic-state.gz',
- 'stateimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'firmware_image': 'generic-firmware.gz',
- 'firmware_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- },
- {
- 'qual_ids': set([6]),
- 'factory_image': '6-factory.gz',
- 'factory_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'release_image': '6-release.gz',
- 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'oempartitionimg_image': '6-oem.gz',
- 'oempartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'efipartitionimg_image': '6-efi.gz',
- 'efipartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'stateimg_image': '6-state.gz',
- 'stateimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- 'firmware_image': '6-firmware.gz',
- 'firmware_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
- },
- ]
- The server will look for the files by name in the static files
- directory.
-
- If validate_checksums is True, validates checksums and exits. If
- a checksum mismatch is found, it's printed to the screen.
- """
- f = open(filename, 'r')
- output = {}
- exec(f.read(), output)
- self.factory_config = output['config']
- success = True
- for stanza in self.factory_config:
- for key in stanza.copy().iterkeys():
- suffix = '_image'
- if key.endswith(suffix):
- kind = key[:-len(suffix)]
- stanza[kind + '_size'] = self._GetSize(os.path.join(
- self.static_dir, stanza[kind + '_image']))
- if validate_checksums:
- factory_checksum = self._GetHash(os.path.join(self.static_dir,
- stanza[kind + '_image']))
- if factory_checksum != stanza[kind + '_checksum']:
- print ('Error: checksum mismatch for %s. Expected "%s" but file '
- 'has checksum "%s".' % (stanza[kind + '_image'],
- stanza[kind + '_checksum'],
- factory_checksum))
- success = False
-
- if validate_checksums:
- if success is False:
- raise Exception('Checksum mismatch in conf file.')
-
- print 'Config file looks good.'
-
- def GetFactoryImage(self, board_id, channel):
- kind = channel.rsplit('-', 1)[0]
- for stanza in self.factory_config:
- if board_id not in stanza['qual_ids']:
- continue
- if kind + '_image' not in stanza:
- break
- return (stanza[kind + '_image'],
- stanza[kind + '_checksum'],
- stanza[kind + '_size'])
- return (None, None, None)
-
- def HandleFactoryRequest(self, board_id, channel):
- (filename, checksum, size) = self.GetFactoryImage(board_id, channel)
- if filename is None:
- _LogMessage('unable to find image for board %s' % board_id)
- return self.GetNoUpdatePayload()
- url = '%s/static/%s' % (self.hostname, filename)
- is_delta_format = self._IsDeltaFormatFile(filename)
- _LogMessage('returning update payload ' + url)
- # Factory install is using memento updater which is using the sha-1 hash so
- # setting sha-256 to an empty string.
- return self.GetUpdatePayload(checksum, '', size, url, is_delta_format)
-
- def HandleUpdatePing(self, data, label=None):
- """Handles an update ping from an update client.
-
- Args:
- data: xml blob from client.
- label: optional label for the update.
- Returns:
- Update payload message for client.
- """
- # Set hostname as the hostname that the client is calling to and set up
- # the url base.
- self.hostname = cherrypy.request.base
- static_urlbase = '%s/static' % self.hostname
-
- # If we have a proxy port, adjust the URL we instruct the client to
- # use to go through the proxy.
- if self.proxy_port:
- static_urlbase = _ChangeUrlPort(static_urlbase, self.proxy_port)
-
- _LogMessage('Using static url base %s' % static_urlbase)
- _LogMessage('Handling update ping as %s: %s' % (self.hostname, data))
-
- update_dom = minidom.parseString(data)
- root = update_dom.firstChild
-
- # Determine request IP, strip any IPv6 data for simplicity.
- client_ip = cherrypy.request.remote.ip.split(':')[-1]
-
- # Initialize host info dictionary for this client if it doesn't exist.
- self.host_info.setdefault(client_ip, {})
-
- # Store event details in the host info dictionary for API usage.
- event = root.getElementsByTagName('o:event')
- if event:
- self.host_info[client_ip]['last_event_status'] = (
- int(event[0].getAttribute('eventresult')))
- self.host_info[client_ip]['last_event_type'] = (
- int(event[0].getAttribute('eventtype')))
-
- # We only generate update payloads for updatecheck requests.
- update_check = root.getElementsByTagName('o:updatecheck')
- if not update_check:
- _LogMessage('Non-update check received. Returning blank payload.')
- # TODO(sosa): Generate correct non-updatecheck payload to better test
- # update clients.
- return self.GetNoUpdatePayload()
-
- # Since this is an updatecheck, get information about the requester.
- query = root.getElementsByTagName('o:app')[0]
- client_version = query.getAttribute('version')
- channel = query.getAttribute('track')
- board_id = (query.hasAttribute('board') and query.getAttribute('board')
- or 'unknown')
-
- # Store version for this host in the cache.
- self.host_info[client_ip]['last_known_version'] = client_version
-
- # Check if an update has been forced for this client.
- forced_update = self.host_info[client_ip].pop('forced_update_label', None)
- if forced_update:
- label = forced_update
-
- return self.HandleFactoryRequest(board_id, channel)
-
- def HandleHostInfoPing(self, ip):
- """Returns host info dictionary for the given IP in JSON format."""
- assert ip, 'No ip provided.'
- if ip in self.host_info:
- return json.dumps(self.host_info[ip])
-
- def HandleSetUpdatePing(self, ip, label):
- """Sets forced_update_label for a given host."""
- assert ip, 'No ip provided.'
- assert label, 'No label provided.'
- self.host_info.setdefault(ip, {})['forced_update_label'] = label
diff --git a/factory_setup/miniomaha_test.py b/factory_setup/miniomaha_test.py
deleted file mode 100755
index 7d32c2a..0000000
--- a/factory_setup/miniomaha_test.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/python
-
-# 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.
-
-"""Regression tests for miniomaha server."""
-
-import json
-import os
-import signal
-import shutil
-import subprocess
-import sys
-import time
-import unittest
-import urllib2
-from xml.dom import minidom
-
-# Paths are relative to this script's base directory.
-STATIC_DIR = 'static'
-TEST_IMAGE_PATH = 'testdata/miniomaha'
-TEST_IMAGE_NAME = 'developer-test.gz'
-TEST_IMAGE = TEST_IMAGE_PATH + '/' + TEST_IMAGE_NAME
-TEST_FACTORY_CONFIG = 'testdata/miniomaha/miniomaha-test.conf'
-TEST_DATA_PATH = '/tmp/miniomaha-test'
-TEST_CLIENT_PREFIX = 'ChromeOSUpdateEngine'
-
-UPDATE_REQUEST = """<?xml version="1.0" encoding="UTF-8"?>
-<o:gupdate xmlns:o="http://www.google.com/update2/request"
- version="ChromeOSUpdateEngine-0.1.0.0"
- updaterversion="ChromeOSUpdateEngine-0.1.0.0"
- protocol="2.0"
- ismachine="1">
- <o:os version="Indy"
- platform="Chrome OS" sp="0.11.254.2011_03_09_1814_i686"></o:os>
- <o:app appid="{DEV-BUILD}" version="0.11.254.2011_03_09_1814"
- lang="en-US" track="developer-build" board="x86-generic"
- hardware_class="BETA DVT" delta_okay="true">
- <o:updatecheck></o:updatecheck>
- <o:event eventtype="3" eventresult="2"
- previousversion="0.11.216.2011_03_02_1358"></o:event>
- </o:app>
-</o:gupdate>
-"""
-# TODO(girts): use a random available port.
-UPDATE_URL = 'http://127.0.0.1:8080/update'
-
-API_HOST_INFO_BAD_URL = 'http://127.0.0.1:8080/api/hostinfo/'
-API_HOST_INFO_URL = API_HOST_INFO_BAD_URL + '127.0.0.1'
-
-API_SET_UPDATE_BAD_URL = 'http://127.0.0.1:8080/api/setnextupdate/'
-API_SET_UPDATE_URL = API_SET_UPDATE_BAD_URL + '127.0.0.1'
-
-API_SET_UPDATE_REQUEST = 'new_update-test/the-new-update'
-
-# Run all tests while being in /
-base_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
-os.chdir("/")
-
-class DevserverTest(unittest.TestCase):
- """Regressions tests for miniomaha."""
-
- def setUp(self):
- """Copies in testing files."""
-
- # Copy in developer-test.gz, as "static/" directory is hardcoded, and it
- # would be very hard to change it (static file serving is handled deep
- # inside webpy).
- self.image_src = os.path.join(base_dir, TEST_IMAGE)
- self.image = os.path.join(base_dir, STATIC_DIR, TEST_IMAGE_NAME)
- if os.path.exists(self.image):
- os.unlink(self.image)
- shutil.copy(self.image_src, self.image)
-
- self.factory_config = os.path.join(base_dir, TEST_FACTORY_CONFIG)
-
- def tearDown(self):
- """Removes testing files."""
- if os.path.exists(self.image):
- os.unlink(self.image)
-
- def testValidateFactoryConfig(self):
- """Tests --validate_factory_config."""
- cmd = [
- 'python',
- os.path.join(base_dir, 'miniomaha.py'),
- '--validate_factory_config',
- '--factory_config', self.factory_config,
- ]
- process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
- stdout, _ = process.communicate()
- self.assertEqual(0, process.returncode)
- self.assertTrue('Config file looks good.' in stdout)
-
- def _StartServer(self, data_dir=''):
- """Starts miniomaha, returns process."""
- cmd = [
- 'python',
- os.path.join(base_dir, 'miniomaha.py'),
- 'miniomaha.py',
- '--factory_config', self.factory_config,
- ]
- if data_dir:
- cmd.append('--data_dir')
- cmd.append(data_dir)
- process = subprocess.Popen(cmd)
- return process.pid
-
- def testHandleUpdate(self):
- """Tests running the server and getting an update."""
- pid = self._StartServer()
- try:
- # Wait for the server to start up.
- time.sleep(1)
- request = urllib2.Request(UPDATE_URL, UPDATE_REQUEST)
- connection = urllib2.urlopen(request)
- response = connection.read()
- connection.close()
- self.assertNotEqual('', response)
-
- # Parse the response and check if it contains the right result.
- dom = minidom.parseString(response)
- update = dom.getElementsByTagName('updatecheck')[0]
-
- codebase = update.getAttribute('codebase')
- self.assertEqual('http://127.0.0.1:8080/static/' + TEST_IMAGE_NAME,
- codebase)
-
- hash_value = update.getAttribute('hash')
- self.assertEqual('kGcOinJ0vA8vdYX53FN0F5BdwfY=', hash_value)
-
- # Try to fetch the image.
- connection = urllib2.urlopen(codebase)
- contents = connection.read()
- connection.close()
- self.assertEqual('Developers, developers, developers!\n', contents)
- finally:
- os.kill(pid, signal.SIGKILL)
-
- def testHandleDatadirUpdate(self):
- """Tests getting an update from a specified datadir"""
- # Push the image to the expected path where miniomaha picks it up.
- image_path = os.path.join(TEST_DATA_PATH, STATIC_DIR)
- if not os.path.exists(image_path):
- os.makedirs(image_path)
-
- foreign_image = os.path.join(image_path, TEST_IMAGE_NAME)
- if os.path.exists(foreign_image):
- os.unlink(foreign_image)
- shutil.copy(self.image_src, foreign_image)
-
- pid = self._StartServer(data_dir=TEST_DATA_PATH)
- try:
- # Wait for the server to start up.
- time.sleep(1)
-
- request = urllib2.Request(UPDATE_URL, UPDATE_REQUEST)
- connection = urllib2.urlopen(request)
- response = connection.read()
- connection.close()
- self.assertNotEqual('', response)
-
- # Parse the response and check if it contains the right result.
- dom = minidom.parseString(response)
- update = dom.getElementsByTagName('updatecheck')[0]
-
- codebase = update.getAttribute('codebase')
- self.assertEqual('http://127.0.0.1:8080/static/' + TEST_IMAGE_NAME,
- codebase)
-
- hash_value = update.getAttribute('hash')
- self.assertEqual('kGcOinJ0vA8vdYX53FN0F5BdwfY=', hash_value)
-
- # Try to fetch the image.
- connection = urllib2.urlopen(codebase)
- contents = connection.read()
- connection.close()
- self.assertEqual('Developers, developers, developers!\n', contents)
- os.unlink(foreign_image)
- finally:
- os.kill(pid, signal.SIGKILL)
-
- def testApiBadSetNextUpdateRequest(self):
- """Tests sending a bad setnextupdate request."""
- pid = self._StartServer()
- try:
- # Wait for the server to start up.
- time.sleep(1)
-
- # Send bad request and ensure it fails...
- try:
- request = urllib2.Request(API_SET_UPDATE_URL, '')
- connection = urllib2.urlopen(request)
- connection.read()
- connection.close()
- self.fail('Invalid setnextupdate request did not fail!')
- except urllib2.URLError:
- pass
- finally:
- os.kill(pid, signal.SIGKILL)
-
- def testApiBadSetNextUpdateURL(self):
- """Tests contacting a bad setnextupdate url."""
- pid = self._StartServer()
- try:
- # Wait for the server to start up.
- time.sleep(1)
-
- # Send bad request and ensure it fails...
- try:
- connection = urllib2.urlopen(API_SET_UPDATE_BAD_URL)
- connection.read()
- connection.close()
- self.fail('Invalid setnextupdate url did not fail!')
- except urllib2.URLError:
- pass
- finally:
- os.kill(pid, signal.SIGKILL)
-
- def testApiBadHostInfoURL(self):
- """Tests contacting a bad hostinfo url."""
- pid = self._StartServer()
- try:
- # Wait for the server to start up.
- time.sleep(1)
-
- # Send bad request and ensure it fails...
- try:
- connection = urllib2.urlopen(API_HOST_INFO_BAD_URL)
- connection.read()
- connection.close()
- self.fail('Invalid hostinfo url did not fail!')
- except urllib2.URLError:
- pass
- finally:
- os.kill(pid, signal.SIGKILL)
-
- def testApiHostInfoAndSetNextUpdate(self):
- """Tests using the setnextupdate and hostinfo api commands."""
- pid = self._StartServer()
- try:
- # Wait for the server to start up.
- time.sleep(1)
-
- # Send setnextupdate command.
- request = urllib2.Request(API_SET_UPDATE_URL, API_SET_UPDATE_REQUEST)
- connection = urllib2.urlopen(request)
- response = connection.read()
- connection.close()
-
- # Send hostinfo command and verify the setnextupdate worked.
- connection = urllib2.urlopen(API_HOST_INFO_URL)
- response = connection.read()
- connection.close()
-
- self.assertEqual(
- json.loads(response)['forced_update_label'], API_SET_UPDATE_REQUEST)
- finally:
- os.kill(pid, signal.SIGKILL)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/factory_setup/mk_memento_images.sh b/factory_setup/mk_memento_images.sh
deleted file mode 100755
index ab28bb3..0000000
--- a/factory_setup/mk_memento_images.sh
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2011 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 takes a path to a rootfs.ext2 which was generated by
-# build_image.sh and generates an image that can be used for auto
-# update.
-
-. "$(dirname "$(readlink -f "$0")")/factory_common.sh" || exit 1
-
-set -e
-# We need 2-3 non-zero parameters.
-if [ "$#" -lt 2 ] || [ "$#" -gt 3 ] || [ -z "$1" ] || [ -z "$2" ]; then
- echo "
-Usage: $0 kernel_partition_img[:index] rootfs_partition_img[:index] \
- [output_file]
-
- Input parameters may be either a simple partition image file, or a
- disk image file name followed by ':' and target partition index number
-
- If output_file is omitted, the folder of kernel_partition_img will be
- used, and the output file will be named as 'update.gz'.
-
-Examples:
- $0 part_2 part_3
- $0 chromiumos_image.bin:2 part3
- $0 chromiumos_image.bin:2 otherimage.bin:3 /tmp/myoutput
- "
- exit 1
-fi
-
-if ! image_has_command pigz; then
- (echo "WARNING:"
- echo " Your system does not have pigz (parallel gzip) installed."
- echo " COMPRESSING WILL BE VERY SLOW. It is recommended to install pigz"
- if image_has_command apt-get; then
- echo " by 'sudo apt-get install pigz'."
- elif image_has_command emerge; then
- echo " by 'sudo emerge pigz'."
- fi) >&2
-fi
-
-if [ $(whoami) = "root" ]; then
- echo "running $0 as root which is unneccessary"
-fi
-
-# Usage: load_partition_file VARIABLE_NAME_PREFIX partition_file
-# Writes VARIABLE_NAME_PREFIX[, _OFFSE, _SIZE, _SECTORS] by parsing
-# partition_file, which can be a simple file or image:partno.
-load_partition_file() {
- local var_prefix="$1"
- local var="$2"
- local var_offset=""
- local var_size=""
- local var_sectors=""
- local part_no="${var##*:}"
-
- # test if var is in image:partno format.
- if [ "$part_no" != "$var" ]; then
- var="${var%:*}"
- else
- part_no=""
- fi
-
- if [ -z "$part_no" ]; then
- var_offset=0
- var_size="$(stat -c"%s" "$var")" ||
- image_die "Invalid file: $var"
- var_sectors="$((var_size / 512))"
- else
- var_offset="$(image_part_offset "$var" "$part_no")" ||
- image_die "Cannot retieve offset for partition $var:$part_no"
- var_sectors="$(image_part_size "$var" "$part_no")" ||
- image_die "Cannot retieve size for partition $var:$part_no"
- var_size=$((var_sectors * 512))
- fi
-
- # publish the values
- eval "${var_prefix}"="$var"
- eval "${var_prefix}_OFFSET"="$var_offset"
- eval "${var_prefix}_SIZE"="$var_size"
- eval "${var_prefix}_SECTORS"="$var_sectors"
-}
-
-load_partition_file KPART "$1"
-load_partition_file ROOTFS "$2"
-
-# Sanity check size.
-if [ "$KPART_SIZE" -gt $((16 * 1024 * 1024)) ]; then
- echo "Kernel partition size ($KPART_SIZE bytes) greater than 16 MiB."
- echo "That's too big."
- exit 1
-fi
-
-if [ "$#" = "3" ]; then
- FINAL_OUT_FILE="$(readlink -f $3)"
-else
- FINAL_OUT_FILE="$(dirname "$(readlink -f $1)")/update.gz"
-fi
-echo "Output: $FINAL_OUT_FILE"
-
-# Update payload format:
-# [kernel_size: big-endian uint64][kernel_blob][rootfs_blob]
-
-# Prepare kernel_size by using printf as a number like 00000000003d0900, then
-# sed to convert as: \x00\x00\x00\x00\x00\x3d\x09\x00, finally echo -e to
-# convert into binary.
-KPART_SIZE_SIGNATURE="$(printf "%016x" "$KPART_SIZE" |
- sed 's/\([0-9a-f][0-9a-f]\)/\\x\1/g')"
-
-# Build the blob!
-CS_AND_RET_CODES="$(
- (echo -en "$KPART_SIZE_SIGNATURE"
- echo "Compressing kernel..." >&2
- image_dump_partial_file "$KPART" "$KPART_OFFSET" "$KPART_SECTORS"
- echo "Compressing rootfs..." >&2
- image_dump_partial_file "$ROOTFS" "$ROOTFS_OFFSET" "$ROOTFS_SECTORS") |
- image_gzip_compress -c -9 |
- tee "$FINAL_OUT_FILE" |
- openssl sha1 -binary |
- openssl base64 |
- tr '\n' ' '
- echo ${PIPESTATUS[*]})"
-
-EXPECTED_RET_CODES="0 0 0 0 0 0"
-set -- $CS_AND_RET_CODES
-CALC_CS="$1"
-shift
-RET_CODES="$@"
-if [ "$RET_CODES" != "$EXPECTED_RET_CODES" ]; then
- echo compression/hash failed. $RET_CODES
- exit 1
-fi
-
-echo Success. hash is "$CALC_CS"
diff --git a/factory_setup/mount_partition.sh b/factory_setup/mount_partition.sh
deleted file mode 100755
index 61febf5..0000000
--- a/factory_setup/mount_partition.sh
+++ /dev/null
@@ -1,54 +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.
-
-# Script to mount a partition chromiumos image.
-# Rootfs with ext2 RO-bit turned on will be mounted with read-only flags,
-# and other kinds of file systems will be mounted in read-writable mode.
-
-. "$(dirname "$(readlink -f "$0")")/factory_common.sh" || exit 1
-
-main() {
- set -e
-
- # Check parameter and environment.
- if [ "$#" != 3 ]; then
- die "Usage: $0 cros_image_file partition_index mount_point
-
- Ex: $0 chromiumos_image.bin 3 /media"
- fi
- if ! image_has_part_tools; then
- die "Missing partition tools. Please install cgpt/parted, or run in chroot."
- fi
-
- local image_file="$1"
- local partition_index="$2"
- local mount_point="$3"
-
- # Basic checking
- [ -f "$image_file" ] || die "Cannot find image file: $image_file"
- [ -d "$mount_point" ] || die "Invalid mount point: $mount_point"
-
- # Check image format.
- local part_offset="$(
- image_part_offset "$image_file" "$partition_index" 2>/dev/null)" || true
- if [ -z "$part_offset" ] || [ "$part_offset" -le "0" ]; then
- die "Invalid image file $image_file for partition #$partition_index."
- fi
-
- # Try to mount with default options, or RO+ext2 if that failed.
- if ! image_mount_partition "$image_file" "$partition_index" "$mount_point" \
- "rw" "" 2>/dev/null; then
- # "-t ext2" must be explicitly specified otherwise ext4+ file system module
- # may change some meta data inside superblock, even in read-only mode.
- image_mount_partition "$image_file" "$partition_index" "$mount_point" \
- "ro" "-t ext2" ||
- die "Failed to mount $image_file partition #$partition_index."
- warn "WARNING: PARTITION #$partition_index IS READ-ONLY!"
- fi
- info "Mounted $image_file#$partition_index at $mount_point."
-}
-
-main "$@"
diff --git a/factory_setup/testdata/miniomaha/developer-test.gz b/factory_setup/testdata/miniomaha/developer-test.gz
deleted file mode 100644
index e69f738..0000000
--- a/factory_setup/testdata/miniomaha/developer-test.gz
+++ /dev/null
@@ -1 +0,0 @@
-Developers, developers, developers!
diff --git a/factory_setup/testdata/miniomaha/miniomaha-test.conf b/factory_setup/testdata/miniomaha/miniomaha-test.conf
deleted file mode 100644
index 09c545e..0000000
--- a/factory_setup/testdata/miniomaha/miniomaha-test.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-config = [
- {
- 'qual_ids': set(["x86-generic"]),
- 'developer_image': 'developer-test.gz',
- 'developer_checksum': 'kGcOinJ0vA8vdYX53FN0F5BdwfY=',
- },
-]
diff --git a/factory_setup/update_firmware_vars.py b/factory_setup/update_firmware_vars.py
deleted file mode 100755
index fc48071..0000000
--- a/factory_setup/update_firmware_vars.py
+++ /dev/null
@@ -1,540 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2011 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.
-
-"""Update environment variables in a legacy_image.bin."""
-
-import copy
-import optparse
-import os
-import shutil
-import struct
-import subprocess
-import sys
-import zlib
-
-
-# Some environment variables are "first class"--you can set them with simple
-# command line options. Those are listed here with the mapping for how to
-# change the command-line option into an environment variable.
-OPTION_ENVIRONMENT_VARS = {
- 'tftpserverip': 'tftpserverip=%s',
-}
-
-# Some kernel arguments are also "first class". They are listed here.
-OPTION_KERNEL_ARGS = {
- 'omahaserver': 'omahaserver=%s',
- 'board': 'cros_board=%s',
-}
-
-# This is the environment we'll write, which tells to merge this environment
-# with whatever is stored in u-boot as the "default" environment.
-DEFAULT_ENV = (
- "merge_with_default=1\0"
-)
-
-# Format of the CRC in the output file.
-CRC_FORMAT = '<i'
-
-
-class ArgumentError(Exception):
- """We'll raise this whenever we have an error that was caused by user-error.
-
- This could be a bad argument or the inability to access a file on the
- filesystem.
- """
- pass
-
-
-class _OptionWithMemsize(optparse.Option):
- """Option subclass that has an additional 'memsize' option.
-
- The memsize option allows you to add a k/m/g suffix to your integers to
- specify KiB, MiB, or GiB.
-
-
- >>> parser = optparse.OptionParser(option_class=_OptionWithMemsize)
- >>> _ = parser.add_option('--test', type='memsize')
-
- # Simple: just a number of bytes...
- >>> opts, args = parser.parse_args(['--test', '999'])
- >>> print opts
- {'test': 999}
-
- # Can do hex number of bytes...
- >>> opts, args = parser.parse_args(['--test', '0x1000'])
- >>> print opts
- {'test': 4096}
-
- # Kilobyte suffix...
- >>> opts, args = parser.parse_args(['--test', '1k'])
- >>> print opts
- {'test': 1024}
-
- # Can handle hex and upper-case suffix too..
- >>> opts, args = parser.parse_args(['--test', '0xfK'])
- >>> print opts
- {'test': 15360}
-
- # Check other suffixes
- >>> opts, args = parser.parse_args(['--test', '1m'])
- >>> print opts
- {'test': 1048576}
- >>> opts, args = parser.parse_args(['--test', '1g'])
- >>> print opts
- {'test': 1073741824}
-
- # Negative test cases; need to quiet stderr first...
- >>> import StringIO
- >>> _oldstderr = sys.stderr
- >>> sys.stderr = StringIO.StringIO()
- >>> opts, args = parser.parse_args(['--test', 'hello'])
- Traceback (most recent call last):
- ...
- SystemExit: 2
- >>> opts, args = parser.parse_args(['--test', ''])
- Traceback (most recent call last):
- ...
- SystemExit: 2
- >>> sys.stderr = _oldstderr
- """
-
- @staticmethod
- def _CheckMemsize(option, opt, value):
- """Check that a 'memsize' option to optparse is good.
-
- Args:
- option: See optparse manual.
- opt: Option name we're parsing; See optparse manual.
- value: Value we're parsing; See optparse manual.
- Returns:
- value: The parsed value.
- Raises:
- OptionValueError: Upon error
- """
- # Note: purposely no 'b' suffix, since that makes 0x12b ambiguous.
- multiplier_table = [
- ('g', 1024 * 1024 * 1024),
- ('m', 1024 * 1024),
- ('k', 1024),
- ('', 1),
- ]
- for (suffix, multiplier) in multiplier_table:
- if value.lower().endswith(suffix):
- new_value = value
- if suffix:
- new_value = new_value[:-len(suffix)]
- try:
- # Convert w/ base 0 (handles hex, binary, octal, etc)
- return int(new_value, 0) * multiplier
- except ValueError:
- # Pass and try other suffixes; not useful now, but may be useful
- # later if we ever allow B vs. GB vs. GiB.
- pass
- raise optparse.OptionValueError("option %s: invalid memsize value: %r" %
- (opt, value))
-
- TYPES = optparse.Option.TYPES + ('memsize',)
- TYPE_CHECKER = copy.copy(optparse.Option.TYPE_CHECKER)
-_OptionWithMemsize.TYPE_CHECKER['memsize'] = _OptionWithMemsize._CheckMemsize
-
-
-def _GetSpecialEnvVars(opts):
- """Grab env vars that the user can set directly via command-line options.
-
- >>> class FakeOpts(object): pass
- >>> opts = FakeOpts()
- >>> opts.tftpserverip = None
-
- >>> _GetSpecialEnvVars(opts)
- []
-
- >>> opts.tftpserverip = "1.2.3.4"
- >>> sorted(_GetSpecialEnvVars(opts))
- ['tftpserverip=1.2.3.4']
-
- Args:
- opts: The options from the option parser.
-
- Returns:
- vars: A list of 'key=value' strings for u-boot environment variables.
- """
- vars = []
- for opt_name, value in OPTION_ENVIRONMENT_VARS.iteritems():
- if getattr(opts, opt_name):
- vars.append(OPTION_ENVIRONMENT_VARS[opt_name] % getattr(opts, opt_name))
- return vars
-
-
-def _GetSpecialKernelArgs(opts):
- """Grab kernel args that the user can set directly via command-line options.
-
- >>> class FakeOpts(object): pass
- >>> opts = FakeOpts()
- >>> opts.omahaserver = None
- >>> opts.board = None
-
- >>> _GetSpecialKernelArgs(opts)
- []
-
- >>> opts.omahaserver = "3.4.5.6"
- >>> sorted(_GetSpecialKernelArgs(opts))
- ['omahaserver=3.4.5.6']
-
- >>> opts.board = "tegra2_kaen-gobi"
- >>> sorted(_GetSpecialKernelArgs(opts))
- ['cros_board=tegra2_kaen-gobi', 'omahaserver=3.4.5.6']
-
- Args:
- opts: The options from the option parser.
-
- Returns:
- vars: A list of strings that will eventually be joined with space to create
- the kernel command line.
- """
- vars = []
- for opt_name, value in OPTION_KERNEL_ARGS.iteritems():
- if getattr(opts, opt_name):
- vars.append(OPTION_KERNEL_ARGS[opt_name] % getattr(opts, opt_name))
- return vars
-
-
-def _BuildEnvironment(env_vars, kernel_args, env_size):
- """Build up the u-boot environment string.
-
- >>> s = _BuildEnvironment(['a=b', 'c=d'], ['noinitrd', 'x=y'], 0x100)
- >>> len(s)
- 256
-
- >>> _ParseEnvStr(s)
- ['merge_with_default=1', 'a=b', 'c=d', 'extra_bootargs=noinitrd x=y']
-
- Args:
- env_vars: List of env_vars to put in the environment (after the default).
- env_size: Final size of the environment.
-
- Returns:
- env_str: The environment string for u-boot, including checksum.
- """
- assert DEFAULT_ENV.endswith('\0')
-
- # Add the command-line args in through extra_bootargs
- if kernel_args:
- env_vars += ['extra_bootargs=%s' % (' '.join(kernel_args))]
-
- env_str = DEFAULT_ENV + '\0'.join(env_vars)
-
- # Pad to full size...
- padding_bytes = env_size - struct.calcsize(CRC_FORMAT) - len(env_str)
- if padding_bytes < 0:
- raise ArgumentError("Environment %d bytes too big" % -padding_bytes)
- env_str += '\0' * padding_bytes
-
- # Add in the CRC.
- crc = zlib.crc32(env_str)
- crc_str = struct.pack(CRC_FORMAT, crc)
-
- return crc_str + env_str
-
-
-def _ParseEnvStr(env_str):
- """Read an environment string and return variables in it.
-
- # Test corrupt case; valid case is tested by _BuildEnvironment()
- >>> _ParseEnvStr('hello; this is not valid') is None
- True
-
- Args:
- env_str: The string to read
-
- Returns:
- env_vars: The variables in the string, or None if the CRC was bad.
- """
- crc_bytes = struct.calcsize(CRC_FORMAT)
-
- stored_crc, = struct.unpack(CRC_FORMAT, env_str[:crc_bytes])
- env_str = env_str[crc_bytes:]
- calc_crc = zlib.crc32(env_str)
-
- if stored_crc != calc_crc:
- return None
-
- return env_str.rstrip('\0').split('\0')
-
-
-def _MakeOutput(input_path, output_path, fw_size):
- """Make and open the output file.
-
- Handles copying the input file to the output file (if the user desires that)
- and also padding.
-
- # Doctests; for tests below...
- # file 1: 0x1000 of zeros
- # file 2: should be a copy of file 1
- # file 3: 0x1000 of 0xff, eventually padded to 0x2000 with 0s.
- # file 4: copy of file 3 padded to 0x2000 with 0s.
- >>> import tempfile
- >>> work_dir = tempfile.mkdtemp('doctest')
- >>> path1 = os.path.join(work_dir, '1.bin')
- >>> path2 = os.path.join(work_dir, '2.bin')
- >>> path3 = os.path.join(work_dir, '3.bin')
- >>> path4 = os.path.join(work_dir, '4.bin')
- >>> open(path1, 'wb').write(chr(0) * 0x1000)
- >>> open(path3, 'wb').write(chr(0xff) * 0x1000)
-
- # Try making a copy: from 1 to 2
- >>> s = _MakeOutput(path1, path2, 0x1000).read()
- >>> len(s) == 0x1000
- True
- >>> s == chr(0) * 0x1000
- True
-
- # No-op (just opens file); tell it to pad the size it already is.
- >>> s = _MakeOutput(path1, None, 0x1000).read()
- >>> len(s) == 0x1000
- True
- >>> s == chr(0) * 0x1000
- True
-
- # Try padding w/ a copy
- >>> s = _MakeOutput(path3, path4, 0x2000).read()
- >>> len(s) == 0x2000
- True
- >>> s == (chr(0xff) * 0x1000) + (chr(0) * 0x1000)
- True
-
- # Try padding w/out a copy
- >>> s = _MakeOutput(path3, None, 0x2000).read()
- >>> len(s) == 0x2000
- True
- >>> s == (chr(0xff) * 0x1000) + (chr(0) * 0x1000)
- True
-
- # Double-check sizes
- >>> os.path.getsize(path1) == 0x1000
- True
- >>> os.path.getsize(path2) == 0x1000
- True
- >>> os.path.getsize(path3) == 0x2000
- True
- >>> os.path.getsize(path4) == 0x2000
- True
-
-
- Args:
- input_path: Path the the input firmware file.
- output_path: Path to the output firmware file; if None/blank we'll modify
- the input in place.
- fw_size: If non-None, we'll pad to this many bytes.
-
- Returns:
- outfile: The output file. Already contains the input and has been padded.
- Left seeked at 0.
- """
- if not output_path:
- output_path = input_path
- else:
- output_dir = os.path.dirname(output_path)
- if not os.path.isdir(output_dir):
- raise ArgumentError("The destination directory %s doesn't exist" %
- output_dir)
-
- try:
- shutil.copy(input_path, output_path)
- except IOError, e:
- raise ArgumentError("Problem copying input to output: %s" % str(e))
-
- try:
- outfile = open(output_path, 'r+b')
- except IOError, e:
- raise ArgumentError("Problem opening output file: %s" % str(e))
-
- if fw_size:
- old_size = os.path.getsize(output_path)
- if fw_size < old_size:
- raise ArgumentError("Can't specify firmware size smaller than input")
-
- padding_bytes = fw_size - old_size
- if padding_bytes:
- outfile.seek(0, os.SEEK_END)
- outfile.write('\0' * padding_bytes)
- outfile.seek(0)
-
- return outfile
-
-
-def _GetEnvVarAddr(image_file):
- """Get environment variable section address from FMAP.
-
- Args:
- image_file: The image file to look for environment variable section.
-
- Returns:
- The address of RW_ENVIRONMENT section is returned.
- """
- try:
- command = ["dump_fmap", "-p", image_file.name, "RW_ENVIRONMENT"]
- stream = subprocess.Popen(command, stdout=subprocess.PIPE)
- result = stream.communicate()[0].split()
- if len(result) == 0:
- raise ArgumentError("Cannot find RW_ENVIRONMENT section in FMAP.")
- addr = int(result[1])
- return addr
- except OSError:
- raise ArgumentError("Error calling dump_fmap.")
-
-
-def _PutEnvInFile(outfile, env_str, clobber_ok):
- """Put the given environment into the output file.
-
- At the moment, this just crams the env_str to the end of the file.
-
- # Sample call with a fake (all zero) file.
- >>> import StringIO
- >>> FILE_SIZE=0x10000
- >>> f = StringIO.StringIO(chr(0) * FILE_SIZE)
- >>> env_str = _BuildEnvironment([], [], 0x100)
- >>> _PutEnvInFile(f, env_str, False)
- >>> s = f.getvalue()
-
- # File should have kept the same size.
- >>> len(s) == FILE_SIZE
- True
-
- # File should end with env_str and start with '\0'
- >>> s[:-0x100].strip(chr(0))
- ''
- >>> s[-0x100:] == env_str
- True
-
- # Running again should get an error if clobbering not OK.
- >>> _PutEnvInFile(f, env_str, False)
- Traceback (most recent call last):
- ...
- ArgumentError: Old arguments will be clobbered; pass --force if OK
-
- # Should be OK if clobbering OK
- >>> _PutEnvInFile(f, env_str, True)
- >>> s_new = f.getvalue()
- >>> s == s_new
- True
-
- Args:
- outfile: An already opened file.
- env_str: The str to store.
- clobber_ok: If True, it's OK to clobber the old environment; if False we'll
- raise an exception if we detect and old environment.
- """
- env_size = len(env_str)
- addr = _GetEnvVarAddr(outfile)
- outfile.seek(addr, os.SEEK_SET)
-
- old_env_str = outfile.read(env_size)
- if old_env_str != ('\0' * env_size):
- old_env = _ParseEnvStr(old_env_str)
-
- # If we get here, our old env section was neither zeros nor valid.
- # that probably means that we either had an unpadded firmware image as
- # input or a completely bogus input file.
- if old_env is None:
- raise ArgumentError("Previous vars were not zero nor valid")
-
- if not clobber_ok:
- raise ArgumentError("Old arguments will be clobbered; pass --force if OK")
-
- outfile.seek(addr, os.SEEK_SET)
- outfile.write(env_str)
-
-
-def _ParseOptions():
- """Parse command-line arguments.
-
- Returns:
- opts: Options from optparse.OptionParser.
- """
- parser = optparse.OptionParser(description=__doc__,
- option_class=_OptionWithMemsize)
-
- parser.add_option('--env-size', dest='env_size', default=0x1000,
- type='memsize',
- help='If specified, overrides the default env_size that '
- 'u-boot expects')
- parser.add_option('--fw-size', dest='fw_size', default=None, type='memsize',
- help='If specified, firmware will be padded to be this '
- 'many bytes')
- parser.add_option('--input', '-i', dest='input', default=None,
- help='Path to the firmware to modify; required')
- parser.add_option('--output', '-o', dest='output', default=None,
- help='Path to store output; if not specified we will '
- 'directly modify the input file')
- parser.add_option('--force', '-f', dest='force', default=False,
- action='store_true',
- help='Bypass ignorable errors')
-
- # Special-case options to make things simpler for factory. Must match
- # OPTION_ENVIRONMENT_VARS and OPTION_KERNEL_ARGS
- parser.add_option('--tftpserverip', default=None,
- help='Set the TFTP server IP address')
-
- parser.add_option('--board', default=None,
- help='Set the cros_board to be passed into the kernel')
- parser.add_option('--omahaserver', default=None,
- help='Set the Omaha server IP address')
-
- parser.add_option('--var', default=[], dest='vars', metavar='var',
- action='append',
- help='Set any arbitrary u-boot var using format arg=value')
- parser.add_option('--arg', default=[], dest='args', metavar='arg',
- action='append',
- help='Set any arbitrary kernel command line arg')
-
- opts, args = parser.parse_args()
- if args:
- raise ArgumentError('Unexpected argument(s): %s' % ', '.join(args))
-
- if not opts.input:
- raise ArgumentError("You must specify the input image")
-
- return opts
-
-
-def main():
- """Main function."""
- prog_name = os.path.basename(sys.argv[0])
-
- try:
- opts = _ParseOptions()
- try:
- print 'Input: %s (0x%08x bytes)' % (opts.input,
- os.path.getsize(opts.input))
- except OSError:
- raise ArgumentError("Error accessing input image: %s" % opts.input)
-
- env_vars = opts.vars + _GetSpecialEnvVars(opts)
- kernel_args = opts.args + _GetSpecialKernelArgs(opts)
- env_str = _BuildEnvironment(env_vars, kernel_args, opts.env_size)
- outfile = _MakeOutput(opts.input, opts.output, opts.fw_size)
- _PutEnvInFile(outfile, env_str, opts.force)
-
- print 'Output: %s (0x%08x bytes)' % (outfile.name,
- os.path.getsize(outfile.name))
- print '\n '.join(['Stored env:'] + env_vars)
- except ArgumentError, e:
- print >>sys.stderr, "%s: error: %s" % (prog_name, str(e))
- sys.exit(1)
-
-
-def _Test(verbose=''):
- """Run any built-in tests."""
- import doctest
- assert verbose in ('', '-v')
- doctest.testmod(verbose=(verbose == '-v'))
-
-
-if __name__ == '__main__':
- if sys.argv[1:2] == ["--test"]:
- _Test(*sys.argv[2:])
- else:
- main()