OLD | NEW |
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 # | 4 # |
5 # This contains common constants and functions for installer scripts. This must | 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 | 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 | 7 # create the initial image at compile time and to install or upgrade a running |
8 # image. | 8 # image. |
9 | 9 |
10 # Here are the GUIDs we'll be using to identify various partitions. | 10 # Here are the GUIDs we'll be using to identify various partitions. |
(...skipping 10 matching lines...) Expand all Loading... |
21 # This returns the size of a file or device in 512-byte sectors, rounded up if | 21 # This returns the size of a file or device in 512-byte sectors, rounded up if |
22 # needed. | 22 # needed. |
23 # Invoke as: subshell | 23 # Invoke as: subshell |
24 # Args: FILENAME | 24 # Args: FILENAME |
25 # Return: whole number of sectors needed to fully contain FILENAME | 25 # Return: whole number of sectors needed to fully contain FILENAME |
26 numsectors() { | 26 numsectors() { |
27 case $1 in | 27 case $1 in |
28 /dev/*[0-9]) | 28 /dev/*[0-9]) |
29 dnum=${1##*/} | 29 dnum=${1##*/} |
30 dev=${dnum%%[0-9]*} | 30 dev=${dnum%%[0-9]*} |
31 cat /sys/block/$dev/$dnum/size | 31 cat /sys/block/$dev/$dnum/size |
32 ;; | 32 ;; |
33 /dev/*) | 33 /dev/*) |
34 dev=${1##*/} | 34 dev=${1##*/} |
35 cat /sys/block/$dev/size | 35 cat /sys/block/$dev/size |
36 ;; | 36 ;; |
37 *) | 37 *) |
38 local bytes=$(stat -c%s "$1") | 38 local bytes=$(stat -c%s "$1") |
39 local sectors=$(( $bytes / 512 )) | 39 local sectors=$(( $bytes / 512 )) |
40 local rem=$(( $bytes % 512 )) | 40 local rem=$(( $bytes % 512 )) |
41 if [ $rem -ne 0 ]; then | 41 if [ $rem -ne 0 ]; then |
42 sectors=$(( $sectors + 1 )) | 42 sectors=$(( $sectors + 1 )) |
43 fi | 43 fi |
44 echo $sectors | 44 echo $sectors |
45 ;; | 45 ;; |
46 esac | 46 esac |
47 } | 47 } |
48 | 48 |
49 # Round a number of 512-byte sectors up to an integral number of 4096-byte | 49 # Round a number of 512-byte sectors up to an integral number of 4096-byte |
50 # blocks. | 50 # blocks. |
51 # Invoke as: subshell | 51 # Invoke as: subshell |
52 # Args: SECTORS | 52 # Args: SECTORS |
53 # Return: Next largest multiple-of-8 sectors (ex: 4->8, 33->40, 32->32) | 53 # Return: Next largest multiple-of-8 sectors (ex: 4->8, 33->40, 32->32) |
54 roundup() { | 54 roundup() { |
55 local num=$1 | 55 local num=$1 |
56 local rem=$(( $num % 8 )) | 56 local rem=$(( $num % 8 )) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 echo "can't find gpt tool" 1>&2 | 88 echo "can't find gpt tool" 1>&2 |
89 exit 1 | 89 exit 1 |
90 fi | 90 fi |
91 fi | 91 fi |
92 | 92 |
93 | 93 |
94 # This installs a GPT into the specified device or file, using the given | 94 # This installs a GPT into the specified device or file, using the given |
95 # components. If the target is a block device or the FORCE_FULL arg is "true" | 95 # components. If the target is a block device or the FORCE_FULL arg is "true" |
96 # we'll do a full install. Otherwise, it'll be just enough to boot. | 96 # we'll do a full install. Otherwise, it'll be just enough to boot. |
97 # Invoke as: command (not subshell) | 97 # Invoke as: command (not subshell) |
98 # Args: TARGET ROOTFS_IMG KERNEL_IMG STATEFUL_IMG PMBRCODE FORCE_FULL | 98 # Args: TARGET ROOTFS_IMG KERNEL_IMG STATEFUL_IMG PMBRCODE ESP_IMG FORCE_FULL |
99 # Return: nothing | 99 # Return: nothing |
100 # Side effects: Sets these global variables describing the GPT partitions | 100 # Side effects: Sets these global variables describing the GPT partitions |
101 # (all untis are 512-byte sectors): | 101 # (all untis are 512-byte sectors): |
102 # NUM_KERN_SECTORS | 102 # NUM_KERN_SECTORS |
103 # NUM_ROOTFS_SECTORS | 103 # NUM_ROOTFS_SECTORS |
104 # NUM_STATEFUL_SECTORS | 104 # NUM_STATEFUL_SECTORS |
105 # NUM_RESERVED_SECTORS | 105 # NUM_RESERVED_SECTORS |
| 106 # NUM_ESP_SECTORS |
106 # START_KERN_A | 107 # START_KERN_A |
107 # START_STATEFUL | 108 # START_STATEFUL |
108 # START_ROOTFS_A | 109 # START_ROOTFS_A |
109 # START_KERN_B | 110 # START_KERN_B |
110 # START_ROOTFS_B | 111 # START_ROOTFS_B |
111 # START_RESERVED | 112 # START_RESERVED |
| 113 # START_ESP |
112 install_gpt() { | 114 install_gpt() { |
113 local outdev=$1 | 115 local outdev=$1 |
114 local rootfs_img=$2 | 116 local rootfs_img=$2 |
115 local kernel_img=$3 | 117 local kernel_img=$3 |
116 local stateful_img=$4 | 118 local stateful_img=$4 |
117 local pmbrcode=$5 | 119 local pmbrcode=$5 |
118 local force_full="${6:-}" | 120 local esp_img=$6 |
| 121 local force_full="${7:-}" |
119 | 122 |
120 # The gpt tool requires a fixed-size target to work on, so we may have to | 123 # The gpt tool requires a fixed-size target to work on, so we may have to |
121 # create a file of the appropriate size. Let's figure out what that size is | 124 # create a file of the appropriate size. Let's figure out what that size is |
122 # now. The partition layout is gonna look something like this: | 125 # now. The partition layout is gonna look something like this: |
123 # | 126 # |
124 # PMBR (512 bytes) | 127 # PMBR (512 bytes) |
125 # Primary GPT Header (512 bytes) | 128 # Primary GPT Header (512 bytes) |
126 # Primary GPT Table (16K) | 129 # Primary GPT Table (16K) |
127 # Kernel A partition 2 | 130 # Kernel A partition 2 |
128 # Kernel B partition 4 | 131 # Kernel B partition 4 |
(...skipping 13 matching lines...) Expand all Loading... |
142 # the size of the stateful partition. | 145 # the size of the stateful partition. |
143 # | 146 # |
144 # One nonobvious contraint is that the ext2-based filesystems typically use | 147 # One nonobvious contraint is that the ext2-based filesystems typically use |
145 # 4096-byte blocks. We'll need a little padding at each end of the disk to | 148 # 4096-byte blocks. We'll need a little padding at each end of the disk to |
146 # align the useable space to that size boundary. | 149 # align the useable space to that size boundary. |
147 | 150 |
148 # Here are the size limits that we're currently requiring | 151 # Here are the size limits that we're currently requiring |
149 local max_kern_sectors=32768 # 16M | 152 local max_kern_sectors=32768 # 16M |
150 local max_rootfs_sectors=2097152 # 1G | 153 local max_rootfs_sectors=2097152 # 1G |
151 local max_reserved_sectors=131072 # 64M | 154 local max_reserved_sectors=131072 # 64M |
| 155 local max_esp_sectors=32768 # 16M |
152 local min_stateful_sectors=262144 # 128M, expands to fill available space | 156 local min_stateful_sectors=262144 # 128M, expands to fill available space |
153 | 157 |
154 local num_pmbr_sectors=1 | 158 local num_pmbr_sectors=1 |
155 local num_gpt_hdr_sectors=1 | 159 local num_gpt_hdr_sectors=1 |
156 local num_gpt_table_sectors=32 # 16K | 160 local num_gpt_table_sectors=32 # 16K |
157 local num_footer_sectors=$(($num_gpt_hdr_sectors + $num_gpt_table_sectors)) | 161 local num_footer_sectors=$(($num_gpt_hdr_sectors + $num_gpt_table_sectors)) |
158 local num_header_sectors=$(($num_pmbr_sectors + $num_footer_sectors)) | 162 local num_header_sectors=$(($num_pmbr_sectors + $num_footer_sectors)) |
159 | 163 |
160 local start_useful=$(roundup $num_header_sectors) | 164 local start_useful=$(roundup $num_header_sectors) |
161 | 165 |
162 # What are we doing? | 166 # What are we doing? |
163 if [ -b "$outdev" -o "$force_full" = "true" ]; then | 167 if [ -b "$outdev" -o "$force_full" = "true" ]; then |
164 # Block device, need to be root. | 168 # Block device, need to be root. |
165 if [ -b "$outdev" ]; then | 169 if [ -b "$outdev" ]; then |
166 local sudo=sudo | 170 local sudo=sudo |
167 else | 171 else |
168 local sudo="" | 172 local sudo="" |
169 fi | 173 fi |
170 | 174 |
171 # Full install, use max sizes and create both A & B images. | 175 # Full install, use max sizes and create both A & B images. |
172 NUM_KERN_SECTORS=$max_kern_sectors | 176 NUM_KERN_SECTORS=$max_kern_sectors |
173 NUM_ROOTFS_SECTORS=$max_rootfs_sectors | 177 NUM_ROOTFS_SECTORS=$max_rootfs_sectors |
| 178 NUM_ESP_SECTORS=$max_esp_sectors |
174 NUM_RESERVED_SECTORS=$max_reserved_sectors | 179 NUM_RESERVED_SECTORS=$max_reserved_sectors |
175 | 180 |
176 # Where do things go? | 181 # Where do things go? |
177 START_KERN_A=$start_useful | 182 START_KERN_A=$start_useful |
178 START_KERN_B=$(($START_KERN_A + $NUM_KERN_SECTORS)) | 183 START_KERN_B=$(($START_KERN_A + $NUM_KERN_SECTORS)) |
179 START_RESERVED=$(($START_KERN_B + $NUM_KERN_SECTORS)) | 184 START_ESP=$(($START_KERN_B + $NUM_KERN_SECTORS)) |
| 185 START_RESERVED=$(($START_ESP + $NUM_ESP_SECTORS)) |
180 START_STATEFUL=$(($START_RESERVED + $NUM_RESERVED_SECTORS)) | 186 START_STATEFUL=$(($START_RESERVED + $NUM_RESERVED_SECTORS)) |
181 | 187 |
182 local total_sectors=$(numsectors $outdev) | 188 local total_sectors=$(numsectors $outdev) |
183 local start_gpt_footer=$(($total_sectors - $num_footer_sectors)) | 189 local start_gpt_footer=$(($total_sectors - $num_footer_sectors)) |
184 local end_useful=$(rounddown $start_gpt_footer) | 190 local end_useful=$(rounddown $start_gpt_footer) |
185 | 191 |
186 START_ROOTFS_A=$(($end_useful - $NUM_ROOTFS_SECTORS)) | 192 START_ROOTFS_A=$(($end_useful - $NUM_ROOTFS_SECTORS)) |
187 START_ROOTFS_B=$(($START_ROOTFS_A - $NUM_ROOTFS_SECTORS)) | 193 START_ROOTFS_B=$(($START_ROOTFS_A - $NUM_ROOTFS_SECTORS)) |
188 | 194 |
189 NUM_STATEFUL_SECTORS=$(($START_ROOTFS_B - $START_STATEFUL)) | 195 NUM_STATEFUL_SECTORS=$(($START_ROOTFS_B - $START_STATEFUL)) |
190 else | 196 else |
191 # Just a local file. | 197 # Just a local file. |
192 local sudo= | 198 local sudo= |
193 | 199 |
194 # We'll only populate partitions 1, 2, 3. Image B isn't required for this, | 200 # We'll only populate partitions 1, 2, 3. Image B isn't required for this, |
195 # and the others are still theoretical. | 201 # and the others are still theoretical. |
196 NUM_KERN_SECTORS=$(roundup $(numsectors $kernel_img)) | 202 NUM_KERN_SECTORS=$(roundup $(numsectors $kernel_img)) |
197 NUM_ROOTFS_SECTORS=$(roundup $(numsectors $rootfs_img)) | 203 NUM_ROOTFS_SECTORS=$(roundup $(numsectors $rootfs_img)) |
198 NUM_STATEFUL_SECTORS=$(roundup $(numsectors $stateful_img)) | 204 NUM_STATEFUL_SECTORS=$(roundup $(numsectors $stateful_img)) |
| 205 NUM_ESP_SECTORS=$(roundup $(numsectors $esp_img)) |
199 NUM_RESERVED_SECTORS=0 | 206 NUM_RESERVED_SECTORS=0 |
200 | 207 |
201 START_KERN_A=$start_useful | 208 START_KERN_A=$start_useful |
202 START_STATEFUL=$(($START_KERN_A + $NUM_KERN_SECTORS)) | 209 START_ESP=$(($START_KERN_A + $NUM_KERN_SECTORS)) |
| 210 START_STATEFUL=$(($START_ESP + $NUM_ESP_SECTORS)) |
203 START_ROOTFS_A=$(($START_STATEFUL + $NUM_STATEFUL_SECTORS)) | 211 START_ROOTFS_A=$(($START_STATEFUL + $NUM_STATEFUL_SECTORS)) |
204 START_KERN_B="" | 212 START_KERN_B="" |
205 START_ROOTFS_B="" | 213 START_ROOTFS_B="" |
206 START_RESERVED="" | 214 START_RESERVED="" |
207 | 215 |
208 # For minimal install, we're not worried about the secondary GPT header | 216 # For minimal install, we're not worried about the secondary GPT header |
209 # being at the end of the device because we're almost always writing to a | 217 # being at the end of the device because we're almost always writing to a |
210 # file. If that's not true, the secondary will just be invalid. | 218 # file. If that's not true, the secondary will just be invalid. |
211 local start_gpt_footer=$(($START_ROOTFS_A + $NUM_ROOTFS_SECTORS)) | 219 local start_gpt_footer=$(($START_ROOTFS_A + $NUM_ROOTFS_SECTORS)) |
212 local end_useful=$start_gpt_footer | 220 local end_useful=$start_gpt_footer |
213 | 221 |
214 local total_sectors=$(($start_gpt_footer + $num_footer_sectors)) | 222 local total_sectors=$(($start_gpt_footer + $num_footer_sectors)) |
215 | 223 |
216 # Create the image file if it doesn't exist. | 224 # Create the image file if it doesn't exist. |
217 if [ ! -e ${outdev} ]; then | 225 if [ ! -e ${outdev} ]; then |
218 dd if=/dev/zero of=${outdev} bs=512 count=1 seek=$(($total_sectors - 1)) | 226 dd if=/dev/zero of=${outdev} bs=512 count=1 seek=$(($total_sectors - 1)) |
219 fi | 227 fi |
220 fi | 228 fi |
221 | 229 |
222 echo "Creating partition tables..." | 230 echo "Creating partition tables..." |
223 | 231 |
224 # Zap any old partitions (otherwise gpt complains). | 232 # Zap any old partitions (otherwise gpt complains). |
225 $sudo dd if=/dev/zero of=${outdev} conv=notrunc bs=512 \ | 233 $sudo dd if=/dev/zero of=${outdev} conv=notrunc bs=512 \ |
226 count=$num_header_sectors | 234 count=$num_header_sectors |
227 $sudo dd if=/dev/zero of=${outdev} conv=notrunc bs=512 \ | 235 $sudo dd if=/dev/zero of=${outdev} conv=notrunc bs=512 \ |
228 seek=${start_gpt_footer} count=$num_footer_sectors | 236 seek=${start_gpt_footer} count=$num_footer_sectors |
229 | 237 |
230 # Create the new GPT partitions. The order determines the partition number. | 238 # Create the new GPT partitions. The order determines the partition number. |
231 # Note that the partition label is in the GPT only. The filesystem label is | 239 # Note that the partition label is in the GPT only. The filesystem label is |
232 # what's used to populate /dev/disk/by-label/, and this is not that. | 240 # what's used to populate /dev/disk/by-label/, and this is not that. |
233 $sudo $GPT create ${outdev} | 241 $sudo $GPT create ${outdev} |
234 | 242 |
235 $sudo $GPT add -b ${START_STATEFUL} -s ${NUM_STATEFUL_SECTORS} \ | 243 $sudo $GPT add -b ${START_STATEFUL} -s ${NUM_STATEFUL_SECTORS} \ |
236 -t ${STATEFUL_GUID} ${outdev} | 244 -t ${STATEFUL_GUID} ${outdev} |
237 $sudo $GPT label -i 1 -l "STATE" ${outdev} | 245 $sudo $GPT label -i 1 -l "STATE" ${outdev} |
238 | 246 |
239 $sudo $GPT add -b ${START_KERN_A} -s ${NUM_KERN_SECTORS} \ | 247 $sudo $GPT add -b ${START_KERN_A} -s ${NUM_KERN_SECTORS} \ |
240 -t ${KERN_GUID} ${outdev} | 248 -t ${KERN_GUID} ${outdev} |
241 $sudo $GPT label -i 2 -l "KERN-A" ${outdev} | 249 $sudo $GPT label -i 2 -l "KERN-A" ${outdev} |
242 | 250 |
243 $sudo $GPT add -b ${START_ROOTFS_A} -s ${NUM_ROOTFS_SECTORS} \ | 251 $sudo $GPT add -b ${START_ROOTFS_A} -s ${NUM_ROOTFS_SECTORS} \ |
244 -t ${ROOTFS_GUID} ${outdev} | 252 -t ${ROOTFS_GUID} ${outdev} |
245 $sudo $GPT label -i 3 -l "ROOT-A" ${outdev} | 253 $sudo $GPT label -i 3 -l "ROOT-A" ${outdev} |
246 | 254 |
247 # add the rest of the partitions for a full install | 255 # add the rest of the partitions for a full install |
248 if [ -n "$START_KERN_B" ]; then | 256 if [ -n "$START_KERN_B" ]; then |
249 $sudo $GPT add -b ${START_KERN_B} -s ${NUM_KERN_SECTORS} \ | 257 $sudo $GPT add -b ${START_KERN_B} -s ${NUM_KERN_SECTORS} \ |
250 -t ${KERN_GUID} ${outdev} | 258 -t ${KERN_GUID} ${outdev} |
251 $sudo $GPT label -i 4 -l "KERN-B" ${outdev} | 259 $sudo $GPT label -i 4 -l "KERN-B" ${outdev} |
252 | 260 |
253 $sudo $GPT add -b ${START_ROOTFS_B} -s ${NUM_ROOTFS_SECTORS} \ | 261 $sudo $GPT add -b ${START_ROOTFS_B} -s ${NUM_ROOTFS_SECTORS} \ |
254 -t ${ROOTFS_GUID} ${outdev} | 262 -t ${ROOTFS_GUID} ${outdev} |
255 $sudo $GPT label -i 5 -l "ROOT-B" ${outdev} | 263 $sudo $GPT label -i 5 -l "ROOT-B" ${outdev} |
256 fi | 264 fi |
257 | 265 |
| 266 # add the ESP partition |
| 267 $sudo $GPT add -b ${START_ESP} -s ${NUM_ESP_SECTORS} \ |
| 268 -t ${ESP_GUID} ${outdev} |
| 269 # FIXME: no label because I've lost count of the partition number |
| 270 # I'll fix this when I've modified gpt to accept a label arg to 'add'. |
| 271 |
258 # Create the PMBR and instruct it to boot ROOT-A | 272 # Create the PMBR and instruct it to boot ROOT-A |
259 $sudo $GPT boot -i 3 -b ${pmbrcode} ${outdev} | 273 $sudo $GPT boot -i 3 -b ${pmbrcode} ${outdev} |
260 | 274 |
261 # Display what we've got | 275 # Display what we've got |
262 $sudo $GPT -r show -l ${outdev} | 276 $sudo $GPT -r show -l ${outdev} |
263 | 277 |
264 sync | 278 sync |
265 } | 279 } |
266 | 280 |
267 | 281 |
268 # Helper function, please ignore and look below. | 282 # Helper function, please ignore and look below. |
269 _partinfo() { | 283 _partinfo() { |
270 local device=$1 | 284 local device=$1 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 # Args: DEVICE PARTNUM | 323 # Args: DEVICE PARTNUM |
310 # Returns: size (in sectors) of partition PARTNUM | 324 # Returns: size (in sectors) of partition PARTNUM |
311 partsize() { | 325 partsize() { |
312 # get string | 326 # get string |
313 local X="$(_partinfo $1 $2)" | 327 local X="$(_partinfo $1 $2)" |
314 # detect success or failure here | 328 # detect success or failure here |
315 [ -n "$X" ] | 329 [ -n "$X" ] |
316 echo ${X#* } | 330 echo ${X#* } |
317 } | 331 } |
318 | 332 |
OLD | NEW |