summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgpt/cgpt_repair.c18
-rw-r--r--firmware/include/gpt_misc.h4
-rw-r--r--firmware/lib/cgptlib/include/cgptlib_internal.h4
-rwxr-xr-xtests/run_cgpt_tests.sh16
4 files changed, 40 insertions, 2 deletions
diff --git a/cgpt/cgpt_repair.c b/cgpt/cgpt_repair.c
index 1880ea5b..ebe034b1 100644
--- a/cgpt/cgpt_repair.c
+++ b/cgpt/cgpt_repair.c
@@ -24,6 +24,24 @@ int CgptRepair(CgptRepairParams *params) {
printf("GptSanityCheck() returned %d: %s\n",
gpt_retval, GptError(gpt_retval));
+ GptHeader *header;
+ if (MASK_PRIMARY == drive.gpt.valid_headers ||
+ MASK_BOTH == drive.gpt.valid_headers) {
+ header = (GptHeader *)(drive.gpt.primary_header);
+ } else {
+ header = (GptHeader *)(drive.gpt.secondary_header);
+ }
+
+ if (MASK_PRIMARY == drive.gpt.valid_entries) {
+ free(drive.gpt.secondary_entries);
+ drive.gpt.secondary_entries =
+ malloc(header->size_of_entry * header->number_of_entries);
+ } else if (MASK_SECONDARY == drive.gpt.valid_entries) {
+ free(drive.gpt.primary_entries);
+ drive.gpt.primary_entries =
+ malloc(header->size_of_entry * header->number_of_entries);
+ }
+
GptRepair(&drive.gpt);
if (drive.gpt.modified & GPT_MODIFIED_HEADER1)
printf("Primary Header is updated.\n");
diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h
index a94224f3..e5a366bb 100644
--- a/firmware/include/gpt_misc.h
+++ b/firmware/include/gpt_misc.h
@@ -84,9 +84,9 @@ typedef struct {
uint8_t *primary_header;
/* GPT secondary header, from last sector of disk (size: 512 bytes) */
uint8_t *secondary_header;
- /* Primary GPT table, follows primary header (size: 16 KB) */
+ /* Primary GPT table, follows primary header */
uint8_t *primary_entries;
- /* Secondary GPT table, precedes secondary header (size: 16 KB) */
+ /* Secondary GPT table, precedes secondary header */
uint8_t *secondary_entries;
/* Size of a LBA sector, in bytes */
uint32_t sector_bytes;
diff --git a/firmware/lib/cgptlib/include/cgptlib_internal.h b/firmware/lib/cgptlib/include/cgptlib_internal.h
index 0be2bc5a..50477c4f 100644
--- a/firmware/lib/cgptlib/include/cgptlib_internal.h
+++ b/firmware/lib/cgptlib/include/cgptlib_internal.h
@@ -125,6 +125,10 @@ int GptSanityCheck(GptData *gpt);
* Repair GPT data by copying from one set of valid headers/entries to the
* other. Assumes GptSanityCheck() has been run to determine which headers
* and/or entries are already valid.
+ *
+ * The caller must make sure that even if one of the entries table is invalid
+ * then corresponding buffer is allocated and big enough to accommodate entries
+ * from the other (good) table.
*/
void GptRepair(GptData *gpt);
diff --git a/tests/run_cgpt_tests.sh b/tests/run_cgpt_tests.sh
index 5176017a..8a46d03a 100755
--- a/tests/run_cgpt_tests.sh
+++ b/tests/run_cgpt_tests.sh
@@ -269,6 +269,22 @@ 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
$CGPT prioritize $MTD -i 1 -f ${DEV}
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
+echo "Test cgpt repair command"
+$CGPT repair $MTD ${DEV}
+($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+
+# Zero primary header and partition table and try to repair it.
+dd if=/dev/zero of=${DEV} conv=notrunc bs=512 count=33 2>/dev/null
+$CGPT show $MTD ${DEV} | grep -q INVALID
+$CGPT repair $MTD ${DEV}
+($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+
+# Zero secondary header and partition table and try to repair it.
+dd if=/dev/zero of=${DEV} seek=$(($NUM_SECTORS - 33)) conv=notrunc bs=512 count=33 2>/dev/null
+$CGPT show $MTD ${DEV} | grep -q INVALID
+$CGPT repair $MTD ${DEV}
+($CGPT show $MTD ${DEV} | grep -q INVALID) && error
+
# Now make sure that we don't need write access if we're just looking.
echo "Test read vs read-write access..."
chmod 0444 ${DEV}