blob: 89af92f6f174c2e80436325847b1c0c34351c0be [file] [log] [blame]
Rahul Chaturvedib5643e82010-07-09 10:46:05 +05301#!/bin/bash
2
3# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# Script to convert the output of build_image.sh to a VMware image and write a
8# corresponding VMware config file.
9
Greg Spencer798d75f2011-02-01 22:04:49 -080010# --- BEGIN COMMON.SH BOILERPLATE ---
11# Load common CrOS utilities. Inside the chroot this file is installed in
12# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
13# location.
14find_common_sh() {
15 local common_paths=(/usr/lib/crosutils $(dirname "$(readlink -f "$0")"))
16 local path
17
18 SCRIPT_ROOT=
19 for path in "${common_paths[@]}"; do
20 if [ -r "${path}/common.sh" ]; then
21 SCRIPT_ROOT=${path}
22 break
23 fi
24 done
25}
26
27find_common_sh
Brian Harringd5d5dbf2011-07-11 16:36:21 -070028. "${SCRIPT_ROOT}/common.sh" || { echo "Unable to load common.sh"; exit 1; }
Greg Spencer798d75f2011-02-01 22:04:49 -080029# --- END COMMON.SH BOILERPLATE ---
30
31# Need to be inside the chroot to load chromeos-common.sh
32assert_inside_chroot
33
34# Load functions and constants for chromeos-install
35. "/usr/lib/installer/chromeos-common.sh" || \
36 die "Unable to load /usr/lib/installer/chromeos-common.sh"
37
38. "${SCRIPT_ROOT}/lib/cros_vm_constants.sh" || \
39 die "Unable to load ${SCRIPT_ROOT}/lib/cros_vm_constants.sh"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053040
41get_default_board
42
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053043# Flags
44DEFINE_string board "${DEFAULT_BOARD}" \
45 "Board for which the image was built"
46DEFINE_boolean factory $FLAGS_FALSE \
47 "Modify the image for manufacturing testing"
48DEFINE_boolean factory_install $FLAGS_FALSE \
49 "Modify the image for factory install shim"
Simon Glass142ca062011-02-09 13:39:43 -080050
51# We default to TRUE so the buildbot gets its image. Note this is different
52# behavior from image_to_usb.sh
Chris Sosa8dad50d2011-02-14 15:29:32 -080053DEFINE_boolean force_copy ${FLAGS_FALSE} "Always rebuild test image"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053054DEFINE_string format "qemu" \
55 "Output format, either qemu, vmware or virtualbox"
56DEFINE_string from "" \
57 "Directory containing rootfs.image and mbr.image"
Chris Sosacc09f842010-09-21 17:09:51 -070058DEFINE_boolean full "${FLAGS_FALSE}" "Build full image with all partitions."
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053059DEFINE_boolean make_vmx ${FLAGS_TRUE} \
60 "Create a vmx file for use with vmplayer (vmware only)."
61DEFINE_integer mem "${DEFAULT_MEM}" \
62 "Memory size for the vm config in MBs (vmware only)."
63DEFINE_integer rootfs_partition_size 1024 \
64 "rootfs parition size in MBs."
65DEFINE_string state_image "" \
66 "Stateful partition image (defaults to creating new statful partition)"
Chris Masone7d04c7a2010-11-09 08:24:13 -080067DEFINE_integer statefulfs_size 2048 \
Rahul Chaturvedie770e162010-07-15 00:35:11 +053068 "Stateful partition size in MBs."
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053069DEFINE_boolean test_image "${FLAGS_FALSE}" \
Simon Glass142ca062011-02-09 13:39:43 -080070 "Copies normal image to ${CHROMEOS_TEST_IMAGE_NAME}, modifies it for test."
Rahul Chaturvedib5643e82010-07-09 10:46:05 +053071DEFINE_string to "" \
72 "Destination folder for VM output file(s)"
73DEFINE_string vbox_disk "${DEFAULT_VBOX_DISK}" \
74 "Filename for the output disk (virtualbox only)."
75DEFINE_integer vdisk_size 3072 \
76 "virtual disk size in MBs."
77DEFINE_string vmdk "${DEFAULT_VMDK}" \
78 "Filename for the vmware disk image (vmware only)."
79DEFINE_string vmx "${DEFAULT_VMX}" \
80 "Filename for the vmware config (vmware only)."
81
82# Parse command line
83FLAGS "$@" || exit 1
84eval set -- "${FLAGS_ARGV}"
85
86# Die on any errors.
87set -e
88
89if [ -z "${FLAGS_board}" ] ; then
90 die "--board is required."
91fi
92
Chris Sosacc09f842010-09-21 17:09:51 -070093if [ "${FLAGS_full}" -eq "${FLAGS_TRUE}" ] && \
94 ( [[ ${FLAGS_vdisk_size} < ${MIN_VDISK_SIZE_FULL} ]] || \
95 [[ ${FLAGS_statefulfs_size} < ${MIN_STATEFUL_FS_SIZE_FULL} ]]); then
Chris Sosa9fe00b92010-10-22 12:34:16 -070096 warn "Disk is too small for full, using minimum: vdisk size equal to \
97${MIN_VDISK_SIZE_FULL} and statefulfs size equal to \
Chris Sosacc09f842010-09-21 17:09:51 -070098${MIN_STATEFUL_FS_SIZE_FULL}."
Chris Sosa9fe00b92010-10-22 12:34:16 -070099 FLAGS_vdisk_size=${MIN_VDISK_SIZE_FULL}
100 FLAGS_statefulfs_size=${MIN_STATEFUL_FS_SIZE_FULL}
Chris Sosacc09f842010-09-21 17:09:51 -0700101fi
102
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530103IMAGES_DIR="${DEFAULT_BUILD_ROOT}/images/${FLAGS_board}"
104# Default to the most recent image
105if [ -z "${FLAGS_from}" ] ; then
Chris Sosabd613042010-10-04 13:29:23 -0700106 FLAGS_from="$(./get_latest_image.sh --board=${FLAGS_board})"
Zelidrag Hornung42ca8182010-07-12 18:08:44 -0700107else
108 pushd "${FLAGS_from}" && FLAGS_from=`pwd` && popd
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530109fi
110if [ -z "${FLAGS_to}" ] ; then
111 FLAGS_to="${FLAGS_from}"
112fi
113
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530114if [ ${FLAGS_test_image} -eq ${FLAGS_TRUE} ] ; then
Simon Glass142ca062011-02-09 13:39:43 -0800115 # Make a test image - this returns the test filename in CHROMEOS_RETURN_VAL
116 prepare_test_image "${FLAGS_from}" "${CHROMEOS_IMAGE_NAME}"
117 SRC_IMAGE="${CHROMEOS_RETURN_VAL}"
118else
119 # Use the standard image
120 SRC_IMAGE="${FLAGS_from}/${CHROMEOS_IMAGE_NAME}"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530121fi
122
123# Memory units are in MBs
Greg Spencer798d75f2011-02-01 22:04:49 -0800124TEMP_IMG="$(dirname "${SRC_IMAGE}")/vm_temp_image.bin"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530125
126# If we're not building for VMWare, don't build the vmx
127if [ "${FLAGS_format}" != "vmware" ]; then
128 FLAGS_make_vmx="${FLAGS_FALSE}"
129fi
130
131# Convert args to paths. Need eval to un-quote the string so that shell
132# chars like ~ are processed; just doing FOO=`readlink -f $FOO` won't work.
133FLAGS_from=`eval readlink -f $FLAGS_from`
134FLAGS_to=`eval readlink -f $FLAGS_to`
135
136# Split apart the partitions and make some new ones
137TEMP_DIR=$(mktemp -d)
138(cd "${TEMP_DIR}" &&
139 "${FLAGS_from}/unpack_partitions.sh" "${SRC_IMAGE}")
140
141# Fix the kernel command line
142TEMP_ESP="${TEMP_DIR}"/part_12
143TEMP_ROOTFS="${TEMP_DIR}"/part_3
144TEMP_STATE="${TEMP_DIR}"/part_1
Will Drewryefce6682010-07-23 19:43:27 -0500145TEMP_KERN="${TEMP_DIR}"/part_2
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530146if [ -n "${FLAGS_state_image}" ]; then
147 TEMP_STATE="${FLAGS_state_image}"
Rahul Chaturvedie770e162010-07-15 00:35:11 +0530148else
149 # If we have a stateful fs size specified create a new state partition
150 # of the specified size.
151 if [ "${FLAGS_statefulfs_size}" -ne -1 ]; then
152 STATEFUL_SIZE_BYTES=$((1024 * 1024 * ${FLAGS_statefulfs_size}))
153 original_image_size=$(stat -c%s "${TEMP_STATE}")
154 if [ "${original_image_size}" -gt "${STATEFUL_SIZE_BYTES}" ]; then
155 die "Cannot resize stateful image to smaller than original. Exiting."
156 fi
157
158 echo "Resizing stateful partition to ${FLAGS_statefulfs_size}MB"
Rahul Chaturvedie770e162010-07-15 00:35:11 +0530159 # Extend the original file size to the new size.
160 dd if=/dev/zero of="${TEMP_STATE}" bs=1 count=1 \
161 seek=$((STATEFUL_SIZE_BYTES - 1))
162 # Resize the partition.
David James8b9643f2011-07-21 22:11:11 -0700163 STATEFUL_LOOP_DEV=$(sudo losetup --show -f "${TEMP_STATE}")
164 if [ -z "${STATEFUL_LOOP_DEV}" ]; then
165 die "No free loop device. Free up a loop device or reboot. Exiting."
166 fi
Chris Sosa020aa692010-10-08 16:36:20 -0700167 sudo e2fsck -pf "${STATEFUL_LOOP_DEV}"
Rahul Chaturvedie770e162010-07-15 00:35:11 +0530168 sudo resize2fs "${STATEFUL_LOOP_DEV}"
Chris Sosa1b11f382010-10-25 15:10:26 -0700169 sync
Rahul Chaturvedie770e162010-07-15 00:35:11 +0530170 sudo losetup -d "${STATEFUL_LOOP_DEV}"
171 fi
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530172fi
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530173TEMP_PMBR="${TEMP_DIR}"/pmbr
174dd if="${SRC_IMAGE}" of="${TEMP_PMBR}" bs=512 count=1
175
176TEMP_MNT=$(mktemp -d)
Will Drewryefce6682010-07-23 19:43:27 -0500177TEMP_ESP_MNT=$(mktemp -d)
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530178cleanup() {
179 sudo umount -d "${TEMP_MNT}"
Will Drewryefce6682010-07-23 19:43:27 -0500180 sudo umount -d "${TEMP_ESP_MNT}"
181 rmdir "${TEMP_MNT}" "${TEMP_ESP_MNT}"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530182}
183trap cleanup INT TERM EXIT
184mkdir -p "${TEMP_MNT}"
Will Drewryf929c302010-10-20 18:48:20 -0500185enable_rw_mount "${TEMP_ROOTFS}"
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530186sudo mount -o loop "${TEMP_ROOTFS}" "${TEMP_MNT}"
Will Drewryefce6682010-07-23 19:43:27 -0500187mkdir -p "${TEMP_ESP_MNT}"
188sudo mount -o loop "${TEMP_ESP}" "${TEMP_ESP_MNT}"
189
Stéphane Marchesin7e0b3d82011-03-29 06:58:17 -0700190sudo python "${SCRIPTS_DIR}/fixup_image_for_qemu.py" \
191 --mounted_dir="${TEMP_MNT}"
192
Will Drewry537caa92010-08-20 20:30:56 -0500193# Modify the unverified usb template which uses a default usb_disk of sdb3
194sudo sed -i -e 's/sdb3/sda3/g' "${TEMP_MNT}/boot/syslinux/usb.A.cfg"
195
196# Unmount everything prior to building a final image
Will Drewryefce6682010-07-23 19:43:27 -0500197sync
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530198trap - INT TERM EXIT
199cleanup
200
Chris Sosacc09f842010-09-21 17:09:51 -0700201# TOOD(adlr): pick a size that will for sure accomodate the partitions.
Will Drewry537caa92010-08-20 20:30:56 -0500202dd if=/dev/zero of="${TEMP_IMG}" bs=1 count=1 \
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530203 seek=$((${FLAGS_vdisk_size} * 1024 * 1024 - 1))
204
Chris Sosacc09f842010-09-21 17:09:51 -0700205GPT_FULL="false"
206[ "${FLAGS_full}" -eq "${FLAGS_TRUE}" ] && GPT_FULL="true"
207
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530208# Set up the partition table
Tan Gao0d5f9482010-08-06 08:28:20 -0700209install_gpt "${TEMP_IMG}" "$(numsectors $TEMP_ROOTFS)" \
210 "$(numsectors $TEMP_STATE)" "${TEMP_PMBR}" "$(numsectors $TEMP_ESP)" \
Chris Sosacc09f842010-09-21 17:09:51 -0700211 "${GPT_FULL}" ${FLAGS_rootfs_partition_size}
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530212# Copy into the partition parts of the file
213dd if="${TEMP_ROOTFS}" of="${TEMP_IMG}" conv=notrunc bs=512 \
214 seek="${START_ROOTFS_A}"
215dd if="${TEMP_STATE}" of="${TEMP_IMG}" conv=notrunc bs=512 \
216 seek="${START_STATEFUL}"
217dd if="${TEMP_KERN}" of="${TEMP_IMG}" conv=notrunc bs=512 \
218 seek="${START_KERN_A}"
219dd if="${TEMP_ESP}" of="${TEMP_IMG}" conv=notrunc bs=512 \
220 seek="${START_ESP}"
221
Will Drewry537caa92010-08-20 20:30:56 -0500222# Make the built-image bootable and ensure that the legacy default usb boot
223# uses /dev/sda instead of /dev/sdb3.
224# NOTE: The TEMP_IMG must live in the same image dir as the original image
225# to operate automatically below.
226${SCRIPTS_DIR}/bin/cros_make_image_bootable $(dirname "${TEMP_IMG}") \
227 $(basename "${TEMP_IMG}") \
Arkaitz Ruiz Alvarez2bf88592011-07-07 15:47:31 -0700228 --usb_disk /dev/sda3 \
229 --force_developer_mode
Will Drewry537caa92010-08-20 20:30:56 -0500230
Rahul Chaturvedib5643e82010-07-09 10:46:05 +0530231echo Creating final image
232# Convert image to output format
233if [ "${FLAGS_format}" = "virtualbox" -o "${FLAGS_format}" = "qemu" ]; then
234 if [ "${FLAGS_format}" = "virtualbox" ]; then
235 VBoxManage convertdd "${TEMP_IMG}" "${FLAGS_to}/${FLAGS_vbox_disk}"
236 else
237 mv ${TEMP_IMG} ${FLAGS_to}/${DEFAULT_QEMU_IMAGE}
238 fi
239elif [ "${FLAGS_format}" = "vmware" ]; then
240 qemu-img convert -f raw "${TEMP_IMG}" \
241 -O vmdk "${FLAGS_to}/${FLAGS_vmdk}"
242else
243 die "Invalid format: ${FLAGS_format}"
244fi
245
246rm -rf "${TEMP_DIR}" "${TEMP_IMG}"
247if [ -z "${FLAGS_state_image}" ]; then
248 rm -f "${STATE_IMAGE}"
249fi
250
251echo "Created image at ${FLAGS_to}"
252
253# Generate the vmware config file
254# A good reference doc: http://www.sanbarrow.com/vmx.html
255VMX_CONFIG="#!/usr/bin/vmware
256.encoding = \"UTF-8\"
257config.version = \"8\"
258virtualHW.version = \"4\"
259memsize = \"${FLAGS_mem}\"
260ide0:0.present = \"TRUE\"
261ide0:0.fileName = \"${FLAGS_vmdk}\"
262ethernet0.present = \"TRUE\"
263usb.present = \"TRUE\"
264sound.present = \"TRUE\"
265sound.virtualDev = \"es1371\"
266displayName = \"Chromium OS\"
267guestOS = \"otherlinux\"
268ethernet0.addressType = \"generated\"
269floppy0.present = \"FALSE\""
270
271if [[ "${FLAGS_make_vmx}" = "${FLAGS_TRUE}" ]]; then
272 echo "${VMX_CONFIG}" > "${FLAGS_to}/${FLAGS_vmx}"
273 echo "Wrote the following config to: ${FLAGS_to}/${FLAGS_vmx}"
274 echo "${VMX_CONFIG}"
275fi
276
Olof Johansson3ed8d122010-09-27 13:29:40 -0500277
278if [ "${FLAGS_format}" == "qemu" ]; then
279 echo "If you have qemu-kvm installed, you can start the image by:"
Anush Elangovan0de6de62010-12-07 17:31:48 -0800280 echo "sudo kvm -m ${FLAGS_mem} -vga std -pidfile /tmp/kvm.pid -net nic,model=virtio " \
Chris Masone7d04c7a2010-11-09 08:24:13 -0800281 "-net user,hostfwd=tcp::9222-:22 \\"
Olof Johansson3ed8d122010-09-27 13:29:40 -0500282 echo " -hda ${FLAGS_to}/${DEFAULT_QEMU_IMAGE}"
283fi