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
11extern const char* progname;
12
13static 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
38int 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