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