Blame view

disk/part.c 15.3 KB
affae2bff   wdenk   Initial revision
1
2
3
4
  /*
   * (C) Copyright 2001
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
5
   * SPDX-License-Identifier:	GPL-2.0+
affae2bff   wdenk   Initial revision
6
7
8
9
   */
  
  #include <common.h>
  #include <command.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
751bb5710   Stefan Roese   [PATCH] Fix reloc...
25
  DECLARE_GLOBAL_DATA_PTR;
751bb5710   Stefan Roese   [PATCH] Fix reloc...
26

1811a928c   Adam Ford   Move most CONFIG_...
27
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
96e5b03c8   Simon Glass   dm: part: Convert...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  static struct part_driver *part_driver_lookup_type(int part_type)
  {
  	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;
  
  	for (entry = drv; entry != drv + n_ents; entry++) {
  		if (part_type == entry->part_type)
  			return entry;
  	}
  
  	/* Not found */
  	return NULL;
  }
4101f6879   Simon Glass   dm: Drop the bloc...
43
  static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
44
  {
6dd9faf8f   Simon Glass   dm: part: Drop th...
45
46
  	struct blk_desc *dev_desc;
  	int ret;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
47

6dd9faf8f   Simon Glass   dm: part: Drop th...
48
49
50
51
52
  	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 ...
53
  		return NULL;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
54
  	}
6dd9faf8f   Simon Glass   dm: part: Drop th...
55
56
57
58
59
60
61
62
63
  	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...
64
  }
336b6f904   Stephen Warren   disk: support dev...
65

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

affae2bff   wdenk   Initial revision
82
83
84
85
  /* ------------------------------------------------------------------------- */
  /*
   * reports device info to the user
   */
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
86

42dfe7a18   wdenk   Code cleanup; mak...
87
  #ifdef CONFIG_LBA48
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
88
  typedef uint64_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
89
  #else
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
90
  typedef lbaint_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
91
  #endif
affae2bff   wdenk   Initial revision
92

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

c40b29568   wdenk   * Patch by Rune T...
183
  		lba512 = (lba * (dev_desc->blksz/512));
affae2bff   wdenk   Initial revision
184
  		/* round to 1 digit */
214b3f311   Pavel Machek   cleanup disk/part...
185
186
  		/* 2048 = (1024 * 1024) / 512 MB */
  		mb = lba512_muldiv(lba512, 10, 2048);
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
187

affae2bff   wdenk   Initial revision
188
189
190
191
192
193
  		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...
194
  #ifdef CONFIG_LBA48
6e5923851   wdenk   * Cleanup, minor ...
195
  		if (dev_desc->lba48)
c40b29568   wdenk   * Patch by Rune T...
196
197
198
  			printf ("            Supports 48-bit addressing
  ");
  #endif
4b142febf   Heiko Schocher   common: delete CO...
199
  #if defined(CONFIG_SYS_64BIT_LBA)
139f7b1de   Jean-Jacques Hiblot   disk: Fixed capac...
200
201
  		printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)
  ",
c40b29568   wdenk   * Patch by Rune T...
202
203
204
205
206
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
  			lba,
  			dev_desc->blksz);
  #else
139f7b1de   Jean-Jacques Hiblot   disk: Fixed capac...
207
208
  		printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)
  ",
affae2bff   wdenk   Initial revision
209
210
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
c40b29568   wdenk   * Patch by Rune T...
211
  			(ulong)lba,
affae2bff   wdenk   Initial revision
212
  			dev_desc->blksz);
c40b29568   wdenk   * Patch by Rune T...
213
  #endif
affae2bff   wdenk   Initial revision
214
215
216
217
218
  	} else {
  		puts ("            Capacity: not available
  ");
  	}
  }
b3aff0cb9   Jon Loeliger   disk/ doc/ lib_*/...
219
  #endif
affae2bff   wdenk   Initial revision
220

1811a928c   Adam Ford   Move most CONFIG_...
221
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
affae2bff   wdenk   Initial revision
222

