1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 4 * 5 * made from cmd_ext2, which was: 6 * 7 * (C) Copyright 2004 8 * esd gmbh <www.esd-electronics.com> 9 * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 10 * 11 * made from cmd_reiserfs by 12 * 13 * (C) Copyright 2003 - 2004 14 * Sysgo Real-Time Solutions, AG <www.elinos.com> 15 * Pavel Bartusek <pba@sysgo.com> 16 */ 17 18#include <common.h> 19#include <config.h> 20#include <command.h> 21#include <env.h> 22#include <part.h> 23#include <vsprintf.h> 24 25enum cmd_part_info { 26 CMD_PART_INFO_START = 0, 27 CMD_PART_INFO_SIZE, 28 CMD_PART_INFO_NUMBER 29}; 30 31static int do_part_uuid(int argc, char *const argv[]) 32{ 33 int part; 34 struct blk_desc *dev_desc; 35 struct disk_partition info; 36 37 if (argc < 2) 38 return CMD_RET_USAGE; 39 if (argc > 3) 40 return CMD_RET_USAGE; 41 42 part = blk_get_device_part_str(argv[0], argv[1], &dev_desc, &info, 0); 43 if (part < 0) 44 return 1; 45 46 if (argc > 2) 47 env_set(argv[2], info.uuid); 48 else 49 printf("%s\n", info.uuid); 50 51 return 0; 52} 53 54static int do_part_list(int argc, char *const argv[]) 55{ 56 int ret; 57 struct blk_desc *desc; 58 char *var = NULL; 59 bool bootable = false; 60 int i; 61 62 if (argc < 2) 63 return CMD_RET_USAGE; 64 65 if (argc > 2) { 66 for (i = 2; i < argc ; i++) { 67 if (argv[i][0] == '-') { 68 if (!strcmp(argv[i], "-bootable")) { 69 bootable = true; 70 } else { 71 printf("Unknown option %s\n", argv[i]); 72 return CMD_RET_USAGE; 73 } 74 } else { 75 var = argv[i]; 76 break; 77 } 78 } 79 80 /* Loops should have been exited at the last argument, which 81 * as it contained the variable */ 82 if (argc != i + 1) 83 return CMD_RET_USAGE; 84 } 85 86 ret = blk_get_device_by_str(argv[0], argv[1], &desc); 87 if (ret < 0) 88 return 1; 89 90 if (var != NULL) { 91 int p; 92 char str[3 * MAX_SEARCH_PARTITIONS] = { '\0', }; 93 struct disk_partition info; 94 95 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 96 char t[5]; 97 int r = part_get_info(desc, p, &info); 98 99 if (r != 0) 100 continue; 101 102 if (bootable && !info.bootable) 103 continue; 104 105 sprintf(t, "%s%x", str[0] ? " " : "", p); 106 strcat(str, t); 107 } 108 env_set(var, str); 109 return 0; 110 } 111 112 part_print(desc); 113 114 return 0; 115} 116 117static int do_part_info(int argc, char *const argv[], enum cmd_part_info param) 118{ 119 struct blk_desc *desc; 120 struct disk_partition info; 121 char buf[512] = { 0 }; 122 char *endp; 123 int part; 124 int err; 125 int ret; 126 127 if (argc < 3) 128 return CMD_RET_USAGE; 129 if (argc > 4) 130 return CMD_RET_USAGE; 131 132 ret = blk_get_device_by_str(argv[0], argv[1], &desc); 133 if (ret < 0) 134 return 1; 135 136 part = simple_strtoul(argv[2], &endp, 0); 137 if (*endp == '\0') { 138 err = part_get_info(desc, part, &info); 139 if (err) 140 return 1; 141 } else { 142 part = part_get_info_by_name(desc, argv[2], &info); 143 if (part < 0) 144 return 1; 145 } 146 147 switch (param) { 148 case CMD_PART_INFO_START: 149 snprintf(buf, sizeof(buf), LBAF, info.start); 150 break; 151 case CMD_PART_INFO_SIZE: 152 snprintf(buf, sizeof(buf), LBAF, info.size); 153 break; 154 case CMD_PART_INFO_NUMBER: 155 snprintf(buf, sizeof(buf), "0x%x", part); 156 break; 157 default: 158 printf("** Unknown cmd_part_info value: %d\n", param); 159 return 1; 160 } 161 162 if (argc > 3) 163 env_set(argv[3], buf); 164 else 165 printf("%s\n", buf); 166 167 return 0; 168} 169 170static int do_part_start(int argc, char *const argv[]) 171{ 172 return do_part_info(argc, argv, CMD_PART_INFO_START); 173} 174 175static int do_part_size(int argc, char *const argv[]) 176{ 177 return do_part_info(argc, argv, CMD_PART_INFO_SIZE); 178} 179 180static int do_part_number(int argc, char *const argv[]) 181{ 182 return do_part_info(argc, argv, CMD_PART_INFO_NUMBER); 183} 184 185static int do_part_set(int argc, char *const argv[]) 186{ 187 const char *devname, *partstr, *typestr; 188 struct blk_desc *desc; 189 int dev; 190 191 if (argc < 3) 192 return CMD_RET_USAGE; 193 194 /* Look up the device */ 195 devname = argv[0]; 196 partstr = argv[1]; 197 typestr = argv[2]; 198 dev = blk_get_device_by_str(devname, partstr, &desc); 199 if (dev < 0) { 200 printf("** Bad device specification %s %s **\n", devname, 201 partstr); 202 return CMD_RET_FAILURE; 203 } 204 205 desc->part_type = part_get_type_by_name(typestr); 206 if (!desc->part_type) { 207 printf("Unknown partition type '%s'\n", typestr); 208 return CMD_RET_FAILURE; 209 } 210 part_print(desc); 211 212 return 0; 213} 214 215#ifdef CONFIG_PARTITION_TYPE_GUID 216static int do_part_type(int argc, char *const argv[]) 217{ 218 int part; 219 struct blk_desc *dev_desc; 220 struct disk_partition info; 221 222 if (argc < 2) 223 return CMD_RET_USAGE; 224 if (argc > 3) 225 return CMD_RET_USAGE; 226 227 part = blk_get_device_part_str(argv[0], argv[1], &dev_desc, &info, 0); 228 if (part < 0) 229 return 1; 230 231 if (argc > 2) 232 env_set(argv[2], info.type_guid); 233 else 234 printf("%s\n", info.type_guid); 235 236 return 0; 237} 238#endif 239 240static int do_part_types(int argc, char * const argv[]) 241{ 242 struct part_driver *drv = ll_entry_start(struct part_driver, 243 part_driver); 244 const int n_ents = ll_entry_count(struct part_driver, part_driver); 245 struct part_driver *entry; 246 int i = 0; 247 248 puts("Supported partition tables"); 249 250 for (entry = drv; entry != drv + n_ents; entry++) { 251 printf("%c %s", i ? ',' : ':', entry->name); 252 i++; 253 } 254 if (!i) 255 puts(": <none>"); 256 puts("\n"); 257 return CMD_RET_SUCCESS; 258} 259 260static int do_part(struct cmd_tbl *cmdtp, int flag, int argc, 261 char *const argv[]) 262{ 263 if (argc < 2) 264 return CMD_RET_USAGE; 265 266 if (!strcmp(argv[1], "uuid")) 267 return do_part_uuid(argc - 2, argv + 2); 268 else if (!strcmp(argv[1], "list")) 269 return do_part_list(argc - 2, argv + 2); 270 else if (!strcmp(argv[1], "start")) 271 return do_part_start(argc - 2, argv + 2); 272 else if (!strcmp(argv[1], "size")) 273 return do_part_size(argc - 2, argv + 2); 274 else if (!strcmp(argv[1], "number")) 275 return do_part_number(argc - 2, argv + 2); 276 else if (!strcmp(argv[1], "types")) 277 return do_part_types(argc - 2, argv + 2); 278 else if (!strcmp(argv[1], "set")) 279 return do_part_set(argc - 2, argv + 2); 280#ifdef CONFIG_PARTITION_TYPE_GUID 281 else if (!strcmp(argv[1], "type")) 282 return do_part_type(argc - 2, argv + 2); 283#endif 284 return CMD_RET_USAGE; 285} 286 287U_BOOT_CMD( 288 part, CONFIG_SYS_MAXARGS, 1, do_part, 289 "disk partition related commands", 290 "uuid <interface> <dev>:<part>\n" 291 " - print partition UUID\n" 292 "part uuid <interface> <dev>:<part> <varname>\n" 293 " - set environment variable to partition UUID\n" 294 "part list <interface> <dev>\n" 295 " - print a device's partition table\n" 296 "part list <interface> <dev> [flags] <varname>\n" 297 " - set environment variable to the list of partitions\n" 298 " flags can be -bootable (list only bootable partitions)\n" 299 "part start <interface> <dev> <part> <varname>\n" 300 " - set environment variable to the start of the partition (in blocks)\n" 301 " part can be either partition number or partition name\n" 302 "part size <interface> <dev> <part> <varname>\n" 303 " - set environment variable to the size of the partition (in blocks)\n" 304 " part can be either partition number or partition name\n" 305 "part number <interface> <dev> <part> <varname>\n" 306 " - set environment variable to the partition number using the partition name\n" 307 " part must be specified as partition name\n" 308#ifdef CONFIG_PARTITION_TYPE_GUID 309 "part type <interface> <dev>:<part>\n" 310 " - print partition type\n" 311 "part type <interface> <dev>:<part> <varname>\n" 312 " - set environment variable to partition type\n" 313#endif 314 "part set <interface> <dev> type\n" 315 " - set partition type for a device\n" 316 "part types\n" 317 " - list supported partition table types" 318); 319