| OLD | NEW |
| 1 #!/bin/sh | 1 #!/bin/sh |
| 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 # A script to install from removable media to hard disk. | 7 # A script to install from removable media to hard disk. |
| 8 | 8 |
| 9 if [ "$USER" != "chronos" ] | 9 echo "" |
| 10 then | 10 echo "Usage: $0 [destination_device] [skip_source_removable_check]" |
| 11 echo "" | 11 echo "" |
| 12 echo "Note: You must be the 'chronos' user to run this script." | 12 echo "This will install the usb image to your machine's hard disk." |
| 13 echo "" | 13 echo "By default, it will attempt to install to '/dev/sda'." |
| 14 echo "Usage: $0 [destination_device] [skip_source_removable_check]" | 14 echo "Skips checking whether the source device is removable if second" |
| 15 echo "" | 15 echo "argument is 'true'." |
| 16 echo "This will install the usb image to your machine's hard disk." | 16 echo "" |
| 17 echo "By default, it will attempt to install to '/dev/sda'." | |
| 18 echo "First 'su chronos' and then run the script. It will ask" | |
| 19 echo "for the root password before messing with your hard disk." | |
| 20 echo "Skips checking whether the source device is removable if second" | |
| 21 echo "argument is 'true'." | |
| 22 exit 1 | |
| 23 fi | |
| 24 | 17 |
| 25 DST=/dev/sda | 18 DST=/dev/sda |
| 26 if [ -n "$1" ] | 19 if [ -n "$1" ] |
| 27 then | 20 then |
| 28 DST="$1" | 21 DST="$1" |
| 29 fi | 22 fi |
| 30 | 23 |
| 31 SKIP_CHECK_SOURCE_REMOVABLE="false" | 24 SKIP_CHECK_SOURCE_REMOVABLE="false" |
| 32 if [ "$2" = "true" ] | 25 if [ "$2" = "true" ] |
| 33 then | 26 then |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 then | 69 then |
| 77 echo "Error: Invalid destiation device (must be whole device): $DST" | 70 echo "Error: Invalid destiation device (must be whole device): $DST" |
| 78 exit 1 | 71 exit 1 |
| 79 fi | 72 fi |
| 80 if [ "$REMOVABLE" != "0" ] | 73 if [ "$REMOVABLE" != "0" ] |
| 81 then | 74 then |
| 82 echo "Error: Attempt to install to a removeable device: $DST" | 75 echo "Error: Attempt to install to a removeable device: $DST" |
| 83 exit 1 | 76 exit 1 |
| 84 fi | 77 fi |
| 85 | 78 |
| 86 # Ask for root password to be sure. | 79 # TODO: We should install the mbr into the image rather than taking it from the |
| 87 echo "This will install from '$SRC' to '$DST'. If you are sure this is " | 80 # source device as we do here. |
| 88 echo "what you want then feel free to enter the root password to proceed." | 81 MBR="/tmp/gptmbr.bin" |
| 89 sudo -K # Force them to enter a password | 82 sudo dd if="$SRC" of="$MBR" bs=512 count=1 |
| 90 | 83 |
| 91 # Verify sizes. Since we use sfdisk, this needs to be done after we start | 84 . /usr/sbin/chromeos_install_functions.sh |
| 92 # asking for the root password. | |
| 93 SIZE=`sudo sfdisk -l "$SRC" 2>/dev/null | grep "$SRC_PARTITION" | grep '*' | awk
'{ print $6 }'` | |
| 94 SIZE=$((SIZE * 1024)) | |
| 95 if [ $SIZE -eq 0 ] | |
| 96 then | |
| 97 echo "Error: Unable to get system partition size." | |
| 98 exit 1 | |
| 99 fi | |
| 100 SIZE_NEEDED=$((SIZE * 4)) # Assume 2 system images, swap, and user space. | |
| 101 DST_SIZE=`cat /sys/block/$DST_DEV/size` | |
| 102 DST_SIZE=$((DST_SIZE * 512)) | |
| 103 if [ $DST_SIZE -lt $SIZE_NEEDED ] | |
| 104 then | |
| 105 echo "Error: Destination device is too small ($DST_SIZE vs $SIZE_NEEDED)" | |
| 106 exit 1 | |
| 107 fi | |
| 108 | 85 |
| 109 # Location to temporarily mount the new system image to fix things up. | 86 # Make sure that the destination file/device is ok to blow away. |
| 110 ROOTFS_DIR="/tmp/chromeos_hd_install" | 87 echo "Installing from '$SRC_PARTITION' to '$DST'" |
| 88 do_verify "$SRC_PARTITION" "$DST" "full" |
| 111 | 89 |
| 112 # From now on we die on error. We set up a failure handler and continue. | 90 # Perform standard installation to destination. |
| 113 error_handler() { | 91 install_chromeos "$SRC_PARTITION" "$DST" "H" "full" |
| 114 ! sudo umount "$ROOTFS_DIR" | |
| 115 | |
| 116 echo "Sorry, an error occurred after we messed with the hard disk." | |
| 117 echo "The chromeos image was NOT installed successfully and there is " | |
| 118 echo "a chance that you will not be able to boot off the netbook hard disk." | |
| 119 } | |
| 120 set -e | |
| 121 trap error_handler EXIT | |
| 122 | |
| 123 # Set up the partition table. This is different from the USB partition table | |
| 124 # because the user paritition expands to fill the space on the disk. | |
| 125 # NOTE: We currently create an EFI partition rather than swap since the | |
| 126 # eeepc can take advantage of this to speed POST time. | |
| 127 sudo dd if="$SRC" of="$DST" bs=512 count=1 | |
| 128 | |
| 129 PARTITION_NUM_SECTORS=$((SIZE / 512)) | |
| 130 # size of the device in 512 bytes sectors: | |
| 131 DEVICE_NUM_SECTORS=$(cat /sys/block/${DST#/dev/}/size) | |
| 132 | |
| 133 sudo sfdisk --force -uS "$DST" <<EOF | |
| 134 ,$(($DEVICE_NUM_SECTORS - (3 * $PARTITION_NUM_SECTORS) - 1)),L,-, | |
| 135 ,$PARTITION_NUM_SECTORS,ef,-, | |
| 136 ,$PARTITION_NUM_SECTORS,L,*, | |
| 137 ,$PARTITION_NUM_SECTORS,L,-, | |
| 138 ; | |
| 139 EOF | |
| 140 sync | |
| 141 | 92 |
| 142 # Tell kernel to update partition devices based on the new MBR: | 93 # Tell kernel to update partition devices based on the new MBR: |
| 143 sudo sfdisk -R "$DST" | 94 sudo sfdisk -R "$DST" |
| 144 | 95 |
| 145 # Wait a bit and make sure that the partition device shows up. | 96 # Wait a bit and make sure that the partition device shows up. |
| 146 DST_PARTITION="${DST}3" | 97 DST_PARTITION="${DST}3" |
| 147 sleep 5 | 98 sleep 5 |
| 148 if [ ! -b "$DST_PARTITION" ] | 99 if [ ! -b "$DST_PARTITION" ] |
| 149 then | 100 then |
| 150 echo "Error: Destination system partition was not created: $DST_PARTITION" | 101 echo "Error: Destination system partition was not created: $DST_PARTITION" |
| 151 exit 1 | 102 exit 1 |
| 152 fi | 103 fi |
| 153 | 104 |
| 154 # Copy the system image. We sync first to try to make the copy as safe as we | 105 # From now on we die on error. We set up a failure handler and continue. |
| 155 # can. We skip the first block which contains the filesystem label (aka | 106 error_handler() { |
| 156 # volume name). It's 16 bytes in length at 120 bytes in the superblock, | 107 ! sudo umount "$ROOTFS_DIR" |
| 157 # which is itself at offset 1024 of the device. | |
| 158 echo "" | |
| 159 echo "Copying the system image. This might take a while..." | |
| 160 sync | |
| 161 sudo dd if="$SRC_PARTITION" of="$DST_PARTITION" bs=1M seek=1 skip=1 | |
| 162 # Copy all but the first 2 kibibytes now | |
| 163 sudo dd if="$SRC_PARTITION" of="$DST_PARTITION" bs=1024 seek=2 skip=2 count=1022 | |
| 164 | 108 |
| 165 # Check new file system label. We skip the first char and prefix with 'H' | 109 echo "Sorry, an error occurred after we messed with the hard disk." |
| 166 NEW_LABEL=`expr substr "$LABEL" 2 ${#LABEL}` | 110 echo "The chromeos image was NOT installed successfully and there is " |
| 167 NEW_LABEL="H${NEW_LABEL}" | 111 echo "a chance that you will not be able to boot off the netbook hard disk." |
| 168 if [ ${#NEW_LABEL} -gt 15 ] | 112 } |
| 169 then | 113 set -e |
| 170 echo "New label " "$NEW_LABEL is too long (greater than 15 bytes)" | |
| 171 fi | |
| 172 | 114 |
| 173 # Copy first 2 kibibytes of the partition to a temp file | 115 # Mount root partition and run postinst script. |
| 174 TEMP_FILE=/tmp/install_part_head | 116 ROOTFS_DIR=$(mktemp -d) |
| 175 sudo dd if="$SRC_PARTITION" of="$TEMP_FILE" bs=1024 count=2 | 117 trap error_handler EXIT |
| 176 | |
| 177 # Manually update the label. First zero it, then write the new label. | |
| 178 SUPERBLOCK_OFFSET=1024 | |
| 179 LABEL_FIELD_OFFSET=120 | |
| 180 LABEL_FIELD_LENGTH=16 | |
| 181 sudo dd if=/dev/zero of="$TEMP_FILE" bs=1 \ | |
| 182 seek=$(( $SUPERBLOCK_OFFSET + $LABEL_FIELD_OFFSET )) \ | |
| 183 count=$LABEL_FIELD_LENGTH conv=notrunc | |
| 184 echo -n "$NEW_LABEL" | sudo dd of="$TEMP_FILE" \ | |
| 185 seek=$(( $SUPERBLOCK_OFFSET + $LABEL_FIELD_OFFSET )) \ | |
| 186 bs=1 count=15 conv=notrunc | |
| 187 | |
| 188 # Copy the temp file into the new partition | |
| 189 sudo dd if="$TEMP_FILE" of="$DST_PARTITION" | |
| 190 sudo rm -f "$TEMP_FILE" | |
| 191 sync | |
| 192 | |
| 193 # Mount root partition | |
| 194 mkdir -p "$ROOTFS_DIR" | |
| 195 sudo mount "$DST_PARTITION" "$ROOTFS_DIR" | 118 sudo mount "$DST_PARTITION" "$ROOTFS_DIR" |
| 196 # run postinst script | |
| 197 sudo "$ROOTFS_DIR"/postinst "$DST_PARTITION" | 119 sudo "$ROOTFS_DIR"/postinst "$DST_PARTITION" |
| 198 sudo umount "$ROOTFS_DIR" | 120 sudo umount "$ROOTFS_DIR" |
| 199 | 121 trap - EXIT |
| 200 # set up stateful partition | 122 rmdir "$ROOTFS_DIR" |
| 201 STATEFUL_PARTITION="${DST}1" | |
| 202 sudo mkfs.ext3 "$STATEFUL_PARTITION" | |
| 203 sudo tune2fs -L "H-STATE" "$STATEFUL_PARTITION" | |
| 204 | 123 |
| 205 # Force data to disk before we declare done. | 124 # Force data to disk before we declare done. |
| 206 sync | 125 sync |
| 207 | 126 |
| 208 echo "------------------------------------------------------------" | 127 echo "------------------------------------------------------------" |
| 209 echo "" | 128 echo "" |
| 210 echo "Installation to '$DST' complete." | 129 echo "Installation to '$DST' complete." |
| 211 echo "Please shutdown, remove the USB device, cross your fingers, and reboot." | 130 echo "Please shutdown, remove the USB device, cross your fingers, and reboot." |
| 212 | |
| 213 trap - EXIT | |
| OLD | NEW |