3e8bd4695   Simon Glass   dm: part: Rename ...
223
  void part_init(struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
224
  {
96e5b03c8   Simon Glass   dm: part: Convert...
225
226
227
228
  	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
229

e40cf34a2   Eric Nelson   drivers: block: a...
230
  	blkcache_invalidate(dev_desc->if_type, dev_desc->devnum);
99d2c205d   Rob Herring   disk/part: introd...
231
  	dev_desc->part_type = PART_TYPE_UNKNOWN;
96e5b03c8   Simon Glass   dm: part: Convert...
232
233
234
235
236
237
238
239
240
241
242
  	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
243
  }
96e5b03c8   Simon Glass   dm: part: Convert...
244
245
  static void print_part_header(const char *type, struct blk_desc *dev_desc)
  {
f18fa31cd   Patrick Delaunay   disk: convert CON...
246
  #if CONFIG_IS_ENABLED(MAC_PARTITION) || \
b0cf73393   Patrick Delaunay   disk: convert CON...
247
  	CONFIG_IS_ENABLED(DOS_PARTITION) || \
1acc00878   Patrick Delaunay   disk: convert CON...
248
  	CONFIG_IS_ENABLED(ISO_PARTITION) || \
863c5b6cd   Patrick Delaunay   disk: convert CON...
249
  	CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
bd42a9426   Patrick Delaunay   disk: convert CON...
250
  	CONFIG_IS_ENABLED(EFI_PARTITION)
affae2bff   wdenk   Initial revision
251
252
253
  	puts ("
  Partition Map for ");
  	switch (dev_desc->if_type) {
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  	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...
272
273
274
  	case IF_TYPE_MMC:
  		puts ("MMC");
  		break;
f4d8de48f   Henrik Nordström   sandbox: block dr...
275
  	case IF_TYPE_HOST:
ffab6945e   Zhikang Zhang   dm: blk: part: Ad...
276
277
278
279
  		puts ("HOST");
  		break;
  	case IF_TYPE_NVME:
  		puts ("NVMe");
f4d8de48f   Henrik Nordström   sandbox: block dr...
280
  		break;
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
281
282
283
  	default:
  		puts ("UNKNOWN");
  		break;
affae2bff   wdenk   Initial revision
284
285
286
287
  	}
  	printf (" device %d  --   Partition Type: %s
  
  ",
bcce53d04   Simon Glass   dm: block: Rename...
288
  			dev_desc->devnum, type);
0c9c8fb5e   Gabe Black   disk: Make the di...
289
  #endif /* any CONFIG_..._PARTITION */
96e5b03c8   Simon Glass   dm: part: Convert...
290
  }
0c9c8fb5e   Gabe Black   disk: Make the di...
291

3e8bd4695   Simon Glass   dm: part: Rename ...
292
  void part_print(struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
293
  {
96e5b03c8   Simon Glass   dm: part: Convert...
294
  	struct part_driver *drv;
affae2bff   wdenk   Initial revision
295

96e5b03c8   Simon Glass   dm: part: Convert...
296
297
298
299
300
  	drv = part_driver_lookup_type(dev_desc->part_type);
  	if (!drv) {
  		printf("## Unknown partition table type %x
  ",
  		       dev_desc->part_type);
affae2bff   wdenk   Initial revision
301
  		return;
affae2bff   wdenk   Initial revision
302
  	}
96e5b03c8   Simon Glass   dm: part: Convert...
303
304
305
306
307
308
  
  	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
309
  }
1811a928c   Adam Ford   Move most CONFIG_...
310
  #endif /* CONFIG_HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
311

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

b331cd620   Patrick Delaunay   cmd, disk: conver...
318
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
894bfbbfb   Stephen Warren   disk: part_efi: p...
319
320
321
  	/* The common case is no UUID support */
  	info->uuid[0] = 0;
  #endif
7561b258a   Patrick Delaunay   gpt: add optional...
322
323
324
  #ifdef CONFIG_PARTITION_TYPE_GUID
  	info->type_guid[0] = 0;
  #endif
894bfbbfb   Stephen Warren   disk: part_efi: p...
325

96e5b03c8   Simon Glass   dm: part: Convert...
326
327
328
329
330
331
332
333
  	drv = part_driver_lookup_type(dev_desc->part_type);
  	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...
334
335
336
  		PRINTF("## Driver %s does not have the get_info() method
  ",
  		       drv->name);
96e5b03c8   Simon Glass   dm: part: Convert...
337
338
339
340
341
342
  		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...
343
  	}
1811a928c   Adam Ford   Move most CONFIG_...
344
  #endif /* CONFIG_HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
345
346
347
  
  	return -1;
  }
99d2c205d   Rob Herring   disk/part: introd...
348

4bbcc965f   Rob Clark   fs: add fs_readdir()
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  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...
366
367
  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...
368
369
  {
  	char *ep;
336b6f904   Stephen Warren   disk: support dev...
370
371
372
373
374
375
376
377
378
379
380
381
  	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 ...
382
  		hwpart = 0;
336b6f904   Stephen Warren   disk: support dev...
383
  	}
2023e6086   Stephen Warren   disk: introduce g...
384
385
386
387
388
389
  
  	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 ...
390
  		dev = -EINVAL;
336b6f904   Stephen Warren   disk: support dev...
391
392
393
394
395
396
397
398
399
  		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 ...
400
  			dev = -EINVAL;
336b6f904   Stephen Warren   disk: support dev...
401
402
  			goto cleanup;
  		}
