xref: /openbmc/u-boot/disk/part.c (revision 849fc424)
1 /*
2  * (C) Copyright 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 #include <command.h>
26 #include <ide.h>
27 #include <part.h>
28 
29 #undef	PART_DEBUG
30 
31 #ifdef	PART_DEBUG
32 #define	PRINTF(fmt,args...)	printf (fmt ,##args)
33 #else
34 #define PRINTF(fmt,args...)
35 #endif
36 
37 #if (defined(CONFIG_CMD_IDE) || \
38      defined(CONFIG_CMD_SATA) || \
39      defined(CONFIG_CMD_SCSI) || \
40      defined(CONFIG_CMD_USB) || \
41      defined(CONFIG_MMC) || \
42      defined(CONFIG_SYSTEMACE) )
43 
44 struct block_drvr {
45 	char *name;
46 	block_dev_desc_t* (*get_dev)(int dev);
47 };
48 
49 static const struct block_drvr block_drvr[] = {
50 #if defined(CONFIG_CMD_IDE)
51 	{ .name = "ide", .get_dev = ide_get_dev, },
52 #endif
53 #if defined(CONFIG_CMD_SATA)
54 	{.name = "sata", .get_dev = sata_get_dev, },
55 #endif
56 #if defined(CONFIG_CMD_SCSI)
57 	{ .name = "scsi", .get_dev = scsi_get_dev, },
58 #endif
59 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
60 	{ .name = "usb", .get_dev = usb_stor_get_dev, },
61 #endif
62 #if defined(CONFIG_MMC)
63 	{ .name = "mmc", .get_dev = mmc_get_dev, },
64 #endif
65 #if defined(CONFIG_SYSTEMACE)
66 	{ .name = "ace", .get_dev = systemace_get_dev, },
67 #endif
68 	{ },
69 };
70 
71 DECLARE_GLOBAL_DATA_PTR;
72 
73 block_dev_desc_t *get_dev(char* ifname, int dev)
74 {
75 	const struct block_drvr *drvr = block_drvr;
76 	block_dev_desc_t* (*reloc_get_dev)(int dev);
77 	char *name;
78 
79 	if (!ifname)
80 		return NULL;
81 
82 	name = drvr->name;
83 #ifdef CONFIG_NEEDS_MANUAL_RELOC
84 	name += gd->reloc_off;
85 #endif
86 	while (drvr->name) {
87 		name = drvr->name;
88 		reloc_get_dev = drvr->get_dev;
89 #ifdef CONFIG_NEEDS_MANUAL_RELOC
90 		name += gd->reloc_off;
91 		reloc_get_dev += gd->reloc_off;
92 #endif
93 		if (strncmp(ifname, name, strlen(name)) == 0)
94 			return reloc_get_dev(dev);
95 		drvr++;
96 	}
97 	return NULL;
98 }
99 #else
100 block_dev_desc_t *get_dev(char* ifname, int dev)
101 {
102 	return NULL;
103 }
104 #endif
105 
106 #if (defined(CONFIG_CMD_IDE) || \
107      defined(CONFIG_CMD_SATA) || \
108      defined(CONFIG_CMD_SCSI) || \
109      defined(CONFIG_CMD_USB) || \
110      defined(CONFIG_MMC) || \
111      defined(CONFIG_SYSTEMACE) )
112 
113 /* ------------------------------------------------------------------------- */
114 /*
115  * reports device info to the user
116  */
117 
118 #ifdef CONFIG_LBA48
119 typedef uint64_t lba512_t;
120 #else
121 typedef lbaint_t lba512_t;
122 #endif
123 
124 /*
125  * Overflowless variant of (block_count * mul_by / div_by)
126  * when div_by > mul_by
127  */
128 static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t div_by)
129 {
130 	lba512_t bc_quot, bc_rem;
131 
132 	/* x * m / d == x / d * m + (x % d) * m / d */
133 	bc_quot = block_count / div_by;
134 	bc_rem  = block_count - div_by * bc_quot;
135 	return bc_quot * mul_by + (bc_rem * mul_by) / div_by;
136 }
137 
138 void dev_print (block_dev_desc_t *dev_desc)
139 {
140 	lba512_t lba512; /* number of blocks if 512bytes block size */
141 
142 	if (dev_desc->type == DEV_TYPE_UNKNOWN) {
143 		puts ("not available\n");
144 		return;
145 	}
146 
147 	switch (dev_desc->if_type) {
148 	case IF_TYPE_SCSI:
149 		printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
150 			dev_desc->target,dev_desc->lun,
151 			dev_desc->vendor,
152 			dev_desc->product,
153 			dev_desc->revision);
154 		break;
155 	case IF_TYPE_ATAPI:
156 	case IF_TYPE_IDE:
157 	case IF_TYPE_SATA:
158 		printf ("Model: %s Firm: %s Ser#: %s\n",
159 			dev_desc->vendor,
160 			dev_desc->revision,
161 			dev_desc->product);
162 		break;
163 	case IF_TYPE_SD:
164 	case IF_TYPE_MMC:
165 	case IF_TYPE_USB:
166 		printf ("Vendor: %s Rev: %s Prod: %s\n",
167 			dev_desc->vendor,
168 			dev_desc->revision,
169 			dev_desc->product);
170 		break;
171 	case IF_TYPE_DOC:
172 		puts("device type DOC\n");
173 		return;
174 	case IF_TYPE_UNKNOWN:
175 		puts("device type unknown\n");
176 		return;
177 	default:
178 		printf("Unhandled device type: %i\n", dev_desc->if_type);
179 		return;
180 	}
181 	puts ("            Type: ");
182 	if (dev_desc->removable)
183 		puts ("Removable ");
184 	switch (dev_desc->type & 0x1F) {
185 	case DEV_TYPE_HARDDISK:
186 		puts ("Hard Disk");
187 		break;
188 	case DEV_TYPE_CDROM:
189 		puts ("CD ROM");
190 		break;
191 	case DEV_TYPE_OPDISK:
192 		puts ("Optical Device");
193 		break;
194 	case DEV_TYPE_TAPE:
195 		puts ("Tape");
196 		break;
197 	default:
198 		printf ("# %02X #", dev_desc->type & 0x1F);
199 		break;
200 	}
201 	puts ("\n");
202 	if ((dev_desc->lba * dev_desc->blksz)>0L) {
203 		ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
204 		lbaint_t lba;
205 
206 		lba = dev_desc->lba;
207 
208 		lba512 = (lba * (dev_desc->blksz/512));
209 		/* round to 1 digit */
210 		mb = lba512_muldiv(lba512, 10, 2048);	/* 2048 = (1024 * 1024) / 512 MB */
211 
212 		mb_quot	= mb / 10;
213 		mb_rem	= mb - (10 * mb_quot);
214 
215 		gb = mb / 1024;
216 		gb_quot	= gb / 10;
217 		gb_rem	= gb - (10 * gb_quot);
218 #ifdef CONFIG_LBA48
219 		if (dev_desc->lba48)
220 			printf ("            Supports 48-bit addressing\n");
221 #endif
222 #if defined(CONFIG_SYS_64BIT_LBA)
223 		printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%Ld x %ld)\n",
224 			mb_quot, mb_rem,
225 			gb_quot, gb_rem,
226 			lba,
227 			dev_desc->blksz);
228 #else
229 		printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n",
230 			mb_quot, mb_rem,
231 			gb_quot, gb_rem,
232 			(ulong)lba,
233 			dev_desc->blksz);
234 #endif
235 	} else {
236 		puts ("            Capacity: not available\n");
237 	}
238 }
239 #endif
240 
241 #if (defined(CONFIG_CMD_IDE) || \
242      defined(CONFIG_CMD_SATA) || \
243      defined(CONFIG_CMD_SCSI) || \
244      defined(CONFIG_CMD_USB) || \
245      defined(CONFIG_MMC)		|| \
246      defined(CONFIG_SYSTEMACE) )
247 
248 #if defined(CONFIG_MAC_PARTITION) || \
249     defined(CONFIG_DOS_PARTITION) || \
250     defined(CONFIG_ISO_PARTITION) || \
251     defined(CONFIG_AMIGA_PARTITION) || \
252     defined(CONFIG_EFI_PARTITION)
253 
254 void init_part (block_dev_desc_t * dev_desc)
255 {
256 #ifdef CONFIG_ISO_PARTITION
257 	if (test_part_iso(dev_desc) == 0) {
258 		dev_desc->part_type = PART_TYPE_ISO;
259 		return;
260 	}
261 #endif
262 
263 #ifdef CONFIG_MAC_PARTITION
264 	if (test_part_mac(dev_desc) == 0) {
265 		dev_desc->part_type = PART_TYPE_MAC;
266 		return;
267 	}
268 #endif
269 
270 /* must be placed before DOS partition detection */
271 #ifdef CONFIG_EFI_PARTITION
272 	if (test_part_efi(dev_desc) == 0) {
273 		dev_desc->part_type = PART_TYPE_EFI;
274 		return;
275 	}
276 #endif
277 
278 #ifdef CONFIG_DOS_PARTITION
279 	if (test_part_dos(dev_desc) == 0) {
280 		dev_desc->part_type = PART_TYPE_DOS;
281 		return;
282 	}
283 #endif
284 
285 #ifdef CONFIG_AMIGA_PARTITION
286 	if (test_part_amiga(dev_desc) == 0) {
287 	    dev_desc->part_type = PART_TYPE_AMIGA;
288 	    return;
289 	}
290 #endif
291 }
292 
293 
294 int get_partition_info (block_dev_desc_t *dev_desc, int part
295 					, disk_partition_t *info)
296 {
297 	switch (dev_desc->part_type) {
298 #ifdef CONFIG_MAC_PARTITION
299 	case PART_TYPE_MAC:
300 		if (get_partition_info_mac(dev_desc,part,info) == 0) {
301 			PRINTF ("## Valid MAC partition found ##\n");
302 			return (0);
303 		}
304 		break;
305 #endif
306 
307 #ifdef CONFIG_DOS_PARTITION
308 	case PART_TYPE_DOS:
309 		if (get_partition_info_dos(dev_desc,part,info) == 0) {
310 			PRINTF ("## Valid DOS partition found ##\n");
311 			return (0);
312 		}
313 		break;
314 #endif
315 
316 #ifdef CONFIG_ISO_PARTITION
317 	case PART_TYPE_ISO:
318 		if (get_partition_info_iso(dev_desc,part,info) == 0) {
319 			PRINTF ("## Valid ISO boot partition found ##\n");
320 			return (0);
321 		}
322 		break;
323 #endif
324 
325 #ifdef CONFIG_AMIGA_PARTITION
326 	case PART_TYPE_AMIGA:
327 	    if (get_partition_info_amiga(dev_desc, part, info) == 0)
328 	    {
329 		PRINTF ("## Valid Amiga partition found ##\n");
330 		return (0);
331 	    }
332 	    break;
333 #endif
334 
335 #ifdef CONFIG_EFI_PARTITION
336 	case PART_TYPE_EFI:
337 		if (get_partition_info_efi(dev_desc,part,info) == 0) {
338 			PRINTF ("## Valid EFI partition found ##\n");
339 			return (0);
340 		}
341 		break;
342 #endif
343 	default:
344 		break;
345 	}
346 	return (-1);
347 }
348 
349 static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
350 {
351 	puts ("\nPartition Map for ");
352 	switch (dev_desc->if_type) {
353 	case IF_TYPE_IDE:
354 		puts ("IDE");
355 		break;
356 	case IF_TYPE_SATA:
357 		puts ("SATA");
358 		break;
359 	case IF_TYPE_SCSI:
360 		puts ("SCSI");
361 		break;
362 	case IF_TYPE_ATAPI:
363 		puts ("ATAPI");
364 		break;
365 	case IF_TYPE_USB:
366 		puts ("USB");
367 		break;
368 	case IF_TYPE_DOC:
369 		puts ("DOC");
370 		break;
371 	case IF_TYPE_MMC:
372 		puts ("MMC");
373 		break;
374 	default:
375 		puts ("UNKNOWN");
376 		break;
377 	}
378 	printf (" device %d  --   Partition Type: %s\n\n",
379 			dev_desc->dev, type);
380 }
381 
382 void print_part (block_dev_desc_t * dev_desc)
383 {
384 
385 		switch (dev_desc->part_type) {
386 #ifdef CONFIG_MAC_PARTITION
387 	case PART_TYPE_MAC:
388 		PRINTF ("## Testing for valid MAC partition ##\n");
389 		print_part_header ("MAC", dev_desc);
390 		print_part_mac (dev_desc);
391 		return;
392 #endif
393 #ifdef CONFIG_DOS_PARTITION
394 	case PART_TYPE_DOS:
395 		PRINTF ("## Testing for valid DOS partition ##\n");
396 		print_part_header ("DOS", dev_desc);
397 		print_part_dos (dev_desc);
398 		return;
399 #endif
400 
401 #ifdef CONFIG_ISO_PARTITION
402 	case PART_TYPE_ISO:
403 		PRINTF ("## Testing for valid ISO Boot partition ##\n");
404 		print_part_header ("ISO", dev_desc);
405 		print_part_iso (dev_desc);
406 		return;
407 #endif
408 
409 #ifdef CONFIG_AMIGA_PARTITION
410 	case PART_TYPE_AMIGA:
411 	    PRINTF ("## Testing for a valid Amiga partition ##\n");
412 	    print_part_header ("AMIGA", dev_desc);
413 	    print_part_amiga (dev_desc);
414 	    return;
415 #endif
416 
417 #ifdef CONFIG_EFI_PARTITION
418 	case PART_TYPE_EFI:
419 		PRINTF ("## Testing for valid EFI partition ##\n");
420 		print_part_header ("EFI", dev_desc);
421 		print_part_efi (dev_desc);
422 		return;
423 #endif
424 	}
425 	puts ("## Unknown partition table\n");
426 }
427 
428 
429 #else	/* neither MAC nor DOS nor ISO nor AMIGA nor EFI partition configured */
430 # error neither CONFIG_MAC_PARTITION nor CONFIG_DOS_PARTITION
431 # error nor CONFIG_ISO_PARTITION nor CONFIG_AMIGA_PARTITION
432 # error nor CONFIG_EFI_PARTITION configured!
433 #endif
434 
435 #endif
436