| OLD | NEW |
| 1 #!/bin/bash | 1 #!/bin/bash |
| 2 | 2 |
| 3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 # Script to convert the output of build_image.sh to a usb image. | 7 # Script to convert the output of build_image.sh to a usb image. |
| 8 | 8 |
| 9 # Load common constants. This should be the first executable line. | 9 # Load common constants. This should be the first executable line. |
| 10 # The path to common.sh should be relative to your script's location. | 10 # The path to common.sh should be relative to your script's location. |
| 11 . "$(dirname "$0")/common.sh" | 11 . "$(dirname "$0")/common.sh" |
| 12 | 12 |
| 13 # Load functions and constants for chromeos-install |
| 14 . "$(dirname "$0")/chromeos-common.sh" |
| 15 |
| 13 get_default_board | 16 get_default_board |
| 14 | 17 |
| 15 # Flags | 18 # Flags |
| 16 DEFINE_string board "${DEFAULT_BOARD}" "Board for which the image was built" | 19 DEFINE_string board "${DEFAULT_BOARD}" "Board for which the image was built" |
| 17 DEFINE_string from "" \ | 20 DEFINE_string from "" \ |
| 18 "Directory containing rootfs.image and mbr.image" | 21 "Directory containing rootfs.image and mbr.image" |
| 19 DEFINE_string to "" "${DEFAULT_TO_HELP}" | 22 DEFINE_string to "" "${DEFAULT_TO_HELP}" |
| 20 DEFINE_boolean yes ${FLAGS_FALSE} "Answer yes to all prompts" "y" | 23 DEFINE_boolean yes ${FLAGS_FALSE} "Answer yes to all prompts" "y" |
| 21 DEFINE_boolean install_autotest ${FLAGS_FALSE} \ | 24 DEFINE_boolean install_autotest ${FLAGS_FALSE} \ |
| 22 "Whether to install autotest to the stateful partition." | 25 "Whether to install autotest to the stateful partition." |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 if [ ! -d "${FLAGS_from}" ] ; then | 62 if [ ! -d "${FLAGS_from}" ] ; then |
| 60 echo "Cannot find image directory ${FLAGS_from}" | 63 echo "Cannot find image directory ${FLAGS_from}" |
| 61 exit 1 | 64 exit 1 |
| 62 fi | 65 fi |
| 63 | 66 |
| 64 # If to isn't explicitly set | 67 # If to isn't explicitly set |
| 65 if [ -z "${FLAGS_to}" ]; then | 68 if [ -z "${FLAGS_to}" ]; then |
| 66 # Script can be run either inside or outside the chroot. | 69 # Script can be run either inside or outside the chroot. |
| 67 if [ ${INSIDE_CHROOT} -eq 1 ] | 70 if [ ${INSIDE_CHROOT} -eq 1 ] |
| 68 then | 71 then |
| 69 # Inside the chroot, so output to usb.img in the same dir as the other | 72 # Inside the chroot, we'll only output to a file, and we probably already |
| 70 # images. | 73 # have a valid image. Make the user specify a filename. |
| 71 FLAGS_to="${FLAGS_from}/usb.img" | 74 echo "ERROR: Inside the chroot, you must specify a --to FILE to create." |
| 75 exit 1 |
| 72 else | 76 else |
| 73 # Outside the chroot, so output to the default device for a usb key. | 77 # Outside the chroot, so output to the default device for a usb key. |
| 74 FLAGS_to="/dev/sdb" | 78 FLAGS_to="/dev/sdb" |
| 75 fi | 79 fi |
| 76 fi | 80 fi |
| 77 | 81 |
| 78 # Convert args to paths. Need eval to un-quote the string so that shell | 82 # Convert args to paths. Need eval to un-quote the string so that shell |
| 79 # chars like ~ are processed; just doing FOO=`readlink -f ${FOO}` won't work. | 83 # chars like ~ are processed; just doing FOO=`readlink -f ${FOO}` won't work. |
| 80 FLAGS_from=`eval readlink -f ${FLAGS_from}` | 84 FLAGS_from=`eval readlink -f ${FLAGS_from}` |
| 81 FLAGS_to=`eval readlink -f ${FLAGS_to}` | 85 FLAGS_to=`eval readlink -f ${FLAGS_to}` |
| 82 | 86 |
| 83 # Uses this rootfs image as the source image to copy | 87 # Use this image as the source image to copy |
| 84 ROOTFS_IMAGE="${FLAGS_from}/rootfs.image" | 88 SRC_IMAGE="${FLAGS_from}/chromiumos_image.bin" |
| 85 PART_SIZE=$(stat -c%s "${ROOTFS_IMAGE}") # Bytes | |
| 86 | 89 |
| 87 # Setup stateful partition variables | 90 # If we're asked to modify the image for test, then let's make a copy and |
| 88 STATEFUL_IMG="${FLAGS_from}/stateful_partition.image" | 91 # modify that instead. |
| 89 STATEFUL_DIR="${FLAGS_from}/stateful_partition" | 92 if [ ${FLAGS_test_image} -eq ${FLAGS_TRUE} ] ; then |
| 90 | 93 # Copy it. |
| 91 # TODO(sosa@chromium.org) - Remove legacy support. | 94 echo "Creating test image from original..." |
| 92 if [ ! -f "${STATEFUL_IMG}" ] ; then | 95 cp -f "${SRC_IMAGE}" "${FLAGS_from}/chromiumos_test_image.bin" |
| 93 echo "WARNING! Stateful partition not found. Creating clean stateful" | 96 # Use it. |
| 94 STATEFUL_LOOP_DEV=$(sudo losetup -f) | 97 SRC_IMAGE="${FLAGS_from}/chromiumos_test_image.bin" |
| 95 if [ -z "${STATEFUL_LOOP_DEV}" ] ; then | 98 # Modify it. |
| 96 echo "No free loop device. Free up a loop device or reboot. exiting. " | 99 "${SCRIPTS_DIR}/mod_image_for_test.sh" --image "${SRC_IMAGE}" |
| 97 exit 1 | |
| 98 fi | |
| 99 set -x | |
| 100 dd if=/dev/zero of="${STATEFUL_IMG}" bs=1 count=1 \ | |
| 101 seek=$(( (${PART_SIZE} - 1) )) | |
| 102 set +x | |
| 103 trap do_cleanup INT TERM EXIT | |
| 104 sudo losetup "$STATEFUL_LOOP_DEV" "$STATEFUL_IMG" | |
| 105 sudo mkfs.ext3 "$STATEFUL_LOOP_DEV" | |
| 106 sudo tune2fs -L "C-STATE" -c 0 -i 0 "$STATEFUL_LOOP_DEV" | |
| 107 sudo losetup -d "${STATEFUL_LOOP_DEV}" | |
| 108 trap - INT TERM EXIT | |
| 109 fi | 100 fi |
| 110 | 101 |
| 111 # Modifies image for test if requested | 102 STATEFUL_DIR="${FLAGS_from}/stateful_partition" |
| 112 if [ ${FLAGS_test_image} -eq ${FLAGS_TRUE} ] ; then | |
| 113 if [ ! -f "${FLAGS_from}/rootfs_test.image" ] ; then | |
| 114 echo "Test image not found, creating test image from original ... " | |
| 115 cp "${FLAGS_from}/rootfs.image" "${FLAGS_from}/rootfs_test.image" | |
| 116 "${SCRIPTS_DIR}/mod_image_for_test.sh" \ | |
| 117 --image "${FLAGS_from}/rootfs_test.image" | |
| 118 fi | |
| 119 # Use the test image instead | |
| 120 ROOTFS_IMAGE="${FLAGS_from}/rootfs_test.image" | |
| 121 fi | |
| 122 | 103 |
| 123 function do_cleanup { | 104 function do_cleanup { |
| 124 echo "Cleaning loopback devices: ${STATEFUL_LOOP_DEV}" | 105 echo "Cleaning loopback devices: ${STATEFUL_LOOP_DEV}" |
| 125 if [ "${STATEFUL_LOOP_DEV}" != "" ]; then | 106 if [ "${STATEFUL_LOOP_DEV}" != "" ]; then |
| 126 sudo umount "${STATEFUL_DIR}" | 107 sudo umount "${STATEFUL_DIR}" |
| 127 sudo losetup -d "${STATEFUL_LOOP_DEV}" | 108 sudo losetup -d "${STATEFUL_LOOP_DEV}" |
| 128 echo "Cleaned" | 109 echo "Cleaned" |
| 129 fi | 110 fi |
| 130 } | 111 } |
| 131 | 112 |
| 132 function install_autotest { | 113 if [ ${FLAGS_install_autotest} -eq ${FLAGS_TRUE} ] ; then |
| 133 echo "Detecting autotest at ${AUTOTEST_SRC}" | 114 echo "Detecting autotest at ${AUTOTEST_SRC}" |
| 134 if [ -d ${AUTOTEST_SRC} ] | 115 if [ -d ${AUTOTEST_SRC} ] |
| 135 then | 116 then |
| 136 local stateful_loop_dev=$(sudo losetup -f) | 117 # Figure out how to loop mount the stateful partition. It's always |
| 137 local stateful_root="${STATEFUL_DIR}/dev_image" | 118 # partition 1 on the disk image. |
| 119 offset=$(partoffset "${SRC_IMAGE}" 1) |
| 120 |
| 121 stateful_loop_dev=$(sudo losetup -f) |
| 138 if [ -z "${stateful_loop_dev}" ] | 122 if [ -z "${stateful_loop_dev}" ] |
| 139 then | 123 then |
| 140 echo "No free loop device. Free up a loop device or reboot. exiting." | 124 echo "No free loop device. Free up a loop device or reboot. exiting." |
| 141 exit 1 | 125 exit 1 |
| 142 fi | 126 fi |
| 127 STATEFUL_LOOP_DEV=$stateful_loop_dev |
| 143 trap do_cleanup INT TERM EXIT | 128 trap do_cleanup INT TERM EXIT |
| 144 STATEFUL_LOOP_DEV=$stateful_loop_dev | 129 |
| 145 echo "Mounting ${STATEFUL_DIR} loopback" | 130 echo "Mounting ${STATEFUL_DIR} loopback" |
| 146 sudo losetup "${stateful_loop_dev}" "${STATEFUL_DIR}.image" | 131 sudo losetup -o $(( $offset * 512 )) "${stateful_loop_dev}" "${SRC_IMAGE}" |
| 147 sudo mount "${stateful_loop_dev}" "${STATEFUL_DIR}" | 132 sudo mount "${stateful_loop_dev}" "${STATEFUL_DIR}" |
| 148 | 133 stateful_root="${STATEFUL_DIR}/dev_image" |
| 149 echo -ne "Install autotest into stateful partition..." | 134 |
| 150 local autotest_client="/home/autotest-client" | 135 echo "Install autotest into stateful partition..." |
| 151 sudo mkdir -p "${stateful_root}/${autotest_client}" | 136 autotest_client="/home/autotest-client" |
| 137 sudo mkdir -p "${stateful_root}${autotest_client}" |
| 138 |
| 152 sudo cp -fpru ${AUTOTEST_SRC}/client/* \ | 139 sudo cp -fpru ${AUTOTEST_SRC}/client/* \ |
| 153 "${stateful_root}/${autotest_client}" | 140 "${stateful_root}/${autotest_client}" |
| 154 sudo chmod 755 "${stateful_root}/${autotest_client}" | 141 sudo chmod 755 "${stateful_root}/${autotest_client}" |
| 155 sudo chown -R 1000:1000 "${stateful_root}/${autotest_client}" | 142 sudo chown -R 1000:1000 "${stateful_root}/${autotest_client}" |
| 156 | 143 |
| 157 sudo umount ${STATEFUL_DIR} | 144 sudo umount ${STATEFUL_DIR} |
| 158 sudo losetup -d "${stateful_loop_dev}" | 145 sudo losetup -d "${stateful_loop_dev}" |
| 159 trap - INT TERM EXIT | 146 trap - INT TERM EXIT |
| 160 else | 147 else |
| 161 echo "/usr/local/autotest under ${DEFAULT_CHROOT_DIR} is not installed." | 148 echo "/usr/local/autotest under ${DEFAULT_CHROOT_DIR} is not installed." |
| 162 echo "Please call make_autotest.sh inside chroot first." | 149 echo "Please call make_autotest.sh inside chroot first." |
| 163 exit -1 | 150 exit -1 |
| 164 fi | 151 fi |
| 165 } | 152 fi |
| 166 | 153 |
| 167 # Copy MBR and rootfs to output image | 154 |
| 155 # Let's do it. |
| 168 if [ -b "${FLAGS_to}" ] | 156 if [ -b "${FLAGS_to}" ] |
| 169 then | 157 then |
| 170 # Output to a block device (i.e., a real USB key), so need sudo dd | 158 # Output to a block device (i.e., a real USB key), so need sudo dd |
| 171 echo "Copying USB image ${FLAGS_from} to device ${FLAGS_to}..." | 159 echo "Copying USB image ${SRC_IMAGE} to device ${FLAGS_to}..." |
| 172 | 160 |
| 173 # Warn if it looks like they supplied a partition as the destination. | 161 # Warn if it looks like they supplied a partition as the destination. |
| 174 if echo ${FLAGS_to} | grep -q '[0-9]$'; then | 162 if echo "${FLAGS_to}" | grep -q '[0-9]$'; then |
| 175 local drive=$(echo ${FLAGS_to} | sed -re 's/[0-9]+$//') | 163 local drive=$(echo "${FLAGS_to}" | sed -re 's/[0-9]+$//') |
| 176 if [ -b "${drive}" ]; then | 164 if [ -b "${drive}" ]; then |
| 177 echo | 165 echo |
| 178 echo "NOTE: It looks like you may have supplied a partition as the " | 166 echo "NOTE: It looks like you may have supplied a partition as the " |
| 179 echo "destination. This script needs to write to the drive's device " | 167 echo "destination. This script needs to write to the drive's device " |
| 180 echo "node instead (i.e. ${drive} rather than ${FLAGS_to})." | 168 echo "node instead (i.e. ${drive} rather than ${FLAGS_to})." |
| 181 echo | 169 echo |
| 182 fi | 170 fi |
| 183 fi | 171 fi |
| 184 | 172 |
| 185 # Make sure this is really what the user wants, before nuking the device | 173 # Make sure this is really what the user wants, before nuking the device |
| 186 if [ ${FLAGS_yes} -ne ${FLAGS_TRUE} ] | 174 if [ ${FLAGS_yes} -ne ${FLAGS_TRUE} ] |
| 187 then | 175 then |
| 176 sudo fdisk -l "${FLAGS_to}" 2>/dev/null | grep Disk | head -1 |
| 188 echo "This will erase all data on this device:" | 177 echo "This will erase all data on this device:" |
| 189 sudo fdisk -l "${FLAGS_to}" | grep Disk | head -1 | |
| 190 read -p "Are you sure (y/N)? " SURE | 178 read -p "Are you sure (y/N)? " SURE |
| 191 SURE="${SURE:0:1}" # Get just the first character | 179 SURE="${SURE:0:1}" # Get just the first character |
| 192 if [ "${SURE}" != "y" ] | 180 if [ "${SURE}" != "y" ] |
| 193 then | 181 then |
| 194 echo "Ok, better safe than sorry." | 182 echo "Ok, better safe than sorry." |
| 195 exit 1 | 183 exit 1 |
| 196 fi | 184 fi |
| 197 fi | 185 fi |
| 198 | 186 |
| 199 echo "attempting to unmount any mounts on the USB device" | 187 echo "Attempting to unmount any mounts on the USB device..." |
| 200 for i in "${FLAGS_to}"* | 188 for i in $(mount | grep ^"${FLAGS_to}" | awk '{print $1}') |
| 201 do | 189 do |
| 202 ! sudo umount "$i" | 190 sudo umount "$i" |
| 203 done | 191 done |
| 204 sleep 3 | 192 sleep 3 |
| 205 | 193 |
| 206 if [ ${FLAGS_install_autotest} -eq ${FLAGS_TRUE} ] ; then | 194 echo "Copying ${SRC_IMAGE} to ${FLAGS_to}..." |
| 207 install_autotest | 195 sudo dd if="${SRC_IMAGE}" of="${FLAGS_to}" bs=4M |
| 208 fi | |
| 209 | 196 |
| 210 # Write stateful partition to first partition. | |
| 211 echo "Copying stateful partition ..." | |
| 212 sudo "${SCRIPTS_DIR}"/file_copy.py \ | |
| 213 if="${STATEFUL_IMG}" of="${FLAGS_to}" bs=4M \ | |
| 214 seek_bytes=512 | |
| 215 | |
| 216 # Write root fs to third partition. | |
| 217 echo "Copying root fs partition ..." | |
| 218 sudo "${SCRIPTS_DIR}"/file_copy.py \ | |
| 219 if="${ROOTFS_IMAGE}" of="${FLAGS_to}" bs=4M \ | |
| 220 seek_bytes=$(( (${PART_SIZE} * 2) + 512 )) | |
| 221 | |
| 222 trap - EXIT | |
| 223 | |
| 224 if [ ${FLAGS_copy_kernel} -eq ${FLAGS_TRUE} ] | |
| 225 then | |
| 226 echo "Copying Kernel..." | |
| 227 "${SCRIPTS_DIR}"/kernel_fetcher.sh \ | |
| 228 --from "${FLAGS_from}" \ | |
| 229 --to "${FLAGS_to}" \ | |
| 230 --offset "$(( (${PART_SIZE} * 3) + 512 ))" | |
| 231 fi | |
| 232 | |
| 233 echo "Copying MBR..." | |
| 234 sudo "${SCRIPTS_DIR}"/file_copy.py \ | |
| 235 if="${FLAGS_from}/mbr.image" of="${FLAGS_to}" | |
| 236 sync | |
| 237 echo "Done." | 197 echo "Done." |
| 238 else | 198 else |
| 239 # Output to a file, so just cat the source images together | 199 # Output to a file, so just make a copy. |
| 240 | 200 echo "Copying ${SRC_IMAGE} to ${FLAGS_to}..." |
| 241 PART_SIZE=$(stat -c%s "${ROOTFS_IMAGE}") | 201 cp -f "${SRC_IMAGE}" "${FLAGS_to}" |
| 242 | |
| 243 if [ ${FLAGS_install_autotest} -eq ${FLAGS_TRUE} ] ; then | |
| 244 install_autotest | |
| 245 fi | |
| 246 | |
| 247 # Create a sparse output file | |
| 248 dd if=/dev/zero of="${FLAGS_to}" bs=1 count=1 \ | |
| 249 seek=$(( (${PART_SIZE} * 2) + 512 - 1)) | |
| 250 | |
| 251 echo "Copying USB image to file ${FLAGS_to}..." | |
| 252 | |
| 253 dd if="${FLAGS_from}/mbr.image" of="${FLAGS_to}" conv=notrunc | |
| 254 dd if="${FLAGS_from}/stateful_partition.image" of="${FLAGS_to}" seek=1 bs=512
\ | |
| 255 conv=notrunc | |
| 256 cat "${ROOTFS_IMAGE}" >> "${FLAGS_to}" | |
| 257 | 202 |
| 258 echo "Done. To copy to USB keyfob, outside the chroot, do something like:" | 203 echo "Done. To copy to USB keyfob, outside the chroot, do something like:" |
| 259 echo " sudo dd if=${FLAGS_to} of=/dev/sdb bs=4M" | 204 echo " sudo dd if=${FLAGS_to} of=/dev/sdb bs=4M" |
| 260 echo "where /dev/sdb is the entire keyfob." | 205 echo "where /dev/sdb is the entire keyfob." |
| 261 if [ ${INSIDE_CHROOT} -eq 1 ] | 206 if [ ${INSIDE_CHROOT} -eq 1 ] |
| 262 then | 207 then |
| 208 example=$(basename "${FLAGS_to}") |
| 263 echo "NOTE: Since you are currently inside the chroot, and you'll need to" | 209 echo "NOTE: Since you are currently inside the chroot, and you'll need to" |
| 264 echo "run dd outside the chroot, the path to the USB image will be" | 210 echo "run dd outside the chroot, the path to the USB image will be" |
| 265 echo "different (ex: ~/chromeos/trunk/src/build/images/SOME_DIR/usb.img)." | 211 echo "different (ex: ~/chromeos/trunk/src/build/images/SOME_DIR/$example)." |
| 266 fi | 212 fi |
| 267 fi | 213 fi |
| OLD | NEW |