1#!/bin/bash -eu 2 3# Copyright 2010 The ChromiumOS Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6# 7# Run tests for cgpt utility. 8 9# Load common constants and variables. 10. "$(dirname "$0")/common.sh" 11 12CGPT=$(readlink -f "$1") 13[ -x ""${CGPT}"" ] || error "Can't execute $CGPT" 14 15MTD=("${@:2}") 16 17# Run tests in a dedicated directory for easy cleanup or debugging. 18DIR="${TEST_DIR}/cgpt_test_dir" 19[ -d "$DIR" ] || mkdir -p "$DIR" 20warning "testing "${CGPT}" in $DIR" 21cd "$DIR" 22 23assert_fail() { 24 set +e 25 if "$@" 2>/dev/null; then 26 error "$*" " should have failed but did not" 27 fi 28 set -e 29} 30 31# Test failure on non existing file. 32assert_fail "${CGPT}" show "${MTD[@]}" blah_404_haha 33 34echo "Create an empty file to use as the device..." 35NUM_SECTORS=1000 36DEV=fake_dev.bin 37rm -f ${DEV} 38dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=${NUM_SECTORS} 2>/dev/null 39 40DATA_START=100 41DATA_SIZE=20 42DATA_LABEL="data stuff" 43DATA_GUID='0fc63daf-8483-4772-8e79-3d69d8477de4' 44DATA_NUM=1 45 46KERN_START=200 47KERN_SIZE=30 48KERN_LABEL="kernel stuff" 49KERN_GUID='fe3a2a5d-4f32-41a7-b725-accc3285a309' 50KERN_NUM=2 51 52ROOTFS_START=300 53ROOTFS_SIZE=40 54ROOTFS_LABEL="rootfs stuff" 55ROOTFS_GUID='3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec' 56ROOTFS_NUM=3 57 58ESP_START=400 59ESP_SIZE=50 60ESP_LABEL="ESP stuff" 61ESP_GUID='c12a7328-f81f-11d2-ba4b-00a0c93ec93b' 62ESP_NUM=4 63 64FUTURE_START=500 65FUTURE_SIZE=60 66FUTURE_LABEL="future stuff" 67FUTURE_GUID='2e0a753d-9e48-43b0-8337-b15192cb1b5e' 68FUTURE_NUM=5 69 70RANDOM_START=600 71RANDOM_SIZE=70 72RANDOM_LABEL="random stuff" 73RANDOM_GUID='2364a860-bf63-42fb-a83d-9ad3e057fcf5' 74RANDOM_NUM=6 75 76RANDOM_DRIVE_GUID='12345678-0000-1111-2222-123456789ABC' 77 78"${CGPT}" create "${MTD[@]}" ${DEV} 79 80run_basic_tests() { 81 echo "Create a bunch of partitions, using the real GUID types..." 82 83 "${CGPT}" add "${MTD[@]}" -b ${DATA_START} -s ${DATA_SIZE} -t ${DATA_GUID} \ 84 -l "${DATA_LABEL}" ${DEV} 85 "${CGPT}" add "${MTD[@]}" -b ${KERN_START} -s ${KERN_SIZE} -t ${KERN_GUID} \ 86 -l "${KERN_LABEL}" ${DEV} 87 "${CGPT}" add "${MTD[@]}" -b ${ROOTFS_START} -s ${ROOTFS_SIZE} \ 88 -t ${ROOTFS_GUID} -l "${ROOTFS_LABEL}" ${DEV} 89 "${CGPT}" add "${MTD[@]}" -b ${ESP_START} -s ${ESP_SIZE} -t ${ESP_GUID} \ 90 -l "${ESP_LABEL}" ${DEV} 91 "${CGPT}" add "${MTD[@]}" -b ${FUTURE_START} -s ${FUTURE_SIZE} \ 92 -t ${FUTURE_GUID} -l "${FUTURE_LABEL}" ${DEV} 93 "${CGPT}" add "${MTD[@]}" -b ${RANDOM_START} -s ${RANDOM_SIZE} \ 94 -t ${RANDOM_GUID} -l "${RANDOM_LABEL}" ${DEV} 95 96 97 echo "Extract the start and size of given partitions..." 98 99 X=$("${CGPT}" show "${MTD[@]}" -b -i $DATA_NUM ${DEV}) 100 Y=$("${CGPT}" show "${MTD[@]}" -s -i $DATA_NUM ${DEV}) 101 [ "$X $Y" = "$DATA_START $DATA_SIZE" ] || error 102 103 X=$("${CGPT}" show "${MTD[@]}" -b -i $KERN_NUM ${DEV}) 104 Y=$("${CGPT}" show "${MTD[@]}" -s -i $KERN_NUM ${DEV}) 105 [ "$X $Y" = "$KERN_START $KERN_SIZE" ] || error 106 107 X=$("${CGPT}" show "${MTD[@]}" -b -i $ROOTFS_NUM ${DEV}) 108 Y=$("${CGPT}" show "${MTD[@]}" -s -i $ROOTFS_NUM ${DEV}) 109 [ "$X $Y" = "$ROOTFS_START $ROOTFS_SIZE" ] || error 110 111 X=$("${CGPT}" show "${MTD[@]}" -b -i $ESP_NUM ${DEV}) 112 Y=$("${CGPT}" show "${MTD[@]}" -s -i $ESP_NUM ${DEV}) 113 [ "$X $Y" = "$ESP_START $ESP_SIZE" ] || error 114 115 X=$("${CGPT}" show "${MTD[@]}" -b -i $FUTURE_NUM ${DEV}) 116 Y=$("${CGPT}" show "${MTD[@]}" -s -i $FUTURE_NUM ${DEV}) 117 [ "$X $Y" = "$FUTURE_START $FUTURE_SIZE" ] || error 118 119 X=$("${CGPT}" show "${MTD[@]}" -b -i $RANDOM_NUM ${DEV}) 120 Y=$("${CGPT}" show "${MTD[@]}" -s -i $RANDOM_NUM ${DEV}) 121 [ "$X $Y" = "$RANDOM_START $RANDOM_SIZE" ] || error 122 123 124 echo "Change the beginning..." 125 DATA_START=$((DATA_START + 10)) 126 "${CGPT}" add "${MTD[@]}" -i 1 -b ${DATA_START} ${DEV} || error 127 X=$("${CGPT}" show "${MTD[@]}" -b -i 1 ${DEV}) 128 [ "$X" = "$DATA_START" ] || error 129 130 echo "Change the size..." 131 DATA_SIZE=$((DATA_SIZE + 10)) 132 "${CGPT}" add "${MTD[@]}" -i 1 -s ${DATA_SIZE} ${DEV} || error 133 X=$("${CGPT}" show "${MTD[@]}" -s -i 1 ${DEV}) 134 [ "$X" = "$DATA_SIZE" ] || error 135 136 echo "Change the type..." 137 "${CGPT}" add "${MTD[@]}" -i 1 -t reserved ${DEV} || error 138 X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV} | tr '[:upper:]' '[:lower:]') 139 [ "$X" = "$FUTURE_GUID" ] || error 140 # arbitrary value 141 "${CGPT}" add "${MTD[@]}" -i 1 -t 610a563a-a55c-4ae0-ab07-86e5bb9db67f \ 142 ${DEV} || error 143 X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV}) 144 [ "$X" = "610A563A-A55C-4AE0-AB07-86E5BB9DB67F" ] || error 145 146 "${CGPT}" add "${MTD[@]}" -i 1 -t data ${DEV} || error 147 X=$("${CGPT}" show "${MTD[@]}" -t -i 1 ${DEV} | tr '[:upper:]' '[:lower:]') 148 [ "$X" = "$DATA_GUID" ] || error 149 150 ORIG_ID=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | \ 151 grep -i "disk uuid" | head -1 | awk ' { print $3 } ' ) 152 [ ! "$ORIG_ID" = "$RANDOM_DRIVE_GUID" ] || error 153 "${CGPT}" edit "${MTD[@]}" -u ${RANDOM_DRIVE_GUID} ${DEV} || error 154 X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \ 155 head -1 | awk ' { print $3 } ' ) 156 [ "$X" = "${RANDOM_DRIVE_GUID}" ] || error 157 "${CGPT}" edit "${MTD[@]}" -u "${ORIG_ID}" ${DEV} || error 158 X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \ 159 head -1 | awk ' { print $3 } ' ) 160 [ "$X" = "${ORIG_ID}" ] || error 161} 162run_basic_tests 163 164ORIG_ID=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | \ 165 grep -i "disk uuid" | awk ' { print $3 } ' ) 166[ ! "$ORIG_ID" = "$RANDOM_DRIVE_GUID" ] || error 167"${CGPT}" edit "${MTD[@]}" -u ${RANDOM_DRIVE_GUID} ${DEV} || error 168X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \ 169 head -1 | awk ' { print $3 } ' ) 170[ "$X" = "${RANDOM_DRIVE_GUID}" ] || error 171"${CGPT}" edit "${MTD[@]}" -u "${ORIG_ID}" ${DEV} || error 172X=$("${CGPT}" show "${MTD[@]}" -v ${DEV} | grep -i "disk uuid" | \ 173 awk ' { print $3 } ' ) 174[ "$X" = "${ORIG_ID}" ] || error 175 176echo "Set the boot partition.." 177"${CGPT}" boot "${MTD[@]}" -i ${KERN_NUM} ${DEV} >/dev/null 178 179echo "Check the PMBR's idea of the boot partition..." 180X=$("${CGPT}" boot "${MTD[@]}" ${DEV}) 181Y=$("${CGPT}" show "${MTD[@]}" -u -i $KERN_NUM $DEV) 182[ "$X" = "$Y" ] || error 183 184# Input: sequence of priorities 185# Output: ${DEV} has kernel partitions with the given priorities 186make_pri() { 187 local idx=0 188 "${CGPT}" create "${MTD[@]}" ${DEV} 189 for pri in "$@"; do 190 idx=$((idx+1)) 191 "${CGPT}" add "${MTD[@]}" -t kernel -l "kern$idx" -b $((100 + 2 * idx)) \ 192 -s 1 -P $pri ${DEV} 193 done 194} 195 196# Output: returns string containing priorities of all kernels 197get_pri() { 198 local output=() 199 for idx in $("${CGPT}" find "${MTD[@]}" -t kernel ${DEV} | sed -e s@${DEV}@@); 200 do 201 output+=("$("${CGPT}" show "${MTD[@]}" -i "$idx" -P ${DEV})") 202 done 203 echo "${output[@]}" 204} 205 206# Input: list of priorities 207# Operation: expects ${DEV} to contain those kernel priorities 208assert_pri() { 209 local expected="$*" 210 local actual 211 actual=$(get_pri) 212 [ "$actual" = "$expected" ] || \ 213 error 1 "expected priority \"$expected\", actual priority \"$actual\"" 214} 215 216# no kernels at all. This should do nothing. 217"${CGPT}" create "${MTD[@]}" ${DEV} 218 219run_prioritize_tests() { 220 echo "Test the cgpt prioritize command..." 221 "${CGPT}" add "${MTD[@]}" -t rootfs -b 100 -s 1 ${DEV} 222 "${CGPT}" prioritize "${MTD[@]}" ${DEV} 223 assert_pri "" 224 225 # common install/upgrade sequence 226 make_pri 2 0 0 227 "${CGPT}" prioritize "${MTD[@]}" -i 1 ${DEV} 228 assert_pri 1 0 0 229 "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV} 230 assert_pri 1 2 0 231 "${CGPT}" prioritize "${MTD[@]}" -i 1 ${DEV} 232 assert_pri 2 1 0 233 "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV} 234 assert_pri 1 2 0 235 # lots of kernels, all same starting priority, should go to priority 1 236 make_pri 8 8 8 8 8 8 8 8 8 8 8 0 0 8 237 "${CGPT}" prioritize "${MTD[@]}" ${DEV} 238 assert_pri 1 1 1 1 1 1 1 1 1 1 1 0 0 1 239 240 # now raise them all up again 241 "${CGPT}" prioritize "${MTD[@]}" -P 4 ${DEV} 242 assert_pri 4 4 4 4 4 4 4 4 4 4 4 0 0 4 243 244 # set one of them higher, should leave the rest alone 245 "${CGPT}" prioritize "${MTD[@]}" -P 5 -i 3 ${DEV} 246 assert_pri 4 4 5 4 4 4 4 4 4 4 4 0 0 4 247 248 # set one of them lower, should bring the rest down 249 "${CGPT}" prioritize "${MTD[@]}" -P 3 -i 4 ${DEV} 250 assert_pri 1 1 2 3 1 1 1 1 1 1 1 0 0 1 251 252 # raise a group by including the friends of one partition 253 "${CGPT}" prioritize "${MTD[@]}" -P 6 -i 1 -f ${DEV} 254 assert_pri 6 6 4 5 6 6 6 6 6 6 6 0 0 6 255 256 # resurrect one, should not affect the others 257 make_pri 0 0 0 0 0 0 0 0 0 0 0 0 0 0 258 "${CGPT}" prioritize "${MTD[@]}" -i 2 ${DEV} 259 assert_pri 0 1 0 0 0 0 0 0 0 0 0 0 0 0 260 261 # resurrect one and all its friends 262 make_pri 0 0 0 0 0 0 0 0 1 2 0 0 0 0 263 "${CGPT}" prioritize "${MTD[@]}" -P 5 -i 2 -f ${DEV} 264 assert_pri 5 5 5 5 5 5 5 5 3 4 5 5 5 5 265 266 # no options should maintain the same order 267 "${CGPT}" prioritize "${MTD[@]}" ${DEV} 268 assert_pri 3 3 3 3 3 3 3 3 1 2 3 3 3 3 269 270 # squish all the ranks 271 make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7 272 "${CGPT}" prioritize "${MTD[@]}" -P 6 ${DEV} 273 assert_pri 1 1 1 1 2 2 3 3 4 4 0 5 6 6 274 275 # squish the ranks by not leaving room 276 make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7 277 "${CGPT}" prioritize "${MTD[@]}" -P 7 -i 3 ${DEV} 278 assert_pri 1 1 7 1 2 2 3 3 4 4 0 5 6 6 279 280 # squish the ranks while bringing the friends along 281 make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7 282 "${CGPT}" prioritize "${MTD[@]}" -P 6 -i 3 -f ${DEV} 283 assert_pri 1 1 6 6 1 1 2 2 3 3 0 4 5 5 284 285 # squish them pretty hard 286 make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7 287 "${CGPT}" prioritize "${MTD[@]}" -P 2 ${DEV} 288 assert_pri 1 1 1 1 1 1 1 1 1 1 0 1 2 2 289 290 # squish them really really hard (nobody gets reduced to zero, though) 291 make_pri 1 1 2 2 3 3 4 4 5 5 0 6 7 7 292 "${CGPT}" prioritize "${MTD[@]}" -P 1 -i 3 ${DEV} 293 assert_pri 1 1 1 1 1 1 1 1 1 1 0 1 1 1 294 295 make_pri 15 15 14 14 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 296 "${CGPT}" prioritize "${MTD[@]}" -i 3 ${DEV} 297 assert_pri 14 14 15 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 0 298 "${CGPT}" prioritize "${MTD[@]}" -i 5 ${DEV} 299 assert_pri 13 13 14 12 15 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1 1 0 300 # but if I bring friends I don't have to squish 301 "${CGPT}" prioritize "${MTD[@]}" -i 1 -f ${DEV} 302 assert_pri 15 15 13 12 14 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 1 1 1 1 0 303} 304run_prioritize_tests 305 306echo "Test cgpt repair command" 307"${CGPT}" repair "${MTD[@]}" ${DEV} 308("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error 309 310# Zero primary header and partition table and try to repair it. 311dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=33 2>/dev/null 312"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID 313"${CGPT}" repair "${MTD[@]}" ${DEV} 314("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error 315 316# Zero secondary header and partition table and try to repair it. 317dd if=/dev/zero of=${DEV} seek=$((NUM_SECTORS - 33)) conv=notrunc bs=512 \ 318 count=33 2>/dev/null 319"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID 320"${CGPT}" repair "${MTD[@]}" ${DEV} 321("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q INVALID) && error 322 323echo "Test with IGNOREME primary GPT..." 324"${CGPT}" create "${MTD[@]}" ${DEV} 325"${CGPT}" legacy "${MTD[@]}" -p ${DEV} 326"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT" 2>/dev/null 327("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && \ 328 error 329"${CGPT}" repair "${MTD[@]}" ${DEV} 2>/dev/null 330"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT" 2>/dev/null 331("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table" 2>/dev/null) && \ 332 error 333"${CGPT}" legacy "${MTD[@]}" -e ${DEV} 2>/dev/null 334("${CGPT}" show "${MTD[@]}" ${DEV} | grep -q -E "IGNORED.*Pri GPT") && error 335"${CGPT}" show "${MTD[@]}" ${DEV} | grep -q "Pri GPT table" 336 337"${CGPT}" create "${MTD[@]}" ${DEV} 338"${CGPT}" legacy "${MTD[@]}" -p ${DEV} 339run_basic_tests 2>/dev/null 340 341"${CGPT}" create "${MTD[@]}" ${DEV} 342"${CGPT}" legacy "${MTD[@]}" -p ${DEV} 343run_prioritize_tests 2>/dev/null 344 345# Now make sure that we don't need write access if we're just looking. 346echo "Test read vs read-write access..." 347chmod 0444 ${DEV} 348 349# These should fail 350"${CGPT}" create "${MTD[@]}" -z ${DEV} 2>/dev/null && error 351"${CGPT}" add "${MTD[@]}" -i 2 -P 3 ${DEV} 2>/dev/null && error 352"${CGPT}" repair "${MTD[@]}" ${DEV} 2>/dev/null && error 353"${CGPT}" prioritize "${MTD[@]}" -i 3 ${DEV} 2>/dev/null && error 354 355# Most 'boot' usage should fail too. 356"${CGPT}" boot "${MTD[@]}" -p ${DEV} 2>/dev/null && error 357dd if=/dev/zero of=fake_mbr.bin bs=100 count=1 2>/dev/null 358"${CGPT}" boot "${MTD[@]}" -b fake_mbr.bin ${DEV} 2>/dev/null && error 359"${CGPT}" boot "${MTD[@]}" -i 2 ${DEV} 2>/dev/null && error 360 361"${CGPT}" boot "${MTD[@]}" ${DEV} >/dev/null 362"${CGPT}" show "${MTD[@]}" ${DEV} >/dev/null 363"${CGPT}" find "${MTD[@]}" -t kernel ${DEV} >/dev/null 364 365# Enable write access again to test boundary in off device storage 366chmod 600 ${DEV} 367# GPT too small 368dd if=/dev/zero of=${DEV} bs=5632 count=1 369assert_fail ""${CGPT}"" create -D 1024 ${DEV} 370# GPT is just right for 16 entries (512 + 512 + 16 * 128) * 2 = 6144 371dd if=/dev/zero of=${DEV} bs=6144 count=1 372"${CGPT}" create -D 1024 ${DEV} 373# Create a small 8K file to simulate Flash NOR section 374dd if=/dev/zero of=${DEV} bs=8K count=1 375# Drive size is not multiple of 512 376assert_fail ""${CGPT}"" create -D 511 ${DEV} 377assert_fail ""${CGPT}"" create -D 513 ${DEV} 378# Create a GPT table for a device of 1024 bytes (2 sectors) 379"${CGPT}" create -D 1024 ${DEV} 380# Make sure number of entries is reasonable for 8KiB GPT 381X=$("${CGPT}" show -D 1024 -d ${DEV} | grep -c "Number of entries: 24") 382[ "$X" = "2" ] || error 383# This fails because header verification is off due to different drive size 384assert_fail ""${CGPT}"" show ${DEV} 385# But this passes because we pass in correct drive size 386"${CGPT}" show -D 1024 ${DEV} 387# This fails because beginning sector is over the size of the device 388assert_fail ""${CGPT}"" add -D 1024 -b 2 -s 1 -t data ${DEV} 389# This fails because partition size is over the size of the device 390assert_fail ""${CGPT}"" add -D 1024 -b 0 -s 3 -t data ${DEV} 391 392 393echo "Done." 394 395happy "All tests passed." 396