blob: c546ed120d60ff96426420e79c7bd4022f0cb6e6 [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;
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700292 g.drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT;
Duncan Laurie162f7882014-10-01 09:58:10 -0700293 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");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700318 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800319 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
320 1, "Primary header is invalid");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700321 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800322 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
323 0, "Secondary header is valid");
Duncan Laurie162f7882014-10-01 09:58:10 -0700324 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
325 "VbExDiskRead(h, 1023, 1)\n"
326 "VbExDiskRead(h, 991, 32)\n");
327 WriteAndFreeGptData(handle, &g);
328
329 /*
330 * Invalidate secondary GPT header,
331 * check that AllocAndReadGptData still succeeds
332 */
333 ResetMocks();
334 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
335 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
336 "AllocAndRead secondary invalid");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700337 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800338 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
339 0, "Primary header is valid");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700340 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800341 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
342 1, "Secondary header is invalid");
Duncan Laurie162f7882014-10-01 09:58:10 -0700343 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
344 "VbExDiskRead(h, 2, 32)\n"
345 "VbExDiskRead(h, 1023, 1)\n");
346 WriteAndFreeGptData(handle, &g);
347
348 /*
349 * Invalidate primary AND secondary GPT header,
350 * check that AllocAndReadGptData fails.
351 */
352 ResetMocks();
353 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
354 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
355 TEST_EQ(AllocAndReadGptData(handle, &g), 1,
356 "AllocAndRead primary and secondary invalid");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700357 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800358 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
359 1, "Primary header is invalid");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700360 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800361 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
362 1, "Secondary header is invalid");
Duncan Laurie162f7882014-10-01 09:58:10 -0700363 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
364 "VbExDiskRead(h, 1023, 1)\n");
365 WriteAndFreeGptData(handle, &g);
366
367 /*
368 * Invalidate primary GPT header and check that it is
369 * repaired by GptRepair().
370 *
371 * This would normally be called by LoadKernel()->GptInit()
372 * but this callback is mocked in these tests.
373 */
374 ResetMocks();
375 Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
376 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
377 "Fix Primary GPT: AllocAndRead");
378 /* Call GptRepair() with input indicating secondary GPT is valid */
379 g.valid_headers = g.valid_entries = MASK_SECONDARY;
380 GptRepair(&g);
381 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
382 "Fix Primary GPT: WriteAndFreeGptData");
383 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
384 "VbExDiskRead(h, 1023, 1)\n"
385 "VbExDiskRead(h, 991, 32)\n"
386 "VbExDiskWrite(h, 1, 1)\n"
387 "VbExDiskWrite(h, 2, 32)\n");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700388 TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800389 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
390 0, "Fix Primary GPT: Primary header is valid");
Duncan Laurie162f7882014-10-01 09:58:10 -0700391
392 /*
393 * Invalidate secondary GPT header and check that it can be
394 * repaired by GptRepair().
395 *
396 * This would normally be called by LoadKernel()->GptInit()
397 * but this callback is mocked in these tests.
398 */
399 ResetMocks();
400 Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
401 TEST_EQ(AllocAndReadGptData(handle, &g), 0,
402 "Fix Secondary GPT: AllocAndRead");
403 /* Call GptRepair() with input indicating primary GPT is valid */
404 g.valid_headers = g.valid_entries = MASK_PRIMARY;
405 GptRepair(&g);
406 TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
407 "Fix Secondary GPT: WriteAndFreeGptData");
408 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
409 "VbExDiskRead(h, 2, 32)\n"
410 "VbExDiskRead(h, 1023, 1)\n"
411 "VbExDiskWrite(h, 1023, 1)\n"
412 "VbExDiskWrite(h, 991, 32)\n");
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700413 TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800414 g.gpt_drive_sectors, GPT_STORED_ON_DEVICE),
415 0, "Fix Secondary GPT: Secondary header is valid");
Duncan Laurie162f7882014-10-01 09:58:10 -0700416
Randall Spangler49cb0d32013-01-29 14:28:16 -0800417 /* Data which is changed is written */
418 ResetMocks();
419 AllocAndReadGptData(handle, &g);
420 g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
421 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600422 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700423 h = (GptHeader*)g.primary_header;
424 h->entries_lba = 2;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800425 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
426 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
427 "VbExDiskWrite(h, 2, 32)\n");
428
429 /* Data which is changed is written */
430 ResetMocks();
431 AllocAndReadGptData(handle, &g);
432 g.modified = -1;
433 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600434 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700435 h = (GptHeader*)g.primary_header;
436 h->entries_lba = 2;
437 h = (GptHeader*)g.secondary_header;
438 h->entries_lba = 991;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800439 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
440 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
441 "VbExDiskWrite(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700442 "VbExDiskWrite(h, 1023, 1)\n"
443 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800444
445 /* If legacy signature, don't modify GPT header/entries 1 */
446 ResetMocks();
447 AllocAndReadGptData(handle, &g);
448 h = (GptHeader *)g.primary_header;
449 memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
450 g.modified = -1;
451 ResetCallLog();
452 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700453 TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
454 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800455
456 /* Error reading */
457 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800458 disk_read_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800459 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600460 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800461 WriteAndFreeGptData(handle, &g);
462
Randall Spangler3e9cf902013-02-01 13:31:20 -0800463 ResetMocks();
464 disk_read_to_fail = 2;
465 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600466 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800467 WriteAndFreeGptData(handle, &g);
468
469 ResetMocks();
470 disk_read_to_fail = 991;
471 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600472 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800473 WriteAndFreeGptData(handle, &g);
474
475 ResetMocks();
476 disk_read_to_fail = 1023;
477 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600478 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800479 WriteAndFreeGptData(handle, &g);
480
Randall Spangler49cb0d32013-01-29 14:28:16 -0800481 /* Error writing */
482 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800483 disk_write_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800484 AllocAndReadGptData(handle, &g);
485 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600486 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800487 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800488
489 ResetMocks();
490 disk_write_to_fail = 2;
491 AllocAndReadGptData(handle, &g);
492 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600493 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700494 h = (GptHeader*)g.primary_header;
495 h->entries_lba = 2;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800496 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
497
498 ResetMocks();
499 disk_write_to_fail = 991;
500 AllocAndReadGptData(handle, &g);
501 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600502 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800503 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
504
505 ResetMocks();
506 disk_write_to_fail = 1023;
507 AllocAndReadGptData(handle, &g);
508 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600509 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800510 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
511
Randall Spangler49cb0d32013-01-29 14:28:16 -0800512}
513
514/**
515 * Trivial invalid calls to LoadKernel()
516 */
517static void InvalidParamsTest(void)
518{
519 ResetMocks();
520 lkp.bytes_per_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600521 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
522 "Bad lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800523
524 ResetMocks();
525 lkp.ending_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600526 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
527 "Bad lba count");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800528
529 ResetMocks();
530 lkp.bytes_per_lba = 128*1024;
Simon Glass527ba812013-07-25 08:48:47 -0600531 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
532 "Huge lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800533
534 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800535 disk_read_to_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600536 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
537 "Can't read disk");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800538
539 ResetMocks();
540 gpt_init_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600541 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
542 "Bad GPT");
Randall Spangler4184e622014-10-08 16:41:01 -0700543
544 /* This causes the stream open call to fail */
545 ResetMocks();
546 lkp.disk_handle = NULL;
547 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
548 "Bad disk handle");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800549}
550
Randall Spangler3e9cf902013-02-01 13:31:20 -0800551static void LoadKernelTest(void)
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800552{
Randall Spangler3e9cf902013-02-01 13:31:20 -0800553 uint32_t u;
554
555 ResetMocks();
Randall Spangler4184e622014-10-08 16:41:01 -0700556
557 u = LoadKernel(&lkp, &cparams);
558 TEST_EQ(u, 0, "First kernel good");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800559 TEST_EQ(lkp.partition_number, 1, " part num");
560 TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
561 TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
562 TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", " guid");
563 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
564 TEST_EQ(u, 0, " recovery request");
565
566 ResetMocks();
567 mock_parts[1].start = 300;
568 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600569 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800570 TEST_EQ(lkp.partition_number, 1, " part num");
571 TEST_EQ(mock_part_next, 1, " didn't read second one");
572
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800573 /* Fail if no kernels found */
574 ResetMocks();
575 mock_parts[0].size = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600576 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800577 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
578 TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800579
580 /* Skip kernels which are too small */
581 ResetMocks();
582 mock_parts[0].size = 10;
Simon Glass527ba812013-07-25 08:48:47 -0600583 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800584 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
585 TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800586
587 ResetMocks();
588 disk_read_to_fail = 100;
Simon Glass527ba812013-07-25 08:48:47 -0600589 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800590 "Fail reading kernel start");
591
592 ResetMocks();
593 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600594 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800595 "Fail key block sig");
596
597 /* In dev mode, fail if hash is bad too */
598 ResetMocks();
599 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
600 key_block_verify_fail = 2;
Simon Glass527ba812013-07-25 08:48:47 -0600601 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800602 "Fail key block dev hash");
603
Randall Spangler3e9cf902013-02-01 13:31:20 -0800604 /* But just bad sig is ok */
605 ResetMocks();
606 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
607 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600608 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800609
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800610 /* In dev mode and requiring signed kernel, fail if sig is bad */
611 ResetMocks();
612 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
613 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
614 VbNvTeardown(&vnc);
615 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600616 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800617 "Fail key block dev sig");
618
619 /* Check key block flag mismatches */
620 ResetMocks();
621 kbh.key_block_flags =
622 KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600623 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800624 "Key block dev flag mismatch");
625
626 ResetMocks();
627 kbh.key_block_flags =
628 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600629 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800630 "Key block rec flag mismatch");
631
632 ResetMocks();
633 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
634 kbh.key_block_flags =
635 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
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 recdev flag mismatch");
638
639 ResetMocks();
640 lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
641 kbh.key_block_flags =
642 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600643 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800644 "Key block rec!dev flag mismatch");
645
646 ResetMocks();
647 kbh.data_key.key_version = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600648 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800649 "Key block kernel key rollback");
650
651 ResetMocks();
652 kbh.data_key.key_version = 0x10000;
Simon Glass527ba812013-07-25 08:48:47 -0600653 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800654 "Key block kernel key version too big");
655
Randall Spangler3e9cf902013-02-01 13:31:20 -0800656 ResetMocks();
657 kbh.data_key.key_version = 3;
Simon Glass527ba812013-07-25 08:48:47 -0600658 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800659 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
660
661 ResetMocks();
662 kbh.data_key.key_version = 3;
663 mock_parts[1].start = 300;
664 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600665 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800666 TEST_EQ(mock_part_next, 2, " read both");
667 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
668
669 ResetMocks();
670 kbh.data_key.key_version = 1;
671 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600672 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800673
674 ResetMocks();
675 kbh.data_key.key_version = 1;
676 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600677 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800678
679 ResetMocks();
680 mock_data_key = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600681 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
682 "Bad data key");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800683
684 ResetMocks();
685 preamble_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600686 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
687 "Bad preamble");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800688
689 ResetMocks();
690 kph.kernel_version = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600691 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800692 "Kernel version rollback");
693
Randall Spangler3e9cf902013-02-01 13:31:20 -0800694 ResetMocks();
695 kph.kernel_version = 0;
696 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600697 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800698
699 ResetMocks();
700 kph.kernel_version = 0;
701 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600702 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800703
704 ResetMocks();
705 kph.preamble_size |= 0x07;
Simon Glass527ba812013-07-25 08:48:47 -0600706 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800707 "Kernel body offset");
708
Randall Spangler4184e622014-10-08 16:41:01 -0700709 ResetMocks();
710 kph.preamble_size += 65536;
711 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
712 "Kernel body offset huge");
713
Randall Spangler3e9cf902013-02-01 13:31:20 -0800714 /* Check getting kernel load address from header */
715 ResetMocks();
716 kph.body_load_address = (size_t)kernel_buffer;
717 lkp.kernel_buffer = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600718 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800719 TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
720 /* Size is rounded up to nearest sector */
721 TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
722
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800723 ResetMocks();
724 lkp.kernel_buffer_size = 8192;
Simon Glass527ba812013-07-25 08:48:47 -0600725 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800726 "Kernel too big for buffer");
727
728 ResetMocks();
729 mock_parts[0].size = 130;
Simon Glass527ba812013-07-25 08:48:47 -0600730 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800731 "Kernel too big for partition");
732
Randall Spangler3e9cf902013-02-01 13:31:20 -0800733 ResetMocks();
Randall Spangler4184e622014-10-08 16:41:01 -0700734 kph.body_signature.data_size = 8192;
735 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel tiny");
736
737 ResetMocks();
738 disk_read_to_fail = 228;
Simon Glass527ba812013-07-25 08:48:47 -0600739 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler3e9cf902013-02-01 13:31:20 -0800740 "Fail reading kernel data");
741
742 ResetMocks();
743 verify_data_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600744 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800745}
746
Randall Spangler49cb0d32013-01-29 14:28:16 -0800747int main(void)
748{
749 ReadWriteGptTest();
750 InvalidParamsTest();
Randall Spangler3e9cf902013-02-01 13:31:20 -0800751 LoadKernelTest();
Randall Spangler49cb0d32013-01-29 14:28:16 -0800752
Simon Glass25001852013-08-16 02:47:57 -0600753 if (vboot_api_stub_check_memory())
754 return 255;
755
Randall Spangler49cb0d32013-01-29 14:28:16 -0800756 return gTestSuccess ? 0 : 255;
757}