1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2012 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
6*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
7*8617a60dSAndroid Build Coastguard Worker #include <string.h>
8*8617a60dSAndroid Build Coastguard Worker
9*8617a60dSAndroid Build Coastguard Worker #include "cgpt.h"
10*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
11*8617a60dSAndroid Build Coastguard Worker #include "cgpt_params.h"
12*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
13*8617a60dSAndroid Build Coastguard Worker
PrintCgptAddParams(const CgptAddParams * params)14*8617a60dSAndroid Build Coastguard Worker static void PrintCgptAddParams(const CgptAddParams *params) {
15*8617a60dSAndroid Build Coastguard Worker char tmp[64];
16*8617a60dSAndroid Build Coastguard Worker
17*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-i %d ", params->partition);
18*8617a60dSAndroid Build Coastguard Worker if (params->label)
19*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-l %s ", params->label);
20*8617a60dSAndroid Build Coastguard Worker if (params->set_begin)
21*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-b %llu ", (unsigned long long)params->begin);
22*8617a60dSAndroid Build Coastguard Worker if (params->set_size)
23*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-s %llu ", (unsigned long long)params->size);
24*8617a60dSAndroid Build Coastguard Worker if (params->set_type) {
25*8617a60dSAndroid Build Coastguard Worker GuidToStr(¶ms->type_guid, tmp, sizeof(tmp));
26*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-t %s ", tmp);
27*8617a60dSAndroid Build Coastguard Worker }
28*8617a60dSAndroid Build Coastguard Worker if (params->set_unique) {
29*8617a60dSAndroid Build Coastguard Worker GuidToStr(¶ms->unique_guid, tmp, sizeof(tmp));
30*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-u %s ", tmp);
31*8617a60dSAndroid Build Coastguard Worker }
32*8617a60dSAndroid Build Coastguard Worker if (params->set_error_counter)
33*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-E %d ", params->error_counter);
34*8617a60dSAndroid Build Coastguard Worker if (params->set_successful)
35*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-S %d ", params->successful);
36*8617a60dSAndroid Build Coastguard Worker if (params->set_tries)
37*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-T %d ", params->tries);
38*8617a60dSAndroid Build Coastguard Worker if (params->set_priority)
39*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-P %d ", params->priority);
40*8617a60dSAndroid Build Coastguard Worker if (params->set_required)
41*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-R %d ", params->required);
42*8617a60dSAndroid Build Coastguard Worker if (params->set_legacy_boot)
43*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-B %d ", params->legacy_boot);
44*8617a60dSAndroid Build Coastguard Worker if (params->set_raw)
45*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "-A %#x ", params->raw_value);
46*8617a60dSAndroid Build Coastguard Worker
47*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "\n");
48*8617a60dSAndroid Build Coastguard Worker }
49*8617a60dSAndroid Build Coastguard Worker
50*8617a60dSAndroid Build Coastguard Worker // This is the implementation-specific helper function.
GptSetEntryAttributes(struct drive * drive,uint32_t index,CgptAddParams * params)51*8617a60dSAndroid Build Coastguard Worker static int GptSetEntryAttributes(struct drive *drive,
52*8617a60dSAndroid Build Coastguard Worker uint32_t index,
53*8617a60dSAndroid Build Coastguard Worker CgptAddParams *params) {
54*8617a60dSAndroid Build Coastguard Worker GptEntry *entry;
55*8617a60dSAndroid Build Coastguard Worker
56*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, PRIMARY, index);
57*8617a60dSAndroid Build Coastguard Worker if (params->set_begin)
58*8617a60dSAndroid Build Coastguard Worker entry->starting_lba = params->begin;
59*8617a60dSAndroid Build Coastguard Worker if (params->set_size)
60*8617a60dSAndroid Build Coastguard Worker entry->ending_lba = entry->starting_lba + params->size - 1;
61*8617a60dSAndroid Build Coastguard Worker if (params->set_unique) {
62*8617a60dSAndroid Build Coastguard Worker memcpy(&entry->unique, ¶ms->unique_guid, sizeof(Guid));
63*8617a60dSAndroid Build Coastguard Worker } else if (GuidIsZero(&entry->type)) {
64*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != GenerateGuid(&entry->unique)) {
65*8617a60dSAndroid Build Coastguard Worker Error("Unable to generate new GUID.\n");
66*8617a60dSAndroid Build Coastguard Worker return -1;
67*8617a60dSAndroid Build Coastguard Worker }
68*8617a60dSAndroid Build Coastguard Worker }
69*8617a60dSAndroid Build Coastguard Worker if (params->set_type)
70*8617a60dSAndroid Build Coastguard Worker memcpy(&entry->type, ¶ms->type_guid, sizeof(Guid));
71*8617a60dSAndroid Build Coastguard Worker if (params->label) {
72*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != UTF8ToUTF16((const uint8_t *)params->label, entry->name,
73*8617a60dSAndroid Build Coastguard Worker sizeof(entry->name) / sizeof(entry->name[0]))) {
74*8617a60dSAndroid Build Coastguard Worker Error("The label cannot be converted to UTF16.\n");
75*8617a60dSAndroid Build Coastguard Worker return -1;
76*8617a60dSAndroid Build Coastguard Worker }
77*8617a60dSAndroid Build Coastguard Worker }
78*8617a60dSAndroid Build Coastguard Worker return 0;
79*8617a60dSAndroid Build Coastguard Worker }
80*8617a60dSAndroid Build Coastguard Worker
81*8617a60dSAndroid Build Coastguard Worker // This is an internal helper function which assumes no NULL args are passed.
82*8617a60dSAndroid Build Coastguard Worker // It sets the given attribute values for a single entry at the given index.
SetEntryAttributes(struct drive * drive,uint32_t index,CgptAddParams * params)83*8617a60dSAndroid Build Coastguard Worker static int SetEntryAttributes(struct drive *drive,
84*8617a60dSAndroid Build Coastguard Worker uint32_t index,
85*8617a60dSAndroid Build Coastguard Worker CgptAddParams *params) {
86*8617a60dSAndroid Build Coastguard Worker if (params->set_raw) {
87*8617a60dSAndroid Build Coastguard Worker SetRaw(drive, PRIMARY, index, params->raw_value);
88*8617a60dSAndroid Build Coastguard Worker } else {
89*8617a60dSAndroid Build Coastguard Worker if (params->set_error_counter)
90*8617a60dSAndroid Build Coastguard Worker SetErrorCounter(drive, PRIMARY, index, params->error_counter);
91*8617a60dSAndroid Build Coastguard Worker if (params->set_successful)
92*8617a60dSAndroid Build Coastguard Worker SetSuccessful(drive, PRIMARY, index, params->successful);
93*8617a60dSAndroid Build Coastguard Worker if (params->set_tries)
94*8617a60dSAndroid Build Coastguard Worker SetTries(drive, PRIMARY, index, params->tries);
95*8617a60dSAndroid Build Coastguard Worker if (params->set_priority)
96*8617a60dSAndroid Build Coastguard Worker SetPriority(drive, PRIMARY, index, params->priority);
97*8617a60dSAndroid Build Coastguard Worker if (params->set_legacy_boot)
98*8617a60dSAndroid Build Coastguard Worker SetLegacyBoot(drive, PRIMARY, index, params->legacy_boot);
99*8617a60dSAndroid Build Coastguard Worker if (params->set_required)
100*8617a60dSAndroid Build Coastguard Worker SetRequired(drive, PRIMARY, index, params->required);
101*8617a60dSAndroid Build Coastguard Worker }
102*8617a60dSAndroid Build Coastguard Worker
103*8617a60dSAndroid Build Coastguard Worker // New partitions must specify type, begin, and size.
104*8617a60dSAndroid Build Coastguard Worker if (IsUnused(drive, PRIMARY, index)) {
105*8617a60dSAndroid Build Coastguard Worker if (!params->set_begin || !params->set_size || !params->set_type) {
106*8617a60dSAndroid Build Coastguard Worker Error("-t, -b, and -s options are required for new partitions\n");
107*8617a60dSAndroid Build Coastguard Worker return -1;
108*8617a60dSAndroid Build Coastguard Worker }
109*8617a60dSAndroid Build Coastguard Worker if (GuidIsZero(¶ms->type_guid)) {
110*8617a60dSAndroid Build Coastguard Worker Error("New partitions must have a type other than \"unused\"\n");
111*8617a60dSAndroid Build Coastguard Worker return -1;
112*8617a60dSAndroid Build Coastguard Worker }
113*8617a60dSAndroid Build Coastguard Worker }
114*8617a60dSAndroid Build Coastguard Worker
115*8617a60dSAndroid Build Coastguard Worker return 0;
116*8617a60dSAndroid Build Coastguard Worker }
117*8617a60dSAndroid Build Coastguard Worker
CgptCheckAddValidity(struct drive * drive)118*8617a60dSAndroid Build Coastguard Worker static int CgptCheckAddValidity(struct drive *drive) {
119*8617a60dSAndroid Build Coastguard Worker int gpt_retval;
120*8617a60dSAndroid Build Coastguard Worker if (GPT_SUCCESS != (gpt_retval = GptValidityCheck(&drive->gpt))) {
121*8617a60dSAndroid Build Coastguard Worker Error("GptValidityCheck() returned %d: %s\n",
122*8617a60dSAndroid Build Coastguard Worker gpt_retval, GptError(gpt_retval));
123*8617a60dSAndroid Build Coastguard Worker return -1;
124*8617a60dSAndroid Build Coastguard Worker }
125*8617a60dSAndroid Build Coastguard Worker
126*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != CheckValid(drive)) {
127*8617a60dSAndroid Build Coastguard Worker Error("please run 'cgpt repair' before adding anything.\n");
128*8617a60dSAndroid Build Coastguard Worker return -1;
129*8617a60dSAndroid Build Coastguard Worker }
130*8617a60dSAndroid Build Coastguard Worker
131*8617a60dSAndroid Build Coastguard Worker return 0;
132*8617a60dSAndroid Build Coastguard Worker }
133*8617a60dSAndroid Build Coastguard Worker
CgptGetUnusedPartition(struct drive * drive,uint32_t * index,CgptAddParams * params)134*8617a60dSAndroid Build Coastguard Worker static int CgptGetUnusedPartition(struct drive *drive, uint32_t *index,
135*8617a60dSAndroid Build Coastguard Worker CgptAddParams *params) {
136*8617a60dSAndroid Build Coastguard Worker uint32_t i;
137*8617a60dSAndroid Build Coastguard Worker uint32_t max_part = GetNumberOfEntries(drive);
138*8617a60dSAndroid Build Coastguard Worker if (params->partition) {
139*8617a60dSAndroid Build Coastguard Worker if (params->partition > max_part) {
140*8617a60dSAndroid Build Coastguard Worker Error("invalid partition number: %d\n", params->partition);
141*8617a60dSAndroid Build Coastguard Worker return -1;
142*8617a60dSAndroid Build Coastguard Worker }
143*8617a60dSAndroid Build Coastguard Worker *index = params->partition - 1;
144*8617a60dSAndroid Build Coastguard Worker return 0;
145*8617a60dSAndroid Build Coastguard Worker } else {
146*8617a60dSAndroid Build Coastguard Worker // Find next empty partition.
147*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < max_part; i++) {
148*8617a60dSAndroid Build Coastguard Worker if (IsUnused(drive, PRIMARY, i)) {
149*8617a60dSAndroid Build Coastguard Worker params->partition = i + 1;
150*8617a60dSAndroid Build Coastguard Worker *index = i;
151*8617a60dSAndroid Build Coastguard Worker return 0;
152*8617a60dSAndroid Build Coastguard Worker }
153*8617a60dSAndroid Build Coastguard Worker }
154*8617a60dSAndroid Build Coastguard Worker Error("no unused partitions available\n");
155*8617a60dSAndroid Build Coastguard Worker return -1;
156*8617a60dSAndroid Build Coastguard Worker }
157*8617a60dSAndroid Build Coastguard Worker }
158*8617a60dSAndroid Build Coastguard Worker
CgptSetAttributes(CgptAddParams * params)159*8617a60dSAndroid Build Coastguard Worker int CgptSetAttributes(CgptAddParams *params) {
160*8617a60dSAndroid Build Coastguard Worker struct drive drive;
161*8617a60dSAndroid Build Coastguard Worker
162*8617a60dSAndroid Build Coastguard Worker if (params == NULL)
163*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
164*8617a60dSAndroid Build Coastguard Worker
165*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
166*8617a60dSAndroid Build Coastguard Worker params->drive_size))
167*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
168*8617a60dSAndroid Build Coastguard Worker
169*8617a60dSAndroid Build Coastguard Worker if (CgptCheckAddValidity(&drive)) {
170*8617a60dSAndroid Build Coastguard Worker goto bad;
171*8617a60dSAndroid Build Coastguard Worker }
172*8617a60dSAndroid Build Coastguard Worker
173*8617a60dSAndroid Build Coastguard Worker if (params->partition == 0 ||
174*8617a60dSAndroid Build Coastguard Worker params->partition >= GetNumberOfEntries(&drive)) {
175*8617a60dSAndroid Build Coastguard Worker Error("invalid partition number: %d\n", params->partition);
176*8617a60dSAndroid Build Coastguard Worker goto bad;
177*8617a60dSAndroid Build Coastguard Worker }
178*8617a60dSAndroid Build Coastguard Worker
179*8617a60dSAndroid Build Coastguard Worker SetEntryAttributes(&drive, params->partition - 1, params);
180*8617a60dSAndroid Build Coastguard Worker
181*8617a60dSAndroid Build Coastguard Worker UpdateAllEntries(&drive);
182*8617a60dSAndroid Build Coastguard Worker
183*8617a60dSAndroid Build Coastguard Worker // Write it all out.
184*8617a60dSAndroid Build Coastguard Worker return DriveClose(&drive, 1);
185*8617a60dSAndroid Build Coastguard Worker
186*8617a60dSAndroid Build Coastguard Worker bad:
187*8617a60dSAndroid Build Coastguard Worker DriveClose(&drive, 0);
188*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
189*8617a60dSAndroid Build Coastguard Worker }
190*8617a60dSAndroid Build Coastguard Worker
191*8617a60dSAndroid Build Coastguard Worker // This method gets the partition details such as the attributes, the
192*8617a60dSAndroid Build Coastguard Worker // guids of the partitions, etc. Input is the partition number or the
193*8617a60dSAndroid Build Coastguard Worker // unique id of the partition. Output is populated in the respective
194*8617a60dSAndroid Build Coastguard Worker // fields of params.
CgptGetPartitionDetails(CgptAddParams * params)195*8617a60dSAndroid Build Coastguard Worker int CgptGetPartitionDetails(CgptAddParams *params) {
196*8617a60dSAndroid Build Coastguard Worker struct drive drive;
197*8617a60dSAndroid Build Coastguard Worker int result = CGPT_FAILED;
198*8617a60dSAndroid Build Coastguard Worker int index;
199*8617a60dSAndroid Build Coastguard Worker
200*8617a60dSAndroid Build Coastguard Worker if (params == NULL)
201*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
204*8617a60dSAndroid Build Coastguard Worker params->drive_size))
205*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
206*8617a60dSAndroid Build Coastguard Worker
207*8617a60dSAndroid Build Coastguard Worker if (CgptCheckAddValidity(&drive)) {
208*8617a60dSAndroid Build Coastguard Worker goto bad;
209*8617a60dSAndroid Build Coastguard Worker }
210*8617a60dSAndroid Build Coastguard Worker
211*8617a60dSAndroid Build Coastguard Worker int max_part = GetNumberOfEntries(&drive);
212*8617a60dSAndroid Build Coastguard Worker if (params->partition > 0) {
213*8617a60dSAndroid Build Coastguard Worker if (params->partition >= max_part) {
214*8617a60dSAndroid Build Coastguard Worker Error("invalid partition number: %d\n", params->partition);
215*8617a60dSAndroid Build Coastguard Worker goto bad;
216*8617a60dSAndroid Build Coastguard Worker }
217*8617a60dSAndroid Build Coastguard Worker } else {
218*8617a60dSAndroid Build Coastguard Worker if (!params->set_unique) {
219*8617a60dSAndroid Build Coastguard Worker Error("either partition or unique_id must be specified\n");
220*8617a60dSAndroid Build Coastguard Worker goto bad;
221*8617a60dSAndroid Build Coastguard Worker }
222*8617a60dSAndroid Build Coastguard Worker for (index = 0; index < max_part; index++) {
223*8617a60dSAndroid Build Coastguard Worker GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
224*8617a60dSAndroid Build Coastguard Worker if (GuidEqual(&entry->unique, ¶ms->unique_guid)) {
225*8617a60dSAndroid Build Coastguard Worker params->partition = index + 1;
226*8617a60dSAndroid Build Coastguard Worker break;
227*8617a60dSAndroid Build Coastguard Worker }
228*8617a60dSAndroid Build Coastguard Worker }
229*8617a60dSAndroid Build Coastguard Worker if (index >= max_part) {
230*8617a60dSAndroid Build Coastguard Worker Error("no partitions with the given unique id available\n");
231*8617a60dSAndroid Build Coastguard Worker goto bad;
232*8617a60dSAndroid Build Coastguard Worker }
233*8617a60dSAndroid Build Coastguard Worker }
234*8617a60dSAndroid Build Coastguard Worker index = params->partition - 1;
235*8617a60dSAndroid Build Coastguard Worker
236*8617a60dSAndroid Build Coastguard Worker // GPT-specific code
237*8617a60dSAndroid Build Coastguard Worker GptEntry *entry = GetEntry(&drive.gpt, PRIMARY, index);
238*8617a60dSAndroid Build Coastguard Worker params->begin = entry->starting_lba;
239*8617a60dSAndroid Build Coastguard Worker params->size = entry->ending_lba - entry->starting_lba + 1;
240*8617a60dSAndroid Build Coastguard Worker memcpy(¶ms->type_guid, &entry->type, sizeof(Guid));
241*8617a60dSAndroid Build Coastguard Worker memcpy(¶ms->unique_guid, &entry->unique, sizeof(Guid));
242*8617a60dSAndroid Build Coastguard Worker params->raw_value = entry->attrs.fields.gpt_att;
243*8617a60dSAndroid Build Coastguard Worker
244*8617a60dSAndroid Build Coastguard Worker params->error_counter = GetErrorCounter(&drive, PRIMARY, index);
245*8617a60dSAndroid Build Coastguard Worker params->successful = GetSuccessful(&drive, PRIMARY, index);
246*8617a60dSAndroid Build Coastguard Worker params->tries = GetTries(&drive, PRIMARY, index);
247*8617a60dSAndroid Build Coastguard Worker params->priority = GetPriority(&drive, PRIMARY, index);
248*8617a60dSAndroid Build Coastguard Worker result = CGPT_OK;
249*8617a60dSAndroid Build Coastguard Worker
250*8617a60dSAndroid Build Coastguard Worker bad:
251*8617a60dSAndroid Build Coastguard Worker DriveClose(&drive, 0);
252*8617a60dSAndroid Build Coastguard Worker return result;
253*8617a60dSAndroid Build Coastguard Worker }
254*8617a60dSAndroid Build Coastguard Worker
GptAdd(struct drive * drive,CgptAddParams * params,uint32_t index)255*8617a60dSAndroid Build Coastguard Worker static int GptAdd(struct drive *drive, CgptAddParams *params, uint32_t index) {
256*8617a60dSAndroid Build Coastguard Worker GptEntry *entry, backup;
257*8617a60dSAndroid Build Coastguard Worker int rv;
258*8617a60dSAndroid Build Coastguard Worker
259*8617a60dSAndroid Build Coastguard Worker entry = GetEntry(&drive->gpt, PRIMARY, index);
260*8617a60dSAndroid Build Coastguard Worker memcpy(&backup, entry, sizeof(backup));
261*8617a60dSAndroid Build Coastguard Worker
262*8617a60dSAndroid Build Coastguard Worker if (SetEntryAttributes(drive, index, params) ||
263*8617a60dSAndroid Build Coastguard Worker GptSetEntryAttributes(drive, index, params)) {
264*8617a60dSAndroid Build Coastguard Worker memcpy(entry, &backup, sizeof(*entry));
265*8617a60dSAndroid Build Coastguard Worker return -1;
266*8617a60dSAndroid Build Coastguard Worker }
267*8617a60dSAndroid Build Coastguard Worker
268*8617a60dSAndroid Build Coastguard Worker UpdateAllEntries(drive);
269*8617a60dSAndroid Build Coastguard Worker
270*8617a60dSAndroid Build Coastguard Worker rv = CheckEntries((GptEntry*)drive->gpt.primary_entries,
271*8617a60dSAndroid Build Coastguard Worker (GptHeader*)drive->gpt.primary_header);
272*8617a60dSAndroid Build Coastguard Worker
273*8617a60dSAndroid Build Coastguard Worker if (0 != rv) {
274*8617a60dSAndroid Build Coastguard Worker // If the modified entry is illegal, recover it and return error.
275*8617a60dSAndroid Build Coastguard Worker memcpy(entry, &backup, sizeof(*entry));
276*8617a60dSAndroid Build Coastguard Worker Error("%s\n", GptErrorText(rv));
277*8617a60dSAndroid Build Coastguard Worker Error("");
278*8617a60dSAndroid Build Coastguard Worker PrintCgptAddParams(params);
279*8617a60dSAndroid Build Coastguard Worker return -1;
280*8617a60dSAndroid Build Coastguard Worker }
281*8617a60dSAndroid Build Coastguard Worker
282*8617a60dSAndroid Build Coastguard Worker return 0;
283*8617a60dSAndroid Build Coastguard Worker }
284*8617a60dSAndroid Build Coastguard Worker
CgptAdd(CgptAddParams * params)285*8617a60dSAndroid Build Coastguard Worker int CgptAdd(CgptAddParams *params) {
286*8617a60dSAndroid Build Coastguard Worker struct drive drive;
287*8617a60dSAndroid Build Coastguard Worker uint32_t index;
288*8617a60dSAndroid Build Coastguard Worker
289*8617a60dSAndroid Build Coastguard Worker if (params == NULL)
290*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
291*8617a60dSAndroid Build Coastguard Worker
292*8617a60dSAndroid Build Coastguard Worker if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDWR,
293*8617a60dSAndroid Build Coastguard Worker params->drive_size))
294*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
295*8617a60dSAndroid Build Coastguard Worker
296*8617a60dSAndroid Build Coastguard Worker if (CgptCheckAddValidity(&drive)) {
297*8617a60dSAndroid Build Coastguard Worker goto bad;
298*8617a60dSAndroid Build Coastguard Worker }
299*8617a60dSAndroid Build Coastguard Worker
300*8617a60dSAndroid Build Coastguard Worker if (CgptGetUnusedPartition(&drive, &index, params)) {
301*8617a60dSAndroid Build Coastguard Worker goto bad;
302*8617a60dSAndroid Build Coastguard Worker }
303*8617a60dSAndroid Build Coastguard Worker
304*8617a60dSAndroid Build Coastguard Worker if (GptAdd(&drive, params, index))
305*8617a60dSAndroid Build Coastguard Worker goto bad;
306*8617a60dSAndroid Build Coastguard Worker
307*8617a60dSAndroid Build Coastguard Worker // Write it all out.
308*8617a60dSAndroid Build Coastguard Worker return DriveClose(&drive, 1);
309*8617a60dSAndroid Build Coastguard Worker
310*8617a60dSAndroid Build Coastguard Worker bad:
311*8617a60dSAndroid Build Coastguard Worker DriveClose(&drive, 0);
312*8617a60dSAndroid Build Coastguard Worker return CGPT_FAILED;
313*8617a60dSAndroid Build Coastguard Worker }
314