cgpt: repair: handle drive size expansion
Currently, if the drive size increases, 'cgpt repair' correctly
updates/moves the Secondary GPT header/entries to end of drive,
but it does _NOT_ update headers to reflect the new drive size.
It 'must' as per section 5.3.2 GPT Header of the UEFI spec [1]:
Both the primary and backup GPTs must be valid before
an attempt is made to grow the size of a physical volume.
[...]
As soon as the volume size is increased the backup GPT must be
be moved to the end of the volume, and the primary and backup
GPT Headers must be updated to reflect the new volume size.
That prevents resizing/growing a partition to new available space
(as Last Usable LBA is not updated and used in valid range check),
and incorrectly points to the old secondary GPT header in primary
(as Alternate LBA is not updated).
Change CgptRepair() to check for (only) the secondary header and
entries modified (i.e., moved to end of drive) and Alternate LBA
in the primary header being less than My LBA in secondary header
(i.e., confirm secondary header moved), then update both headers.
BUG=b:396007118
TEST=`cgpt show -v $DEV | grep -E 'Alternate LBA:|Last LBA:|Sec GPT'`
after drive size expansion and `cgpt repair`, then resize partition
to all new available space (described below); and `run_cgpt_tests.sh`.
BRANCH=none
Before:
```
$ dd if=/dev/zero of=drive.img bs=512 count=2048
$ ./build/cgpt/cgpt create drive.img
$ ./build/cgpt/cgpt add -b 34 -s $((2048-33-34)) -t data drive.img
$ ./build/cgpt/cgpt show -v drive.img 2>&1 \
| grep -E '(Alternate LBA:|Last LBA:|Sec GPT|INVALID|Label)'
Alternate LBA: 2047
Last LBA: 2014
34 1981 1 Label: ""
2015 32 Sec GPT table
2047 1 Sec GPT header
$ dd if=/dev/zero of=drive.img bs=512 seek=4096 count=0
$ ./build/cgpt/cgpt repair drive.img
WARNING: Secondary GPT header is invalid
Secondary Entries is updated.
Secondary Header is updated.
$ ./build/cgpt/cgpt add -b 34 -s $((4096-33-34)) -i 1 drive.img
ERROR: Entry outside of valid region
ERROR: -i 1 -b 34 -s 4029
$ ./build/cgpt/cgpt show -v drive.img 2>&1 \
| grep -E '(Alternate LBA:|Last LBA:|Sec GPT|INVALID|Label)'
Alternate LBA: 2047
Last LBA: 2014
34 1981 1 Label: ""
4063 32 Sec GPT table
4095 1 Sec GPT header
```
After:
```
$ dd if=/dev/zero of=drive.img bs=512 count=2048
$ ./build/cgpt/cgpt create drive.img
$ ./build/cgpt/cgpt add -b 34 -s $((2048-33-34)) -t data drive.img
$ ./build/cgpt/cgpt show -v drive.img 2>&1 \
| grep -E '(Alternate LBA:|Last LBA:|Sec GPT|INVALID|Label)'
Alternate LBA: 2047
Last LBA: 2014
34 1981 1 Label: ""
2015 32 Sec GPT table
2047 1 Sec GPT header
$ dd if=/dev/zero of=drive.img bs=512 seek=4096 count=0
$ ./build/cgpt/cgpt repair drive.img
WARNING: Secondary GPT header is invalid
Secondary Entries is updated.
Secondary Header is updated.
Drive size expansion detected; headers update required.
Primary Header updated.
Secondary Header updated.
$ ./build/cgpt/cgpt add -b 34 -s $((4096-33-34)) -i 1 drive.img
$ ./build/cgpt/cgpt show -v drive.img 2>&1 \
| grep -E '(Alternate LBA:|Last LBA:|Sec GPT|INVALID|Label)'
Alternate LBA: 4095
Last LBA: 4062
34 4029 1 Label: ""
4063 32 Sec GPT table
4095 1 Sec GPT header
```
[1] https://uefi.org/sites/default/files/resources/UEFI_Spec_Final_2.11.pdf
Change-Id: Iee372277546a4f6b7ef53b4a16df4c93819af031
Signed-off-by: Mauricio Faria de Oliveira <mfo@igalia.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/6258636
Reviewed-by: Tomasz Michalec <tmichalec@google.com>
Reviewed-by: Jakub "Kuba" Czapiga <czapiga@google.com>
Commit-Queue: Jakub "Kuba" Czapiga <czapiga@google.com>
2 files changed