1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2010 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker *
5*8617a60dSAndroid Build Coastguard Worker * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
6*8617a60dSAndroid Build Coastguard Worker * files for more details.
7*8617a60dSAndroid Build Coastguard Worker */
8*8617a60dSAndroid Build Coastguard Worker
9*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
10*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
11*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
12*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
13*8617a60dSAndroid Build Coastguard Worker #include <linux/major.h>
14*8617a60dSAndroid Build Coastguard Worker #include <mtd/mtd-user.h>
15*8617a60dSAndroid Build Coastguard Worker #endif
16*8617a60dSAndroid Build Coastguard Worker #include <stdarg.h>
17*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
18*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
19*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
20*8617a60dSAndroid Build Coastguard Worker #include <string.h>
21*8617a60dSAndroid Build Coastguard Worker #include <sys/ioctl.h>
22*8617a60dSAndroid Build Coastguard Worker #include <sys/mount.h>
23*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
24*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
25*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
26*8617a60dSAndroid Build Coastguard Worker
27*8617a60dSAndroid Build Coastguard Worker #include "cgpt.h"
28*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
29*8617a60dSAndroid Build Coastguard Worker #include "crc32.h"
30*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
31*8617a60dSAndroid Build Coastguard Worker
32*8617a60dSAndroid Build Coastguard Worker static const char kErrorTag[] = "ERROR";
33*8617a60dSAndroid Build Coastguard Worker static const char kWarningTag[] = "WARNING";
34*8617a60dSAndroid Build Coastguard Worker
LogToStderr(const char * tag,const char * format,va_list ap)35*8617a60dSAndroid Build Coastguard Worker static void LogToStderr(const char *tag, const char *format, va_list ap) {
36*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "%s: ", tag);
37*8617a60dSAndroid Build Coastguard Worker vfprintf(stderr, format, ap);
38*8617a60dSAndroid Build Coastguard Worker }
39*8617a60dSAndroid Build Coastguard Worker
Error(const char * format,...)40*8617a60dSAndroid Build Coastguard Worker void Error(const char *format, ...) {
41*8617a60dSAndroid Build Coastguard Worker va_list ap;
42*8617a60dSAndroid Build Coastguard Worker va_start(ap, format);
43*8617a60dSAndroid Build Coastguard Worker LogToStderr(kErrorTag, format, ap);
44*8617a60dSAndroid Build Coastguard Worker va_end(ap);
45*8617a60dSAndroid Build Coastguard Worker }
46*8617a60dSAndroid Build Coastguard Worker
Warning(const char * format,...)47*8617a60dSAndroid Build Coastguard Worker void Warning(const char *format, ...) {
48*8617a60dSAndroid Build Coastguard Worker va_list ap;
49*8617a60dSAndroid Build Coastguard Worker va_start(ap, format);
50*8617a60dSAndroid Build Coastguard Worker LogToStderr(kWarningTag, format, ap);
51*8617a60dSAndroid Build Coastguard Worker va_end(ap);
52*8617a60dSAndroid Build Coastguard Worker }
53*8617a60dSAndroid Build Coastguard Worker
check_int_parse(char option,const char * buf)54*8617a60dSAndroid Build Coastguard Worker int check_int_parse(char option, const char *buf) {
55*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (buf && *buf)) {
56*8617a60dSAndroid Build Coastguard Worker Error("invalid argument to -%c: \"%s\"\n", option, optarg);
57*8617a60dSAndroid Build Coastguard Worker return 1;
58*8617a60dSAndroid Build Coastguard Worker }
59*8617a60dSAndroid Build Coastguard Worker return 0;
60*8617a60dSAndroid Build Coastguard Worker }
61*8617a60dSAndroid Build Coastguard Worker
check_int_limit(char option,int val,int low,int high)62*8617a60dSAndroid Build Coastguard Worker int check_int_limit(char option, int val, int low, int high) {
63*8617a60dSAndroid Build Coastguard Worker if (val < low || val > high) {
64*8617a60dSAndroid Build Coastguard Worker Error("value for -%c must be between %d and %d", option, low, high);
65*8617a60dSAndroid Build Coastguard Worker return 1;
66*8617a60dSAndroid Build Coastguard Worker }
67*8617a60dSAndroid Build Coastguard Worker return 0;
68*8617a60dSAndroid Build Coastguard Worker }
69*8617a60dSAndroid Build Coastguard Worker
CheckValid(const struct drive * drive)70*8617a60dSAndroid Build Coastguard Worker int CheckValid(const struct drive *drive) {
71*8617a60dSAndroid Build Coastguard Worker if ((drive->gpt.valid_headers != MASK_BOTH) ||
72*8617a60dSAndroid Build Coastguard Worker (drive->gpt.valid_entries != MASK_BOTH)) {
73*8617a60dSAndroid Build Coastguard Worker Warning("One of the GPT headers/entries is invalid\n\n");
74*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
75*8617a60dSAndroid Build Coastguard Worker }
76*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
77*8617a60dSAndroid Build Coastguard Worker }
78*8617a60dSAndroid Build Coastguard Worker
Load(struct drive * drive,uint8_t * buf,const uint64_t sector,const uint64_t sector_bytes,const uint64_t sector_count)79*8617a60dSAndroid Build Coastguard Worker int Load(struct drive *drive, uint8_t *buf,
80*8617a60dSAndroid Build Coastguard Worker const uint64_t sector,
81*8617a60dSAndroid Build Coastguard Worker const uint64_t sector_bytes,
82*8617a60dSAndroid Build Coastguard Worker const uint64_t sector_count) {
83*8617a60dSAndroid Build Coastguard Worker int count; /* byte count to read */
84*8617a60dSAndroid Build Coastguard Worker int nread;
85*8617a60dSAndroid Build Coastguard Worker
86*8617a60dSAndroid Build Coastguard Worker require(buf);
87*8617a60dSAndroid Build Coastguard Worker if (!sector_count || !sector_bytes) {
88*8617a60dSAndroid Build Coastguard Worker Error("%s() failed at line %d: sector_count=%" PRIu64 ", sector_bytes=%" PRIu64 "\n",
89*8617a60dSAndroid Build Coastguard Worker __FUNCTION__, __LINE__, sector_count, sector_bytes);
90*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
91*8617a60dSAndroid Build Coastguard Worker }
92*8617a60dSAndroid Build Coastguard Worker /* Make sure that sector_bytes * sector_count doesn't roll over. */
93*8617a60dSAndroid Build Coastguard Worker if (sector_bytes > (UINT64_MAX / sector_count)) {
94*8617a60dSAndroid Build Coastguard Worker Error("%s() failed at line %d: sector_count=%" PRIu64 ", sector_bytes=%" PRIu64 "\n",
95*8617a60dSAndroid Build Coastguard Worker __FUNCTION__, __LINE__, sector_count, sector_bytes);
96*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
97*8617a60dSAndroid Build Coastguard Worker }
98*8617a60dSAndroid Build Coastguard Worker count = sector_bytes * sector_count;
99*8617a60dSAndroid Build Coastguard Worker
100*8617a60dSAndroid Build Coastguard Worker if (-1 == lseek(drive->fd, sector * sector_bytes, SEEK_SET)) {
101*8617a60dSAndroid Build Coastguard Worker Error("Can't seek: %s\n", strerror(errno));
102*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
103*8617a60dSAndroid Build Coastguard Worker }
104*8617a60dSAndroid Build Coastguard Worker
105*8617a60dSAndroid Build Coastguard Worker nread = read(drive->fd, buf, count);
106*8617a60dSAndroid Build Coastguard Worker if (nread < count) {
107*8617a60dSAndroid Build Coastguard Worker Error("Can't read enough: %d, not %d\n", nread, count);
108*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
109*8617a60dSAndroid Build Coastguard Worker }
110*8617a60dSAndroid Build Coastguard Worker
111*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
112*8617a60dSAndroid Build Coastguard Worker }
113*8617a60dSAndroid Build Coastguard Worker
114*8617a60dSAndroid Build Coastguard Worker
ReadPMBR(struct drive * drive)115*8617a60dSAndroid Build Coastguard Worker int ReadPMBR(struct drive *drive) {
116*8617a60dSAndroid Build Coastguard Worker if (-1 == lseek(drive->fd, 0, SEEK_SET))
117*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
118*8617a60dSAndroid Build Coastguard Worker
119*8617a60dSAndroid Build Coastguard Worker int nread = read(drive->fd, &drive->pmbr, sizeof(struct pmbr));
120*8617a60dSAndroid Build Coastguard Worker if (nread != sizeof(struct pmbr))
121*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
122*8617a60dSAndroid Build Coastguard Worker
123*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
124*8617a60dSAndroid Build Coastguard Worker }
125*8617a60dSAndroid Build Coastguard Worker
WritePMBR(struct drive * drive)126*8617a60dSAndroid Build Coastguard Worker int WritePMBR(struct drive *drive) {
127*8617a60dSAndroid Build Coastguard Worker if (-1 == lseek(drive->fd, 0, SEEK_SET))
128*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
129*8617a60dSAndroid Build Coastguard Worker
130*8617a60dSAndroid Build Coastguard Worker int nwrote = write(drive->fd, &drive->pmbr, sizeof(struct pmbr));
131*8617a60dSAndroid Build Coastguard Worker if (nwrote != sizeof(struct pmbr))
132*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
133*8617a60dSAndroid Build Coastguard Worker
134*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
135*8617a60dSAndroid Build Coastguard Worker }
136*8617a60dSAndroid Build Coastguard Worker
Save(struct drive * drive,const uint8_t * buf,const uint64_t sector,const uint64_t sector_bytes,const uint64_t sector_count)137*8617a60dSAndroid Build Coastguard Worker int Save(struct drive *drive, const uint8_t *buf,
138*8617a60dSAndroid Build Coastguard Worker const uint64_t sector,
139*8617a60dSAndroid Build Coastguard Worker const uint64_t sector_bytes,
140*8617a60dSAndroid Build Coastguard Worker const uint64_t sector_count) {
141*8617a60dSAndroid Build Coastguard Worker int count; /* byte count to write */
142*8617a60dSAndroid Build Coastguard Worker int nwrote;
143*8617a60dSAndroid Build Coastguard Worker
144*8617a60dSAndroid Build Coastguard Worker require(buf);
145*8617a60dSAndroid Build Coastguard Worker count = sector_bytes * sector_count;
146*8617a60dSAndroid Build Coastguard Worker
147*8617a60dSAndroid Build Coastguard Worker if (-1 == lseek(drive->fd, sector * sector_bytes, SEEK_SET))
148*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
149*8617a60dSAndroid Build Coastguard Worker
150*8617a60dSAndroid Build Coastguard Worker nwrote = write(drive->fd, buf, count);
151*8617a60dSAndroid Build Coastguard Worker if (nwrote < count)
152*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
153*8617a60dSAndroid Build Coastguard Worker
154*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
155*8617a60dSAndroid Build Coastguard Worker }
156*8617a60dSAndroid Build Coastguard Worker
GptLoad(struct drive * drive,uint32_t sector_bytes)157*8617a60dSAndroid Build Coastguard Worker static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
158*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes = sector_bytes;
159*8617a60dSAndroid Build Coastguard Worker if (drive->size % drive->gpt.sector_bytes) {
160*8617a60dSAndroid Build Coastguard Worker Error("Media size (%llu) is not a multiple of sector size(%d)\n",
161*8617a60dSAndroid Build Coastguard Worker (long long unsigned int)drive->size, drive->gpt.sector_bytes);
162*8617a60dSAndroid Build Coastguard Worker return -1;
163*8617a60dSAndroid Build Coastguard Worker }
164*8617a60dSAndroid Build Coastguard Worker drive->gpt.streaming_drive_sectors = drive->size / drive->gpt.sector_bytes;
165*8617a60dSAndroid Build Coastguard Worker
166*8617a60dSAndroid Build Coastguard Worker drive->gpt.primary_header = malloc(drive->gpt.sector_bytes);
167*8617a60dSAndroid Build Coastguard Worker drive->gpt.secondary_header = malloc(drive->gpt.sector_bytes);
168*8617a60dSAndroid Build Coastguard Worker drive->gpt.primary_entries = malloc(GPT_ENTRIES_ALLOC_SIZE);
169*8617a60dSAndroid Build Coastguard Worker drive->gpt.secondary_entries = malloc(GPT_ENTRIES_ALLOC_SIZE);
170*8617a60dSAndroid Build Coastguard Worker if (!drive->gpt.primary_header || !drive->gpt.secondary_header ||
171*8617a60dSAndroid Build Coastguard Worker !drive->gpt.primary_entries || !drive->gpt.secondary_entries)
172*8617a60dSAndroid Build Coastguard Worker return -1;
173*8617a60dSAndroid Build Coastguard Worker
174*8617a60dSAndroid Build Coastguard Worker /* TODO(namnguyen): Remove this and totally trust gpt_drive_sectors. */
175*8617a60dSAndroid Build Coastguard Worker if (!(drive->gpt.flags & GPT_FLAG_EXTERNAL)) {
176*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors = drive->gpt.streaming_drive_sectors;
177*8617a60dSAndroid Build Coastguard Worker } /* Else, we trust gpt.gpt_drive_sectors. */
178*8617a60dSAndroid Build Coastguard Worker
179*8617a60dSAndroid Build Coastguard Worker // Read the data.
180*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Load(drive, drive->gpt.primary_header,
181*8617a60dSAndroid Build Coastguard Worker GPT_PMBR_SECTORS,
182*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
183*8617a60dSAndroid Build Coastguard Worker Error("Cannot read primary GPT header\n");
184*8617a60dSAndroid Build Coastguard Worker return -1;
185*8617a60dSAndroid Build Coastguard Worker }
186*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Load(drive, drive->gpt.secondary_header,
187*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS,
188*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
189*8617a60dSAndroid Build Coastguard Worker Error("Cannot read secondary GPT header\n");
190*8617a60dSAndroid Build Coastguard Worker return -1;
191*8617a60dSAndroid Build Coastguard Worker }
192*8617a60dSAndroid Build Coastguard Worker GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
193*8617a60dSAndroid Build Coastguard Worker if (CheckHeader(primary_header, 0, drive->gpt.streaming_drive_sectors,
194*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors,
195*8617a60dSAndroid Build Coastguard Worker drive->gpt.flags,
196*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes) == 0) {
197*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Load(drive, drive->gpt.primary_entries,
198*8617a60dSAndroid Build Coastguard Worker primary_header->entries_lba,
199*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes,
200*8617a60dSAndroid Build Coastguard Worker CalculateEntriesSectors(primary_header,
201*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes))) {
202*8617a60dSAndroid Build Coastguard Worker Error("Cannot read primary partition entry array\n");
203*8617a60dSAndroid Build Coastguard Worker return -1;
204*8617a60dSAndroid Build Coastguard Worker }
205*8617a60dSAndroid Build Coastguard Worker } else {
206*8617a60dSAndroid Build Coastguard Worker Warning("Primary GPT header is %s\n",
207*8617a60dSAndroid Build Coastguard Worker memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
208*8617a60dSAndroid Build Coastguard Worker GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
209*8617a60dSAndroid Build Coastguard Worker }
210*8617a60dSAndroid Build Coastguard Worker GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
211*8617a60dSAndroid Build Coastguard Worker if (CheckHeader(secondary_header, 1, drive->gpt.streaming_drive_sectors,
212*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors,
213*8617a60dSAndroid Build Coastguard Worker drive->gpt.flags,
214*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes) == 0) {
215*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Load(drive, drive->gpt.secondary_entries,
216*8617a60dSAndroid Build Coastguard Worker secondary_header->entries_lba,
217*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes,
218*8617a60dSAndroid Build Coastguard Worker CalculateEntriesSectors(secondary_header,
219*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes))) {
220*8617a60dSAndroid Build Coastguard Worker Error("Cannot read secondary partition entry array\n");
221*8617a60dSAndroid Build Coastguard Worker return -1;
222*8617a60dSAndroid Build Coastguard Worker }
223*8617a60dSAndroid Build Coastguard Worker } else {
224*8617a60dSAndroid Build Coastguard Worker Warning("Secondary GPT header is %s\n",
225*8617a60dSAndroid Build Coastguard Worker memcmp(primary_header->signature, GPT_HEADER_SIGNATURE_IGNORED,
226*8617a60dSAndroid Build Coastguard Worker GPT_HEADER_SIGNATURE_SIZE) ? "invalid" : "being ignored");
227*8617a60dSAndroid Build Coastguard Worker }
228*8617a60dSAndroid Build Coastguard Worker return 0;
229*8617a60dSAndroid Build Coastguard Worker }
230*8617a60dSAndroid Build Coastguard Worker
GptSave(struct drive * drive)231*8617a60dSAndroid Build Coastguard Worker static int GptSave(struct drive *drive) {
232*8617a60dSAndroid Build Coastguard Worker int errors = 0;
233*8617a60dSAndroid Build Coastguard Worker
234*8617a60dSAndroid Build Coastguard Worker if (!(drive->gpt.ignored & MASK_PRIMARY)) {
235*8617a60dSAndroid Build Coastguard Worker if (drive->gpt.modified & GPT_MODIFIED_HEADER1) {
236*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Save(drive, drive->gpt.primary_header,
237*8617a60dSAndroid Build Coastguard Worker GPT_PMBR_SECTORS,
238*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
239*8617a60dSAndroid Build Coastguard Worker errors++;
240*8617a60dSAndroid Build Coastguard Worker Error("Cannot write primary header: %s\n", strerror(errno));
241*8617a60dSAndroid Build Coastguard Worker }
242*8617a60dSAndroid Build Coastguard Worker }
243*8617a60dSAndroid Build Coastguard Worker GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
244*8617a60dSAndroid Build Coastguard Worker if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1) {
245*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Save(drive, drive->gpt.primary_entries,
246*8617a60dSAndroid Build Coastguard Worker primary_header->entries_lba,
247*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes,
248*8617a60dSAndroid Build Coastguard Worker CalculateEntriesSectors(primary_header,
249*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes))) {
250*8617a60dSAndroid Build Coastguard Worker errors++;
251*8617a60dSAndroid Build Coastguard Worker Error("Cannot write primary entries: %s\n", strerror(errno));
252*8617a60dSAndroid Build Coastguard Worker }
253*8617a60dSAndroid Build Coastguard Worker }
254*8617a60dSAndroid Build Coastguard Worker
255*8617a60dSAndroid Build Coastguard Worker // Sync primary GPT before touching secondary so one is always valid.
256*8617a60dSAndroid Build Coastguard Worker if (drive->gpt.modified & (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1))
257*8617a60dSAndroid Build Coastguard Worker if (fsync(drive->fd) < 0 && errno == EIO) {
258*8617a60dSAndroid Build Coastguard Worker errors++;
259*8617a60dSAndroid Build Coastguard Worker Error("I/O error when trying to write primary GPT\n");
260*8617a60dSAndroid Build Coastguard Worker }
261*8617a60dSAndroid Build Coastguard Worker }
262*8617a60dSAndroid Build Coastguard Worker
263*8617a60dSAndroid Build Coastguard Worker // Only start writing secondary GPT if primary was written correctly.
264*8617a60dSAndroid Build Coastguard Worker if (!errors && !(drive->gpt.ignored & MASK_SECONDARY)) {
265*8617a60dSAndroid Build Coastguard Worker if (drive->gpt.modified & GPT_MODIFIED_HEADER2) {
266*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Save(drive, drive->gpt.secondary_header,
267*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors - GPT_PMBR_SECTORS,
268*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
269*8617a60dSAndroid Build Coastguard Worker errors++;
270*8617a60dSAndroid Build Coastguard Worker Error("Cannot write secondary header: %s\n", strerror(errno));
271*8617a60dSAndroid Build Coastguard Worker }
272*8617a60dSAndroid Build Coastguard Worker }
273*8617a60dSAndroid Build Coastguard Worker GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
274*8617a60dSAndroid Build Coastguard Worker if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2) {
275*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != Save(drive, drive->gpt.secondary_entries,
276*8617a60dSAndroid Build Coastguard Worker secondary_header->entries_lba,
277*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes,
278*8617a60dSAndroid Build Coastguard Worker CalculateEntriesSectors(secondary_header,
279*8617a60dSAndroid Build Coastguard Worker drive->gpt.sector_bytes))) {
280*8617a60dSAndroid Build Coastguard Worker errors++;
281*8617a60dSAndroid Build Coastguard Worker Error("Cannot write secondary entries: %s\n", strerror(errno));
282*8617a60dSAndroid Build Coastguard Worker }
283*8617a60dSAndroid Build Coastguard Worker }
284*8617a60dSAndroid Build Coastguard Worker }
285*8617a60dSAndroid Build Coastguard Worker
286*8617a60dSAndroid Build Coastguard Worker return errors ? -1 : 0;
287*8617a60dSAndroid Build Coastguard Worker }
288*8617a60dSAndroid Build Coastguard Worker
289*8617a60dSAndroid Build Coastguard Worker /*
290*8617a60dSAndroid Build Coastguard Worker * Query drive size and bytes per sector. Return zero on success. On error,
291*8617a60dSAndroid Build Coastguard Worker * -1 is returned and errno is set appropriately.
292*8617a60dSAndroid Build Coastguard Worker */
ObtainDriveSize(int fd,uint64_t * size,uint32_t * sector_bytes)293*8617a60dSAndroid Build Coastguard Worker static int ObtainDriveSize(int fd, uint64_t* size, uint32_t* sector_bytes) {
294*8617a60dSAndroid Build Coastguard Worker struct stat stat;
295*8617a60dSAndroid Build Coastguard Worker if (fstat(fd, &stat) == -1) {
296*8617a60dSAndroid Build Coastguard Worker return -1;
297*8617a60dSAndroid Build Coastguard Worker }
298*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
299*8617a60dSAndroid Build Coastguard Worker if ((stat.st_mode & S_IFMT) != S_IFREG) {
300*8617a60dSAndroid Build Coastguard Worker if (ioctl(fd, BLKGETSIZE64, size) < 0) {
301*8617a60dSAndroid Build Coastguard Worker return -1;
302*8617a60dSAndroid Build Coastguard Worker }
303*8617a60dSAndroid Build Coastguard Worker if (ioctl(fd, BLKSSZGET, sector_bytes) < 0) {
304*8617a60dSAndroid Build Coastguard Worker return -1;
305*8617a60dSAndroid Build Coastguard Worker }
306*8617a60dSAndroid Build Coastguard Worker } else {
307*8617a60dSAndroid Build Coastguard Worker *sector_bytes = 512; /* bytes */
308*8617a60dSAndroid Build Coastguard Worker *size = stat.st_size;
309*8617a60dSAndroid Build Coastguard Worker }
310*8617a60dSAndroid Build Coastguard Worker #else
311*8617a60dSAndroid Build Coastguard Worker *sector_bytes = 512; /* bytes */
312*8617a60dSAndroid Build Coastguard Worker *size = stat.st_size;
313*8617a60dSAndroid Build Coastguard Worker #endif
314*8617a60dSAndroid Build Coastguard Worker return 0;
315*8617a60dSAndroid Build Coastguard Worker }
316*8617a60dSAndroid Build Coastguard Worker
DriveOpen(const char * drive_path,struct drive * drive,int mode,uint64_t drive_size)317*8617a60dSAndroid Build Coastguard Worker int DriveOpen(const char *drive_path, struct drive *drive, int mode,
318*8617a60dSAndroid Build Coastguard Worker uint64_t drive_size) {
319*8617a60dSAndroid Build Coastguard Worker uint32_t sector_bytes;
320*8617a60dSAndroid Build Coastguard Worker
321*8617a60dSAndroid Build Coastguard Worker require(drive_path);
322*8617a60dSAndroid Build Coastguard Worker require(drive);
323*8617a60dSAndroid Build Coastguard Worker
324*8617a60dSAndroid Build Coastguard Worker // Clear struct for proper error handling.
325*8617a60dSAndroid Build Coastguard Worker memset(drive, 0, sizeof(struct drive));
326*8617a60dSAndroid Build Coastguard Worker
327*8617a60dSAndroid Build Coastguard Worker drive->fd = open(drive_path, mode |
328*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
329*8617a60dSAndroid Build Coastguard Worker O_LARGEFILE |
330*8617a60dSAndroid Build Coastguard Worker #endif
331*8617a60dSAndroid Build Coastguard Worker O_NOFOLLOW);
332*8617a60dSAndroid Build Coastguard Worker if (drive->fd == -1) {
333*8617a60dSAndroid Build Coastguard Worker Error("Can't open %s: %s\n", drive_path, strerror(errno));
334*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
335*8617a60dSAndroid Build Coastguard Worker }
336*8617a60dSAndroid Build Coastguard Worker
337*8617a60dSAndroid Build Coastguard Worker uint64_t gpt_drive_size;
338*8617a60dSAndroid Build Coastguard Worker if (ObtainDriveSize(drive->fd, &gpt_drive_size, §or_bytes) != 0) {
339*8617a60dSAndroid Build Coastguard Worker Error("Can't get drive size and bytes per sector for %s: %s\n",
340*8617a60dSAndroid Build Coastguard Worker drive_path, strerror(errno));
341*8617a60dSAndroid Build Coastguard Worker goto error_close;
342*8617a60dSAndroid Build Coastguard Worker }
343*8617a60dSAndroid Build Coastguard Worker
344*8617a60dSAndroid Build Coastguard Worker drive->gpt.gpt_drive_sectors = gpt_drive_size / sector_bytes;
345*8617a60dSAndroid Build Coastguard Worker if (drive_size == 0) {
346*8617a60dSAndroid Build Coastguard Worker drive->size = gpt_drive_size;
347*8617a60dSAndroid Build Coastguard Worker drive->gpt.flags = 0;
348*8617a60dSAndroid Build Coastguard Worker } else {
349*8617a60dSAndroid Build Coastguard Worker drive->size = drive_size;
350*8617a60dSAndroid Build Coastguard Worker drive->gpt.flags = GPT_FLAG_EXTERNAL;
351*8617a60dSAndroid Build Coastguard Worker }
352*8617a60dSAndroid Build Coastguard Worker
353*8617a60dSAndroid Build Coastguard Worker
354*8617a60dSAndroid Build Coastguard Worker if (GptLoad(drive, sector_bytes)) {
355*8617a60dSAndroid Build Coastguard Worker goto error_close;
356*8617a60dSAndroid Build Coastguard Worker }
357*8617a60dSAndroid Build Coastguard Worker
358*8617a60dSAndroid Build Coastguard Worker // We just load the data. Caller must validate it.
359*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
360*8617a60dSAndroid Build Coastguard Worker
361*8617a60dSAndroid Build Coastguard Worker error_close:
362*8617a60dSAndroid Build Coastguard Worker (void) DriveClose(drive, 0);
363*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
364*8617a60dSAndroid Build Coastguard Worker }
365*8617a60dSAndroid Build Coastguard Worker
366*8617a60dSAndroid Build Coastguard Worker
DriveClose(struct drive * drive,int update_as_needed)367*8617a60dSAndroid Build Coastguard Worker int DriveClose(struct drive *drive, int update_as_needed) {
368*8617a60dSAndroid Build Coastguard Worker int errors = 0;
369*8617a60dSAndroid Build Coastguard Worker
370*8617a60dSAndroid Build Coastguard Worker if (update_as_needed) {
371*8617a60dSAndroid Build Coastguard Worker if (GptSave(drive)) {
372*8617a60dSAndroid Build Coastguard Worker errors++;
373*8617a60dSAndroid Build Coastguard Worker }
374*8617a60dSAndroid Build Coastguard Worker }
375*8617a60dSAndroid Build Coastguard Worker
376*8617a60dSAndroid Build Coastguard Worker free(drive->gpt.primary_header);
377*8617a60dSAndroid Build Coastguard Worker drive->gpt.primary_header = NULL;
378*8617a60dSAndroid Build Coastguard Worker free(drive->gpt.primary_entries);
379*8617a60dSAndroid Build Coastguard Worker drive->gpt.primary_entries = NULL;
380*8617a60dSAndroid Build Coastguard Worker free(drive->gpt.secondary_header);
381*8617a60dSAndroid Build Coastguard Worker drive->gpt.secondary_header = NULL;
382*8617a60dSAndroid Build Coastguard Worker free(drive->gpt.secondary_entries);
383*8617a60dSAndroid Build Coastguard Worker drive->gpt.secondary_entries = NULL;
384*8617a60dSAndroid Build Coastguard Worker
385*8617a60dSAndroid Build Coastguard Worker // Sync early! Only sync file descriptor here, and leave the whole system sync
386*8617a60dSAndroid Build Coastguard Worker // outside cgpt because whole system sync would trigger tons of disk accesses
387*8617a60dSAndroid Build Coastguard Worker // and timeout tests.
388*8617a60dSAndroid Build Coastguard Worker fsync(drive->fd);
389*8617a60dSAndroid Build Coastguard Worker
390*8617a60dSAndroid Build Coastguard Worker close(drive->fd);
391*8617a60dSAndroid Build Coastguard Worker
392*8617a60dSAndroid Build Coastguard Worker return errors ? CGPT_FAILED : CGPT_OK;
393*8617a60dSAndroid Build Coastguard Worker }
394*8617a60dSAndroid Build Coastguard Worker
395*8617a60dSAndroid Build Coastguard Worker
396*8617a60dSAndroid Build Coastguard Worker /* GUID conversion functions. Accepted format:
397*8617a60dSAndroid Build Coastguard Worker *
398*8617a60dSAndroid Build Coastguard Worker * "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
399*8617a60dSAndroid Build Coastguard Worker *
400*8617a60dSAndroid Build Coastguard Worker * Returns CGPT_OK if parsing is successful; otherwise CGPT_FAILED.
401*8617a60dSAndroid Build Coastguard Worker */
StrToGuid(const char * str,Guid * guid)402*8617a60dSAndroid Build Coastguard Worker int StrToGuid(const char *str, Guid *guid) {
403*8617a60dSAndroid Build Coastguard Worker uint32_t time_low;
404*8617a60dSAndroid Build Coastguard Worker uint16_t time_mid;
405*8617a60dSAndroid Build Coastguard Worker uint16_t time_high_and_version;
406*8617a60dSAndroid Build Coastguard Worker unsigned int chunk[11];
407*8617a60dSAndroid Build Coastguard Worker
408*8617a60dSAndroid Build Coastguard Worker if (11 != sscanf(str, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
409*8617a60dSAndroid Build Coastguard Worker chunk+0,
410*8617a60dSAndroid Build Coastguard Worker chunk+1,
411*8617a60dSAndroid Build Coastguard Worker chunk+2,
412*8617a60dSAndroid Build Coastguard Worker chunk+3,
413*8617a60dSAndroid Build Coastguard Worker chunk+4,
414*8617a60dSAndroid Build Coastguard Worker chunk+5,
415*8617a60dSAndroid Build Coastguard Worker chunk+6,
416*8617a60dSAndroid Build Coastguard Worker chunk+7,
417*8617a60dSAndroid Build Coastguard Worker chunk+8,
418*8617a60dSAndroid Build Coastguard Worker chunk+9,
419*8617a60dSAndroid Build Coastguard Worker chunk+10)) {
420*8617a60dSAndroid Build Coastguard Worker printf("FAILED\n");
421*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
422*8617a60dSAndroid Build Coastguard Worker }
423*8617a60dSAndroid Build Coastguard Worker
424*8617a60dSAndroid Build Coastguard Worker time_low = chunk[0] & 0xffffffff;
425*8617a60dSAndroid Build Coastguard Worker time_mid = chunk[1] & 0xffff;
426*8617a60dSAndroid Build Coastguard Worker time_high_and_version = chunk[2] & 0xffff;
427*8617a60dSAndroid Build Coastguard Worker
428*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.time_low = htole32(time_low);
429*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.time_mid = htole16(time_mid);
430*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.time_high_and_version = htole16(time_high_and_version);
431*8617a60dSAndroid Build Coastguard Worker
432*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.clock_seq_high_and_reserved = chunk[3] & 0xff;
433*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.clock_seq_low = chunk[4] & 0xff;
434*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[0] = chunk[5] & 0xff;
435*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[1] = chunk[6] & 0xff;
436*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[2] = chunk[7] & 0xff;
437*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[3] = chunk[8] & 0xff;
438*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[4] = chunk[9] & 0xff;
439*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[5] = chunk[10] & 0xff;
440*8617a60dSAndroid Build Coastguard Worker
441*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
442*8617a60dSAndroid Build Coastguard Worker }
GuidToStr(const Guid * guid,char * str,unsigned int buflen)443*8617a60dSAndroid Build Coastguard Worker void GuidToStr(const Guid *guid, char *str, unsigned int buflen) {
444*8617a60dSAndroid Build Coastguard Worker require(buflen >= GUID_STRLEN);
445*8617a60dSAndroid Build Coastguard Worker require(snprintf(str, buflen,
446*8617a60dSAndroid Build Coastguard Worker "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
447*8617a60dSAndroid Build Coastguard Worker le32toh(guid->u.Uuid.time_low),
448*8617a60dSAndroid Build Coastguard Worker le16toh(guid->u.Uuid.time_mid),
449*8617a60dSAndroid Build Coastguard Worker le16toh(guid->u.Uuid.time_high_and_version),
450*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.clock_seq_high_and_reserved,
451*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.clock_seq_low,
452*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[0], guid->u.Uuid.node[1],
453*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[2], guid->u.Uuid.node[3],
454*8617a60dSAndroid Build Coastguard Worker guid->u.Uuid.node[4], guid->u.Uuid.node[5]) == GUID_STRLEN-1);
455*8617a60dSAndroid Build Coastguard Worker }
456*8617a60dSAndroid Build Coastguard Worker
457*8617a60dSAndroid Build Coastguard Worker /* Convert possibly unterminated UTF16 string to UTF8.
458*8617a60dSAndroid Build Coastguard Worker * Caller must prepare enough space for UTF8, which could be up to
459*8617a60dSAndroid Build Coastguard Worker * twice the byte length of UTF16 string plus the terminating '\0'.
460*8617a60dSAndroid Build Coastguard Worker * See the following table for encoding lengths.
461*8617a60dSAndroid Build Coastguard Worker *
462*8617a60dSAndroid Build Coastguard Worker * Code point UTF16 UTF8
463*8617a60dSAndroid Build Coastguard Worker * 0x0000-0x007F 2 bytes 1 byte
464*8617a60dSAndroid Build Coastguard Worker * 0x0080-0x07FF 2 bytes 2 bytes
465*8617a60dSAndroid Build Coastguard Worker * 0x0800-0xFFFF 2 bytes 3 bytes
466*8617a60dSAndroid Build Coastguard Worker * 0x10000-0x10FFFF 4 bytes 4 bytes
467*8617a60dSAndroid Build Coastguard Worker *
468*8617a60dSAndroid Build Coastguard Worker * This function uses a simple state meachine to convert UTF-16 char(s) to
469*8617a60dSAndroid Build Coastguard Worker * a code point. Once a code point is parsed out, the state machine throws
470*8617a60dSAndroid Build Coastguard Worker * out sequencial UTF-8 chars in one time.
471*8617a60dSAndroid Build Coastguard Worker *
472*8617a60dSAndroid Build Coastguard Worker * Return: CGPT_OK --- all character are converted successfully.
473*8617a60dSAndroid Build Coastguard Worker * CGPT_FAILED --- convert error, i.e. output buffer is too short.
474*8617a60dSAndroid Build Coastguard Worker */
UTF16ToUTF8(const uint16_t * utf16,unsigned int maxinput,uint8_t * utf8,unsigned int maxoutput)475*8617a60dSAndroid Build Coastguard Worker int UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
476*8617a60dSAndroid Build Coastguard Worker uint8_t *utf8, unsigned int maxoutput)
477*8617a60dSAndroid Build Coastguard Worker {
478*8617a60dSAndroid Build Coastguard Worker size_t s16idx, s8idx;
479*8617a60dSAndroid Build Coastguard Worker uint32_t code_point = 0;
480*8617a60dSAndroid Build Coastguard Worker int code_point_ready = 1; // code point is ready to output.
481*8617a60dSAndroid Build Coastguard Worker int retval = CGPT_OK;
482*8617a60dSAndroid Build Coastguard Worker
483*8617a60dSAndroid Build Coastguard Worker if (!utf16 || !maxinput || !utf8 || !maxoutput)
484*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
485*8617a60dSAndroid Build Coastguard Worker
486*8617a60dSAndroid Build Coastguard Worker maxoutput--; /* plan for termination now */
487*8617a60dSAndroid Build Coastguard Worker
488*8617a60dSAndroid Build Coastguard Worker for (s16idx = s8idx = 0;
489*8617a60dSAndroid Build Coastguard Worker s16idx < maxinput && utf16[s16idx] && maxoutput;
490*8617a60dSAndroid Build Coastguard Worker s16idx++) {
491*8617a60dSAndroid Build Coastguard Worker uint16_t codeunit = le16toh(utf16[s16idx]);
492*8617a60dSAndroid Build Coastguard Worker
493*8617a60dSAndroid Build Coastguard Worker if (code_point_ready) {
494*8617a60dSAndroid Build Coastguard Worker if (codeunit >= 0xD800 && codeunit <= 0xDBFF) {
495*8617a60dSAndroid Build Coastguard Worker /* high surrogate, need the low surrogate. */
496*8617a60dSAndroid Build Coastguard Worker code_point_ready = 0;
497*8617a60dSAndroid Build Coastguard Worker code_point = (codeunit & 0x03FF) + 0x0040;
498*8617a60dSAndroid Build Coastguard Worker } else {
499*8617a60dSAndroid Build Coastguard Worker /* BMP char, output it. */
500*8617a60dSAndroid Build Coastguard Worker code_point = codeunit;
501*8617a60dSAndroid Build Coastguard Worker }
502*8617a60dSAndroid Build Coastguard Worker } else {
503*8617a60dSAndroid Build Coastguard Worker /* expect the low surrogate */
504*8617a60dSAndroid Build Coastguard Worker if (codeunit >= 0xDC00 && codeunit <= 0xDFFF) {
505*8617a60dSAndroid Build Coastguard Worker code_point = (code_point << 10) | (codeunit & 0x03FF);
506*8617a60dSAndroid Build Coastguard Worker code_point_ready = 1;
507*8617a60dSAndroid Build Coastguard Worker } else {
508*8617a60dSAndroid Build Coastguard Worker /* the second code unit is NOT the low surrogate. Unexpected. */
509*8617a60dSAndroid Build Coastguard Worker code_point_ready = 0;
510*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
511*8617a60dSAndroid Build Coastguard Worker break;
512*8617a60dSAndroid Build Coastguard Worker }
513*8617a60dSAndroid Build Coastguard Worker }
514*8617a60dSAndroid Build Coastguard Worker
515*8617a60dSAndroid Build Coastguard Worker /* If UTF code point is ready, output it. */
516*8617a60dSAndroid Build Coastguard Worker if (code_point_ready) {
517*8617a60dSAndroid Build Coastguard Worker require(code_point <= 0x10FFFF);
518*8617a60dSAndroid Build Coastguard Worker if (code_point <= 0x7F && maxoutput >= 1) {
519*8617a60dSAndroid Build Coastguard Worker maxoutput -= 1;
520*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = code_point & 0x7F;
521*8617a60dSAndroid Build Coastguard Worker } else if (code_point <= 0x7FF && maxoutput >= 2) {
522*8617a60dSAndroid Build Coastguard Worker maxoutput -= 2;
523*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0xC0 | (code_point >> 6);
524*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | (code_point & 0x3F);
525*8617a60dSAndroid Build Coastguard Worker } else if (code_point <= 0xFFFF && maxoutput >= 3) {
526*8617a60dSAndroid Build Coastguard Worker maxoutput -= 3;
527*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0xE0 | (code_point >> 12);
528*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
529*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | (code_point & 0x3F);
530*8617a60dSAndroid Build Coastguard Worker } else if (code_point <= 0x10FFFF && maxoutput >= 4) {
531*8617a60dSAndroid Build Coastguard Worker maxoutput -= 4;
532*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0xF0 | (code_point >> 18);
533*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | ((code_point >> 12) & 0x3F);
534*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | ((code_point >> 6) & 0x3F);
535*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0x80 | (code_point & 0x3F);
536*8617a60dSAndroid Build Coastguard Worker } else {
537*8617a60dSAndroid Build Coastguard Worker /* buffer underrun */
538*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
539*8617a60dSAndroid Build Coastguard Worker break;
540*8617a60dSAndroid Build Coastguard Worker }
541*8617a60dSAndroid Build Coastguard Worker }
542*8617a60dSAndroid Build Coastguard Worker }
543*8617a60dSAndroid Build Coastguard Worker utf8[s8idx++] = 0;
544*8617a60dSAndroid Build Coastguard Worker return retval;
545*8617a60dSAndroid Build Coastguard Worker }
546*8617a60dSAndroid Build Coastguard Worker
547*8617a60dSAndroid Build Coastguard Worker /* Convert UTF8 string to UTF16. The UTF8 string must be null-terminated.
548*8617a60dSAndroid Build Coastguard Worker * Caller must prepare enough space for UTF16, including a terminating 0x0000.
549*8617a60dSAndroid Build Coastguard Worker * See the following table for encoding lengths. In any case, the caller
550*8617a60dSAndroid Build Coastguard Worker * just needs to prepare the byte length of UTF8 plus the terminating 0x0000.
551*8617a60dSAndroid Build Coastguard Worker *
552*8617a60dSAndroid Build Coastguard Worker * Code point UTF16 UTF8
553*8617a60dSAndroid Build Coastguard Worker * 0x0000-0x007F 2 bytes 1 byte
554*8617a60dSAndroid Build Coastguard Worker * 0x0080-0x07FF 2 bytes 2 bytes
555*8617a60dSAndroid Build Coastguard Worker * 0x0800-0xFFFF 2 bytes 3 bytes
556*8617a60dSAndroid Build Coastguard Worker * 0x10000-0x10FFFF 4 bytes 4 bytes
557*8617a60dSAndroid Build Coastguard Worker *
558*8617a60dSAndroid Build Coastguard Worker * This function converts UTF8 chars to a code point first. Then, convrts it
559*8617a60dSAndroid Build Coastguard Worker * to UTF16 code unit(s).
560*8617a60dSAndroid Build Coastguard Worker *
561*8617a60dSAndroid Build Coastguard Worker * Return: CGPT_OK --- all character are converted successfully.
562*8617a60dSAndroid Build Coastguard Worker * CGPT_FAILED --- convert error, i.e. output buffer is too short.
563*8617a60dSAndroid Build Coastguard Worker */
UTF8ToUTF16(const uint8_t * utf8,uint16_t * utf16,unsigned int maxoutput)564*8617a60dSAndroid Build Coastguard Worker int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput)
565*8617a60dSAndroid Build Coastguard Worker {
566*8617a60dSAndroid Build Coastguard Worker size_t s16idx, s8idx;
567*8617a60dSAndroid Build Coastguard Worker uint32_t code_point = 0;
568*8617a60dSAndroid Build Coastguard Worker unsigned int expected_units = 1;
569*8617a60dSAndroid Build Coastguard Worker unsigned int decoded_units = 1;
570*8617a60dSAndroid Build Coastguard Worker int retval = CGPT_OK;
571*8617a60dSAndroid Build Coastguard Worker
572*8617a60dSAndroid Build Coastguard Worker if (!utf8 || !utf16 || !maxoutput)
573*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
574*8617a60dSAndroid Build Coastguard Worker
575*8617a60dSAndroid Build Coastguard Worker maxoutput--; /* plan for termination */
576*8617a60dSAndroid Build Coastguard Worker
577*8617a60dSAndroid Build Coastguard Worker for (s8idx = s16idx = 0;
578*8617a60dSAndroid Build Coastguard Worker utf8[s8idx] && maxoutput;
579*8617a60dSAndroid Build Coastguard Worker s8idx++) {
580*8617a60dSAndroid Build Coastguard Worker uint8_t code_unit;
581*8617a60dSAndroid Build Coastguard Worker code_unit = utf8[s8idx];
582*8617a60dSAndroid Build Coastguard Worker
583*8617a60dSAndroid Build Coastguard Worker if (expected_units != decoded_units) {
584*8617a60dSAndroid Build Coastguard Worker /* Trailing bytes of multi-byte character */
585*8617a60dSAndroid Build Coastguard Worker if ((code_unit & 0xC0) == 0x80) {
586*8617a60dSAndroid Build Coastguard Worker code_point = (code_point << 6) | (code_unit & 0x3F);
587*8617a60dSAndroid Build Coastguard Worker ++decoded_units;
588*8617a60dSAndroid Build Coastguard Worker } else {
589*8617a60dSAndroid Build Coastguard Worker /* Unexpected code unit. */
590*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
591*8617a60dSAndroid Build Coastguard Worker break;
592*8617a60dSAndroid Build Coastguard Worker }
593*8617a60dSAndroid Build Coastguard Worker } else {
594*8617a60dSAndroid Build Coastguard Worker /* parsing a new code point. */
595*8617a60dSAndroid Build Coastguard Worker decoded_units = 1;
596*8617a60dSAndroid Build Coastguard Worker if (code_unit <= 0x7F) {
597*8617a60dSAndroid Build Coastguard Worker code_point = code_unit;
598*8617a60dSAndroid Build Coastguard Worker expected_units = 1;
599*8617a60dSAndroid Build Coastguard Worker } else if (code_unit <= 0xBF) {
600*8617a60dSAndroid Build Coastguard Worker /* 0x80-0xBF must NOT be the heading byte unit of a new code point. */
601*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
602*8617a60dSAndroid Build Coastguard Worker break;
603*8617a60dSAndroid Build Coastguard Worker } else if (code_unit >= 0xC2 && code_unit <= 0xDF) {
604*8617a60dSAndroid Build Coastguard Worker code_point = code_unit & 0x1F;
605*8617a60dSAndroid Build Coastguard Worker expected_units = 2;
606*8617a60dSAndroid Build Coastguard Worker } else if (code_unit >= 0xE0 && code_unit <= 0xEF) {
607*8617a60dSAndroid Build Coastguard Worker code_point = code_unit & 0x0F;
608*8617a60dSAndroid Build Coastguard Worker expected_units = 3;
609*8617a60dSAndroid Build Coastguard Worker } else if (code_unit >= 0xF0 && code_unit <= 0xF4) {
610*8617a60dSAndroid Build Coastguard Worker code_point = code_unit & 0x07;
611*8617a60dSAndroid Build Coastguard Worker expected_units = 4;
612*8617a60dSAndroid Build Coastguard Worker } else {
613*8617a60dSAndroid Build Coastguard Worker /* illegal code unit: 0xC0-0xC1, 0xF5-0xFF */
614*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
615*8617a60dSAndroid Build Coastguard Worker break;
616*8617a60dSAndroid Build Coastguard Worker }
617*8617a60dSAndroid Build Coastguard Worker }
618*8617a60dSAndroid Build Coastguard Worker
619*8617a60dSAndroid Build Coastguard Worker /* If no more unit is needed, output the UTF16 unit(s). */
620*8617a60dSAndroid Build Coastguard Worker if ((retval == CGPT_OK) &&
621*8617a60dSAndroid Build Coastguard Worker (expected_units == decoded_units)) {
622*8617a60dSAndroid Build Coastguard Worker /* Check if the encoding is the shortest possible UTF-8 sequence. */
623*8617a60dSAndroid Build Coastguard Worker switch (expected_units) {
624*8617a60dSAndroid Build Coastguard Worker case 2:
625*8617a60dSAndroid Build Coastguard Worker if (code_point <= 0x7F) retval = CGPT_FAILED;
626*8617a60dSAndroid Build Coastguard Worker break;
627*8617a60dSAndroid Build Coastguard Worker case 3:
628*8617a60dSAndroid Build Coastguard Worker if (code_point <= 0x7FF) retval = CGPT_FAILED;
629*8617a60dSAndroid Build Coastguard Worker break;
630*8617a60dSAndroid Build Coastguard Worker case 4:
631*8617a60dSAndroid Build Coastguard Worker if (code_point <= 0xFFFF) retval = CGPT_FAILED;
632*8617a60dSAndroid Build Coastguard Worker break;
633*8617a60dSAndroid Build Coastguard Worker }
634*8617a60dSAndroid Build Coastguard Worker if (retval == CGPT_FAILED) break; /* leave immediately */
635*8617a60dSAndroid Build Coastguard Worker
636*8617a60dSAndroid Build Coastguard Worker if ((code_point <= 0xD7FF) ||
637*8617a60dSAndroid Build Coastguard Worker (code_point >= 0xE000 && code_point <= 0xFFFF)) {
638*8617a60dSAndroid Build Coastguard Worker utf16[s16idx++] = code_point;
639*8617a60dSAndroid Build Coastguard Worker maxoutput -= 1;
640*8617a60dSAndroid Build Coastguard Worker } else if (code_point >= 0x10000 && code_point <= 0x10FFFF &&
641*8617a60dSAndroid Build Coastguard Worker maxoutput >= 2) {
642*8617a60dSAndroid Build Coastguard Worker utf16[s16idx++] = 0xD800 | ((code_point >> 10) - 0x0040);
643*8617a60dSAndroid Build Coastguard Worker utf16[s16idx++] = 0xDC00 | (code_point & 0x03FF);
644*8617a60dSAndroid Build Coastguard Worker maxoutput -= 2;
645*8617a60dSAndroid Build Coastguard Worker } else {
646*8617a60dSAndroid Build Coastguard Worker /* Three possibilities fall into here. Both are failure cases.
647*8617a60dSAndroid Build Coastguard Worker * a. surrogate pair (non-BMP characters; 0xD800~0xDFFF)
648*8617a60dSAndroid Build Coastguard Worker * b. invalid code point > 0x10FFFF
649*8617a60dSAndroid Build Coastguard Worker * c. buffer underrun
650*8617a60dSAndroid Build Coastguard Worker */
651*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
652*8617a60dSAndroid Build Coastguard Worker break;
653*8617a60dSAndroid Build Coastguard Worker }
654*8617a60dSAndroid Build Coastguard Worker }
655*8617a60dSAndroid Build Coastguard Worker }
656*8617a60dSAndroid Build Coastguard Worker
657*8617a60dSAndroid Build Coastguard Worker /* A null-terminator shows up before the UTF8 sequence ends. */
658*8617a60dSAndroid Build Coastguard Worker if (expected_units != decoded_units) {
659*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
660*8617a60dSAndroid Build Coastguard Worker }
661*8617a60dSAndroid Build Coastguard Worker
662*8617a60dSAndroid Build Coastguard Worker utf16[s16idx++] = 0;
663*8617a60dSAndroid Build Coastguard Worker return retval;
664*8617a60dSAndroid Build Coastguard Worker }
665*8617a60dSAndroid Build Coastguard Worker
666*8617a60dSAndroid Build Coastguard Worker /* global types to compare against */
667*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_firmware = GPT_ENT_TYPE_CHROMEOS_FIRMWARE;
668*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
669*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS;
670*8617a60dSAndroid Build Coastguard Worker const Guid guid_basic_data = GPT_ENT_TYPE_BASIC_DATA;
671*8617a60dSAndroid Build Coastguard Worker const Guid guid_linux_data = GPT_ENT_TYPE_LINUX_FS;
672*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_reserved = GPT_ENT_TYPE_CHROMEOS_RESERVED;
673*8617a60dSAndroid Build Coastguard Worker const Guid guid_efi = GPT_ENT_TYPE_EFI;
674*8617a60dSAndroid Build Coastguard Worker const Guid guid_unused = GPT_ENT_TYPE_UNUSED;
675*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_minios = GPT_ENT_TYPE_CHROMEOS_MINIOS;
676*8617a60dSAndroid Build Coastguard Worker const Guid guid_chromeos_hibernate = GPT_ENT_TYPE_CHROMEOS_HIBERNATE;
677*8617a60dSAndroid Build Coastguard Worker
678*8617a60dSAndroid Build Coastguard Worker static const struct {
679*8617a60dSAndroid Build Coastguard Worker const Guid *type;
680*8617a60dSAndroid Build Coastguard Worker const char *name;
681*8617a60dSAndroid Build Coastguard Worker const char *description;
682*8617a60dSAndroid Build Coastguard Worker } supported_types[] = {
683*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_firmware, "firmware", "ChromeOS firmware"},
684*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_kernel, "kernel", "ChromeOS kernel"},
685*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_rootfs, "rootfs", "ChromeOS rootfs"},
686*8617a60dSAndroid Build Coastguard Worker {&guid_linux_data, "data", "Linux data"},
687*8617a60dSAndroid Build Coastguard Worker {&guid_basic_data, "basicdata", "Basic data"},
688*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"},
689*8617a60dSAndroid Build Coastguard Worker {&guid_efi, "efi", "EFI System Partition"},
690*8617a60dSAndroid Build Coastguard Worker {&guid_unused, "unused", "Unused (nonexistent) partition"},
691*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_minios, "minios", "ChromeOS miniOS"},
692*8617a60dSAndroid Build Coastguard Worker {&guid_chromeos_hibernate, "hibernate", "ChromeOS hibernate"},
693*8617a60dSAndroid Build Coastguard Worker };
694*8617a60dSAndroid Build Coastguard Worker
695*8617a60dSAndroid Build Coastguard Worker /* Resolves human-readable GPT type.
696*8617a60dSAndroid Build Coastguard Worker * Returns CGPT_OK if found.
697*8617a60dSAndroid Build Coastguard Worker * Returns CGPT_FAILED if no known type found. */
ResolveType(const Guid * type,char * buf)698*8617a60dSAndroid Build Coastguard Worker int ResolveType(const Guid *type, char *buf) {
699*8617a60dSAndroid Build Coastguard Worker int i;
700*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
701*8617a60dSAndroid Build Coastguard Worker if (!memcmp(type, supported_types[i].type, sizeof(Guid))) {
702*8617a60dSAndroid Build Coastguard Worker strcpy(buf, supported_types[i].description);
703*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
704*8617a60dSAndroid Build Coastguard Worker }
705*8617a60dSAndroid Build Coastguard Worker }
706*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
707*8617a60dSAndroid Build Coastguard Worker }
708*8617a60dSAndroid Build Coastguard Worker
SupportedType(const char * name,Guid * type)709*8617a60dSAndroid Build Coastguard Worker int SupportedType(const char *name, Guid *type) {
710*8617a60dSAndroid Build Coastguard Worker int i;
711*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
712*8617a60dSAndroid Build Coastguard Worker if (!strcmp(name, supported_types[i].name)) {
713*8617a60dSAndroid Build Coastguard Worker memcpy(type, supported_types[i].type, sizeof(Guid));
714*8617a60dSAndroid Build Coastguard Worker return CGPT_OK;
715*8617a60dSAndroid Build Coastguard Worker }
716*8617a60dSAndroid Build Coastguard Worker }
717*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
718*8617a60dSAndroid Build Coastguard Worker }
719*8617a60dSAndroid Build Coastguard Worker
PrintTypes(void)720*8617a60dSAndroid Build Coastguard Worker void PrintTypes(void) {
721*8617a60dSAndroid Build Coastguard Worker int i;
722*8617a60dSAndroid Build Coastguard Worker printf("The partition type may also be given as one of these aliases:\n\n");
723*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_COUNT(supported_types); ++i) {
724*8617a60dSAndroid Build Coastguard Worker printf(" %-10s %s\n", supported_types[i].name,
725*8617a60dSAndroid Build Coastguard Worker supported_types[i].description);
726*8617a60dSAndroid Build Coastguard Worker }
727*8617a60dSAndroid Build Coastguard Worker printf("\n");
728*8617a60dSAndroid Build Coastguard Worker }
729*8617a60dSAndroid Build Coastguard Worker
GetGptHeader(const GptData * gpt)730*8617a60dSAndroid Build Coastguard Worker static GptHeader* GetGptHeader(const GptData *gpt) {
731*8617a60dSAndroid Build Coastguard Worker if (gpt->valid_headers & MASK_PRIMARY)
732*8617a60dSAndroid Build Coastguard Worker return (GptHeader*)gpt->primary_header;
733*8617a60dSAndroid Build Coastguard Worker else if (gpt->valid_headers & MASK_SECONDARY)
734*8617a60dSAndroid Build Coastguard Worker return (GptHeader*)gpt->secondary_header;
735*8617a60dSAndroid Build Coastguard Worker else
736*8617a60dSAndroid Build Coastguard Worker return 0;
737*8617a60dSAndroid Build Coastguard Worker }
738*8617a60dSAndroid Build Coastguard Worker
GetNumberOfEntries(const struct drive * drive)739*8617a60dSAndroid Build Coastguard Worker uint32_t GetNumberOfEntries(const struct drive *drive) {
740*8617a60dSAndroid Build Coastguard Worker GptHeader *header = GetGptHeader(&drive->gpt);
741*8617a60dSAndroid Build Coastguard Worker if (!header)
742*8617a60dSAndroid Build Coastguard Worker return 0;
743*8617a60dSAndroid Build Coastguard Worker return header->number_of_entries;
744*8617a60dSAndroid Build Coastguard Worker }
745*8617a60dSAndroid Build Coastguard Worker
746*8617a60dSAndroid Build Coastguard Worker
GetEntry(GptData * gpt,int secondary,uint32_t entry_index)747*8617a60dSAndroid Build Coastguard Worker GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) {
748*8617a60dSAndroid Build Coastguard Worker GptHeader *header = GetGptHeader(gpt);
749*8617a60dSAndroid Build Coastguard Worker uint8_t *entries;
750*8617a60dSAndroid Build Coastguard Worker uint32_t stride = header->size_of_entry;
751*8617a60dSAndroid Build Coastguard Worker require(stride);
752*8617a60dSAndroid Build Coastguard Worker require(entry_index < header->number_of_entries);
753*8617a60dSAndroid Build Coastguard Worker
754*8617a60dSAndroid Build Coastguard Worker if (secondary == PRIMARY) {
755*8617a60dSAndroid Build Coastguard Worker entries = gpt->primary_entries;
756*8617a60dSAndroid Build Coastguard Worker } else if (secondary == SECONDARY) {
757*8617a60dSAndroid Build Coastguard Worker entries = gpt->secondary_entries;
758*8617a60dSAndroid Build Coastguard Worker } else { /* ANY_VALID */
759*8617a60dSAndroid Build Coastguard Worker require(secondary == ANY_VALID);
760*8617a60dSAndroid Build Coastguard Worker if (gpt->valid_entries & MASK_PRIMARY) {
761*8617a60dSAndroid Build Coastguard Worker entries = gpt->primary_entries;
762*8617a60dSAndroid Build Coastguard Worker } else {
763*8617a60dSAndroid Build Coastguard Worker require(gpt->valid_entries & MASK_SECONDARY);
764*8617a60dSAndroid Build Coastguard Worker entries = gpt->secondary_entries;
765*8617a60dSAndroid Build Coastguard Worker }
766*8617a60dSAndroid Build Coastguard Worker }
767*8617a60dSAndroid Build Coastguard Worker
768*8617a60dSAndroid Build Coastguard Worker return (GptEntry*)(&entries[stride * entry_index]);
769*8617a60dSAndroid Build Coastguard Worker }
770*8617a60dSAndroid Build Coastguard Worker
SetRequired(struct drive * drive,int secondary,uint32_t entry_index,int required)771*8617a60dSAndroid Build Coastguard Worker void SetRequired(struct drive *drive, int secondary, uint32_t entry_index,
772*8617a60dSAndroid Build Coastguard Worker int required) {
773*8617a60dSAndroid Build Coastguard Worker require(required >= 0 && required <= CGPT_ATTRIBUTE_MAX_REQUIRED);
774*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
775*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
776*8617a60dSAndroid Build Coastguard Worker SetEntryRequired(entry, required);
777*8617a60dSAndroid Build Coastguard Worker }
778*8617a60dSAndroid Build Coastguard Worker
GetRequired(struct drive * drive,int secondary,uint32_t entry_index)779*8617a60dSAndroid Build Coastguard Worker int GetRequired(struct drive *drive, int secondary, uint32_t entry_index) {
780*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
781*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
782*8617a60dSAndroid Build Coastguard Worker return GetEntryRequired(entry);
783*8617a60dSAndroid Build Coastguard Worker }
784*8617a60dSAndroid Build Coastguard Worker
SetLegacyBoot(struct drive * drive,int secondary,uint32_t entry_index,int legacy_boot)785*8617a60dSAndroid Build Coastguard Worker void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
786*8617a60dSAndroid Build Coastguard Worker int legacy_boot) {
787*8617a60dSAndroid Build Coastguard Worker require(legacy_boot >= 0 && legacy_boot <= CGPT_ATTRIBUTE_MAX_LEGACY_BOOT);
788*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
789*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
790*8617a60dSAndroid Build Coastguard Worker SetEntryLegacyBoot(entry, legacy_boot);
791*8617a60dSAndroid Build Coastguard Worker }
792*8617a60dSAndroid Build Coastguard Worker
GetLegacyBoot(struct drive * drive,int secondary,uint32_t entry_index)793*8617a60dSAndroid Build Coastguard Worker int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index) {
794*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
795*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
796*8617a60dSAndroid Build Coastguard Worker return GetEntryLegacyBoot(entry);
797*8617a60dSAndroid Build Coastguard Worker }
798*8617a60dSAndroid Build Coastguard Worker
SetPriority(struct drive * drive,int secondary,uint32_t entry_index,int priority)799*8617a60dSAndroid Build Coastguard Worker void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
800*8617a60dSAndroid Build Coastguard Worker int priority) {
801*8617a60dSAndroid Build Coastguard Worker require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
802*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
803*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
804*8617a60dSAndroid Build Coastguard Worker SetEntryPriority(entry, priority);
805*8617a60dSAndroid Build Coastguard Worker }
806*8617a60dSAndroid Build Coastguard Worker
GetPriority(struct drive * drive,int secondary,uint32_t entry_index)807*8617a60dSAndroid Build Coastguard Worker int GetPriority(struct drive *drive, int secondary, uint32_t entry_index) {
808*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
809*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
810*8617a60dSAndroid Build Coastguard Worker return GetEntryPriority(entry);
811*8617a60dSAndroid Build Coastguard Worker }
812*8617a60dSAndroid Build Coastguard Worker
SetTries(struct drive * drive,int secondary,uint32_t entry_index,int tries)813*8617a60dSAndroid Build Coastguard Worker void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
814*8617a60dSAndroid Build Coastguard Worker int tries) {
815*8617a60dSAndroid Build Coastguard Worker require(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
816*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
817*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
818*8617a60dSAndroid Build Coastguard Worker SetEntryTries(entry, tries);
819*8617a60dSAndroid Build Coastguard Worker }
820*8617a60dSAndroid Build Coastguard Worker
GetTries(struct drive * drive,int secondary,uint32_t entry_index)821*8617a60dSAndroid Build Coastguard Worker int GetTries(struct drive *drive, int secondary, uint32_t entry_index) {
822*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
823*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
824*8617a60dSAndroid Build Coastguard Worker return GetEntryTries(entry);
825*8617a60dSAndroid Build Coastguard Worker }
826*8617a60dSAndroid Build Coastguard Worker
SetSuccessful(struct drive * drive,int secondary,uint32_t entry_index,int success)827*8617a60dSAndroid Build Coastguard Worker void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
828*8617a60dSAndroid Build Coastguard Worker int success) {
829*8617a60dSAndroid Build Coastguard Worker require(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
830*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
831*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
832*8617a60dSAndroid Build Coastguard Worker SetEntrySuccessful(entry, success);
833*8617a60dSAndroid Build Coastguard Worker }
834*8617a60dSAndroid Build Coastguard Worker
GetSuccessful(struct drive * drive,int secondary,uint32_t entry_index)835*8617a60dSAndroid Build Coastguard Worker int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index) {
836*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
837*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
838*8617a60dSAndroid Build Coastguard Worker return GetEntrySuccessful(entry);
839*8617a60dSAndroid Build Coastguard Worker }
840*8617a60dSAndroid Build Coastguard Worker
SetErrorCounter(struct drive * drive,int secondary,uint32_t entry_index,int error_counter)841*8617a60dSAndroid Build Coastguard Worker void SetErrorCounter(struct drive *drive, int secondary, uint32_t entry_index,
842*8617a60dSAndroid Build Coastguard Worker int error_counter) {
843*8617a60dSAndroid Build Coastguard Worker require(error_counter >= 0 &&
844*8617a60dSAndroid Build Coastguard Worker error_counter <= CGPT_ATTRIBUTE_MAX_ERROR_COUNTER);
845*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
846*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
847*8617a60dSAndroid Build Coastguard Worker SetEntryErrorCounter(entry, error_counter);
848*8617a60dSAndroid Build Coastguard Worker }
849*8617a60dSAndroid Build Coastguard Worker
GetErrorCounter(struct drive * drive,int secondary,uint32_t entry_index)850*8617a60dSAndroid Build Coastguard Worker int GetErrorCounter(struct drive *drive, int secondary, uint32_t entry_index) {
851*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
852*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
853*8617a60dSAndroid Build Coastguard Worker return GetEntryErrorCounter(entry);
854*8617a60dSAndroid Build Coastguard Worker }
855*8617a60dSAndroid Build Coastguard Worker
SetRaw(struct drive * drive,int secondary,uint32_t entry_index,uint32_t raw)856*8617a60dSAndroid Build Coastguard Worker void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
857*8617a60dSAndroid Build Coastguard Worker uint32_t raw) {
858*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
859*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, entry_index);
860*8617a60dSAndroid Build Coastguard Worker entry->attrs.fields.gpt_att = (uint16_t)raw;
861*8617a60dSAndroid Build Coastguard Worker }
862*8617a60dSAndroid Build Coastguard Worker
UpdateAllEntries(struct drive * drive)863*8617a60dSAndroid Build Coastguard Worker void UpdateAllEntries(struct drive *drive) {
864*8617a60dSAndroid Build Coastguard Worker RepairEntries(&drive->gpt, MASK_PRIMARY);
865*8617a60dSAndroid Build Coastguard Worker RepairHeader(&drive->gpt, MASK_PRIMARY);
866*8617a60dSAndroid Build Coastguard Worker
867*8617a60dSAndroid Build Coastguard Worker drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
868*8617a60dSAndroid Build Coastguard Worker GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
869*8617a60dSAndroid Build Coastguard Worker UpdateCrc(&drive->gpt);
870*8617a60dSAndroid Build Coastguard Worker }
871*8617a60dSAndroid Build Coastguard Worker
IsUnused(struct drive * drive,int secondary,uint32_t index)872*8617a60dSAndroid Build Coastguard Worker int IsUnused(struct drive *drive, int secondary, uint32_t index) {
873*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
874*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, index);
875*8617a60dSAndroid Build Coastguard Worker return GuidIsZero(&entry->type);
876*8617a60dSAndroid Build Coastguard Worker }
877*8617a60dSAndroid Build Coastguard Worker
IsKernel(struct drive * drive,int secondary,uint32_t index)878*8617a60dSAndroid Build Coastguard Worker int IsKernel(struct drive *drive, int secondary, uint32_t index) {
879*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
880*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, secondary, index);
881*8617a60dSAndroid Build Coastguard Worker return GuidEqual(&entry->type, &guid_chromeos_kernel);
882*8617a60dSAndroid Build Coastguard Worker }
883*8617a60dSAndroid Build Coastguard Worker
884*8617a60dSAndroid Build Coastguard Worker
885*8617a60dSAndroid Build Coastguard Worker #define TOSTRING(A) #A
GptError(int errnum)886*8617a60dSAndroid Build Coastguard Worker const char *GptError(int errnum) {
887*8617a60dSAndroid Build Coastguard Worker const char *error_string[] = {
888*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_SUCCESS),
889*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_NO_VALID_KERNEL),
890*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_INVALID_HEADERS),
891*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_INVALID_ENTRIES),
892*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_INVALID_SECTOR_SIZE),
893*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_INVALID_SECTOR_NUMBER),
894*8617a60dSAndroid Build Coastguard Worker TOSTRING(GPT_ERROR_INVALID_UPDATE_TYPE)
895*8617a60dSAndroid Build Coastguard Worker };
896*8617a60dSAndroid Build Coastguard Worker if (errnum < 0 || errnum >= ARRAY_COUNT(error_string))
897*8617a60dSAndroid Build Coastguard Worker return "<illegal value>";
898*8617a60dSAndroid Build Coastguard Worker return error_string[errnum];
899*8617a60dSAndroid Build Coastguard Worker }
900*8617a60dSAndroid Build Coastguard Worker
901*8617a60dSAndroid Build Coastguard Worker /* Update CRC value if necessary. */
UpdateCrc(GptData * gpt)902*8617a60dSAndroid Build Coastguard Worker void UpdateCrc(GptData *gpt) {
903*8617a60dSAndroid Build Coastguard Worker GptHeader *primary_header, *secondary_header;
904*8617a60dSAndroid Build Coastguard Worker
905*8617a60dSAndroid Build Coastguard Worker primary_header = (GptHeader*)gpt->primary_header;
906*8617a60dSAndroid Build Coastguard Worker secondary_header = (GptHeader*)gpt->secondary_header;
907*8617a60dSAndroid Build Coastguard Worker
908*8617a60dSAndroid Build Coastguard Worker if (gpt->modified & GPT_MODIFIED_ENTRIES1 &&
909*8617a60dSAndroid Build Coastguard Worker memcmp(primary_header, GPT_HEADER_SIGNATURE2,
910*8617a60dSAndroid Build Coastguard Worker GPT_HEADER_SIGNATURE_SIZE)) {
911*8617a60dSAndroid Build Coastguard Worker size_t entries_size = primary_header->size_of_entry *
912*8617a60dSAndroid Build Coastguard Worker primary_header->number_of_entries;
913*8617a60dSAndroid Build Coastguard Worker primary_header->entries_crc32 =
914*8617a60dSAndroid Build Coastguard Worker Crc32(gpt->primary_entries, entries_size);
915*8617a60dSAndroid Build Coastguard Worker }
916*8617a60dSAndroid Build Coastguard Worker if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
917*8617a60dSAndroid Build Coastguard Worker size_t entries_size = secondary_header->size_of_entry *
918*8617a60dSAndroid Build Coastguard Worker secondary_header->number_of_entries;
919*8617a60dSAndroid Build Coastguard Worker secondary_header->entries_crc32 =
920*8617a60dSAndroid Build Coastguard Worker Crc32(gpt->secondary_entries, entries_size);
921*8617a60dSAndroid Build Coastguard Worker }
922*8617a60dSAndroid Build Coastguard Worker if (gpt->modified & GPT_MODIFIED_HEADER1) {
923*8617a60dSAndroid Build Coastguard Worker primary_header->header_crc32 = 0;
924*8617a60dSAndroid Build Coastguard Worker primary_header->header_crc32 = Crc32(
925*8617a60dSAndroid Build Coastguard Worker (const uint8_t *)primary_header, sizeof(GptHeader));
926*8617a60dSAndroid Build Coastguard Worker }
927*8617a60dSAndroid Build Coastguard Worker if (gpt->modified & GPT_MODIFIED_HEADER2) {
928*8617a60dSAndroid Build Coastguard Worker secondary_header->header_crc32 = 0;
929*8617a60dSAndroid Build Coastguard Worker secondary_header->header_crc32 = Crc32(
930*8617a60dSAndroid Build Coastguard Worker (const uint8_t *)secondary_header, sizeof(GptHeader));
931*8617a60dSAndroid Build Coastguard Worker }
932*8617a60dSAndroid Build Coastguard Worker }
933*8617a60dSAndroid Build Coastguard Worker /* Two headers are NOT bitwise identical. For example, my_lba pointers to header
934*8617a60dSAndroid Build Coastguard Worker * itself so that my_lba in primary and secondary is definitely different.
935*8617a60dSAndroid Build Coastguard Worker * Only the following fields should be identical.
936*8617a60dSAndroid Build Coastguard Worker *
937*8617a60dSAndroid Build Coastguard Worker * first_usable_lba
938*8617a60dSAndroid Build Coastguard Worker * last_usable_lba
939*8617a60dSAndroid Build Coastguard Worker * number_of_entries
940*8617a60dSAndroid Build Coastguard Worker * size_of_entry
941*8617a60dSAndroid Build Coastguard Worker * disk_uuid
942*8617a60dSAndroid Build Coastguard Worker *
943*8617a60dSAndroid Build Coastguard Worker * If any of above field are not matched, overwrite secondary with primary since
944*8617a60dSAndroid Build Coastguard Worker * we always trust primary.
945*8617a60dSAndroid Build Coastguard Worker * If any one of header is invalid, copy from another. */
IsSynonymous(const GptHeader * a,const GptHeader * b)946*8617a60dSAndroid Build Coastguard Worker int IsSynonymous(const GptHeader* a, const GptHeader* b) {
947*8617a60dSAndroid Build Coastguard Worker if ((a->first_usable_lba == b->first_usable_lba) &&
948*8617a60dSAndroid Build Coastguard Worker (a->last_usable_lba == b->last_usable_lba) &&
949*8617a60dSAndroid Build Coastguard Worker (a->number_of_entries == b->number_of_entries) &&
950*8617a60dSAndroid Build Coastguard Worker (a->size_of_entry == b->size_of_entry) &&
951*8617a60dSAndroid Build Coastguard Worker (!memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid))))
952*8617a60dSAndroid Build Coastguard Worker return 1;
953*8617a60dSAndroid Build Coastguard Worker return 0;
954*8617a60dSAndroid Build Coastguard Worker }
955*8617a60dSAndroid Build Coastguard Worker
956*8617a60dSAndroid Build Coastguard Worker /* Primary entries and secondary entries should be bitwise identical.
957*8617a60dSAndroid Build Coastguard Worker * If two entries tables are valid, compare them. If not the same,
958*8617a60dSAndroid Build Coastguard Worker * overwrites secondary with primary (primary always has higher priority),
959*8617a60dSAndroid Build Coastguard Worker * and marks secondary as modified.
960*8617a60dSAndroid Build Coastguard Worker * If only one is valid, overwrites invalid one.
961*8617a60dSAndroid Build Coastguard Worker * If all are invalid, does nothing.
962*8617a60dSAndroid Build Coastguard Worker * This function returns bit masks for GptData.modified field.
963*8617a60dSAndroid Build Coastguard Worker * Note that CRC is NOT re-computed in this function.
964*8617a60dSAndroid Build Coastguard Worker */
RepairEntries(GptData * gpt,const uint32_t valid_entries)965*8617a60dSAndroid Build Coastguard Worker uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
966*8617a60dSAndroid Build Coastguard Worker /* If we have an alternate GPT header signature, don't overwrite
967*8617a60dSAndroid Build Coastguard Worker * the secondary GPT with the primary one as that might wipe the
968*8617a60dSAndroid Build Coastguard Worker * partition table. Also don't overwrite the primary one with the
969*8617a60dSAndroid Build Coastguard Worker * secondary one as that will stop Windows from booting. */
970*8617a60dSAndroid Build Coastguard Worker GptHeader* h = (GptHeader*)(gpt->primary_header);
971*8617a60dSAndroid Build Coastguard Worker if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE))
972*8617a60dSAndroid Build Coastguard Worker return 0;
973*8617a60dSAndroid Build Coastguard Worker
974*8617a60dSAndroid Build Coastguard Worker if (gpt->valid_headers & MASK_PRIMARY) {
975*8617a60dSAndroid Build Coastguard Worker h = (GptHeader*)gpt->primary_header;
976*8617a60dSAndroid Build Coastguard Worker } else if (gpt->valid_headers & MASK_SECONDARY) {
977*8617a60dSAndroid Build Coastguard Worker h = (GptHeader*)gpt->secondary_header;
978*8617a60dSAndroid Build Coastguard Worker } else {
979*8617a60dSAndroid Build Coastguard Worker /* We cannot trust any header, don't update entries. */
980*8617a60dSAndroid Build Coastguard Worker return 0;
981*8617a60dSAndroid Build Coastguard Worker }
982*8617a60dSAndroid Build Coastguard Worker
983*8617a60dSAndroid Build Coastguard Worker size_t entries_size = h->number_of_entries * h->size_of_entry;
984*8617a60dSAndroid Build Coastguard Worker if (valid_entries == MASK_BOTH) {
985*8617a60dSAndroid Build Coastguard Worker if (memcmp(gpt->primary_entries, gpt->secondary_entries, entries_size)) {
986*8617a60dSAndroid Build Coastguard Worker memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
987*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_ENTRIES2;
988*8617a60dSAndroid Build Coastguard Worker }
989*8617a60dSAndroid Build Coastguard Worker } else if (valid_entries == MASK_PRIMARY) {
990*8617a60dSAndroid Build Coastguard Worker memcpy(gpt->secondary_entries, gpt->primary_entries, entries_size);
991*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_ENTRIES2;
992*8617a60dSAndroid Build Coastguard Worker } else if (valid_entries == MASK_SECONDARY) {
993*8617a60dSAndroid Build Coastguard Worker memcpy(gpt->primary_entries, gpt->secondary_entries, entries_size);
994*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_ENTRIES1;
995*8617a60dSAndroid Build Coastguard Worker }
996*8617a60dSAndroid Build Coastguard Worker
997*8617a60dSAndroid Build Coastguard Worker return 0;
998*8617a60dSAndroid Build Coastguard Worker }
999*8617a60dSAndroid Build Coastguard Worker
1000*8617a60dSAndroid Build Coastguard Worker /* The above five fields are shared between primary and secondary headers.
1001*8617a60dSAndroid Build Coastguard Worker * We can recover one header from another through copying those fields. */
CopySynonymousParts(GptHeader * target,const GptHeader * source)1002*8617a60dSAndroid Build Coastguard Worker static void CopySynonymousParts(GptHeader* target, const GptHeader* source) {
1003*8617a60dSAndroid Build Coastguard Worker target->first_usable_lba = source->first_usable_lba;
1004*8617a60dSAndroid Build Coastguard Worker target->last_usable_lba = source->last_usable_lba;
1005*8617a60dSAndroid Build Coastguard Worker target->number_of_entries = source->number_of_entries;
1006*8617a60dSAndroid Build Coastguard Worker target->size_of_entry = source->size_of_entry;
1007*8617a60dSAndroid Build Coastguard Worker memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid));
1008*8617a60dSAndroid Build Coastguard Worker }
1009*8617a60dSAndroid Build Coastguard Worker
1010*8617a60dSAndroid Build Coastguard Worker /* This function repairs primary and secondary headers if possible.
1011*8617a60dSAndroid Build Coastguard Worker * If both headers are valid (CRC32 is correct) but
1012*8617a60dSAndroid Build Coastguard Worker * a) indicate inconsistent usable LBA ranges,
1013*8617a60dSAndroid Build Coastguard Worker * b) inconsistent partition entry size and number,
1014*8617a60dSAndroid Build Coastguard Worker * c) inconsistent disk_uuid,
1015*8617a60dSAndroid Build Coastguard Worker * we will use the primary header to overwrite secondary header.
1016*8617a60dSAndroid Build Coastguard Worker * If primary is invalid (CRC32 is wrong), then we repair it from secondary.
1017*8617a60dSAndroid Build Coastguard Worker * If secondary is invalid (CRC32 is wrong), then we repair it from primary.
1018*8617a60dSAndroid Build Coastguard Worker * This function returns the bitmasks for modified header.
1019*8617a60dSAndroid Build Coastguard Worker * Note that CRC value is NOT re-computed in this function. UpdateCrc() will
1020*8617a60dSAndroid Build Coastguard Worker * do it later.
1021*8617a60dSAndroid Build Coastguard Worker */
RepairHeader(GptData * gpt,const uint32_t valid_headers)1022*8617a60dSAndroid Build Coastguard Worker uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
1023*8617a60dSAndroid Build Coastguard Worker GptHeader *primary_header, *secondary_header;
1024*8617a60dSAndroid Build Coastguard Worker
1025*8617a60dSAndroid Build Coastguard Worker primary_header = (GptHeader*)gpt->primary_header;
1026*8617a60dSAndroid Build Coastguard Worker secondary_header = (GptHeader*)gpt->secondary_header;
1027*8617a60dSAndroid Build Coastguard Worker
1028*8617a60dSAndroid Build Coastguard Worker if (valid_headers == MASK_BOTH) {
1029*8617a60dSAndroid Build Coastguard Worker if (!IsSynonymous(primary_header, secondary_header)) {
1030*8617a60dSAndroid Build Coastguard Worker CopySynonymousParts(secondary_header, primary_header);
1031*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_HEADER2;
1032*8617a60dSAndroid Build Coastguard Worker }
1033*8617a60dSAndroid Build Coastguard Worker } else if (valid_headers == MASK_PRIMARY) {
1034*8617a60dSAndroid Build Coastguard Worker memcpy(secondary_header, primary_header, sizeof(GptHeader));
1035*8617a60dSAndroid Build Coastguard Worker secondary_header->my_lba = gpt->gpt_drive_sectors - 1; /* the last sector */
1036*8617a60dSAndroid Build Coastguard Worker secondary_header->alternate_lba = primary_header->my_lba;
1037*8617a60dSAndroid Build Coastguard Worker secondary_header->entries_lba = secondary_header->my_lba -
1038*8617a60dSAndroid Build Coastguard Worker CalculateEntriesSectors(primary_header, gpt->sector_bytes);
1039*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_HEADER2;
1040*8617a60dSAndroid Build Coastguard Worker } else if (valid_headers == MASK_SECONDARY) {
1041*8617a60dSAndroid Build Coastguard Worker memcpy(primary_header, secondary_header, sizeof(GptHeader));
1042*8617a60dSAndroid Build Coastguard Worker primary_header->my_lba = GPT_PMBR_SECTORS; /* the second sector on drive */
1043*8617a60dSAndroid Build Coastguard Worker primary_header->alternate_lba = secondary_header->my_lba;
1044*8617a60dSAndroid Build Coastguard Worker /* TODO (namnguyen): Preserve (header, entries) padding space. */
1045*8617a60dSAndroid Build Coastguard Worker primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTORS;
1046*8617a60dSAndroid Build Coastguard Worker return GPT_MODIFIED_HEADER1;
1047*8617a60dSAndroid Build Coastguard Worker }
1048*8617a60dSAndroid Build Coastguard Worker
1049*8617a60dSAndroid Build Coastguard Worker return 0;
1050*8617a60dSAndroid Build Coastguard Worker }
1051*8617a60dSAndroid Build Coastguard Worker
CgptGetNumNonEmptyPartitions(CgptShowParams * params)1052*8617a60dSAndroid Build Coastguard Worker int CgptGetNumNonEmptyPartitions(CgptShowParams *params) {
1053*8617a60dSAndroid Build Coastguard Worker struct drive drive;
1054*8617a60dSAndroid Build Coastguard Worker int gpt_retval;
1055*8617a60dSAndroid Build Coastguard Worker int retval;
1056*8617a60dSAndroid Build Coastguard Worker
1057*8617a60dSAndroid Build Coastguard Worker if (params == NULL)
1058*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
1059*8617a60dSAndroid Build Coastguard Worker
1060*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
1061*8617a60dSAndroid Build Coastguard Worker params->drive_size))
1062*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
1063*8617a60dSAndroid Build Coastguard Worker
1064*8617a60dSAndroid Build Coastguard Worker if (GPT_SUCCESS != (gpt_retval = GptValidityCheck(&drive.gpt))) {
1065*8617a60dSAndroid Build Coastguard Worker Error("GptValidityCheck() returned %d: %s\n",
1066*8617a60dSAndroid Build Coastguard Worker gpt_retval, GptError(gpt_retval));
1067*8617a60dSAndroid Build Coastguard Worker retval = CGPT_FAILED;
1068*8617a60dSAndroid Build Coastguard Worker goto done;
1069*8617a60dSAndroid Build Coastguard Worker }
1070*8617a60dSAndroid Build Coastguard Worker
1071*8617a60dSAndroid Build Coastguard Worker params->num_partitions = 0;
1072*8617a60dSAndroid Build Coastguard Worker int numEntries = GetNumberOfEntries(&drive);
1073*8617a60dSAndroid Build Coastguard Worker int i;
1074*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < numEntries; i++) {
1075*8617a60dSAndroid Build Coastguard Worker GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
1076*8617a60dSAndroid Build Coastguard Worker if (GuidIsZero(&entry->type))
1077*8617a60dSAndroid Build Coastguard Worker continue;
1078*8617a60dSAndroid Build Coastguard Worker
1079*8617a60dSAndroid Build Coastguard Worker params->num_partitions++;
1080*8617a60dSAndroid Build Coastguard Worker }
1081*8617a60dSAndroid Build Coastguard Worker
1082*8617a60dSAndroid Build Coastguard Worker retval = CGPT_OK;
1083*8617a60dSAndroid Build Coastguard Worker
1084*8617a60dSAndroid Build Coastguard Worker done:
1085*8617a60dSAndroid Build Coastguard Worker DriveClose(&drive, 0);
1086*8617a60dSAndroid Build Coastguard Worker return retval;
1087*8617a60dSAndroid Build Coastguard Worker }
1088*8617a60dSAndroid Build Coastguard Worker
GuidEqual(const Guid * guid1,const Guid * guid2)1089*8617a60dSAndroid Build Coastguard Worker int GuidEqual(const Guid *guid1, const Guid *guid2) {
1090*8617a60dSAndroid Build Coastguard Worker return (0 == memcmp(guid1, guid2, sizeof(Guid)));
1091*8617a60dSAndroid Build Coastguard Worker }
1092*8617a60dSAndroid Build Coastguard Worker
GuidIsZero(const Guid * gp)1093*8617a60dSAndroid Build Coastguard Worker int GuidIsZero(const Guid *gp) {
1094*8617a60dSAndroid Build Coastguard Worker return GuidEqual(gp, &guid_unused);
1095*8617a60dSAndroid Build Coastguard Worker }
1096*8617a60dSAndroid Build Coastguard Worker
PMBRToStr(struct pmbr * pmbr,char * str,unsigned int buflen)1097*8617a60dSAndroid Build Coastguard Worker void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen) {
1098*8617a60dSAndroid Build Coastguard Worker char buf[GUID_STRLEN];
1099*8617a60dSAndroid Build Coastguard Worker if (GuidIsZero(&pmbr->boot_guid)) {
1100*8617a60dSAndroid Build Coastguard Worker require(snprintf(str, buflen, "PMBR") < buflen);
1101*8617a60dSAndroid Build Coastguard Worker } else {
1102*8617a60dSAndroid Build Coastguard Worker GuidToStr(&pmbr->boot_guid, buf, sizeof(buf));
1103*8617a60dSAndroid Build Coastguard Worker require(snprintf(str, buflen, "PMBR (Boot GUID: %s)", buf) < buflen);
1104*8617a60dSAndroid Build Coastguard Worker }
1105*8617a60dSAndroid Build Coastguard Worker }
1106*8617a60dSAndroid Build Coastguard Worker
1107*8617a60dSAndroid Build Coastguard Worker /*
1108*8617a60dSAndroid Build Coastguard Worker * This is here because some CGPT functionality is provided in libvboot_host.a
1109*8617a60dSAndroid Build Coastguard Worker * for other host utilities. GenerateGuid() is implemented (in cgpt.c which is
1110*8617a60dSAndroid Build Coastguard Worker * *not* linked into libvboot_host.a) by calling into libuuid. We don't want to
1111*8617a60dSAndroid Build Coastguard Worker * mandate libuuid as a dependency for every utilitity that wants to link
1112*8617a60dSAndroid Build Coastguard Worker * libvboot_host.a, since they usually don't use the functionality that needs
1113*8617a60dSAndroid Build Coastguard Worker * to generate new UUIDs anyway (just other functionality implemented in the
1114*8617a60dSAndroid Build Coastguard Worker * same files).
1115*8617a60dSAndroid Build Coastguard Worker */
1116*8617a60dSAndroid Build Coastguard Worker #ifndef HAVE_MACOS
GenerateGuid(Guid * newguid)1117*8617a60dSAndroid Build Coastguard Worker __attribute__((weak)) int GenerateGuid(Guid *newguid) { return CGPT_FAILED; };
1118*8617a60dSAndroid Build Coastguard Worker #endif
1119