mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 18:55:24 +00:00
cgpt: Handle read errors gracefully
When a read fails in getting the GPT, just zero the contents of the buffer and carry on. Some testing changes are required for this. When a read of the GPT fails, it is no longer fatal, so tests of that have been adjusted. Tests have been improved to show that the GPT is automatically repaired when a read error occurs. There was one test which checked that a zero-sized disk would fail to load a kernel, but it was surrounded by a number of mocked functions which normally do that error checking, and it amounted to the same test as read failure; that test was deleted. BUG=chrome-os-partner:35440 TEST=vboot tests pass BRANCH=none Change-Id: I0c05813e7492920433733947d3fb74a7e4aa66f2 Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/266882 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
e2e14ae827
commit
d7da706484
@@ -43,8 +43,10 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Read primary header from the drive, skipping the protective MBR */
|
/* Read primary header from the drive, skipping the protective MBR */
|
||||||
if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header))
|
if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header)) {
|
||||||
return 1;
|
VBDEBUG(("Read error in primary GPT header\n"));
|
||||||
|
Memset(gptdata->primary_header, 0, gptdata->sector_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/* Only read primary GPT if the primary header is valid */
|
/* Only read primary GPT if the primary header is valid */
|
||||||
GptHeader* primary_header = (GptHeader*)gptdata->primary_header;
|
GptHeader* primary_header = (GptHeader*)gptdata->primary_header;
|
||||||
@@ -60,16 +62,20 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
|
|||||||
if (0 != VbExDiskRead(disk_handle,
|
if (0 != VbExDiskRead(disk_handle,
|
||||||
primary_header->entries_lba,
|
primary_header->entries_lba,
|
||||||
entries_sectors,
|
entries_sectors,
|
||||||
gptdata->primary_entries))
|
gptdata->primary_entries)) {
|
||||||
return 1;
|
VBDEBUG(("Read error in primary GPT entries\n"));
|
||||||
|
primary_valid = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
VBDEBUG(("Primary GPT header invalid!\n"));
|
VBDEBUG(("Primary GPT header invalid!\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read secondary header from the end of the drive */
|
/* Read secondary header from the end of the drive */
|
||||||
if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1,
|
if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1,
|
||||||
gptdata->secondary_header))
|
gptdata->secondary_header)) {
|
||||||
return 1;
|
VBDEBUG(("Read error in secondary GPT header\n"));
|
||||||
|
Memset(gptdata->secondary_header, 0, gptdata->sector_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/* Only read secondary GPT if the secondary header is valid */
|
/* Only read secondary GPT if the secondary header is valid */
|
||||||
GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header;
|
GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header;
|
||||||
@@ -85,8 +91,10 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
|
|||||||
if (0 != VbExDiskRead(disk_handle,
|
if (0 != VbExDiskRead(disk_handle,
|
||||||
secondary_header->entries_lba,
|
secondary_header->entries_lba,
|
||||||
entries_sectors,
|
entries_sectors,
|
||||||
gptdata->secondary_entries))
|
gptdata->secondary_entries)) {
|
||||||
return 1;
|
VBDEBUG(("Read error in secondary GPT entries\n"));
|
||||||
|
secondary_valid = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
VBDEBUG(("Secondary GPT header invalid!\n"));
|
VBDEBUG(("Secondary GPT header invalid!\n"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "cgptlib.h"
|
#include "cgptlib.h"
|
||||||
#include "cgptlib_internal.h"
|
#include "cgptlib_internal.h"
|
||||||
|
#include "crc32.h"
|
||||||
#include "gbb_header.h"
|
#include "gbb_header.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "host_common.h"
|
#include "host_common.h"
|
||||||
@@ -467,27 +468,43 @@ static void ReadWriteGptTest(void)
|
|||||||
/* Error reading */
|
/* Error reading */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
disk_read_to_fail = 1;
|
disk_read_to_fail = 1;
|
||||||
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
||||||
Memset(g.primary_header, '\0', g.sector_bytes);
|
g.valid_headers = g.valid_entries = MASK_SECONDARY;
|
||||||
WriteAndFreeGptData(handle, &g);
|
GptRepair(&g);
|
||||||
|
ResetCallLog();
|
||||||
|
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
|
||||||
|
TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
|
||||||
|
"VbExDiskWrite(h, 2, 32)\n");
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
disk_read_to_fail = 2;
|
disk_read_to_fail = 2;
|
||||||
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
||||||
Memset(g.primary_header, '\0', g.sector_bytes);
|
g.valid_headers = MASK_BOTH;
|
||||||
WriteAndFreeGptData(handle, &g);
|
g.valid_entries = MASK_SECONDARY;
|
||||||
|
GptRepair(&g);
|
||||||
|
ResetCallLog();
|
||||||
|
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
|
||||||
|
TEST_CALLS("VbExDiskWrite(h, 2, 32)\n");
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
disk_read_to_fail = 991;
|
disk_read_to_fail = 991;
|
||||||
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
||||||
Memset(g.primary_header, '\0', g.sector_bytes);
|
g.valid_headers = MASK_BOTH;
|
||||||
WriteAndFreeGptData(handle, &g);
|
g.valid_entries = MASK_PRIMARY;
|
||||||
|
GptRepair(&g);
|
||||||
|
ResetCallLog();
|
||||||
|
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
|
||||||
|
TEST_CALLS("VbExDiskWrite(h, 991, 32)\n");
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
disk_read_to_fail = 1023;
|
disk_read_to_fail = 1023;
|
||||||
TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
|
||||||
Memset(g.primary_header, '\0', g.sector_bytes);
|
g.valid_headers = g.valid_entries = MASK_PRIMARY;
|
||||||
WriteAndFreeGptData(handle, &g);
|
GptRepair(&g);
|
||||||
|
ResetCallLog();
|
||||||
|
TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2");
|
||||||
|
TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
|
||||||
|
"VbExDiskWrite(h, 991, 32)\n");
|
||||||
|
|
||||||
/* Error writing */
|
/* Error writing */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
@@ -542,21 +559,11 @@ static void InvalidParamsTest(void)
|
|||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
|
||||||
"Huge lba size");
|
"Huge lba size");
|
||||||
|
|
||||||
ResetMocks();
|
|
||||||
disk_read_to_fail = 1;
|
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
|
|
||||||
"Can't read disk");
|
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
gpt_init_fail = 1;
|
gpt_init_fail = 1;
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
|
||||||
"Bad GPT");
|
"Bad GPT");
|
||||||
|
|
||||||
ResetMocks();
|
|
||||||
lkp.gpt_lba_count = 0;
|
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
|
|
||||||
"GPT size = 0");
|
|
||||||
|
|
||||||
/* This causes the stream open call to fail */
|
/* This causes the stream open call to fail */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
lkp.disk_handle = NULL;
|
lkp.disk_handle = NULL;
|
||||||
@@ -765,6 +772,11 @@ static void LoadKernelTest(void)
|
|||||||
lkp.boot_flags |= BOOT_FLAG_EXTERNAL_GPT;
|
lkp.boot_flags |= BOOT_FLAG_EXTERNAL_GPT;
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed external GPT");
|
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed external GPT");
|
||||||
TEST_EQ(gpt_flag_external, 1, "GPT was external");
|
TEST_EQ(gpt_flag_external, 1, "GPT was external");
|
||||||
|
|
||||||
|
/* Check recovery from unreadble primary GPT */
|
||||||
|
ResetMocks();
|
||||||
|
disk_read_to_fail = 1;
|
||||||
|
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Can't read disk");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user