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