2023e6086   Stephen Warren   disk: introduce g...
403
  	}
336b6f904   Stephen Warren   disk: support dev...
404
  	*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
2023e6086   Stephen Warren   disk: introduce g...
405
  	if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
336b6f904   Stephen Warren   disk: support dev...
406
407
  		printf("** Bad device %s %s **
  ", ifname, dev_hwpart_str);
1598dfcb1   Simon Glass   dm: blk: Use the ...
408
  		dev = -ENOENT;
336b6f904   Stephen Warren   disk: support dev...
409
  		goto cleanup;
2023e6086   Stephen Warren   disk: introduce g...
410
  	}
1811a928c   Adam Ford   Move most CONFIG_...
411
  #ifdef CONFIG_HAVE_BLOCK_DEVICE
99e7fc8a2   Erik Tideman   mmc: emmc and hw ...
412
413
414
415
416
417
  	/*
  	 * Updates the partition table for the specified hw partition.
  	 * Does not need to be done for hwpart 0 since it is default and
  	 * already loaded.
  	 */
  	if(hwpart != 0)
3e8bd4695   Simon Glass   dm: part: Rename ...
418
  		part_init(*dev_desc);
99e7fc8a2   Erik Tideman   mmc: emmc and hw ...
419
  #endif
336b6f904   Stephen Warren   disk: support dev...
420
421
  cleanup:
  	free(dup_str);
2023e6086   Stephen Warren   disk: introduce g...
422
423
  	return dev;
  }
10a37fd7a   Stephen Warren   disk: get_device_...
424
425
  #define PART_UNSPECIFIED -2
  #define PART_AUTO -1
e35929e4a   Simon Glass   dm: blk: Rename g...
426
  int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
4101f6879   Simon Glass   dm: Drop the bloc...
427
  			     struct blk_desc **dev_desc,
10a37fd7a   Stephen Warren   disk: get_device_...
428
  			     disk_partition_t *info, int allow_whole_dev)
