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

Side by Side Diff: src/platform/vboot_reference/vboot_firmware/lib/load_kernel_fw.c

Issue 2438005: Much rearranging of cgptlib. Passes all its (new) unit tests. (Closed) Base URL: ssh://gitrw.chromium.org/chromiumos
Patch Set: Pre commit 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 unified diff | Download patch
« no previous file with comments | « src/platform/vboot_reference/vboot_firmware/lib/cgptlib/quick_sort.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Functions for loading a kernel from disk. 5 * Functions for loading a kernel from disk.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "load_kernel_fw.h" 9 #include "load_kernel_fw.h"
10 10
11 #include "boot_device.h" 11 #include "boot_device.h"
12 #include "cgptlib.h" 12 #include "cgptlib.h"
13 #include "kernel_image_fw.h" 13 #include "kernel_image_fw.h"
14 #include "rollback_index.h" 14 #include "rollback_index.h"
15 #include "utility.h" 15 #include "utility.h"
16 16
17 #define GPT_ENTRIES_SIZE 16384 /* Bytes to read for GPT entries */
18
19 // TODO: for testing
20 #include <stdio.h>
21 #include "cgptlib_internal.h"
22
23 /* TODO: Remove this terrible hack which fakes partition attributes
24 * for the kernel partitions so that GptNextKernelEntry() won't
25 * choke. */
26 void FakePartitionAttributes(GptData* gpt) {
27 GptEntry* entries = (GptEntry*)gpt->primary_entries;
28 GptEntry* e;
29 int i;
30 printf("Hacking partition attributes...\n");
31 printf("Note that GUIDs below have first 3 fields endian-swapped\n");
32
33 for (i = 0, e = entries; i < 12; i++, e++) {
34
35 printf("%2d %08x %04x %04x %02x %02x %02x %02x %02x %02x %02x %02x\n",
36 i,
37 e->type.u.Uuid.time_low,
38 e->type.u.Uuid.time_mid,
39 e->type.u.Uuid.time_high_and_version,
40 e->type.u.Uuid.clock_seq_high_and_reserved,
41 e->type.u.Uuid.clock_seq_low,
42 e->type.u.Uuid.node[0],
43 e->type.u.Uuid.node[1],
44 e->type.u.Uuid.node[2],
45 e->type.u.Uuid.node[3],
46 e->type.u.Uuid.node[4],
47 e->type.u.Uuid.node[5]
48 );
49 if (!IsKernelEntry(e))
50 continue;
51 printf("Hacking attributes for kernel partition %d\n", i);
52 SetEntryPriority(e, 2);
53 SetEntrySuccessful(e, 1);
54 }
55 }
56
17 57
18 int AllocAndReadGptData(GptData *gptdata) { 58 int AllocAndReadGptData(GptData *gptdata) {
19 /* Allocates and reads GPT data from the drive. The sector_bytes and 59 /* Allocates and reads GPT data from the drive. The sector_bytes and
20 * drive_sectors fields should be filled on input. The primary and 60 * drive_sectors fields should be filled on input. The primary and
21 * secondary header and entries are filled on output. 61 * secondary header and entries are filled on output.
22 * 62 *
23 * Returns 0 if successful, 1 if error. */ 63 * Returns 0 if successful, 1 if error. */
24 64
25 uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; 65 uint64_t entries_sectors = GPT_ENTRIES_SIZE / gptdata->sector_bytes;
26 66
27 /* No data to be written yet */ 67 /* No data to be written yet */
28 gptdata->modified = 0; 68 gptdata->modified = 0;
29 69
30 /* Allocate all buffers */ 70 /* Allocate all buffers */
31 gptdata->primary_header = (uint8_t*)Malloc(gptdata->sector_bytes); 71 gptdata->primary_header = (uint8_t*)Malloc(gptdata->sector_bytes);
32 gptdata->secondary_header = (uint8_t*)Malloc(gptdata->sector_bytes); 72 gptdata->secondary_header = (uint8_t*)Malloc(gptdata->sector_bytes);
33 gptdata->primary_entries = (uint8_t*)Malloc(TOTAL_ENTRIES_SIZE); 73 gptdata->primary_entries = (uint8_t*)Malloc(GPT_ENTRIES_SIZE);
34 gptdata->secondary_entries = (uint8_t*)Malloc(TOTAL_ENTRIES_SIZE); 74 gptdata->secondary_entries = (uint8_t*)Malloc(GPT_ENTRIES_SIZE);
35 75
36 if (gptdata->primary_header == NULL || gptdata->secondary_header == NULL || 76 if (gptdata->primary_header == NULL || gptdata->secondary_header == NULL ||
37 gptdata->primary_entries == NULL || gptdata->secondary_entries == NULL) 77 gptdata->primary_entries == NULL || gptdata->secondary_entries == NULL)
38 return 1; 78 return 1;
39 79
40 /* Read data from the drive */ 80 /* Read data from the drive, skipping the protective MBR */
41 if (0 != BootDeviceReadLBA(0, 1, gptdata->primary_header)) 81 if (0 != BootDeviceReadLBA(1, 1, gptdata->primary_header))
42 return 1; 82 return 1;
43 if (0 != BootDeviceReadLBA(1, entries_sectors, gptdata->primary_entries)) 83 if (0 != BootDeviceReadLBA(2, entries_sectors, gptdata->primary_entries))
44 return 1; 84 return 1;
45 if (0 != BootDeviceReadLBA(gptdata->drive_sectors - entries_sectors - 1, 85 if (0 != BootDeviceReadLBA(gptdata->drive_sectors - entries_sectors - 1,
46 entries_sectors, gptdata->secondary_entries)) 86 entries_sectors, gptdata->secondary_entries))
47 return 1; 87 return 1;
48 if (0 != BootDeviceReadLBA(gptdata->drive_sectors - entries_sectors - 1, 88 if (0 != BootDeviceReadLBA(gptdata->drive_sectors - 1,
49 1, gptdata->secondary_header)) 89 1, gptdata->secondary_header))
50 return 1; 90 return 1;
51 91
52 return 0; 92 return 0;
53 } 93 }
54 94
55 void WriteAndFreeGptData(GptData *gptdata) { 95 void WriteAndFreeGptData(GptData *gptdata) {
56 /* Writes any changes for the GPT data back to the drive, then frees the 96 /* Writes any changes for the GPT data back to the drive, then frees the
57 * buffers. */ 97 * buffers. */
58 98
59 uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; 99 uint64_t entries_sectors = GPT_ENTRIES_SIZE / gptdata->sector_bytes;
60 100
61 if (gptdata->primary_header) { 101 if (gptdata->primary_header) {
62 if (gptdata->modified & GPT_MODIFIED_HEADER1) 102 if (gptdata->modified & GPT_MODIFIED_HEADER1)
63 BootDeviceWriteLBA(0, 1, gptdata->primary_header); 103 BootDeviceWriteLBA(1, 1, gptdata->primary_header);
64 Free(gptdata->primary_header); 104 Free(gptdata->primary_header);
65 } 105 }
66 106
67 if (gptdata->primary_entries) { 107 if (gptdata->primary_entries) {
68 if (gptdata->modified & GPT_MODIFIED_ENTRIES1) 108 if (gptdata->modified & GPT_MODIFIED_ENTRIES1)
69 BootDeviceWriteLBA(1, entries_sectors, gptdata->primary_entries); 109 BootDeviceWriteLBA(2, entries_sectors, gptdata->primary_entries);
70 Free(gptdata->primary_entries); 110 Free(gptdata->primary_entries);
71 } 111 }
72 112
73 if (gptdata->secondary_entries) { 113 if (gptdata->secondary_entries) {
74 if (gptdata->modified & GPT_MODIFIED_ENTRIES2) 114 if (gptdata->modified & GPT_MODIFIED_ENTRIES2)
75 BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1, 115 BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1,
76 entries_sectors, gptdata->secondary_entries); 116 entries_sectors, gptdata->secondary_entries);
77 Free(gptdata->secondary_entries); 117 Free(gptdata->secondary_entries);
78 } 118 }
79 119
80 if (gptdata->secondary_header) { 120 if (gptdata->secondary_header) {
81 if (gptdata->modified & GPT_MODIFIED_HEADER2) 121 if (gptdata->modified & GPT_MODIFIED_HEADER2)
82 BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1, 122 BootDeviceWriteLBA(gptdata->drive_sectors - entries_sectors - 1,
83 1, gptdata->secondary_header); 123 1, gptdata->secondary_header);
84 BootDeviceWriteLBA(0, 1, gptdata->primary_header); 124 BootDeviceWriteLBA(gptdata->drive_sectors - 1, 1,
85 Free(gptdata->primary_header); 125 gptdata->secondary_header);
126 Free(gptdata->secondary_header);
86 } 127 }
87 /* TODO: What to do with return codes from the writes? */ 128 /* TODO: What to do with return codes from the writes? */
88 } 129 }
89 130
90 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ 131 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
91 132
92 int LoadKernel(LoadKernelParams* params) { 133 int LoadKernel(LoadKernelParams* params) {
93 134
94 GptData gpt; 135 GptData gpt;
95 uint64_t part_start, part_size; 136 uint64_t part_start, part_size;
96 uint64_t blba = params->bytes_per_lba; 137 uint64_t blba = params->bytes_per_lba;
97 uint8_t* kbuf = NULL; 138 uint8_t* kbuf = NULL;
98 uint64_t kbuf_sectors; 139 uint64_t kbuf_sectors;
99 int found_partition = 0; 140 int found_partition = 0;
100 int good_partition = -1; 141 int good_partition = -1;
101 uint16_t tpm_kernel_key_version, tpm_kernel_version; 142 uint16_t tpm_kernel_key_version, tpm_kernel_version;
102 uint16_t lowest_kernel_key_version = 0xFFFF; 143 uint16_t lowest_kernel_key_version = 0xFFFF;
103 uint16_t lowest_kernel_version = 0xFFFF; 144 uint16_t lowest_kernel_version = 0xFFFF;
104 KernelImage *kim = NULL; 145 KernelImage *kim = NULL;
105 146
106 /* Read current kernel key index from TPM. Assumes TPM is already 147 /* Read current kernel key index from TPM. Assumes TPM is already
107 * initialized. */ 148 * initialized. */
108 /* TODO: Is that a safe assumption? Normally, SetupTPM() would be called 149 /* TODO: Is that a safe assumption? Normally, SetupTPM() would be called
109 * when the RW firmware is verified. Is it harmful to call SetupTPM() 150 * when the RW firmware is verified. Is it harmful to call SetupTPM()
110 * again if it's already initialized? It'd be easier if we could just do 151 * again if it's already initialized? It'd be easier if we could just do
111 * that. */ 152 * that. */
112 GetStoredVersions(KERNEL_VERSIONS, 153 GetStoredVersions(KERNEL_VERSIONS,
113 &tpm_kernel_key_version, 154 &tpm_kernel_key_version,
114 &tpm_kernel_version); 155 &tpm_kernel_version);
156
115 do { 157 do {
116 /* Read GPT data */ 158 /* Read GPT data */
117 gpt.sector_bytes = blba; 159 gpt.sector_bytes = blba;
118 gpt.drive_sectors = params->ending_lba + 1; 160 gpt.drive_sectors = params->ending_lba + 1;
119 if (0 != AllocAndReadGptData(&gpt)) 161 if (0 != AllocAndReadGptData(&gpt))
120 break; 162 break;
121 163
164 fprintf(stderr, "RRS1\n");
165
122 /* Initialize GPT library */ 166 /* Initialize GPT library */
123 if (GPT_SUCCESS != GptInit(&gpt)) 167 if (GPT_SUCCESS != GptInit(&gpt))
124 break; 168 break;
125 169
170 /* TODO: TERRIBLE KLUDGE - fake partition attributes */
171 FakePartitionAttributes(&gpt);
172
126 /* Allocate kernel header and image work buffers */ 173 /* Allocate kernel header and image work buffers */
127 kbuf = (uint8_t*)Malloc(KBUF_SIZE); 174 kbuf = (uint8_t*)Malloc(KBUF_SIZE);
128 if (!kbuf) 175 if (!kbuf)
129 break; 176 break;
177
130 kbuf_sectors = KBUF_SIZE / blba; 178 kbuf_sectors = KBUF_SIZE / blba;
131 kim = (KernelImage*)Malloc(sizeof(KernelImage)); 179 kim = (KernelImage*)Malloc(sizeof(KernelImage));
132 if (!kim) 180 if (!kim)
133 break; 181 break;
134 182
183 fprintf(stderr, "RRS2\n");
184
135 /* Loop over candidate kernel partitions */ 185 /* Loop over candidate kernel partitions */
136 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { 186 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) {
137 RSAPublicKey *kernel_sign_key = NULL; 187 RSAPublicKey *kernel_sign_key = NULL;
138 int kernel_start, kernel_sectors; 188 int kernel_start, kernel_sectors;
139 189
190 fprintf(stderr, "RRS3\n");
191
140 /* Found at least one kernel partition. */ 192 /* Found at least one kernel partition. */
141 found_partition = 1; 193 found_partition = 1;
142 194
143 /* Read the first part of the kernel partition */ 195 /* Read the first part of the kernel partition */
144 if (part_size < kbuf_sectors) 196 if (part_size < kbuf_sectors)
145 continue; 197 continue;
146 if (1 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf)) 198 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf))
147 continue; 199 continue;
148 200
201 fprintf(stderr, "RRS4\n");
202
149 /* Verify the kernel header and preamble */ 203 /* Verify the kernel header and preamble */
150 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader( 204 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader(
151 params->header_sign_key_blob, 205 params->header_sign_key_blob,
152 kbuf, 206 kbuf,
153 KBUF_SIZE, 207 KBUF_SIZE,
154 (BOOT_MODE_DEVELOPER == params->boot_mode ? 1 : 0), 208 (BOOT_MODE_DEVELOPER == params->boot_mode ? 1 : 0),
155 kim, 209 kim,
156 &kernel_sign_key)) { 210 &kernel_sign_key)) {
157 continue; 211 continue;
158 } 212 }
159 213
214 fprintf(stderr, "RRS5\n");
215
160 /* Check for rollback of key version */ 216 /* Check for rollback of key version */
161 if (kim->kernel_key_version < tpm_kernel_key_version) { 217 if (kim->kernel_key_version < tpm_kernel_key_version) {
162 RSAPublicKeyFree(kernel_sign_key); 218 RSAPublicKeyFree(kernel_sign_key);
163 continue; 219 continue;
164 } 220 }
165 221
166 /* Check for rollback of kernel version */ 222 /* Check for rollback of kernel version */
167 if (kim->kernel_key_version == tpm_kernel_key_version && 223 if (kim->kernel_key_version == tpm_kernel_key_version &&
168 kim->kernel_version < tpm_kernel_version) { 224 kim->kernel_version < tpm_kernel_version) {
169 RSAPublicKeyFree(kernel_sign_key); 225 RSAPublicKeyFree(kernel_sign_key);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 323
268 // Handle error cases 324 // Handle error cases
269 if (found_partition) 325 if (found_partition)
270 return LOAD_KERNEL_INVALID; 326 return LOAD_KERNEL_INVALID;
271 else 327 else
272 return LOAD_KERNEL_NOT_FOUND; 328 return LOAD_KERNEL_NOT_FOUND;
273 /* TODO: no error code for "internal error", but what would the firmware do 329 /* TODO: no error code for "internal error", but what would the firmware do
274 * with that anyway? So in the do-while(0) code above, the firmware just 330 * with that anyway? So in the do-while(0) code above, the firmware just
275 * does 'break' to indicate an internal error... */ 331 * does 'break' to indicate an internal error... */
276 } 332 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/vboot_firmware/lib/cgptlib/quick_sort.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698