blob: 2b65a012d0a429371184e5df13a72a61a11b7c49 [file] [log] [blame]
Szymon Starzyckib6c5f282013-07-24 17:08:04 -07001/*
2 * Copyright (c) 2009-2013, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google, Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
Elliott Hughes4f241252014-01-14 16:17:08 -080032#include <getopt.h>
33#include <inttypes.h>
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070034#include <stdio.h>
35#include <stdlib.h>
Elliott Hughesa744b052015-01-28 11:37:57 -080036#include <string.h>
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070037#include <unistd.h>
38
39#include <cutils/klog.h>
40
41#include "commands/partitions.h"
42#include "debug.h"
43
44unsigned int debug_level = DEBUG;
45//TODO: add tool to generate config file
46
47void usage() {
48 fprintf(stderr,
49 "usage: test_gpt [ <option> ] <file>\n"
50 "\n"
51 "options:\n"
52 " -p print partitions\n"
53 " -c print config file\n"
54 " -a adds new partition\n"
55 " -d deletes partition (-o needed)\n"
56 "\n"
57 " -n name@startlba,endlba new partition detail\n"
58 " -o old partition name\n"
59 " -t type guid\n"
60 " -g partition guid\n"
61 " -l gpt_location specyfies gpt secto\n"
62 );
63
64}
65
66void printGPT(struct GPT_entry_table *table);
67void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
68void deleteGPT(struct GPT_entry_table *table, const char *name);
69void configPrintGPT(struct GPT_entry_table *table);
70
71int main(int argc, char *argv[]) {
72 int print_cmd = 0;
73 int config_cmd = 0;
74 int add_cmd = 0;
75 int del_cmd = 0;
76 int sync_cmd = 0;
77 int c;
78 const char *new_partition = NULL;
79 const char *old_partition = NULL;
80 const char *type_guid = NULL;
81 const char *partition_guid = NULL;
82 unsigned gpt_location = 1;
83
84 klog_init();
85 klog_set_level(6);
86
87 const struct option longopts[] = {
88 {"print", no_argument, 0, 'p'},
89 {"config-print", no_argument, 0, 'c'},
90 {"add", no_argument, 0, 'a'},
91 {"del", no_argument, 0, 'd'},
92 {"new", required_argument, 0, 'n'},
93 {"old", required_argument, 0, 'o'},
94 {"type", required_argument, 0, 't'},
95 {"sync", required_argument, 0, 's'},
96 {"guid", required_argument, 0, 'g'},
97 {"location", required_argument, 0, 'l'},
98 {0, 0, 0, 0}
99 };
100
101 while (1) {
102 c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
103 /* Alphabetical cases */
104 if (c < 0)
105 break;
106 switch (c) {
107 case 'p':
108 print_cmd = 1;
109 break;
110 case 'c':
111 config_cmd = 1;
112 break;
113 case 'a':
114 add_cmd = 1;
115 break;
116 case 'd':
117 del_cmd = 1;
118 break;
119 case 'n':
120 new_partition = optarg;
121 break;
122 case 'o':
123 old_partition = optarg;
124 break;
125 case 't':
126 type_guid = optarg;
127 case 'g':
128 partition_guid = optarg;
129 break;
130 case 's':
131 sync_cmd = 1;
132 break;
133 case 'l':
134 gpt_location = strtoul(optarg, NULL, 10);
135 fprintf(stderr, "Got offset as %d", gpt_location);
136 break;
137 case '?':
138 return 1;
139 default:
140 abort();
141 }
142 }
143
144 argc -= optind;
145 argv += optind;
146
147 if (argc < 1) {
148 usage();
149 return 1;
150 }
151
152 const char *path = argv[0];
153 struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
154 if (table == NULL) {
155 fprintf(stderr, "unable to get GPT table from %s\n", path);
156 return 1;
157 }
158
Szymon Starzyckib6c5f282013-07-24 17:08:04 -0700159 if (add_cmd)
160 addGPT(table, new_partition, partition_guid, type_guid);
161 if (del_cmd)
162 deleteGPT(table, old_partition);
163 if (print_cmd)
164 printGPT(table);
165 if (config_cmd)
166 configPrintGPT(table);
167 if (sync_cmd)
168 GPT_sync(table);
169
170 GPT_release_device(table);
171
172 return 0;
173}
174
175void printGPT(struct GPT_entry_table *table) {
176 struct GPT_entry_raw *entry = table->entries;
177 unsigned n, m;
178 char name[GPT_NAMELEN + 1];
179
180 printf("ptn start block end block name\n");
181 printf("---- ------------- -------------\n");
182
183 for (n = 0; n < table->header->entries_count; n++, entry++) {
184 if (entry->type_guid[0] == 0)
185 continue;
186 for (m = 0; m < GPT_NAMELEN; m++) {
187 name[m] = entry->name[m] & 127;
188 }
189 name[m] = 0;
Elliott Hughes4f241252014-01-14 16:17:08 -0800190 printf("#%03d %13"PRId64" %13"PRId64" %s\n",
Szymon Starzyckib6c5f282013-07-24 17:08:04 -0700191 n + 1, entry->first_lba, entry->last_lba, name);
192 }
193}
194
195void configPrintGPT(struct GPT_entry_table *table) {
196 struct GPT_entry_raw *entry = table->entries;
197 unsigned n, m;
198 char name[GPT_NAMELEN + 1];
Szymon Starzyckib88fa322013-09-17 14:17:32 -0700199 char temp_guid[17];
200 temp_guid[16] = 0;
Szymon Starzyckib6c5f282013-07-24 17:08:04 -0700201
Elliott Hughes4f241252014-01-14 16:17:08 -0800202 printf("header_lba %"PRId64"\n", table->header->current_lba);
203 printf("backup_lba %"PRId64"\n", table->header->backup_lba);
204 printf("first_lba %"PRId64"\n", table->header->first_usable_lba);
205 printf("last_lba %"PRId64"\n", table->header->last_usable_lba);
206 printf("entries_lba %"PRId64"\n", table->header->entries_lba);
Szymon Starzyckib88fa322013-09-17 14:17:32 -0700207 snprintf(temp_guid, 17, "%s", table->header->disk_guid);
208 printf("guid \"%s\"", temp_guid);
Szymon Starzyckib6c5f282013-07-24 17:08:04 -0700209
210 printf("\npartitions {\n");
211
212 for (n = 0; n < table->header->entries_count; n++, entry++) {
213 uint64_t size = entry->last_lba - entry->first_lba + 1;
214
215 if (entry->type_guid[0] == 0)
216 continue;
217 for (m = 0; m < GPT_NAMELEN; m++) {
218 name[m] = entry->name[m] & 127;
219 }
220 name[m] = 0;
221
222 printf(" %s {\n", name);
Szymon Starzyckib88fa322013-09-17 14:17:32 -0700223 snprintf(temp_guid, 17, "%s", entry->partition_guid);
224 printf(" guid \"%s\"\n", temp_guid);
Elliott Hughes4f241252014-01-14 16:17:08 -0800225 printf(" first_lba %"PRId64"\n", entry->first_lba);
226 printf(" partition_size %"PRId64"\n", size);
Szymon Starzyckib88fa322013-09-17 14:17:32 -0700227 if (entry->flags & GPT_FLAG_SYSTEM)
228 printf(" system\n");
229 if (entry->flags & GPT_FLAG_BOOTABLE)
230 printf(" bootable\n");
231 if (entry->flags & GPT_FLAG_READONLY)
232 printf(" readonly\n");
233 if (entry->flags & GPT_FLAG_DOAUTOMOUNT)
234 printf(" automount\n");
Szymon Starzyckib6c5f282013-07-24 17:08:04 -0700235 printf(" }\n\n");
236 }
237 printf("}\n");
238}
239
240void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) {
241 char *c, *c2;
242 char *arg = malloc(strlen(str));
243 char *name = arg;
244 unsigned start, end;
245 strcpy(arg, str);
246 if (guid == NULL || tguid == NULL) {
247 fprintf(stderr, "Type guid and partion guid needed");
248 free(arg);
249 return;
250 }
251
252 c = strchr(arg, '@');
253
254 if (c == NULL) {
255 fprintf(stderr, "Wrong entry format");
256 free(arg);
257 return;
258 }
259
260 *c++ = '\0';
261
262 c2 = strchr(c, ',');
263
264 if (c2 == NULL) {
265 fprintf(stderr, "Wrong entry format");
266 free(arg);
267 return;
268 }
269
270 start = strtoul(c, NULL, 10);
271 *c2++ = '\0';
272 end = strtoul(c2, NULL, 10);
273
274 struct GPT_entry_raw data;
275 strncpy((char *)data.partition_guid, guid, 15);
276 data.partition_guid[15] = '\0';
277 strncpy((char *)data.type_guid, tguid, 15);
278 data.type_guid[15] = '\0';
279 GPT_to_UTF16(data.name, name, GPT_NAMELEN);
280 data.first_lba = start;
281 data.last_lba = end;
282
283 fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
284 GPT_add_entry(table, &data);
285 free(arg);
286}
287
288void deleteGPT(struct GPT_entry_table *table, const char *name) {
289 struct GPT_entry_raw *entry;
290
291 if (name == NULL) {
292 fprintf(stderr, "Need partition name");
293 return;
294 }
295
296 entry = GPT_get_pointer_by_name(table, name);
297
298 if (!entry) {
299 fprintf(stderr, "Unable to find partition: %s", name);
300 return;
301 }
302 GPT_delete_entry(table, entry);
303}
304