blob: 363ecc8ab3c20df8b80861883420f04859cc900a [file] [log] [blame]
Randall Spanglere9213a72013-01-24 11:19:55 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Alex Deymof5109732014-08-25 16:34:52 -07006#include <errno.h>
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -07007#include <string.h>
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07008
Albert Chaulk534723a2013-03-20 14:46:50 -07009#include "../cgpt/cgpt.h"
Bill Richardson18e03702014-06-23 17:48:33 -070010#include "../cgpt/flash_ts.h"
Louis Yung-Chieh Lo0dce41c2010-05-17 22:45:30 -070011#include "cgptlib_internal.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070012#include "cgptlib_test.h"
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070013#include "crc32.h"
Louis Yung-Chieh Lob31ddce2010-05-21 16:35:44 +080014#include "crc32_test.h"
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070015#include "gpt.h"
Albert Chaulk5c9e4532013-03-20 16:03:49 -070016#include "mtdlib.h"
Bill Richardson18e03702014-06-23 17:48:33 -070017#include "mtdlib_unused.h"
vbendeb3ecaf772010-06-24 16:19:53 -070018#include "test_common.h"
Albert Chaulk534723a2013-03-20 14:46:50 -070019#define _STUB_IMPLEMENTATION_
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070020#include "utility.h"
21
Randall Spanglere9213a72013-01-24 11:19:55 -080022/*
23 * Testing partition layout (sector_bytes=512)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070024 *
25 * LBA Size Usage
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070026 * ---------------------------------------------------------
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070027 * 0 1 PMBR
28 * 1 1 primary partition header
29 * 2 32 primary partition entries (128B * 128)
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070030 * 34 100 kernel A (index: 0)
31 * 134 100 root A (index: 1)
32 * 234 100 root B (index: 2)
33 * 334 100 kernel B (index: 3)
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070034 * 434 32 secondary partition entries
35 * 466 1 secondary partition header
36 * 467
37 */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070038#define KERNEL_A 0
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070039#define KERNEL_B 1
40#define ROOTFS_A 2
41#define ROOTFS_B 3
42#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
43#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -070044
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070045#define DEFAULT_SECTOR_SIZE 512
46#define MAX_SECTOR_SIZE 4096
47#define DEFAULT_DRIVE_SECTORS 467
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070048#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070049
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070050static const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
51static const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
52static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
53
Albert Chaulk534723a2013-03-20 14:46:50 -070054// cgpt_common.c requires these be defined if linked in.
55const char *progname = "CGPT-TEST";
56const char *command = "TEST";
57
58// Ramdisk for flash ts testing.
59static uint8_t *nand_drive = NULL;
60static uint32_t nand_drive_sz;
61static uint8_t *nand_bad_block_map = NULL;
62
Randall Spanglere9213a72013-01-24 11:19:55 -080063/*
64 * Copy a random-for-this-program-only Guid into the dest. The num parameter
Bill Richardsonaa8eda42010-08-27 09:31:26 -070065 * completely determines the Guid.
66 */
Randall Spanglere9213a72013-01-24 11:19:55 -080067static void SetGuid(void *dest, uint32_t num)
68{
69 Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
70 {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
71 Memcpy(dest, &g, sizeof(Guid));
Bill Richardsonaa8eda42010-08-27 09:31:26 -070072}
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070073
Randall Spanglere9213a72013-01-24 11:19:55 -080074/*
75 * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
76 * header CRC32 value to 0, and calculate header CRC32 value. Both primary and
77 * secondary are updated.
78 */
79static void RefreshCrc32(GptData *gpt)
80{
81 GptHeader *header, *header2;
82 GptEntry *entries, *entries2;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070083
Randall Spanglere9213a72013-01-24 11:19:55 -080084 header = (GptHeader *)gpt->primary_header;
85 entries = (GptEntry *)gpt->primary_entries;
86 header2 = (GptHeader *)gpt->secondary_header;
87 entries2 = (GptEntry *)gpt->secondary_entries;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -070088
Randall Spanglere9213a72013-01-24 11:19:55 -080089 header->entries_crc32 =
90 Crc32((uint8_t *)entries,
91 header->number_of_entries * header->size_of_entry);
92 header->header_crc32 = 0;
93 header->header_crc32 = Crc32((uint8_t *)header, header->size);
94 header2->entries_crc32 =
95 Crc32((uint8_t *)entries2,
96 header2->number_of_entries * header2->size_of_entry);
97 header2->header_crc32 = 0;
98 header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -070099}
100
Randall Spanglere9213a72013-01-24 11:19:55 -0800101static void ZeroHeaders(GptData *gpt)
102{
103 Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
104 Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700105}
106
Randall Spanglere9213a72013-01-24 11:19:55 -0800107static void ZeroEntries(GptData *gpt)
108{
109 Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
110 Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700111}
112
Randall Spanglere9213a72013-01-24 11:19:55 -0800113static void ZeroHeadersEntries(GptData *gpt)
114{
115 ZeroHeaders(gpt);
116 ZeroEntries(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700117}
118
Randall Spanglere9213a72013-01-24 11:19:55 -0800119/*
120 * Return a pointer to a static GptData instance (no free is required).
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700121 * All fields are zero except 4 pointers linking to header and entries.
Randall Spanglere9213a72013-01-24 11:19:55 -0800122 * All content of headers and entries are zero.
123 */
124static GptData *GetEmptyGptData(void)
125{
126 static GptData gpt;
127 static uint8_t primary_header[MAX_SECTOR_SIZE];
128 static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
129 static uint8_t secondary_header[MAX_SECTOR_SIZE];
130 static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700131
Randall Spanglere9213a72013-01-24 11:19:55 -0800132 Memset(&gpt, 0, sizeof(gpt));
133 gpt.primary_header = primary_header;
134 gpt.primary_entries = primary_entries;
135 gpt.secondary_header = secondary_header;
136 gpt.secondary_entries = secondary_entries;
137 ZeroHeadersEntries(&gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700138
Randall Spanglere9213a72013-01-24 11:19:55 -0800139 /* Initialize GptData internal states. */
140 gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -0700141
Randall Spanglere9213a72013-01-24 11:19:55 -0800142 return &gpt;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700143}
144
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700145static MtdData *GetEmptyMtdData() {
146 static MtdData mtd;
147 Memset(&mtd, 0, sizeof(mtd));
148 mtd.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
149 return &mtd;
150}
151
Randall Spanglere9213a72013-01-24 11:19:55 -0800152/*
153 * Fill in most of fields and creates the layout described in the top of this
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700154 * file. Before calling this function, primary/secondary header/entries must
155 * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
156 * This function returns a good (valid) copy of GPT layout described in top of
Randall Spanglere9213a72013-01-24 11:19:55 -0800157 * this file.
158 */
159static void BuildTestGptData(GptData *gpt)
160{
161 GptHeader *header, *header2;
162 GptEntry *entries, *entries2;
163 Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
164 Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700165
Randall Spanglere9213a72013-01-24 11:19:55 -0800166 gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
167 gpt->drive_sectors = DEFAULT_DRIVE_SECTORS;
168 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
169 gpt->valid_headers = MASK_BOTH;
170 gpt->valid_entries = MASK_BOTH;
171 gpt->modified = 0;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700172
Randall Spanglere9213a72013-01-24 11:19:55 -0800173 /* Build primary */
174 header = (GptHeader *)gpt->primary_header;
175 entries = (GptEntry *)gpt->primary_entries;
176 Memcpy(header->signature, GPT_HEADER_SIGNATURE,
177 sizeof(GPT_HEADER_SIGNATURE));
178 header->revision = GPT_HEADER_REVISION;
179 header->size = sizeof(GptHeader);
180 header->reserved_zero = 0;
181 header->my_lba = 1;
182 header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
183 header->first_usable_lba = 34;
184 header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1; /* 433 */
185 header->entries_lba = 2;
186 /* 512B / 128B * 32sectors = 128 entries */
187 header->number_of_entries = 128;
188 header->size_of_entry = 128; /* bytes */
189 Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
190 SetGuid(&entries[0].unique, 0);
191 entries[0].starting_lba = 34;
192 entries[0].ending_lba = 133;
193 Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
194 SetGuid(&entries[1].unique, 1);
195 entries[1].starting_lba = 134;
196 entries[1].ending_lba = 232;
197 Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
198 SetGuid(&entries[2].unique, 2);
199 entries[2].starting_lba = 234;
200 entries[2].ending_lba = 331;
201 Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
202 SetGuid(&entries[3].unique, 3);
203 entries[3].starting_lba = 334;
204 entries[3].ending_lba = 430;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700205
Randall Spanglere9213a72013-01-24 11:19:55 -0800206 /* Build secondary */
207 header2 = (GptHeader *)gpt->secondary_header;
208 entries2 = (GptEntry *)gpt->secondary_entries;
209 Memcpy(header2, header, sizeof(GptHeader));
210 Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
211 header2->my_lba = DEFAULT_DRIVE_SECTORS - 1; /* 466 */
212 header2->alternate_lba = 1;
213 header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32; /* 434 */
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700214
Randall Spanglere9213a72013-01-24 11:19:55 -0800215 RefreshCrc32(gpt);
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700216}
217
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700218static void BuildTestMtdData(MtdData *mtd) {
219 MtdDiskPartition *partitions;
220
221 mtd->sector_bytes = DEFAULT_SECTOR_SIZE;
222 mtd->drive_sectors = DEFAULT_DRIVE_SECTORS;
223 mtd->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
224 mtd->modified = 0;
225 Memset(&mtd->primary, 0, sizeof(mtd->primary));
226
227 Memcpy(mtd->primary.signature, MTD_DRIVE_SIGNATURE,
228 sizeof(mtd->primary.signature));
Albert Chaulk289b6042013-06-25 11:30:46 -0700229 mtd->primary.first_offset = 32 * DEFAULT_SECTOR_SIZE;
230 mtd->primary.last_offset = DEFAULT_DRIVE_SECTORS * DEFAULT_SECTOR_SIZE - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700231 mtd->primary.size = MTD_DRIVE_V1_SIZE;
232
233 /* These values are not used directly by the library, but they are checked */
234 mtd->flash_page_bytes = mtd->sector_bytes * 8;
235 mtd->flash_block_bytes = mtd->flash_page_bytes * 8;
236 mtd->fts_block_offset = 1;
237 mtd->fts_block_size = 1;
238
239 partitions = &mtd->primary.partitions[0];
Albert Chaulk289b6042013-06-25 11:30:46 -0700240 partitions[0].starting_offset = 34 * DEFAULT_SECTOR_SIZE;
241 partitions[0].ending_offset = 134 * DEFAULT_SECTOR_SIZE - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700242 partitions[0].flags =
243 MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
Albert Chaulk289b6042013-06-25 11:30:46 -0700244 partitions[1].starting_offset = 134 * DEFAULT_SECTOR_SIZE;
245 partitions[1].ending_offset = 233 * DEFAULT_SECTOR_SIZE - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700246 partitions[1].flags =
247 MTD_PARTITION_TYPE_CHROMEOS_ROOTFS << MTD_ATTRIBUTE_TYPE_OFFSET;
Albert Chaulk289b6042013-06-25 11:30:46 -0700248 partitions[2].starting_offset = 234 * DEFAULT_SECTOR_SIZE;
249 partitions[2].ending_offset = 332 * DEFAULT_SECTOR_SIZE - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700250 partitions[2].flags =
251 MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
Albert Chaulk289b6042013-06-25 11:30:46 -0700252 partitions[3].starting_offset = 334 * DEFAULT_SECTOR_SIZE;
253 partitions[3].ending_offset = 431 * DEFAULT_SECTOR_SIZE - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700254 partitions[3].flags =
255 MTD_PARTITION_TYPE_CHROMEOS_ROOTFS << MTD_ATTRIBUTE_TYPE_OFFSET;
256
257 mtd->primary.crc32 = 0;
258 mtd->primary.crc32 = Crc32(&mtd->primary, MTD_DRIVE_V1_SIZE);
259}
260
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700261
Randall Spanglere9213a72013-01-24 11:19:55 -0800262/*
263 * Test if the structures are the expected size; if this fails, struct packing
264 * is not working properly.
265 */
266static int StructSizeTest(void)
267{
Randall Spangler81d09962010-06-23 10:15:38 -0700268
Randall Spanglere9213a72013-01-24 11:19:55 -0800269 EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
270 EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
271 EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700272 EXPECT(MTDENTRY_EXPECTED_SIZE == sizeof(MtdDiskPartition));
273 EXPECT(MTDLAYOUT_EXPECTED_SIZE == sizeof(MtdDiskLayout));
Randall Spanglere9213a72013-01-24 11:19:55 -0800274 return TEST_OK;
Randall Spangler81d09962010-06-23 10:15:38 -0700275}
276
277
Randall Spanglere9213a72013-01-24 11:19:55 -0800278/* Test if the default structure returned by BuildTestGptData() is good. */
279static int TestBuildTestGptData(void)
280{
281 GptData *gpt;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700282
Randall Spanglere9213a72013-01-24 11:19:55 -0800283 gpt = GetEmptyGptData();
284 BuildTestGptData(gpt);
285 EXPECT(GPT_SUCCESS == GptInit(gpt));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800286 gpt->sector_bytes = 0;
287 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
Randall Spanglere9213a72013-01-24 11:19:55 -0800288 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700289}
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700290
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700291static int TestBuildTestMtdData() {
292 MtdData *mtd = GetEmptyMtdData();
293
294 BuildTestMtdData(mtd);
295 EXPECT(GPT_SUCCESS == MtdInit(mtd));
296 return TEST_OK;
297}
298
Randall Spanglere9213a72013-01-24 11:19:55 -0800299/*
300 * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
301 * Currently we only support 512 bytes per sector. In the future, we may
302 * support other sizes. A too small drive_sectors should be rejected by
303 * GptInit().
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700304 * For MtdInit(), additionally test various flash geometries to verify
305 * that only valid ones are accepted.
Randall Spanglere9213a72013-01-24 11:19:55 -0800306 */
307static int ParameterTests(void)
308{
309 GptData *gpt;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700310 MtdData *mtd;
Randall Spanglere9213a72013-01-24 11:19:55 -0800311 struct {
312 uint32_t sector_bytes;
313 uint64_t drive_sectors;
314 int expected_retval;
315 } cases[] = {
316 {512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
317 {520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
318 {512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
319 {512, 66, GPT_ERROR_INVALID_SECTOR_NUMBER},
Nam T. Nguyen88458d92014-08-28 10:58:47 -0700320 {512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
Randall Spanglere9213a72013-01-24 11:19:55 -0800321 GPT_ENTRIES_SECTORS * 2, GPT_SUCCESS},
322 {4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
323 };
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700324 struct {
325 uint32_t sector_bytes;
326 uint32_t drive_sectors;
327 uint32_t flash_page_bytes;
328 uint32_t flash_block_bytes;
329 int expected_retval;
330 } mtdcases[] = {
331 {512, DEFAULT_DRIVE_SECTORS, 8*512,
332 8*512, GPT_SUCCESS},
333 {510, DEFAULT_DRIVE_SECTORS, 8*512,
334 8*512, GPT_ERROR_INVALID_SECTOR_SIZE},
335 {512, DEFAULT_DRIVE_SECTORS, 8*512,
336 8*512, GPT_SUCCESS},
337 {512, DEFAULT_DRIVE_SECTORS, 512,
338 8*512, GPT_SUCCESS},
339 {512, DEFAULT_DRIVE_SECTORS, 8*512,
340 10*512, GPT_ERROR_INVALID_FLASH_GEOMETRY},
341 {512, DEFAULT_DRIVE_SECTORS, 3*512,
342 9*512, GPT_SUCCESS},
343 {512, DEFAULT_DRIVE_SECTORS, 8*512,
344 6*512, GPT_ERROR_INVALID_FLASH_GEOMETRY},
345 {512, DEFAULT_DRIVE_SECTORS, 256,
346 6*512, GPT_ERROR_INVALID_FLASH_GEOMETRY},
347 {512, DEFAULT_DRIVE_SECTORS, 512,
348 6*512 + 256, GPT_ERROR_INVALID_FLASH_GEOMETRY},
349 };
Randall Spanglere9213a72013-01-24 11:19:55 -0800350 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700351
Randall Spanglere9213a72013-01-24 11:19:55 -0800352 gpt = GetEmptyGptData();
353 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
354 BuildTestGptData(gpt);
355 gpt->sector_bytes = cases[i].sector_bytes;
356 gpt->drive_sectors = cases[i].drive_sectors;
357 EXPECT(cases[i].expected_retval == CheckParameters(gpt));
358 }
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700359
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700360 mtd = GetEmptyMtdData();
361 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
362 BuildTestMtdData(mtd);
363 mtd->sector_bytes = mtdcases[i].sector_bytes;
364 mtd->drive_sectors = mtdcases[i].drive_sectors;
365 mtd->flash_block_bytes = mtdcases[i].flash_block_bytes;
366 mtd->flash_page_bytes = mtdcases[i].flash_page_bytes;
367 if(mtdcases[i].expected_retval != MtdCheckParameters(mtd)) {
368 printf("i=%d\n",i);
369 }
370 EXPECT(mtdcases[i].expected_retval == MtdCheckParameters(mtd));
371 }
372
Randall Spanglere9213a72013-01-24 11:19:55 -0800373 return TEST_OK;
Louis Yung-Chieh Lo37f6b552010-04-22 21:22:22 -0700374}
375
Randall Spanglere9213a72013-01-24 11:19:55 -0800376/* Test if header CRC in two copies are calculated. */
377static int HeaderCrcTest(void)
378{
379 GptData *gpt = GetEmptyGptData();
380 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700381
Randall Spanglere9213a72013-01-24 11:19:55 -0800382 BuildTestGptData(gpt);
383 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700384
Randall Spanglere9213a72013-01-24 11:19:55 -0800385 /* CRC covers first byte of header */
386 BuildTestGptData(gpt);
387 gpt->primary_header[0] ^= 0xa5;
388 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700389
Randall Spanglere9213a72013-01-24 11:19:55 -0800390 /* CRC covers last byte of header */
391 BuildTestGptData(gpt);
392 gpt->primary_header[h1->size - 1] ^= 0x5a;
393 EXPECT(HeaderCrc(h1) != h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700394
Randall Spanglere9213a72013-01-24 11:19:55 -0800395 /* CRC only covers header */
396 BuildTestGptData(gpt);
397 gpt->primary_header[h1->size] ^= 0x5a;
398 EXPECT(HeaderCrc(h1) == h1->header_crc32);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700399
Randall Spanglere9213a72013-01-24 11:19:55 -0800400 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700401}
402
Randall Spangler0bda13f2013-01-24 12:25:26 -0800403/* Test if header-same comparison works. */
404static int HeaderSameTest(void)
405{
406 GptData *gpt = GetEmptyGptData();
407 GptHeader *h1 = (GptHeader *)gpt->primary_header;
408 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
409 GptHeader h3;
410
411 EXPECT(0 == HeaderFieldsSame(h1, h2));
412
413 Memcpy(&h3, h2, sizeof(h3));
414 h3.signature[0] ^= 0xba;
415 EXPECT(1 == HeaderFieldsSame(h1, &h3));
416
417 Memcpy(&h3, h2, sizeof(h3));
418 h3.revision++;
419 EXPECT(1 == HeaderFieldsSame(h1, &h3));
420
421 Memcpy(&h3, h2, sizeof(h3));
422 h3.size++;
423 EXPECT(1 == HeaderFieldsSame(h1, &h3));
424
425 Memcpy(&h3, h2, sizeof(h3));
426 h3.reserved_zero++;
427 EXPECT(1 == HeaderFieldsSame(h1, &h3));
428
429 Memcpy(&h3, h2, sizeof(h3));
430 h3.first_usable_lba++;
431 EXPECT(1 == HeaderFieldsSame(h1, &h3));
432
433 Memcpy(&h3, h2, sizeof(h3));
434 h3.last_usable_lba++;
435 EXPECT(1 == HeaderFieldsSame(h1, &h3));
436
437 Memcpy(&h3, h2, sizeof(h3));
438 h3.disk_uuid.u.raw[0] ^= 0xba;
439 EXPECT(1 == HeaderFieldsSame(h1, &h3));
440
441 Memcpy(&h3, h2, sizeof(h3));
442 h3.number_of_entries++;
443 EXPECT(1 == HeaderFieldsSame(h1, &h3));
444
445 Memcpy(&h3, h2, sizeof(h3));
446 h3.size_of_entry++;
447 EXPECT(1 == HeaderFieldsSame(h1, &h3));
448
449 Memcpy(&h3, h2, sizeof(h3));
450 h3.entries_crc32++;
451 EXPECT(1 == HeaderFieldsSame(h1, &h3));
452
453 return TEST_OK;
454}
455
Randall Spanglere9213a72013-01-24 11:19:55 -0800456/* Test if signature ("EFI PART") is checked. */
457static int SignatureTest(void)
458{
459 GptData *gpt = GetEmptyGptData();
460 GptHeader *h1 = (GptHeader *)gpt->primary_header;
461 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
462 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700463
Randall Spangler0bda13f2013-01-24 12:25:26 -0800464 EXPECT(1 == CheckHeader(NULL, 0, gpt->drive_sectors));
465
Randall Spanglere9213a72013-01-24 11:19:55 -0800466 for (i = 0; i < 8; ++i) {
467 BuildTestGptData(gpt);
468 h1->signature[i] ^= 0xff;
469 h2->signature[i] ^= 0xff;
470 RefreshCrc32(gpt);
471 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
472 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
473 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700474
Randall Spanglere9213a72013-01-24 11:19:55 -0800475 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700476}
477
Randall Spanglere9213a72013-01-24 11:19:55 -0800478/*
479 * The revision we currently support is GPT_HEADER_REVISION. If the revision
480 * in header is not that, we expect the header is invalid.
481 */
482static int RevisionTest(void)
483{
484 GptData *gpt = GetEmptyGptData();
485 GptHeader *h1 = (GptHeader *)gpt->primary_header;
486 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
487 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700488
Randall Spanglere9213a72013-01-24 11:19:55 -0800489 struct {
490 uint32_t value_to_test;
491 int expect_rv;
492 } cases[] = {
493 {0x01000000, 1},
494 {0x00010000, 0}, /* GPT_HEADER_REVISION */
495 {0x00000100, 1},
496 {0x00000001, 1},
497 {0x23010456, 1},
498 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700499
Randall Spanglere9213a72013-01-24 11:19:55 -0800500 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
501 BuildTestGptData(gpt);
502 h1->revision = cases[i].value_to_test;
503 h2->revision = cases[i].value_to_test;
504 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700505
Randall Spanglere9213a72013-01-24 11:19:55 -0800506 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) ==
507 cases[i].expect_rv);
508 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) ==
509 cases[i].expect_rv);
510 }
511 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700512}
513
Randall Spanglere9213a72013-01-24 11:19:55 -0800514static int SizeTest(void)
515{
516 GptData *gpt = GetEmptyGptData();
517 GptHeader *h1 = (GptHeader *)gpt->primary_header;
518 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
519 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700520
Randall Spanglere9213a72013-01-24 11:19:55 -0800521 struct {
522 uint32_t value_to_test;
523 int expect_rv;
524 } cases[] = {
525 {91, 1},
526 {92, 0},
527 {93, 0},
528 {511, 0},
529 {512, 0},
530 {513, 1},
531 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700532
Randall Spanglere9213a72013-01-24 11:19:55 -0800533 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
534 BuildTestGptData(gpt);
535 h1->size = cases[i].value_to_test;
536 h2->size = cases[i].value_to_test;
537 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700538
Randall Spanglere9213a72013-01-24 11:19:55 -0800539 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) ==
540 cases[i].expect_rv);
541 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) ==
542 cases[i].expect_rv);
543 }
544 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700545}
546
Randall Spanglere9213a72013-01-24 11:19:55 -0800547/* Test if CRC is checked. */
548static int CrcFieldTest(void)
549{
550 GptData *gpt = GetEmptyGptData();
551 GptHeader *h1 = (GptHeader *)gpt->primary_header;
552 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700553
Randall Spanglere9213a72013-01-24 11:19:55 -0800554 BuildTestGptData(gpt);
555 /* Modify a field that the header verification doesn't care about */
556 h1->entries_crc32++;
557 h2->entries_crc32++;
558 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
559 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
560 /* Refresh the CRC; should pass now */
561 RefreshCrc32(gpt);
562 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
563 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700564
Randall Spanglere9213a72013-01-24 11:19:55 -0800565 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700566}
567
Randall Spanglere9213a72013-01-24 11:19:55 -0800568/* Test if reserved fields are checked. We'll try non-zero values to test. */
569static int ReservedFieldsTest(void)
570{
571 GptData *gpt = GetEmptyGptData();
572 GptHeader *h1 = (GptHeader *)gpt->primary_header;
573 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700574
Randall Spanglere9213a72013-01-24 11:19:55 -0800575 BuildTestGptData(gpt);
576 h1->reserved_zero ^= 0x12345678; /* whatever random */
577 h2->reserved_zero ^= 0x12345678; /* whatever random */
578 RefreshCrc32(gpt);
579 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
580 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700581
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700582#ifdef PADDING_CHECKED
Randall Spanglere9213a72013-01-24 11:19:55 -0800583 /* TODO: padding check is currently disabled */
584 BuildTestGptData(gpt);
585 h1->padding[12] ^= 0x34; /* whatever random */
586 h2->padding[56] ^= 0x78; /* whatever random */
587 RefreshCrc32(gpt);
588 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
589 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700590#endif
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700591
Randall Spanglere9213a72013-01-24 11:19:55 -0800592 return TEST_OK;
593}
594
595/*
596 * Technically, any size which is 2^N where N > 6 should work, but our
597 * library only supports one size.
598 */
599static int SizeOfPartitionEntryTest(void) {
600 GptData *gpt = GetEmptyGptData();
601 GptHeader *h1 = (GptHeader *)gpt->primary_header;
602 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
603 int i;
604
605 struct {
606 uint32_t value_to_test;
607 int expect_rv;
608 } cases[] = {
609 {127, 1},
610 {128, 0},
611 {129, 1},
612 {256, 1},
613 {512, 1},
614 };
615
616 /* Check size of entryes */
617 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
618 BuildTestGptData(gpt);
619 h1->size_of_entry = cases[i].value_to_test;
620 h2->size_of_entry = cases[i].value_to_test;
621 h1->number_of_entries = TOTAL_ENTRIES_SIZE /
622 cases[i].value_to_test;
623 h2->number_of_entries = TOTAL_ENTRIES_SIZE /
624 cases[i].value_to_test;
625 RefreshCrc32(gpt);
626
627 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) ==
628 cases[i].expect_rv);
629 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) ==
630 cases[i].expect_rv);
631 }
632
633 return TEST_OK;
634}
635
636/*
637 * Technically, any size which is 2^N where N > 6 should work, but our library
638 * only supports one size.
639 */
640static int NumberOfPartitionEntriesTest(void)
641{
642 GptData *gpt = GetEmptyGptData();
643 GptHeader *h1 = (GptHeader *)gpt->primary_header;
644 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
645
646 BuildTestGptData(gpt);
647 h1->number_of_entries--;
648 h2->number_of_entries /= 2;
649 RefreshCrc32(gpt);
650 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
651 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
652
653 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700654}
655
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700656
Randall Spanglere9213a72013-01-24 11:19:55 -0800657/* Test if myLBA field is checked (1 for primary, last for secondary). */
658static int MyLbaTest(void)
659{
660 GptData *gpt = GetEmptyGptData();
661 GptHeader *h1 = (GptHeader *)gpt->primary_header;
662 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700663
Randall Spanglere9213a72013-01-24 11:19:55 -0800664 /* myLBA depends on primary vs secondary flag */
665 BuildTestGptData(gpt);
666 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors));
667 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700668
Randall Spanglere9213a72013-01-24 11:19:55 -0800669 BuildTestGptData(gpt);
670 h1->my_lba--;
671 h2->my_lba--;
672 RefreshCrc32(gpt);
673 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
674 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700675
Randall Spanglere9213a72013-01-24 11:19:55 -0800676 BuildTestGptData(gpt);
677 h1->my_lba = 2;
678 h2->my_lba--;
679 RefreshCrc32(gpt);
680 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
681 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700682
Randall Spanglere9213a72013-01-24 11:19:55 -0800683 /* We should ignore the alternate_lba field entirely */
684 BuildTestGptData(gpt);
685 h1->alternate_lba++;
686 h2->alternate_lba++;
687 RefreshCrc32(gpt);
688 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
689 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
690
691 BuildTestGptData(gpt);
692 h1->alternate_lba--;
693 h2->alternate_lba--;
694 RefreshCrc32(gpt);
695 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
696 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors));
697
698 BuildTestGptData(gpt);
699 h1->entries_lba++;
700 h2->entries_lba++;
701 RefreshCrc32(gpt);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700702 /*
703 * We support a padding between primary GPT header and its entries. So
704 * this still passes.
705 */
706 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors));
707 /*
708 * But the secondary table should fail because it would overlap the
709 * header, which is now lying after its entry array.
710 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800711 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
712
713 BuildTestGptData(gpt);
714 h1->entries_lba--;
715 h2->entries_lba--;
716 RefreshCrc32(gpt);
717 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors));
718 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors));
719
720 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700721}
722
Randall Spanglere9213a72013-01-24 11:19:55 -0800723/* Test if FirstUsableLBA and LastUsableLBA are checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700724 * FirstUsableLBA must be after the end of the primary GPT table array.
725 * LastUsableLBA must be before the start of the secondary GPT table array.
726 * FirstUsableLBA <= LastUsableLBA. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800727static int FirstUsableLbaAndLastUsableLbaTest(void)
728{
729 GptData *gpt = GetEmptyGptData();
730 GptHeader *h1 = (GptHeader *)gpt->primary_header;
731 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
732 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700733
Randall Spanglere9213a72013-01-24 11:19:55 -0800734 struct {
735 uint64_t primary_entries_lba;
736 uint64_t primary_first_usable_lba;
737 uint64_t primary_last_usable_lba;
738 uint64_t secondary_first_usable_lba;
739 uint64_t secondary_last_usable_lba;
740 uint64_t secondary_entries_lba;
741 int primary_rv;
742 int secondary_rv;
743 } cases[] = {
744 {2, 34, 433, 34, 433, 434, 0, 0},
745 {2, 34, 432, 34, 430, 434, 0, 0},
746 {2, 33, 433, 33, 433, 434, 1, 1},
747 {2, 34, 434, 34, 433, 434, 1, 0},
748 {2, 34, 433, 34, 434, 434, 0, 1},
749 {2, 35, 433, 35, 433, 434, 0, 0},
750 {2, 433, 433, 433, 433, 434, 0, 0},
751 {2, 434, 433, 434, 434, 434, 1, 1},
752 {2, 433, 34, 34, 433, 434, 1, 0},
753 {2, 34, 433, 433, 34, 434, 0, 1},
754 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700755
Randall Spanglere9213a72013-01-24 11:19:55 -0800756 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
757 BuildTestGptData(gpt);
758 h1->entries_lba = cases[i].primary_entries_lba;
759 h1->first_usable_lba = cases[i].primary_first_usable_lba;
760 h1->last_usable_lba = cases[i].primary_last_usable_lba;
761 h2->entries_lba = cases[i].secondary_entries_lba;
762 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
763 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
764 RefreshCrc32(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700765
Randall Spanglere9213a72013-01-24 11:19:55 -0800766 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors) ==
767 cases[i].primary_rv);
768 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors) ==
769 cases[i].secondary_rv);
770 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700771
Randall Spanglere9213a72013-01-24 11:19:55 -0800772 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700773}
774
Randall Spanglere9213a72013-01-24 11:19:55 -0800775/*
776 * Test if PartitionEntryArrayCRC32 is checked. PartitionEntryArrayCRC32 must
777 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700778 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800779static int EntriesCrcTest(void)
780{
781 GptData *gpt = GetEmptyGptData();
782 GptHeader *h1 = (GptHeader *)gpt->primary_header;
783 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
784 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700785
Randall Spanglere9213a72013-01-24 11:19:55 -0800786 /* Modify first byte of primary entries, and expect the CRC is wrong. */
787 BuildTestGptData(gpt);
788 EXPECT(0 == CheckEntries(e1, h1));
789 EXPECT(0 == CheckEntries(e2, h1));
790 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
791 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
792 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
793 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700794
Randall Spanglere9213a72013-01-24 11:19:55 -0800795 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700796}
797
Randall Spanglere9213a72013-01-24 11:19:55 -0800798/*
799 * Test if partition geometry is checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700800 * All active (non-zero PartitionTypeGUID) partition entries should have:
801 * entry.StartingLBA >= header.FirstUsableLBA
802 * entry.EndingLBA <= header.LastUsableLBA
803 * entry.StartingLBA <= entry.EndingLBA
804 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800805static int ValidEntryTest(void)
806{
807 GptData *gpt = GetEmptyGptData();
808 GptHeader *h1 = (GptHeader *)gpt->primary_header;
809 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700810 MtdData *mtd = GetEmptyMtdData();
811 MtdDiskLayout *mh = &mtd->primary;
812 MtdDiskPartition *me = mh->partitions;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700813
Randall Spanglere9213a72013-01-24 11:19:55 -0800814 /* error case: entry.StartingLBA < header.FirstUsableLBA */
815 BuildTestGptData(gpt);
816 e1[0].starting_lba = h1->first_usable_lba - 1;
817 RefreshCrc32(gpt);
818 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700819
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700820 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700821 if (mh->first_offset > 0) {
822 me[0].starting_offset = mh->first_offset - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700823 mh->crc32 = MtdHeaderCrc(mh);
824 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
825 }
826
Randall Spanglere9213a72013-01-24 11:19:55 -0800827 /* error case: entry.EndingLBA > header.LastUsableLBA */
828 BuildTestGptData(gpt);
829 e1[2].ending_lba = h1->last_usable_lba + 1;
830 RefreshCrc32(gpt);
831 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700832
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700833 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700834 me[0].ending_offset = mh->last_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700835 mh->crc32 = MtdHeaderCrc(mh);
836 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
837
Randall Spanglere9213a72013-01-24 11:19:55 -0800838 /* error case: entry.StartingLBA > entry.EndingLBA */
839 BuildTestGptData(gpt);
840 e1[3].starting_lba = e1[3].ending_lba + 1;
841 RefreshCrc32(gpt);
842 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700843
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700844 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700845 me[0].starting_offset = me[0].ending_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700846 mh->crc32 = MtdHeaderCrc(mh);
847 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
848
Randall Spanglere9213a72013-01-24 11:19:55 -0800849 /* case: non active entry should be ignored. */
850 BuildTestGptData(gpt);
851 Memset(&e1[1].type, 0, sizeof(e1[1].type));
852 e1[1].starting_lba = e1[1].ending_lba + 1;
853 RefreshCrc32(gpt);
854 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700855
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700856 BuildTestMtdData(mtd);
857 me[0].flags = 0;
Albert Chaulk289b6042013-06-25 11:30:46 -0700858 me[0].starting_offset = me[0].ending_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700859 mh->crc32 = MtdHeaderCrc(mh);
860 EXPECT(GPT_SUCCESS == MtdCheckEntries(me, mh));
861
Randall Spanglere9213a72013-01-24 11:19:55 -0800862 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700863}
864
Randall Spanglere9213a72013-01-24 11:19:55 -0800865/* Test if overlapped partition tables can be detected. */
866static int OverlappedPartitionTest(void) {
867 GptData *gpt = GetEmptyGptData();
868 GptHeader *h = (GptHeader *)gpt->primary_header;
869 GptEntry *e = (GptEntry *)gpt->primary_entries;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700870 MtdData *mtd = GetEmptyMtdData();
871 MtdDiskLayout *mh = &mtd->primary;
872 MtdDiskPartition *me = mh->partitions;
Randall Spanglere9213a72013-01-24 11:19:55 -0800873 int i, j;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700874
Randall Spanglere9213a72013-01-24 11:19:55 -0800875 struct {
876 int overlapped;
877 struct {
878 int active;
879 uint64_t starting_lba;
880 uint64_t ending_lba;
881 } entries[16]; /* enough for testing. */
882 } cases[] = {
883 {GPT_SUCCESS, {{0, 100, 199}}},
884 {GPT_SUCCESS, {{1, 100, 199}}},
885 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
886 {GPT_ERROR_START_LBA_OVERLAP,
887 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
888 {GPT_ERROR_END_LBA_OVERLAP,
889 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
890 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
891 {GPT_ERROR_END_LBA_OVERLAP,
892 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
893 {GPT_ERROR_START_LBA_OVERLAP,
894 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
895 {GPT_ERROR_START_LBA_OVERLAP,
896 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
897 {GPT_ERROR_END_LBA_OVERLAP,
898 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
899 {GPT_ERROR_START_LBA_OVERLAP,
900 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
901 {GPT_SUCCESS,
902 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
903 {GPT_ERROR_START_LBA_OVERLAP,
904 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
905 {GPT_ERROR_START_LBA_OVERLAP,
906 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
907 {GPT_SUCCESS,
908 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
909 {GPT_ERROR_END_LBA_OVERLAP,
910 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
911 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
912 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
913 {GPT_ERROR_START_LBA_OVERLAP,
914 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
915 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
916 {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
917 {GPT_SUCCESS,
918 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
919 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
920 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
921 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700922
Randall Spanglere9213a72013-01-24 11:19:55 -0800923 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
924 BuildTestGptData(gpt);
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700925 BuildTestMtdData(mtd);
926 Memset(mh->partitions, 0, sizeof(mh->partitions));
Randall Spanglere9213a72013-01-24 11:19:55 -0800927 ZeroEntries(gpt);
928 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
929 if (!cases[i].entries[j].starting_lba)
930 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700931
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700932 if (cases[i].entries[j].active) {
Randall Spanglere9213a72013-01-24 11:19:55 -0800933 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700934 me[j].flags =
935 MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
936 }
Randall Spanglere9213a72013-01-24 11:19:55 -0800937 SetGuid(&e[j].unique, j);
938 e[j].starting_lba = cases[i].entries[j].starting_lba;
939 e[j].ending_lba = cases[i].entries[j].ending_lba;
Albert Chaulk289b6042013-06-25 11:30:46 -0700940 me[j].starting_offset = cases[i].entries[j].starting_lba *
941 DEFAULT_SECTOR_SIZE;
942 me[j].ending_offset = cases[i].entries[j].ending_lba *
943 DEFAULT_SECTOR_SIZE;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700944
Randall Spanglere9213a72013-01-24 11:19:55 -0800945 }
946 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700947
Randall Spanglere9213a72013-01-24 11:19:55 -0800948 EXPECT(cases[i].overlapped == CheckEntries(e, h));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700949 EXPECT(cases[i].overlapped == MtdCheckEntries(me, mh));
Randall Spanglere9213a72013-01-24 11:19:55 -0800950 }
951 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700952}
953
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700954/* Test both sanity checking and repair. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800955static int SanityCheckTest(void)
956{
957 GptData *gpt = GetEmptyGptData();
958 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler0bda13f2013-01-24 12:25:26 -0800959 GptEntry *e1 = (GptEntry *)gpt->primary_entries;
960 uint8_t *tempptr;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700961
Randall Spanglere9213a72013-01-24 11:19:55 -0800962 /* Unmodified test data is completely sane */
963 BuildTestGptData(gpt);
964 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
965 EXPECT(MASK_BOTH == gpt->valid_headers);
966 EXPECT(MASK_BOTH == gpt->valid_entries);
967 /* Repair doesn't damage it */
968 GptRepair(gpt);
969 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
970 EXPECT(MASK_BOTH == gpt->valid_headers);
971 EXPECT(MASK_BOTH == gpt->valid_entries);
972 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700973
Randall Spangler0bda13f2013-01-24 12:25:26 -0800974 /* Invalid sector size should fail */
975 BuildTestGptData(gpt);
976 gpt->sector_bytes = 1024;
977 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
978
Randall Spanglere9213a72013-01-24 11:19:55 -0800979 /* Modify headers */
980 BuildTestGptData(gpt);
981 gpt->primary_header[0]++;
982 gpt->secondary_header[0]++;
983 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
984 EXPECT(0 == gpt->valid_headers);
985 EXPECT(0 == gpt->valid_entries);
986 /* Repair can't fix completely busted headers */
987 GptRepair(gpt);
988 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
989 EXPECT(0 == gpt->valid_headers);
990 EXPECT(0 == gpt->valid_entries);
991 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700992
Randall Spanglere9213a72013-01-24 11:19:55 -0800993 BuildTestGptData(gpt);
994 gpt->primary_header[0]++;
995 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
996 EXPECT(MASK_SECONDARY == gpt->valid_headers);
997 EXPECT(MASK_BOTH == gpt->valid_entries);
998 GptRepair(gpt);
999 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1000 EXPECT(MASK_BOTH == gpt->valid_headers);
1001 EXPECT(MASK_BOTH == gpt->valid_entries);
1002 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001003
Randall Spanglere9213a72013-01-24 11:19:55 -08001004 BuildTestGptData(gpt);
1005 gpt->secondary_header[0]++;
1006 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1007 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1008 EXPECT(MASK_BOTH == gpt->valid_entries);
1009 GptRepair(gpt);
1010 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1011 EXPECT(MASK_BOTH == gpt->valid_headers);
1012 EXPECT(MASK_BOTH == gpt->valid_entries);
1013 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001014
Randall Spanglere9213a72013-01-24 11:19:55 -08001015 /*
1016 * Modify header1 and update its CRC. Since header2 is now different
1017 * than header1, it'll be the one considered invalid.
1018 */
1019 BuildTestGptData(gpt);
1020 h1->size++;
1021 RefreshCrc32(gpt);
1022 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1023 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1024 EXPECT(MASK_BOTH == gpt->valid_entries);
1025 GptRepair(gpt);
1026 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1027 EXPECT(MASK_BOTH == gpt->valid_headers);
1028 EXPECT(MASK_BOTH == gpt->valid_entries);
1029 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001030
Randall Spanglere9213a72013-01-24 11:19:55 -08001031 /* Modify entries */
1032 BuildTestGptData(gpt);
1033 gpt->primary_entries[0]++;
1034 gpt->secondary_entries[0]++;
1035 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
1036 EXPECT(MASK_BOTH == gpt->valid_headers);
1037 EXPECT(MASK_NONE == gpt->valid_entries);
1038 /* Repair can't fix both copies of entries being bad, either. */
1039 GptRepair(gpt);
1040 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
1041 EXPECT(MASK_BOTH == gpt->valid_headers);
1042 EXPECT(MASK_NONE == gpt->valid_entries);
1043 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001044
Randall Spanglere9213a72013-01-24 11:19:55 -08001045 BuildTestGptData(gpt);
1046 gpt->primary_entries[0]++;
1047 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1048 EXPECT(MASK_BOTH == gpt->valid_headers);
1049 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1050 GptRepair(gpt);
1051 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1052 EXPECT(MASK_BOTH == gpt->valid_headers);
1053 EXPECT(MASK_BOTH == gpt->valid_entries);
1054 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001055
Randall Spanglere9213a72013-01-24 11:19:55 -08001056 BuildTestGptData(gpt);
1057 gpt->secondary_entries[0]++;
1058 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1059 EXPECT(MASK_BOTH == gpt->valid_headers);
1060 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1061 GptRepair(gpt);
1062 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1063 EXPECT(MASK_BOTH == gpt->valid_headers);
1064 EXPECT(MASK_BOTH == gpt->valid_entries);
1065 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001066
Randall Spangler0bda13f2013-01-24 12:25:26 -08001067 /*
1068 * Modify entries and recompute CRCs, then make both primary and
1069 * secondary entry pointers use the secondary data. The primary
1070 * header will have the wrong entries CRC, so we should fall back
1071 * to the secondary header.
1072 */
1073 BuildTestGptData(gpt);
1074 e1->starting_lba++;
1075 RefreshCrc32(gpt);
1076 tempptr = gpt->primary_entries;
1077 gpt->primary_entries = gpt->secondary_entries;
1078 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1079 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1080 EXPECT(MASK_BOTH == gpt->valid_entries);
1081 gpt->primary_entries = tempptr;
1082
Randall Spanglere9213a72013-01-24 11:19:55 -08001083 /* Modify both header and entries */
1084 BuildTestGptData(gpt);
1085 gpt->primary_header[0]++;
1086 gpt->primary_entries[0]++;
1087 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1088 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1089 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1090 GptRepair(gpt);
1091 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1092 EXPECT(MASK_BOTH == gpt->valid_headers);
1093 EXPECT(MASK_BOTH == gpt->valid_entries);
1094 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001095
Randall Spanglere9213a72013-01-24 11:19:55 -08001096 BuildTestGptData(gpt);
1097 gpt->secondary_header[0]++;
1098 gpt->secondary_entries[0]++;
1099 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1100 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1101 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1102 GptRepair(gpt);
1103 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1104 EXPECT(MASK_BOTH == gpt->valid_headers);
1105 EXPECT(MASK_BOTH == gpt->valid_entries);
1106 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001107
Randall Spanglere9213a72013-01-24 11:19:55 -08001108 /* Test cross-correction (h1+e2, h2+e1) */
1109 BuildTestGptData(gpt);
1110 gpt->primary_header[0]++;
1111 gpt->secondary_entries[0]++;
1112 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1113 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1114 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1115 GptRepair(gpt);
1116 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1117 EXPECT(MASK_BOTH == gpt->valid_headers);
1118 EXPECT(MASK_BOTH == gpt->valid_entries);
1119 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001120
Randall Spanglere9213a72013-01-24 11:19:55 -08001121 BuildTestGptData(gpt);
1122 gpt->secondary_header[0]++;
1123 gpt->primary_entries[0]++;
1124 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1125 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1126 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1127 GptRepair(gpt);
1128 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1129 EXPECT(MASK_BOTH == gpt->valid_headers);
1130 EXPECT(MASK_BOTH == gpt->valid_entries);
1131 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001132
Randall Spanglere9213a72013-01-24 11:19:55 -08001133 /*
1134 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
1135 * simulates a partial update of the drive.
1136 */
1137 BuildTestGptData(gpt);
1138 gpt->secondary_entries[0]++;
1139 RefreshCrc32(gpt);
1140 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1141 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1142 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1143 GptRepair(gpt);
1144 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1145 EXPECT(MASK_BOTH == gpt->valid_headers);
1146 EXPECT(MASK_BOTH == gpt->valid_entries);
1147 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001148
Nam T. Nguyen5ce83252014-10-30 15:09:43 -07001149 /* Test unloaded entry array. */
1150 gpt = GetEmptyGptData();
1151 BuildTestGptData(gpt);
1152 gpt->primary_entries = NULL;
1153 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1154 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1155 gpt = GetEmptyGptData();
1156 BuildTestGptData(gpt);
1157 gpt->secondary_entries = NULL;
1158 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1159 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1160
1161 /* Test unloaded header. */
1162 gpt = GetEmptyGptData();
1163 BuildTestGptData(gpt);
1164 gpt->primary_header = NULL;
1165 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1166 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1167 gpt = GetEmptyGptData();
1168 BuildTestGptData(gpt);
1169 gpt->secondary_header = NULL;
1170 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1171 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1172
Randall Spanglere9213a72013-01-24 11:19:55 -08001173 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001174}
1175
Randall Spanglere9213a72013-01-24 11:19:55 -08001176static int EntryAttributeGetSetTest(void)
1177{
1178 GptData *gpt = GetEmptyGptData();
1179 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001180 MtdData *mtd = GetEmptyMtdData();
1181 MtdDiskPartition *m = &mtd->primary.partitions[0];
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001182
Randall Spanglere9213a72013-01-24 11:19:55 -08001183 e->attrs.whole = 0x0000000000000000ULL;
1184 SetEntrySuccessful(e, 1);
1185 EXPECT(0x0100000000000000ULL == e->attrs.whole);
1186 EXPECT(1 == GetEntrySuccessful(e));
1187 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1188 SetEntrySuccessful(e, 0);
1189 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1190 EXPECT(0 == GetEntrySuccessful(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001191
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001192 m->flags = 0;
1193 MtdSetEntrySuccessful(m, 1);
1194 EXPECT(0x00000100 == m->flags);
1195 EXPECT(1 == MtdGetEntrySuccessful(m));
1196 m->flags = ~0;
1197 MtdSetEntrySuccessful(m, 0);
1198 EXPECT(0xFFFFFEFF == m->flags);
1199 EXPECT(0 == MtdGetEntrySuccessful(m));
1200
Randall Spanglere9213a72013-01-24 11:19:55 -08001201 e->attrs.whole = 0x0000000000000000ULL;
1202 SetEntryTries(e, 15);
1203 EXPECT(15 == GetEntryTries(e));
1204 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1205 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1206 SetEntryTries(e, 0);
1207 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1208 EXPECT(0 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001209
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001210 m->flags = 0;
1211 MtdSetEntryTries(m, 15);
1212 EXPECT(0x000000F0 == m->flags);
1213 EXPECT(15 == MtdGetEntryTries(m));
1214 m->flags = ~0;
1215 MtdSetEntryTries(m, 0);
1216 EXPECT(0xFFFFFF0F == m->flags);
1217 EXPECT(0 == MtdGetEntryTries(m));
1218
Randall Spanglere9213a72013-01-24 11:19:55 -08001219 e->attrs.whole = 0x0000000000000000ULL;
1220 SetEntryPriority(e, 15);
1221 EXPECT(0x000F000000000000ULL == e->attrs.whole);
1222 EXPECT(15 == GetEntryPriority(e));
1223 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1224 SetEntryPriority(e, 0);
1225 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1226 EXPECT(0 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001227
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001228 m->flags = 0;
1229 MtdSetEntryPriority(m, 15);
1230 EXPECT(0x0000000F == m->flags);
1231 EXPECT(15 == MtdGetEntryPriority(m));
1232 m->flags = ~0;
1233 MtdSetEntryPriority(m, 0);
1234 EXPECT(0xFFFFFFF0 == m->flags);
1235 EXPECT(0 == MtdGetEntryPriority(m));
1236
Randall Spanglere9213a72013-01-24 11:19:55 -08001237 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1238 EXPECT(1 == GetEntrySuccessful(e));
1239 EXPECT(15 == GetEntryPriority(e));
1240 EXPECT(15 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001241
Randall Spanglere9213a72013-01-24 11:19:55 -08001242 e->attrs.whole = 0x0123000000000000ULL;
1243 EXPECT(1 == GetEntrySuccessful(e));
1244 EXPECT(2 == GetEntryTries(e));
1245 EXPECT(3 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001246
Randall Spanglere9213a72013-01-24 11:19:55 -08001247 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001248}
1249
Randall Spanglere9213a72013-01-24 11:19:55 -08001250static int EntryTypeTest(void)
1251{
1252 GptData *gpt = GetEmptyGptData();
1253 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001254
Randall Spanglere9213a72013-01-24 11:19:55 -08001255 Memcpy(&e->type, &guid_zero, sizeof(Guid));
1256 EXPECT(1 == IsUnusedEntry(e));
1257 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001258
Randall Spanglere9213a72013-01-24 11:19:55 -08001259 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1260 EXPECT(0 == IsUnusedEntry(e));
1261 EXPECT(1 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001262
Randall Spanglere9213a72013-01-24 11:19:55 -08001263 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1264 EXPECT(0 == IsUnusedEntry(e));
1265 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001266
Randall Spanglere9213a72013-01-24 11:19:55 -08001267 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001268}
1269
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001270/* Make an entry unused by clearing its type. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001271static void FreeEntry(GptEntry *e)
1272{
1273 Memset(&e->type, 0, sizeof(Guid));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001274}
1275
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001276static void MtdFreeEntry(MtdDiskPartition *e)
1277{
1278 MtdSetEntryType(e, MTD_PARTITION_TYPE_UNUSED);
1279}
1280
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001281/* Set up an entry. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001282static void FillEntry(GptEntry *e, int is_kernel,
1283 int priority, int successful, int tries)
1284{
1285 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1286 SetEntryPriority(e, priority);
1287 SetEntrySuccessful(e, successful);
1288 SetEntryTries(e, tries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001289}
1290
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001291static void MtdFillEntry(MtdDiskPartition *e, int is_kernel,
1292 int priority, int successful, int tries)
1293{
1294 MtdSetEntryType(e, is_kernel ? MTD_PARTITION_TYPE_CHROMEOS_KERNEL :
1295 MTD_PARTITION_TYPE_CHROMEOS_FIRMWARE);
1296 MtdSetEntryPriority(e, priority);
1297 MtdSetEntrySuccessful(e, successful);
1298 MtdSetEntryTries(e, tries);
1299}
1300
Randall Spanglere9213a72013-01-24 11:19:55 -08001301/*
1302 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001303 * any usable kernel entry.
1304 */
Randall Spanglere9213a72013-01-24 11:19:55 -08001305static int NoValidKernelEntryTest(void)
1306{
1307 GptData *gpt = GetEmptyGptData();
1308 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001309
Randall Spanglere9213a72013-01-24 11:19:55 -08001310 BuildTestGptData(gpt);
1311 SetEntryPriority(e1 + KERNEL_A, 0);
1312 FreeEntry(e1 + KERNEL_B);
1313 RefreshCrc32(gpt);
1314 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1315 GptNextKernelEntry(gpt, NULL, NULL));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001316
Randall Spanglere9213a72013-01-24 11:19:55 -08001317 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001318}
1319
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001320static int MtdNoValidKernelEntryTest(void)
1321{
1322 MtdData *mtd = GetEmptyMtdData();
1323 MtdDiskPartition *e1 = mtd->primary.partitions;
1324
1325 BuildTestMtdData(mtd);
1326 MtdSetEntryPriority(e1 + KERNEL_A, 0);
1327 MtdFreeEntry(e1 + KERNEL_B);
1328 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1329 MtdNextKernelEntry(mtd, NULL, NULL));
1330
1331 return TEST_OK;
1332}
1333
Randall Spanglere9213a72013-01-24 11:19:55 -08001334static int GetNextNormalTest(void)
1335{
1336 GptData *gpt = GetEmptyGptData();
1337 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1338 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001339
Randall Spanglere9213a72013-01-24 11:19:55 -08001340 /* Normal case - both kernels successful */
1341 BuildTestGptData(gpt);
1342 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1343 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1344 RefreshCrc32(gpt);
1345 GptInit(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001346
Randall Spanglere9213a72013-01-24 11:19:55 -08001347 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1348 EXPECT(KERNEL_A == gpt->current_kernel);
1349 EXPECT(34 == start);
1350 EXPECT(100 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001351
Randall Spanglere9213a72013-01-24 11:19:55 -08001352 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1353 EXPECT(KERNEL_B == gpt->current_kernel);
1354 EXPECT(134 == start);
1355 EXPECT(99 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001356
Randall Spanglere9213a72013-01-24 11:19:55 -08001357 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1358 GptNextKernelEntry(gpt, &start, &size));
1359 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001360
Randall Spanglere9213a72013-01-24 11:19:55 -08001361 /* Call as many times as you want; you won't get another kernel... */
1362 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1363 GptNextKernelEntry(gpt, &start, &size));
1364 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001365
Randall Spanglere9213a72013-01-24 11:19:55 -08001366 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001367}
1368
Randall Spanglere9213a72013-01-24 11:19:55 -08001369static int GetNextPrioTest(void)
1370{
1371 GptData *gpt = GetEmptyGptData();
1372 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1373 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001374
Randall Spanglere9213a72013-01-24 11:19:55 -08001375 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1376 BuildTestGptData(gpt);
1377 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1378 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1379 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1380 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1381 RefreshCrc32(gpt);
1382 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001383
Randall Spanglere9213a72013-01-24 11:19:55 -08001384 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1385 EXPECT(KERNEL_B == gpt->current_kernel);
1386 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1387 EXPECT(KERNEL_Y == gpt->current_kernel);
1388 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1389 EXPECT(KERNEL_A == gpt->current_kernel);
1390 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1391 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001392
Randall Spanglere9213a72013-01-24 11:19:55 -08001393 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001394}
1395
Randall Spanglere9213a72013-01-24 11:19:55 -08001396static int GetNextTriesTest(void)
1397{
1398 GptData *gpt = GetEmptyGptData();
1399 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1400 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001401
Randall Spanglere9213a72013-01-24 11:19:55 -08001402 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1403 BuildTestGptData(gpt);
1404 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1405 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1406 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1407 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1408 RefreshCrc32(gpt);
1409 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001410
Randall Spanglere9213a72013-01-24 11:19:55 -08001411 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1412 EXPECT(KERNEL_X == gpt->current_kernel);
1413 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1414 EXPECT(KERNEL_A == gpt->current_kernel);
1415 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1416 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001417
Randall Spanglere9213a72013-01-24 11:19:55 -08001418 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001419}
1420
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001421static int MtdGetNextNormalTest(void)
1422{
1423 MtdData *mtd = GetEmptyMtdData();
1424 MtdDiskPartition *e1 = mtd->primary.partitions;
1425 uint64_t start, size;
1426
1427 /* Normal case - both kernels successful */
1428 BuildTestMtdData(mtd);
1429 MtdFillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1430 MtdFillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1431 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1432 MtdInit(mtd);
1433
1434 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1435 EXPECT(KERNEL_A == mtd->current_kernel);
1436 EXPECT(34 == start);
1437 EXPECT(100 == size);
1438
1439 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1440 EXPECT(KERNEL_B == mtd->current_kernel);
1441 EXPECT(134 == start);
1442 EXPECT(99 == size);
1443
1444 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1445 MtdNextKernelEntry(mtd, &start, &size));
1446 EXPECT(-1 == mtd->current_kernel);
1447
1448 /* Call as many times as you want; you won't get another kernel... */
1449 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1450 MtdNextKernelEntry(mtd, &start, &size));
1451 EXPECT(-1 == mtd->current_kernel);
1452
1453 return TEST_OK;
1454}
1455
1456static int MtdGetNextPrioTest(void)
1457{
1458 MtdData *mtd = GetEmptyMtdData();
1459 MtdDiskPartition *e1 = mtd->primary.partitions;
1460 uint64_t start, size;
1461
1462 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1463 BuildTestMtdData(mtd);
1464 MtdFillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1465 MtdFillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1466 MtdFillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1467 MtdFillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1468 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1469 MtdInit(mtd);
1470
1471 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1472 EXPECT(KERNEL_B == mtd->current_kernel);
1473 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1474 EXPECT(KERNEL_Y == mtd->current_kernel);
1475 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1476 EXPECT(KERNEL_A == mtd->current_kernel);
1477 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1478 MtdNextKernelEntry(mtd, &start, &size));
1479
1480 return TEST_OK;
1481}
1482
1483static int MtdGetNextTriesTest(void)
1484{
1485 MtdData *mtd = GetEmptyMtdData();
1486 MtdDiskPartition *e1 = mtd->primary.partitions;
1487 uint64_t start, size;
1488
1489 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1490 BuildTestMtdData(mtd);
1491 MtdFillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1492 MtdFillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1493 MtdFillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1494 MtdFillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1495 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1496 MtdInit(mtd);
1497
1498 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1499 EXPECT(KERNEL_X == mtd->current_kernel);
1500 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1501 EXPECT(KERNEL_A == mtd->current_kernel);
1502 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1503 MtdNextKernelEntry(mtd, &start, &size));
1504
1505 return TEST_OK;
1506}
1507
1508static int MtdUpdateTest() {
1509 MtdData *mtd = GetEmptyMtdData();
1510 MtdDiskPartition *e = &mtd->primary.partitions[0];
1511 uint64_t start, size;
1512
1513 BuildTestMtdData(mtd);
1514
1515 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1516 MtdFillEntry(e + KERNEL_A, 1, 4, 1, 0);
1517 MtdFillEntry(e + KERNEL_B, 1, 3, 0, 2);
1518 MtdFillEntry(e + KERNEL_X, 1, 2, 0, 2);
1519 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1520 mtd->modified = 0;
1521 EXPECT(GPT_SUCCESS == MtdInit(mtd));
1522
1523 /* Successful kernel */
1524 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1525 EXPECT(KERNEL_A == mtd->current_kernel);
1526 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1527 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1528 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1529 /* Trying successful kernel changes nothing */
1530 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1531 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1532 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1533 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1534 EXPECT(0 == mtd->modified);
1535 /* Marking it bad also does not update it. */
1536 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1537 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1538 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1539 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1540 EXPECT(0 == mtd->modified);
1541
1542 /* Kernel with tries */
1543 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1544 EXPECT(KERNEL_B == mtd->current_kernel);
1545 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_B));
1546 EXPECT(3 == MtdGetEntryPriority(e + KERNEL_B));
1547 EXPECT(2 == MtdGetEntryTries(e + KERNEL_B));
1548 /* Marking it bad clears it */
1549 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1550 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_B));
1551 EXPECT(0 == MtdGetEntryPriority(e + KERNEL_B));
1552 EXPECT(0 == MtdGetEntryTries(e + KERNEL_B));
1553 /* And that's caused the mtd to need updating */
1554 EXPECT(1 == mtd->modified);
1555
1556 /* Another kernel with tries */
1557 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1558 EXPECT(KERNEL_X == mtd->current_kernel);
1559 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1560 EXPECT(2 == MtdGetEntryPriority(e + KERNEL_X));
1561 EXPECT(2 == MtdGetEntryTries(e + KERNEL_X));
1562 /* Trying it uses up a try */
1563 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1564 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1565 EXPECT(2 == MtdGetEntryPriority(e + KERNEL_X));
1566 EXPECT(1 == MtdGetEntryTries(e + KERNEL_X));
1567 /* Trying it again marks it inactive */
1568 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1569 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1570 EXPECT(0 == MtdGetEntryPriority(e + KERNEL_X));
1571 EXPECT(0 == MtdGetEntryTries(e + KERNEL_X));
1572
1573 /* Can't update if entry isn't a kernel, or there isn't an entry */
1574 MtdSetEntryType(e + KERNEL_X, MTD_PARTITION_TYPE_UNUSED);
1575 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1576 MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1577 mtd->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1578 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1579 MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1580
1581 return TEST_OK;
1582}
1583
Randall Spanglere9213a72013-01-24 11:19:55 -08001584static int GptUpdateTest(void)
1585{
1586 GptData *gpt = GetEmptyGptData();
1587 GptEntry *e = (GptEntry *)(gpt->primary_entries);
1588 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1589 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001590
Randall Spanglere9213a72013-01-24 11:19:55 -08001591 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1592 BuildTestGptData(gpt);
1593 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1594 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1595 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1596 RefreshCrc32(gpt);
1597 GptInit(gpt);
1598 gpt->modified = 0; /* Nothing modified yet */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001599
Randall Spanglere9213a72013-01-24 11:19:55 -08001600 /* Successful kernel */
1601 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1602 EXPECT(KERNEL_A == gpt->current_kernel);
1603 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1604 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1605 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1606 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1607 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1608 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1609 /* Trying successful kernel changes nothing */
1610 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1611 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1612 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1613 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1614 EXPECT(0 == gpt->modified);
1615 /* Marking it bad also does not update it. */
1616 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1617 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1618 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1619 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1620 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001621
Randall Spanglere9213a72013-01-24 11:19:55 -08001622 /* Kernel with tries */
1623 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1624 EXPECT(KERNEL_B == gpt->current_kernel);
1625 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1626 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1627 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1628 /* Marking it bad clears it */
1629 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1630 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1631 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1632 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1633 /* Which affects both copies of the partition entries */
1634 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1635 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1636 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1637 /* And that's caused the GPT to need updating */
1638 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001639
Randall Spanglere9213a72013-01-24 11:19:55 -08001640 /* Another kernel with tries */
1641 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1642 EXPECT(KERNEL_X == gpt->current_kernel);
1643 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1644 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1645 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1646 /* Trying it uses up a try */
1647 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1648 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1649 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1650 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1651 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1652 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1653 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1654 /* Trying it again marks it inactive */
1655 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1656 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1657 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1658 EXPECT(0 == GetEntryTries(e + KERNEL_X));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001659
Randall Spangler0bda13f2013-01-24 12:25:26 -08001660 /* Can't update if entry isn't a kernel, or there isn't an entry */
1661 Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1662 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1663 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1664 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1665 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1666 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1667
1668
Randall Spanglere9213a72013-01-24 11:19:55 -08001669 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001670}
1671
Randall Spanglere9213a72013-01-24 11:19:55 -08001672/*
1673 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1674 * GPT_ERROR_INVALID_UPDATE_TYPE.
1675 */
1676static int UpdateInvalidKernelTypeTest(void)
1677{
1678 GptData *gpt = GetEmptyGptData();
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001679
Randall Spanglere9213a72013-01-24 11:19:55 -08001680 BuildTestGptData(gpt);
1681 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1682 gpt->current_kernel = 0;
1683 /* any invalid update_type value */
1684 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1685 GptUpdateKernelEntry(gpt, 99));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001686
Randall Spanglere9213a72013-01-24 11:19:55 -08001687 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001688}
1689
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001690static int MtdUpdateInvalidKernelTypeTest(void)
1691{
1692 MtdData *mtd = GetEmptyMtdData();
1693
1694 BuildTestMtdData(mtd);
1695 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1696 mtd->current_kernel = 0;
1697 /* any invalid update_type value */
1698 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1699 MtdUpdateKernelEntry(mtd, 99));
1700
1701 return TEST_OK;
1702}
1703
Randall Spanglere9213a72013-01-24 11:19:55 -08001704/* Test duplicate UniqueGuids can be detected. */
1705static int DuplicateUniqueGuidTest(void)
1706{
1707 GptData *gpt = GetEmptyGptData();
1708 GptHeader *h = (GptHeader *)gpt->primary_header;
1709 GptEntry *e = (GptEntry *)gpt->primary_entries;
1710 int i, j;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001711
Randall Spanglere9213a72013-01-24 11:19:55 -08001712 struct {
1713 int duplicate;
1714 struct {
1715 uint64_t starting_lba;
1716 uint64_t ending_lba;
1717 uint32_t type_guid;
1718 uint32_t unique_guid;
1719 } entries[16]; /* enough for testing. */
1720 } cases[] = {
1721 {GPT_SUCCESS, {{100, 109, 1, 1},
1722 {110, 119, 2, 2},
1723 {120, 129, 3, 3},
1724 {130, 139, 4, 4},
1725 }},
1726 {GPT_SUCCESS, {{100, 109, 1, 1},
1727 {110, 119, 1, 2},
1728 {120, 129, 2, 3},
1729 {130, 139, 2, 4},
1730 }},
1731 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1732 {110, 119, 2, 2},
1733 {120, 129, 3, 1},
1734 {130, 139, 4, 4},
1735 }},
1736 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1737 {110, 119, 1, 2},
1738 {120, 129, 2, 3},
1739 {130, 139, 2, 2},
1740 }},
1741 };
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001742
Randall Spanglere9213a72013-01-24 11:19:55 -08001743 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1744 BuildTestGptData(gpt);
1745 ZeroEntries(gpt);
1746 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1747 if (!cases[i].entries[j].starting_lba)
1748 break;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001749
Randall Spanglere9213a72013-01-24 11:19:55 -08001750 e[j].starting_lba = cases[i].entries[j].starting_lba;
1751 e[j].ending_lba = cases[i].entries[j].ending_lba;
1752 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1753 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1754 }
1755 RefreshCrc32(gpt);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001756
Randall Spanglere9213a72013-01-24 11:19:55 -08001757 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1758 }
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001759
Randall Spanglere9213a72013-01-24 11:19:55 -08001760 return TEST_OK;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001761}
1762
Randall Spangler0bda13f2013-01-24 12:25:26 -08001763/* Test getting the current kernel GUID */
1764static int GetKernelGuidTest(void)
1765{
1766 GptData *gpt = GetEmptyGptData();
1767 GptEntry *e = (GptEntry *)gpt->primary_entries;
1768 Guid g;
1769
1770 BuildTestGptData(gpt);
1771 gpt->current_kernel = 0;
1772 GetCurrentKernelUniqueGuid(gpt, &g);
1773 EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1774 gpt->current_kernel = 1;
1775 GetCurrentKernelUniqueGuid(gpt, &g);
1776 EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1777
1778 return TEST_OK;
1779}
1780
1781/* Test getting GPT error text strings */
1782static int ErrorTextTest(void)
1783{
1784 int i;
1785
1786 /* Known errors are not unknown */
1787 for (i = 0; i < GPT_ERROR_COUNT; i++) {
1788 EXPECT(GptErrorText(i));
1789 EXPECT(strcmp(GptErrorText(i), "Unknown"));
1790 }
1791
1792 /* But other error values are */
1793 EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1794
1795 return TEST_OK;
1796}
1797
Albert Chaulk534723a2013-03-20 14:46:50 -07001798int nand_read_page(const nand_geom *nand, int page, void *buf, int size) {
1799 uint32_t ofs = page * nand->szofpg;
1800 uint32_t sz = size;
1801 if (ofs + sz > nand_drive_sz) {
1802 return -1;
1803 }
1804 Memcpy(buf, nand_drive + ofs, sz);
1805 return 0;
1806}
1807
1808int nand_write_page(const nand_geom *nand, int page,
1809 const void *buf, int size) {
1810 uint32_t ofs = page * nand->szofpg;
1811 uint32_t sz = size;
1812 uint32_t i;
1813 if (ofs + sz > nand_drive_sz) {
1814 return -1;
1815 }
1816 for (i = 0; i < sz; i++) {
1817 if (nand_drive[ofs + i] != 0xff) {
1818 return -1;
1819 }
1820 }
1821 Memcpy(nand_drive + ofs, buf, sz);
1822 return 0;
1823}
1824
1825int nand_erase_block(const nand_geom *nand, int block) {
1826 uint32_t ofs = block * nand->szofblk;
1827 uint32_t sz = nand->szofblk;
1828 if (ofs + sz > nand_drive_sz) {
1829 return -1;
1830 }
1831 if (!--nand_bad_block_map[block]) {
1832 return -1;
1833 }
1834 Memset(nand_drive + ofs, 0xFF, sz);
1835 return 0;
1836}
1837
1838int nand_is_bad_block(const nand_geom *nand, int block) {
1839 return nand_bad_block_map[block] == 0;
1840}
1841
1842
1843static void nand_make_ramdisk() {
1844 if (nand_drive) {
1845 free(nand_drive);
1846 }
1847 if (nand_bad_block_map) {
1848 free(nand_bad_block_map);
1849 }
1850 nand_drive_sz = 1024 * 1024 * 16;
1851 nand_drive = (uint8_t *)malloc(nand_drive_sz);
1852 nand_bad_block_map = (uint8_t *)malloc(nand_drive_sz / 512);
1853 Memset(nand_drive, 0xff, nand_drive_sz);
1854 Memset(nand_bad_block_map, 0xff, nand_drive_sz / 512);
1855}
1856
1857static int MtdFtsTest() {
1858 int MtdLoad(struct drive *drive, int sector_bytes);
1859 int MtdSave(struct drive *drive);
1860 int FlashGet(const char *key, uint8_t *data, uint32_t *bufsz);
1861 int FlashSet(const char *key, const uint8_t *data, uint32_t bufsz);
1862
1863 int i, j, err;
1864
1865 struct {
1866 int result;
1867 unsigned int offset, size, block_size_bytes, page_size_bytes;
1868 } cases[] = {
1869 { 0, 1, 2, 1024 * 1024, 1024 * 4 },
1870 { 0, 1, 2, 1024 * 1024, 1024 * 16 },
1871
1872 /* Failure cases, non-power-of-2 */
1873 { -ENODEV, 1, 2, 5000000, 1024 * 16 },
1874 { -ENODEV, 1, 2, 1024 * 1024, 65535 },
1875
1876 /* Page > block */
1877 { -ENODEV, 1, 2, 1024 * 16, 1024 * 1024 },
1878 };
1879
1880
1881 /* Check if the FTS store works */
1882 for (i = 0; i < ARRAY_SIZE(cases); i++) {
1883 nand_make_ramdisk();
1884 EXPECT(cases[i].result == flash_ts_init(cases[i].offset, cases[i].size,
1885 cases[i].page_size_bytes,
1886 cases[i].block_size_bytes, 512, 0));
1887
1888 if (cases[i].result == 0) {
1889 /* We should have a working FTS store now */
1890 char buffer[64];
1891 uint8_t blob[256], blob_read[256];
1892 uint32_t sz = sizeof(blob_read);
1893 struct drive drive;
1894
1895 /* Test the low level API */
1896 EXPECT(0 == flash_ts_set("some_key", "some value"));
1897 flash_ts_get("some_key", buffer, sizeof(buffer));
1898 EXPECT(0 == strcmp(buffer, "some value"));
1899
1900 /* Check overwrite */
1901 EXPECT(0 == flash_ts_set("some_key", "some other value"));
1902 flash_ts_get("some_key", buffer, sizeof(buffer));
1903 EXPECT(0 == strcmp(buffer, "some other value"));
1904
1905 /* Check delete */
1906 EXPECT(0 == flash_ts_set("some_key", ""));
1907
1908 /* Verify that re-initialization pulls the right record. */
1909 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1910 cases[i].block_size_bytes, 512, 0);
1911 flash_ts_get("some_key", buffer, sizeof(buffer));
1912 EXPECT(0 == strcmp(buffer, ""));
1913
1914 /* Fill up the disk, eating all erase cycles */
1915 for (j = 0; j < nand_drive_sz / 512; j++) {
1916 nand_bad_block_map[j] = 2;
1917 }
1918 for (j = 0; j < 999999; j++) {
1919 char str[32];
1920 sprintf(str, "%d", j);
1921 err = flash_ts_set("some_new_key", str);
1922 if (err) {
1923 EXPECT(err == -ENOMEM);
1924 break;
1925 }
1926
1927 /* Make sure we can figure out where the latest is. */
1928 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1929 cases[i].block_size_bytes, 512, 0);
1930 flash_ts_get("some_new_key", buffer, sizeof(buffer));
1931 EXPECT(0 == strcmp(buffer, str));
1932 }
1933 EXPECT(j < 999999);
1934
1935 /* We need our drive back. */
1936 nand_make_ramdisk();
1937 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1938 cases[i].block_size_bytes, 512, 0);
1939
1940
1941 for (j = 0; j < 256; j++) {
1942 blob[j] = j;
1943 }
1944
1945 /* Hex conversion / blob storage */
1946 EXPECT(0 == FlashSet("some_blob", blob, sizeof(blob)));
1947 EXPECT(0 == FlashGet("some_blob", blob_read, &sz));
1948 EXPECT(sz == sizeof(blob_read));
1949 EXPECT(0 == Memcmp(blob, blob_read, sizeof(blob)));
1950
1951 BuildTestMtdData(&drive.mtd);
1952 drive.mtd.flash_block_bytes = cases[i].block_size_bytes;
1953 drive.mtd.flash_page_bytes = cases[i].page_size_bytes;
1954 drive.mtd.fts_block_offset = cases[i].offset;
1955 drive.mtd.fts_block_size = cases[i].size;
1956 drive.mtd.sector_bytes = 512;
1957 drive.mtd.drive_sectors = nand_drive_sz / 512;
1958
1959 /* MTD-level API */
1960 EXPECT(0 == MtdSave(&drive));
1961 Memset(&drive.mtd.primary, 0, sizeof(drive.mtd.primary));
1962 EXPECT(0 == MtdLoad(&drive, 512));
1963 }
1964 }
1965
1966 return TEST_OK;
1967}
1968
Randall Spanglere9213a72013-01-24 11:19:55 -08001969int main(int argc, char *argv[])
1970{
1971 int i;
1972 int error_count = 0;
1973 struct {
1974 char *name;
1975 test_func fp;
1976 int retval;
1977 } test_cases[] = {
1978 { TEST_CASE(StructSizeTest), },
1979 { TEST_CASE(TestBuildTestGptData), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001980 { TEST_CASE(TestBuildTestMtdData), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001981 { TEST_CASE(ParameterTests), },
1982 { TEST_CASE(HeaderCrcTest), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08001983 { TEST_CASE(HeaderSameTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001984 { TEST_CASE(SignatureTest), },
1985 { TEST_CASE(RevisionTest), },
1986 { TEST_CASE(SizeTest), },
1987 { TEST_CASE(CrcFieldTest), },
1988 { TEST_CASE(ReservedFieldsTest), },
1989 { TEST_CASE(SizeOfPartitionEntryTest), },
1990 { TEST_CASE(NumberOfPartitionEntriesTest), },
1991 { TEST_CASE(MyLbaTest), },
1992 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1993 { TEST_CASE(EntriesCrcTest), },
1994 { TEST_CASE(ValidEntryTest), },
1995 { TEST_CASE(OverlappedPartitionTest), },
1996 { TEST_CASE(SanityCheckTest), },
1997 { TEST_CASE(NoValidKernelEntryTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001998 { TEST_CASE(MtdNoValidKernelEntryTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08001999 { TEST_CASE(EntryAttributeGetSetTest), },
2000 { TEST_CASE(EntryTypeTest), },
2001 { TEST_CASE(GetNextNormalTest), },
2002 { TEST_CASE(GetNextPrioTest), },
2003 { TEST_CASE(GetNextTriesTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002004 { TEST_CASE(MtdGetNextNormalTest), },
2005 { TEST_CASE(MtdGetNextPrioTest), },
2006 { TEST_CASE(MtdGetNextTriesTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002007 { TEST_CASE(GptUpdateTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002008 { TEST_CASE(MtdUpdateTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002009 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002010 { TEST_CASE(MtdUpdateInvalidKernelTypeTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002011 { TEST_CASE(DuplicateUniqueGuidTest), },
2012 { TEST_CASE(TestCrc32TestVectors), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08002013 { TEST_CASE(GetKernelGuidTest), },
2014 { TEST_CASE(ErrorTextTest), },
Albert Chaulk534723a2013-03-20 14:46:50 -07002015 { TEST_CASE(MtdFtsTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002016 };
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002017
Randall Spanglere9213a72013-01-24 11:19:55 -08002018 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
2019 printf("Running %s() ...\n", test_cases[i].name);
2020 test_cases[i].retval = test_cases[i].fp();
2021 if (test_cases[i].retval) {
2022 printf(COL_RED "[ERROR]\n\n" COL_STOP);
2023 ++error_count;
2024 } else {
2025 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
2026 }
2027 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002028
Randall Spanglere9213a72013-01-24 11:19:55 -08002029 if (error_count) {
2030 printf("\n------------------------------------------------\n");
2031 printf(COL_RED "The following %d test cases are failed:\n"
2032 COL_STOP, error_count);
2033 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
2034 if (test_cases[i].retval)
2035 printf(" %s()\n", test_cases[i].name);
2036 }
2037 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002038
Randall Spanglere9213a72013-01-24 11:19:55 -08002039 return error_count ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002040}