]> Git Repo - J-u-boot.git/blame - disk/part.c
tools: relocate-rela: adjust le64_to_cpu -> le32_to_cpu in decode_elf32()
[J-u-boot.git] / disk / part.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
affae2bf
WD
2/*
3 * (C) Copyright 2001
4 * Wolfgang Denk, DENX Software Engineering, [email protected].
affae2bf
WD
5 */
6
7#include <common.h>
e6f6f9e6 8#include <blk.h>
affae2bf 9#include <command.h>
7b51b576 10#include <env.h>
96e5b03c 11#include <errno.h>
affae2bf 12#include <ide.h>
f7ae49fc 13#include <log.h>
10a37fd7 14#include <malloc.h>
735dd97b 15#include <part.h>
251cee0d 16#include <ubifs_uboot.h>
affae2bf
WD
17
18#undef PART_DEBUG
19
20#ifdef PART_DEBUG
21#define PRINTF(fmt,args...) printf (fmt ,##args)
22#else
23#define PRINTF(fmt,args...)
24#endif
25
30789095
SP
26/* Check all partition types */
27#define PART_TYPE_ALL -1
28
d4729269 29static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc)
96e5b03c
SG
30{
31 struct part_driver *drv =
32 ll_entry_start(struct part_driver, part_driver);
33 const int n_ents = ll_entry_count(struct part_driver, part_driver);
34 struct part_driver *entry;
35
d4729269
KY
36 if (dev_desc->part_type == PART_TYPE_UNKNOWN) {
37 for (entry = drv; entry != drv + n_ents; entry++) {
38 int ret;
39
40 ret = entry->test(dev_desc);
41 if (!ret) {
42 dev_desc->part_type = entry->part_type;
43 return entry;
44 }
45 }
46 } else {
47 for (entry = drv; entry != drv + n_ents; entry++) {
48 if (dev_desc->part_type == entry->part_type)
49 return entry;
50 }
96e5b03c
SG
51 }
52
53 /* Not found */
54 return NULL;
55}
56
4101f687 57static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
735dd97b 58{
6dd9faf8
SG
59 struct blk_desc *dev_desc;
60 int ret;
735dd97b 61
a51eb8de
SG
62 if (!blk_enabled())
63 return NULL;
8149b150 64 dev_desc = blk_get_devnum_by_uclass_idname(ifname, dev);
6dd9faf8
SG
65 if (!dev_desc) {
66 debug("%s: No device for iface '%s', dev %d\n", __func__,
67 ifname, dev);
7e71dc68 68 return NULL;
735dd97b 69 }
6dd9faf8
SG
70 ret = blk_dselect_hwpart(dev_desc, hwpart);
71 if (ret) {
72 debug("%s: Failed to select h/w partition: err-%d\n", __func__,
73 ret);
74 return NULL;
75 }
76
77 return dev_desc;
735dd97b 78}
336b6f90 79
db1d9e78 80struct blk_desc *blk_get_dev(const char *ifname, int dev)
336b6f90 81{
a51eb8de
SG
82 if (!blk_enabled())
83 return NULL;
336b6f90 84
a51eb8de 85 return get_dev_hwpart(ifname, dev, 0);
735dd97b 86}
affae2bf
WD
87
88/* ------------------------------------------------------------------------- */
89/*
90 * reports device info to the user
91 */
69a2a4d9 92
42dfe7a1 93#ifdef CONFIG_LBA48
69a2a4d9 94typedef uint64_t lba512_t;
c40b2956 95#else
69a2a4d9 96typedef lbaint_t lba512_t;
c40b2956 97#endif
affae2bf 98
69a2a4d9 99/*
a9d1c0e2
HS
100 * Overflowless variant of (block_count * mul_by / 2**right_shift)
101 * when 2**right_shift > mul_by
69a2a4d9 102 */
a9d1c0e2
HS
103static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by,
104 int right_shift)
69a2a4d9
ST
105{
106 lba512_t bc_quot, bc_rem;
107
108 /* x * m / d == x / d * m + (x % d) * m / d */
a9d1c0e2
HS
109 bc_quot = block_count >> right_shift;
110 bc_rem = block_count - (bc_quot << right_shift);
111 return bc_quot * mul_by + ((bc_rem * mul_by) >> right_shift);
69a2a4d9
ST
112}
113
ef4b66bc 114void dev_print(struct blk_desc *dev_desc)
69a2a4d9
ST
115{
116 lba512_t lba512; /* number of blocks if 512bytes block size */
117
af75a45d
WD
118 if (dev_desc->type == DEV_TYPE_UNKNOWN) {
119 puts ("not available\n");
120 return;
121 }
122
8149b150 123 switch (dev_desc->uclass_id) {
e33a5c6b 124 case UCLASS_SCSI:
574b3195
DZ
125 printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
126 dev_desc->target,dev_desc->lun,
affae2bf 127 dev_desc->vendor,
574b3195
DZ
128 dev_desc->product,
129 dev_desc->revision);
130 break;
e33a5c6b
SG
131 case UCLASS_IDE:
132 case UCLASS_AHCI:
c7057b52
DL
133 printf ("Model: %s Firm: %s Ser#: %s\n",
134 dev_desc->vendor,
135 dev_desc->revision,
136 dev_desc->product);
574b3195 137 break;
e33a5c6b
SG
138 case UCLASS_MMC:
139 case UCLASS_USB:
140 case UCLASS_NVME:
141 case UCLASS_PVBLOCK:
95201811 142 case UCLASS_HOST:
47bebe34
NCL
143 printf ("Vendor: %s Rev: %s Prod: %s\n",
144 dev_desc->vendor,
145 dev_desc->revision,
146 dev_desc->product);
147 break;
e33a5c6b 148 case UCLASS_VIRTIO:
4ad54ec4
TT
149 printf("%s VirtIO Block Device\n", dev_desc->vendor);
150 break;
ef4b66bc
SG
151 case UCLASS_EFI_MEDIA:
152 printf("EFI media Block Device %d\n", dev_desc->devnum);
153 break;
e33a5c6b 154 case UCLASS_INVALID:
6e24a1eb
RB
155 puts("device type unknown\n");
156 return;
574b3195 157 default:
8149b150 158 printf("Unhandled device type: %i\n", dev_desc->uclass_id);
574b3195 159 return;
affae2bf
WD
160 }
161 puts (" Type: ");
162 if (dev_desc->removable)
163 puts ("Removable ");
164 switch (dev_desc->type & 0x1F) {
726c0f1e
DZ
165 case DEV_TYPE_HARDDISK:
166 puts ("Hard Disk");
167 break;
168 case DEV_TYPE_CDROM:
169 puts ("CD ROM");
170 break;
171 case DEV_TYPE_OPDISK:
172 puts ("Optical Device");
173 break;
174 case DEV_TYPE_TAPE:
175 puts ("Tape");
176 break;
177 default:
178 printf ("# %02X #", dev_desc->type & 0x1F);
179 break;
affae2bf
WD
180 }
181 puts ("\n");
33699df1 182 if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
affae2bf 183 ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
c40b2956 184 lbaint_t lba;
6e592385
WD
185
186 lba = dev_desc->lba;
affae2bf 187
c40b2956 188 lba512 = (lba * (dev_desc->blksz/512));
affae2bf 189 /* round to 1 digit */
214b3f31 190 /* 2048 = (1024 * 1024) / 512 MB */
17416eaf 191 mb = lba512_muldiv(lba512, 10, 11);
69a2a4d9 192
affae2bf
WD
193 mb_quot = mb / 10;
194 mb_rem = mb - (10 * mb_quot);
195
196 gb = mb / 1024;
197 gb_quot = gb / 10;
198 gb_rem = gb - (10 * gb_quot);
42dfe7a1 199#ifdef CONFIG_LBA48
6e592385 200 if (dev_desc->lba48)
c40b2956
WD
201 printf (" Supports 48-bit addressing\n");
202#endif
4b142feb 203#if defined(CONFIG_SYS_64BIT_LBA)
139f7b1d 204 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n",
c40b2956
WD
205 mb_quot, mb_rem,
206 gb_quot, gb_rem,
207 lba,
208 dev_desc->blksz);
209#else
139f7b1d 210 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n",
affae2bf
WD
211 mb_quot, mb_rem,
212 gb_quot, gb_rem,
c40b2956 213 (ulong)lba,
affae2bf 214 dev_desc->blksz);
c40b2956 215#endif
affae2bf
WD
216 } else {
217 puts (" Capacity: not available\n");
218 }
219}
affae2bf 220
3e8bd469 221void part_init(struct blk_desc *dev_desc)
affae2bf 222{
96e5b03c
SG
223 struct part_driver *drv =
224 ll_entry_start(struct part_driver, part_driver);
225 const int n_ents = ll_entry_count(struct part_driver, part_driver);
226 struct part_driver *entry;
affae2bf 227
8149b150 228 blkcache_invalidate(dev_desc->uclass_id, dev_desc->devnum);
e40cf34a 229
99d2c205 230 dev_desc->part_type = PART_TYPE_UNKNOWN;
96e5b03c
SG
231 for (entry = drv; entry != drv + n_ents; entry++) {
232 int ret;
233
234 ret = entry->test(dev_desc);
235 debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret);
236 if (!ret) {
237 dev_desc->part_type = entry->part_type;
238 break;
239 }
240 }
affae2bf
WD
241}
242
96e5b03c
SG
243static void print_part_header(const char *type, struct blk_desc *dev_desc)
244{
f18fa31c 245#if CONFIG_IS_ENABLED(MAC_PARTITION) || \
b0cf7339 246 CONFIG_IS_ENABLED(DOS_PARTITION) || \
1acc0087 247 CONFIG_IS_ENABLED(ISO_PARTITION) || \
863c5b6c 248 CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
bd42a942 249 CONFIG_IS_ENABLED(EFI_PARTITION)
affae2bf 250 puts ("\nPartition Map for ");
8149b150 251 switch (dev_desc->uclass_id) {
e33a5c6b 252 case UCLASS_IDE:
726c0f1e
DZ
253 puts ("IDE");
254 break;
e33a5c6b 255 case UCLASS_AHCI:
726c0f1e
DZ
256 puts ("SATA");
257 break;
e33a5c6b 258 case UCLASS_SCSI:
726c0f1e
DZ
259 puts ("SCSI");
260 break;
e33a5c6b 261 case UCLASS_USB:
726c0f1e
DZ
262 puts ("USB");
263 break;
e33a5c6b 264 case UCLASS_MMC:
8f3b9642
LW
265 puts ("MMC");
266 break;
95201811 267 case UCLASS_HOST:
ffab6945
ZZ
268 puts ("HOST");
269 break;
e33a5c6b 270 case UCLASS_NVME:
ffab6945 271 puts ("NVMe");
f4d8de48 272 break;
e33a5c6b 273 case UCLASS_PVBLOCK:
722bc5b5
AL
274 puts("PV BLOCK");
275 break;
e33a5c6b 276 case UCLASS_VIRTIO:
4ad54ec4
TT
277 puts("VirtIO");
278 break;
e33a5c6b 279 case UCLASS_EFI_MEDIA:
42b7f421
SG
280 puts("EFI");
281 break;
726c0f1e 282 default:
42b7f421 283 puts("UNKNOWN");
726c0f1e 284 break;
affae2bf
WD
285 }
286 printf (" device %d -- Partition Type: %s\n\n",
bcce53d0 287 dev_desc->devnum, type);
0c9c8fb5 288#endif /* any CONFIG_..._PARTITION */
96e5b03c 289}
0c9c8fb5 290
3e8bd469 291void part_print(struct blk_desc *dev_desc)
affae2bf 292{
96e5b03c 293 struct part_driver *drv;
affae2bf 294
d4729269 295 drv = part_driver_lookup_type(dev_desc);
96e5b03c
SG
296 if (!drv) {
297 printf("## Unknown partition table type %x\n",
298 dev_desc->part_type);
affae2bf 299 return;
affae2bf 300 }
96e5b03c
SG
301
302 PRINTF("## Testing for valid %s partition ##\n", drv->name);
303 print_part_header(drv->name, dev_desc);
304 if (drv->print)
305 drv->print(dev_desc);
affae2bf
WD
306}
307
3e8bd469 308int part_get_info(struct blk_desc *dev_desc, int part,
0528979f 309 struct disk_partition *info)
2f501646 310{
96e5b03c 311 struct part_driver *drv;
2f501646 312
a51eb8de 313 if (blk_enabled()) {
b331cd62 314#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
a51eb8de
SG
315 /* The common case is no UUID support */
316 info->uuid[0] = 0;
894bfbbf 317#endif
7561b258 318#ifdef CONFIG_PARTITION_TYPE_GUID
a51eb8de 319 info->type_guid[0] = 0;
7561b258 320#endif
894bfbbf 321
a51eb8de
SG
322 drv = part_driver_lookup_type(dev_desc);
323 if (!drv) {
324 debug("## Unknown partition table type %x\n",
325 dev_desc->part_type);
326 return -EPROTONOSUPPORT;
327 }
328 if (!drv->get_info) {
329 PRINTF("## Driver %s does not have the get_info() method\n",
330 drv->name);
331 return -ENOSYS;
332 }
333 if (drv->get_info(dev_desc, part, info) == 0) {
334 PRINTF("## Valid %s partition found ##\n", drv->name);
335 return 0;
336 }
2f501646 337 }
2f501646 338
59715754 339 return -ENOENT;
2f501646 340}
99d2c205 341
0528979f
SG
342int part_get_info_whole_disk(struct blk_desc *dev_desc,
343 struct disk_partition *info)
4bbcc965
RC
344{
345 info->start = 0;
346 info->size = dev_desc->lba;
347 info->blksz = dev_desc->blksz;
348 info->bootable = 0;
349 strcpy((char *)info->type, BOOT_PART_TYPE);
350 strcpy((char *)info->name, "Whole Disk");
351#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
352 info->uuid[0] = 0;
353#endif
354#ifdef CONFIG_PARTITION_TYPE_GUID
355 info->type_guid[0] = 0;
356#endif
357
358 return 0;
359}
360
ebac37cf
SG
361int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
362 struct blk_desc **dev_desc)
2023e608
SW
363{
364 char *ep;
336b6f90
SW
365 char *dup_str = NULL;
366 const char *dev_str, *hwpart_str;
367 int dev, hwpart;
368
369 hwpart_str = strchr(dev_hwpart_str, '.');
370 if (hwpart_str) {
371 dup_str = strdup(dev_hwpart_str);
372 dup_str[hwpart_str - dev_hwpart_str] = 0;
373 dev_str = dup_str;
374 hwpart_str++;
375 } else {
376 dev_str = dev_hwpart_str;
ecdd57e2 377 hwpart = 0;
336b6f90 378 }
2023e608 379
7e5f460e 380 dev = hextoul(dev_str, &ep);
2023e608
SW
381 if (*ep) {
382 printf("** Bad device specification %s %s **\n",
383 ifname, dev_str);
1598dfcb 384 dev = -EINVAL;
336b6f90
SW
385 goto cleanup;
386 }
387
388 if (hwpart_str) {
7e5f460e 389 hwpart = hextoul(hwpart_str, &ep);
336b6f90
SW
390 if (*ep) {
391 printf("** Bad HW partition specification %s %s **\n",
392 ifname, hwpart_str);
1598dfcb 393 dev = -EINVAL;
336b6f90
SW
394 goto cleanup;
395 }
2023e608
SW
396 }
397
336b6f90 398 *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
2023e608 399 if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
8f690848 400 debug("** Bad device %s %s **\n", ifname, dev_hwpart_str);
59715754 401 dev = -ENODEV;
336b6f90 402 goto cleanup;
2023e608
SW
403 }
404
a51eb8de
SG
405 if (blk_enabled()) {
406 /*
407 * Updates the partition table for the specified hw partition.
408 * Always should be done, otherwise hw partition 0 will return
409 * stale data after displaying a non-zero hw partition.
410 */
8149b150 411 if ((*dev_desc)->uclass_id == UCLASS_MMC)
a51eb8de
SG
412 part_init(*dev_desc);
413 }
99e7fc8a 414
336b6f90
SW
415cleanup:
416 free(dup_str);
2023e608
SW
417 return dev;
418}
419
10a37fd7
SW
420#define PART_UNSPECIFIED -2
421#define PART_AUTO -1
e35929e4 422int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
4101f687 423 struct blk_desc **dev_desc,
0528979f 424 struct disk_partition *info, int allow_whole_dev)
99d2c205 425{
59715754 426 int ret;
10a37fd7
SW
427 const char *part_str;
428 char *dup_str = NULL;
429 const char *dev_str;
99d2c205 430 int dev;
10a37fd7
SW
431 char *ep;
432 int p;
433 int part;
0528979f 434 struct disk_partition tmpinfo;
10a37fd7 435
be2e42fa
HS
436 *dev_desc = NULL;
437 memset(info, 0, sizeof(*info));
438
f676b451 439#if IS_ENABLED(CONFIG_SANDBOX) || IS_ENABLED(CONFIG_SEMIHOSTING)
4d907025 440 /*
3f9eb6e1 441 * Special-case a pseudo block device "hostfs", to allow access to the
4d907025
SW
442 * host's own filesystem.
443 */
be2e42fa 444 if (!strcmp(ifname, "hostfs")) {
4d907025 445 strcpy((char *)info->type, BOOT_PART_TYPE);
f676b451 446 strcpy((char *)info->name, "Host filesystem");
4d907025
SW
447
448 return 0;
449 }
afc1744e 450#endif
4d907025 451
2f03a639 452#if IS_ENABLED(CONFIG_CMD_UBIFS) && !IS_ENABLED(CONFIG_SPL_BUILD)
251cee0d 453 /*
3174cafd 454 * Special-case ubi, ubi goes through a mtd, rather than through
251cee0d
HG
455 * a regular block device.
456 */
be2e42fa 457 if (!strcmp(ifname, "ubi")) {
251cee0d
HG
458 if (!ubifs_is_mounted()) {
459 printf("UBIFS not mounted, use ubifsmount to mount volume first!\n");
59715754 460 return -EINVAL;
251cee0d
HG
461 }
462
251cee0d
HG
463 strcpy((char *)info->type, BOOT_PART_TYPE);
464 strcpy((char *)info->name, "UBI");
251cee0d
HG
465 return 0;
466 }
467#endif
468
10a37fd7 469 /* If no dev_part_str, use bootdevice environment variable */
a10973e7
SW
470 if (!dev_part_str || !strlen(dev_part_str) ||
471 !strcmp(dev_part_str, "-"))
00caae6d 472 dev_part_str = env_get("bootdevice");
10a37fd7
SW
473
474 /* If still no dev_part_str, it's an error */
475 if (!dev_part_str) {
476 printf("** No device specified **\n");
59715754 477 ret = -ENODEV;
10a37fd7
SW
478 goto cleanup;
479 }
480
481 /* Separate device and partition ID specification */
482 part_str = strchr(dev_part_str, ':');
483 if (part_str) {
484 dup_str = strdup(dev_part_str);
485 dup_str[part_str - dev_part_str] = 0;
486 dev_str = dup_str;
487 part_str++;
488 } else {
489 dev_str = dev_part_str;
99d2c205
RH
490 }
491
10a37fd7 492 /* Look up the device */
ebac37cf 493 dev = blk_get_device_by_str(ifname, dev_str, dev_desc);
59715754 494 if (dev < 0) {
192e7012
OB
495 printf("** Bad device specification %s %s **\n",
496 ifname, dev_str);
59715754 497 ret = dev;
10a37fd7 498 goto cleanup;
59715754 499 }
10a37fd7
SW
500
501 /* Convert partition ID string to number */
502 if (!part_str || !*part_str) {
503 part = PART_UNSPECIFIED;
504 } else if (!strcmp(part_str, "auto")) {
505 part = PART_AUTO;
506 } else {
507 /* Something specified -> use exactly that */
7e5f460e 508 part = (int)hextoul(part_str, &ep);
10a37fd7
SW
509 /*
510 * Less than whole string converted,
511 * or request for whole device, but caller requires partition.
512 */
513 if (*ep || (part == 0 && !allow_whole_dev)) {
514 printf("** Bad partition specification %s %s **\n",
515 ifname, dev_part_str);
59715754 516 ret = -ENOENT;
10a37fd7
SW
517 goto cleanup;
518 }
519 }
520
521 /*
522 * No partition table on device,
523 * or user requested partition 0 (entire device).
524 */
525 if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
526 (part == 0)) {
527 if (!(*dev_desc)->lba) {
528 printf("** Bad device size - %s %s **\n", ifname,
529 dev_str);
59715754 530 ret = -EINVAL;
10a37fd7
SW
531 goto cleanup;
532 }
99d2c205 533
10a37fd7
SW
534 /*
535 * If user specified a partition ID other than 0,
536 * or the calling command only accepts partitions,
537 * it's an error.
538 */
539 if ((part > 0) || (!allow_whole_dev)) {
540 printf("** No partition table - %s %s **\n", ifname,
541 dev_str);
59715754 542 ret = -EPROTONOSUPPORT;
10a37fd7 543 goto cleanup;
99d2c205 544 }
10a37fd7 545
50ffc3b6
LY
546 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
547
4bbcc965 548 part_get_info_whole_disk(*dev_desc, info);
99d2c205 549
10a37fd7
SW
550 ret = 0;
551 goto cleanup;
99d2c205
RH
552 }
553
10a37fd7
SW
554 /*
555 * Now there's known to be a partition table,
556 * not specifying a partition means to pick partition 1.
557 */
558 if (part == PART_UNSPECIFIED)
559 part = 1;
560
561 /*
562 * If user didn't specify a partition number, or did specify something
563 * other than "auto", use that partition number directly.
564 */
565 if (part != PART_AUTO) {
3e8bd469 566 ret = part_get_info(*dev_desc, part, info);
10a37fd7
SW
567 if (ret) {
568 printf("** Invalid partition %d **\n", part);
569 goto cleanup;
570 }
571 } else {
572 /*
573 * Find the first bootable partition.
574 * If none are bootable, fall back to the first valid partition.
575 */
576 part = 0;
577 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
3e8bd469 578 ret = part_get_info(*dev_desc, p, info);
10a37fd7
SW
579 if (ret)
580 continue;
581
582 /*
583 * First valid partition, or new better partition?
584 * If so, save partition ID.
585 */
586 if (!part || info->bootable)
587 part = p;
588
589 /* Best possible partition? Stop searching. */
590 if (info->bootable)
591 break;
592
593 /*
594 * We now need to search further for best possible.
595 * If we what we just queried was the best so far,
596 * save the info since we over-write it next loop.
597 */
598 if (part == p)
599 tmpinfo = *info;
600 }
601 /* If we found any acceptable partition */
602 if (part) {
603 /*
604 * If we searched all possible partition IDs,
605 * return the first valid partition we found.
606 */
607 if (p == MAX_SEARCH_PARTITIONS + 1)
608 *info = tmpinfo;
10a37fd7
SW
609 } else {
610 printf("** No valid partitions found **\n");
611 goto cleanup;
612 }
99d2c205
RH
613 }
614 if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
615 printf("** Invalid partition type \"%.32s\""
616 " (expect \"" BOOT_PART_TYPE "\")\n",
617 info->type);
59715754 618 ret = -EINVAL;
10a37fd7 619 goto cleanup;
99d2c205
RH
620 }
621
50ffc3b6
LY
622 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
623
10a37fd7
SW
624 ret = part;
625 goto cleanup;
99d2c205 626
10a37fd7
SW
627cleanup:
628 free(dup_str);
629 return ret;
99d2c205 630}
87b8530f 631
30789095 632int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
0528979f 633 struct disk_partition *info, int part_type)
87b8530f 634{
87b8530f 635 struct part_driver *part_drv;
56670d6f
KY
636 int ret;
637 int i;
638
639 part_drv = part_driver_lookup_type(dev_desc);
640 if (!part_drv)
641 return -1;
50f7b2ef 642
643 if (!part_drv->get_info) {
644 log_debug("## Driver %s does not have the get_info() method\n",
645 part_drv->name);
646 return -ENOSYS;
647 }
648
56670d6f
KY
649 for (i = 1; i < part_drv->max_entries; i++) {
650 ret = part_drv->get_info(dev_desc, i, info);
651 if (ret != 0) {
652 /* no more entries in table */
653 break;
654 }
655 if (strcmp(name, (const char *)info->name) == 0) {
656 /* matched */
657 return i;
87b8530f
PK
658 }
659 }
56670d6f 660
59715754 661 return -ENOENT;
87b8530f 662}
da2ee24d 663
30789095 664int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
0528979f 665 struct disk_partition *info)
30789095
SP
666{
667 return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
668}
669
6eccd1f7
RT
670/**
671 * Get partition info from device number and partition name.
672 *
673 * Parse a device number and partition name string in the form of
81c1aa89
SA
674 * "devicenum.hwpartnum#partition_name", for example "0.1#misc". devicenum and
675 * hwpartnum are both optional, defaulting to 0. If the partition is found,
676 * sets dev_desc and part_info accordingly with the information of the
677 * partition with the given partition_name.
6eccd1f7
RT
678 *
679 * @param[in] dev_iface Device interface
81c1aa89 680 * @param[in] dev_part_str Input string argument, like "0.1#misc"
6eccd1f7
RT
681 * @param[out] dev_desc Place to store the device description pointer
682 * @param[out] part_info Place to store the partition information
185f812c 683 * Return: 0 on success, or a negative on error
6eccd1f7
RT
684 */
685static int part_get_info_by_dev_and_name(const char *dev_iface,
686 const char *dev_part_str,
687 struct blk_desc **dev_desc,
0528979f 688 struct disk_partition *part_info)
6eccd1f7 689{
81c1aa89
SA
690 char *dup_str = NULL;
691 const char *dev_str, *part_str;
692 int ret;
6eccd1f7 693
81c1aa89 694 /* Separate device and partition name specification */
26de4296
SA
695 if (dev_part_str)
696 part_str = strchr(dev_part_str, '#');
697 else
698 part_str = NULL;
699
81c1aa89
SA
700 if (part_str) {
701 dup_str = strdup(dev_part_str);
702 dup_str[part_str - dev_part_str] = 0;
703 dev_str = dup_str;
704 part_str++;
705 } else {
6eccd1f7
RT
706 return -EINVAL;
707 }
6eccd1f7 708
81c1aa89 709 ret = blk_get_device_by_str(dev_iface, dev_str, dev_desc);
fe5a5091 710 if (ret < 0)
81c1aa89
SA
711 goto cleanup;
712
59715754
SA
713 ret = part_get_info_by_name(*dev_desc, part_str, part_info);
714 if (ret < 0)
6eccd1f7 715 printf("Could not find \"%s\" partition\n", part_str);
81c1aa89
SA
716
717cleanup:
718 free(dup_str);
59715754 719 return ret;
6eccd1f7
RT
720}
721
722int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
723 const char *dev_part_str,
724 struct blk_desc **dev_desc,
9f7bb282
SA
725 struct disk_partition *part_info,
726 int allow_whole_dev)
6eccd1f7 727{
59715754
SA
728 int ret;
729
6eccd1f7 730 /* Split the part_name if passed as "$dev_num#part_name". */
59715754
SA
731 ret = part_get_info_by_dev_and_name(dev_iface, dev_part_str,
732 dev_desc, part_info);
733 if (ret >= 0)
734 return ret;
6eccd1f7
RT
735 /*
736 * Couldn't lookup by name, try looking up the partition description
737 * directly.
738 */
59715754 739 ret = blk_get_device_part_str(dev_iface, dev_part_str,
9f7bb282 740 dev_desc, part_info, allow_whole_dev);
59715754 741 if (ret < 0)
6eccd1f7
RT
742 printf("Couldn't find partition %s %s\n",
743 dev_iface, dev_part_str);
59715754 744 return ret;
6eccd1f7
RT
745}
746
da2ee24d
PK
747void part_set_generic_name(const struct blk_desc *dev_desc,
748 int part_num, char *name)
749{
750 char *devtype;
751
8149b150 752 switch (dev_desc->uclass_id) {
e33a5c6b
SG
753 case UCLASS_IDE:
754 case UCLASS_AHCI:
da2ee24d
PK
755 devtype = "hd";
756 break;
e33a5c6b 757 case UCLASS_SCSI:
da2ee24d
PK
758 devtype = "sd";
759 break;
e33a5c6b 760 case UCLASS_USB:
da2ee24d
PK
761 devtype = "usbd";
762 break;
e33a5c6b 763 case UCLASS_MMC:
da2ee24d
PK
764 devtype = "mmcsd";
765 break;
766 default:
767 devtype = "xx";
768 break;
769 }
770
771 sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num);
772}
dcffa442
SG
773
774int part_get_bootable(struct blk_desc *desc)
775{
776 struct disk_partition info;
777 int p;
778
779 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
780 int ret;
781
782 ret = part_get_info(desc, p, &info);
783 if (!ret && info.bootable)
784 return p;
785 }
786
787 return 0;
788}
This page took 0.662376 seconds and 4 git commands to generate.