diff --git a/grub-core/commands/gptprio.c b/grub-core/commands/gptprio.c index ce5840b4e..6b61bb56d 100644 --- a/grub-core/commands/gptprio.c +++ b/grub-core/commands/gptprio.c @@ -91,7 +91,7 @@ grub_find_next (const char *disk_name, if (!gpt) goto done; - if (!(gpt->status & GRUB_GPT_BOTH_VALID)) + if ((gpt->status & GRUB_GPT_BOTH_VALID) != GRUB_GPT_BOTH_VALID) if (grub_gpt_repair (dev->disk, gpt)) goto done; diff --git a/grub-core/lib/gpt.c b/grub-core/lib/gpt.c index 05d50bf3e..39c5f50ba 100644 --- a/grub-core/lib/gpt.c +++ b/grub-core/lib/gpt.c @@ -649,7 +649,7 @@ grub_gpt_write (grub_disk_t disk, grub_gpt_t gpt) { /* TODO: update/repair protective MBRs too. */ - if (!(gpt->status & GRUB_GPT_BOTH_VALID)) + if ((gpt->status & GRUB_GPT_BOTH_VALID) != GRUB_GPT_BOTH_VALID) return grub_error (GRUB_ERR_BAD_PART_TABLE, "Invalid GPT data"); grub_dprintf ("gpt", "writing primary GPT to %s\n", disk->name); diff --git a/tests/gptprio_test.in b/tests/gptprio_test.in index f4aea0dc9..c5cf0f3b7 100644 --- a/tests/gptprio_test.in +++ b/tests/gptprio_test.in @@ -66,8 +66,9 @@ prio_uuid[3]="1aa5a658-5b02-414d-9b71-f7e6c151f0cd" prio_uuid[4]="8aa0240d-98af-42b0-b32a-ccbe0572d62b" create_disk_image () { + size=$1 rm -f "${img1}" - dd if=/dev/zero of="${img1}" bs=512 count=1 seek=100 status=none + dd if=/dev/zero of="${img1}" bs=512 count=1 seek=$((size - 1)) status=none ${sgdisk} \ -n 1:0:+1 -c 1:ESP -t 1:ef00 \ -n 2:0:+1 -c 2:A -t 2:"${prio_type}" -u 2:"${prio_uuid[2]}" \ @@ -76,6 +77,35 @@ create_disk_image () { "${img1}" >/dev/null } +wipe_disk_area () { + sector=$1 + size=$2 + dd if=/dev/zero of="${img1}" bs=512 count=${size} seek=${sector} conv=notrunc status=none +} + +is_zero () { + sector=$1 + size=$2 + cmp -s -i $((sector * 512)) -n $((size * 512)) /dev/zero "${img1}" +} + +check_is_zero () { + sector=$1 + size=$2 + if ! is_zero "$@"; then + echo "$size sector(s) starting at $sector should be all zero" + exit 1 + fi +} + +check_not_zero () { + sector=$1 + size=$2 + if is_zero "$@"; then + echo "$size sector(s) starting at $sector should not be all zero" + exit 1 + fi +} fmt_prio () { priority=$(( ( $1 & 15 ) << 48 )) @@ -93,10 +123,10 @@ set_prio () { check_prio () { part="$1" expect=$(fmt_prio $2 $3 $4) - result=$(LANG=C ${sgdisk} -i "${part}" "${img1}" \ + result=$(LANG=C ${sgdisk} -i "${part}" "${img1}" 2>&1 \ | awk '/^Attribute flags: / {print $3}') if [[ "${expect}" != "${result}" ]]; then - echo "Partition ${part} has attributes ${result}, not ${expect}" >&2 + echo "Partition ${part} has attributes ${result:-??}, not ${expect}" exit 1 fi } @@ -133,6 +163,33 @@ create_disk_image 100 set_prio 2 3 2 1 check_prio 2 3 2 1 +# Check gptprio works without modifying the disk when no update is required. +# Leaves any existing corruption as is, repairing in the OS is better. +create_disk_image 100 +set_prio 2 1 0 1 +wipe_disk_area 99 1 +check_next 2 1 0 1 +check_is_zero 99 1 + +create_disk_image 100 +set_prio 2 1 0 1 +wipe_disk_area 1 1 +check_next 2 1 0 1 +check_is_zero 1 1 + +# When writes do need to be made go ahead and perform the repair. +create_disk_image 100 +set_prio 2 1 1 0 +wipe_disk_area 99 1 +check_next 2 1 0 0 +check_not_zero 99 1 + +create_disk_image 100 +set_prio 2 1 1 0 +wipe_disk_area 1 1 +check_next 2 1 0 0 +check_not_zero 1 1 + # Try two partitions before falling before falling back to a third create_disk_image 100 set_prio 2 3 3 0 diff --git a/tests/gptrepair_test.in b/tests/gptrepair_test.in index 80b2de633..805dc171a 100644 --- a/tests/gptrepair_test.in +++ b/tests/gptrepair_test.in @@ -53,7 +53,7 @@ case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in esac img1="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 img2="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 -trap "rm -f '${img1}' '${ing2}'" EXIT +trap "rm -f '${img1}' '${img2}'" EXIT create_disk_image () { size=$1