blob: 2c5a3db385f437a77ee350b75ce2ca29d2704433 [file] [log] [blame]
Mike Frysinger1963df12013-06-03 14:01:35 -04001#!/bin/sh
Bill Richardsoneff5b062010-03-30 14:17:34 -07002# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# This contains common constants and functions for installer scripts. This must
7# evaluate properly for both /bin/bash and /bin/sh, since it's used both to
8# create the initial image at compile time and to install or upgrade a running
9# image.
10
Bill Richardsoneff5b062010-03-30 14:17:34 -070011# The GPT tables describe things in terms of 512-byte sectors, but some
12# filesystems prefer 4096-byte blocks. These functions help with alignment
13# issues.
14
Richard Barnette0c3aef02017-04-14 15:11:13 +000015# These fixed partition numbers are deprecated.
16# We should use values derived from disk_layout.
17PARTITION_NUM_STATE=1
18PARTITION_NUM_KERN_A=2
19PARTITION_NUM_ROOT_A=3
20PARTITION_NUM_KERN_B=4
21PARTITION_NUM_ROOT_B=5
22PARTITION_NUM_KERN_C=6
23PARTITION_NUM_ROOT_C=7
24PARTITION_NUM_OEM=8
25PARTITION_NUM_RWFW=11
26PARTITION_NUM_EFI_SYSTEM=12
27
Bill Richardsoneff5b062010-03-30 14:17:34 -070028# This returns the size of a file or device in 512-byte sectors, rounded up if
29# needed.
30# Invoke as: subshell
31# Args: FILENAME
32# Return: whole number of sectors needed to fully contain FILENAME
33numsectors() {
Jie Sun1f9d4122010-04-12 17:04:36 -070034 if [ -b "${1}" ]; then
Bill Richardsoneff5b062010-03-30 14:17:34 -070035 dev=${1##*/}
Jie Sun1f9d4122010-04-12 17:04:36 -070036 if [ -e /sys/block/$dev/size ]; then
37 cat /sys/block/$dev/size
38 else
39 part=${1##*/}
40 block=$(get_block_dev_from_partition_dev "${1}")
41 block=${block##*/}
42 cat /sys/block/$block/$part/size
43 fi
44 else
Bill Richardsoneff5b062010-03-30 14:17:34 -070045 local bytes=$(stat -c%s "$1")
46 local sectors=$(( $bytes / 512 ))
47 local rem=$(( $bytes % 512 ))
48 if [ $rem -ne 0 ]; then
49 sectors=$(( $sectors + 1 ))
50 fi
51 echo $sectors
Jie Sun1f9d4122010-04-12 17:04:36 -070052 fi
Bill Richardsoneff5b062010-03-30 14:17:34 -070053}
54
Bill Richardson7c358a92010-06-11 09:16:03 -070055# Locate the cgpt tool. It should already be installed in the build chroot,
robotboya7684292010-04-21 14:46:00 -070056# but some of these functions may be invoked outside the chroot (by
Bill Richardsoneff5b062010-03-30 14:17:34 -070057# image_to_usb or similar), so we need to find it.
robotboya7684292010-04-21 14:46:00 -070058GPT=""
Yusuke Satod55cea92010-04-21 10:46:59 +090059
robotboya7684292010-04-21 14:46:00 -070060locate_gpt() {
61 if [ -z "$GPT" ]; then
Bill Richardsonf67f8442010-12-01 08:27:37 -080062 if [ -x "${DEFAULT_CHROOT_DIR:-}/usr/bin/cgpt" ]; then
63 GPT="${DEFAULT_CHROOT_DIR:-}/usr/bin/cgpt"
64 else
65 GPT=$(which cgpt 2>/dev/null) || /bin/true
66 if [ -z "$GPT" ]; then
Bill Richardson7c358a92010-06-11 09:16:03 -070067 echo "can't find cgpt tool" 1>&2
robotboya7684292010-04-21 14:46:00 -070068 exit 1
69 fi
70 fi
71 fi
72}
Bill Richardsoneff5b062010-03-30 14:17:34 -070073
Bill Richardsoneff5b062010-03-30 14:17:34 -070074# Read GPT table to find the starting location of a specific partition.
75# Invoke as: subshell
76# Args: DEVICE PARTNUM
77# Returns: offset (in sectors) of partition PARTNUM
78partoffset() {
Elly Jones7f1dc652011-08-12 15:44:18 -040079 sudo $GPT show -b -i $2 $1
Bill Richardsoneff5b062010-03-30 14:17:34 -070080}
81
82# Read GPT table to find the size of a specific partition.
83# Invoke as: subshell
84# Args: DEVICE PARTNUM
85# Returns: size (in sectors) of partition PARTNUM
86partsize() {
Elly Jones7f1dc652011-08-12 15:44:18 -040087 sudo $GPT show -s -i $2 $1
Bill Richardsoneff5b062010-03-30 14:17:34 -070088}
89
Jie Sun1f9d4122010-04-12 17:04:36 -070090# Extract the whole disk block device from the partition device.
91# This works for /dev/sda3 (-> /dev/sda) as well as /dev/mmcblk0p2
92# (-> /dev/mmcblk0).
93get_block_dev_from_partition_dev() {
94 local partition=$1
95 if ! (expr match "$partition" ".*[0-9]$" >/dev/null) ; then
96 echo "Invalid partition name: $partition" >&2
97 exit 1
98 fi
Will Drewry056e9c82010-08-06 16:10:59 -050099 # Removes any trailing digits.
100 local block=$(echo "$partition" | sed -e 's/[0-9]*$//')
Jie Sun1f9d4122010-04-12 17:04:36 -0700101 # If needed, strip the trailing 'p'.
102 if (expr match "$block" ".*[0-9]p$" >/dev/null); then
103 echo "${block%p}"
104 else
105 echo "$block"
106 fi
107}
108
109# Extract the partition number from the partition device.
110# This works for /dev/sda3 (-> 3) as well as /dev/mmcblk0p2 (-> 2).
111get_partition_number() {
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
117 # Extract the last digit.
118 echo "$partition" | sed -e 's/^.*\([0-9]\)$/\1/'
119}
120
121# Construct a partition device name from a whole disk block device and a
122# partition number.
123# This works for [/dev/sda, 3] (-> /dev/sda3) as well as [/dev/mmcblk0, 2]
124# (-> /dev/mmcblk0p2).
125make_partition_dev() {
126 local block=$1
127 local num=$2
128 # If the disk block device ends with a number, we add a 'p' before the
129 # partition number.
130 if (expr match "$block" ".*[0-9]$" >/dev/null) ; then
131 echo "${block}p${num}"
132 else
133 echo "${block}${num}"
134 fi
135}
136
Gwendal Grignou20f0ca72014-03-13 16:14:43 -0700137# Return the type of device.
138#
139# The type can be:
140# MMC, SD for device managed by the MMC stack
141# ATA for ATA disk
Deepti Patildf2d2692016-03-04 15:24:58 +0530142# NVME for NVMe device
Gwendal Grignou20f0ca72014-03-13 16:14:43 -0700143# OTHER for other devices.
144get_device_type() {
145 local dev="$(basename "$1")"
146 local vdr
147 local type_file
148 local vendor_file
Deepti Patildf2d2692016-03-04 15:24:58 +0530149 # True device path of a NVMe device is just a simple PCI device.
150 # (there are no other buses),
151 # Use the device name to identify the type precisely.
152 case "${dev}" in
153 nvme*)
154 echo "NVME"
155 return
156 ;;
157 esac
158
Gwendal Grignou20f0ca72014-03-13 16:14:43 -0700159 type_file="/sys/block/${dev}/device/type"
160 # To detect device managed by the MMC stack
161 case $(readlink -f "${type_file}") in
162 *mmc*)
163 cat "${type_file}"
164 ;;
165 *usb*)
166 # Now if it contains 'usb', it is managed through
167 # a USB controller.
168 echo "USB"
169 ;;
170 *target*)
171 # Other SCSI devices.
172 # Check if it is an ATA device.
173 vdr="$(cat "/sys/block/${dev}/device/vendor")"
174 if [ "${vdr%% *}" = "ATA" ]; then
175 echo "ATA"
176 else
177 echo "OTHER"
178 fi
179 ;;
180 *)
181 echo "OTHER"
182 esac
183}
184
Gwendal Grignou732af512014-04-07 20:07:29 +0000185# ATA disk have ATA as vendor.
186# They may not contain ata in their device path if behind a SAS
187# controller.
188# Exclude disks with size 0, it means they did not spin up properly.
189list_fixed_ata_disks() {
190 local sd
191 local remo
192 local vdr
193 local size
194
195 for sd in /sys/block/sd*; do
196 if [ ! -r "${sd}/size" ]; then
197 continue
Paul Stewart04f3ef12010-05-27 15:56:42 -0700198 fi
Gwendal Grignou732af512014-04-07 20:07:29 +0000199 size=$(cat "${sd}/size")
200 remo=$(cat "${sd}/removable")
201 vdr=$(cat "${sd}/device/vendor")
202 if [ "${vdr%% *}" = "ATA" -a ${remo:-0} -eq 0 -a ${size:-0} -gt 0 ]; then
203 echo "${sd##*/}"
204 fi
Paul Stewart04f3ef12010-05-27 15:56:42 -0700205 done
Gwendal Grignou732af512014-04-07 20:07:29 +0000206}
207
208# We assume we only have eMMC devices, not removable MMC devices.
209# also, do not consider special hardware partitions non the eMMC, like boot.
210# These devices are built on top of the eMMC sysfs path:
211# /sys/block/mmcblk0 -> .../mmc_host/.../mmc0:0001/.../mmcblk0
212# /sys/block/mmcblk0boot0 -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0boot0
213# /sys/block/mmcblk0boot1 -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0boot1
214# /sys/block/mmcblk0rpmb -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0rpmb
215#
216# Their device link points back to mmcblk0, not to the hardware
217# device (mmc0:0001). Therefore there is no type in their device link.
218# (it should be /device/device/type)
219list_fixed_mmc_disks() {
220 local mmc
221 local type_file
222 for mmc in /sys/block/mmcblk*; do
223 type_file="${mmc}/device/type"
224 if [ -r "${type_file}" ]; then
225 if [ "$(cat "${type_file}")" = "MMC" ]; then
226 echo "${mmc##*/}"
227 fi
228 fi
229 done
230}
231
Gwendal Grignou66cc8352016-10-14 08:48:57 -0700232# NVMe device
233# Exclude disks with size 0, it means they did not spin up properly.
234list_fixed_nvme_disks() {
235 local nvme remo size
236
237 for nvme in /sys/block/nvme*; do
238 if [ ! -r "${sd}/size" ]; then
239 continue
240 fi
241 size=$(cat "${sd}/size")
242 remo=$(cat "${sd}/removable")
243 if [ ${remo:-0} -eq 0 -a ${size:-0} -gt 0 ]; then
244 echo "${nvme##*/}"
245 fi
246 done
247}
248
Gwendal Grignou732af512014-04-07 20:07:29 +0000249# Find the drive to install based on the build write_cgpt.sh
250# script. If not found, return ""
251get_fixed_dst_drive() {
252 local dev
253 if [ -z "${DEFAULT_ROOTDEV}" ]; then
254 dev=""
255 else
256 # No " here, the variable may contain wildcards.
257 dev="/dev/$(basename ${DEFAULT_ROOTDEV})"
258 if [ ! -b "${dev}" ]; then
259 # The device is not found
260 dev=""
261 fi
262 fi
263 echo "${dev}"
Paul Stewart04f3ef12010-05-27 15:56:42 -0700264}
Liam McLoughlin2dd21d62012-07-09 17:45:06 -0700265
J. Richard Barnette40ce8a02015-03-18 14:59:26 -0700266edit_mbr() {
Liam McLoughlin2dd21d62012-07-09 17:45:06 -0700267 locate_gpt
Steven 'Steve' Kendallbde39b12015-09-30 12:59:02 -0400268 local start_esp=$(partoffset "$1" ${PARTITION_NUM_EFI_SYSTEM})
269 local num_esp_sectors=$(partsize "$1" ${PARTITION_NUM_EFI_SYSTEM})
Victor Dodonf3888602016-04-21 10:36:15 -0700270 sfdisk -X dos "${1}" <<EOF
Liam McLoughlin2dd21d62012-07-09 17:45:06 -0700271unit: sectors
272
273disk1 : start= $start_esp, size= $num_esp_sectors, Id= c, bootable
274disk2 : start= 1, size= 1, Id= ee
275EOF
276}
J. Richard Barnette40ce8a02015-03-18 14:59:26 -0700277
278install_hybrid_mbr() {
279 # Creates a hybrid MBR which points the MBR partition 1 to GPT
280 # partition 12 (ESP). This is useful on ARM boards that boot
J. Richard Barnette2db77d42015-03-19 17:19:15 -0700281 # from MBR formatted disks only.
J. Richard Barnette40ce8a02015-03-18 14:59:26 -0700282 #
283 # Currently, this code path is used principally to install to
284 # SD cards using chromeos-install run from inside the chroot.
J. Richard Barnette2db77d42015-03-19 17:19:15 -0700285 # In that environment, `sfdisk` can be racing with udev, leading
286 # to EBUSY when it calls BLKRRPART for the target disk. We avoid
287 # the conflict by using `udevadm settle`, so that udev goes first.
288 # cf. crbug.com/343681.
J. Richard Barnette40ce8a02015-03-18 14:59:26 -0700289
290 echo "Creating hybrid MBR"
291 if ! edit_mbr "${1}"; then
J. Richard Barnette2db77d42015-03-19 17:19:15 -0700292 udevadm settle
J. Richard Barnette40ce8a02015-03-18 14:59:26 -0700293 blockdev --rereadpt "${1}"
294 fi
295}
Gwendal Grignouacb06352017-02-08 20:30:47 -0800296
297ext4_dir_encryption_supported() {
298 # Can be set in the ebuild.
299 local direncryption_enabled=false
300
301 # Return true if kernel support ext4 directory encryption.
302 ${direncryption_enabled} && \
303 ! LC_LANG=C e4crypt get_policy / | grep -qF \
304 -e "Operation not supported" \
305 -e "Inappropriate ioctl for device"
306}