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 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 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 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 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 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 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