1#!/bin/bash
2#
3# Copyright 2021 The ChromiumOS Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# This is a generic ChromeOS package/image test setup script. It is meant to
8# be used for either the object file or package bisection tools. This script
9# does one of the following depending on what ${BISECT_MODE} is set to:
10#
11# 1) ${BISECT_MODE} is PACKAGE_MODE:
12#   build_image is called and generates a new ChromeOS image using whatever
13#   packages are currently in the build tree. This image is then pushed to the
14#   remote machine using flash over ethernet (or usb flash if ethernet flash
15#   fails).
16#
17# 2) ${BISECT_MODE} is OBJECT_MODE:
18#   emerge is called for ${BISECT_PACKAGE} and generates a build for said
19#   package. This package is then deployed to the remote machine and the machine
20#   is rebooted. If deploying fails then a new ChromeOS image is built from
21#   scratch and pushed to the machine like in PACKAGE_MODE.
22#
23# This script is intended to be used by binary_search_state.py, as
24# part of the binary search triage on ChromeOS objects and packages. It should
25# return '0' if the setup succeeds; and '1' if the setup fails (the image
26# could not build or be flashed).
27#
28
29export PYTHONUNBUFFERED=1
30
31source common/common.sh
32
33usb_flash()
34{
35  echo
36  echo "Insert a usb stick into the current machine"
37  echo "Note: The cros flash will take time and doesn't give much output."
38  echo "      Be patient. If your usb access light is flashing it's working."
39  sleep 1
40  read -p "Press enter to continue" notused
41
42  cros flash --board=${BISECT_BOARD} --clobber-stateful usb:// ~/trunk/src/build/images/${BISECT_BOARD}/latest/chromiumos_test_image.bin
43
44  echo
45  echo "Flash to usb complete!"
46  echo "Plug the usb into your chromebook and install the image."
47  echo "Refer to the ChromiumOS Developer's Handbook for more details."
48  echo "http://www.chromium.org/chromium-os/developer-guide#TOC-Boot-from-your-USB-disk"
49  while true; do
50    sleep 1
51    read -p "Was the installation of the image successful? " choice
52    case $choice in
53        [Yy]*) return 0;;
54        [Nn]*) return 1;;
55        *) echo "Please answer y or n.";;
56    esac
57  done
58}
59
60ethernet_flash()
61{
62  echo
63  echo "Please ensure your Chromebook is up and running Chrome so"
64  echo "cros flash may run."
65  echo "If your Chromebook has a broken image you can try:"
66  echo "1. Rebooting your Chromebook 6 times to install the last working image"
67  echo "2. Alternatively, running the following command on the Chromebook"
68  echo "   will also rollback to the last working image:"
69  echo "   'update_engine_client --rollback --nopowerwash --reboot'"
70  echo "3. Flashing a new image through USB"
71  echo
72  sleep 1
73  read -p $'Press enter to continue and retry the ethernet flash' notused
74  cros flash --board=${BISECT_BOARD} --clobber-stateful ${BISECT_REMOTE} ~/trunk/src/build/images/${BISECT_BOARD}/latest/chromiumos_test_image.bin
75}
76
77reboot()
78{
79  ret_val=0
80  pushd ~/trunk/src/scripts > /dev/null
81  set -- --remote=${BISECT_REMOTE}
82  . ./common.sh || ret_val=1
83  . ./remote_access.sh || ret_val=1
84  TMP=$(mktemp -d)
85  FLAGS "$@" || ret_val=1
86  remote_access_init || ret_val=1
87  remote_reboot || ret_val=1
88  popd > /dev/null
89
90  return $ret_val
91}
92
93echo
94echo "INSTALLATION BEGIN"
95echo
96
97if [[ "${BISECT_MODE}" == "OBJECT_MODE" ]]; then
98  echo "EMERGING ${BISECT_PACKAGE}"
99  set -x
100  sudo rm -rf /build/${BISECT_BOARD}/var/cache/portage/*
101  sudo rm -rf /build/${BISECT_BOARD}/tmp/portage/${BISECT_PACKAGE}*
102  set +x
103  if [[ ${BISECT_PACKAGE} == *chromeos-chrome ]]; then
104    if [[ ${BISECT_USE_FLAGS} == *chrome_internal* && \
105      ${BISECT_USE_FLAGS} != *-chrome_internal* ]]; then
106      # for the pre-upload check of the length of lines
107      chrome_build_dir="/var/cache/chromeos-chrome/chrome-src-internal/src/"
108      chrome_build_dir+="out_${BISECT_BOARD}"
109    else
110      # for the pre-upload check of the length of lines
111      chrome_build_dir="/var/cache/chromeos-chrome/chrome-src/src/"
112      chrome_build_dir+="out_${BISECT_BOARD}"
113    fi
114    set -x
115    sudo rm -rf ${chrome_build_dir}
116    set +x
117  fi
118  set -x
119  CLEAN_DELAY=0 emerge-${BISECT_BOARD} -C ${BISECT_PACKAGE}
120  USE="${BISECT_USE_FLAGS}" emerge-${BISECT_BOARD} ${BISECT_PACKAGE}
121  set +x
122  emerge_status=$?
123
124  if [[ ${emerge_status} -ne 0 ]] ; then
125    echo "emerging ${BISECT_PACKAGE} returned a non-zero status: $emerge_status"
126    exit 1
127  fi
128
129  echo
130  echo "DEPLOYING TO ${BISECT_REMOTE}"
131
132  if [[ ${BISECT_PACKAGE} == *chromeos-kernel-* ]]; then
133    cmd="/mnt/host/source/src/scripts/update_kernel.sh --board=${BISECT_BOARD} --remote=${BISECT_REMOTE}"
134    if [[ ${BISECT_REMOTE} == *:* ]]; then
135      IP=$(echo $1 | cut -d ":" -f1)
136      PORT=$(echo $1 | cut -d ":" -f2)
137      cmd="/mnt/host/source/src/scripts/update_kernel.sh --board=${BISECT_BOARD} --remote=${IP} --ssh_port=${PORT}"
138    fi
139    if [[ ${BISECT_REBOOT_OPTION} == false ]]; then
140      cmd+=" --noreboot"
141    fi
142    set -x
143    # exec the command to make sure it always exit after
144    exec $cmd
145    set +x
146  fi
147
148  if [[ ${BISECT_PACKAGE} == *chromeos-chrome ]]; then
149    # deploy_chrome needs to run inside chrome source tree
150    pushd ~/chrome_root
151    set -x
152    deploy_chrome --force --build-dir=${chrome_build_dir}/Release \
153      --device=${BISECT_REMOTE}
154    set +x
155    popd
156  else
157    set -x
158    cros deploy ${BISECT_REMOTE} ${BISECT_PACKAGE} --log-level=info
159    set +x
160  fi
161  deploy_status=$?
162
163  if [[ ${BISECT_REBOOT_OPTION} == false ]]; then
164    exit 0
165  fi
166
167  if [[ ${deploy_status} -eq 0 ]] ; then
168    echo "Deploy successful. Rebooting device..."
169    reboot
170    if [[ $? -ne 0 ]] ; then
171      echo
172      echo "Could not automatically reboot device!"
173      read -p "Please manually reboot device and press enter to continue" notused
174    fi
175    exit 0
176  fi
177
178  echo "Deploy failed! Trying build_image/cros flash instead..."
179  echo
180fi
181
182echo "BUILDING IMAGE"
183pushd ~/trunk/src/scripts
184USE="${BISECT_USE_FLAGS}" ./build_image test --board=${BISECT_BOARD} \
185  --noenable_rootfs_verification --noeclean
186build_status=$?
187popd
188
189if [[ ${build_status} -eq 0 ]] ; then
190    echo
191    echo "FLASHING"
192    echo "Pushing built image onto device."
193    echo "cros flash --board=${BISECT_BOARD} --clobber-stateful ${BISECT_REMOTE} ~/trunk/src/build/images/${BISECT_BOARD}/latest/chromiumos_test_image.bin"
194    cros flash --board=${BISECT_BOARD} --clobber-stateful ${BISECT_REMOTE} ~/trunk/src/build/images/${BISECT_BOARD}/latest/chromiumos_test_image.bin
195    cros_flash_status=$?
196    while [[ ${cros_flash_status} -ne 0 ]] ; do
197        while true; do
198          echo
199          echo "cros flash has failed! From here you can:"
200          echo "1. Flash through USB"
201          echo "2. Retry flashing over ethernet"
202          echo "3. Abort this installation and skip this image"
203          echo "4. Abort this installation and mark test as failed"
204          sleep 1
205          read -p "Which method would you like to do? " choice
206          case $choice in
207              1) usb_flash && break;;
208              2) ethernet_flash && break;;
209              3) exit 125;;
210              4) exit 1;;
211              *) echo "Please answer 1, 2, 3, or 4.";;
212          esac
213        done
214
215        cros_flash_status=$?
216    done
217else
218    echo "build_image returned a non-zero status: ${build_status}"
219    exit 1
220fi
221
222exit 0
223