Blame view

disk/part.c 15 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
10
   */
  
  #include <common.h>
  #include <command.h>
  #include <ide.h>
10a37fd7a   Stephen Warren   disk: get_device_...
11
  #include <malloc.h>
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
12
  #include <part.h>
affae2bff   wdenk   Initial revision
13
14
15
16
17
18
19
20
  
  #undef	PART_DEBUG
  
  #ifdef	PART_DEBUG
  #define	PRINTF(fmt,args...)	printf (fmt ,##args)
  #else
  #define PRINTF(fmt,args...)
  #endif
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
21
22
23
  struct block_drvr {
  	char *name;
  	block_dev_desc_t* (*get_dev)(int dev);
336b6f904   Stephen Warren   disk: support dev...
24
  	int (*select_hwpart)(int dev_num, int hwpart);
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
25
26
27
  };
  
  static const struct block_drvr block_drvr[] = {
cde5c64d1   Jon Loeliger   disk/: Remove obs...
28
  #if defined(CONFIG_CMD_IDE)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
29
30
  	{ .name = "ide", .get_dev = ide_get_dev, },
  #endif
c7057b529   Dave Liu   ata: add the supp...
31
32
33
  #if defined(CONFIG_CMD_SATA)
  	{.name = "sata", .get_dev = sata_get_dev, },
  #endif
cde5c64d1   Jon Loeliger   disk/: Remove obs...
34
  #if defined(CONFIG_CMD_SCSI)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
35
36
  	{ .name = "scsi", .get_dev = scsi_get_dev, },
  #endif
cde5c64d1   Jon Loeliger   disk/: Remove obs...
37
  #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
38
39
40
  	{ .name = "usb", .get_dev = usb_stor_get_dev, },
  #endif
  #if defined(CONFIG_MMC)
d23562843   Stephen Warren   mmc: provide a se...
41
42
43
44
45
  	{
  		.name = "mmc",
  		.get_dev = mmc_get_dev,
  		.select_hwpart = mmc_select_hwpart,
  	},
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
46
47
48
49
  #endif
  #if defined(CONFIG_SYSTEMACE)
  	{ .name = "ace", .get_dev = systemace_get_dev, },
  #endif
f4d8de48f   Henrik Nordström   sandbox: block dr...
50
51
52
  #if defined(CONFIG_SANDBOX)
  	{ .name = "host", .get_dev = host_get_dev, },
  #endif
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
53
54
  	{ },
  };
751bb5710   Stefan Roese   [PATCH] Fix reloc...
55
  DECLARE_GLOBAL_DATA_PTR;
751bb5710   Stefan Roese   [PATCH] Fix reloc...
56

0c9c8fb5e   Gabe Black   disk: Make the di...
57
  #ifdef HAVE_BLOCK_DEVICE
76ee65bde   Jeroen Hofstee   disk/part.c: make...
58
  static block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
59
60
  {
  	const struct block_drvr *drvr = block_drvr;
6c7cac8c4   Stefan Roese   [PATCH] get_dev()...
61
  	block_dev_desc_t* (*reloc_get_dev)(int dev);
336b6f904   Stephen Warren   disk: support dev...
62
  	int (*select_hwpart)(int dev_num, int hwpart);
23090dacd   Heiko Schocher   disk/part.c: fix ...
63
  	char *name;
336b6f904   Stephen Warren   disk: support dev...
64
  	int ret;
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
65

7e71dc688   Tim Kientzle   disk/part.c: Fix ...
66
67
  	if (!ifname)
  		return NULL;
23090dacd   Heiko Schocher   disk/part.c: fix ...
68
  	name = drvr->name;
2e5167cca   Wolfgang Denk   Replace CONFIG_RE...
69
  #ifdef CONFIG_NEEDS_MANUAL_RELOC
23090dacd   Heiko Schocher   disk/part.c: fix ...
70
71
  	name += gd->reloc_off;
  #endif
b16aadf41   Lei Wen   disk/part.c: fix ...
72
  	while (drvr->name) {
23090dacd   Heiko Schocher   disk/part.c: fix ...
73
  		name = drvr->name;
521af04d8   Peter Tyser   Conditionally per...
74
  		reloc_get_dev = drvr->get_dev;
336b6f904   Stephen Warren   disk: support dev...
75
  		select_hwpart = drvr->select_hwpart;
2e5167cca   Wolfgang Denk   Replace CONFIG_RE...
76
  #ifdef CONFIG_NEEDS_MANUAL_RELOC
23090dacd   Heiko Schocher   disk/part.c: fix ...
77
  		name += gd->reloc_off;
521af04d8   Peter Tyser   Conditionally per...
78
  		reloc_get_dev += gd->reloc_off;
336b6f904   Stephen Warren   disk: support dev...
79
80
  		if (select_hwpart)
  			select_hwpart += gd->reloc_off;
521af04d8   Peter Tyser   Conditionally per...
81
  #endif
336b6f904   Stephen Warren   disk: support dev...
82
83
84
85
  		if (strncmp(ifname, name, strlen(name)) == 0) {
  			block_dev_desc_t *dev_desc = reloc_get_dev(dev);
  			if (!dev_desc)
  				return NULL;
ecdd57e27   Stephen Warren   disk: default to ...
86
  			if (hwpart == 0 && !select_hwpart)
336b6f904   Stephen Warren   disk: support dev...
87
88
89
90
91
92
93
94
  				return dev_desc;
  			if (!select_hwpart)
  				return NULL;
  			ret = select_hwpart(dev_desc->dev, hwpart);
  			if (ret < 0)
  				return NULL;
  			return dev_desc;
  		}
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
95
96
97
98
  		drvr++;
  	}
  	return NULL;
  }
