xref: /aosp_15_r20/external/vboot_reference/cgpt/cgpt_add.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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(&params->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(&params->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, &params->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, &params->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(&params->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, &params->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(&params->type_guid, &entry->type, sizeof(Guid));
241*8617a60dSAndroid Build Coastguard Worker   memcpy(&params->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