99d2c205d   Rob Herring   disk/part: introd...
429
  {
10a37fd7a   Stephen Warren   disk: get_device_...
430
431
432
433
  	int ret = -1;
  	const char *part_str;
  	char *dup_str = NULL;
  	const char *dev_str;
99d2c205d   Rob Herring   disk/part: introd...
434
  	int dev;
10a37fd7a   Stephen Warren   disk: get_device_...
435
436
437
438
  	char *ep;
  	int p;
  	int part;
  	disk_partition_t tmpinfo;
afc1744ec   Hans de Goede   disk/part: Only b...
439
  #ifdef CONFIG_SANDBOX
4d907025d   Stephen Warren   sandbox: restore ...
440
  	/*
3f9eb6e10   Pavel Machek   whitespace cleanups
441
  	 * Special-case a pseudo block device "hostfs", to allow access to the
4d907025d   Stephen Warren   sandbox: restore ...
442
443
444
445
446
447
448
449
450
451
  	 * 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...
452
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
4d907025d   Stephen Warren   sandbox: restore ...
453
454
  		info->uuid[0] = 0;
  #endif
7561b258a   Patrick Delaunay   gpt: add optional...
455
456
457
  #ifdef CONFIG_PARTITION_TYPE_GUID
  		info->type_guid[0] = 0;
  #endif
4d907025d   Stephen Warren   sandbox: restore ...
458
459
460
  
  		return 0;
  	}
afc1744ec   Hans de Goede   disk/part: Only b...
461
  #endif
4d907025d   Stephen Warren   sandbox: restore ...
462

251cee0db   Hans de Goede   ubifs: Add generi...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  #ifdef CONFIG_CMD_UBIFS
  	/*
  	 * Special-case ubi, ubi goes through a mtd, rathen then through
  	 * 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...
479
  #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
251cee0db   Hans de Goede   ubifs: Add generi...
480
481
482
483
484
  		info->uuid[0] = 0;
  #endif
  		return 0;
  	}
  #endif
10a37fd7a   Stephen Warren   disk: get_device_...
485
  	/* If no dev_part_str, use bootdevice environment variable */
a10973e7f   Stephen Warren   disk: allow - or ...
486
487
  	if (!dev_part_str || !strlen(dev_part_str) ||
  	    !strcmp(dev_part_str, "-"))
00caae6d4   Simon Glass   env: Rename geten...
488
  		dev_part_str = env_get("bootdevice");
10a37fd7a   Stephen Warren   disk: get_device_...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  
  	/* 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...
506
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
507
  	/* Look up the device */
ebac37cfb   Simon Glass   dm: blk: Rename g...
508
  	dev = blk_get_device_by_str(ifname, dev_str, dev_desc);
10a37fd7a   Stephen Warren   disk: get_device_...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
  	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...
544

10a37fd7a   Stephen Warren   disk: get_device_...
545
546
547
548
549
550
551
552
553
554
  		/*
  		 * 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...
555
  		}
10a37fd7a   Stephen Warren   disk: get_device_...
556

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

10a37fd7a   Stephen Warren   disk: get_device_...
560
561
  		ret = 0;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
562
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
563
564
565
566
567
568
569
570
571
572
573
574
  	/*
  	 * 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 ...
575
  		ret = part_get_info(*dev_desc, part, info);
10a37fd7a   Stephen Warren   disk: get_device_...
576
577
578
579
580
581
582
583
584
585
586
587
  		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 ...
588
  			ret = part_get_info(*dev_desc, p, info);
10a37fd7a   Stephen Warren   disk: get_device_...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
  			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_...
619
620
621
  		} else {
  			printf("** No valid partitions found **
  ");
71bba424a   Stephen Warren   disk: get_device_...
622
  			ret = -1;
10a37fd7a   Stephen Warren   disk: get_device_...
623
624
  			goto cleanup;
  		}
99d2c205d   Rob Herring   disk/part: introd...
625
626
627
628
629
630
  	}
  	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_...
631
632
  		ret  = -1;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
633
  	}
50ffc3b64   Lan Yixun (dlan)   fs/ext4: fix log2...
634
  	(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
10a37fd7a   Stephen Warren   disk: get_device_...
635
636
  	ret = part;
  	goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
637

10a37fd7a   Stephen Warren   disk: get_device_...
638
639
640
  cleanup:
  	free(dup_str);
  	return ret;
99d2c205d   Rob Herring   disk/part: introd...
641
  }
87b8530fe   Petr Kulhavy   disk: part: imple...
642

307890955   Sam Protsenko   disk: Provide API...
643
644
  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...
645
646
647
648
649
650
651
652
653
654
  {
  	struct part_driver *first_drv =
  		ll_entry_start(struct part_driver, part_driver);
  	const int n_drvs = ll_entry_count(struct part_driver, part_driver);
  	struct part_driver *part_drv;
  
  	for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) {
  		int ret;
  		int i;
  		for (i = 1; i < part_drv->max_entries; i++) {
307890955   Sam Protsenko   disk: Provide API...
655
656
  			if (part_type >= 0 && part_type != part_drv->part_type)
  				break;
87b8530fe   Petr Kulhavy   disk: part: imple...
657
658
659
660
661
662
663
  			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 */
88b6329cc   Alex Deymo   disk: Return the ...
664
  				return i;
87b8530fe   Petr Kulhavy   disk: part: imple...
665
666
667
668
669
  			}
  		}
  	}
  	return -1;
  }
da2ee24d9   Petr Kulhavy   disk: part: refac...
670

307890955   Sam Protsenko   disk: Provide API...
671
672
673
674
675
  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);
  }
da2ee24d9   Petr Kulhavy   disk: part: refac...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
  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);
  }