1fe8c2806Swdenk /* 2fe8c2806Swdenk * (C) Copyright 2000 3fe8c2806Swdenk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4fe8c2806Swdenk * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 6fe8c2806Swdenk */ 7fe8c2806Swdenk 8fe8c2806Swdenk /* 9fe8c2806Swdenk * Support for harddisk partitions. 10fe8c2806Swdenk * 11fe8c2806Swdenk * To be compatible with LinuxPPC and Apple we use the standard Apple 12fe8c2806Swdenk * SCSI disk partitioning scheme. For more information see: 13fe8c2806Swdenk * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92 14fe8c2806Swdenk */ 15fe8c2806Swdenk 16fe8c2806Swdenk #include <common.h> 17fe8c2806Swdenk #include <command.h> 18cf92e05cSSimon Glass #include <memalign.h> 19fe8c2806Swdenk #include <ide.h> 20fe8c2806Swdenk #include "part_mac.h" 21fe8c2806Swdenk 222c1af9dcSStephen Warren #ifdef HAVE_BLOCK_DEVICE 23fe8c2806Swdenk 24fe8c2806Swdenk /* stdlib.h causes some compatibility problems; should fixe these! -- wd */ 25fe8c2806Swdenk #ifndef __ldiv_t_defined 26fe8c2806Swdenk typedef struct { 27fe8c2806Swdenk long int quot; /* Quotient */ 28fe8c2806Swdenk long int rem; /* Remainder */ 29fe8c2806Swdenk } ldiv_t; 30fe8c2806Swdenk extern ldiv_t ldiv (long int __numer, long int __denom); 31fe8c2806Swdenk # define __ldiv_t_defined 1 32fe8c2806Swdenk #endif 33fe8c2806Swdenk 34fe8c2806Swdenk 354101f687SSimon Glass static int part_mac_read_ddb(struct blk_desc *dev_desc, 364101f687SSimon Glass mac_driver_desc_t *ddb_p); 374101f687SSimon Glass static int part_mac_read_pdb(struct blk_desc *dev_desc, int part, 384101f687SSimon Glass mac_partition_t *pdb_p); 39fe8c2806Swdenk 40fe8c2806Swdenk /* 41fe8c2806Swdenk * Test for a valid MAC partition 42fe8c2806Swdenk */ 4396e5b03cSSimon Glass static int test_part_mac(struct blk_desc *dev_desc) 44fe8c2806Swdenk { 4564a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 4664a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 47fe8c2806Swdenk ulong i, n; 48fe8c2806Swdenk 4964a08a9fSBenoît Thébaudeau if (part_mac_read_ddb (dev_desc, ddesc)) { 50fe8c2806Swdenk /* error reading Driver Desriptor Block, or no valid Signature */ 51fe8c2806Swdenk return (-1); 52fe8c2806Swdenk } 53fe8c2806Swdenk 54fe8c2806Swdenk n = 1; /* assuming at least one partition */ 55fe8c2806Swdenk for (i=1; i<=n; ++i) { 567c4213f6SStephen Warren if ((dev_desc->block_read(dev_desc, i, 1, 577c4213f6SStephen Warren (ulong *)mpart) != 1) || 5864a08a9fSBenoît Thébaudeau (mpart->signature != MAC_PARTITION_MAGIC) ) { 59fe8c2806Swdenk return (-1); 60fe8c2806Swdenk } 61fe8c2806Swdenk /* update partition count */ 6264a08a9fSBenoît Thébaudeau n = mpart->map_count; 63fe8c2806Swdenk } 64fe8c2806Swdenk return (0); 65fe8c2806Swdenk } 66fe8c2806Swdenk 6796e5b03cSSimon Glass static void print_part_mac(struct blk_desc *dev_desc) 68fe8c2806Swdenk { 69fe8c2806Swdenk ulong i, n; 7064a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 7164a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 72fe8c2806Swdenk ldiv_t mb, gb; 73fe8c2806Swdenk 7464a08a9fSBenoît Thébaudeau if (part_mac_read_ddb (dev_desc, ddesc)) { 75fe8c2806Swdenk /* error reading Driver Desriptor Block, or no valid Signature */ 76fe8c2806Swdenk return; 77fe8c2806Swdenk } 78fe8c2806Swdenk 7964a08a9fSBenoît Thébaudeau n = ddesc->blk_count; 80fe8c2806Swdenk 8164a08a9fSBenoît Thébaudeau mb = ldiv(n, ((1024 * 1024) / ddesc->blk_size)); /* MB */ 82fe8c2806Swdenk /* round to 1 digit */ 8364a08a9fSBenoît Thébaudeau mb.rem *= 10 * ddesc->blk_size; 84fe8c2806Swdenk mb.rem += 512 * 1024; 85fe8c2806Swdenk mb.rem /= 1024 * 1024; 86fe8c2806Swdenk 87fe8c2806Swdenk gb = ldiv(10 * mb.quot + mb.rem, 10240); 88fe8c2806Swdenk gb.rem += 512; 89fe8c2806Swdenk gb.rem /= 1024; 90fe8c2806Swdenk 91fe8c2806Swdenk 92fe8c2806Swdenk printf ("Block Size=%d, Number of Blocks=%d, " 93fe8c2806Swdenk "Total Capacity: %ld.%ld MB = %ld.%ld GB\n" 94fe8c2806Swdenk "DeviceType=0x%x, DeviceId=0x%x\n\n" 95fe8c2806Swdenk " #: type name" 96fe8c2806Swdenk " length base (size)\n", 9764a08a9fSBenoît Thébaudeau ddesc->blk_size, 9864a08a9fSBenoît Thébaudeau ddesc->blk_count, 99fe8c2806Swdenk mb.quot, mb.rem, gb.quot, gb.rem, 10064a08a9fSBenoît Thébaudeau ddesc->dev_type, ddesc->dev_id 101fe8c2806Swdenk ); 102fe8c2806Swdenk 103fe8c2806Swdenk n = 1; /* assuming at least one partition */ 104fe8c2806Swdenk for (i=1; i<=n; ++i) { 105fe8c2806Swdenk ulong bytes; 106fe8c2806Swdenk char c; 107fe8c2806Swdenk 108fe8c2806Swdenk printf ("%4ld: ", i); 1097c4213f6SStephen Warren if (dev_desc->block_read(dev_desc, i, 1, (ulong *)mpart) != 1) { 110fe8c2806Swdenk printf ("** Can't read Partition Map on %d:%ld **\n", 111fe8c2806Swdenk dev_desc->dev, i); 112fe8c2806Swdenk return; 113fe8c2806Swdenk } 114fe8c2806Swdenk 11564a08a9fSBenoît Thébaudeau if (mpart->signature != MAC_PARTITION_MAGIC) { 116fe8c2806Swdenk printf ("** Bad Signature on %d:%ld - " 117fe8c2806Swdenk "expected 0x%04x, got 0x%04x\n", 11864a08a9fSBenoît Thébaudeau dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart->signature); 119fe8c2806Swdenk return; 120fe8c2806Swdenk } 121fe8c2806Swdenk 122fe8c2806Swdenk /* update partition count */ 12364a08a9fSBenoît Thébaudeau n = mpart->map_count; 124fe8c2806Swdenk 125fe8c2806Swdenk c = 'k'; 12664a08a9fSBenoît Thébaudeau bytes = mpart->block_count; 12764a08a9fSBenoît Thébaudeau bytes /= (1024 / ddesc->blk_size); /* kB; assumes blk_size == 512 */ 128fe8c2806Swdenk if (bytes >= 1024) { 129fe8c2806Swdenk bytes >>= 10; 130fe8c2806Swdenk c = 'M'; 131fe8c2806Swdenk } 132fe8c2806Swdenk if (bytes >= 1024) { 133fe8c2806Swdenk bytes >>= 10; 134fe8c2806Swdenk c = 'G'; 135fe8c2806Swdenk } 136fe8c2806Swdenk 137fe8c2806Swdenk printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)\n", 13864a08a9fSBenoît Thébaudeau mpart->type, 13964a08a9fSBenoît Thébaudeau mpart->name, 14064a08a9fSBenoît Thébaudeau mpart->block_count, 14164a08a9fSBenoît Thébaudeau mpart->start_block, 142fe8c2806Swdenk bytes, c 143fe8c2806Swdenk ); 144fe8c2806Swdenk } 145fe8c2806Swdenk 146fe8c2806Swdenk return; 147fe8c2806Swdenk } 148fe8c2806Swdenk 149fe8c2806Swdenk 150fe8c2806Swdenk /* 151fe8c2806Swdenk * Read Device Descriptor Block 152fe8c2806Swdenk */ 1534101f687SSimon Glass static int part_mac_read_ddb(struct blk_desc *dev_desc, 1544101f687SSimon Glass mac_driver_desc_t *ddb_p) 155fe8c2806Swdenk { 1567c4213f6SStephen Warren if (dev_desc->block_read(dev_desc, 0, 1, (ulong *)ddb_p) != 1) { 157fe8c2806Swdenk printf ("** Can't read Driver Desriptor Block **\n"); 158fe8c2806Swdenk return (-1); 159fe8c2806Swdenk } 160fe8c2806Swdenk 161fe8c2806Swdenk if (ddb_p->signature != MAC_DRIVER_MAGIC) { 162fe8c2806Swdenk #if 0 163fe8c2806Swdenk printf ("** Bad Signature: expected 0x%04x, got 0x%04x\n", 164fe8c2806Swdenk MAC_DRIVER_MAGIC, ddb_p->signature); 165fe8c2806Swdenk #endif 166fe8c2806Swdenk return (-1); 167fe8c2806Swdenk } 168fe8c2806Swdenk return (0); 169fe8c2806Swdenk } 170fe8c2806Swdenk 171fe8c2806Swdenk /* 172fe8c2806Swdenk * Read Partition Descriptor Block 173fe8c2806Swdenk */ 1744101f687SSimon Glass static int part_mac_read_pdb(struct blk_desc *dev_desc, int part, 1754101f687SSimon Glass mac_partition_t *pdb_p) 176fe8c2806Swdenk { 177fe8c2806Swdenk int n = 1; 178fe8c2806Swdenk 179fe8c2806Swdenk for (;;) { 180fe8c2806Swdenk /* 181fe8c2806Swdenk * We must always read the descritpor block for 182fe8c2806Swdenk * partition 1 first since this is the only way to 183fe8c2806Swdenk * know how many partitions we have. 184fe8c2806Swdenk */ 1857c4213f6SStephen Warren if (dev_desc->block_read(dev_desc, n, 1, (ulong *)pdb_p) != 1) { 186fe8c2806Swdenk printf ("** Can't read Partition Map on %d:%d **\n", 187fe8c2806Swdenk dev_desc->dev, n); 188fe8c2806Swdenk return (-1); 189fe8c2806Swdenk } 190fe8c2806Swdenk 191fe8c2806Swdenk if (pdb_p->signature != MAC_PARTITION_MAGIC) { 192fe8c2806Swdenk printf ("** Bad Signature on %d:%d: " 193fe8c2806Swdenk "expected 0x%04x, got 0x%04x\n", 194fe8c2806Swdenk dev_desc->dev, n, MAC_PARTITION_MAGIC, pdb_p->signature); 195fe8c2806Swdenk return (-1); 196fe8c2806Swdenk } 197fe8c2806Swdenk 198fe8c2806Swdenk if (n == part) 199fe8c2806Swdenk return (0); 200fe8c2806Swdenk 201fe8c2806Swdenk if ((part < 1) || (part > pdb_p->map_count)) { 202fe8c2806Swdenk printf ("** Invalid partition %d:%d [%d:1...%d:%d only]\n", 203fe8c2806Swdenk dev_desc->dev, part, 204fe8c2806Swdenk dev_desc->dev, 205fe8c2806Swdenk dev_desc->dev, pdb_p->map_count); 206fe8c2806Swdenk return (-1); 207fe8c2806Swdenk } 208fe8c2806Swdenk 209fe8c2806Swdenk /* update partition count */ 210fe8c2806Swdenk n = part; 211fe8c2806Swdenk } 212fe8c2806Swdenk 213fe8c2806Swdenk /* NOTREACHED */ 214fe8c2806Swdenk } 215fe8c2806Swdenk 216*3e8bd469SSimon Glass static int part_get_info_mac(struct blk_desc *dev_desc, int part, 2174101f687SSimon Glass disk_partition_t *info) 218fe8c2806Swdenk { 21964a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1); 22064a08a9fSBenoît Thébaudeau ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1); 221fe8c2806Swdenk 22264a08a9fSBenoît Thébaudeau if (part_mac_read_ddb (dev_desc, ddesc)) { 223fe8c2806Swdenk return (-1); 224fe8c2806Swdenk } 225fe8c2806Swdenk 22664a08a9fSBenoît Thébaudeau info->blksz = ddesc->blk_size; 227fe8c2806Swdenk 22864a08a9fSBenoît Thébaudeau if (part_mac_read_pdb (dev_desc, part, mpart)) { 229fe8c2806Swdenk return (-1); 230fe8c2806Swdenk } 231fe8c2806Swdenk 23264a08a9fSBenoît Thébaudeau info->start = mpart->start_block; 23364a08a9fSBenoît Thébaudeau info->size = mpart->block_count; 23464a08a9fSBenoît Thébaudeau memcpy (info->type, mpart->type, sizeof(info->type)); 23564a08a9fSBenoît Thébaudeau memcpy (info->name, mpart->name, sizeof(info->name)); 236fe8c2806Swdenk 237fe8c2806Swdenk return (0); 238fe8c2806Swdenk } 239fe8c2806Swdenk 24096e5b03cSSimon Glass U_BOOT_PART_TYPE(mac) = { 24196e5b03cSSimon Glass .name = "MAC", 24296e5b03cSSimon Glass .part_type = PART_TYPE_MAC, 243*3e8bd469SSimon Glass .get_info = part_get_info_mac, 24496e5b03cSSimon Glass .print = print_part_mac, 24596e5b03cSSimon Glass .test = test_part_mac, 24696e5b03cSSimon Glass }; 247cde5c64dSJon Loeliger #endif 248