1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <getopt.h>
6 #include <string.h>
7 
8 #include "cgpt.h"
9 #include "vboot_host.h"
10 
11 extern const char* progname;
12 
Usage(void)13 static void Usage(void)
14 {
15   printf("\nUsage: %s add [OPTIONS] DRIVE\n\n"
16          "Add, edit, or remove a partition entry.\n\n"
17          "Options:\n"
18          "  -D NUM       Size (in bytes) of the disk where partitions reside\n"
19          "                 default 0, meaning partitions and GPT structs are\n"
20          "                 both on DRIVE\n"
21          "  -i NUM       Specify partition (default is next available)\n"
22          "  -b NUM       Beginning sector\n"
23          "  -s NUM       Size in sectors\n"
24          "  -t GUID      Partition Type GUID\n"
25          "  -u GUID      Partition Unique ID\n"
26          "  -l LABEL     Label\n"
27          "  -S NUM       set Successful flag (0|1)\n"
28          "  -T NUM       set Tries flag (0-15)\n"
29          "  -P NUM       set Priority flag (0-15)\n"
30          "  -A NUM       set raw 64-bit attribute value\n"
31          "\n"
32          "Use the -i option to modify an existing partition.\n"
33          "The -b, -s, and -t options must be given for new partitions.\n"
34          "\n", progname);
35   PrintTypes();
36 }
37 
cmd_add(int argc,char * argv[])38 int cmd_add(int argc, char *argv[]) {
39 
40   CgptAddParams params;
41   memset(&params, 0, sizeof(params));
42 
43   int c;
44   int errorcnt = 0;
45   char *e = 0;
46 
47   opterr = 0;                     // quiet, you
48   while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:A:D:")) != -1)
49   {
50     switch (c)
51     {
52     case 'D':
53       params.drive_size = strtoull(optarg, &e, 0);
54       if (!*optarg || (e && *e))
55       {
56         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
57         errorcnt++;
58       }
59       break;
60     case 'i':
61       params.partition = (uint32_t)strtoul(optarg, &e, 0);
62       if (!*optarg || (e && *e))
63       {
64         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
65         errorcnt++;
66       }
67       break;
68     case 'b':
69       params.set_begin = 1;
70       params.begin = strtoull(optarg, &e, 0);
71       if (!*optarg || (e && *e))
72       {
73         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
74         errorcnt++;
75       }
76       break;
77     case 's':
78       params.set_size = 1;
79       params.size = strtoull(optarg, &e, 0);
80       if (!*optarg || (e && *e))
81       {
82         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
83         errorcnt++;
84       }
85       break;
86     case 't':
87       params.set_type = 1;
88       if (CGPT_OK != SupportedType(optarg, &params.type_guid) &&
89           CGPT_OK != StrToGuid(optarg, &params.type_guid)) {
90         Error("invalid argument to -%c: %s\n", c, optarg);
91         errorcnt++;
92       }
93       break;
94     case 'u':
95       params.set_unique = 1;
96       if (CGPT_OK != StrToGuid(optarg, &params.unique_guid)) {
97         Error("invalid argument to -%c: %s\n", c, optarg);
98         errorcnt++;
99       }
100       break;
101     case 'l':
102       params.label = optarg;
103       break;
104     case 'S':
105       params.set_successful = 1;
106       params.successful = (uint32_t)strtoul(optarg, &e, 0);
107       if (!*optarg || (e && *e))
108       {
109         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
110         errorcnt++;
111       }
112       if (params.successful < 0 || params.successful > 1) {
113         Error("value for -%c must be between 0 and 1", c);
114         errorcnt++;
115       }
116       break;
117     case 'T':
118       params.set_tries = 1;
119       params.tries = (uint32_t)strtoul(optarg, &e, 0);
120       if (!*optarg || (e && *e))
121       {
122         fprintf(stderr, "%s: invalid argument to -%c: \"%s\"\n",
123                 progname, c, optarg);
124         errorcnt++;
125       }
126       if (params.tries < 0 || params.tries > 15) {
127         Error("value for -%c must be between 0 and 15", c);
128         errorcnt++;
129       }
130       break;
131     case 'P':
132       params.set_priority = 1;
133       params.priority = (uint32_t)strtoul(optarg, &e, 0);
134       if (!*optarg || (e && *e))
135       {
136         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
137         errorcnt++;
138       }
139       if (params.priority < 0 || params.priority > 15) {
140         Error("value for -%c must be between 0 and 15", c);
141         errorcnt++;
142       }
143       break;
144     case 'A':
145       params.set_raw = 1;
146       params.raw_value = strtoull(optarg, &e, 0);
147       if (!*optarg || (e && *e))
148       {
149         Error("invalid argument to -%c: \"%s\"\n", c, optarg);
150         errorcnt++;
151       }
152       break;
153 
154     case 'h':
155       Usage();
156       return CGPT_OK;
157     case '?':
158       Error("unrecognized option: -%c\n", optopt);
159       errorcnt++;
160       break;
161     case ':':
162       Error("missing argument to -%c\n", optopt);
163       errorcnt++;
164       break;
165     default:
166       errorcnt++;
167       break;
168     }
169   }
170   if (errorcnt)
171   {
172     Usage();
173     return CGPT_FAILED;
174   }
175 
176   if (optind >= argc)
177   {
178     Error("missing drive argument\n");
179     return CGPT_FAILED;
180   }
181 
182   params.drive_name = argv[optind];
183 
184   return CgptAdd(&params);
185 }
186