blob: 004ab932618cce7c109b0a4bfa54e6485fc3a632 [file] [log] [blame]
Bill Richardsoneff5b062010-03-30 14:17:34 -07001# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4#
5# This contains common constants and functions for installer scripts. This must
6# evaluate properly for both /bin/bash and /bin/sh, since it's used both to
7# create the initial image at compile time and to install or upgrade a running
8# image.
9
Bill Richardsoneff5b062010-03-30 14:17:34 -070010# The GPT tables describe things in terms of 512-byte sectors, but some
11# filesystems prefer 4096-byte blocks. These functions help with alignment
12# issues.
13
14# This returns the size of a file or device in 512-byte sectors, rounded up if
15# needed.
16# Invoke as: subshell
17# Args: FILENAME
18# Return: whole number of sectors needed to fully contain FILENAME
19numsectors() {
Jie Sun1f9d4122010-04-12 17:04:36 -070020 if [ -b "${1}" ]; then
Bill Richardsoneff5b062010-03-30 14:17:34 -070021 dev=${1##*/}
Jie Sun1f9d4122010-04-12 17:04:36 -070022 if [ -e /sys/block/$dev/size ]; then
23 cat /sys/block/$dev/size
24 else
25 part=${1##*/}
26 block=$(get_block_dev_from_partition_dev "${1}")
27 block=${block##*/}
28 cat /sys/block/$block/$part/size
29 fi
30 else
Bill Richardsoneff5b062010-03-30 14:17:34 -070031 local bytes=$(stat -c%s "$1")
32 local sectors=$(( $bytes / 512 ))
33 local rem=$(( $bytes % 512 ))
34 if [ $rem -ne 0 ]; then
35 sectors=$(( $sectors + 1 ))
36 fi
37 echo $sectors
Jie Sun1f9d4122010-04-12 17:04:36 -070038 fi
Bill Richardsoneff5b062010-03-30 14:17:34 -070039}
40
Bill Richardsond6b71b02010-04-14 12:46:14 -070041# Round a number of 512-byte sectors up to an integral number of 2Mb
42# blocks. Divisor is 2 * 1024 * 1024 / 512 == 4096.
Bill Richardsoneff5b062010-03-30 14:17:34 -070043# Invoke as: subshell
44# Args: SECTORS
45# Return: Next largest multiple-of-8 sectors (ex: 4->8, 33->40, 32->32)
46roundup() {
47 local num=$1
Bill Richardsond6b71b02010-04-14 12:46:14 -070048 local div=${2:-4096}
49 local rem=$(( $num % $div ))
Bill Richardsoneff5b062010-03-30 14:17:34 -070050
Andrew de los Reyes344709b2010-04-05 10:49:08 -070051 if [ $rem -ne 0 ]; then
Bill Richardsond6b71b02010-04-14 12:46:14 -070052 num=$(($num + $div - $rem))
Bill Richardsoneff5b062010-03-30 14:17:34 -070053 fi
54 echo $num
55}
56
Bill Richardsond6b71b02010-04-14 12:46:14 -070057# Truncate a number of 512-byte sectors down to an integral number of 2Mb
58# blocks. Divisor is 2 * 1024 * 1024 / 512 == 4096.
Bill Richardsoneff5b062010-03-30 14:17:34 -070059# Invoke as: subshell
60# Args: SECTORS
61# Return: Next smallest multiple-of-8 sectors (ex: 4->0, 33->32, 32->32)
62rounddown() {
63 local num=$1
Bill Richardsond6b71b02010-04-14 12:46:14 -070064 local div=${2:-4096}
65 local rem=$(( $num % $div ))
Bill Richardsoneff5b062010-03-30 14:17:34 -070066
Andrew de los Reyes344709b2010-04-05 10:49:08 -070067 if [ $rem -ne 0 ]; then
Bill Richardsoneff5b062010-03-30 14:17:34 -070068 num=$(($num - $rem))
69 fi
70 echo $num
71}
72
Bill Richardson7c358a92010-06-11 09:16:03 -070073# Locate the cgpt tool. It should already be installed in the build chroot,
robotboya7684292010-04-21 14:46:00 -070074# but some of these functions may be invoked outside the chroot (by
Bill Richardsoneff5b062010-03-30 14:17:34 -070075# image_to_usb or similar), so we need to find it.
robotboya7684292010-04-21 14:46:00 -070076GPT=""
Yusuke Satod55cea92010-04-21 10:46:59 +090077
robotboya7684292010-04-21 14:46:00 -070078locate_gpt() {
79 if [ -z "$GPT" ]; then
Bill Richardsonf67f8442010-12-01 08:27:37 -080080 if [ -x "${DEFAULT_CHROOT_DIR:-}/usr/bin/cgpt" ]; then
81 GPT="${DEFAULT_CHROOT_DIR:-}/usr/bin/cgpt"
82 else
83 GPT=$(which cgpt 2>/dev/null) || /bin/true
84 if [ -z "$GPT" ]; then
Bill Richardson7c358a92010-06-11 09:16:03 -070085 echo "can't find cgpt tool" 1>&2
robotboya7684292010-04-21 14:46:00 -070086 exit 1
87 fi
88 fi
89 fi
90}
Bill Richardsoneff5b062010-03-30 14:17:34 -070091
Bill Richardsoneff5b062010-03-30 14:17:34 -070092# Read GPT table to find the starting location of a specific partition.
93# Invoke as: subshell
94# Args: DEVICE PARTNUM
95# Returns: offset (in sectors) of partition PARTNUM
96partoffset() {
Elly Jones7f1dc652011-08-12 15:44:18 -040097 sudo $GPT show -b -i $2 $1
Bill Richardsoneff5b062010-03-30 14:17:34 -070098}
99
100# Read GPT table to find the size of a specific partition.
101# Invoke as: subshell
102# Args: DEVICE PARTNUM
103# Returns: size (in sectors) of partition PARTNUM
104partsize() {
Elly Jones7f1dc652011-08-12 15:44:18 -0400105 sudo $GPT show -s -i $2 $1
Bill Richardsoneff5b062010-03-30 14:17:34 -0700106}
107
Jie Sun1f9d4122010-04-12 17:04:36 -0700108# Extract the whole disk block device from the partition device.
109# This works for /dev/sda3 (-> /dev/sda) as well as /dev/mmcblk0p2
110# (-> /dev/mmcblk0).
111get_block_dev_from_partition_dev() {
112 local partition=$1
113 if ! (expr match "$partition" ".*[0-9]$" >/dev/null) ; then
114 echo "Invalid partition name: $partition" >&2
115 exit 1
116 fi
Will Drewry056e9c82010-08-06 16:10:59 -0500117 # Removes any trailing digits.
118 local block=$(echo "$partition" | sed -e 's/[0-9]*$//')
Jie Sun1f9d4122010-04-12 17:04:36 -0700119 # If needed, strip the trailing 'p'.
120 if (expr match "$block" ".*[0-9]p$" >/dev/null); then
121 echo "${block%p}"
122 else
123 echo "$block"
124 fi
125}
126
127# Extract the partition number from the partition device.
128# This works for /dev/sda3 (-> 3) as well as /dev/mmcblk0p2 (-> 2).
129get_partition_number() {
130 local partition=$1
131 if ! (expr match "$partition" ".*[0-9]$" >/dev/null) ; then
132 echo "Invalid partition name: $partition" >&2
133 exit 1
134 fi
135 # Extract the last digit.
136 echo "$partition" | sed -e 's/^.*\([0-9]\)$/\1/'
137}
138
139# Construct a partition device name from a whole disk block device and a
140# partition number.
141# This works for [/dev/sda, 3] (-> /dev/sda3) as well as [/dev/mmcblk0, 2]
142# (-> /dev/mmcblk0p2).
143make_partition_dev() {
144 local block=$1
145 local num=$2
146 # If the disk block device ends with a number, we add a 'p' before the
147 # partition number.
148 if (expr match "$block" ".*[0-9]$" >/dev/null) ; then
149 echo "${block}p${num}"
150 else
151 echo "${block}${num}"
152 fi
153}
154
Elly Jones677ffec2011-08-10 18:35:29 -0400155# Find the uuid for a (disk, partnum) pair (e.g., ("/dev/sda", 3))
156part_index_to_uuid() {
157 local dev="$1"
158 local idx="$2"
159
Elly Jones7f1dc652011-08-12 15:44:18 -0400160 sudo $GPT show -i "$idx" -u "$dev"
Elly Jones677ffec2011-08-10 18:35:29 -0400161}
162
Paul Stewart04f3ef12010-05-27 15:56:42 -0700163list_usb_disks() {
164 local sd
165 for sd in /sys/block/sd*; do
Paul Stewart248f4642010-06-09 10:11:15 -0700166 if readlink -f ${sd}/device | grep -q usb &&
Paul Stewart04f3ef12010-05-27 15:56:42 -0700167 [ "$(cat ${sd}/removable)" = 1 ]; then
168 echo ${sd##*/}
169 fi
170 done
171}
172
Mario Limonciello80d52762011-05-24 19:30:55 -0500173list_mmc_disks() {
174 local mmc
175 for mmc in /sys/block/mmcblk*; do
176 if readlink -f ${mmc}/device | grep -q mmc; then
177 echo ${mmc##*/}
178 fi
179 done
180}
181
Paul Stewart04f3ef12010-05-27 15:56:42 -0700182get_disk_info() {
183 # look for a "given" file somewhere in the path upwards from the device
184 local dev_path=/sys/block/${1}/device
185 while [ -d "${dev_path}" -a "${dev_path}" != "/sys" ]; do
186 if [ -f "${dev_path}/${2}" ]; then
187 cat "${dev_path}/${2}"
188 return
189 fi
190 dev_path=$(readlink -f ${dev_path}/..)
191 done
192 echo '[Unknown]'
193}
Liam McLoughlin2dd21d62012-07-09 17:45:06 -0700194
Liam McLoughlin87aa6982012-08-13 13:49:34 -0700195legacy_offset_size_export() {
196 # Exports all the variables that install_gpt did previously.
197 # This should disappear eventually, but it's here to make existing
198 # code work for now.
199
200 START_STATEFUL=$(partoffset $1 1)
201 START_KERN_A=$(partoffset $1 2)
202 START_ROOTFS_A=$(partoffset $1 3)
203 START_KERN_B=$(partoffset $1 4)
Mike Frysinger9a715bf2012-09-24 18:47:05 -0400204 START_ROOTFS_B=$(partoffset $1 5)
Liam McLoughlin87aa6982012-08-13 13:49:34 -0700205 START_OEM=$(partoffset $1 8)
206 START_RWFW=$(partoffset $1 11)
207 START_ESP=$(partoffset $1 12)
208
209 NUM_STATEFUL_SECTORS=$(partsize $1 1)
210 NUM_KERN_SECTORS=$(partsize $1 2)
211 NUM_ROOTFS_SECTORS=$(partsize $1 3)
212 NUM_OEM_SECTORS=$(partsize $1 8)
213 NUM_RWFW_SECTORS=$(partsize $1 11)
214 NUM_ESP_SECTORS=$(partsize $1 12)
215
216 STATEFUL_IMG_SECTORS=$(partsize $1 1)
217 KERNEL_IMG_SECTORS=$(partsize $1 2)
218 ROOTFS_IMG_SECTORS=$(partsize $1 3)
219 OEM_IMG_SECTORS=$(partsize $1 8)
220 ESP_IMG_SECTORS=$(partsize $1 12)
221}
222
Liam McLoughlin2dd21d62012-07-09 17:45:06 -0700223install_hybrid_mbr() {
224 # Creates a hybrid MBR which points the MBR partition 1 to GPT
225 # partition 12 (ESP). This is useful on ARM boards that boot
226 # from MBR formatted disks only
227 info "Creating hybrid MBR"
228 locate_gpt
229 local start_esp=$(partoffset "$1" 12)
230 local num_esp_sectors=$(partsize "$1" 12)
231 sudo sfdisk "${1}" <<EOF
232unit: sectors
233
234disk1 : start= $start_esp, size= $num_esp_sectors, Id= c, bootable
235disk2 : start= 1, size= 1, Id= ee
236EOF
237}