Home | History | Annotate | Line # | Download | only in gpt
      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