1 # $NetBSD: t_gpt.sh,v 1.17 2022/11/21 16:06:00 kre Exp $ 2 # 3 # Copyright (c) 2015 The NetBSD Foundation, Inc. 4 # All rights reserved. 5 # 6 # This code is derived from software contributed to The NetBSD Foundation 7 # by Christos Zoulas 8 # 9 # Redistribution and use in source and binary forms, with or without 10 # modification, are permitted provided that the following conditions 11 # are met: 12 # 1. Redistributions of source code must retain the above copyright 13 # notice, this list of conditions and the following disclaimer. 14 # 2. Redistributions in binary form must reproduce the above copyright 15 # notice, this list of conditions and the following disclaimer in the 16 # documentation and/or other materials provided with the distribution. 17 # 18 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 # POSSIBILITY OF SUCH DAMAGE. 29 # 30 31 bootblk=/usr/mdec/gptmbr.bin 32 size=10240 33 newsize=20480 34 shdr=34 35 disk=gpt.disk 36 uuid="........-....-....-....-............" 37 zero="00000000-0000-0000-0000-000000000000" 38 src=$(atf_get_srcdir) 39 40 silence() { 41 atf_check -s exit:0 -o empty -e empty "$@" 42 } 43 44 inline() { 45 local inline="$1" 46 shift 47 atf_check -s exit:0 -e empty -o inline:"$inline" "$@" 48 } 49 50 match() { 51 local match="$1" 52 shift 53 atf_check -s exit:0 -e empty -o match:"$match" "$@" 54 } 55 56 matcherr() { 57 local match="$1" 58 shift 59 atf_check -s exit:0 -o empty -e match:"$match" "$@" 60 } 61 62 file() { 63 local file="$1" 64 shift 65 atf_check -s exit:0 -e empty -o file:"$file" "$@" 66 } 67 68 save() { 69 local save="$1" 70 shift 71 atf_check -s exit:0 -e empty -o save:"$save" "$@" 72 } 73 74 zerodd() { 75 silence dd conv=notrunc msgfmt=quiet if=/dev/zero of="$disk" "$@" 76 } 77 78 prepare() { 79 rm -f "$disk" 80 zerodd seek="$size" count=1 81 } 82 83 prepare_2part() { 84 prepare 85 silence gpt create "$disk" 86 match "$(partaddmsg 1 34 1024)" gpt add -t efi -s 1024 "$disk" 87 match "$(partaddmsg 2 1058 9150)" gpt add "$disk" 88 } 89 90 # Calling this from tests does not work. BUG! 91 check_2part() { 92 file "$src/gpt.2part.show.normal" gpt show "$disk" 93 file "$src/gpt.2part.show.uuid" gpt show -u "$disk" 94 } 95 96 partaddmsg() { 97 echo "^$disk: Partition $1 added: $uuid $2 $3\$" 98 } 99 100 partresmsg() { 101 echo "^$disk: Partition $1 resized: $2 $3\$" 102 } 103 104 partremmsg() { 105 echo "^$disk: Partition $1 removed\$" 106 } 107 108 partlblmsg() { 109 echo "^$disk: Partition $1 label changed\$" 110 } 111 112 partbootmsg() { 113 echo "^$disk: Partition $1 marked as bootable\$" 114 } 115 116 recovermsg() { 117 echo "^$disk: Recovered $1 GPT [a-z]* from $2\$" 118 } 119 120 migratemsg() { 121 echo -n "^gpt: $disk: Partition $1 unknown type MSDOS, " 122 echo 'using "Microsoft Basic Data"$' 123 } 124 125 attrmsg() { 126 echo "^$disk: Partition $1 attributes updated\$" 127 } 128 129 typemsg() { 130 echo "^$disk: Partition $1 type changed\$" 131 } 132 133 atf_test_case create_empty 134 create_empty_head() { 135 atf_set "descr" "Create empty disk" 136 } 137 138 create_empty_body() { 139 prepare 140 silence gpt create "$disk" 141 file "$src/gpt.empty.show.normal" gpt show "$disk" 142 } 143 144 atf_test_case create_2part 145 create_2part_head() { 146 atf_set "descr" "Create 2 partition disk" 147 } 148 149 create_2part_body() { 150 prepare_2part 151 check_2part 152 } 153 154 atf_test_case change_attr_2part 155 change_attr_2part_head() { 156 atf_set "descr" "Change the attribute of 2 partition disk" 157 } 158 159 change_attr_2part_body() { 160 prepare_2part 161 match "$(attrmsg 1)" gpt set -i 1 -a biosboot,bootme "$disk" 162 save attr gpt show -i 1 "$disk" 163 match "^Attributes: biosboot, bootme\$" tail -1 attr 164 match "$(attrmsg 1)" gpt unset -i 1 -a biosboot,bootme "$disk" 165 save attr gpt show -i 1 "$disk" 166 match "^Attributes: None\$" tail -1 attr 167 } 168 169 atf_test_case change_type_2part 170 change_type_2part_head() { 171 atf_set "descr" "Change the partition type type of 2 partition disk" 172 } 173 174 change_type_2part_body() { 175 prepare_2part 176 match "$(typemsg 1)" gpt type -i 1 -T apple "$disk" 177 save type gpt show -i 1 "$disk" 178 inline "Type: apple (48465300-0000-11aa-aa11-00306543ecac)\n" \ 179 grep "^Type:" type 180 match "$(typemsg 1)" gpt type -i 1 -T efi "$disk" 181 save type gpt show -i 1 "$disk" 182 inline "Type: efi (c12a7328-f81f-11d2-ba4b-00a0c93ec93b)\n" \ 183 grep "^Type:" type 184 } 185 186 atf_test_case backup_2part 187 backup_2part_head() { 188 atf_set "descr" "Backup 2 partition disk" 189 } 190 191 backup_2part_body() { 192 prepare_2part 193 save test.backup gpt backup "$disk" 194 file "$src/gpt.backup" sed -e "s/$uuid/$zero/g" "test.backup" 195 } 196 197 atf_test_case restore_2part 198 restore_2part_head() { 199 atf_set "descr" "Restore 2 partition disk" 200 } 201 202 restore_2part_body() { 203 prepare_2part 204 save test.backup gpt backup "$disk" 205 prepare 206 silence gpt restore -i test.backup "$disk" 207 check_2part 208 } 209 210 atf_test_case recover_backup 211 recover_backup_head() { 212 atf_set "descr" "Recover the backup GPT header and table" 213 } 214 215 recover_backup_body() { 216 prepare_2part 217 zerodd seek="$((size - shdr))" count="$shdr" 218 match "$(recovermsg secondary primary)" gpt recover "$disk" 219 check_2part 220 } 221 222 atf_test_case recover_primary 223 recover_primary_head() { 224 atf_set "descr" "Recover the primary GPT header and table" 225 } 226 227 recover_primary_body() { 228 prepare_2part 229 zerodd seek=1 count="$shdr" 230 match "$(recovermsg primary secondary)" gpt recover "$disk" 231 check_2part 232 } 233 234 atf_test_case resize_2part 235 resize_2part_head() { 236 atf_set "descr" "Resize a 2 partition disk and partition" 237 } 238 239 resize_2part_body() { 240 prepare_2part 241 zerodd seek="$newsize" count=1 242 match 'Moving secondary GPT header' gpt resizedisk "$disk" 243 file "$src/gpt.resizedisk.show.normal" gpt show "$disk" 244 match "$(partresmsg 2 1058 19390)" gpt resize -i 2 "$disk" 245 file "$src/gpt.resizepart.show.normal" gpt show "$disk" 246 } 247 248 atf_test_case remove_2part 249 remove_2part_head() { 250 atf_set "descr" "Remove a partition from a 2 partition disk" 251 } 252 253 remove_2part_body() { 254 prepare_2part 255 match "$(partremmsg 1)" -e empty gpt remove \ 256 -i 1 "$disk" 257 file "$src/gpt.removepart.show.normal" \ 258 gpt show "$disk" 259 } 260 261 atf_test_case label_2part 262 label_2part_head() { 263 atf_set "descr" "Label partitions in a 2 partition disk" 264 } 265 266 label_2part_body() { 267 prepare_2part 268 match "$(partlblmsg 1)" gpt label -i 1 -l potato "$disk" 269 match "$(partlblmsg 2)" gpt label -i 2 -l tomato "$disk" 270 file "$src/gpt.2part.show.label" \ 271 gpt show -l "$disk" 272 } 273 274 atf_test_case bootable_2part 275 bootable_2part_head() { 276 atf_set "descr" "Make partition 2 bootable in a 2 partition disk" 277 atf_set "require.files" "$bootblk" 278 } 279 280 bootable_2part_body() { 281 prepare_2part 282 match "$(partbootmsg 2)" gpt biosboot -i 2 "$disk" 283 local bootsz="$(ls -l "$bootblk" | awk '{ print $5 }')" 284 silence dd msgfmt=quiet if="$disk" of=bootblk bs=1 count="$bootsz" 285 silence cmp "$bootblk" bootblk 286 save bootattr gpt show -i 2 "$disk" 287 match "^Attributes: biosboot\$" tail -1 bootattr 288 } 289 290 atf_test_case migrate_disklabel 291 migrate_disklabel_head() { 292 atf_set "descr" "Migrate an MBR+disklabel disk to GPT" 293 } 294 295 migrate_disklabel_body() { 296 if [ $( sysctl -n kern.rawpartition ) -ne 3 ]; then 297 atf_skip "This test is specific to architectures using MBR" 298 fi 299 300 prepare 301 silence fdisk -fi "$disk" 302 silence fdisk -fu0s "169/63/$((size / 10))" "$disk" 303 silence disklabel -R "$disk" "$src/gpt.disklabel" 304 matcherr "$(migratemsg 5)" gpt migrate "$disk" 305 file "$src/gpt.disklabel.show.normal" gpt show "$disk" 306 } 307 308 atf_init_test_cases() { 309 atf_add_test_case create_empty 310 atf_add_test_case create_2part 311 atf_add_test_case change_attr_2part 312 atf_add_test_case change_type_2part 313 atf_add_test_case backup_2part 314 atf_add_test_case remove_2part 315 atf_add_test_case restore_2part 316 atf_add_test_case recover_backup 317 atf_add_test_case recover_primary 318 atf_add_test_case resize_2part 319 atf_add_test_case label_2part 320 atf_add_test_case bootable_2part 321 atf_add_test_case migrate_disklabel 322 } 323