336b6f904   Stephen Warren   disk: support dev...
99
100
101
  
  block_dev_desc_t *get_dev(const char *ifname, int dev)
  {
ecdd57e27   Stephen Warren   disk: default to ...
102
  	return get_dev_hwpart(ifname, dev, 0);
336b6f904   Stephen Warren   disk: support dev...
103
  }
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
104
  #else
336b6f904   Stephen Warren   disk: support dev...
105
106
107
108
  block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
  {
  	return NULL;
  }
99d2c205d   Rob Herring   disk/part: introd...
109
  block_dev_desc_t *get_dev(const char *ifname, int dev)
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
110
111
112
113
  {
  	return NULL;
  }
  #endif
0c9c8fb5e   Gabe Black   disk: Make the di...
114
  #ifdef HAVE_BLOCK_DEVICE
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
115

affae2bff   wdenk   Initial revision
116
117
118
119
  /* ------------------------------------------------------------------------- */
  /*
   * reports device info to the user
   */
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
120

42dfe7a18   wdenk   Code cleanup; mak...
121
  #ifdef CONFIG_LBA48
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
122
  typedef uint64_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
123
  #else
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
124
  typedef lbaint_t lba512_t;
c40b29568   wdenk   * Patch by Rune T...
125
  #endif
affae2bff   wdenk   Initial revision
126

69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
127
128
129
130
  /*
   * Overflowless variant of (block_count * mul_by / div_by)
   * when div_by > mul_by
   */
214b3f311   Pavel Machek   cleanup disk/part...
131
  static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by)
