Blame view

disk/part.c 17.5 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
affae2bff   wdenk   Initial revision
2
3
4
  /*
   * (C) Copyright 2001
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
affae2bff   wdenk   Initial revision
5
6
7
8
   */
  
  #include <common.h>
  #include <command.h>
7b51b576d   Simon Glass   env: Move env_get...
9
  #include <env.h>
96e5b03c8   Simon Glass   dm: part: Convert...
10
  #include <errno.h>
affae2bff   wdenk   Initial revision
11
  #include <ide.h>
10a37fd7a   Stephen Warren   disk: get_device_...
12
  #include <malloc.h>
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
13
  #include <part.h>
251cee0db   Hans de Goede   ubifs: Add generi...
14
  #include <ubifs_uboot.h>
affae2bff   wdenk   Initial revision
15
16
17
18
19
20
21
22
  
  #undef	PART_DEBUG
  
  #ifdef	PART_DEBUG
  #define	PRINTF(fmt,args...)	printf (fmt ,##args)
  #else
  #define PRINTF(fmt,args...)
  #endif
307890955   Sam Protsenko   disk: Provide API...
23
24
  /* Check all partition types */
  #define PART_TYPE_ALL		-1
d47292691   Kever Yang   disk: part: scan ...
25
  static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc)
96e5b03c8   Simon Glass   dm: part: Convert...
26
27
28
29
30
  {
  	struct part_driver *drv =
  		ll_entry_start(struct part_driver, part_driver);
  	const int n_ents = ll_entry_count(struct part_driver, part_driver);
  	struct part_driver *entry;
d47292691   Kever Yang   disk: part: scan ...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  	if (dev_desc->part_type == PART_TYPE_UNKNOWN) {
  		for (entry = drv; entry != drv + n_ents; entry++) {
  			int ret;
  
  			ret = entry->test(dev_desc);
  			if (!ret) {
  				dev_desc->part_type = entry->part_type;
  				return entry;
  			}
  		}
  	} else {
  		for (entry = drv; entry != drv + n_ents; entry++) {
  			if (dev_desc->part_type == entry->part_type)
  				return entry;
  		}
96e5b03c8   Simon Glass   dm: part: Convert...
46
47
48
49
50
  	}
  
  	/* Not found */
  	return NULL;
  }
56670d6fb   Kever Yang   disk: part: use c...
51
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
4101f6879   Simon Glass   dm: Drop the bloc...
52
  static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
53
  {
6dd9faf8f   Simon Glass   dm: part: Drop th...
54
55
  	struct blk_desc *dev_desc;
  	int ret;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
56

6dd9faf8f   Simon Glass   dm: part: Drop th...
57
58
59
60
61
  	dev_desc = blk_get_devnum_by_typename(ifname, dev);
  	if (!dev_desc) {
  		debug("%s: No device for iface '%s', dev %d
  ", __func__,
  		      ifname, dev);
7e71dc688   Tim Kientzle   disk/part.c: Fix ...
62
  		return NULL;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
63
  	}
6dd9faf8f   Simon Glass   dm: part: Drop th...
64
65
66
67
68
69
70
71
72
  	ret = blk_dselect_hwpart(dev_desc, hwpart);
  	if (ret) {
  		debug("%s: Failed to select h/w partition: err-%d
  ", __func__,
  		      ret);
  		return NULL;
  	}
  
  	return dev_desc;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
73
  }
336b6f904   Stephen Warren   disk: support dev...
74

db1d9e78e   Simon Glass   dm: blk: Rename g...
75
  struct blk_desc *blk_get_dev(const char *ifname, int dev)
336b6f904   Stephen Warren   disk: support dev...
76
  {
ecdd57e27   Stephen Warren   disk: default to ...
77
  	return get_dev_hwpart(ifname, dev, 0);
336b6f904   Stephen Warren   disk: support dev...
78
  }
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
79
  #else
4101f6879   Simon Glass   dm: Drop the bloc...
80
  struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
336b6f904   Stephen Warren   disk: support dev...
81
82
83
  {
  	return NULL;
  }
db1d9e78e   Simon Glass   dm: blk: Rename g...
84
  struct blk_desc *blk_get_dev(const char *ifname, int dev)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
85
86
87
88
  {
  	return NULL;
  }
  #endif
1811a928c   Adam Ford   Move most CONFIG_...
89
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
90

affae2bff   wdenk   Initial revision
91
92
93
94
  /* ------------------------------------------------------------------------- */
  /*
   * reports device info to the user
   */
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
95

42dfe7a18   wdenk   Code cleanup; mak...
96
  #ifdef CONFIG_LBA48
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
97
  typedef uint64_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
98
  #else
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
99
  typedef lbaint_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
100
  #endif
affae2bff   wdenk   Initial revision
101

