Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Unified Diff: vboot_firmware/lib/load_kernel_fw.c

Issue 2735004: Uses TPM return codes. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « vboot_firmware/include/rollback_index.h ('k') | vboot_firmware/lib/rollback_index.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vboot_firmware/lib/load_kernel_fw.c
diff --git a/vboot_firmware/lib/load_kernel_fw.c b/vboot_firmware/lib/load_kernel_fw.c
index e79e2457267deeba9aa85b8b8595eb3b34d8a9ab..cea6b771570b6c0cb86b729fe20594d50f0b5446 100644
--- a/vboot_firmware/lib/load_kernel_fw.c
+++ b/vboot_firmware/lib/load_kernel_fw.c
@@ -63,12 +63,12 @@ void FakePartitionAttributes(GptData* gpt) {
}
-int AllocAndReadGptData(GptData *gptdata) {
- /* Allocates and reads GPT data from the drive. The sector_bytes and
- * drive_sectors fields should be filled on input. The primary and
- * secondary header and entries are filled on output.
- *
- * Returns 0 if successful, 1 if error. */
+/* Allocates and reads GPT data from the drive. The sector_bytes and
+ * drive_sectors fields should be filled on input. The primary and
+ * secondary header and entries are filled on output.
+ *
+ * Returns 0 if successful, 1 if error. */
+int AllocAndReadGptData(GptData* gptdata) {
uint64_t entries_sectors = GPT_ENTRIES_SIZE / gptdata->sector_bytes;
@@ -100,42 +100,55 @@ int AllocAndReadGptData(GptData *gptdata) {
return 0;
}
-void WriteAndFreeGptData(GptData *gptdata) {
- /* Writes any changes for the GPT data back to the drive, then frees the
- * buffers. */
+
+/* Writes any changes for the GPT data back to the drive, then frees
+ * the buffers.
+ *
+ * Returns 0 if successful, 1 if error. */
+int WriteAndFreeGptData(GptData* gptdata) {
uint64_t entries_sectors = GPT_ENTRIES_SIZE / gptdata->sector_bytes;
if (gptdata->primary_header) {
- if (gptdata->modified & GPT_MODIFIED_HEADER1)
- BootDeviceWriteLBA(1, 1, gptdata->primary_header);
+ if (gptdata->modified & GPT_MODIFIED_HEADER1) {
+ if (0 != BootDeviceWriteLBA(1, 1, gptdata->primary_header))
+ return 1;
+ }
Free(gptdata->primary_header);
}
if (gptdata->primary_entries) {
- if (gptdata->modified & GPT_MODIFIED_ENTRIES1)
- BootDeviceWriteLBA(2, entries_sectors, gptdata->primary_entries);
+ if (gptdata->modified & GPT_MODIFIED_ENTRIES1) {
+ if (0 != BootDeviceWriteLBA(2, entries_sectors,
+ gptdata->primary_entries))
+ return 1;
+ }
Free(gptdata->primary_entries);
}
if (gptdata->secondary_entries) {
- if (gptdata->modified & GPT_MODIFIED_ENTRIES2)
- BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1,
- entries_sectors, gptdata->secondary_entries);
+ if (gptdata->modified & GPT_MODIFIED_ENTRIES2) {
+ if (0 != BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1,
+ entries_sectors, gptdata->secondary_entries))
+ return 1;
+ }
Free(gptdata->secondary_entries);
}
if (gptdata->secondary_header) {
- if (gptdata->modified & GPT_MODIFIED_HEADER2)
- BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1,
- 1, gptdata->secondary_header);
- BootDeviceWriteLBA(gptdata->drive_sectors - 1, 1,
- gptdata->secondary_header);
+ if (gptdata->modified & GPT_MODIFIED_HEADER2) {
+ if (0 != BootDeviceWriteLBA(gptdata->drive_sectors - 1, 1,
+ gptdata->secondary_header))
+ return 1;
+ }
Free(gptdata->secondary_header);
}
- /* TODO: What to do with return codes from the writes? */
+
+ /* Success */
+ return 0;
}
+
#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
int LoadKernel(LoadKernelParams* params) {
@@ -157,15 +170,14 @@ int LoadKernel(LoadKernelParams* params) {
params->bootloader_address = 0;
params->bootloader_size = 0;
- /* Read current kernel key index from TPM. Assumes TPM is already
- * initialized. */
- /* TODO: Is that a safe assumption? Normally, SetupTPM() would be called
- * when the RW firmware is verified. Is it harmful to call SetupTPM()
- * again if it's already initialized? It'd be easier if we could just do
- * that. */
- GetStoredVersions(KERNEL_VERSIONS,
- &tpm_kernel_key_version,
- &tpm_kernel_version);
+ if (BOOT_MODE_NORMAL == params->boot_mode) {
+ /* Read current kernel key index from TPM. Assumes TPM is already
+ * initialized. */
+ if (0 != GetStoredVersions(KERNEL_VERSIONS,
+ &tpm_kernel_key_version,
+ &tpm_kernel_version))
+ return LOAD_KERNEL_RECOVERY;
+ }
do {
/* Read GPT data */
@@ -290,9 +302,16 @@ int LoadKernel(LoadKernelParams* params) {
params->bootloader_address = kim->bootloader_offset;
params->bootloader_size = kim->bootloader_size;
- /* If the good partition's key version is the same as the tpm, then
- * the TPM doesn't need updating; we can stop now. Otherwise, we'll
- * check all the other headers to see if they contain a newer key. */
+ /* If we're in developer or recovery mode, there's no rollback
+ * protection, so we can stop at the first valid kernel. */
+ if (BOOT_MODE_NORMAL != params->boot_mode)
+ break;
+
+ /* Otherwise, we're in normal boot mode, so we do care about
+ * the key index in the TPM. If the good partition's key
+ * version is the same as the tpm, then the TPM doesn't need
+ * updating; we can stop now. Otherwise, we'll check all the
+ * other headers to see if they contain a newer key. */
if (kim->kernel_key_version == tpm_kernel_key_version &&
kim->kernel_version == tpm_kernel_version)
break;
@@ -306,19 +325,22 @@ int LoadKernel(LoadKernelParams* params) {
if (kim)
Free(kim);
- // Write and free GPT data
+ /* Write and free GPT data */
WriteAndFreeGptData(&gpt);
- // Handle finding a good partition
+ /* Handle finding a good partition */
if (good_partition >= 0) {
- /* See if we need to update the TPM */
- if ((lowest_kernel_key_version > tpm_kernel_key_version) ||
- (lowest_kernel_key_version == tpm_kernel_key_version &&
- lowest_kernel_version > tpm_kernel_version)) {
- WriteStoredVersions(KERNEL_VERSIONS,
- lowest_kernel_key_version,
- lowest_kernel_version);
+ if (BOOT_MODE_NORMAL == params->boot_mode) {
+ /* See if we need to update the TPM, for normal boot mode only. */
+ if ((lowest_kernel_key_version > tpm_kernel_key_version) ||
+ (lowest_kernel_key_version == tpm_kernel_key_version &&
+ lowest_kernel_version > tpm_kernel_version)) {
+ if (0 != WriteStoredVersions(KERNEL_VERSIONS,
+ lowest_kernel_key_version,
+ lowest_kernel_version))
+ return LOAD_KERNEL_RECOVERY;
+ }
}
if (BOOT_MODE_RECOVERY != params->boot_mode) {
@@ -330,19 +352,17 @@ int LoadKernel(LoadKernelParams* params) {
*
* If we're already in recovery mode, we need to leave PP unlocked,
* so don't lock the kernel versions. */
- LockKernelVersionsByLockingPP();
+ if (0 != LockKernelVersionsByLockingPP())
+ return LOAD_KERNEL_RECOVERY;
}
/* Success! */
return LOAD_KERNEL_SUCCESS;
}
- // Handle error cases
+ /* Handle error cases */
if (found_partition)
return LOAD_KERNEL_INVALID;
else
return LOAD_KERNEL_NOT_FOUND;
- /* TODO: no error code for "internal error", but what would the firmware do
- * with that anyway? So in the do-while(0) code above, the firmware just
- * does 'break' to indicate an internal error... */
}
« no previous file with comments | « vboot_firmware/include/rollback_index.h ('k') | vboot_firmware/lib/rollback_index.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698