69a2a4d9a   Sergei Trofimovich   disk/part.c: 'usb...
132
133
134
135
136
137
138
139
140
141
142
143
  {
  	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;
  }
  
  void dev_print (block_dev_desc_t *dev_desc)
  {
  	lba512_t lba512; /* number of blocks if 512bytes block size */
af75a45d2   Wolfgang Denk   IDE: bail out of ...
144
145
146
147
148
  	if (dev_desc->type == DEV_TYPE_UNKNOWN) {
  		puts ("not available
  ");
  		return;
  	}
8ec6e332e   Tor Krill   Fix incorrect swi...
149
  	switch (dev_desc->if_type) {
574b31951   Detlev Zundel   Fix disk type out...
150
151
152
153
  	case IF_TYPE_SCSI:
  		printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s
  ",
  			dev_desc->target,dev_desc->lun,
affae2bff   wdenk   Initial revision
154
  			dev_desc->vendor,
574b31951   Detlev Zundel   Fix disk type out...
155
156
157
  			dev_desc->product,
  			dev_desc->revision);
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
158
  	case IF_TYPE_ATAPI:
574b31951   Detlev Zundel   Fix disk type out...
159
160
  	case IF_TYPE_IDE:
  	case IF_TYPE_SATA:
c7057b529   Dave Liu   ata: add the supp...
161
162
163
164
165
  		printf ("Model: %s Firm: %s Ser#: %s
  ",
  			dev_desc->vendor,
  			dev_desc->revision,
  			dev_desc->product);
574b31951   Detlev Zundel   Fix disk type out...
166
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
167
168
  	case IF_TYPE_SD:
  	case IF_TYPE_MMC:
47bebe34c   Nícolas Carneiro Lebedenco   Fix dev_print whe...
169
170
171
172
173
174
175
  	case IF_TYPE_USB:
  		printf ("Vendor: %s Rev: %s Prod: %s
  ",
  			dev_desc->vendor,
  			dev_desc->revision,
  			dev_desc->product);
  		break;
6e24a1eb1   Remy Bohmer   Add missing devic...
176
177
178
179
  	case IF_TYPE_DOC:
  		puts("device type DOC
  ");
  		return;
8ec6e332e   Tor Krill   Fix incorrect swi...
180
  	case IF_TYPE_UNKNOWN:
6e24a1eb1   Remy Bohmer   Add missing devic...
181
182
183
  		puts("device type unknown
  ");
  		return;
574b31951   Detlev Zundel   Fix disk type out...
184
  	default:
6e24a1eb1   Remy Bohmer   Add missing devic...
185
186
  		printf("Unhandled device type: %i
  ", dev_desc->if_type);
574b31951   Detlev Zundel   Fix disk type out...
187
  		return;
affae2bff   wdenk   Initial revision
188
189
190
191
192
  	}
  	puts ("            Type: ");
  	if (dev_desc->removable)
  		puts ("Removable ");
  	switch (dev_desc->type & 0x1F) {
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  	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
208
209
210
  	}
  	puts ("
  ");
33699df12   Jerry Huang   part: check each ...
211
  	if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
affae2bff   wdenk   Initial revision
212
  		ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
c40b29568   wdenk   * Patch by Rune T...
213
  		lbaint_t lba;
6e5923851   wdenk   * Cleanup, minor ...
214
215
  
  		lba = dev_desc->lba;
affae2bff   wdenk   Initial revision
216

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

affae2bff   wdenk   Initial revision
222
223
224
225
226
227
  		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...
228
  #ifdef CONFIG_LBA48
6e5923851   wdenk   * Cleanup, minor ...
229
  		if (dev_desc->lba48)
c40b29568   wdenk   * Patch by Rune T...
230
231
232
  			printf ("            Supports 48-bit addressing
  ");
  #endif
4b142febf   Heiko Schocher   common: delete CO...
233
  #if defined(CONFIG_SYS_64BIT_LBA)
6c6166f52   Mike Frysinger   vsprintf: pull up...
234
235
  		printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%Ld x %ld)
  ",
c40b29568   wdenk   * Patch by Rune T...
236
237
238
239
240
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
  			lba,
  			dev_desc->blksz);
  #else
affae2bff   wdenk   Initial revision
241
242
243
244
  		printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)
  ",
  			mb_quot, mb_rem,
  			gb_quot, gb_rem,
c40b29568   wdenk   * Patch by Rune T...
245
  			(ulong)lba,
affae2bff   wdenk   Initial revision
246
  			dev_desc->blksz);
c40b29568   wdenk   * Patch by Rune T...
247
  #endif
affae2bff   wdenk   Initial revision
248
249
250
251
252
  	} else {
  		puts ("            Capacity: not available
  ");
  	}
  }
b3aff0cb9   Jon Loeliger   disk/ doc/ lib_*/...
253
  #endif
affae2bff   wdenk   Initial revision
254

0c9c8fb5e   Gabe Black   disk: Make the di...
255
  #ifdef HAVE_BLOCK_DEVICE
affae2bff   wdenk   Initial revision
256

214b3f311   Pavel Machek   cleanup disk/part...
257
  void init_part(block_dev_desc_t *dev_desc)
affae2bff   wdenk   Initial revision
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  {
  #ifdef CONFIG_ISO_PARTITION
  	if (test_part_iso(dev_desc) == 0) {
  		dev_desc->part_type = PART_TYPE_ISO;
  		return;
  	}
  #endif
  
  #ifdef CONFIG_MAC_PARTITION
  	if (test_part_mac(dev_desc) == 0) {
  		dev_desc->part_type = PART_TYPE_MAC;
  		return;
  	}
  #endif
07f3d789b   richardretanubun   Add support for C...
272
273
274
275
276
277
278
  /* must be placed before DOS partition detection */
  #ifdef CONFIG_EFI_PARTITION
  	if (test_part_efi(dev_desc) == 0) {
  		dev_desc->part_type = PART_TYPE_EFI;
  		return;
  	}
  #endif
affae2bff   wdenk   Initial revision
279
280
281
282
283
284
  #ifdef CONFIG_DOS_PARTITION
  	if (test_part_dos(dev_desc) == 0) {
  		dev_desc->part_type = PART_TYPE_DOS;
  		return;
  	}
  #endif
c7de829c7   wdenk   * Patch by Thomas...
285
286
287
288
289
290
291
  
  #ifdef CONFIG_AMIGA_PARTITION
  	if (test_part_amiga(dev_desc) == 0) {
  	    dev_desc->part_type = PART_TYPE_AMIGA;
  	    return;
  	}
  #endif
99d2c205d   Rob Herring   disk/part: introd...
292
  	dev_desc->part_type = PART_TYPE_UNKNOWN;
affae2bff   wdenk   Initial revision
293
  }
0c9c8fb5e   Gabe Black   disk: Make the di...
294
295
296
297
298
  #if defined(CONFIG_MAC_PARTITION) || \
  	defined(CONFIG_DOS_PARTITION) || \
  	defined(CONFIG_ISO_PARTITION) || \
  	defined(CONFIG_AMIGA_PARTITION) || \
  	defined(CONFIG_EFI_PARTITION)
214b3f311   Pavel Machek   cleanup disk/part...
299
  static void print_part_header(const char *type, block_dev_desc_t *dev_desc)
affae2bff   wdenk   Initial revision
300
301
302
303
  {
  	puts ("
  Partition Map for ");
  	switch (dev_desc->if_type) {
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  	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...
322
323
324
  	case IF_TYPE_MMC:
  		puts ("MMC");
  		break;
f4d8de48f   Henrik Nordström   sandbox: block dr...
325
326
327
  	case IF_TYPE_HOST:
  		puts("HOST");
  		break;
726c0f1e5   Detlev Zundel   cosmetic: Adjust ...
328
329
330
  	default:
  		puts ("UNKNOWN");
  		break;
affae2bff   wdenk   Initial revision
331
332
333
334
335
336
  	}
  	printf (" device %d  --   Partition Type: %s
  
  ",
  			dev_desc->dev, type);
  }
0c9c8fb5e   Gabe Black   disk: Make the di...
337
  #endif /* any CONFIG_..._PARTITION */
3f9eb6e10   Pavel Machek   whitespace cleanups
338
  void print_part(block_dev_desc_t * dev_desc)
affae2bff   wdenk   Initial revision
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  {
  
  		switch (dev_desc->part_type) {
  #ifdef CONFIG_MAC_PARTITION
  	case PART_TYPE_MAC:
  		PRINTF ("## Testing for valid MAC partition ##
  ");
  		print_part_header ("MAC", dev_desc);
  		print_part_mac (dev_desc);
  		return;
  #endif
  #ifdef CONFIG_DOS_PARTITION
  	case PART_TYPE_DOS:
  		PRINTF ("## Testing for valid DOS partition ##
  ");
  		print_part_header ("DOS", dev_desc);
  		print_part_dos (dev_desc);
  		return;
  #endif
  
  #ifdef CONFIG_ISO_PARTITION
  	case PART_TYPE_ISO:
  		PRINTF ("## Testing for valid ISO Boot partition ##
  ");
  		print_part_header ("ISO", dev_desc);
  		print_part_iso (dev_desc);
  		return;
  #endif
c7de829c7   wdenk   * Patch by Thomas...
367
368
369
370
371
372
373
374
375
  
  #ifdef CONFIG_AMIGA_PARTITION
  	case PART_TYPE_AMIGA:
  	    PRINTF ("## Testing for a valid Amiga partition ##
  ");
  	    print_part_header ("AMIGA", dev_desc);
  	    print_part_amiga (dev_desc);
  	    return;
  #endif
07f3d789b   richardretanubun   Add support for C...
376
377
378
379
380
381
382
383
384
  
  #ifdef CONFIG_EFI_PARTITION
  	case PART_TYPE_EFI:
  		PRINTF ("## Testing for valid EFI partition ##
  ");
  		print_part_header ("EFI", dev_desc);
  		print_part_efi (dev_desc);
  		return;
  #endif
affae2bff   wdenk   Initial revision
385
386
387
388
  	}
  	puts ("## Unknown partition table
  ");
  }
0c9c8fb5e   Gabe Black   disk: Make the di...
389
  #endif /* HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
390

3f9eb6e10   Pavel Machek   whitespace cleanups
391
392
  int get_partition_info(block_dev_desc_t *dev_desc, int part,
  		       disk_partition_t *info)
2f5016462   Stephen Warren   disk: make get_pa...
393
  {
0c9c8fb5e   Gabe Black   disk: Make the di...
394
  #ifdef HAVE_BLOCK_DEVICE
2f5016462   Stephen Warren   disk: make get_pa...
395

894bfbbfb   Stephen Warren   disk: part_efi: p...
396
397
398
399
  #ifdef CONFIG_PARTITION_UUIDS
  	/* The common case is no UUID support */
  	info->uuid[0] = 0;
  #endif
2f5016462   Stephen Warren   disk: make get_pa...
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  	switch (dev_desc->part_type) {
  #ifdef CONFIG_MAC_PARTITION
  	case PART_TYPE_MAC:
  		if (get_partition_info_mac(dev_desc, part, info) == 0) {
  			PRINTF("## Valid MAC partition found ##
  ");
  			return 0;
  		}
  		break;
  #endif
  
  #ifdef CONFIG_DOS_PARTITION
  	case PART_TYPE_DOS:
  		if (get_partition_info_dos(dev_desc, part, info) == 0) {
  			PRINTF("## Valid DOS partition found ##
  ");
  			return 0;
  		}
  		break;
  #endif
  
  #ifdef CONFIG_ISO_PARTITION
  	case PART_TYPE_ISO:
  		if (get_partition_info_iso(dev_desc, part, info) == 0) {
  			PRINTF("## Valid ISO boot partition found ##
  ");
  			return 0;
  		}
  		break;
  #endif
  
  #ifdef CONFIG_AMIGA_PARTITION
  	case PART_TYPE_AMIGA:
  		if (get_partition_info_amiga(dev_desc, part, info) == 0) {
  			PRINTF("## Valid Amiga partition found ##
  ");
  			return 0;
  		}
  		break;
  #endif
  
  #ifdef CONFIG_EFI_PARTITION
  	case PART_TYPE_EFI:
  		if (get_partition_info_efi(dev_desc, part, info) == 0) {
  			PRINTF("## Valid EFI partition found ##
  ");
  			return 0;
  		}
  		break;
  #endif
  	default:
  		break;
  	}
0c9c8fb5e   Gabe Black   disk: Make the di...
453
  #endif /* HAVE_BLOCK_DEVICE */
2f5016462   Stephen Warren   disk: make get_pa...
454
455
456
  
  	return -1;
  }
99d2c205d   Rob Herring   disk/part: introd...
457

336b6f904   Stephen Warren   disk: support dev...
458
  int get_device(const char *ifname, const char *dev_hwpart_str,
2023e6086   Stephen Warren   disk: introduce g...
459
460
461
  	       block_dev_desc_t **dev_desc)
  {
  	char *ep;
336b6f904   Stephen Warren   disk: support dev...
462
463
464
465
466
467
468
469
470
471
472
473
  	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 ...
474
  		hwpart = 0;
336b6f904   Stephen Warren   disk: support dev...
475
  	}
2023e6086   Stephen Warren   disk: introduce g...
476
477
478
479
480
481
  
  	dev = simple_strtoul(dev_str, &ep, 16);
  	if (*ep) {
  		printf("** Bad device specification %s %s **
  ",
  		       ifname, dev_str);
336b6f904   Stephen Warren   disk: support dev...
482
483
484
485
486
487
488
489
490
491
492
493
494
  		dev = -1;
  		goto cleanup;
  	}
  
  	if (hwpart_str) {
  		hwpart = simple_strtoul(hwpart_str, &ep, 16);
  		if (*ep) {
  			printf("** Bad HW partition specification %s %s **
  ",
  			    ifname, hwpart_str);
  			dev = -1;
  			goto cleanup;
  		}
2023e6086   Stephen Warren   disk: introduce g...
495
  	}
336b6f904   Stephen Warren   disk: support dev...
496
  	*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
2023e6086   Stephen Warren   disk: introduce g...
497
  	if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
336b6f904   Stephen Warren   disk: support dev...
498
499
500
501
  		printf("** Bad device %s %s **
  ", ifname, dev_hwpart_str);
  		dev = -1;
  		goto cleanup;
2023e6086   Stephen Warren   disk: introduce g...
502
  	}
336b6f904   Stephen Warren   disk: support dev...
503
504
  cleanup:
  	free(dup_str);
2023e6086   Stephen Warren   disk: introduce g...
505
506
  	return dev;
  }
10a37fd7a   Stephen Warren   disk: get_device_...
507
508
509
510
  #define PART_UNSPECIFIED -2
  #define PART_AUTO -1
  #define MAX_SEARCH_PARTITIONS 16
  int get_device_and_partition(const char *ifname, const char *dev_part_str,
99d2c205d   Rob Herring   disk/part: introd...
511
  			     block_dev_desc_t **dev_desc,
10a37fd7a   Stephen Warren   disk: get_device_...
512
  			     disk_partition_t *info, int allow_whole_dev)
99d2c205d   Rob Herring   disk/part: introd...
513
  {
10a37fd7a   Stephen Warren   disk: get_device_...
514
515
516
517
  	int ret = -1;
  	const char *part_str;
  	char *dup_str = NULL;
  	const char *dev_str;
99d2c205d   Rob Herring   disk/part: introd...
518
  	int dev;
10a37fd7a   Stephen Warren   disk: get_device_...
519
520
521
522
  	char *ep;
  	int p;
  	int part;
  	disk_partition_t tmpinfo;
4d907025d   Stephen Warren   sandbox: restore ...
523
  	/*
3f9eb6e10   Pavel Machek   whitespace cleanups
524
  	 * Special-case a pseudo block device "hostfs", to allow access to the
4d907025d   Stephen Warren   sandbox: restore ...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  	 * 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");
  #ifdef CONFIG_PARTITION_UUIDS
  		info->uuid[0] = 0;
  #endif
  
  		return 0;
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
541
  	/* If no dev_part_str, use bootdevice environment variable */
a10973e7f   Stephen Warren   disk: allow - or ...
542
543
  	if (!dev_part_str || !strlen(dev_part_str) ||
  	    !strcmp(dev_part_str, "-"))
10a37fd7a   Stephen Warren   disk: get_device_...
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
  		dev_part_str = getenv("bootdevice");
  
  	/* 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...
562
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  	/* Look up the device */
  	dev = get_device(ifname, dev_str, dev_desc);
  	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...
600

10a37fd7a   Stephen Warren   disk: get_device_...
601
602
603
604
605
606
607
608
609
610
  		/*
  		 * 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...
611
  		}
10a37fd7a   Stephen Warren   disk: get_device_...
612

50ffc3b64   Lan Yixun (dlan)   fs/ext4: fix log2...
613
  		(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
99d2c205d   Rob Herring   disk/part: introd...
614
  		info->start = 0;
10a37fd7a   Stephen Warren   disk: get_device_...
615
616
617
  		info->size = (*dev_desc)->lba;
  		info->blksz = (*dev_desc)->blksz;
  		info->bootable = 0;
6ab6a650a   Stephen Warren   disk: initialize ...
618
619
  		strcpy((char *)info->type, BOOT_PART_TYPE);
  		strcpy((char *)info->name, "Whole Disk");
10a37fd7a   Stephen Warren   disk: get_device_...
620
621
622
  #ifdef CONFIG_PARTITION_UUIDS
  		info->uuid[0] = 0;
  #endif
99d2c205d   Rob Herring   disk/part: introd...
623

10a37fd7a   Stephen Warren   disk: get_device_...
624
625
  		ret = 0;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
626
  	}
10a37fd7a   Stephen Warren   disk: get_device_...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  	/*
  	 * 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) {
  		ret = get_partition_info(*dev_desc, part, info);
  		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++) {
  			ret = get_partition_info(*dev_desc, p, info);
  			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_...
683
684
685
  		} else {
  			printf("** No valid partitions found **
  ");
71bba424a   Stephen Warren   disk: get_device_...
686
  			ret = -1;
10a37fd7a   Stephen Warren   disk: get_device_...
687
688
  			goto cleanup;
  		}
99d2c205d   Rob Herring   disk/part: introd...
689
690
691
692
693
694
  	}
  	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_...
695
696
  		ret  = -1;
  		goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
697
  	}
50ffc3b64   Lan Yixun (dlan)   fs/ext4: fix log2...
698
  	(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
10a37fd7a   Stephen Warren   disk: get_device_...
699
700
  	ret = part;
  	goto cleanup;
99d2c205d   Rob Herring   disk/part: introd...
701

10a37fd7a   Stephen Warren   disk: get_device_...
702
703
704
  cleanup:
  	free(dup_str);
  	return ret;
99d2c205d   Rob Herring   disk/part: introd...
705
  }