3 Copyright (C) 1999 Benjamin Herrenschmidt
5 Todo: Add disklabel (or let OF do it ?). Eventually think about
6 fixing CDROM handling by directly using the ATAPI layer.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
27 #include "fdisk-part.h"
28 #include "partition.h"
31 #include "linux/iso_fs.h"
35 /* We currently don't check the partition type, some users
36 * are putting crap there and still expect it to work...
38 #undef CHECK_FOR_VALID_MAC_PARTITION_TYPE
40 #ifdef CHECK_FOR_VALID_MAC_PARTITION_TYPE
41 static const char *valid_mac_partition_types[] = {
53 static unsigned long swab32(unsigned long value);
55 #define MAX_BLOCK_SIZE 2048
56 static unsigned char block_buffer[MAX_BLOCK_SIZE];
59 add_new_partition(struct partition_t** list, int part_number, const char *part_type,
60 const char *part_name, unsigned long part_start, unsigned long part_size,
61 unsigned short part_blocksize)
63 struct partition_t* part;
64 part = (struct partition_t*)malloc(sizeof(struct partition_t));
66 part->part_number = part_number;
67 strncpy(part->part_type, part_type, MAX_PART_NAME);
68 strncpy(part->part_name, part_name, MAX_PART_NAME);
69 part->part_start = part_start;
70 part->part_size = part_size;
71 part->blocksize = part_blocksize;
73 /* Tack this entry onto the list */
78 /* Note, we rely on partitions being dev-block-size aligned,
79 * I have to check if it's true. If it's not, then things will get
80 * a bit more complicated
83 partition_mac_lookup( const char *dev_name, prom_handle disk,
84 unsigned int prom_blksize, struct partition_t** list )
88 /* block_buffer contains block 0 from the partitions_lookup() stage */
89 struct mac_partition* part = (struct mac_partition *)block_buffer;
90 unsigned short ptable_block_size =
91 ((struct mac_driver_desc *)block_buffer)->block_size;
94 for (block=1; block < map_size + 1; block++)
96 #ifdef CHECK_FOR_VALID_MAC_PARTITION_TYPE
100 if (prom_readblocks(disk, block, 1, block_buffer) != 1) {
101 prom_printf("Can't read partition %d\n", block);
104 if (part->signature != MAC_PARTITION_MAGIC) {
106 prom_printf("Wrong partition %d signature\n", block);
111 map_size = part->map_count;
113 #ifdef CHECK_FOR_VALID_MAC_PARTITION_TYPE
114 /* We don't bother looking at swap partitions of any type,
115 * and the rest are the ones we know about */
116 for (ptype = valid_mac_partition_types; ptype; ptype++)
117 if (!strcmp (part->type, ptype))
124 prom_printf( "MAC: Unsupported partition #%d; type=%s\n",
130 #ifdef CHECK_FOR_VALID_MAC_PARTITION_TYPE
133 /* We use the partition block size from the partition table.
134 * The filesystem implmentations are responsible for mapping
135 * to their own fs blocksize */
137 list, /* partition list */
138 block, /* partition number */
139 part->type, /* type */
140 part->name, /* name */
141 part->start_block + part->data_start, /* start */
142 part->data_count, /* size */
148 * Same function as partition_mac_lookup(), except for fdisk
152 partition_fdisk_lookup( const char *dev_name, prom_handle disk,
153 unsigned int prom_blksize, struct partition_t** list )
157 /* fdisk partition tables start at offset 0x1be
158 * from byte 0 of the boot drive.
160 struct fdisk_partition* part =
161 (struct fdisk_partition *) (block_buffer + 0x1be);
163 for (partition=1; partition <= 4 ;partition++, part++) {
164 if (part->sys_ind == LINUX_NATIVE) {
165 add_new_partition( list,
169 swab32(*(unsigned int *)(part->start4)),
170 swab32(*(unsigned int *)(part->size4)),
176 /* I don't know if it's possible to handle multisession and other multitrack
177 * stuffs with the current OF disklabel package. This can still be implemented
178 * with direct calls to atapi stuffs.
179 * Currently, we enter this code for any device of block size 0x2048 who lacks
180 * a MacOS partition map signature.
183 identify_iso_fs(ihandle device, unsigned int *iso_root_block)
187 for (block = 16; block < 100; block++) {
188 struct iso_volume_descriptor * vdp;
190 if (prom_readblocks(device, block, 1, block_buffer) != 1) {
191 prom_printf("Can't read volume desc block %d\n", block);
195 vdp = (struct iso_volume_descriptor *)block_buffer;
197 /* Due to the overlapping physical location of the descriptors,
198 * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure
199 * proper identification in this case, we first check for ISO.
201 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
202 *iso_root_block = block;
211 partitions_lookup(const char *device)
214 struct mac_driver_desc *desc = (struct mac_driver_desc *)block_buffer;
215 struct partition_t* list = NULL;
216 unsigned int prom_blksize, iso_root_block;
218 strncpy(block_buffer, device, 2040);
219 strcat(block_buffer, ":0");
222 disk = prom_open(block_buffer);
224 prom_printf("Can't open device <%s>\n", block_buffer);
227 prom_blksize = prom_getblksize(disk);
228 DEBUG_F("block size of device is %d\n", prom_blksize);
230 if (prom_blksize <= 1)
232 if (prom_blksize > MAX_BLOCK_SIZE) {
233 prom_printf("block_size %d not supported !\n", prom_blksize);
237 /* Read boot blocs */
238 if (prom_readblocks(disk, 0, 1, block_buffer) != 1) {
239 prom_printf("Can't read boot blocks\n");
242 if (desc->signature == MAC_DRIVER_MAGIC) {
243 /* pdisk partition format */
244 partition_mac_lookup(device, disk, prom_blksize, &list);
245 } else if ((block_buffer[510] == 0x55) && (block_buffer[511] == 0xaa)) {
246 /* fdisk partition format */
247 partition_fdisk_lookup(device, disk, prom_blksize, &list);
248 } else if (prom_blksize == 2048 && identify_iso_fs(disk, &iso_root_block)) {
249 add_new_partition(&list,
256 prom_printf("ISO9660 disk\n");
258 prom_printf("No supported partition table detected\n");
269 get_part_type(char *device, int partition)
271 struct partition_t* parts;
272 struct partition_t* p;
273 struct partition_t* found;
276 if (prom_get_devtype(device) != FILE_DEVICE_BLOCK)
279 parts = partitions_lookup(device);
285 for (p = parts; p && !found; p=p->next) {
286 DEBUG_F("number: %02d, start: 0x%08lx, length: 0x%08lx, type: %s, name: %s\n",
287 p->part_number, p->part_start, p->part_size, p->part_type, p->part_name);
288 if ((partition >= 0) && (partition == p->part_number)) {
289 type = strdup(p->part_type);
294 partitions_free(parts);
298 /* Freed in reverse order of allocation to help malloc'ator */
300 partitions_free(struct partition_t* list)
302 struct partition_t* next;
311 swab32(unsigned long value)
315 __asm__("rlwimi %0,%1,24,16,23\n\t"
316 "rlwimi %0,%1,8,8,15\n\t"
317 "rlwimi %0,%1,24,0,7"
319 : "r" (value), "0" (value >> 24));
326 * c-file-style: "k&r"