| #!/bin/bash |
| |
| # 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 manipulate the tag files in the output of build_image |
| |
| # Load common constants. This should be the first executable line. |
| # The path to common.sh should be relative to your script's location. |
| . "$(dirname "$0")/common.sh" |
| |
| load_shflags |
| |
| DEFINE_string from "chromiumos_image.bin" \ |
| "Input file name of Chrome OS image to tag/stamp." |
| DEFINE_string dev_mode "" \ |
| "(build-info) Tag as a developer mode build (1 to enable, 0 to disable)" |
| DEFINE_string update_firmware "" \ |
| "(auto-update) Force updating firmware (1 to enable, 0 to disable)" |
| DEFINE_string leave_firmware_alone "" \ |
| "(auto-update) For BIOS development use ONLY (1 to enable, 0 to disable)" |
| DEFINE_string leave_core "" \ |
| "(crash-reporter) Leave core dumps (1 to enable, 0 to disable)" |
| |
| # Parameters for manipulating /etc/lsb-release. |
| DEFINE_boolean remove_test_label false \ |
| "(build-info) Remove 'test' suffix in /etc/lsb-release" |
| DEFINE_boolean change_dev_to_beta false \ |
| "(build-info) Change 'dev' -> 'beta' in /etc/lsb-release" |
| |
| |
| # TODO(hungte) we can add factory_installer and factory_test, |
| # but I don't see any reason to tweak/check these values. |
| |
| # Parse command line. |
| FLAGS "$@" || exit 1 |
| eval set -- "${FLAGS_ARGV}" |
| |
| # Abort on error. |
| set -e |
| |
| if [ -z "${FLAGS_from}" ] || [ ! -s "${FLAGS_from}" ] ; then |
| echo "Error: need a valid file by --from" |
| exit 1 |
| fi |
| |
| # Global variable to track if the image is modified. |
| g_modified=${FLAGS_FALSE} |
| |
| # Processes (enable, disable, or simply report) a tag file. |
| # Args: DO_MODIFICATION NAME ROOT TAG_FILE ACTION |
| # |
| # When DO_MODIFICATION=${FLAGS_TRUE}, |
| # Creates (ACTION=1) the TAG_FILE in ROOT, or |
| # removes (ACTION=0) the TAG_FILE in ROOT, then |
| # reports the status (and change) to the tag file. |
| # When DO_MODIFICATION=${FLAGS_FALSE}, |
| # make a dry-run and only change ${g_modified} |
| function process_tag() { |
| local tag_status_text="" |
| local do_modification="$1" |
| local name="$2" |
| local root="$3" |
| local tag_file_path="$3/$4" |
| local action="$5" |
| local do_enable=${FLAGS_FALSE} |
| local do_disable=${FLAGS_FALSE} |
| |
| # only 1, 0, and "" are valid params to action. |
| case "${action}" in |
| "1" ) |
| do_enable=${FLAGS_TRUE} |
| ;; |
| "0" ) |
| do_disable=${FLAGS_TRUE} |
| ;; |
| "" ) |
| ;; |
| * ) |
| echo "Error: invalid param to ${name}: ${action} (must be 1 or 0)." |
| exit 1 |
| ;; |
| esac |
| |
| if [ -f "${tag_file_path}" ]; then |
| tag_status_text="ENABLED" |
| if [ "${do_disable}" = ${FLAGS_TRUE} ]; then |
| # disable the tag |
| if [ "${do_modification}" = ${FLAGS_TRUE} ]; then |
| sudo rm "${tag_file_path}" |
| fi |
| g_modified=${FLAGS_TRUE} |
| tag_status_text="${tag_status_text} => disabled" |
| elif [ "${do_disable}" != ${FLAGS_FALSE} ]; then |
| # internal error |
| echo "Internal error for tag ${name}: need disable param." 1>&2 |
| exit 1 |
| fi |
| else |
| tag_status_text="disabled" |
| if [ "${do_enable}" = ${FLAGS_TRUE} ]; then |
| # enable the tag |
| if [ "${do_modification}" = ${FLAGS_TRUE} ]; then |
| sudo touch "${tag_file_path}" |
| fi |
| g_modified=${FLAGS_TRUE} |
| tag_status_text="${tag_status_text} => ENABLED" |
| elif [ "${do_enable}" != ${FLAGS_FALSE} ]; then |
| # internal error |
| echo "Internal error for tag ${name}: need enable param." 1>&2 |
| exit 1 |
| fi |
| fi |
| |
| # report tag status |
| if [ "${do_modification}" != ${FLAGS_TRUE} ]; then |
| echo "${name}: ${tag_status_text}" |
| fi |
| } |
| |
| # Iterates all tags to a given partition root. |
| # Args: ROOTFS DO_MODIFICATION |
| # |
| # Check process_tag for the meaning of parameters. |
| process_all_tags() { |
| local rootfs="$1" |
| local do_modification="$2" |
| |
| process_tag "${do_modification}" \ |
| "(build-info) dev_mode" \ |
| "${rootfs}" \ |
| /root/.dev_mode \ |
| "${FLAGS_dev_mode}" |
| |
| process_tag "${do_modification}" \ |
| "(auto-update) update_firmware" \ |
| "${rootfs}" \ |
| /root/.force_update_firmware \ |
| "${FLAGS_update_firmware}" |
| |
| process_tag "${do_modification}" \ |
| "(auto-update) leave_firmware_alone" \ |
| "${rootfs}" \ |
| /root/.leave_firmware_alone \ |
| "${FLAGS_leave_firmware_alone}" |
| |
| process_tag "${do_modification}" \ |
| "(crash-reporter) leave_core" \ |
| "${rootfs}" \ |
| /root/.leave_core \ |
| "${FLAGS_leave_core}" |
| } |
| |
| # Iterates through all options for manipulating the lsb-release. |
| # Args: ROOTFS DO_MODIFICATION |
| process_all_lsb_mods() { |
| local rootfs="$1" |
| local do_modifications="$2" |
| local lsb="${rootfs}/etc/lsb-release" |
| local sudo |
| |
| if [ ! -w "${lsb}" ]; then |
| sudo="sudo" |
| fi |
| |
| if [ ${FLAGS_remove_test_label} = ${FLAGS_TRUE} ]; then |
| if grep -wq "test" "${lsb}"; then |
| g_modified=${FLAGS_TRUE} |
| fi |
| if [ ${do_modifications} = ${FLAGS_TRUE} ]; then |
| ${sudo} sed -i 's/\btest\b//' "${lsb}" && |
| restore_lsb_selinux "${lsb}" && |
| echo "Test Label removed from /etc/lsb-release" |
| fi |
| fi |
| |
| if [ ${FLAGS_change_dev_to_beta} = ${FLAGS_TRUE} ]; then |
| if grep -wq "dev" "${lsb}"; then |
| g_modified=${FLAGS_TRUE} |
| fi |
| if [ ${do_modifications} = ${FLAGS_TRUE} ]; then |
| ${sudo} sed -i 's/\bdev\b/beta/' "${lsb}" && |
| restore_lsb_selinux "${lsb}" && |
| echo "Dev Channel Label was changed to Beta" |
| fi |
| fi |
| } |
| |
| |
| IMAGE=$(readlink -f "${FLAGS_from}") |
| if [[ -z "${IMAGE}" || ! -f "${IMAGE}" ]]; then |
| echo "Missing required argument: --from (image to update)" |
| usage |
| exit 1 |
| fi |
| |
| # First round, mount as read-only and check if we need any modifications. |
| loopdev=$(loopback_partscan "${IMAGE}") |
| rootfs=$(make_temp_dir) |
| mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" |
| |
| # we don't have tags in stateful partition yet... |
| # stateful_dir=$(make_temp_dir) |
| # mount_loop_image_partition "${loopdev}" 1 "${stateful_dir}" |
| |
| process_all_tags "${rootfs}" ${FLAGS_FALSE} |
| process_all_lsb_mods "${rootfs}" ${FLAGS_FALSE} |
| |
| if [ ${g_modified} = ${FLAGS_TRUE} ]; then |
| # Remount as RW. We can't use `mount -o rw,remount` because of the bits in |
| # the ext4 header we've set to block that. See enable_rw_mount for details. |
| sudo umount "${rootfs}" |
| mount_loop_image_partition "${loopdev}" 3 "${rootfs}" |
| |
| # second round, apply the modification to image. |
| process_all_tags "${rootfs}" ${FLAGS_TRUE} |
| process_all_lsb_mods "${rootfs}" ${FLAGS_TRUE} |
| |
| # This is supposed to be automatically done in mount_loop_image_partition, |
| # but it's no harm to explicitly make it again here. |
| tag_as_needs_to_be_resigned "${rootfs}" |
| echo "IMAGE IS MODIFIED. PLEASE REMEMBER TO RESIGN YOUR IMAGE." |
| else |
| echo "Image is not modified." |
| fi |