• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
32 #include <getopt.h>
33 #include <inttypes.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 
38 #include <cutils/klog.h>
39 
40 #include "commands/partitions.h"
41 #include "debug.h"
42 
43 unsigned int debug_level = DEBUG;
44 //TODO: add tool to generate config file
45 
usage()46 void usage() {
47     fprintf(stderr,
48             "usage: test_gpt [ <option> ] <file>\n"
49             "\n"
50             "options:\n"
51             "  -p                                       print partitions\n"
52             "  -c                                       print config file\n"
53             "  -a                                       adds new partition\n"
54             "  -d                                       deletes partition (-o needed)\n"
55             "\n"
56             "  -n name@startlba,endlba                  new partition detail\n"
57             "  -o                                       old partition name\n"
58             "  -t                                       type guid\n"
59             "  -g                                       partition guid\n"
60             "  -l gpt_location                          specyfies gpt secto\n"
61     );
62 
63 }
64 
65 void printGPT(struct GPT_entry_table *table);
66 void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
67 void deleteGPT(struct GPT_entry_table *table, const char *name);
68 void configPrintGPT(struct GPT_entry_table *table);
69 
main(int argc,char * argv[])70 int main(int argc, char *argv[]) {
71     int print_cmd = 0;
72     int config_cmd = 0;
73     int add_cmd = 0;
74     int del_cmd = 0;
75     int sync_cmd = 0;
76     int c;
77     const char *new_partition = NULL;
78     const char *old_partition = NULL;
79     const char *type_guid = NULL;
80     const char *partition_guid = NULL;
81     unsigned gpt_location = 1;
82 
83     klog_init();
84     klog_set_level(6);
85 
86     const struct option longopts[] = {
87         {"print", no_argument, 0, 'p'},
88         {"config-print", no_argument, 0, 'c'},
89         {"add", no_argument, 0, 'a'},
90         {"del", no_argument, 0, 'd'},
91         {"new", required_argument, 0, 'n'},
92         {"old", required_argument, 0, 'o'},
93         {"type", required_argument, 0, 't'},
94         {"sync", required_argument, 0, 's'},
95         {"guid", required_argument, 0, 'g'},
96         {"location", required_argument, 0, 'l'},
97         {0, 0, 0, 0}
98     };
99 
100     while (1) {
101         c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
102         /* Alphabetical cases */
103         if (c < 0)
104             break;
105         switch (c) {
106         case 'p':
107             print_cmd = 1;
108             break;
109         case 'c':
110             config_cmd = 1;
111             break;
112         case 'a':
113             add_cmd = 1;
114             break;
115         case 'd':
116             del_cmd = 1;
117             break;
118         case 'n':
119             new_partition = optarg;
120             break;
121         case 'o':
122             old_partition = optarg;
123             break;
124         case 't':
125             type_guid = optarg;
126         case 'g':
127             partition_guid = optarg;
128             break;
129         case 's':
130             sync_cmd = 1;
131             break;
132         case 'l':
133             gpt_location = strtoul(optarg, NULL, 10);
134             fprintf(stderr, "Got offset as %d", gpt_location);
135             break;
136         case '?':
137             return 1;
138         default:
139             abort();
140         }
141     }
142 
143     argc -= optind;
144     argv += optind;
145 
146     if (argc < 1) {
147         usage();
148         return 1;
149     }
150 
151     const char *path = argv[0];
152     struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
153     if (table == NULL) {
154         fprintf(stderr, "unable to get GPT table from %s\n", path);
155         return 1;
156     }
157 
158     if (add_cmd)
159         addGPT(table, new_partition, partition_guid, type_guid);
160     if (del_cmd)
161         deleteGPT(table, old_partition);
162     if (print_cmd)
163         printGPT(table);
164     if (config_cmd)
165         configPrintGPT(table);
166     if (sync_cmd)
167         GPT_sync(table);
168 
169     GPT_release_device(table);
170 
171     return 0;
172 }
173 
printGPT(struct GPT_entry_table * table)174 void printGPT(struct GPT_entry_table *table) {
175     struct GPT_entry_raw *entry = table->entries;
176     unsigned n, m;
177     char name[GPT_NAMELEN + 1];
178 
179     printf("ptn  start block   end block     name\n");
180     printf("---- ------------- -------------\n");
181 
182     for (n = 0; n < table->header->entries_count; n++, entry++) {
183         if (entry->type_guid[0] == 0)
184             continue;
185         for (m = 0; m < GPT_NAMELEN; m++) {
186             name[m] = entry->name[m] & 127;
187         }
188         name[m] = 0;
189         printf("#%03d %13"PRId64" %13"PRId64" %s\n",
190             n + 1, entry->first_lba, entry->last_lba, name);
191     }
192 }
193 
configPrintGPT(struct GPT_entry_table * table)194 void configPrintGPT(struct GPT_entry_table *table) {
195     struct GPT_entry_raw *entry = table->entries;
196     unsigned n, m;
197     char name[GPT_NAMELEN + 1];
198     char temp_guid[17];
199     temp_guid[16] = 0;
200 
201     printf("header_lba %"PRId64"\n", table->header->current_lba);
202     printf("backup_lba %"PRId64"\n", table->header->backup_lba);
203     printf("first_lba %"PRId64"\n", table->header->first_usable_lba);
204     printf("last_lba %"PRId64"\n", table->header->last_usable_lba);
205     printf("entries_lba %"PRId64"\n", table->header->entries_lba);
206     snprintf(temp_guid, 17, "%s", table->header->disk_guid);
207     printf("guid \"%s\"", temp_guid);
208 
209     printf("\npartitions {\n");
210 
211     for (n = 0; n < table->header->entries_count; n++, entry++) {
212         uint64_t size = entry->last_lba - entry->first_lba + 1;
213 
214         if (entry->type_guid[0] == 0)
215             continue;
216         for (m = 0; m < GPT_NAMELEN; m++) {
217             name[m] = entry->name[m] & 127;
218         }
219         name[m] = 0;
220 
221         printf("    %s {\n", name);
222         snprintf(temp_guid, 17, "%s", entry->partition_guid);
223         printf("        guid \"%s\"\n", temp_guid);
224         printf("        first_lba %"PRId64"\n", entry->first_lba);
225         printf("        partition_size %"PRId64"\n", size);
226         if (entry->flags & GPT_FLAG_SYSTEM)
227             printf("        system\n");
228         if (entry->flags & GPT_FLAG_BOOTABLE)
229             printf("        bootable\n");
230         if (entry->flags & GPT_FLAG_READONLY)
231             printf("        readonly\n");
232         if (entry->flags & GPT_FLAG_DOAUTOMOUNT)
233             printf("        automount\n");
234         printf("    }\n\n");
235     }
236     printf("}\n");
237 }
238 
addGPT(struct GPT_entry_table * table,const char * str,const char * guid,const char * tguid)239 void addGPT(struct GPT_entry_table *table, const char *str  , const char *guid, const char *tguid) {
240     char *c, *c2;
241     char *arg = malloc(strlen(str));
242     char *name = arg;
243     unsigned start, end;
244     strcpy(arg, str);
245     if (guid == NULL || tguid == NULL) {
246         fprintf(stderr, "Type guid and partion guid needed");
247         free(arg);
248         return;
249     }
250 
251     c = strchr(arg, '@');
252 
253     if (c == NULL) {
254         fprintf(stderr, "Wrong entry format");
255         free(arg);
256         return;
257     }
258 
259     *c++ = '\0';
260 
261     c2 = strchr(c, ',');
262 
263     if (c2 == NULL) {
264         fprintf(stderr, "Wrong entry format");
265         free(arg);
266         return;
267     }
268 
269     start = strtoul(c, NULL, 10);
270     *c2++ = '\0';
271     end = strtoul(c2, NULL, 10);
272 
273     struct GPT_entry_raw data;
274     strncpy((char *)data.partition_guid, guid, 15);
275     data.partition_guid[15] = '\0';
276     strncpy((char *)data.type_guid, tguid, 15);
277     data.type_guid[15] = '\0';
278     GPT_to_UTF16(data.name, name, GPT_NAMELEN);
279     data.first_lba = start;
280     data.last_lba = end;
281 
282     fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
283     GPT_add_entry(table, &data);
284     free(arg);
285 }
286 
deleteGPT(struct GPT_entry_table * table,const char * name)287 void deleteGPT(struct GPT_entry_table *table, const char *name) {
288     struct GPT_entry_raw *entry;
289 
290     if (name == NULL) {
291         fprintf(stderr, "Need partition name");
292         return;
293     }
294 
295     entry = GPT_get_pointer_by_name(table, name);
296 
297     if (!entry) {
298         fprintf(stderr, "Unable to find partition: %s", name);
299         return;
300     }
301     GPT_delete_entry(table, entry);
302 }
303 
304