1e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
24bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo * Use of this source code is governed by a BSD-style license that can be
34bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo * found in the LICENSE file.
44bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo */
54bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
6f510973497a430c1bb41d9b7e996d02fb7f7179eAlex Deymo#include <errno.h>
737f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#include <string.h>
83dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
9534723a6519267461855441279b321e6fc1e4e90Albert Chaulk#include "../cgpt/cgpt.h"
100dce41c2ece9020d5ac9bb68c9772432fac85e64Louis Yung-Chieh Lo#include "cgptlib_internal.h"
113dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#include "cgptlib_test.h"
1249fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo#include "crc32.h"
13b31ddcec6a826986cd215725bf4defbc6021fe6bLouis Yung-Chieh Lo#include "crc32_test.h"
1437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#include "gpt.h"
153ecaf776d82d29573be083b2e5c6ddc5b9f49c70vbendeb#include "test_common.h"
16534723a6519267461855441279b321e6fc1e4e90Albert Chaulk#define _STUB_IMPLEMENTATION_
1737f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#include "utility.h"
1837f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
19e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
20e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Testing partition layout (sector_bytes=512)
2137f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *
2237f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *     LBA   Size  Usage
23b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo * ---------------------------------------------------------
2437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *       0      1  PMBR
2537f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *       1      1  primary partition header
2637f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *       2     32  primary partition entries (128B * 128)
27b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo *      34    100  kernel A (index: 0)
28b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo *     134    100  root A (index: 1)
29b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo *     234    100  root B (index: 2)
30b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo *     334    100  kernel B (index: 3)
3137f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *     434     32  secondary partition entries
3237f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *     466      1  secondary partition header
3337f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo *     467
3437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo */
35b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo#define KERNEL_A 0
363dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#define KERNEL_B 1
373dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#define ROOTFS_A 2
383dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#define ROOTFS_B 3
393dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#define KERNEL_X 2 /* Overload ROOTFS_A, for some GetNext tests */
403dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#define KERNEL_Y 3 /* Overload ROOTFS_B, for some GetNext tests */
41b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
4237f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#define DEFAULT_SECTOR_SIZE 512
4337f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#define MAX_SECTOR_SIZE 4096
4437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo#define DEFAULT_DRIVE_SECTORS 467
45f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg#define TOTAL_ENTRIES_SIZE (MAX_NUMBER_OF_ENTRIES * sizeof(GptEntry)) /* 16384 */
4649fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo#define PARTITION_ENTRIES_SIZE TOTAL_ENTRIES_SIZE /* 16384 */
4737f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
483dcf9dce04301d6d735f265652625fffb6758430Randall Spanglerstatic const Guid guid_zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
493dcf9dce04301d6d735f265652625fffb6758430Randall Spanglerstatic const Guid guid_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
503dcf9dce04301d6d735f265652625fffb6758430Randall Spanglerstatic const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
513dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
52534723a6519267461855441279b321e6fc1e4e90Albert Chaulk// cgpt_common.c requires these be defined if linked in.
53534723a6519267461855441279b321e6fc1e4e90Albert Chaulkconst char *progname = "CGPT-TEST";
54534723a6519267461855441279b321e6fc1e4e90Albert Chaulkconst char *command = "TEST";
55534723a6519267461855441279b321e6fc1e4e90Albert Chaulk
56e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
57e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Copy a random-for-this-program-only Guid into the dest. The num parameter
58aa8eda4f97f43a51bfec4fc096635565617a89e0Bill Richardson * completely determines the Guid.
59aa8eda4f97f43a51bfec4fc096635565617a89e0Bill Richardson */
60e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void SetGuid(void *dest, uint32_t num)
61e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
62e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Guid g = {{{num,0xd450,0x44bc,0xa6,0x93,
63e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		    {0xb8,0xac,0x75,0x5f,0xcd,0x48}}}};
64e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(dest, &g, sizeof(Guid));
65aa8eda4f97f43a51bfec4fc096635565617a89e0Bill Richardson}
663dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
67e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
68e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Given a GptData pointer, first re-calculate entries CRC32 value, then reset
69e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * header CRC32 value to 0, and calculate header CRC32 value.  Both primary and
70e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * secondary are updated.
71e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
72e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void RefreshCrc32(GptData *gpt)
73e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
74e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *header, *header2;
75e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *entries, *entries2;
76e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
77e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header = (GptHeader *)gpt->primary_header;
78e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries = (GptEntry *)gpt->primary_entries;
79e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2 = (GptHeader *)gpt->secondary_header;
80e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries2 = (GptEntry *)gpt->secondary_entries;
81e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
82e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->entries_crc32 =
83e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		Crc32((uint8_t *)entries,
84e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		      header->number_of_entries * header->size_of_entry);
85e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->header_crc32 = 0;
86e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->header_crc32 = Crc32((uint8_t *)header, header->size);
87e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->entries_crc32 =
88e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		Crc32((uint8_t *)entries2,
89e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		      header2->number_of_entries * header2->size_of_entry);
90e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->header_crc32 = 0;
91e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->header_crc32 = Crc32((uint8_t *)header2, header2->size);
9249fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
9349fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
94e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void ZeroHeaders(GptData *gpt)
95e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
96e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(gpt->primary_header, 0, MAX_SECTOR_SIZE);
97e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(gpt->secondary_header, 0, MAX_SECTOR_SIZE);
9849fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
9949fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
100e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void ZeroEntries(GptData *gpt)
101e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
102e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(gpt->primary_entries, 0, PARTITION_ENTRIES_SIZE);
103e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(gpt->secondary_entries, 0, PARTITION_ENTRIES_SIZE);
10449fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
10549fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
106e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void ZeroHeadersEntries(GptData *gpt)
107e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
108e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	ZeroHeaders(gpt);
109e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	ZeroEntries(gpt);
11037f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo}
11137f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
112e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
113e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Return a pointer to a static GptData instance (no free is required).
11437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo * All fields are zero except 4 pointers linking to header and entries.
115e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * All content of headers and entries are zero.
116e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
117e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic GptData *GetEmptyGptData(void)
118e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
119e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	static GptData gpt;
120e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	static uint8_t primary_header[MAX_SECTOR_SIZE];
121e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	static uint8_t primary_entries[PARTITION_ENTRIES_SIZE];
122e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	static uint8_t secondary_header[MAX_SECTOR_SIZE];
123e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	static uint8_t secondary_entries[PARTITION_ENTRIES_SIZE];
124e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
125e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(&gpt, 0, sizeof(gpt));
126e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt.primary_header = primary_header;
127e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt.primary_entries = primary_entries;
128e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt.secondary_header = secondary_header;
129e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt.secondary_entries = secondary_entries;
130e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	ZeroHeadersEntries(&gpt);
131e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
132e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Initialize GptData internal states. */
133e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt.current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
134e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
135e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return &gpt;
13637f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo}
13737f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
138e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
139e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Fill in most of fields and creates the layout described in the top of this
14049fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo * file. Before calling this function, primary/secondary header/entries must
14149fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo * have been pointed to the buffer, say, a gpt returned from GetEmptyGptData().
14249fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo * This function returns a good (valid) copy of GPT layout described in top of
143e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * this file.
144e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
145e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void BuildTestGptData(GptData *gpt)
146e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
147e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *header, *header2;
148e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *entries, *entries2;
149e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
150e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Guid chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
151e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
152e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->sector_bytes = DEFAULT_SECTOR_SIZE;
153b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	gpt->streaming_drive_sectors =
154b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors = DEFAULT_DRIVE_SECTORS;
155e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
156e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->valid_headers = MASK_BOTH;
157e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->valid_entries = MASK_BOTH;
158e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->modified = 0;
159e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
160e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Build primary */
161e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header = (GptHeader *)gpt->primary_header;
162e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries = (GptEntry *)gpt->primary_entries;
163e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(header->signature, GPT_HEADER_SIGNATURE,
164e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       sizeof(GPT_HEADER_SIGNATURE));
165e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->revision = GPT_HEADER_REVISION;
166e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->size = sizeof(GptHeader);
167e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->reserved_zero = 0;
168e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->my_lba = 1;
169e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->alternate_lba = DEFAULT_DRIVE_SECTORS - 1;
170e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->first_usable_lba = 34;
171e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->last_usable_lba = DEFAULT_DRIVE_SECTORS - 1 - 32 - 1;  /* 433 */
172e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->entries_lba = 2;
173e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	  /* 512B / 128B * 32sectors = 128 entries */
174e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->number_of_entries = 128;
175e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header->size_of_entry = 128;  /* bytes */
176e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&entries[0].type, &chromeos_kernel, sizeof(chromeos_kernel));
177e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetGuid(&entries[0].unique, 0);
178e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[0].starting_lba = 34;
179e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[0].ending_lba = 133;
180e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&entries[1].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
181e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetGuid(&entries[1].unique, 1);
182e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[1].starting_lba = 134;
183e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[1].ending_lba = 232;
184e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&entries[2].type, &chromeos_rootfs, sizeof(chromeos_rootfs));
185e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetGuid(&entries[2].unique, 2);
186e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[2].starting_lba = 234;
187e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[2].ending_lba = 331;
188e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&entries[3].type, &chromeos_kernel, sizeof(chromeos_kernel));
189e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetGuid(&entries[3].unique, 3);
190e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[3].starting_lba = 334;
191e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries[3].ending_lba = 430;
192e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
193e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Build secondary */
194e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2 = (GptHeader *)gpt->secondary_header;
195e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	entries2 = (GptEntry *)gpt->secondary_entries;
196e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(header2, header, sizeof(GptHeader));
197e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(entries2, entries, PARTITION_ENTRIES_SIZE);
198e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->my_lba = DEFAULT_DRIVE_SECTORS - 1;  /* 466 */
199e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->alternate_lba = 1;
200e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	header2->entries_lba = DEFAULT_DRIVE_SECTORS - 1 - 32;  /* 434 */
201e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
202e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
20337f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo}
20437f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
205e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
206e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Test if the structures are the expected size; if this fails, struct packing
207e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * is not working properly.
208e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
209e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int StructSizeTest(void)
210e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
21181d0996901387619cc782ca258fcb4a9f3f591e7Randall Spangler
212e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GUID_EXPECTED_SIZE == sizeof(Guid));
213e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPTHEADER_EXPECTED_SIZE == sizeof(GptHeader));
214e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPTENTRY_EXPECTED_SIZE == sizeof(GptEntry));
215e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
21681d0996901387619cc782ca258fcb4a9f3f591e7Randall Spangler}
21781d0996901387619cc782ca258fcb4a9f3f591e7Randall Spangler
21881d0996901387619cc782ca258fcb4a9f3f591e7Randall Spangler
219e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if the default structure returned by BuildTestGptData() is good. */
220e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int TestBuildTestGptData(void)
221e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
222e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt;
2233dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
224e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt = GetEmptyGptData();
225e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
226e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptInit(gpt));
2270bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->sector_bytes = 0;
2280bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptInit(gpt));
229e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
23049fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
23149fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
232e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
233e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Test if wrong sector_bytes or drive_sectors is detected by GptInit().
234e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Currently we only support 512 bytes per sector.  In the future, we may
235e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * support other sizes.  A too small drive_sectors should be rejected by
236e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * GptInit().
237e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
238e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int ParameterTests(void)
239e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
240e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt;
241e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
242e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint32_t sector_bytes;
243e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t drive_sectors;
244e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int expected_retval;
245e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
246e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{512, DEFAULT_DRIVE_SECTORS, GPT_SUCCESS},
247e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{520, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
248e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{512, 0, GPT_ERROR_INVALID_SECTOR_NUMBER},
249f3f7fca07fbcb6bb9655a71257f09c71b0a1458dDan Ehrenberg		{512, 10, GPT_ERROR_INVALID_SECTOR_NUMBER},
25088458d9b5281aca162821a369707781ac9abb44eNam T. Nguyen		{512, GPT_PMBR_SECTORS + GPT_HEADER_SECTORS * 2 +
2513200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen		 TOTAL_ENTRIES_SIZE / DEFAULT_SECTOR_SIZE * 2, GPT_SUCCESS},
252e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{4096, DEFAULT_DRIVE_SECTORS, GPT_ERROR_INVALID_SECTOR_SIZE},
253e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
254e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
255e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
256e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt = GetEmptyGptData();
257e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
258e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
259e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		gpt->sector_bytes = cases[i].sector_bytes;
260b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->streaming_drive_sectors =
261b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg			gpt->gpt_drive_sectors = cases[i].drive_sectors;
262e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		EXPECT(cases[i].expected_retval == CheckParameters(gpt));
263e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
264e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
265e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
26649fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
26749fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
268e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if header CRC in two copies are calculated. */
269e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int HeaderCrcTest(void)
270e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
271e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
272e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
2733dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
274e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
275e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(HeaderCrc(h1) == h1->header_crc32);
2763dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
277e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* CRC covers first byte of header */
278e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
279e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[0] ^= 0xa5;
280e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(HeaderCrc(h1) != h1->header_crc32);
2813dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
282e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* CRC covers last byte of header */
283e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
284e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[h1->size - 1] ^= 0x5a;
285e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(HeaderCrc(h1) != h1->header_crc32);
2863dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
287e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* CRC only covers header */
288e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
289e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[h1->size] ^= 0x5a;
290e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(HeaderCrc(h1) == h1->header_crc32);
2913dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
292e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
2933dcf9dce04301d6d735f265652625fffb6758430Randall Spangler}
2943dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
2950bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler/* Test if header-same comparison works. */
2960bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spanglerstatic int HeaderSameTest(void)
2970bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler{
2980bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptData *gpt = GetEmptyGptData();
2990bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
3000bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
3010bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptHeader h3;
3020bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3030bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(0 == HeaderFieldsSame(h1, h2));
3040bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3050bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3060bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.signature[0] ^= 0xba;
3070bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3080bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3090bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3100bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.revision++;
3110bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3120bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3130bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3140bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.size++;
3150bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3160bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3170bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3180bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.reserved_zero++;
3190bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3200bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3210bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3220bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.first_usable_lba++;
3230bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3240bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3250bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3260bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.last_usable_lba++;
3270bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3280bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3290bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3300bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.disk_uuid.u.raw[0] ^= 0xba;
3310bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3320bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3330bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3340bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.number_of_entries++;
3350bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3360bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3370bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3380bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.size_of_entry++;
3390bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3400bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3410bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&h3, h2, sizeof(h3));
3420bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	h3.entries_crc32++;
3430bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(1 == HeaderFieldsSame(h1, &h3));
3440bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
3450bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	return TEST_OK;
3460bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler}
3470bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
348e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if signature ("EFI PART") is checked. */
349e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int SignatureTest(void)
350e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
351e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
352e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
353e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
354e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
355e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
356b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(NULL, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
3570bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
358e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < 8; ++i) {
359e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
360e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->signature[i] ^= 0xff;
361e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->signature[i] ^= 0xff;
362e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
363b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
364b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
365e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
366e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
367e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
36849fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
36949fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
370e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
371e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * The revision we currently support is GPT_HEADER_REVISION.  If the revision
372e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * in header is not that, we expect the header is invalid.
373e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
374e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int RevisionTest(void)
375e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
376e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
377e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
378e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
379e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
380e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
381e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
382e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint32_t value_to_test;
383e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int expect_rv;
384e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
385e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{0x01000000, 1},
386e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{0x00010000, 0},  /* GPT_HEADER_REVISION */
387e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{0x00000100, 1},
388e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{0x00000001, 1},
389e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{0x23010456, 1},
390e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
391e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
392e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
393e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
394e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->revision = cases[i].value_to_test;
395e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->revision = cases[i].value_to_test;
396e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
397e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
398b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
399e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
400b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
401e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
402e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
403e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
40449fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
40549fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
406e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int SizeTest(void)
407e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
408e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
409e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
410e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
411e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
412e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
413e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
414e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint32_t value_to_test;
415e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int expect_rv;
416e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
417e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{91, 1},
418e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{92, 0},
419e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{93, 0},
420e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{511, 0},
421e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{512, 0},
422e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{513, 1},
423e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
424e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
425e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
426e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
427e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->size = cases[i].value_to_test;
428e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->size = cases[i].value_to_test;
429e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
430e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
431b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
432e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
433b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
434e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
435e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
436e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
43749fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
43849fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
439e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if CRC is checked. */
440e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int CrcFieldTest(void)
441e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
442e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
443e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
444e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
445e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
446e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
447e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Modify a field that the header verification doesn't care about */
448e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->entries_crc32++;
449e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->entries_crc32++;
450b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
451b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
452e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Refresh the CRC; should pass now */
453e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
454b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
455b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
456e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
457e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
4583dcf9dce04301d6d735f265652625fffb6758430Randall Spangler}
4593dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
460e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if reserved fields are checked.  We'll try non-zero values to test. */
461e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int ReservedFieldsTest(void)
462e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
463e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
464e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
465e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
4663dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
467e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
468e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->reserved_zero ^= 0x12345678;  /* whatever random */
469e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->reserved_zero ^= 0x12345678;  /* whatever random */
470e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
471b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
472b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
47337f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
4743dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#ifdef PADDING_CHECKED
475e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* TODO: padding check is currently disabled */
476e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
477e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->padding[12] ^= 0x34;  /* whatever random */
478e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->padding[56] ^= 0x78;  /* whatever random */
479e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
480b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
481b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
4823dcf9dce04301d6d735f265652625fffb6758430Randall Spangler#endif
48337f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
484e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
48537f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo}
48637f6b55a25f337f555da1dfbe585d32cd004103dLouis Yung-Chieh Lo
487e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
488e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Technically, any size which is 2^N where N > 6 should work, but our
489e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * library only supports one size.
490e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
491e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int SizeOfPartitionEntryTest(void) {
492e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
493e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
494e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
495e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
496e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
497e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
498e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint32_t value_to_test;
499e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int expect_rv;
500e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
501e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{127, 1},
502e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{128, 0},
503e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{129, 1},
504e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{256, 1},
505e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{512, 1},
506e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
507e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
508e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Check size of entryes */
509e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
510e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
511e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->size_of_entry = cases[i].value_to_test;
512e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->size_of_entry = cases[i].value_to_test;
513e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->number_of_entries = TOTAL_ENTRIES_SIZE /
514e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			cases[i].value_to_test;
515e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->number_of_entries = TOTAL_ENTRIES_SIZE /
516e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			cases[i].value_to_test;
517e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
518e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
519b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
520e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
521b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
522e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].expect_rv);
523e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
524e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
525e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
5264bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
5274bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
528e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
529e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Technically, any size which is 2^N where N > 6 should work, but our library
530e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * only supports one size.
531e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
532e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int NumberOfPartitionEntriesTest(void)
533e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
534e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
535e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
536e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
537e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
538e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
539e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->number_of_entries--;
540e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->number_of_entries /= 2;
5413200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen	/* Because we halved h2 entries, its entries_lba is going to change. */
5423200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen	h2->entries_lba = h2->my_lba - CalculateEntriesSectors(h2);
543e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
544b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
545b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
5466ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	/* But it's okay to have less if the GPT structs are stored elsewhere. */
547b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
548b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
549e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
550e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
5514bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
5524bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
55349fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
554e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if myLBA field is checked (1 for primary, last for secondary). */
555e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int MyLbaTest(void)
556e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
557e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
558e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
559e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
560e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
561e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* myLBA depends on primary vs secondary flag */
562e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
563b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
564b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
565e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
566e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
567e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->my_lba--;
568e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->my_lba--;
569e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
570b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
571b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
572e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
573e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
574e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->my_lba = 2;
575e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->my_lba--;
576e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
577b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
578b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
579e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
580e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* We should ignore the alternate_lba field entirely */
581e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
582e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->alternate_lba++;
583e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->alternate_lba++;
584e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
585b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
586b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
587e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
588e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
589e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->alternate_lba--;
590e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->alternate_lba--;
591e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
592b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
593b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
594e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
595e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
596e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->entries_lba++;
597e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->entries_lba++;
598e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
599a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	/*
600a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 * We support a padding between primary GPT header and its entries. So
601a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 * this still passes.
602a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 */
603b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
604a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	/*
605a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 * But the secondary table should fail because it would overlap the
606a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 * header, which is now lying after its entry array.
607a2d72f70c18905aba25eb0971f6f601dd1fa5a60Nam T. Nguyen	 */
608b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
609e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
610e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
611e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->entries_lba--;
612e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h2->entries_lba--;
613e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
614b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
615b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0));
616e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
617e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
6184bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
6194bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
620e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if FirstUsableLBA and LastUsableLBA are checked.
6214bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo * FirstUsableLBA must be after the end of the primary GPT table array.
6224bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo * LastUsableLBA must be before the start of the secondary GPT table array.
6236ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen * FirstUsableLBA <= LastUsableLBA.
6246ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen * Also see CheckHeaderOffDevice() test. */
625e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int FirstUsableLbaAndLastUsableLbaTest(void)
626e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
627e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
628e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
629e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h2 = (GptHeader *)gpt->secondary_header;
630e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
631e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
632e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
633e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t primary_entries_lba;
634e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t primary_first_usable_lba;
635e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t primary_last_usable_lba;
636e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t secondary_first_usable_lba;
637e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t secondary_last_usable_lba;
638e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		uint64_t secondary_entries_lba;
639e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int primary_rv;
640e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int secondary_rv;
641e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
642e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  34, 433,   34, 433, 434,  0, 0},
643e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  34, 432,   34, 430, 434,  0, 0},
644e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  33, 433,   33, 433, 434,  1, 1},
645e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  34, 434,   34, 433, 434,  1, 0},
646e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  34, 433,   34, 434, 434,  0, 1},
647e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  35, 433,   35, 433, 434,  0, 0},
648e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2, 433, 433,  433, 433, 434,  0, 0},
649e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2, 434, 433,  434, 434, 434,  1, 1},
650e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2, 433,  34,   34, 433, 434,  1, 0},
651e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{2,  34, 433,  433,  34, 434,  0, 1},
652e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
653e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
654e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
655e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
656e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->entries_lba = cases[i].primary_entries_lba;
657e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->first_usable_lba = cases[i].primary_first_usable_lba;
658e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h1->last_usable_lba = cases[i].primary_last_usable_lba;
659e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->entries_lba = cases[i].secondary_entries_lba;
660e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->first_usable_lba = cases[i].secondary_first_usable_lba;
661e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		h2->last_usable_lba = cases[i].secondary_last_usable_lba;
662e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
663e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
664b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h1, 0, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
665e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].primary_rv);
666b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		EXPECT(CheckHeader(h2, 1, gpt->streaming_drive_sectors, gpt->gpt_drive_sectors, 0) ==
667e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       cases[i].secondary_rv);
668e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
669e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
670e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
6714bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
6724bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
673e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
674e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Test if PartitionEntryArrayCRC32 is checked.  PartitionEntryArrayCRC32 must
675e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * be calculated over SizeOfPartitionEntry * NumberOfPartitionEntries bytes.
6764bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo */
677e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int EntriesCrcTest(void)
678e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
679e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
680e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
681e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
682e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
683e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
684e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Modify first byte of primary entries, and expect the CRC is wrong. */
685e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
686e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == CheckEntries(e1, h1));
687e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == CheckEntries(e2, h1));
688e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_entries[0] ^= 0xa5;  /* just XOR a non-zero value */
689e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[TOTAL_ENTRIES_SIZE-1] ^= 0x5a;
690e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e1, h1));
691e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_CRC_CORRUPTED == CheckEntries(e2, h1));
692e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
693e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
69449fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo}
69549fa8e51ad4dff55b74d852d270ce5d0b9590034Louis Yung-Chieh Lo
696e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
697e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Test if partition geometry is checked.
6984bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo * All active (non-zero PartitionTypeGUID) partition entries should have:
6994bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo *   entry.StartingLBA >= header.FirstUsableLBA
7004bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo *   entry.EndingLBA <= header.LastUsableLBA
7014bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo *   entry.StartingLBA <= entry.EndingLBA
7024bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo */
703e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int ValidEntryTest(void)
704e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
705e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
706e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
707e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
708e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
709e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* error case: entry.StartingLBA < header.FirstUsableLBA */
710e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
711e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e1[0].starting_lba = h1->first_usable_lba - 1;
712e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
713e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
714e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
715e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* error case: entry.EndingLBA > header.LastUsableLBA */
716e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
717e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e1[2].ending_lba = h1->last_usable_lba + 1;
718e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
719e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
720e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
721e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* error case: entry.StartingLBA > entry.EndingLBA */
722e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
723e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e1[3].starting_lba = e1[3].ending_lba + 1;
724e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
725e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_OUT_OF_REGION == CheckEntries(e1, h1));
726e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
727e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* case: non active entry should be ignored. */
728e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
729e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(&e1[1].type, 0, sizeof(e1[1].type));
730e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e1[1].starting_lba = e1[1].ending_lba + 1;
731e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
732e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == CheckEntries(e1, h1));
733e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
734e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
7354bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
7364bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
737e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test if overlapped partition tables can be detected. */
738e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int OverlappedPartitionTest(void) {
739e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
740e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h = (GptHeader *)gpt->primary_header;
741e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e = (GptEntry *)gpt->primary_entries;
742e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i, j;
743e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
744e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
745e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int overlapped;
746e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		struct {
747e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			int active;
748e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint64_t starting_lba;
749e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint64_t ending_lba;
750e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		} entries[16];  /* enough for testing. */
751e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
752e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{0, 100, 199}}},
753e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{1, 100, 199}}},
754e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{1, 100, 150}, {1, 200, 250}, {1, 300, 350}}},
755e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
756e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 299}, {1, 100, 199}, {1, 100, 100}}},
757e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_END_LBA_OVERLAP,
758e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 299}, {1, 100, 199}, {1, 299, 299}}},
759e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{1, 300, 399}, {1, 200, 299}, {1, 100, 199}}},
760e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_END_LBA_OVERLAP,
761e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 100, 199}, {1, 199, 299}, {1, 299, 399}}},
762e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
763e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 100, 199}, {1, 200, 299}, {1, 75, 399}}},
764e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
765e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 100, 199}, {1, 75, 250}, {1, 200, 299}}},
766e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_END_LBA_OVERLAP,
767e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 75, 150}, {1, 100, 199}, {1, 200, 299}}},
768e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
769e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {1, 100, 399}}},
770e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS,
771e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 299}, {1, 100, 199}, {1, 300, 399}, {0, 100, 399}}},
772e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
773e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
774e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
775e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{0, 200, 300}, {1, 100, 200}, {1, 100, 400}, {1, 300, 400}}},
776e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS,
777e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 300}, {1, 100, 199}, {0, 100, 400}, {0, 300, 400}}},
778e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_END_LBA_OVERLAP,
779e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 200, 299}, {1, 100, 199}, {1, 199, 199}}},
780e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{1, 200, 299}, {0, 100, 199}, {1, 199, 199}}},
781e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{1, 200, 299}, {1, 100, 199}, {0, 199, 199}}},
782e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_START_LBA_OVERLAP,
783e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
784e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
785e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		  {1, 207, 207}, {1, 208, 208}, {1, 199, 199}}},
786e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS,
787e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		 {{1, 199, 199}, {1, 200, 200}, {1, 201, 201}, {1, 202, 202},
788e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		  {1, 203, 203}, {1, 204, 204}, {1, 205, 205}, {1, 206, 206},
789e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		  {1, 207, 207}, {1, 208, 208}, {0, 199, 199}}},
790e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
791e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
792e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
793e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
794e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		ZeroEntries(gpt);
795e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
796e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			if (!cases[i].entries[j].starting_lba)
797e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				break;
798e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
7995c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk			if (cases[i].entries[j].active) {
800e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				Memcpy(&e[j].type, &guid_kernel, sizeof(Guid));
8015c9e4532b9bc45cff22f37d3556da679809a60a7Albert Chaulk			}
802e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			SetGuid(&e[j].unique, j);
803e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			e[j].starting_lba = cases[i].entries[j].starting_lba;
804e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			e[j].ending_lba = cases[i].entries[j].ending_lba;
805e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		}
806e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
807e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
808e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		EXPECT(cases[i].overlapped == CheckEntries(e, h));
809e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
810e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
8114bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
8124bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo
8133dcf9dce04301d6d735f265652625fffb6758430Randall Spangler/* Test both sanity checking and repair. */
814e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int SanityCheckTest(void)
815e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
816e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
817e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h1 = (GptHeader *)gpt->primary_header;
8180bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptEntry *e1 = (GptEntry *)gpt->primary_entries;
8190bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	uint8_t *tempptr;
820e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
821e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Unmodified test data is completely sane */
822e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
823e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
824e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
825e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
826e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Repair doesn't damage it */
827e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
828e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
829e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
830e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
831e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->modified);
832e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
8330bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	/* Invalid sector size should fail */
8340bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	BuildTestGptData(gpt);
8350bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->sector_bytes = 1024;
8360bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(GPT_ERROR_INVALID_SECTOR_SIZE == GptSanityCheck(gpt));
8370bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
838e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Modify headers */
839e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
840e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[0]++;
841e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_header[0]++;
842e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
843e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->valid_headers);
844e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->valid_entries);
845e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Repair can't fix completely busted headers */
846e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
847e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_INVALID_HEADERS == GptSanityCheck(gpt));
848e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->valid_headers);
849e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->valid_entries);
850e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->modified);
851e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
852e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
853e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[0]++;
854e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
855e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_headers);
856e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
857e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
858e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
859e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
860e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
861e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_MODIFIED_HEADER1 == gpt->modified);
862e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
863e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
864e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_header[0]++;
865e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
866e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_headers);
867e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
868e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
869e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
870e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
871e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
872e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
873e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
874e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/*
875e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 * Modify header1 and update its CRC.  Since header2 is now different
876e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 * than header1, it'll be the one considered invalid.
877e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 */
878e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
879e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	h1->size++;
880e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
881e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
882e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_headers);
883e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
884e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
885e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
886e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
887e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
888e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_MODIFIED_HEADER2 == gpt->modified);
889e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
890e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Modify entries */
891e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
892e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_entries[0]++;
893e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[0]++;
894e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
895e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
896e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_NONE == gpt->valid_entries);
897e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Repair can't fix both copies of entries being bad, either. */
898e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
899e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_INVALID_ENTRIES == GptSanityCheck(gpt));
900e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
901e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_NONE == gpt->valid_entries);
902e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->modified);
903e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
904e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
905e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_entries[0]++;
906e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
907e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
908e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_entries);
909e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
910e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
911e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
912e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
913e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_MODIFIED_ENTRIES1 == gpt->modified);
914e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
915e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
916e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[0]++;
917e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
918e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
919e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_entries);
920e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
921e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
922e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
923e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
924e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_MODIFIED_ENTRIES2 == gpt->modified);
925e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
9260bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	/*
9270bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	 * Modify entries and recompute CRCs, then make both primary and
9280bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	 * secondary entry pointers use the secondary data.  The primary
9290bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	 * header will have the wrong entries CRC, so we should fall back
9300bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	 * to the secondary header.
9310bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	 */
9320bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	BuildTestGptData(gpt);
9330bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	e1->starting_lba++;
9340bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	RefreshCrc32(gpt);
9350bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	tempptr = gpt->primary_entries;
9360bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->primary_entries = gpt->secondary_entries;
9370bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
9380bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_headers);
9390bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
9400bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->primary_entries = tempptr;
9410bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
942e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Modify both header and entries */
943e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
944e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[0]++;
945e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_entries[0]++;
946e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
947e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_headers);
948e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_entries);
949e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
950e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
951e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
952e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
953e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
954e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
955e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
956e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_header[0]++;
957e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[0]++;
958e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
959e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_headers);
960e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_entries);
961e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
962e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
963e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
964e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
965e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
966e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
967e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Test cross-correction (h1+e2, h2+e1) */
968e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
969e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_header[0]++;
970e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[0]++;
971e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
972e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_headers);
973e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_entries);
974e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
975e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
976e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
977e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
978e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT((GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
979e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
980e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
981e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_header[0]++;
982e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->primary_entries[0]++;
983e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
984e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_headers);
985e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_SECONDARY == gpt->valid_entries);
986e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
987e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
988e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
989e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
990e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES1) == gpt->modified);
991e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
992e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/*
993e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 * Test mismatched pairs (h1+e1 valid, h2+e2 valid but different.  This
994e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 * simulates a partial update of the drive.
995e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	 */
996e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
997e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->secondary_entries[0]++;
998e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
999e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1000e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_headers);
1001e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_PRIMARY == gpt->valid_entries);
1002e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptRepair(gpt);
1003e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
1004e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_headers);
1005e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(MASK_BOTH == gpt->valid_entries);
1006e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT((GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2) == gpt->modified);
1007e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
10085ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	/* Test unloaded entry array. */
10095ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt = GetEmptyGptData();
10105ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	BuildTestGptData(gpt);
10115ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt->primary_entries = NULL;
10125ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
10135ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(MASK_SECONDARY == gpt->valid_entries);
10145ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt = GetEmptyGptData();
10155ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	BuildTestGptData(gpt);
10165ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt->secondary_entries = NULL;
10175ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
10185ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(MASK_PRIMARY == gpt->valid_entries);
10195ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen
10205ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	/* Test unloaded header. */
10215ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt = GetEmptyGptData();
10225ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	BuildTestGptData(gpt);
10235ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt->primary_header = NULL;
10245ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
10255ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(MASK_SECONDARY == gpt->valid_headers);
10265ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt = GetEmptyGptData();
10275ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	BuildTestGptData(gpt);
10285ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	gpt->secondary_header = NULL;
10295ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(GPT_SUCCESS == GptSanityCheck(gpt));
10305ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen	EXPECT(MASK_PRIMARY == gpt->valid_headers);
10315ce8325f4ac4662d0daef63878c85462a8e59ff4Nam T. Nguyen
1032e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1033b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1034b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1035e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int EntryAttributeGetSetTest(void)
1036e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1037e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1038e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e = (GptEntry *)(gpt->primary_entries);
1039e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1040e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0x0000000000000000ULL;
1041e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntrySuccessful(e, 1);
1042e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0x0100000000000000ULL == e->attrs.whole);
1043e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e));
1044e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1045e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntrySuccessful(e, 0);
1046e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0xFEFFFFFFFFFFFFFFULL == e->attrs.whole);
1047e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e));
1048e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1049e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0x0000000000000000ULL;
1050e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryTries(e, 15);
1051e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(15 == GetEntryTries(e));
1052e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0x00F0000000000000ULL == e->attrs.whole);
1053e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1054e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryTries(e, 0);
1055e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0xFF0FFFFFFFFFFFFFULL == e->attrs.whole);
1056e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e));
1057e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1058e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0x0000000000000000ULL;
1059e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryPriority(e, 15);
1060e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0x000F000000000000ULL == e->attrs.whole);
1061e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(15 == GetEntryPriority(e));
1062e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1063e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryPriority(e, 0);
1064e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole);
1065e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryPriority(e));
1066e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1067e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL;
1068e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e));
1069e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(15 == GetEntryPriority(e));
1070e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(15 == GetEntryTries(e));
1071e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1072e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	e->attrs.whole = 0x0123000000000000ULL;
1073e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e));
1074e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryTries(e));
1075e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(3 == GetEntryPriority(e));
1076e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1077e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1078b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1079b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1080e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int EntryTypeTest(void)
1081e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1082e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1083e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e = (GptEntry *)(gpt->primary_entries);
10843dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
1085e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&e->type, &guid_zero, sizeof(Guid));
1086e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == IsUnusedEntry(e));
1087e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == IsKernelEntry(e));
10883dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
1089e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&e->type, &guid_kernel, sizeof(Guid));
1090e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == IsUnusedEntry(e));
1091e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == IsKernelEntry(e));
10923dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
1093e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&e->type, &guid_rootfs, sizeof(Guid));
1094e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == IsUnusedEntry(e));
1095e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == IsKernelEntry(e));
10963dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
1097e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1098b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1099b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
11003dcf9dce04301d6d735f265652625fffb6758430Randall Spangler/* Make an entry unused by clearing its type. */
1101e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void FreeEntry(GptEntry *e)
1102e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1103e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memset(&e->type, 0, sizeof(Guid));
11043dcf9dce04301d6d735f265652625fffb6758430Randall Spangler}
11053dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
11063dcf9dce04301d6d735f265652625fffb6758430Randall Spangler/* Set up an entry. */
1107e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic void FillEntry(GptEntry *e, int is_kernel,
1108e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler                      int priority, int successful, int tries)
1109e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1110e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	Memcpy(&e->type, (is_kernel ? &guid_kernel : &guid_zero), sizeof(Guid));
1111e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryPriority(e, priority);
1112e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntrySuccessful(e, successful);
1113e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryTries(e, tries);
11143dcf9dce04301d6d735f265652625fffb6758430Randall Spangler}
11153dcf9dce04301d6d735f265652625fffb6758430Randall Spangler
1116e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
1117e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Invalidate all kernel entries and expect GptNextKernelEntry() cannot find
11183dcf9dce04301d6d735f265652625fffb6758430Randall Spangler * any usable kernel entry.
1119b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo */
1120e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int NoValidKernelEntryTest(void)
1121e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1122e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1123e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1124e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1125e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1126e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	SetEntryPriority(e1 + KERNEL_A, 0);
1127e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FreeEntry(e1 + KERNEL_B);
1128e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
1129e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1130e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptNextKernelEntry(gpt, NULL, NULL));
1131e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1132e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1133b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1134b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1135e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int GetNextNormalTest(void)
1136e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1137e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1138e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1139e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	uint64_t start, size;
1140e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1141e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Normal case - both kernels successful */
1142e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1143e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1144e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_B, 1, 2, 1, 0);
1145e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
1146e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptInit(gpt);
1147e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1148e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1149e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_A == gpt->current_kernel);
1150e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(34 == start);
1151e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(100 == size);
1152e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1153e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1154e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_B == gpt->current_kernel);
1155e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(134 == start);
1156e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(99 == size);
1157e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1158e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1159e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptNextKernelEntry(gpt, &start, &size));
1160e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(-1 == gpt->current_kernel);
1161e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1162e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Call as many times as you want; you won't get another kernel... */
1163e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1164e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptNextKernelEntry(gpt, &start, &size));
1165e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(-1 == gpt->current_kernel);
1166e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1167e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1168b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1169b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1170e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int GetNextPrioTest(void)
1171e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1172e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1173e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1174e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	uint64_t start, size;
1175e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1176e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Priority 3, 4, 0, 4 - should boot order B, Y, A */
1177e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1178e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_A, 1, 3, 1, 0);
1179e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_B, 1, 4, 1, 0);
1180e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_X, 1, 0, 1, 0);
1181e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_Y, 1, 4, 1, 0);
1182e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
1183e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptInit(gpt);
1184e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1185e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1186e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_B == gpt->current_kernel);
1187e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1188e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_Y == gpt->current_kernel);
1189e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1190e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_A == gpt->current_kernel);
1191e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1192e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptNextKernelEntry(gpt, &start, &size));
1193e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1194e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1195b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1196b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1197e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int GetNextTriesTest(void)
1198e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1199e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1200e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e1 = (GptEntry *)(gpt->primary_entries);
1201e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	uint64_t start, size;
1202e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1203e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
1204e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1205e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_A, 1, 2, 1, 0);
1206e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_B, 1, 3, 0, 0);
1207e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_X, 1, 4, 0, 1);
1208e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e1 + KERNEL_Y, 1, 0, 0, 5);
1209e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
1210e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptInit(gpt);
1211e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1212e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1213e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_X == gpt->current_kernel);
1214e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1215e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_A == gpt->current_kernel);
1216e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_NO_VALID_KERNEL ==
1217e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptNextKernelEntry(gpt, &start, &size));
1218e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1219e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1220b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1221b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1222e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int GptUpdateTest(void)
1223e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1224e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1225e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e = (GptEntry *)(gpt->primary_entries);
1226e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e2 = (GptEntry *)(gpt->secondary_entries);
1227e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	uint64_t start, size;
1228e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1229e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Tries=nonzero is attempted just like success, but tries=0 isn't */
1230e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1231e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e + KERNEL_A, 1, 4, 1, 0);
1232e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e + KERNEL_B, 1, 3, 0, 2);
1233e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	FillEntry(e + KERNEL_X, 1, 2, 0, 2);
1234e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	RefreshCrc32(gpt);
1235e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptInit(gpt);
1236e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->modified = 0;  /* Nothing modified yet */
1237e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1238e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Successful kernel */
1239e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1240e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_A == gpt->current_kernel);
1241e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1242e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1243e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1244e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e2 + KERNEL_A));
1245e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(4 == GetEntryPriority(e2 + KERNEL_A));
1246e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e2 + KERNEL_A));
1247e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Trying successful kernel changes nothing */
1248e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1249e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1250e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1251e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1252e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->modified);
1253e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Marking it bad also does not update it. */
1254e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1255e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntrySuccessful(e + KERNEL_A));
1256e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(4 == GetEntryPriority(e + KERNEL_A));
1257e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e + KERNEL_A));
1258e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == gpt->modified);
1259e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1260e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Kernel with tries */
1261e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1262e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_B == gpt->current_kernel);
1263e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1264e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(3 == GetEntryPriority(e + KERNEL_B));
1265e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryTries(e + KERNEL_B));
1266e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Marking it bad clears it */
1267e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
1268e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e + KERNEL_B));
1269e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryPriority(e + KERNEL_B));
1270e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e + KERNEL_B));
1271e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Which affects both copies of the partition entries */
1272e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_B));
1273e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryPriority(e2 + KERNEL_B));
1274e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e2 + KERNEL_B));
1275e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* And that's caused the GPT to need updating */
1276e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0x0F == gpt->modified);
1277e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1278e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Another kernel with tries */
1279e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size));
1280e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(KERNEL_X == gpt->current_kernel);
1281e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1282e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1283e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryTries(e + KERNEL_X));
1284e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Trying it uses up a try */
1285e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1286e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1287e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryPriority(e + KERNEL_X));
1288e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntryTries(e + KERNEL_X));
1289e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e2 + KERNEL_X));
1290e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(2 == GetEntryPriority(e2 + KERNEL_X));
1291e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(1 == GetEntryTries(e2 + KERNEL_X));
1292e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* Trying it again marks it inactive */
1293e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_SUCCESS == GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_TRY));
1294e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntrySuccessful(e + KERNEL_X));
1295e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryPriority(e + KERNEL_X));
1296e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(0 == GetEntryTries(e + KERNEL_X));
1297e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
12980bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	/* Can't update if entry isn't a kernel, or there isn't an entry */
12990bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Memcpy(&e[KERNEL_X].type, &guid_rootfs, sizeof(guid_rootfs));
13000bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
13010bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
13020bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->current_kernel = CGPT_KERNEL_ENTRY_NOT_FOUND;
13030bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
13040bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	       GptUpdateKernelEntry(gpt, GPT_UPDATE_ENTRY_BAD));
13050bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
13060bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
1307e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
13083dcf9dce04301d6d735f265652625fffb6758430Randall Spangler}
1309b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1310e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/*
1311e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns
1312e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler * GPT_ERROR_INVALID_UPDATE_TYPE.
1313e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler */
1314e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int UpdateInvalidKernelTypeTest(void)
1315e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1316e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1317e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1318e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	BuildTestGptData(gpt);
1319e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* anything, but not CGPT_KERNEL_ENTRY_NOT_FOUND */
1320e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	gpt->current_kernel = 0;
1321e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	/* any invalid update_type value */
1322e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	EXPECT(GPT_ERROR_INVALID_UPDATE_TYPE ==
1323e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	       GptUpdateKernelEntry(gpt, 99));
1324e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1325e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1326b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo}
1327b17db3c4b9e7051e51af72bfd404d3d243b44f5cLouis Yung-Chieh Lo
1328e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler/* Test duplicate UniqueGuids can be detected. */
1329e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerstatic int DuplicateUniqueGuidTest(void)
1330e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1331e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptData *gpt = GetEmptyGptData();
1332e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptHeader *h = (GptHeader *)gpt->primary_header;
1333e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	GptEntry *e = (GptEntry *)gpt->primary_entries;
1334e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i, j;
1335e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1336e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
1337e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int duplicate;
1338e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		struct {
1339e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint64_t starting_lba;
1340e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint64_t ending_lba;
1341e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint32_t type_guid;
1342e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			uint32_t unique_guid;
1343e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		} entries[16];   /* enough for testing. */
1344e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} cases[] = {
1345e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{100, 109, 1, 1},
1346e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {110, 119, 2, 2},
1347e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {120, 129, 3, 3},
1348e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {130, 139, 4, 4},
1349e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			}},
1350e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_SUCCESS, {{100, 109, 1, 1},
1351e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {110, 119, 1, 2},
1352e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {120, 129, 2, 3},
1353e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			       {130, 139, 2, 4},
1354e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			}},
1355e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1356e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {110, 119, 2, 2},
1357e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {120, 129, 3, 1},
1358e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {130, 139, 4, 4},
1359e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			}},
1360e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{GPT_ERROR_DUP_GUID, {{100, 109, 1, 1},
1361e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {110, 119, 1, 2},
1362e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {120, 129, 2, 3},
1363e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				      {130, 139, 2, 2},
1364e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			}},
1365e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
1366e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1367e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < ARRAY_SIZE(cases); ++i) {
1368e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		BuildTestGptData(gpt);
1369e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		ZeroEntries(gpt);
1370e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		for(j = 0; j < ARRAY_SIZE(cases[0].entries); ++j) {
1371e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			if (!cases[i].entries[j].starting_lba)
1372e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				break;
1373e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1374e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			e[j].starting_lba = cases[i].entries[j].starting_lba;
1375e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			e[j].ending_lba = cases[i].entries[j].ending_lba;
1376e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			SetGuid(&e[j].type, cases[i].entries[j].type_guid);
1377e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			SetGuid(&e[j].unique, cases[i].entries[j].unique_guid);
1378e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		}
1379e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		RefreshCrc32(gpt);
1380e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1381e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		EXPECT(cases[i].duplicate == CheckEntries(e, h));
1382e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
1383e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1384e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return TEST_OK;
1385aa8eda4f97f43a51bfec4fc096635565617a89e0Bill Richardson}
1386aa8eda4f97f43a51bfec4fc096635565617a89e0Bill Richardson
13870bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler/* Test getting the current kernel GUID */
13880bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spanglerstatic int GetKernelGuidTest(void)
13890bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler{
13900bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptData *gpt = GetEmptyGptData();
13910bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GptEntry *e = (GptEntry *)gpt->primary_entries;
13920bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	Guid g;
13930bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
13940bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	BuildTestGptData(gpt);
13950bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->current_kernel = 0;
13960bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GetCurrentKernelUniqueGuid(gpt, &g);
13970bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(!Memcmp(&g, &e[0].unique, sizeof(Guid)));
13980bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	gpt->current_kernel = 1;
13990bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	GetCurrentKernelUniqueGuid(gpt, &g);
14000bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(!Memcmp(&g, &e[1].unique, sizeof(Guid)));
14010bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14020bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	return TEST_OK;
14030bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler}
14040bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14050bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler/* Test getting GPT error text strings */
14060bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spanglerstatic int ErrorTextTest(void)
14070bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler{
14080bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	int i;
14090bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14100bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	/* Known errors are not unknown */
14110bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	for (i = 0; i < GPT_ERROR_COUNT; i++) {
14120bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler		EXPECT(GptErrorText(i));
14130bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler		EXPECT(strcmp(GptErrorText(i), "Unknown"));
14140bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	}
14150bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14160bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	/* But other error values are */
14170bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	EXPECT(!strcmp(GptErrorText(GPT_ERROR_COUNT), "Unknown"));
14180bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14190bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler	return TEST_OK;
14200bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler}
14210bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler
14226ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyenstatic int CheckHeaderOffDevice()
14236ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen{
14246ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	GptData* gpt = GetEmptyGptData();
14256ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	BuildTestGptData(gpt);
14266ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14276ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	GptHeader* primary_header = (GptHeader*)gpt->primary_header;
14286ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	primary_header->first_usable_lba = 0;
14296ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
14306ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// GPT is stored on the same device so first usable lba should not
14316ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// start at 0.
1432b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1433b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, 0));
14346ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// But off device, it is okay to accept this GPT header.
1435b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1436b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14376ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14386ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	BuildTestGptData(gpt);
14396ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	primary_header->number_of_entries = 100;
14406ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
14416ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// Normally, number of entries is 128. So this should fail.
1442b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1443b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, 0));
14446ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// But off device, it is okay.
1445b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1446b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14476ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14486ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	primary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
14496ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
14506ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// However, too few entries is not good.
1451b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(primary_header, 0, gpt->streaming_drive_sectors,
1452b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14536ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14546ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	// Repeat for secondary header.
14556ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	BuildTestGptData(gpt);
14566ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	GptHeader* secondary_header = (GptHeader*)gpt->secondary_header;
14576ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	secondary_header->first_usable_lba = 0;
14586ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
1459b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1460b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, 0));
1461b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1462b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14636ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14646ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	BuildTestGptData(gpt);
14656ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	secondary_header->number_of_entries = 100;
14663200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen	/* Because we change number of entries, we need to also update entrie_lba. */
14673200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen	secondary_header->entries_lba = secondary_header->my_lba -
14683200401242aec1521e7c4a8b1906366fcabfb1a2Nam T. Nguyen		CalculateEntriesSectors(secondary_header);
14696ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
1470b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1471b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, 0));
1472b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(0 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1473b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14746ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14756ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	secondary_header->number_of_entries = MIN_NUMBER_OF_ENTRIES - 1;
14766ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	RefreshCrc32(gpt);
1477b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg	EXPECT(1 == CheckHeader(secondary_header, 1, gpt->streaming_drive_sectors,
1478b3d38f5c620da89662deb1a08971c5025d6c1132Dan Ehrenberg		gpt->gpt_drive_sectors, GPT_FLAG_EXTERNAL));
14796ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
14806ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen	return TEST_OK;
14816ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen}
14826ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen
1483e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spanglerint main(int argc, char *argv[])
1484e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler{
1485e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int i;
1486e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	int error_count = 0;
1487e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	struct {
1488e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		char *name;
1489e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		test_func fp;
1490e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		int retval;
1491e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	} test_cases[] = {
1492e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(StructSizeTest), },
1493e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(TestBuildTestGptData), },
1494e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(ParameterTests), },
1495e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(HeaderCrcTest), },
14960bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler		{ TEST_CASE(HeaderSameTest), },
1497e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(SignatureTest), },
1498e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(RevisionTest), },
1499e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(SizeTest), },
1500e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(CrcFieldTest), },
1501e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(ReservedFieldsTest), },
1502e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(SizeOfPartitionEntryTest), },
1503e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(NumberOfPartitionEntriesTest), },
1504e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(MyLbaTest), },
1505e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(FirstUsableLbaAndLastUsableLbaTest), },
1506e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(EntriesCrcTest), },
1507e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(ValidEntryTest), },
1508e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(OverlappedPartitionTest), },
1509e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(SanityCheckTest), },
1510e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(NoValidKernelEntryTest), },
1511e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(EntryAttributeGetSetTest), },
1512e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(EntryTypeTest), },
1513e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(GetNextNormalTest), },
1514e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(GetNextPrioTest), },
1515e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(GetNextTriesTest), },
1516e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(GptUpdateTest), },
1517e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(UpdateInvalidKernelTypeTest), },
1518e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(DuplicateUniqueGuidTest), },
1519e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		{ TEST_CASE(TestCrc32TestVectors), },
15200bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler		{ TEST_CASE(GetKernelGuidTest), },
15210bda13f5154afc8068e7d2d4563ff20b152f1c87Randall Spangler		{ TEST_CASE(ErrorTextTest), },
15226ee52d9a929d00e871e7316240b54f381146fbc6Nam T. Nguyen		{ TEST_CASE(CheckHeaderOffDevice), },
1523e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	};
1524e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1525e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1526e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		printf("Running %s() ...\n", test_cases[i].name);
1527e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		test_cases[i].retval = test_cases[i].fp();
1528e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		if (test_cases[i].retval) {
1529e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			printf(COL_RED "[ERROR]\n\n" COL_STOP);
1530e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			++error_count;
1531e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		} else {
1532e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			printf(COL_GREEN "[PASS]\n\n" COL_STOP);
1533e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		}
1534e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
1535e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1536e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	if (error_count) {
1537e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		printf("\n------------------------------------------------\n");
1538e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		printf(COL_RED "The following %d test cases are failed:\n"
1539e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		       COL_STOP, error_count);
1540e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i) {
1541e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler			if (test_cases[i].retval)
1542e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler				printf("  %s()\n", test_cases[i].name);
1543e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler		}
1544e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	}
1545e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler
1546e9213a7c133681d6f565adbf218bafa7a3115c22Randall Spangler	return error_count ? 1 : 0;
15474bbf21e47663914d355941ff61fcbf262b4085acLouis Yung-Chieh Lo}
1548