1 /* 2 * (C) Copyright 2000 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 /* 25 * Support for harddisk partitions. 26 * 27 * To be compatible with LinuxPPC and Apple we use the standard Apple 28 * SCSI disk partitioning scheme. For more information see: 29 * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92 30 */ 31 32 #include <common.h> 33 #include <command.h> 34 #include <ide.h> 35 #include "part_mac.h" 36 37 #if defined(CONFIG_CMD_IDE) || \ 38 defined(CONFIG_CMD_SCSI) || \ 39 defined(CONFIG_CMD_SATA) || \ 40 defined(CONFIG_CMD_USB) || \ 41 defined(CONFIG_MMC) || \ 42 defined(CONFIG_SYSTEMACE) 43 44 /* stdlib.h causes some compatibility problems; should fixe these! -- wd */ 45 #ifndef __ldiv_t_defined 46 typedef struct { 47 long int quot; /* Quotient */ 48 long int rem; /* Remainder */ 49 } ldiv_t; 50 extern ldiv_t ldiv (long int __numer, long int __denom); 51 # define __ldiv_t_defined 1 52 #endif 53 54 55 static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p); 56 static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p); 57 58 /* 59 * Test for a valid MAC partition 60 */ 61 int test_part_mac (block_dev_desc_t *dev_desc) 62 { 63 ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 64 ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 65 ulong i, n; 66 67 if (part_mac_read_ddb (dev_desc, ddesc)) { 68 /* error reading Driver Desriptor Block, or no valid Signature */ 69 return (-1); 70 } 71 72 n = 1; /* assuming at least one partition */ 73 for (i=1; i<=n; ++i) { 74 if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)mpart) != 1) || 75 (mpart->signature != MAC_PARTITION_MAGIC) ) { 76 return (-1); 77 } 78 /* update partition count */ 79 n = mpart->map_count; 80 } 81 return (0); 82 } 83 84 85 void print_part_mac (block_dev_desc_t *dev_desc) 86 { 87 ulong i, n; 88 ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 89 ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 90 ldiv_t mb, gb; 91 92 if (part_mac_read_ddb (dev_desc, ddesc)) { 93 /* error reading Driver Desriptor Block, or no valid Signature */ 94 return; 95 } 96 97 n = ddesc->blk_count; 98 99 mb = ldiv(n, ((1024 * 1024) / ddesc->blk_size)); /* MB */ 100 /* round to 1 digit */ 101 mb.rem *= 10 * ddesc->blk_size; 102 mb.rem += 512 * 1024; 103 mb.rem /= 1024 * 1024; 104 105 gb = ldiv(10 * mb.quot + mb.rem, 10240); 106 gb.rem += 512; 107 gb.rem /= 1024; 108 109 110 printf ("Block Size=%d, Number of Blocks=%d, " 111 "Total Capacity: %ld.%ld MB = %ld.%ld GB\n" 112 "DeviceType=0x%x, DeviceId=0x%x\n\n" 113 " #: type name" 114 " length base (size)\n", 115 ddesc->blk_size, 116 ddesc->blk_count, 117 mb.quot, mb.rem, gb.quot, gb.rem, 118 ddesc->dev_type, ddesc->dev_id 119 ); 120 121 n = 1; /* assuming at least one partition */ 122 for (i=1; i<=n; ++i) { 123 ulong bytes; 124 char c; 125 126 printf ("%4ld: ", i); 127 if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *)mpart) != 1) { 128 printf ("** Can't read Partition Map on %d:%ld **\n", 129 dev_desc->dev, i); 130 return; 131 } 132 133 if (mpart->signature != MAC_PARTITION_MAGIC) { 134 printf ("** Bad Signature on %d:%ld - " 135 "expected 0x%04x, got 0x%04x\n", 136 dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart->signature); 137 return; 138 } 139 140 /* update partition count */ 141 n = mpart->map_count; 142 143 c = 'k'; 144 bytes = mpart->block_count; 145 bytes /= (1024 / ddesc->blk_size); /* kB; assumes blk_size == 512 */ 146 if (bytes >= 1024) { 147 bytes >>= 10; 148 c = 'M'; 149 } 150 if (bytes >= 1024) { 151 bytes >>= 10; 152 c = 'G'; 153 } 154 155 printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)\n", 156 mpart->type, 157 mpart->name, 158 mpart->block_count, 159 mpart->start_block, 160 bytes, c 161 ); 162 } 163 164 return; 165 } 166 167 168 /* 169 * Read Device Descriptor Block 170 */ 171 static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p) 172 { 173 if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)ddb_p) != 1) { 174 printf ("** Can't read Driver Desriptor Block **\n"); 175 return (-1); 176 } 177 178 if (ddb_p->signature != MAC_DRIVER_MAGIC) { 179 #if 0 180 printf ("** Bad Signature: expected 0x%04x, got 0x%04x\n", 181 MAC_DRIVER_MAGIC, ddb_p->signature); 182 #endif 183 return (-1); 184 } 185 return (0); 186 } 187 188 /* 189 * Read Partition Descriptor Block 190 */ 191 static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p) 192 { 193 int n = 1; 194 195 for (;;) { 196 /* 197 * We must always read the descritpor block for 198 * partition 1 first since this is the only way to 199 * know how many partitions we have. 200 */ 201 if (dev_desc->block_read (dev_desc->dev, n, 1, (ulong *)pdb_p) != 1) { 202 printf ("** Can't read Partition Map on %d:%d **\n", 203 dev_desc->dev, n); 204 return (-1); 205 } 206 207 if (pdb_p->signature != MAC_PARTITION_MAGIC) { 208 printf ("** Bad Signature on %d:%d: " 209 "expected 0x%04x, got 0x%04x\n", 210 dev_desc->dev, n, MAC_PARTITION_MAGIC, pdb_p->signature); 211 return (-1); 212 } 213 214 if (n == part) 215 return (0); 216 217 if ((part < 1) || (part > pdb_p->map_count)) { 218 printf ("** Invalid partition %d:%d [%d:1...%d:%d only]\n", 219 dev_desc->dev, part, 220 dev_desc->dev, 221 dev_desc->dev, pdb_p->map_count); 222 return (-1); 223 } 224 225 /* update partition count */ 226 n = part; 227 } 228 229 /* NOTREACHED */ 230 } 231 232 int get_partition_info_mac (block_dev_desc_t *dev_desc, int part, disk_partition_t *info) 233 { 234 ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 235 ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 236 237 if (part_mac_read_ddb (dev_desc, ddesc)) { 238 return (-1); 239 } 240 241 info->blksz = ddesc->blk_size; 242 243 if (part_mac_read_pdb (dev_desc, part, mpart)) { 244 return (-1); 245 } 246 247 info->start = mpart->start_block; 248 info->size = mpart->block_count; 249 memcpy (info->type, mpart->type, sizeof(info->type)); 250 memcpy (info->name, mpart->name, sizeof(info->name)); 251 252 return (0); 253 } 254 255 #endif 256