blob: fc166fda3a3b469f9857f2f48ffced7382c9d24f [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;
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700167 gpt->drive_sectors = gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
Randall Spanglere9213a72013-01-24 11:19:55 -0800168 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;
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700356 gpt->drive_sectors = gpt->gpt_drive_sectors = cases[i].drive_sectors;
Randall Spanglere9213a72013-01-24 11:19:55 -0800357 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
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800464 EXPECT(1 == CheckHeader(NULL, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler0bda13f2013-01-24 12:25:26 -0800465
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);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800471 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
472 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800473 }
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
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800506 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800507 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800508 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800509 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
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800539 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800540 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800541 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800542 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++;
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800558 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
559 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800560 /* Refresh the CRC; should pass now */
561 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800562 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
563 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
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);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800579 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
580 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
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);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800588 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
589 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
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
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800627 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800628 cases[i].expect_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800629 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800630 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);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800650 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
651 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700652 /* But it's okay to have less if the GPT structs are stored elsewhere. */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800653 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
654 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800655
656 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700657}
658
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700659
Randall Spanglere9213a72013-01-24 11:19:55 -0800660/* Test if myLBA field is checked (1 for primary, last for secondary). */
661static int MyLbaTest(void)
662{
663 GptData *gpt = GetEmptyGptData();
664 GptHeader *h1 = (GptHeader *)gpt->primary_header;
665 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700666
Randall Spanglere9213a72013-01-24 11:19:55 -0800667 /* myLBA depends on primary vs secondary flag */
668 BuildTestGptData(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800669 EXPECT(1 == CheckHeader(h1, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
670 EXPECT(1 == CheckHeader(h2, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700671
Randall Spanglere9213a72013-01-24 11:19:55 -0800672 BuildTestGptData(gpt);
673 h1->my_lba--;
674 h2->my_lba--;
675 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800676 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
677 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700678
Randall Spanglere9213a72013-01-24 11:19:55 -0800679 BuildTestGptData(gpt);
680 h1->my_lba = 2;
681 h2->my_lba--;
682 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800683 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
684 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700685
Randall Spanglere9213a72013-01-24 11:19:55 -0800686 /* We should ignore the alternate_lba field entirely */
687 BuildTestGptData(gpt);
688 h1->alternate_lba++;
689 h2->alternate_lba++;
690 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800691 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
692 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800693
694 BuildTestGptData(gpt);
695 h1->alternate_lba--;
696 h2->alternate_lba--;
697 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800698 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
699 EXPECT(0 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800700
701 BuildTestGptData(gpt);
702 h1->entries_lba++;
703 h2->entries_lba++;
704 RefreshCrc32(gpt);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700705 /*
706 * We support a padding between primary GPT header and its entries. So
707 * this still passes.
708 */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800709 EXPECT(0 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700710 /*
711 * But the secondary table should fail because it would overlap the
712 * header, which is now lying after its entry array.
713 */
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800714 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800715
716 BuildTestGptData(gpt);
717 h1->entries_lba--;
718 h2->entries_lba--;
719 RefreshCrc32(gpt);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800720 EXPECT(1 == CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
721 EXPECT(1 == CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Randall Spanglere9213a72013-01-24 11:19:55 -0800722
723 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700724}
725
Randall Spanglere9213a72013-01-24 11:19:55 -0800726/* Test if FirstUsableLBA and LastUsableLBA are checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700727 * FirstUsableLBA must be after the end of the primary GPT table array.
728 * LastUsableLBA must be before the start of the secondary GPT table array.
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -0700729 * FirstUsableLBA <= LastUsableLBA.
730 * Also see CheckHeaderOffDevice() test. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800731static int FirstUsableLbaAndLastUsableLbaTest(void)
732{
733 GptData *gpt = GetEmptyGptData();
734 GptHeader *h1 = (GptHeader *)gpt->primary_header;
735 GptHeader *h2 = (GptHeader *)gpt->secondary_header;
736 int i;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700737
Randall Spanglere9213a72013-01-24 11:19:55 -0800738 struct {
739 uint64_t primary_entries_lba;
740 uint64_t primary_first_usable_lba;
741 uint64_t primary_last_usable_lba;
742 uint64_t secondary_first_usable_lba;
743 uint64_t secondary_last_usable_lba;
744 uint64_t secondary_entries_lba;
745 int primary_rv;
746 int secondary_rv;
747 } cases[] = {
748 {2, 34, 433, 34, 433, 434, 0, 0},
749 {2, 34, 432, 34, 430, 434, 0, 0},
750 {2, 33, 433, 33, 433, 434, 1, 1},
751 {2, 34, 434, 34, 433, 434, 1, 0},
752 {2, 34, 433, 34, 434, 434, 0, 1},
753 {2, 35, 433, 35, 433, 434, 0, 0},
754 {2, 433, 433, 433, 433, 434, 0, 0},
755 {2, 434, 433, 434, 434, 434, 1, 1},
756 {2, 433, 34, 34, 433, 434, 1, 0},
757 {2, 34, 433, 433, 34, 434, 0, 1},
758 };
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700759
Randall Spanglere9213a72013-01-24 11:19:55 -0800760 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
761 BuildTestGptData(gpt);
762 h1->entries_lba = cases[i].primary_entries_lba;
763 h1->first_usable_lba = cases[i].primary_first_usable_lba;
764 h1->last_usable_lba = cases[i].primary_last_usable_lba;
765 h2->entries_lba = cases[i].secondary_entries_lba;
766 h2->first_usable_lba = cases[i].secondary_first_usable_lba;
767 h2->last_usable_lba = cases[i].secondary_last_usable_lba;
768 RefreshCrc32(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700769
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800770 EXPECT(CheckHeader(h1, 0, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800771 cases[i].primary_rv);
Dan Ehrenberga524a3a2014-11-06 16:22:24 -0800772 EXPECT(CheckHeader(h2, 1, gpt->drive_sectors, gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE) ==
Randall Spanglere9213a72013-01-24 11:19:55 -0800773 cases[i].secondary_rv);
774 }
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700775
Randall Spanglere9213a72013-01-24 11:19:55 -0800776 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700777}
778
Randall Spanglere9213a72013-01-24 11:19:55 -0800779/*
780 * Test if PartitionEntryArrayCRC32 is checked. PartitionEntryArrayCRC32 must
781 * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700782 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800783static int EntriesCrcTest(void)
784{
785 GptData *gpt = GetEmptyGptData();
786 GptHeader *h1 = (GptHeader *)gpt->primary_header;
787 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
788 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700789
Randall Spanglere9213a72013-01-24 11:19:55 -0800790 /* Modify first byte of primary entries, and expect the CRC is wrong. */
791 BuildTestGptData(gpt);
792 EXPECT(0 == CheckEntries(e1, h1));
793 EXPECT(0 == CheckEntries(e2, h1));
794 gpt->primary_entries[0] ^= 0xa5; /* just XOR a non-zero value */
795 gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
796 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
797 EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700798
Randall Spanglere9213a72013-01-24 11:19:55 -0800799 return TEST_OK;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700800}
801
Randall Spanglere9213a72013-01-24 11:19:55 -0800802/*
803 * Test if partition geometry is checked.
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700804 * All active (non-zero PartitionTypeGUID) partition entries should have:
805 * entry.StartingLBA >= header.FirstUsableLBA
806 * entry.EndingLBA <= header.LastUsableLBA
807 * entry.StartingLBA <= entry.EndingLBA
808 */
Randall Spanglere9213a72013-01-24 11:19:55 -0800809static int ValidEntryTest(void)
810{
811 GptData *gpt = GetEmptyGptData();
812 GptHeader *h1 = (GptHeader *)gpt->primary_header;
813 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700814 MtdData *mtd = GetEmptyMtdData();
815 MtdDiskLayout *mh = &mtd->primary;
816 MtdDiskPartition *me = mh->partitions;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700817
Randall Spanglere9213a72013-01-24 11:19:55 -0800818 /* error case: entry.StartingLBA < header.FirstUsableLBA */
819 BuildTestGptData(gpt);
820 e1[0].starting_lba = h1->first_usable_lba - 1;
821 RefreshCrc32(gpt);
822 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700823
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700824 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700825 if (mh->first_offset > 0) {
826 me[0].starting_offset = mh->first_offset - 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700827 mh->crc32 = MtdHeaderCrc(mh);
828 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
829 }
830
Randall Spanglere9213a72013-01-24 11:19:55 -0800831 /* error case: entry.EndingLBA > header.LastUsableLBA */
832 BuildTestGptData(gpt);
833 e1[2].ending_lba = h1->last_usable_lba + 1;
834 RefreshCrc32(gpt);
835 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700836
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700837 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700838 me[0].ending_offset = mh->last_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700839 mh->crc32 = MtdHeaderCrc(mh);
840 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
841
Randall Spanglere9213a72013-01-24 11:19:55 -0800842 /* error case: entry.StartingLBA > entry.EndingLBA */
843 BuildTestGptData(gpt);
844 e1[3].starting_lba = e1[3].ending_lba + 1;
845 RefreshCrc32(gpt);
846 EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700847
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700848 BuildTestMtdData(mtd);
Albert Chaulk289b6042013-06-25 11:30:46 -0700849 me[0].starting_offset = me[0].ending_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700850 mh->crc32 = MtdHeaderCrc(mh);
851 EXPECT(GPT_ERROR_OUT_OF_REGION == MtdCheckEntries(me, mh));
852
Randall Spanglere9213a72013-01-24 11:19:55 -0800853 /* case: non active entry should be ignored. */
854 BuildTestGptData(gpt);
855 Memset(&e1[1].type, 0, sizeof(e1[1].type));
856 e1[1].starting_lba = e1[1].ending_lba + 1;
857 RefreshCrc32(gpt);
858 EXPECT(0 == CheckEntries(e1, h1));
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700859
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700860 BuildTestMtdData(mtd);
861 me[0].flags = 0;
Albert Chaulk289b6042013-06-25 11:30:46 -0700862 me[0].starting_offset = me[0].ending_offset + 1;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700863 mh->crc32 = MtdHeaderCrc(mh);
864 EXPECT(GPT_SUCCESS == MtdCheckEntries(me, mh));
865
Randall Spanglere9213a72013-01-24 11:19:55 -0800866 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700867}
868
Randall Spanglere9213a72013-01-24 11:19:55 -0800869/* Test if overlapped partition tables can be detected. */
870static int OverlappedPartitionTest(void) {
871 GptData *gpt = GetEmptyGptData();
872 GptHeader *h = (GptHeader *)gpt->primary_header;
873 GptEntry *e = (GptEntry *)gpt->primary_entries;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700874 MtdData *mtd = GetEmptyMtdData();
875 MtdDiskLayout *mh = &mtd->primary;
876 MtdDiskPartition *me = mh->partitions;
Randall Spanglere9213a72013-01-24 11:19:55 -0800877 int i, j;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700878
Randall Spanglere9213a72013-01-24 11:19:55 -0800879 struct {
880 int overlapped;
881 struct {
882 int active;
883 uint64_t starting_lba;
884 uint64_t ending_lba;
885 } entries[16]; /* enough for testing. */
886 } cases[] = {
887 {GPT_SUCCESS, {{0, 100, 199}}},
888 {GPT_SUCCESS, {{1, 100, 199}}},
889 {GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
890 {GPT_ERROR_START_LBA_OVERLAP,
891 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
892 {GPT_ERROR_END_LBA_OVERLAP,
893 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
894 {GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
895 {GPT_ERROR_END_LBA_OVERLAP,
896 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
897 {GPT_ERROR_START_LBA_OVERLAP,
898 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
899 {GPT_ERROR_START_LBA_OVERLAP,
900 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
901 {GPT_ERROR_END_LBA_OVERLAP,
902 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
903 {GPT_ERROR_START_LBA_OVERLAP,
904 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
905 {GPT_SUCCESS,
906 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
907 {GPT_ERROR_START_LBA_OVERLAP,
908 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
909 {GPT_ERROR_START_LBA_OVERLAP,
910 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
911 {GPT_SUCCESS,
912 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
913 {GPT_ERROR_END_LBA_OVERLAP,
914 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
915 {GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
916 {GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
917 {GPT_ERROR_START_LBA_OVERLAP,
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}, {1, 199, 199}}},
921 {GPT_SUCCESS,
922 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
923 {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
924 {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
925 };
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700926
Randall Spanglere9213a72013-01-24 11:19:55 -0800927 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
928 BuildTestGptData(gpt);
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700929 BuildTestMtdData(mtd);
930 Memset(mh->partitions, 0, sizeof(mh->partitions));
Randall Spanglere9213a72013-01-24 11:19:55 -0800931 ZeroEntries(gpt);
932 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
933 if (!cases[i].entries[j].starting_lba)
934 break;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700935
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700936 if (cases[i].entries[j].active) {
Randall Spanglere9213a72013-01-24 11:19:55 -0800937 Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700938 me[j].flags =
939 MTD_PARTITION_TYPE_CHROMEOS_KERNEL << MTD_ATTRIBUTE_TYPE_OFFSET;
940 }
Randall Spanglere9213a72013-01-24 11:19:55 -0800941 SetGuid(&e[j].unique, j);
942 e[j].starting_lba = cases[i].entries[j].starting_lba;
943 e[j].ending_lba = cases[i].entries[j].ending_lba;
Albert Chaulk289b6042013-06-25 11:30:46 -0700944 me[j].starting_offset = cases[i].entries[j].starting_lba *
945 DEFAULT_SECTOR_SIZE;
946 me[j].ending_offset = cases[i].entries[j].ending_lba *
947 DEFAULT_SECTOR_SIZE;
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700948
Randall Spanglere9213a72013-01-24 11:19:55 -0800949 }
950 RefreshCrc32(gpt);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700951
Randall Spanglere9213a72013-01-24 11:19:55 -0800952 EXPECT(cases[i].overlapped == CheckEntries(e, h));
Albert Chaulk5c9e4532013-03-20 16:03:49 -0700953 EXPECT(cases[i].overlapped == MtdCheckEntries(me, mh));
Randall Spanglere9213a72013-01-24 11:19:55 -0800954 }
955 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -0700956}
957
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700958/* Test both sanity checking and repair. */
Randall Spanglere9213a72013-01-24 11:19:55 -0800959static int SanityCheckTest(void)
960{
961 GptData *gpt = GetEmptyGptData();
962 GptHeader *h1 = (GptHeader *)gpt->primary_header;
Randall Spangler0bda13f2013-01-24 12:25:26 -0800963 GptEntry *e1 = (GptEntry *)gpt->primary_entries;
964 uint8_t *tempptr;
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -0700965
Randall Spanglere9213a72013-01-24 11:19:55 -0800966 /* Unmodified test data is completely sane */
967 BuildTestGptData(gpt);
968 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
969 EXPECT(MASK_BOTH == gpt->valid_headers);
970 EXPECT(MASK_BOTH == gpt->valid_entries);
971 /* Repair doesn't damage it */
972 GptRepair(gpt);
973 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
974 EXPECT(MASK_BOTH == gpt->valid_headers);
975 EXPECT(MASK_BOTH == gpt->valid_entries);
976 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700977
Randall Spangler0bda13f2013-01-24 12:25:26 -0800978 /* Invalid sector size should fail */
979 BuildTestGptData(gpt);
980 gpt->sector_bytes = 1024;
981 EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
982
Randall Spanglere9213a72013-01-24 11:19:55 -0800983 /* Modify headers */
984 BuildTestGptData(gpt);
985 gpt->primary_header[0]++;
986 gpt->secondary_header[0]++;
987 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
988 EXPECT(0 == gpt->valid_headers);
989 EXPECT(0 == gpt->valid_entries);
990 /* Repair can't fix completely busted headers */
991 GptRepair(gpt);
992 EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
993 EXPECT(0 == gpt->valid_headers);
994 EXPECT(0 == gpt->valid_entries);
995 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700996
Randall Spanglere9213a72013-01-24 11:19:55 -0800997 BuildTestGptData(gpt);
998 gpt->primary_header[0]++;
999 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1000 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1001 EXPECT(MASK_BOTH == gpt->valid_entries);
1002 GptRepair(gpt);
1003 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1004 EXPECT(MASK_BOTH == gpt->valid_headers);
1005 EXPECT(MASK_BOTH == gpt->valid_entries);
1006 EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001007
Randall Spanglere9213a72013-01-24 11:19:55 -08001008 BuildTestGptData(gpt);
1009 gpt->secondary_header[0]++;
1010 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1011 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1012 EXPECT(MASK_BOTH == gpt->valid_entries);
1013 GptRepair(gpt);
1014 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1015 EXPECT(MASK_BOTH == gpt->valid_headers);
1016 EXPECT(MASK_BOTH == gpt->valid_entries);
1017 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001018
Randall Spanglere9213a72013-01-24 11:19:55 -08001019 /*
1020 * Modify header1 and update its CRC. Since header2 is now different
1021 * than header1, it'll be the one considered invalid.
1022 */
1023 BuildTestGptData(gpt);
1024 h1->size++;
1025 RefreshCrc32(gpt);
1026 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1027 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1028 EXPECT(MASK_BOTH == gpt->valid_entries);
1029 GptRepair(gpt);
1030 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1031 EXPECT(MASK_BOTH == gpt->valid_headers);
1032 EXPECT(MASK_BOTH == gpt->valid_entries);
1033 EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001034
Randall Spanglere9213a72013-01-24 11:19:55 -08001035 /* Modify entries */
1036 BuildTestGptData(gpt);
1037 gpt->primary_entries[0]++;
1038 gpt->secondary_entries[0]++;
1039 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
1040 EXPECT(MASK_BOTH == gpt->valid_headers);
1041 EXPECT(MASK_NONE == gpt->valid_entries);
1042 /* Repair can't fix both copies of entries being bad, either. */
1043 GptRepair(gpt);
1044 EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
1045 EXPECT(MASK_BOTH == gpt->valid_headers);
1046 EXPECT(MASK_NONE == gpt->valid_entries);
1047 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001048
Randall Spanglere9213a72013-01-24 11:19:55 -08001049 BuildTestGptData(gpt);
1050 gpt->primary_entries[0]++;
1051 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1052 EXPECT(MASK_BOTH == gpt->valid_headers);
1053 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1054 GptRepair(gpt);
1055 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1056 EXPECT(MASK_BOTH == gpt->valid_headers);
1057 EXPECT(MASK_BOTH == gpt->valid_entries);
1058 EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001059
Randall Spanglere9213a72013-01-24 11:19:55 -08001060 BuildTestGptData(gpt);
1061 gpt->secondary_entries[0]++;
1062 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1063 EXPECT(MASK_BOTH == gpt->valid_headers);
1064 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1065 GptRepair(gpt);
1066 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1067 EXPECT(MASK_BOTH == gpt->valid_headers);
1068 EXPECT(MASK_BOTH == gpt->valid_entries);
1069 EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001070
Randall Spangler0bda13f2013-01-24 12:25:26 -08001071 /*
1072 * Modify entries and recompute CRCs, then make both primary and
1073 * secondary entry pointers use the secondary data. The primary
1074 * header will have the wrong entries CRC, so we should fall back
1075 * to the secondary header.
1076 */
1077 BuildTestGptData(gpt);
1078 e1->starting_lba++;
1079 RefreshCrc32(gpt);
1080 tempptr = gpt->primary_entries;
1081 gpt->primary_entries = gpt->secondary_entries;
1082 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1083 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1084 EXPECT(MASK_BOTH == gpt->valid_entries);
1085 gpt->primary_entries = tempptr;
1086
Randall Spanglere9213a72013-01-24 11:19:55 -08001087 /* Modify both header and entries */
1088 BuildTestGptData(gpt);
1089 gpt->primary_header[0]++;
1090 gpt->primary_entries[0]++;
1091 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1092 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1093 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1094 GptRepair(gpt);
1095 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1096 EXPECT(MASK_BOTH == gpt->valid_headers);
1097 EXPECT(MASK_BOTH == gpt->valid_entries);
1098 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001099
Randall Spanglere9213a72013-01-24 11:19:55 -08001100 BuildTestGptData(gpt);
1101 gpt->secondary_header[0]++;
1102 gpt->secondary_entries[0]++;
1103 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1104 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1105 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1106 GptRepair(gpt);
1107 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1108 EXPECT(MASK_BOTH == gpt->valid_headers);
1109 EXPECT(MASK_BOTH == gpt->valid_entries);
1110 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001111
Randall Spanglere9213a72013-01-24 11:19:55 -08001112 /* Test cross-correction (h1+e2, h2+e1) */
1113 BuildTestGptData(gpt);
1114 gpt->primary_header[0]++;
1115 gpt->secondary_entries[0]++;
1116 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1117 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1118 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1119 GptRepair(gpt);
1120 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1121 EXPECT(MASK_BOTH == gpt->valid_headers);
1122 EXPECT(MASK_BOTH == gpt->valid_entries);
1123 EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001124
Randall Spanglere9213a72013-01-24 11:19:55 -08001125 BuildTestGptData(gpt);
1126 gpt->secondary_header[0]++;
1127 gpt->primary_entries[0]++;
1128 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1129 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1130 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1131 GptRepair(gpt);
1132 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1133 EXPECT(MASK_BOTH == gpt->valid_headers);
1134 EXPECT(MASK_BOTH == gpt->valid_entries);
1135 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001136
Randall Spanglere9213a72013-01-24 11:19:55 -08001137 /*
1138 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different. This
1139 * simulates a partial update of the drive.
1140 */
1141 BuildTestGptData(gpt);
1142 gpt->secondary_entries[0]++;
1143 RefreshCrc32(gpt);
1144 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1145 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1146 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1147 GptRepair(gpt);
1148 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1149 EXPECT(MASK_BOTH == gpt->valid_headers);
1150 EXPECT(MASK_BOTH == gpt->valid_entries);
1151 EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
Louis Yung-Chieh Lo49fa8e52010-04-30 16:10:48 -07001152
Nam T. Nguyen5ce83252014-10-30 15:09:43 -07001153 /* Test unloaded entry array. */
1154 gpt = GetEmptyGptData();
1155 BuildTestGptData(gpt);
1156 gpt->primary_entries = NULL;
1157 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1158 EXPECT(MASK_SECONDARY == gpt->valid_entries);
1159 gpt = GetEmptyGptData();
1160 BuildTestGptData(gpt);
1161 gpt->secondary_entries = NULL;
1162 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1163 EXPECT(MASK_PRIMARY == gpt->valid_entries);
1164
1165 /* Test unloaded header. */
1166 gpt = GetEmptyGptData();
1167 BuildTestGptData(gpt);
1168 gpt->primary_header = NULL;
1169 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1170 EXPECT(MASK_SECONDARY == gpt->valid_headers);
1171 gpt = GetEmptyGptData();
1172 BuildTestGptData(gpt);
1173 gpt->secondary_header = NULL;
1174 EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1175 EXPECT(MASK_PRIMARY == gpt->valid_headers);
1176
Randall Spanglere9213a72013-01-24 11:19:55 -08001177 return TEST_OK;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07001178}
1179
Randall Spanglere9213a72013-01-24 11:19:55 -08001180static int EntryAttributeGetSetTest(void)
1181{
1182 GptData *gpt = GetEmptyGptData();
1183 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001184 MtdData *mtd = GetEmptyMtdData();
1185 MtdDiskPartition *m = &mtd->primary.partitions[0];
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001186
Randall Spanglere9213a72013-01-24 11:19:55 -08001187 e->attrs.whole = 0x0000000000000000ULL;
1188 SetEntrySuccessful(e, 1);
1189 EXPECT(0x0100000000000000ULL == e->attrs.whole);
1190 EXPECT(1 == GetEntrySuccessful(e));
1191 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1192 SetEntrySuccessful(e, 0);
1193 EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1194 EXPECT(0 == GetEntrySuccessful(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001195
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001196 m->flags = 0;
1197 MtdSetEntrySuccessful(m, 1);
1198 EXPECT(0x00000100 == m->flags);
1199 EXPECT(1 == MtdGetEntrySuccessful(m));
1200 m->flags = ~0;
1201 MtdSetEntrySuccessful(m, 0);
1202 EXPECT(0xFFFFFEFF == m->flags);
1203 EXPECT(0 == MtdGetEntrySuccessful(m));
1204
Randall Spanglere9213a72013-01-24 11:19:55 -08001205 e->attrs.whole = 0x0000000000000000ULL;
1206 SetEntryTries(e, 15);
1207 EXPECT(15 == GetEntryTries(e));
1208 EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1209 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1210 SetEntryTries(e, 0);
1211 EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1212 EXPECT(0 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001213
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001214 m->flags = 0;
1215 MtdSetEntryTries(m, 15);
1216 EXPECT(0x000000F0 == m->flags);
1217 EXPECT(15 == MtdGetEntryTries(m));
1218 m->flags = ~0;
1219 MtdSetEntryTries(m, 0);
1220 EXPECT(0xFFFFFF0F == m->flags);
1221 EXPECT(0 == MtdGetEntryTries(m));
1222
Randall Spanglere9213a72013-01-24 11:19:55 -08001223 e->attrs.whole = 0x0000000000000000ULL;
1224 SetEntryPriority(e, 15);
1225 EXPECT(0x000F000000000000ULL == e->attrs.whole);
1226 EXPECT(15 == GetEntryPriority(e));
1227 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1228 SetEntryPriority(e, 0);
1229 EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1230 EXPECT(0 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001231
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001232 m->flags = 0;
1233 MtdSetEntryPriority(m, 15);
1234 EXPECT(0x0000000F == m->flags);
1235 EXPECT(15 == MtdGetEntryPriority(m));
1236 m->flags = ~0;
1237 MtdSetEntryPriority(m, 0);
1238 EXPECT(0xFFFFFFF0 == m->flags);
1239 EXPECT(0 == MtdGetEntryPriority(m));
1240
Randall Spanglere9213a72013-01-24 11:19:55 -08001241 e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1242 EXPECT(1 == GetEntrySuccessful(e));
1243 EXPECT(15 == GetEntryPriority(e));
1244 EXPECT(15 == GetEntryTries(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001245
Randall Spanglere9213a72013-01-24 11:19:55 -08001246 e->attrs.whole = 0x0123000000000000ULL;
1247 EXPECT(1 == GetEntrySuccessful(e));
1248 EXPECT(2 == GetEntryTries(e));
1249 EXPECT(3 == GetEntryPriority(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001250
Randall Spanglere9213a72013-01-24 11:19:55 -08001251 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001252}
1253
Randall Spanglere9213a72013-01-24 11:19:55 -08001254static int EntryTypeTest(void)
1255{
1256 GptData *gpt = GetEmptyGptData();
1257 GptEntry *e = (GptEntry *)(gpt->primary_entries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001258
Randall Spanglere9213a72013-01-24 11:19:55 -08001259 Memcpy(&e->type, &guid_zero, sizeof(Guid));
1260 EXPECT(1 == IsUnusedEntry(e));
1261 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001262
Randall Spanglere9213a72013-01-24 11:19:55 -08001263 Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1264 EXPECT(0 == IsUnusedEntry(e));
1265 EXPECT(1 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001266
Randall Spanglere9213a72013-01-24 11:19:55 -08001267 Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1268 EXPECT(0 == IsUnusedEntry(e));
1269 EXPECT(0 == IsKernelEntry(e));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001270
Randall Spanglere9213a72013-01-24 11:19:55 -08001271 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001272}
1273
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001274/* Make an entry unused by clearing its type. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001275static void FreeEntry(GptEntry *e)
1276{
1277 Memset(&e->type, 0, sizeof(Guid));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001278}
1279
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001280static void MtdFreeEntry(MtdDiskPartition *e)
1281{
1282 MtdSetEntryType(e, MTD_PARTITION_TYPE_UNUSED);
1283}
1284
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001285/* Set up an entry. */
Randall Spanglere9213a72013-01-24 11:19:55 -08001286static void FillEntry(GptEntry *e, int is_kernel,
1287 int priority, int successful, int tries)
1288{
1289 Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1290 SetEntryPriority(e, priority);
1291 SetEntrySuccessful(e, successful);
1292 SetEntryTries(e, tries);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001293}
1294
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001295static void MtdFillEntry(MtdDiskPartition *e, int is_kernel,
1296 int priority, int successful, int tries)
1297{
1298 MtdSetEntryType(e, is_kernel ? MTD_PARTITION_TYPE_CHROMEOS_KERNEL :
1299 MTD_PARTITION_TYPE_CHROMEOS_FIRMWARE);
1300 MtdSetEntryPriority(e, priority);
1301 MtdSetEntrySuccessful(e, successful);
1302 MtdSetEntryTries(e, tries);
1303}
1304
Randall Spanglere9213a72013-01-24 11:19:55 -08001305/*
1306 * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001307 * any usable kernel entry.
1308 */
Randall Spanglere9213a72013-01-24 11:19:55 -08001309static int NoValidKernelEntryTest(void)
1310{
1311 GptData *gpt = GetEmptyGptData();
1312 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001313
Randall Spanglere9213a72013-01-24 11:19:55 -08001314 BuildTestGptData(gpt);
1315 SetEntryPriority(e1 + KERNEL_A, 0);
1316 FreeEntry(e1 + KERNEL_B);
1317 RefreshCrc32(gpt);
1318 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1319 GptNextKernelEntry(gpt, NULL, NULL));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001320
Randall Spanglere9213a72013-01-24 11:19:55 -08001321 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001322}
1323
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001324static int MtdNoValidKernelEntryTest(void)
1325{
1326 MtdData *mtd = GetEmptyMtdData();
1327 MtdDiskPartition *e1 = mtd->primary.partitions;
1328
1329 BuildTestMtdData(mtd);
1330 MtdSetEntryPriority(e1 + KERNEL_A, 0);
1331 MtdFreeEntry(e1 + KERNEL_B);
1332 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1333 MtdNextKernelEntry(mtd, NULL, NULL));
1334
1335 return TEST_OK;
1336}
1337
Randall Spanglere9213a72013-01-24 11:19:55 -08001338static int GetNextNormalTest(void)
1339{
1340 GptData *gpt = GetEmptyGptData();
1341 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1342 uint64_t start, size;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001343
Randall Spanglere9213a72013-01-24 11:19:55 -08001344 /* Normal case - both kernels successful */
1345 BuildTestGptData(gpt);
1346 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1347 FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1348 RefreshCrc32(gpt);
1349 GptInit(gpt);
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001350
Randall Spanglere9213a72013-01-24 11:19:55 -08001351 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1352 EXPECT(KERNEL_A == gpt->current_kernel);
1353 EXPECT(34 == start);
1354 EXPECT(100 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001355
Randall Spanglere9213a72013-01-24 11:19:55 -08001356 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1357 EXPECT(KERNEL_B == gpt->current_kernel);
1358 EXPECT(134 == start);
1359 EXPECT(99 == size);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001360
Randall Spanglere9213a72013-01-24 11:19:55 -08001361 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1362 GptNextKernelEntry(gpt, &start, &size));
1363 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001364
Randall Spanglere9213a72013-01-24 11:19:55 -08001365 /* Call as many times as you want; you won't get another kernel... */
1366 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1367 GptNextKernelEntry(gpt, &start, &size));
1368 EXPECT(-1 == gpt->current_kernel);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001369
Randall Spanglere9213a72013-01-24 11:19:55 -08001370 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001371}
1372
Randall Spanglere9213a72013-01-24 11:19:55 -08001373static int GetNextPrioTest(void)
1374{
1375 GptData *gpt = GetEmptyGptData();
1376 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1377 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001378
Randall Spanglere9213a72013-01-24 11:19:55 -08001379 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1380 BuildTestGptData(gpt);
1381 FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1382 FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1383 FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1384 FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1385 RefreshCrc32(gpt);
1386 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001387
Randall Spanglere9213a72013-01-24 11:19:55 -08001388 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1389 EXPECT(KERNEL_B == gpt->current_kernel);
1390 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1391 EXPECT(KERNEL_Y == gpt->current_kernel);
1392 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1393 EXPECT(KERNEL_A == gpt->current_kernel);
1394 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1395 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001396
Randall Spanglere9213a72013-01-24 11:19:55 -08001397 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001398}
1399
Randall Spanglere9213a72013-01-24 11:19:55 -08001400static int GetNextTriesTest(void)
1401{
1402 GptData *gpt = GetEmptyGptData();
1403 GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1404 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001405
Randall Spanglere9213a72013-01-24 11:19:55 -08001406 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1407 BuildTestGptData(gpt);
1408 FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1409 FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1410 FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1411 FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1412 RefreshCrc32(gpt);
1413 GptInit(gpt);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001414
Randall Spanglere9213a72013-01-24 11:19:55 -08001415 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1416 EXPECT(KERNEL_X == gpt->current_kernel);
1417 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1418 EXPECT(KERNEL_A == gpt->current_kernel);
1419 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1420 GptNextKernelEntry(gpt, &start, &size));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001421
Randall Spanglere9213a72013-01-24 11:19:55 -08001422 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001423}
1424
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001425static int MtdGetNextNormalTest(void)
1426{
1427 MtdData *mtd = GetEmptyMtdData();
1428 MtdDiskPartition *e1 = mtd->primary.partitions;
1429 uint64_t start, size;
1430
1431 /* Normal case - both kernels successful */
1432 BuildTestMtdData(mtd);
1433 MtdFillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1434 MtdFillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1435 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1436 MtdInit(mtd);
1437
1438 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1439 EXPECT(KERNEL_A == mtd->current_kernel);
1440 EXPECT(34 == start);
1441 EXPECT(100 == size);
1442
1443 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1444 EXPECT(KERNEL_B == mtd->current_kernel);
1445 EXPECT(134 == start);
1446 EXPECT(99 == size);
1447
1448 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1449 MtdNextKernelEntry(mtd, &start, &size));
1450 EXPECT(-1 == mtd->current_kernel);
1451
1452 /* Call as many times as you want; you won't get another kernel... */
1453 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1454 MtdNextKernelEntry(mtd, &start, &size));
1455 EXPECT(-1 == mtd->current_kernel);
1456
1457 return TEST_OK;
1458}
1459
1460static int MtdGetNextPrioTest(void)
1461{
1462 MtdData *mtd = GetEmptyMtdData();
1463 MtdDiskPartition *e1 = mtd->primary.partitions;
1464 uint64_t start, size;
1465
1466 /* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1467 BuildTestMtdData(mtd);
1468 MtdFillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1469 MtdFillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1470 MtdFillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1471 MtdFillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1472 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1473 MtdInit(mtd);
1474
1475 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1476 EXPECT(KERNEL_B == mtd->current_kernel);
1477 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1478 EXPECT(KERNEL_Y == mtd->current_kernel);
1479 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1480 EXPECT(KERNEL_A == mtd->current_kernel);
1481 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1482 MtdNextKernelEntry(mtd, &start, &size));
1483
1484 return TEST_OK;
1485}
1486
1487static int MtdGetNextTriesTest(void)
1488{
1489 MtdData *mtd = GetEmptyMtdData();
1490 MtdDiskPartition *e1 = mtd->primary.partitions;
1491 uint64_t start, size;
1492
1493 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1494 BuildTestMtdData(mtd);
1495 MtdFillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1496 MtdFillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1497 MtdFillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1498 MtdFillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1499 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1500 MtdInit(mtd);
1501
1502 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1503 EXPECT(KERNEL_X == mtd->current_kernel);
1504 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1505 EXPECT(KERNEL_A == mtd->current_kernel);
1506 EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1507 MtdNextKernelEntry(mtd, &start, &size));
1508
1509 return TEST_OK;
1510}
1511
1512static int MtdUpdateTest() {
1513 MtdData *mtd = GetEmptyMtdData();
1514 MtdDiskPartition *e = &mtd->primary.partitions[0];
1515 uint64_t start, size;
1516
1517 BuildTestMtdData(mtd);
1518
1519 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1520 MtdFillEntry(e + KERNEL_A, 1, 4, 1, 0);
1521 MtdFillEntry(e + KERNEL_B, 1, 3, 0, 2);
1522 MtdFillEntry(e + KERNEL_X, 1, 2, 0, 2);
1523 mtd->primary.crc32 = MtdHeaderCrc(&mtd->primary);
1524 mtd->modified = 0;
1525 EXPECT(GPT_SUCCESS == MtdInit(mtd));
1526
1527 /* Successful kernel */
1528 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1529 EXPECT(KERNEL_A == mtd->current_kernel);
1530 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1531 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1532 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1533 /* Trying successful kernel changes nothing */
1534 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1535 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1536 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1537 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1538 EXPECT(0 == mtd->modified);
1539 /* Marking it bad also does not update it. */
1540 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1541 EXPECT(1 == MtdGetEntrySuccessful(e + KERNEL_A));
1542 EXPECT(4 == MtdGetEntryPriority(e + KERNEL_A));
1543 EXPECT(0 == MtdGetEntryTries(e + KERNEL_A));
1544 EXPECT(0 == mtd->modified);
1545
1546 /* Kernel with tries */
1547 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1548 EXPECT(KERNEL_B == mtd->current_kernel);
1549 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_B));
1550 EXPECT(3 == MtdGetEntryPriority(e + KERNEL_B));
1551 EXPECT(2 == MtdGetEntryTries(e + KERNEL_B));
1552 /* Marking it bad clears it */
1553 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1554 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_B));
1555 EXPECT(0 == MtdGetEntryPriority(e + KERNEL_B));
1556 EXPECT(0 == MtdGetEntryTries(e + KERNEL_B));
1557 /* And that's caused the mtd to need updating */
1558 EXPECT(1 == mtd->modified);
1559
1560 /* Another kernel with tries */
1561 EXPECT(GPT_SUCCESS == MtdNextKernelEntry(mtd, &start, &size));
1562 EXPECT(KERNEL_X == mtd->current_kernel);
1563 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1564 EXPECT(2 == MtdGetEntryPriority(e + KERNEL_X));
1565 EXPECT(2 == MtdGetEntryTries(e + KERNEL_X));
1566 /* Trying it uses up a try */
1567 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1568 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1569 EXPECT(2 == MtdGetEntryPriority(e + KERNEL_X));
1570 EXPECT(1 == MtdGetEntryTries(e + KERNEL_X));
1571 /* Trying it again marks it inactive */
1572 EXPECT(GPT_SUCCESS == MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_TRY));
1573 EXPECT(0 == MtdGetEntrySuccessful(e + KERNEL_X));
1574 EXPECT(0 == MtdGetEntryPriority(e + KERNEL_X));
1575 EXPECT(0 == MtdGetEntryTries(e + KERNEL_X));
1576
1577 /* Can't update if entry isn't a kernel, or there isn't an entry */
1578 MtdSetEntryType(e + KERNEL_X, MTD_PARTITION_TYPE_UNUSED);
1579 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1580 MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1581 mtd->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1582 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1583 MtdUpdateKernelEntry(mtd, GPT_UPDATE_ENTRY_BAD));
1584
1585 return TEST_OK;
1586}
1587
Randall Spanglere9213a72013-01-24 11:19:55 -08001588static int GptUpdateTest(void)
1589{
1590 GptData *gpt = GetEmptyGptData();
1591 GptEntry *e = (GptEntry *)(gpt->primary_entries);
1592 GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1593 uint64_t start, size;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001594
Randall Spanglere9213a72013-01-24 11:19:55 -08001595 /* Tries=nonzero is attempted just like success, but tries=0 isn't */
1596 BuildTestGptData(gpt);
1597 FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1598 FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1599 FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1600 RefreshCrc32(gpt);
1601 GptInit(gpt);
1602 gpt->modified = 0; /* Nothing modified yet */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001603
Randall Spanglere9213a72013-01-24 11:19:55 -08001604 /* Successful kernel */
1605 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1606 EXPECT(KERNEL_A == gpt->current_kernel);
1607 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1608 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1609 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1610 EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1611 EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1612 EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1613 /* Trying successful kernel changes nothing */
1614 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1615 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1616 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1617 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1618 EXPECT(0 == gpt->modified);
1619 /* Marking it bad also does not update it. */
1620 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1621 EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1622 EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1623 EXPECT(0 == GetEntryTries(e + KERNEL_A));
1624 EXPECT(0 == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001625
Randall Spanglere9213a72013-01-24 11:19:55 -08001626 /* Kernel with tries */
1627 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1628 EXPECT(KERNEL_B == gpt->current_kernel);
1629 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1630 EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1631 EXPECT(2 == GetEntryTries(e + KERNEL_B));
1632 /* Marking it bad clears it */
1633 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1634 EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1635 EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1636 EXPECT(0 == GetEntryTries(e + KERNEL_B));
1637 /* Which affects both copies of the partition entries */
1638 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1639 EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1640 EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1641 /* And that's caused the GPT to need updating */
1642 EXPECT(0x0F == gpt->modified);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001643
Randall Spanglere9213a72013-01-24 11:19:55 -08001644 /* Another kernel with tries */
1645 EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1646 EXPECT(KERNEL_X == gpt->current_kernel);
1647 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1648 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1649 EXPECT(2 == GetEntryTries(e + KERNEL_X));
1650 /* Trying it uses up a try */
1651 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1652 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1653 EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1654 EXPECT(1 == GetEntryTries(e + KERNEL_X));
1655 EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1656 EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1657 EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1658 /* Trying it again marks it inactive */
1659 EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1660 EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1661 EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1662 EXPECT(0 == GetEntryTries(e + KERNEL_X));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001663
Randall Spangler0bda13f2013-01-24 12:25:26 -08001664 /* Can't update if entry isn't a kernel, or there isn't an entry */
1665 Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
1666 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1667 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1668 gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
1669 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1670 GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1671
1672
Randall Spanglere9213a72013-01-24 11:19:55 -08001673 return TEST_OK;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001674}
1675
Randall Spanglere9213a72013-01-24 11:19:55 -08001676/*
1677 * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1678 * GPT_ERROR_INVALID_UPDATE_TYPE.
1679 */
1680static int UpdateInvalidKernelTypeTest(void)
1681{
1682 GptData *gpt = GetEmptyGptData();
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07001683
Randall Spanglere9213a72013-01-24 11:19:55 -08001684 BuildTestGptData(gpt);
1685 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1686 gpt->current_kernel = 0;
1687 /* any invalid update_type value */
1688 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1689 GptUpdateKernelEntry(gpt, 99));
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001690
Randall Spanglere9213a72013-01-24 11:19:55 -08001691 return TEST_OK;
Louis Yung-Chieh Lob17db3c2010-05-05 11:21:08 -07001692}
1693
Albert Chaulk5c9e4532013-03-20 16:03:49 -07001694static int MtdUpdateInvalidKernelTypeTest(void)
1695{
1696 MtdData *mtd = GetEmptyMtdData();
1697
1698 BuildTestMtdData(mtd);
1699 /* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1700 mtd->current_kernel = 0;
1701 /* any invalid update_type value */
1702 EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1703 MtdUpdateKernelEntry(mtd, 99));
1704
1705 return TEST_OK;
1706}
1707
Randall Spanglere9213a72013-01-24 11:19:55 -08001708/* Test duplicate UniqueGuids can be detected. */
1709static int DuplicateUniqueGuidTest(void)
1710{
1711 GptData *gpt = GetEmptyGptData();
1712 GptHeader *h = (GptHeader *)gpt->primary_header;
1713 GptEntry *e = (GptEntry *)gpt->primary_entries;
1714 int i, j;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001715
Randall Spanglere9213a72013-01-24 11:19:55 -08001716 struct {
1717 int duplicate;
1718 struct {
1719 uint64_t starting_lba;
1720 uint64_t ending_lba;
1721 uint32_t type_guid;
1722 uint32_t unique_guid;
1723 } entries[16]; /* enough for testing. */
1724 } cases[] = {
1725 {GPT_SUCCESS, {{100, 109, 1, 1},
1726 {110, 119, 2, 2},
1727 {120, 129, 3, 3},
1728 {130, 139, 4, 4},
1729 }},
1730 {GPT_SUCCESS, {{100, 109, 1, 1},
1731 {110, 119, 1, 2},
1732 {120, 129, 2, 3},
1733 {130, 139, 2, 4},
1734 }},
1735 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1736 {110, 119, 2, 2},
1737 {120, 129, 3, 1},
1738 {130, 139, 4, 4},
1739 }},
1740 {GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1741 {110, 119, 1, 2},
1742 {120, 129, 2, 3},
1743 {130, 139, 2, 2},
1744 }},
1745 };
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001746
Randall Spanglere9213a72013-01-24 11:19:55 -08001747 for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1748 BuildTestGptData(gpt);
1749 ZeroEntries(gpt);
1750 for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1751 if (!cases[i].entries[j].starting_lba)
1752 break;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001753
Randall Spanglere9213a72013-01-24 11:19:55 -08001754 e[j].starting_lba = cases[i].entries[j].starting_lba;
1755 e[j].ending_lba = cases[i].entries[j].ending_lba;
1756 SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1757 SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1758 }
1759 RefreshCrc32(gpt);
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001760
Randall Spanglere9213a72013-01-24 11:19:55 -08001761 EXPECT(cases[i].duplicate == CheckEntries(e, h));
1762 }
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001763
Randall Spanglere9213a72013-01-24 11:19:55 -08001764 return TEST_OK;
Bill Richardsonaa8eda42010-08-27 09:31:26 -07001765}
1766
Randall Spangler0bda13f2013-01-24 12:25:26 -08001767/* Test getting the current kernel GUID */
1768static int GetKernelGuidTest(void)
1769{
1770 GptData *gpt = GetEmptyGptData();
1771 GptEntry *e = (GptEntry *)gpt->primary_entries;
1772 Guid g;
1773
1774 BuildTestGptData(gpt);
1775 gpt->current_kernel = 0;
1776 GetCurrentKernelUniqueGuid(gpt, &g);
1777 EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
1778 gpt->current_kernel = 1;
1779 GetCurrentKernelUniqueGuid(gpt, &g);
1780 EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
1781
1782 return TEST_OK;
1783}
1784
1785/* Test getting GPT error text strings */
1786static int ErrorTextTest(void)
1787{
1788 int i;
1789
1790 /* Known errors are not unknown */
1791 for (i = 0; i < GPT_ERROR_COUNT; i++) {
1792 EXPECT(GptErrorText(i));
1793 EXPECT(strcmp(GptErrorText(i), "Unknown"));
1794 }
1795
1796 /* But other error values are */
1797 EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
1798
1799 return TEST_OK;
1800}
1801
Albert Chaulk534723a2013-03-20 14:46:50 -07001802int nand_read_page(const nand_geom *nand, int page, void *buf, int size) {
1803 uint32_t ofs = page * nand->szofpg;
1804 uint32_t sz = size;
1805 if (ofs + sz > nand_drive_sz) {
1806 return -1;
1807 }
1808 Memcpy(buf, nand_drive + ofs, sz);
1809 return 0;
1810}
1811
1812int nand_write_page(const nand_geom *nand, int page,
1813 const void *buf, int size) {
1814 uint32_t ofs = page * nand->szofpg;
1815 uint32_t sz = size;
1816 uint32_t i;
1817 if (ofs + sz > nand_drive_sz) {
1818 return -1;
1819 }
1820 for (i = 0; i < sz; i++) {
1821 if (nand_drive[ofs + i] != 0xff) {
1822 return -1;
1823 }
1824 }
1825 Memcpy(nand_drive + ofs, buf, sz);
1826 return 0;
1827}
1828
1829int nand_erase_block(const nand_geom *nand, int block) {
1830 uint32_t ofs = block * nand->szofblk;
1831 uint32_t sz = nand->szofblk;
1832 if (ofs + sz > nand_drive_sz) {
1833 return -1;
1834 }
1835 if (!--nand_bad_block_map[block]) {
1836 return -1;
1837 }
1838 Memset(nand_drive + ofs, 0xFF, sz);
1839 return 0;
1840}
1841
1842int nand_is_bad_block(const nand_geom *nand, int block) {
1843 return nand_bad_block_map[block] == 0;
1844}
1845
1846
1847static void nand_make_ramdisk() {
1848 if (nand_drive) {
1849 free(nand_drive);
1850 }
1851 if (nand_bad_block_map) {
1852 free(nand_bad_block_map);
1853 }
1854 nand_drive_sz = 1024 * 1024 * 16;
1855 nand_drive = (uint8_t *)malloc(nand_drive_sz);
1856 nand_bad_block_map = (uint8_t *)malloc(nand_drive_sz / 512);
1857 Memset(nand_drive, 0xff, nand_drive_sz);
1858 Memset(nand_bad_block_map, 0xff, nand_drive_sz / 512);
1859}
1860
1861static int MtdFtsTest() {
1862 int MtdLoad(struct drive *drive, int sector_bytes);
1863 int MtdSave(struct drive *drive);
1864 int FlashGet(const char *key, uint8_t *data, uint32_t *bufsz);
1865 int FlashSet(const char *key, const uint8_t *data, uint32_t bufsz);
1866
1867 int i, j, err;
1868
1869 struct {
1870 int result;
1871 unsigned int offset, size, block_size_bytes, page_size_bytes;
1872 } cases[] = {
1873 { 0, 1, 2, 1024 * 1024, 1024 * 4 },
1874 { 0, 1, 2, 1024 * 1024, 1024 * 16 },
1875
1876 /* Failure cases, non-power-of-2 */
1877 { -ENODEV, 1, 2, 5000000, 1024 * 16 },
1878 { -ENODEV, 1, 2, 1024 * 1024, 65535 },
1879
1880 /* Page > block */
1881 { -ENODEV, 1, 2, 1024 * 16, 1024 * 1024 },
1882 };
1883
1884
1885 /* Check if the FTS store works */
1886 for (i = 0; i < ARRAY_SIZE(cases); i++) {
1887 nand_make_ramdisk();
1888 EXPECT(cases[i].result == flash_ts_init(cases[i].offset, cases[i].size,
1889 cases[i].page_size_bytes,
1890 cases[i].block_size_bytes, 512, 0));
1891
1892 if (cases[i].result == 0) {
1893 /* We should have a working FTS store now */
1894 char buffer[64];
1895 uint8_t blob[256], blob_read[256];
1896 uint32_t sz = sizeof(blob_read);
1897 struct drive drive;
1898
1899 /* Test the low level API */
1900 EXPECT(0 == flash_ts_set("some_key", "some value"));
1901 flash_ts_get("some_key", buffer, sizeof(buffer));
1902 EXPECT(0 == strcmp(buffer, "some value"));
1903
1904 /* Check overwrite */
1905 EXPECT(0 == flash_ts_set("some_key", "some other value"));
1906 flash_ts_get("some_key", buffer, sizeof(buffer));
1907 EXPECT(0 == strcmp(buffer, "some other value"));
1908
1909 /* Check delete */
1910 EXPECT(0 == flash_ts_set("some_key", ""));
1911
1912 /* Verify that re-initialization pulls the right record. */
1913 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1914 cases[i].block_size_bytes, 512, 0);
1915 flash_ts_get("some_key", buffer, sizeof(buffer));
1916 EXPECT(0 == strcmp(buffer, ""));
1917
1918 /* Fill up the disk, eating all erase cycles */
1919 for (j = 0; j < nand_drive_sz / 512; j++) {
1920 nand_bad_block_map[j] = 2;
1921 }
1922 for (j = 0; j < 999999; j++) {
1923 char str[32];
1924 sprintf(str, "%d", j);
1925 err = flash_ts_set("some_new_key", str);
1926 if (err) {
1927 EXPECT(err == -ENOMEM);
1928 break;
1929 }
1930
1931 /* Make sure we can figure out where the latest is. */
1932 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1933 cases[i].block_size_bytes, 512, 0);
1934 flash_ts_get("some_new_key", buffer, sizeof(buffer));
1935 EXPECT(0 == strcmp(buffer, str));
1936 }
1937 EXPECT(j < 999999);
1938
1939 /* We need our drive back. */
1940 nand_make_ramdisk();
1941 flash_ts_init(cases[i].offset, cases[i].size, cases[i].page_size_bytes,
1942 cases[i].block_size_bytes, 512, 0);
1943
1944
1945 for (j = 0; j < 256; j++) {
1946 blob[j] = j;
1947 }
1948
1949 /* Hex conversion / blob storage */
1950 EXPECT(0 == FlashSet("some_blob", blob, sizeof(blob)));
1951 EXPECT(0 == FlashGet("some_blob", blob_read, &sz));
1952 EXPECT(sz == sizeof(blob_read));
1953 EXPECT(0 == Memcmp(blob, blob_read, sizeof(blob)));
1954
1955 BuildTestMtdData(&drive.mtd);
1956 drive.mtd.flash_block_bytes = cases[i].block_size_bytes;
1957 drive.mtd.flash_page_bytes = cases[i].page_size_bytes;
1958 drive.mtd.fts_block_offset = cases[i].offset;
1959 drive.mtd.fts_block_size = cases[i].size;
1960 drive.mtd.sector_bytes = 512;
1961 drive.mtd.drive_sectors = nand_drive_sz / 512;
1962
1963 /* MTD-level API */
1964 EXPECT(0 == MtdSave(&drive));
1965 Memset(&drive.mtd.primary, 0, sizeof(drive.mtd.primary));
1966 EXPECT(0 == MtdLoad(&drive, 512));
1967 }
1968 }
1969
1970 return TEST_OK;
1971}
1972
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001973static int CheckHeaderOffDevice()
1974{
1975 GptData* gpt = GetEmptyGptData();
1976 BuildTestGptData(gpt);
1977
1978 GptHeader* primary_header = (GptHeader*)gpt->primary_header;
1979 primary_header->first_usable_lba = 0;
1980 RefreshCrc32(gpt);
1981 // GPT is stored on the same device so first usable lba should not
1982 // start at 0.
1983 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001984 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001985 // But off device, it is okay to accept this GPT header.
1986 EXPECT(0 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001987 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001988
1989 BuildTestGptData(gpt);
1990 primary_header->number_of_entries = 100;
1991 RefreshCrc32(gpt);
1992 // Normally, number of entries is 128. So this should fail.
1993 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001994 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001995 // But off device, it is okay.
1996 EXPECT(0 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08001997 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07001998
1999 primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
2000 RefreshCrc32(gpt);
2001 // However, too few entries is not good.
2002 EXPECT(1 == CheckHeader(primary_header, 0, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002003 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002004
2005 // Repeat for secondary header.
2006 BuildTestGptData(gpt);
2007 GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
2008 secondary_header->first_usable_lba = 0;
2009 RefreshCrc32(gpt);
2010 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002011 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002012 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002013 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002014
2015 BuildTestGptData(gpt);
2016 secondary_header->number_of_entries = 100;
2017 RefreshCrc32(gpt);
2018 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002019 gpt->gpt_drive_sectors, GPT_STORED_ON_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002020 EXPECT(0 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002021 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002022
2023 secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
2024 RefreshCrc32(gpt);
2025 EXPECT(1 == CheckHeader(secondary_header, 1, gpt->drive_sectors,
Dan Ehrenberga524a3a2014-11-06 16:22:24 -08002026 gpt->gpt_drive_sectors, GPT_STORED_OFF_DEVICE));
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002027
2028 return TEST_OK;
2029}
2030
Randall Spanglere9213a72013-01-24 11:19:55 -08002031int main(int argc, char *argv[])
2032{
2033 int i;
2034 int error_count = 0;
2035 struct {
2036 char *name;
2037 test_func fp;
2038 int retval;
2039 } test_cases[] = {
2040 { TEST_CASE(StructSizeTest), },
2041 { TEST_CASE(TestBuildTestGptData), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002042 { TEST_CASE(TestBuildTestMtdData), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002043 { TEST_CASE(ParameterTests), },
2044 { TEST_CASE(HeaderCrcTest), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08002045 { TEST_CASE(HeaderSameTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002046 { TEST_CASE(SignatureTest), },
2047 { TEST_CASE(RevisionTest), },
2048 { TEST_CASE(SizeTest), },
2049 { TEST_CASE(CrcFieldTest), },
2050 { TEST_CASE(ReservedFieldsTest), },
2051 { TEST_CASE(SizeOfPartitionEntryTest), },
2052 { TEST_CASE(NumberOfPartitionEntriesTest), },
2053 { TEST_CASE(MyLbaTest), },
2054 { TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
2055 { TEST_CASE(EntriesCrcTest), },
2056 { TEST_CASE(ValidEntryTest), },
2057 { TEST_CASE(OverlappedPartitionTest), },
2058 { TEST_CASE(SanityCheckTest), },
2059 { TEST_CASE(NoValidKernelEntryTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002060 { TEST_CASE(MtdNoValidKernelEntryTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002061 { TEST_CASE(EntryAttributeGetSetTest), },
2062 { TEST_CASE(EntryTypeTest), },
2063 { TEST_CASE(GetNextNormalTest), },
2064 { TEST_CASE(GetNextPrioTest), },
2065 { TEST_CASE(GetNextTriesTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002066 { TEST_CASE(MtdGetNextNormalTest), },
2067 { TEST_CASE(MtdGetNextPrioTest), },
2068 { TEST_CASE(MtdGetNextTriesTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002069 { TEST_CASE(GptUpdateTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002070 { TEST_CASE(MtdUpdateTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002071 { TEST_CASE(UpdateInvalidKernelTypeTest), },
Albert Chaulk5c9e4532013-03-20 16:03:49 -07002072 { TEST_CASE(MtdUpdateInvalidKernelTypeTest), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002073 { TEST_CASE(DuplicateUniqueGuidTest), },
2074 { TEST_CASE(TestCrc32TestVectors), },
Randall Spangler0bda13f2013-01-24 12:25:26 -08002075 { TEST_CASE(GetKernelGuidTest), },
2076 { TEST_CASE(ErrorTextTest), },
Albert Chaulk534723a2013-03-20 14:46:50 -07002077 { TEST_CASE(MtdFtsTest), },
Nam T. Nguyen6ee52d92014-10-24 13:20:39 -07002078 { TEST_CASE(CheckHeaderOffDevice), },
Randall Spanglere9213a72013-01-24 11:19:55 -08002079 };
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002080
Randall Spanglere9213a72013-01-24 11:19:55 -08002081 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
2082 printf("Running %s() ...\n", test_cases[i].name);
2083 test_cases[i].retval = test_cases[i].fp();
2084 if (test_cases[i].retval) {
2085 printf(COL_RED "[ERROR]\n\n" COL_STOP);
2086 ++error_count;
2087 } else {
2088 printf(COL_GREEN "[PASS]\n\n" COL_STOP);
2089 }
2090 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002091
Randall Spanglere9213a72013-01-24 11:19:55 -08002092 if (error_count) {
2093 printf("\n------------------------------------------------\n");
2094 printf(COL_RED "The following %d test cases are failed:\n"
2095 COL_STOP, error_count);
2096 for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
2097 if (test_cases[i].retval)
2098 printf(" %s()\n", test_cases[i].name);
2099 }
2100 }
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002101
Randall Spanglere9213a72013-01-24 11:19:55 -08002102 return error_count ? 1 : 0;
Louis Yung-Chieh Lo4bbf21e2010-04-21 17:29:05 -07002103}