blob: 0c26d212423676974ea4e3bf9b96fed1b46147a5 [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);
Randall Spangler4184e622014-10-08 16:41:01 -0700156 lkp.disk_handle = (VbExDiskHandle_t)1;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800157
158 memset(&kbh, 0, sizeof(kbh));
159 kbh.data_key.key_version = 2;
160 kbh.key_block_flags = -1;
161 kbh.key_block_size = sizeof(kbh);
162
163 memset(&kph, 0, sizeof(kph));
164 kph.kernel_version = 1;
165 kph.preamble_size = 4096 - kbh.key_block_size;
Randall Spangler4184e622014-10-08 16:41:01 -0700166 kph.body_signature.data_size = 70144;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800167 kph.bootloader_address = 0xbeadd008;
168 kph.bootloader_size = 0x1234;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800169
170 memset(mock_parts, 0, sizeof(mock_parts));
171 mock_parts[0].start = 100;
172 mock_parts[0].size = 150; /* 75 KB */
173 mock_part_next = 0;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800174}
175
176/* Mocks */
177
178VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
179 uint64_t lba_count, void *buffer)
180{
181 LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
182
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800183 if ((int)lba_start == disk_read_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800184 return VBERROR_SIMULATED;
185
Duncan Laurie162f7882014-10-01 09:58:10 -0700186 memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
187 lba_count * MOCK_SECTOR_SIZE);
188
Randall Spangler49cb0d32013-01-29 14:28:16 -0800189 return VBERROR_SUCCESS;
190}
191
192VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
193 uint64_t lba_count, const void *buffer)
194{
195 LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
196
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800197 if ((int)lba_start == disk_write_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800198 return VBERROR_SIMULATED;
199
Duncan Laurie162f7882014-10-01 09:58:10 -0700200 memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
201 lba_count * MOCK_SECTOR_SIZE);
202
Randall Spangler49cb0d32013-01-29 14:28:16 -0800203 return VBERROR_SUCCESS;
204}
205
206int GptInit(GptData *gpt)
207{
208 return gpt_init_fail;
209}
210
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800211int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
212{
213 struct mock_part *p = mock_parts + mock_part_next;
214
215 if (!p->size)
216 return GPT_ERROR_NO_VALID_KERNEL;
217
218 gpt->current_kernel = mock_part_next;
219 *start_sector = p->start;
220 *size = p->size;
221 mock_part_next++;
222 return GPT_SUCCESS;
223}
224
Randall Spangler3e9cf902013-02-01 13:31:20 -0800225void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
226{
227 static char fake_guid[] = "FakeGuid";
228
229 memcpy(dest, fake_guid, sizeof(fake_guid));
230}
231
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800232int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
233 const VbPublicKey *key, int hash_only) {
234
235 if (hash_only && key_block_verify_fail >= 2)
236 return VBERROR_SIMULATED;
237 else if (!hash_only && key_block_verify_fail >= 1)
238 return VBERROR_SIMULATED;
239
240 /* Use this as an opportunity to override the key block */
241 memcpy((void *)block, &kbh, sizeof(kbh));
242 return VBERROR_SUCCESS;
243}
244
245RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
246{
247 TEST_EQ(mock_data_key_allocated, 0, " mock data key not allocated");
248
249 if (mock_data_key)
250 mock_data_key_allocated++;
251
252 return mock_data_key;
253}
254
255void RSAPublicKeyFree(RSAPublicKey* key)
256{
257 TEST_EQ(mock_data_key_allocated, 1, " mock data key allocated");
258 TEST_PTR_EQ(key, mock_data_key, " data key ptr");
259 mock_data_key_allocated--;
260}
261
262int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
263 uint64_t size, const RSAPublicKey *key)
264{
265 if (preamble_verify_fail)
266 return VBERROR_SIMULATED;
267
268 /* Use this as an opportunity to override the preamble */
269 memcpy((void *)preamble, &kph, sizeof(kph));
270 return VBERROR_SUCCESS;
271}
272
Randall Spangler3e9cf902013-02-01 13:31:20 -0800273int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
274 const RSAPublicKey *key)
275{
276 if (verify_data_fail)
277 return VBERROR_SIMULATED;
278
279 return VBERROR_SUCCESS;
280}
281
282
Randall Spangler49cb0d32013-01-29 14:28:16 -0800283/**
284 * Test reading/writing GPT
285 */
286static void ReadWriteGptTest(void)
287{
288 GptData g;
289 GptHeader *h;
290
Duncan Laurie162f7882014-10-01 09:58:10 -0700291 g.sector_bytes = MOCK_SECTOR_SIZE;
292 g.drive_sectors = MOCK_SECTOR_COUNT;
293 g.valid_headers = g.valid_entries = MASK_BOTH;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800294
295 ResetMocks();
296 TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
297 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
298 "VbExDiskRead(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700299 "VbExDiskRead(h, 1023, 1)\n"
300 "VbExDiskRead(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800301 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600302 /*
303 * Valgrind complains about access to uninitialized memory here, so
304 * zero the primary header before each test.
305 */
306 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800307 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
308 TEST_CALLS("");
309
Duncan Laurie162f7882014-10-01 09:58:10 -0700310 /*
311 * Invalidate primary GPT header,
312 * check that AllocAndReadGptData still succeeds
313 */
314 ResetMocks();
315 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
316 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
317 "AllocAndRead primary invalid");
318 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
319 "Primary header is invalid");
320 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
321 "Secondary header is valid");
322 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
323 "VbExDiskRead(h, 1023, 1)\n"
324 "VbExDiskRead(h, 991, 32)\n");
325 WriteAndFreeGptData(handle, &g);
326
327 /*
328 * Invalidate secondary GPT header,
329 * check that AllocAndReadGptData still succeeds
330 */
331 ResetMocks();
332 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
333 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
334 "AllocAndRead secondary invalid");
335 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
336 "Primary header is valid");
337 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
338 "Secondary header is invalid");
339 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
340 "VbExDiskRead(h, 2, 32)\n"
341 "VbExDiskRead(h, 1023, 1)\n");
342 WriteAndFreeGptData(handle, &g);
343
344 /*
345 * Invalidate primary AND secondary GPT header,
346 * check that AllocAndReadGptData fails.
347 */
348 ResetMocks();
349 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
350 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
351 TEST_EQ(AllocAndReadGptData(handle, &g), 1,
352 "AllocAndRead primary and secondary invalid");
353 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 1,
354 "Primary header is invalid");
355 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 1,
356 "Secondary header is invalid");
357 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
358 "VbExDiskRead(h, 1023, 1)\n");
359 WriteAndFreeGptData(handle, &g);
360
361 /*
362 * Invalidate primary GPT header and check that it is
363 * repaired by GptRepair().
364 *
365 * This would normally be called by LoadKernel()->GptInit()
366 * but this callback is mocked in these tests.
367 */
368 ResetMocks();
369 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
370 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
371 "Fix Primary GPT: AllocAndRead");
372 /* Call GptRepair() with input indicating secondary GPT is valid */
373 g.valid_headers = g.valid_entries = MASK_SECONDARY;
374 GptRepair(&g);
375 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
376 "Fix Primary GPT: WriteAndFreeGptData");
377 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
378 "VbExDiskRead(h, 1023, 1)\n"
379 "VbExDiskRead(h, 991, 32)\n"
380 "VbExDiskWrite(h, 1, 1)\n"
381 "VbExDiskWrite(h, 2, 32)\n");
382 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors), 0,
383 "Fix Primary GPT: Primary header is valid");
384
385 /*
386 * Invalidate secondary GPT header and check that it can be
387 * repaired by GptRepair().
388 *
389 * This would normally be called by LoadKernel()->GptInit()
390 * but this callback is mocked in these tests.
391 */
392 ResetMocks();
393 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
394 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
395 "Fix Secondary GPT: AllocAndRead");
396 /* Call GptRepair() with input indicating primary GPT is valid */
397 g.valid_headers = g.valid_entries = MASK_PRIMARY;
398 GptRepair(&g);
399 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
400 "Fix Secondary GPT: WriteAndFreeGptData");
401 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
402 "VbExDiskRead(h, 2, 32)\n"
403 "VbExDiskRead(h, 1023, 1)\n"
404 "VbExDiskWrite(h, 1023, 1)\n"
405 "VbExDiskWrite(h, 991, 32)\n");
406 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors), 0,
407 "Fix Secondary GPT: Secondary header is valid");
408
Randall Spangler49cb0d32013-01-29 14:28:16 -0800409 /* Data which is changed is written */
410 ResetMocks();
411 AllocAndReadGptData(handle, &g);
412 g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
413 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600414 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700415 h = (GptHeader*)g.primary_header;
416 h->entries_lba = 2;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800417 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
418 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
419 "VbExDiskWrite(h, 2, 32)\n");
420
421 /* Data which is changed is written */
422 ResetMocks();
423 AllocAndReadGptData(handle, &g);
424 g.modified = -1;
425 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600426 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700427 h = (GptHeader*)g.primary_header;
428 h->entries_lba = 2;
429 h = (GptHeader*)g.secondary_header;
430 h->entries_lba = 991;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800431 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
432 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
433 "VbExDiskWrite(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700434 "VbExDiskWrite(h, 1023, 1)\n"
435 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800436
437 /* If legacy signature, don't modify GPT header/entries 1 */
438 ResetMocks();
439 AllocAndReadGptData(handle, &g);
440 h = (GptHeader *)g.primary_header;
441 memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
442 g.modified = -1;
443 ResetCallLog();
444 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700445 TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
446 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800447
448 /* Error reading */
449 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800450 disk_read_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800451 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600452 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800453 WriteAndFreeGptData(handle, &g);
454
Randall Spangler3e9cf902013-02-01 13:31:20 -0800455 ResetMocks();
456 disk_read_to_fail = 2;
457 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600458 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800459 WriteAndFreeGptData(handle, &g);
460
461 ResetMocks();
462 disk_read_to_fail = 991;
463 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600464 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800465 WriteAndFreeGptData(handle, &g);
466
467 ResetMocks();
468 disk_read_to_fail = 1023;
469 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600470 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800471 WriteAndFreeGptData(handle, &g);
472
Randall Spangler49cb0d32013-01-29 14:28:16 -0800473 /* Error writing */
474 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800475 disk_write_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800476 AllocAndReadGptData(handle, &g);
477 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600478 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800479 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800480
481 ResetMocks();
482 disk_write_to_fail = 2;
483 AllocAndReadGptData(handle, &g);
484 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600485 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700486 h = (GptHeader*)g.primary_header;
487 h->entries_lba = 2;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800488 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
489
490 ResetMocks();
491 disk_write_to_fail = 991;
492 AllocAndReadGptData(handle, &g);
493 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600494 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800495 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
496
497 ResetMocks();
498 disk_write_to_fail = 1023;
499 AllocAndReadGptData(handle, &g);
500 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600501 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800502 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
503
Randall Spangler49cb0d32013-01-29 14:28:16 -0800504}
505
506/**
507 * Trivial invalid calls to LoadKernel()
508 */
509static void InvalidParamsTest(void)
510{
511 ResetMocks();
512 lkp.bytes_per_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600513 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
514 "Bad lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800515
516 ResetMocks();
517 lkp.ending_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600518 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
519 "Bad lba count");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800520
521 ResetMocks();
522 lkp.bytes_per_lba = 128*1024;
Simon Glass527ba812013-07-25 08:48:47 -0600523 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
524 "Huge lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800525
526 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800527 disk_read_to_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600528 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
529 "Can't read disk");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800530
531 ResetMocks();
532 gpt_init_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600533 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
534 "Bad GPT");
Randall Spangler4184e622014-10-08 16:41:01 -0700535
536 /* This causes the stream open call to fail */
537 ResetMocks();
538 lkp.disk_handle = NULL;
539 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
540 "Bad disk handle");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800541}
542
Randall Spangler3e9cf902013-02-01 13:31:20 -0800543static void LoadKernelTest(void)
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800544{
Randall Spangler3e9cf902013-02-01 13:31:20 -0800545 uint32_t u;
546
547 ResetMocks();
Randall Spangler4184e622014-10-08 16:41:01 -0700548
549 u = LoadKernel(&lkp, &cparams);
550 TEST_EQ(u, 0, "First kernel good");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800551 TEST_EQ(lkp.partition_number, 1, " part num");
552 TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
553 TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
554 TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", " guid");
555 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
556 TEST_EQ(u, 0, " recovery request");
557
558 ResetMocks();
559 mock_parts[1].start = 300;
560 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600561 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800562 TEST_EQ(lkp.partition_number, 1, " part num");
563 TEST_EQ(mock_part_next, 1, " didn't read second one");
564
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800565 /* Fail if no kernels found */
566 ResetMocks();
567 mock_parts[0].size = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600568 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800569 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
570 TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800571
572 /* Skip kernels which are too small */
573 ResetMocks();
574 mock_parts[0].size = 10;
Simon Glass527ba812013-07-25 08:48:47 -0600575 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800576 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
577 TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800578
579 ResetMocks();
580 disk_read_to_fail = 100;
Simon Glass527ba812013-07-25 08:48:47 -0600581 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800582 "Fail reading kernel start");
583
584 ResetMocks();
585 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600586 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800587 "Fail key block sig");
588
589 /* In dev mode, fail if hash is bad too */
590 ResetMocks();
591 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
592 key_block_verify_fail = 2;
Simon Glass527ba812013-07-25 08:48:47 -0600593 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800594 "Fail key block dev hash");
595
Randall Spangler3e9cf902013-02-01 13:31:20 -0800596 /* But just bad sig is ok */
597 ResetMocks();
598 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
599 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600600 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800601
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800602 /* In dev mode and requiring signed kernel, fail if sig is bad */
603 ResetMocks();
604 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
605 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
606 VbNvTeardown(&vnc);
607 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600608 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800609 "Fail key block dev sig");
610
611 /* Check key block flag mismatches */
612 ResetMocks();
613 kbh.key_block_flags =
614 KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600615 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800616 "Key block dev flag mismatch");
617
618 ResetMocks();
619 kbh.key_block_flags =
620 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600621 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800622 "Key block rec flag mismatch");
623
624 ResetMocks();
625 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
626 kbh.key_block_flags =
627 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600628 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800629 "Key block recdev flag mismatch");
630
631 ResetMocks();
632 lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
633 kbh.key_block_flags =
634 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600635 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800636 "Key block rec!dev flag mismatch");
637
638 ResetMocks();
639 kbh.data_key.key_version = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600640 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800641 "Key block kernel key rollback");
642
643 ResetMocks();
644 kbh.data_key.key_version = 0x10000;
Simon Glass527ba812013-07-25 08:48:47 -0600645 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800646 "Key block kernel key version too big");
647
Randall Spangler3e9cf902013-02-01 13:31:20 -0800648 ResetMocks();
649 kbh.data_key.key_version = 3;
Simon Glass527ba812013-07-25 08:48:47 -0600650 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800651 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
652
653 ResetMocks();
654 kbh.data_key.key_version = 3;
655 mock_parts[1].start = 300;
656 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600657 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800658 TEST_EQ(mock_part_next, 2, " read both");
659 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
660
661 ResetMocks();
662 kbh.data_key.key_version = 1;
663 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600664 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800665
666 ResetMocks();
667 kbh.data_key.key_version = 1;
668 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600669 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800670
671 ResetMocks();
672 mock_data_key = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600673 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
674 "Bad data key");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800675
676 ResetMocks();
677 preamble_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600678 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
679 "Bad preamble");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800680
681 ResetMocks();
682 kph.kernel_version = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600683 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800684 "Kernel version rollback");
685
Randall Spangler3e9cf902013-02-01 13:31:20 -0800686 ResetMocks();
687 kph.kernel_version = 0;
688 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600689 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800690
691 ResetMocks();
692 kph.kernel_version = 0;
693 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600694 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800695
696 ResetMocks();
697 kph.preamble_size |= 0x07;
Simon Glass527ba812013-07-25 08:48:47 -0600698 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800699 "Kernel body offset");
700
Randall Spangler4184e622014-10-08 16:41:01 -0700701 ResetMocks();
702 kph.preamble_size += 65536;
703 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
704 "Kernel body offset huge");
705
Randall Spangler3e9cf902013-02-01 13:31:20 -0800706 /* Check getting kernel load address from header */
707 ResetMocks();
708 kph.body_load_address = (size_t)kernel_buffer;
709 lkp.kernel_buffer = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600710 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800711 TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
712 /* Size is rounded up to nearest sector */
713 TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
714
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800715 ResetMocks();
716 lkp.kernel_buffer_size = 8192;
Simon Glass527ba812013-07-25 08:48:47 -0600717 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800718 "Kernel too big for buffer");
719
720 ResetMocks();
721 mock_parts[0].size = 130;
Simon Glass527ba812013-07-25 08:48:47 -0600722 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800723 "Kernel too big for partition");
724
Randall Spangler3e9cf902013-02-01 13:31:20 -0800725 ResetMocks();
Randall Spangler4184e622014-10-08 16:41:01 -0700726 kph.body_signature.data_size = 8192;
727 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel tiny");
728
729 ResetMocks();
730 disk_read_to_fail = 228;
Simon Glass527ba812013-07-25 08:48:47 -0600731 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler3e9cf902013-02-01 13:31:20 -0800732 "Fail reading kernel data");
733
734 ResetMocks();
735 verify_data_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600736 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800737}
738
Randall Spangler49cb0d32013-01-29 14:28:16 -0800739int main(void)
740{
741 ReadWriteGptTest();
742 InvalidParamsTest();
Randall Spangler3e9cf902013-02-01 13:31:20 -0800743 LoadKernelTest();
Randall Spangler49cb0d32013-01-29 14:28:16 -0800744
Simon Glass25001852013-08-16 02:47:57 -0600745 if (vboot_api_stub_check_memory())
746 return 255;
747
Randall Spangler49cb0d32013-01-29 14:28:16 -0800748 return gTestSuccess ? 0 : 255;
749}