69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
102
  /*
a9d1c0e2b   Heinrich Schuchardt   disk: part: renam...
103
104
   * Overflowless variant of (block_count * mul_by / 2**right_shift)
   * when 2**right_shift > mul_by
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
105
   */
a9d1c0e2b   Heinrich Schuchardt   disk: part: renam...
106
107
  static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by,
  			      int right_shift)
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
108
109
110
111
  {
  	lba512_t bc_quot, bc_rem;
  
  	/* x * m / d == x / d * m + (x % d) * m / d */
a9d1c0e2b   Heinrich Schuchardt   disk: part: renam...
112
113
114
  	bc_quot = block_count >> right_shift;
  	bc_rem  = block_count - (bc_quot << right_shift);
  	return bc_quot * mul_by + ((bc_rem * mul_by) >> right_shift);
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
115
  }
4101f6879   Simon Glass   dm: Drop the bloc...
116
  void dev_print (struct blk_desc *dev_desc)
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
117
118
  {
  	lba512_t lba512; /* number of blocks if 512bytes block size */
af75a45d2   Wolfgang Denk   IDE: bail out of ...
119
120
121
122
123
  	if (dev_desc->type == DEV_TYPE_UNKNOWN) {
  		puts ("not available
  ");
  		return;
  	}
8ec6e332e   Tor Krill   Fix incorrect swi...
124
  	switch (dev_desc->if_type) {
574b31951   Detlev Zundel   Fix disk type out...
125
126
127
128
  	case IF_TYPE_SCSI:
  		printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s
  ",
  			dev_desc->target,dev_desc->lun,
affae2bff   wdenk   Initial revision
129
  			dev_desc->vendor,
574b31951   Detlev Zundel   Fix disk type out...
130
131
132
  			dev_desc->product,
  			dev_desc->revision);
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
133
  	case IF_TYPE_ATAPI:
574b31951   Detlev Zundel   Fix disk type out...
134
135
  	case IF_TYPE_IDE:
  	case IF_TYPE_SATA:
c7057b529   Dave Liu   ata: add the supp...
136
137
138
139
140
  		printf ("Model: %s Firm: %s Ser#: %s
  ",
  			dev_desc->vendor,
  			dev_desc->revision,
  			dev_desc->product);
574b31951   Detlev Zundel   Fix disk type out...
141
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
142
143
  	case IF_TYPE_SD:
  	case IF_TYPE_MMC:
47bebe34c   NĂ­colas Carneiro Lebedenco   Fix dev_print whe...
144
  	case IF_TYPE_USB:
ffab6945e   Zhikang Zhang   dm: blk: part: Ad...
145
  	case IF_TYPE_NVME:
47bebe34c   NĂ­colas Carneiro Lebedenco   Fix dev_print whe...
146
147
148
149
150
151
  		printf ("Vendor: %s Rev: %s Prod: %s
  ",
  			dev_desc->vendor,
  			dev_desc->revision,
  			dev_desc->product);
  		break;
4ad54ec4d   Tuomas Tynkkynen   blk: Introduce IF...
152
153
154
155
  	case IF_TYPE_VIRTIO:
  		printf("%s VirtIO Block Device
  ", dev_desc->vendor);
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
156
157
158
159
  	case IF_TYPE_DOC:
  		puts("device type DOC
  ");
  		return;
8ec6e332e   Tor Krill   Fix incorrect swi...
160
  	case IF_TYPE_UNKNOWN:
6e24a1eb1   Remy Bohmer   Add missing devic...
161
162
163
  		puts("device type unknown
  ");
  		return;
574b31951   Detlev Zundel   Fix disk type out...
164
  	default:
6e24a1eb1   Remy Bohmer   Add missing devic...
165
166
  		printf("Unhandled device type: %i
  ", dev_desc->if_type);
574b31951   Detlev Zundel   Fix disk type out...
167
  		return;
affae2bff   wdenk   Initial revision
168
169
170
171
172
  	}
  	puts ("            Type: ");
  	if (dev_desc->removable)
  		puts ("Removable ");
  	switch (dev_desc->type & 0x1F) {
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  	case DEV_TYPE_HARDDISK:
  		puts ("Hard Disk");
  		break;
  	case DEV_TYPE_CDROM:
  		puts ("CD ROM");
  		break;
  	case DEV_TYPE_OPDISK:
  		puts ("Optical Device");
  		break;
  	case DEV_TYPE_TAPE:
  		puts ("Tape");
  		break;
  	default:
  		printf ("# %02X #", dev_desc->type & 0x1F);
  		break;
affae2bff   wdenk   Initial revision
188
189
190
  	}
  	puts ("
  ");
33699df12   Jerry Huang   part: check each ...
191
  	if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
affae2bff   wdenk   Initial revision
192
  		ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
c40b29568   wdenk   * Patch by Rune T...
193
  		lbaint_t lba;
6e5923851   wdenk   * Cleanup, minor ...
194
195
  
  		lba = dev_desc->lba;
affae2bff   wdenk   Initial revision
196

c40b29568   wdenk   * Patch by Rune T...
197
  		lba512 = (lba * (dev_desc->blksz/512));
affae2bff   wdenk   Initial revision
198
  		/* round to 1 digit */
214b3f311   Pavel Machek   cleanup disk/part...
199
  		/* 2048 = (1024 * 1024) / 512 MB */
17416eaff   Heinrich Schuchardt   disk: part: avoid...
200
  		mb = lba512_muldiv(lba512, 10, 11);
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
201

affae2bff   wdenk   Initial revision
202
203
204
205
206
207
  		mb_quot	= mb / 10;
  		mb_rem	= mb - (10 * mb_quot);
  
  		gb = mb / 1024;
  		gb_quot	= gb / 10;
  		gb_rem	= gb - (10 * gb_quot);
42dfe7a18   wdenk   Code cleanup; mak...
208
  #ifdef CONFIG_LBA48
6e5923851   wdenk   * Cleanup, minor ...
209
  		if (dev_desc->lba48)
c40b29568   wdenk   * Patch by Rune T...
210
211
212
  			printf ("            Supports 48-bit addressing
  ");
  #endif
4b142febf   Heiko Schocher   common: delete CO...
213
  #if defined(CONFIG_SYS_64BIT_LBA)
139f7b1de   Jean-Jacques Hiblot   disk: Fixed capac...
214
215
  		printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)
  ",
c40b29568   wdenk   * Patch by Rune T...
216
217
218
219
220
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
  			lba,
  			dev_desc->blksz);
  #else
139f7b1de   Jean-Jacques Hiblot   disk: Fixed capac...
221
222
  		printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)
  ",
affae2bff   wdenk   Initial revision
223
224
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
c40b29568   wdenk   * Patch by Rune T...
225
  			(ulong)lba,
affae2bff   wdenk   Initial revision
226
  			dev_desc->blksz);
c40b29568   wdenk   * Patch by Rune T...
227
  #endif
affae2bff   wdenk   Initial revision
228
229
230
231
232
  	} else {
  		puts ("            Capacity: not available
  ");
  	}
  }
b3aff0cb9   Jon Loeliger   disk/ doc/ lib_*/...
233
  #endif
affae2bff   wdenk   Initial revision
234

1811a928c   Adam Ford   Move most CONFIG_...
235
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
affae2bff   wdenk   Initial revision
236

3e8bd4695   Simon Glass   dm: part: Rename ...
237
  void part_init(struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
238
  {
96e5b03c8   Simon Glass   dm: part: Convert...
239
240
241
242
  	struct part_driver *drv =
  		ll_entry_start(struct part_driver, part_driver);
  	const int n_ents = ll_entry_count(struct part_driver, part_driver);
  	struct part_driver *entry;
affae2bff   wdenk   Initial revision
243

e40cf34a2   Eric Nelson   drivers: block: a...
244
  	blkcache_invalidate(dev_desc->if_type, dev_desc->devnum);
99d2c205d   Rob Herring   disk/part: introd...
245
  	dev_desc->part_type = PART_TYPE_UNKNOWN;
96e5b03c8   Simon Glass   dm: part: Convert...
246
247
248
249
250
251
252
253
254
255
256
  	for (entry = drv; entry != drv + n_ents; entry++) {
  		int ret;
  
  		ret = entry->test(dev_desc);
  		debug("%s: try '%s': ret=%d
  ", __func__, entry->name, ret);
  		if (!ret) {
  			dev_desc->part_type = entry->part_type;
  			break;
  		}
  	}
affae2bff   wdenk   Initial revision
257
  }
96e5b03c8   Simon Glass   dm: part: Convert...
258
259
  static void print_part_header(const char *type, struct blk_desc *dev_desc)
  {
f18fa31cd   Patrick Delaunay   disk: convert CON...
260
  #if CONFIG_IS_ENABLED(MAC_PARTITION) || \
b0cf73393   Patrick Delaunay   disk: convert CON...
261
  	CONFIG_IS_ENABLED(DOS_PARTITION) || \
1acc00878   Patrick Delaunay   disk: convert CON...
262
  	CONFIG_IS_ENABLED(ISO_PARTITION) || \
863c5b6cd   Patrick Delaunay   disk: convert CON...
263
  	CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
bd42a9426   Patrick Delaunay   disk: convert CON...
264
  	CONFIG_IS_ENABLED(EFI_PARTITION)
affae2bff   wdenk   Initial revision
265
266
267
  	puts ("
  Partition Map for ");
  	switch (dev_desc->if_type) {
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  	case IF_TYPE_IDE:
  		puts ("IDE");
  		break;
  	case IF_TYPE_SATA:
  		puts ("SATA");
  		break;
  	case IF_TYPE_SCSI:
  		puts ("SCSI");
  		break;
  	case IF_TYPE_ATAPI:
  		puts ("ATAPI");
  		break;
  	case IF_TYPE_USB:
  		puts ("USB");
  		break;
  	case IF_TYPE_DOC:
  		puts ("DOC");
  		break;
8f3b96427   Lei Wen   mmc: print out pa...
286
287
288
  	case IF_TYPE_MMC:
  		puts ("MMC");
  		break;
f4d8de48f   Henrik Nordström   sandbox: block dr...
289
  	case IF_TYPE_HOST:
ffab6945e   Zhikang Zhang   dm: blk: part: Ad...
290
291
292
293
  		puts ("HOST");
  		break;
  	case IF_TYPE_NVME:
  		puts ("NVMe");
f4d8de48f   Henrik Nordström   sandbox: block dr...
294
  		break;
4ad54ec4d   Tuomas Tynkkynen   blk: Introduce IF...
295
296
297
  	case IF_TYPE_VIRTIO:
  		puts("VirtIO");
  		break;
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
298
299
300
  	default:
  		puts ("UNKNOWN");
  		break;
affae2bff   wdenk   Initial revision
301
302
303
304
  	}
  	printf (" device %d  --   Partition Type: %s
  
  ",
bcce53d04   Simon Glass   dm: block: Rename...
305
  			dev_desc->devnum, type);
0c9c8fb5e   Gabe Black   disk: Make the di...
306
  #endif /* any CONFIG_..._PARTITION */
96e5b03c8   Simon Glass   dm: part: Convert...
307
  }
0c9c8fb5e   Gabe Black   disk: Make the di...
308

3e8bd4695   Simon Glass   dm: part: Rename ...
309
  void part_print(struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
310
  {
96e5b03c8   Simon Glass   dm: part: Convert...
311
  	struct part_driver *drv;
affae2bff   wdenk   Initial revision
312

d47292691   Kever Yang   disk: part: scan ...
313
  	drv = part_driver_lookup_type(dev_desc);
96e5b03c8   Simon Glass   dm: part: Convert...
314
315
316
317
  	if (!drv) {
  		printf("## Unknown partition table type %x
  ",
  		       dev_desc->part_type);
affae2bff   wdenk   Initial revision
318
  		return;
affae2bff   wdenk   Initial revision
319
  	}
96e5b03c8   Simon Glass   dm: part: Convert...
320
321
322
323
324
325
  
  	PRINTF("## Testing for valid %s partition ##
  ", drv->name);
  	print_part_header(drv->name, dev_desc);
  	if (drv->print)
  		drv->print(dev_desc);
affae2bff   wdenk   Initial revision
326
  }
1811a928c   Adam Ford   Move most CONFIG_...
327
  #endif /* CONFIG_HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
328

3e8bd4695   Simon Glass   dm: part: Rename ...
329
  int part_get_info(struct blk_desc *dev_desc, int part,
3f9eb6e10   Pavel Machek   whitespace cleanups
330
  		       disk_partition_t *info)
2f5016462   Stephen Warren   disk: make get_pa...
331
  {
1811a928c   Adam Ford   Move most CONFIG_...
332
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
96e5b03c8   Simon Glass   dm: part: Convert...
333
  	struct part_driver *drv;
2f5016462   Stephen Warren   disk: make get_pa...
334

b331cd620   Patrick Delaunay   cmd, disk: conver...
335
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
894bfbbfb   Stephen Warren   disk: part_efi: p...
336
337
338
  	/* The common case is no UUID support */
  	info->uuid[0] = 0;
  #endif
7561b258a   Patrick Delaunay   gpt: add optional...
339
340
341
  #ifdef CONFIG_PARTITION_TYPE_GUID
  	info->type_guid[0] = 0;
  #endif
894bfbbfb   Stephen Warren   disk: part_efi: p...
342

d47292691   Kever Yang   disk: part: scan ...
343
  	drv = part_driver_lookup_type(dev_desc);
96e5b03c8   Simon Glass   dm: part: Convert...
344
345
346
347
348
349
350
  	if (!drv) {
  		debug("## Unknown partition table type %x
  ",
  		      dev_desc->part_type);
  		return -EPROTONOSUPPORT;
  	}
  	if (!drv->get_info) {
2ae67aec5   Nishanth Menon   dm: part: fix mis...
351
352
353
  		PRINTF("## Driver %s does not have the get_info() method
  ",
  		       drv->name);
96e5b03c8   Simon Glass   dm: part: Convert...
354
355
356
357
358
359
  		return -ENOSYS;
  	}
  	if (drv->get_info(dev_desc, part, info) == 0) {
  		PRINTF("## Valid %s partition found ##
  ", drv->name);
  		return 0;
2f5016462   Stephen Warren   disk: make get_pa...
360
  	}
1811a928c   Adam Ford   Move most CONFIG_...
361
  #endif /* CONFIG_HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
362
363
364
  
  	return -1;
  }
99d2c205d   Rob Herring   disk/part: introd...
365

4bbcc965f   Rob Clark   fs: add fs_readdir()
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info)
  {
  	info->start = 0;
  	info->size = dev_desc->lba;
  	info->blksz = dev_desc->blksz;
  	info->bootable = 0;
  	strcpy((char *)info->type, BOOT_PART_TYPE);
  	strcpy((char *)info->name, "Whole Disk");
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
  	info->uuid[0] = 0;
  #endif
  #ifdef CONFIG_PARTITION_TYPE_GUID
  	info->type_guid[0] = 0;
  #endif
  
  	return 0;
  }
ebac37cfb   Simon Glass   dm: blk: Rename g...
383
384
  int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
  			  struct blk_desc **dev_desc)
2023e6086   Stephen Warren   disk: introduce g...
385
386
  {
  	char *ep;
336b6f904   Stephen Warren   disk: support dev...
387
388
389
390
391
392
393
394
395
396
397
398
  	char *dup_str = NULL;
  	const char *dev_str, *hwpart_str;
  	int dev, hwpart;
  
  	hwpart_str = strchr(dev_hwpart_str, '.');
  	if (hwpart_str) {
  		dup_str = strdup(dev_hwpart_str);
  		dup_str[hwpart_str - dev_hwpart_str] = 0;
  		dev_str = dup_str;
  		hwpart_str++;
  	} else {
  		dev_str = dev_hwpart_str;
ecdd57e27   Stephen Warren   disk: default to ...
399
  		hwpart = 0;
336b6f904   Stephen Warren   disk: support dev...
400
  	}
2023e6086   Stephen Warren   disk: introduce g...
401
402
403
404
405
406
  
  	dev = simple_strtoul(dev_str, &ep, 16);
  	if (*ep) {
  		printf("** Bad device specification %s %s **
  ",
  		       ifname, dev_str);
1598dfcb1   Simon Glass   dm: blk: Use the ...
407
  		dev = -EINVAL;
336b6f904   Stephen Warren   disk: support dev...
408
409
410
411
412
413
414
415
416
  		goto cleanup;
  	}
  
  	if (hwpart_str) {
  		hwpart = simple_strtoul(hwpart_str, &ep, 16);
  		if (*ep) {
  			printf("** Bad HW partition specification %s %s **
  ",
  			    ifname, hwpart_str);
1598dfcb1   Simon Glass   dm: blk: Use the ...
417
  			dev = -EINVAL;
336b6f904   Stephen Warren   disk: support dev...
418
419
  			goto cleanup;
  		}
2023e6086   Stephen Warren   disk: introduce g...
420
  	}
336b6f904   Stephen Warren   disk: support dev...
421
  	*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
2023e6086   Stephen Warren   disk: introduce g...
422
  	if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
8f690848b   Sam Protsenko   disk: part: Don't...
423
424
  		debug("** Bad device %s %s **
  ", ifname, dev_hwpart_str);
1598dfcb1   Simon Glass   dm: blk: Use the ...
425
  		dev = -ENOENT;
336b6f904   Stephen Warren   disk: support dev...
426
  		goto cleanup;
2023e6086   Stephen Warren   disk: introduce g...
427
  	}
1811a928c   Adam Ford   Move most CONFIG_...
428
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
99e7fc8a2   Erik Tideman   mmc: emmc and hw ...
429
430
  	/*
  	 * Updates the partition table for the specified hw partition.
4edfabd9e   Robert Hancock   disk: part: Don't...
431
432
  	 * Always should be done, otherwise hw partition 0 will return stale
  	 * data after displaying a non-zero hw partition.
99e7fc8a2   Erik Tideman   mmc: emmc and hw ...
433
  	 */
4edfabd9e   Robert Hancock   disk: part: Don't...
434
  	part_init(*dev_desc);
99e7fc8a2   Erik Tideman   mmc: emmc and hw ...
435
  #endif
336b6f904   Stephen Warren   disk: support dev...
436
437
  cleanup:
  	free(dup_str);
2023e6086   Stephen Warren   disk: introduce g...
438
439
  	return dev;
  }
10a37fd7a   Stephen Warren   disk: get_device_...
440
441
  #define PART_UNSPECIFIED -2
  #define PART_AUTO -1
e35929e4a   Simon Glass   dm: blk: Rename g...
442
  int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
4101f6879   Simon Glass   dm: Drop the bloc...
443
  			     struct blk_desc **dev_desc,
10a37fd7a   Stephen Warren   disk: get_device_...
444
  			     disk_partition_t *info, int allow_whole_dev)
99d2c205d   Rob Herring   disk/part: introd...
445
  {
10a37fd7a   Stephen Warren   disk: get_device_...
446
447
448
449
  	int ret = -1;
  	const char *part_str;
  	char *dup_str = NULL;
  	const char *dev_str;
99d2c205d   Rob Herring   disk/part: introd...
450
  	int dev;
10a37fd7a   Stephen Warren   disk: get_device_...
451
452
453
454
  	char *ep;
  	int p;
  	int part;
  	disk_partition_t tmpinfo;
afc1744ec   Hans de Goede   disk/part: Only b...
455
  #ifdef CONFIG_SANDBOX
4d907025d   Stephen Warren   sandbox: restore ...
456
  	/*
3f9eb6e10   Pavel Machek   whitespace cleanups
457
  	 * Special-case a pseudo block device "hostfs", to allow access to the
4d907025d   Stephen Warren   sandbox: restore ...
458
459
460
461
462
463
464
465
466
467
  	 * host's own filesystem.
  	 */
  	if (0 == strcmp(ifname, "hostfs")) {
  		*dev_desc = NULL;
  		info->start = 0;
  		info->size = 0;
  		info->blksz = 0;
  		info->bootable = 0;
  		strcpy((char *)info->type, BOOT_PART_TYPE);
  		strcpy((char *)info->name, "Sandbox host");
b331cd620   Patrick Delaunay   cmd, disk: conver...
468
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
4d907025d   Stephen Warren   sandbox: restore ...
469
470
  		info->uuid[0] = 0;
  #endif
7561b258a   Patrick Delaunay   gpt: add optional...
471
472
473
  #ifdef CONFIG_PARTITION_TYPE_GUID
  		info->type_guid[0] = 0;
  #endif
4d907025d   Stephen Warren   sandbox: restore ...
474
475
476
  
  		return 0;
  	}
afc1744ec   Hans de Goede   disk/part: Only b...
477
  #endif
4d907025d   Stephen Warren   sandbox: restore ...
478

251cee0db   Hans de Goede   ubifs: Add generi...
479
480
  #ifdef CONFIG_CMD_UBIFS
  	/*
3174cafd9   Heinrich Schuchardt   disk: part: fix typo
481
  	 * Special-case ubi, ubi goes through a mtd, rather than through
251cee0db   Hans de Goede   ubifs: Add generi...
482
483
484
485
486
487
488
489
490
491
492
493
494
  	 * a regular block device.
  	 */
  	if (0 == strcmp(ifname, "ubi")) {
  		if (!ubifs_is_mounted()) {
  			printf("UBIFS not mounted, use ubifsmount to mount volume first!
  ");
  			return -1;
  		}
  
  		*dev_desc = NULL;
  		memset(info, 0, sizeof(*info));
  		strcpy((char *)info->type, BOOT_PART_TYPE);
  		strcpy((char *)info->name, "UBI");
b331cd620   Patrick Delaunay   cmd, disk: conver...
495
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
251cee0db   Hans de Goede   ubifs: Add generi...
496
497
498
499
500
  		info->uuid[0] = 0;
  #endif
  		return 0;
  	}
  #endif
10a37fd7a   Stephen Warren   disk: get_device_...
501
  	/* If no dev_part_str, use bootdevice environment variable */
a10973e7f   Stephen Warren   disk: allow - or ...
502
503
  	if (!dev_part_str || !strlen(dev_part_str) ||
  	    !strcmp(dev_part_str, "-"))
00caae6d4   Simon Glass   env: Rename geten...
504
  		dev_part_str = env_get("bootdevice");
10a37fd7a   Stephen Warren   disk: get_device_...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
  
  	/* If still no dev_part_str, it's an error */
  	if (!dev_part_str) {
  		printf("** No device specified **
  ");
  		goto cleanup;
  	}
  
  	/* Separate device and partition ID specification */
  	part_str = strchr(dev_part_str, ':');
  	if (part_str) {
  		dup_str = strdup(dev_part_str);
  		dup_str[part_str - dev_part_str] = 0;
  		dev_str = dup_str;
  		part_str++;
  	} else {
  		dev_str = dev_part_str;
99d2c205d   Rob Herring   disk/part: introd...
522
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
523
  	/* Look up the device */
ebac37cfb   Simon Glass   dm: blk: Rename g...
524
  	dev = blk_get_device_by_str(ifname, dev_str, dev_desc);
10a37fd7a   Stephen Warren   disk: get_device_...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  	if (dev < 0)
  		goto cleanup;
  
  	/* Convert partition ID string to number */
  	if (!part_str || !*part_str) {
  		part = PART_UNSPECIFIED;
  	} else if (!strcmp(part_str, "auto")) {
  		part = PART_AUTO;
  	} else {
  		/* Something specified -> use exactly that */
  		part = (int)simple_strtoul(part_str, &ep, 16);
  		/*
  		 * Less than whole string converted,
  		 * or request for whole device, but caller requires partition.
  		 */
  		if (*ep || (part == 0 && !allow_whole_dev)) {
  			printf("** Bad partition specification %s %s **
  ",
  			    ifname, dev_part_str);
  			goto cleanup;
  		}
  	}
  
  	/*
  	 * No partition table on device,
  	 * or user requested partition 0 (entire device).
  	 */
  	if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
  	    (part == 0)) {
  		if (!(*dev_desc)->lba) {
  			printf("** Bad device size - %s %s **
  ", ifname,
  			       dev_str);
  			goto cleanup;
  		}
99d2c205d   Rob Herring   disk/part: introd...
560

10a37fd7a   Stephen Warren   disk: get_device_...
561
562
563
564
565
566
567
568
569
570
  		/*
  		 * If user specified a partition ID other than 0,
  		 * or the calling command only accepts partitions,
  		 * it's an error.
  		 */
  		if ((part > 0) || (!allow_whole_dev)) {
  			printf("** No partition table - %s %s **
  ", ifname,
  			       dev_str);
  			goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
571
  		}
10a37fd7a   Stephen Warren   disk: get_device_...
572

50ffc3b64   Lan Yixun (dlan)   fs/ext4: fix log2...
573
  		(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
4bbcc965f   Rob Clark   fs: add fs_readdir()
574
  		part_get_info_whole_disk(*dev_desc, info);
99d2c205d   Rob Herring   disk/part: introd...
575

10a37fd7a   Stephen Warren   disk: get_device_...
576
577
  		ret = 0;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
578
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
579
580
581
582
583
584
585
586
587
588
589
590
  	/*
  	 * Now there's known to be a partition table,
  	 * not specifying a partition means to pick partition 1.
  	 */
  	if (part == PART_UNSPECIFIED)
  		part = 1;
  
  	/*
  	 * If user didn't specify a partition number, or did specify something
  	 * other than "auto", use that partition number directly.
  	 */
  	if (part != PART_AUTO) {
3e8bd4695   Simon Glass   dm: part: Rename ...
591
  		ret = part_get_info(*dev_desc, part, info);
10a37fd7a   Stephen Warren   disk: get_device_...
592
593
594
595
596
597
598
599
600
601
602
603
  		if (ret) {
  			printf("** Invalid partition %d **
  ", part);
  			goto cleanup;
  		}
  	} else {
  		/*
  		 * Find the first bootable partition.
  		 * If none are bootable, fall back to the first valid partition.
  		 */
  		part = 0;
  		for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
3e8bd4695   Simon Glass   dm: part: Rename ...
604
  			ret = part_get_info(*dev_desc, p, info);
10a37fd7a   Stephen Warren   disk: get_device_...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  			if (ret)
  				continue;
  
  			/*
  			 * First valid partition, or new better partition?
  			 * If so, save partition ID.
  			 */
  			if (!part || info->bootable)
  				part = p;
  
  			/* Best possible partition? Stop searching. */
  			if (info->bootable)
  				break;
  
  			/*
  			 * We now need to search further for best possible.
  			 * If we what we just queried was the best so far,
  			 * save the info since we over-write it next loop.
  			 */
  			if (part == p)
  				tmpinfo = *info;
  		}
  		/* If we found any acceptable partition */
  		if (part) {
  			/*
  			 * If we searched all possible partition IDs,
  			 * return the first valid partition we found.
  			 */
  			if (p == MAX_SEARCH_PARTITIONS + 1)
  				*info = tmpinfo;
10a37fd7a   Stephen Warren   disk: get_device_...
635
636
637
  		} else {
  			printf("** No valid partitions found **
  ");
71bba424a   Stephen Warren   disk: get_device_...
638
  			ret = -1;
10a37fd7a   Stephen Warren   disk: get_device_...
639
640
  			goto cleanup;
  		}
99d2c205d   Rob Herring   disk/part: introd...
641
642
643
644
645
646
  	}
  	if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
  		printf("** Invalid partition type \"%.32s\""
  			" (expect \"" BOOT_PART_TYPE "\")
  ",
  			info->type);
10a37fd7a   Stephen Warren   disk: get_device_...
647
648
  		ret  = -1;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
649
  	}
50ffc3b64   Lan Yixun (dlan)   fs/ext4: fix log2...
650
  	(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
10a37fd7a   Stephen Warren   disk: get_device_...
651
652
  	ret = part;
  	goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
653

10a37fd7a   Stephen Warren   disk: get_device_...
654
655
656
  cleanup:
  	free(dup_str);
  	return ret;
99d2c205d   Rob Herring   disk/part: introd...
657
  }
87b8530fe   Petr Kulhavy   disk: part: imple...
658

307890955   Sam Protsenko   disk: Provide API...
659
660
  int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
  			       disk_partition_t *info, int part_type)
87b8530fe   Petr Kulhavy   disk: part: imple...
661
  {
87b8530fe   Petr Kulhavy   disk: part: imple...
662
  	struct part_driver *part_drv;
56670d6fb   Kever Yang   disk: part: use c...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  	int ret;
  	int i;
  
  	part_drv = part_driver_lookup_type(dev_desc);
  	if (!part_drv)
  		return -1;
  	for (i = 1; i < part_drv->max_entries; i++) {
  		ret = part_drv->get_info(dev_desc, i, info);
  		if (ret != 0) {
  			/* no more entries in table */
  			break;
  		}
  		if (strcmp(name, (const char *)info->name) == 0) {
  			/* matched */
  			return i;
87b8530fe   Petr Kulhavy   disk: part: imple...
678
679
  		}
  	}
56670d6fb   Kever Yang   disk: part: use c...
680

87b8530fe   Petr Kulhavy   disk: part: imple...
681
682
  	return -1;
  }
da2ee24d9   Petr Kulhavy   disk: part: refac...
683

307890955   Sam Protsenko   disk: Provide API...
684
685
686
687
688
  int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
  			  disk_partition_t *info)
  {
  	return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
  }
6eccd1f74   Ruslan Trofymenko   disk: part: Exten...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
  /**
   * Get partition info from device number and partition name.
   *
   * Parse a device number and partition name string in the form of
   * "device_num#partition_name", for example "0#misc". If the partition
   * is found, sets dev_desc and part_info accordingly with the information
   * of the partition with the given partition_name.
   *
   * @param[in] dev_iface Device interface
   * @param[in] dev_part_str Input string argument, like "0#misc"
   * @param[out] dev_desc Place to store the device description pointer
   * @param[out] part_info Place to store the partition information
   * @return 0 on success, or a negative on error
   */
  static int part_get_info_by_dev_and_name(const char *dev_iface,
  					 const char *dev_part_str,
  					 struct blk_desc **dev_desc,
  					 disk_partition_t *part_info)
  {
  	char *ep;
  	const char *part_str;
  	int dev_num;
  
  	part_str = strchr(dev_part_str, '#');
  	if (!part_str || part_str == dev_part_str)
  		return -EINVAL;
  
  	dev_num = simple_strtoul(dev_part_str, &ep, 16);
  	if (ep != part_str) {
  		/* Not all the first part before the # was parsed. */
  		return -EINVAL;
  	}
  	part_str++;
  
  	*dev_desc = blk_get_dev(dev_iface, dev_num);
  	if (!*dev_desc) {
  		printf("Could not find %s %d
  ", dev_iface, dev_num);
  		return -EINVAL;
  	}
  	if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
  		printf("Could not find \"%s\" partition
  ", part_str);
  		return -EINVAL;
  	}
  	return 0;
  }
  
  int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
  					 const char *dev_part_str,
  					 struct blk_desc **dev_desc,
  					 disk_partition_t *part_info)
  {
  	/* Split the part_name if passed as "$dev_num#part_name". */
  	if (!part_get_info_by_dev_and_name(dev_iface, dev_part_str,
  					   dev_desc, part_info))
  		return 0;
  	/*
  	 * Couldn't lookup by name, try looking up the partition description
  	 * directly.
  	 */
  	if (blk_get_device_part_str(dev_iface, dev_part_str,
  				    dev_desc, part_info, 1) < 0) {
  		printf("Couldn't find partition %s %s
  ",
  		       dev_iface, dev_part_str);
  		return -EINVAL;
  	}
  	return 0;
  }
da2ee24d9   Petr Kulhavy   disk: part: refac...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
  void part_set_generic_name(const struct blk_desc *dev_desc,
  	int part_num, char *name)
  {
  	char *devtype;
  
  	switch (dev_desc->if_type) {
  	case IF_TYPE_IDE:
  	case IF_TYPE_SATA:
  	case IF_TYPE_ATAPI:
  		devtype = "hd";
  		break;
  	case IF_TYPE_SCSI:
  		devtype = "sd";
  		break;
  	case IF_TYPE_USB:
  		devtype = "usbd";
  		break;
  	case IF_TYPE_DOC:
  		devtype = "docd";
  		break;
  	case IF_TYPE_MMC:
  	case IF_TYPE_SD:
  		devtype = "mmcsd";
  		break;
  	default:
  		devtype = "xx";
  		break;
  	}
  
  	sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num);
  }