blob: 3712d0d3fc4fdae10e4b45a798c6394442d8938f [file] [log] [blame]
Randall Spangler49cb0d32013-01-29 14:28:16 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Tests for vboot_kernel.c
6 */
7
Bill Richardson0c3ba242013-03-29 11:09:30 -07008#include <stdint.h>
Randall Spangler49cb0d32013-01-29 14:28:16 -08009#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "cgptlib.h"
Duncan Laurie162f7882014-10-01 09:58:10 -070014#include "cgptlib_internal.h"
Randall Spangler49cb0d32013-01-29 14:28:16 -080015#include "gbb_header.h"
16#include "gpt.h"
17#include "host_common.h"
18#include "load_kernel_fw.h"
19#include "test_common.h"
20#include "vboot_api.h"
21#include "vboot_common.h"
22#include "vboot_kernel.h"
23#include "vboot_nvstorage.h"
24
25#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
26#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls")
27
Duncan Laurie162f7882014-10-01 09:58:10 -070028#define MOCK_SECTOR_SIZE 512
29#define MOCK_SECTOR_COUNT 1024
30
Randall Spangler5d0a2e72013-01-30 13:19:19 -080031/* Mock kernel partition */
32struct mock_part {
33 uint32_t start;
34 uint32_t size;
35};
36
37/* Partition list; ends with a 0-size partition. */
38#define MOCK_PART_COUNT 8
39static struct mock_part mock_parts[MOCK_PART_COUNT];
40static int mock_part_next;
41
Randall Spangler49cb0d32013-01-29 14:28:16 -080042/* Mock data */
43static char call_log[4096];
Randall Spangler5d0a2e72013-01-30 13:19:19 -080044static uint8_t kernel_buffer[80000];
45static int disk_read_to_fail;
46static int disk_write_to_fail;
Randall Spangler49cb0d32013-01-29 14:28:16 -080047static int gpt_init_fail;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080048static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */
49static int preamble_verify_fail;
Randall Spangler3e9cf902013-02-01 13:31:20 -080050static int verify_data_fail;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080051static RSAPublicKey *mock_data_key;
52static int mock_data_key_allocated;
Randall Spangler49cb0d32013-01-29 14:28:16 -080053
Simon Glass527ba812013-07-25 08:48:47 -060054static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
55static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data;
Randall Spangler49cb0d32013-01-29 14:28:16 -080056static VbExDiskHandle_t handle;
57static VbNvContext vnc;
58static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
59static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
60static LoadKernelParams lkp;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080061static VbKeyBlockHeader kbh;
62static VbKernelPreambleHeader kph;
Simon Glass527ba812013-07-25 08:48:47 -060063static VbCommonParams cparams;
Duncan Laurie162f7882014-10-01 09:58:10 -070064static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
65static GptHeader *mock_gpt_primary =
66 (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
67static GptHeader *mock_gpt_secondary =
68 (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
69
70
71/**
72 * Prepare a valid GPT header that will pass CheckHeader() tests
73 */
74static void SetupGptHeader(GptHeader *h, int is_secondary)
75{
76 Memset(h, '\0', MOCK_SECTOR_SIZE);
77
78 /* "EFI PART" */
79 memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
80 h->revision = GPT_HEADER_REVISION;
81 h->size = MIN_SIZE_OF_HEADER;
82
83 /* 16KB: 128 entries of 128 bytes */
84 h->size_of_entry = sizeof(GptEntry);
85 h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry;
86
87 /* Set LBA pointers for primary or secondary header */
88 if (is_secondary) {
89 h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
90 h->entries_lba = h->my_lba - GPT_ENTRIES_SECTORS;
91 } else {
92 h->my_lba = GPT_PMBR_SECTORS;
93 h->entries_lba = h->my_lba + 1;
94 }
95
96 h->first_usable_lba = 2 + GPT_ENTRIES_SECTORS;
97 h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - GPT_ENTRIES_SECTORS;
98
99 h->header_crc32 = HeaderCrc(h);
100}
Randall Spangler49cb0d32013-01-29 14:28:16 -0800101
102static void ResetCallLog(void)
103{
104 *call_log = 0;
105}
106
107/**
108 * Reset mock data (for use before each test)
109 */
110static void ResetMocks(void)
111{
112 ResetCallLog();
113
Duncan Laurie162f7882014-10-01 09:58:10 -0700114 memset(&mock_disk, 0, sizeof(mock_disk));
115 SetupGptHeader(mock_gpt_primary, 0);
116 SetupGptHeader(mock_gpt_secondary, 1);
117
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800118 disk_read_to_fail = -1;
119 disk_write_to_fail = -1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800120
121 gpt_init_fail = 0;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800122 key_block_verify_fail = 0;
123 preamble_verify_fail = 0;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800124 verify_data_fail = 0;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800125
126 mock_data_key = (RSAPublicKey *)"TestDataKey";
127 mock_data_key_allocated = 0;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800128
Han Shen1a113812013-09-03 11:23:30 -0700129 memset(gbb, 0, sizeof(*gbb));
Simon Glass527ba812013-07-25 08:48:47 -0600130 gbb->major_version = GBB_MAJOR_VER;
131 gbb->minor_version = GBB_MINOR_VER;
132 gbb->flags = 0;
133
134 memset(&cparams, '\0', sizeof(cparams));
135 cparams.gbb = gbb;
136 cparams.gbb_data = gbb;
137 cparams.gbb_size = sizeof(gbb_data);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800138
139 memset(&vnc, 0, sizeof(vnc));
140 VbNvSetup(&vnc);
141 VbNvTeardown(&vnc); /* So CRC gets generated */
142
143 memset(&shared_data, 0, sizeof(shared_data));
144 VbSharedDataInit(shared, sizeof(shared_data));
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800145 shared->kernel_version_tpm = 0x20001;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800146
147 memset(&lkp, 0, sizeof(lkp));
148 lkp.nv_context = &vnc;
149 lkp.shared_data_blob = shared;
Simon Glass527ba812013-07-25 08:48:47 -0600150 lkp.gbb_data = gbb;
151 lkp.gbb_size = sizeof(gbb_data);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800152 lkp.bytes_per_lba = 512;
153 lkp.ending_lba = 1023;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800154 lkp.kernel_buffer = kernel_buffer;
155 lkp.kernel_buffer_size = sizeof(kernel_buffer);
156
157 memset(&kbh, 0, sizeof(kbh));
158 kbh.data_key.key_version = 2;
159 kbh.key_block_flags = -1;
160 kbh.key_block_size = sizeof(kbh);
161
162 memset(&kph, 0, sizeof(kph));
163 kph.kernel_version = 1;
164 kph.preamble_size = 4096 - kbh.key_block_size;
165 kph.body_signature.data_size = 70000;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800166 kph.bootloader_address = 0xbeadd008;
167 kph.bootloader_size = 0x1234;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800168
169 memset(mock_parts, 0, sizeof(mock_parts));
170 mock_parts[0].start = 100;
171 mock_parts[0].size = 150; /* 75 KB */
172 mock_part_next = 0;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800173}
174
175/* Mocks */
176
177VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
178 uint64_t lba_count, void *buffer)
179{
180 LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
181
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800182 if ((int)lba_start == disk_read_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800183 return VBERROR_SIMULATED;
184
Duncan Laurie162f7882014-10-01 09:58:10 -0700185 memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
186 lba_count * MOCK_SECTOR_SIZE);
187
Randall Spangler49cb0d32013-01-29 14:28:16 -0800188 return VBERROR_SUCCESS;
189}
190
191VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
192 uint64_t lba_count, const void *buffer)
193{
194 LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
195
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800196 if ((int)lba_start == disk_write_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800197 return VBERROR_SIMULATED;
198
Duncan Laurie162f7882014-10-01 09:58:10 -0700199 memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
200 lba_count * MOCK_SECTOR_SIZE);
201
Randall Spangler49cb0d32013-01-29 14:28:16 -0800202 return VBERROR_SUCCESS;
203}
204
205int GptInit(GptData *gpt)
206{
207 return gpt_init_fail;
208}
209
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800210int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
211{
212 struct mock_part *p = mock_parts + mock_part_next;
213
214 if (!p->size)
215 return GPT_ERROR_NO_VALID_KERNEL;
216
217 gpt->current_kernel = mock_part_next;
218 *start_sector = p->start;
219 *size = p->size;
220 mock_part_next++;
221 return GPT_SUCCESS;
222}
223
Randall Spangler3e9cf902013-02-01 13:31:20 -0800224void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
225{
226 static char fake_guid[] = "FakeGuid";
227
228 memcpy(dest, fake_guid, sizeof(fake_guid));
229}
230
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800231int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
232 const VbPublicKey *key, int hash_only) {
233
234 if (hash_only && key_block_verify_fail >= 2)
235 return VBERROR_SIMULATED;
236 else if (!hash_only && key_block_verify_fail >= 1)
237 return VBERROR_SIMULATED;
238
239 /* Use this as an opportunity to override the key block */
240 memcpy((void *)block, &kbh, sizeof(kbh));
241 return VBERROR_SUCCESS;
242}
243
244RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
245{
246 TEST_EQ(mock_data_key_allocated, 0, " mock data key not allocated");
247
248 if (mock_data_key)
249 mock_data_key_allocated++;
250
251 return mock_data_key;
252}
253
254void RSAPublicKeyFree(RSAPublicKey* key)
255{
256 TEST_EQ(mock_data_key_allocated, 1, " mock data key allocated");
257 TEST_PTR_EQ(key, mock_data_key, " data key ptr");
258 mock_data_key_allocated--;
259}
260
261int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
262 uint64_t size, const RSAPublicKey *key)
263{
264 if (preamble_verify_fail)
265 return VBERROR_SIMULATED;
266
267 /* Use this as an opportunity to override the preamble */
268 memcpy((void *)preamble, &kph, sizeof(kph));
269 return VBERROR_SUCCESS;
270}
271
Randall Spangler3e9cf902013-02-01 13:31:20 -0800272int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
273 const RSAPublicKey *key)
274{
275 if (verify_data_fail)
276 return VBERROR_SIMULATED;
277
278 return VBERROR_SUCCESS;
279}
280
281
Randall Spangler49cb0d32013-01-29 14:28:16 -0800282/**
283 * Test reading/writing GPT
284 */
285static void ReadWriteGptTest(void)
286{
287 GptData g;
288 GptHeader *h;
289
Duncan Laurie162f7882014-10-01 09:58:10 -0700290 g.sector_bytes = MOCK_SECTOR_SIZE;
291 g.drive_sectors = MOCK_SECTOR_COUNT;
292 g.valid_headers = g.valid_entries = MASK_BOTH;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800293
294 ResetMocks();
295 TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
296 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
297 "VbExDiskRead(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700298 "VbExDiskRead(h, 1023, 1)\n"
299 "VbExDiskRead(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800300 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600301 /*
302 * Valgrind complains about access to uninitialized memory here, so
303 * zero the primary header before each test.
304 */
305 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800306 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
307 TEST_CALLS("");
308
Duncan Laurie162f7882014-10-01 09:58:10 -0700309 /*
310 * Invalidate primary GPT header,
311 * check that AllocAndReadGptData still succeeds
312 */
313 ResetMocks();
314 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
315 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
316 "AllocAndRead primary invalid");
317 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
318 "Primary header is invalid");
319 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
320 "Secondary header is valid");
321 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
322 "VbExDiskRead(h, 1023, 1)\n"
323 "VbExDiskRead(h, 991, 32)\n");
324 WriteAndFreeGptData(handle, &g);
325
326 /*
327 * Invalidate secondary GPT header,
328 * check that AllocAndReadGptData still succeeds
329 */
330 ResetMocks();
331 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
332 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
333 "AllocAndRead secondary invalid");
334 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
335 "Primary header is valid");
336 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
337 "Secondary header is invalid");
338 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
339 "VbExDiskRead(h, 2, 32)\n"
340 "VbExDiskRead(h, 1023, 1)\n");
341 WriteAndFreeGptData(handle, &g);
342
343 /*
344 * Invalidate primary AND secondary GPT header,
345 * check that AllocAndReadGptData fails.
346 */
347 ResetMocks();
348 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
349 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
350 TEST_EQ(AllocAndReadGptData(handle, &g), 1,
351 "AllocAndRead primary and secondary invalid");
352 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
353 "Primary header is invalid");
354 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
355 "Secondary header is invalid");
356 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
357 "VbExDiskRead(h, 1023, 1)\n");
358 WriteAndFreeGptData(handle, &g);
359
360 /*
361 * Invalidate primary GPT header and check that it is
362 * repaired by GptRepair().
363 *
364 * This would normally be called by LoadKernel()->GptInit()
365 * but this callback is mocked in these tests.
366 */
367 ResetMocks();
368 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
369 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
370 "Fix Primary GPT: AllocAndRead");
371 /* Call GptRepair() with input indicating secondary GPT is valid */
372 g.valid_headers = g.valid_entries = MASK_SECONDARY;
373 GptRepair(&g);
374 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
375 "Fix Primary GPT: WriteAndFreeGptData");
376 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
377 "VbExDiskRead(h, 1023, 1)\n"
378 "VbExDiskRead(h, 991, 32)\n"
379 "VbExDiskWrite(h, 1, 1)\n"
380 "VbExDiskWrite(h, 2, 32)\n");
381 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
382 "Fix Primary GPT: Primary header is valid");
383
384 /*
385 * Invalidate secondary GPT header and check that it can be
386 * repaired by GptRepair().
387 *
388 * This would normally be called by LoadKernel()->GptInit()
389 * but this callback is mocked in these tests.
390 */
391 ResetMocks();
392 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
393 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
394 "Fix Secondary GPT: AllocAndRead");
395 /* Call GptRepair() with input indicating primary GPT is valid */
396 g.valid_headers = g.valid_entries = MASK_PRIMARY;
397 GptRepair(&g);
398 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
399 "Fix Secondary GPT: WriteAndFreeGptData");
400 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
401 "VbExDiskRead(h, 2, 32)\n"
402 "VbExDiskRead(h, 1023, 1)\n"
403 "VbExDiskWrite(h, 1023, 1)\n"
404 "VbExDiskWrite(h, 991, 32)\n");
405 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
406 "Fix Secondary GPT: Secondary header is valid");
407
Randall Spangler49cb0d32013-01-29 14:28:16 -0800408 /* Data which is changed is written */
409 ResetMocks();
410 AllocAndReadGptData(handle, &g);
411 g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
412 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600413 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700414 h = (GptHeader*)g.primary_header;
415 h->entries_lba = 2;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800416 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
417 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
418 "VbExDiskWrite(h, 2, 32)\n");
419
420 /* Data which is changed is written */
421 ResetMocks();
422 AllocAndReadGptData(handle, &g);
423 g.modified = -1;
424 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600425 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700426 h = (GptHeader*)g.primary_header;
427 h->entries_lba = 2;
428 h = (GptHeader*)g.secondary_header;
429 h->entries_lba = 991;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800430 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
431 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
432 "VbExDiskWrite(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700433 "VbExDiskWrite(h, 1023, 1)\n"
434 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800435
436 /* If legacy signature, don't modify GPT header/entries 1 */
437 ResetMocks();
438 AllocAndReadGptData(handle, &g);
439 h = (GptHeader *)g.primary_header;
440 memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
441 g.modified = -1;
442 ResetCallLog();
443 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700444 TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
445 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800446
447 /* Error reading */
448 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800449 disk_read_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800450 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600451 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800452 WriteAndFreeGptData(handle, &g);
453
Randall Spangler3e9cf902013-02-01 13:31:20 -0800454 ResetMocks();
455 disk_read_to_fail = 2;
456 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600457 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800458 WriteAndFreeGptData(handle, &g);
459
460 ResetMocks();
461 disk_read_to_fail = 991;
462 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600463 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800464 WriteAndFreeGptData(handle, &g);
465
466 ResetMocks();
467 disk_read_to_fail = 1023;
468 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600469 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800470 WriteAndFreeGptData(handle, &g);
471
Randall Spangler49cb0d32013-01-29 14:28:16 -0800472 /* Error writing */
473 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800474 disk_write_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800475 AllocAndReadGptData(handle, &g);
476 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600477 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800478 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800479
480 ResetMocks();
481 disk_write_to_fail = 2;
482 AllocAndReadGptData(handle, &g);
483 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600484 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700485 h = (GptHeader*)g.primary_header;
486 h->entries_lba = 2;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800487 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
488
489 ResetMocks();
490 disk_write_to_fail = 991;
491 AllocAndReadGptData(handle, &g);
492 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600493 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800494 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
495
496 ResetMocks();
497 disk_write_to_fail = 1023;
498 AllocAndReadGptData(handle, &g);
499 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600500 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800501 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
502
Randall Spangler49cb0d32013-01-29 14:28:16 -0800503}
504
505/**
506 * Trivial invalid calls to LoadKernel()
507 */
508static void InvalidParamsTest(void)
509{
510 ResetMocks();
511 lkp.bytes_per_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600512 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
513 "Bad lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800514
515 ResetMocks();
516 lkp.ending_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600517 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
518 "Bad lba count");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800519
520 ResetMocks();
521 lkp.bytes_per_lba = 128*1024;
Simon Glass527ba812013-07-25 08:48:47 -0600522 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
523 "Huge lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800524
525 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800526 disk_read_to_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600527 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
528 "Can't read disk");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800529
530 ResetMocks();
531 gpt_init_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600532 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
533 "Bad GPT");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800534}
535
Randall Spangler3e9cf902013-02-01 13:31:20 -0800536static void LoadKernelTest(void)
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800537{
Randall Spangler3e9cf902013-02-01 13:31:20 -0800538 uint32_t u;
539
540 ResetMocks();
Simon Glass527ba812013-07-25 08:48:47 -0600541 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "First kernel good");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800542 TEST_EQ(lkp.partition_number, 1, " part num");
543 TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
544 TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
545 TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", " guid");
546 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
547 TEST_EQ(u, 0, " recovery request");
548
549 ResetMocks();
550 mock_parts[1].start = 300;
551 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600552 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800553 TEST_EQ(lkp.partition_number, 1, " part num");
554 TEST_EQ(mock_part_next, 1, " didn't read second one");
555
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800556 /* Fail if no kernels found */
557 ResetMocks();
558 mock_parts[0].size = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600559 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800560 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
561 TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800562
563 /* Skip kernels which are too small */
564 ResetMocks();
565 mock_parts[0].size = 10;
Simon Glass527ba812013-07-25 08:48:47 -0600566 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800567 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
568 TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800569
570 ResetMocks();
571 disk_read_to_fail = 100;
Simon Glass527ba812013-07-25 08:48:47 -0600572 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800573 "Fail reading kernel start");
574
575 ResetMocks();
576 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600577 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800578 "Fail key block sig");
579
580 /* In dev mode, fail if hash is bad too */
581 ResetMocks();
582 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
583 key_block_verify_fail = 2;
Simon Glass527ba812013-07-25 08:48:47 -0600584 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800585 "Fail key block dev hash");
586
Randall Spangler3e9cf902013-02-01 13:31:20 -0800587 /* But just bad sig is ok */
588 ResetMocks();
589 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
590 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600591 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800592
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800593 /* In dev mode and requiring signed kernel, fail if sig is bad */
594 ResetMocks();
595 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
596 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
597 VbNvTeardown(&vnc);
598 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600599 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800600 "Fail key block dev sig");
601
602 /* Check key block flag mismatches */
603 ResetMocks();
604 kbh.key_block_flags =
605 KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600606 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800607 "Key block dev flag mismatch");
608
609 ResetMocks();
610 kbh.key_block_flags =
611 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600612 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800613 "Key block rec flag mismatch");
614
615 ResetMocks();
616 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
617 kbh.key_block_flags =
618 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600619 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800620 "Key block recdev flag mismatch");
621
622 ResetMocks();
623 lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
624 kbh.key_block_flags =
625 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600626 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800627 "Key block rec!dev flag mismatch");
628
629 ResetMocks();
630 kbh.data_key.key_version = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600631 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800632 "Key block kernel key rollback");
633
634 ResetMocks();
635 kbh.data_key.key_version = 0x10000;
Simon Glass527ba812013-07-25 08:48:47 -0600636 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800637 "Key block kernel key version too big");
638
Randall Spangler3e9cf902013-02-01 13:31:20 -0800639 ResetMocks();
640 kbh.data_key.key_version = 3;
Simon Glass527ba812013-07-25 08:48:47 -0600641 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800642 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
643
644 ResetMocks();
645 kbh.data_key.key_version = 3;
646 mock_parts[1].start = 300;
647 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600648 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800649 TEST_EQ(mock_part_next, 2, " read both");
650 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
651
652 ResetMocks();
653 kbh.data_key.key_version = 1;
654 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600655 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800656
657 ResetMocks();
658 kbh.data_key.key_version = 1;
659 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600660 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800661
662 ResetMocks();
663 mock_data_key = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600664 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
665 "Bad data key");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800666
667 ResetMocks();
668 preamble_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600669 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
670 "Bad preamble");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800671
672 ResetMocks();
673 kph.kernel_version = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600674 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800675 "Kernel version rollback");
676
Randall Spangler3e9cf902013-02-01 13:31:20 -0800677 ResetMocks();
678 kph.kernel_version = 0;
679 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600680 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800681
682 ResetMocks();
683 kph.kernel_version = 0;
684 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600685 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800686
687 ResetMocks();
688 kph.preamble_size |= 0x07;
Simon Glass527ba812013-07-25 08:48:47 -0600689 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800690 "Kernel body offset");
691
Randall Spangler3e9cf902013-02-01 13:31:20 -0800692 /* Check getting kernel load address from header */
693 ResetMocks();
694 kph.body_load_address = (size_t)kernel_buffer;
695 lkp.kernel_buffer = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600696 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800697 TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
698 /* Size is rounded up to nearest sector */
699 TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
700
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800701 ResetMocks();
702 lkp.kernel_buffer_size = 8192;
Simon Glass527ba812013-07-25 08:48:47 -0600703 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800704 "Kernel too big for buffer");
705
706 ResetMocks();
707 mock_parts[0].size = 130;
Simon Glass527ba812013-07-25 08:48:47 -0600708 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800709 "Kernel too big for partition");
710
Randall Spangler3e9cf902013-02-01 13:31:20 -0800711 ResetMocks();
712 disk_read_to_fail = 108;
Simon Glass527ba812013-07-25 08:48:47 -0600713 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler3e9cf902013-02-01 13:31:20 -0800714 "Fail reading kernel data");
715
716 ResetMocks();
717 verify_data_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600718 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800719}
720
Randall Spangler49cb0d32013-01-29 14:28:16 -0800721int main(void)
722{
723 ReadWriteGptTest();
724 InvalidParamsTest();
Randall Spangler3e9cf902013-02-01 13:31:20 -0800725 LoadKernelTest();
Randall Spangler49cb0d32013-01-29 14:28:16 -0800726
Simon Glass25001852013-08-16 02:47:57 -0600727 if (vboot_api_stub_check_memory())
728 return 255;
729
Randall Spangler49cb0d32013-01-29 14:28:16 -0800730 return gTestSuccess ? 0 : 255;
731}