1 /* 2 * fs/partitions/mac.c 3 * 4 * Code extracted from drivers/block/genhd.c 5 * Copyright (C) 1991-1998 Linus Torvalds 6 * Re-organised Feb 1998 Russell King 7 */ 8 9 #include <linux/ctype.h> 10 #include "check.h" 11 #include "mac.h" 12 13 #ifdef CONFIG_PPC_PMAC 14 #include <asm/machdep.h> 15 extern void note_bootable_part(dev_t dev, int part, int goodness); 16 #endif 17 18 /* 19 * Code to understand MacOS partition tables. 20 */ 21 22 static inline void mac_fix_string(char *stg, int len) 23 { 24 int i; 25 26 for (i = len - 1; i >= 0 && stg[i] == ' '; i--) 27 stg[i] = 0; 28 } 29 30 int mac_partition(struct parsed_partitions *state) 31 { 32 Sector sect; 33 unsigned char *data; 34 int slot, blocks_in_map; 35 unsigned secsize, datasize, partoffset; 36 #ifdef CONFIG_PPC_PMAC 37 int found_root = 0; 38 int found_root_goodness = 0; 39 #endif 40 struct mac_partition *part; 41 struct mac_driver_desc *md; 42 43 /* Get 0th block and look at the first partition map entry. */ 44 md = read_part_sector(state, 0, §); 45 if (!md) 46 return -1; 47 if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { 48 put_dev_sector(sect); 49 return 0; 50 } 51 secsize = be16_to_cpu(md->block_size); 52 put_dev_sector(sect); 53 datasize = round_down(secsize, 512); 54 data = read_part_sector(state, datasize / 512, §); 55 if (!data) 56 return -1; 57 partoffset = secsize % 512; 58 if (partoffset + sizeof(*part) > datasize) 59 return -1; 60 part = (struct mac_partition *) (data + partoffset); 61 if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { 62 put_dev_sector(sect); 63 return 0; /* not a MacOS disk */ 64 } 65 blocks_in_map = be32_to_cpu(part->map_count); 66 if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) { 67 put_dev_sector(sect); 68 return 0; 69 } 70 71 if (blocks_in_map >= state->limit) 72 blocks_in_map = state->limit - 1; 73 74 strlcat(state->pp_buf, " [mac]", PAGE_SIZE); 75 for (slot = 1; slot <= blocks_in_map; ++slot) { 76 int pos = slot * secsize; 77 put_dev_sector(sect); 78 data = read_part_sector(state, pos/512, §); 79 if (!data) 80 return -1; 81 part = (struct mac_partition *) (data + pos%512); 82 if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) 83 break; 84 put_partition(state, slot, 85 be32_to_cpu(part->start_block) * (secsize/512), 86 be32_to_cpu(part->block_count) * (secsize/512)); 87 88 if (!strncasecmp(part->type, "Linux_RAID", 10)) 89 state->parts[slot].flags = ADDPART_FLAG_RAID; 90 #ifdef CONFIG_PPC_PMAC 91 /* 92 * If this is the first bootable partition, tell the 93 * setup code, in case it wants to make this the root. 94 */ 95 if (machine_is(powermac)) { 96 int goodness = 0; 97 98 mac_fix_string(part->processor, 16); 99 mac_fix_string(part->name, 32); 100 mac_fix_string(part->type, 32); 101 102 if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) 103 && strcasecmp(part->processor, "powerpc") == 0) 104 goodness++; 105 106 if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0 107 || (strncasecmp(part->type, "Linux", 5) == 0 108 && strcasecmp(part->type, "Linux_swap") != 0)) { 109 int i, l; 110 111 goodness++; 112 l = strlen(part->name); 113 if (strcmp(part->name, "/") == 0) 114 goodness++; 115 for (i = 0; i <= l - 4; ++i) { 116 if (strncasecmp(part->name + i, "root", 117 4) == 0) { 118 goodness += 2; 119 break; 120 } 121 } 122 if (strncasecmp(part->name, "swap", 4) == 0) 123 goodness--; 124 } 125 126 if (goodness > found_root_goodness) { 127 found_root = slot; 128 found_root_goodness = goodness; 129 } 130 } 131 #endif /* CONFIG_PPC_PMAC */ 132 } 133 #ifdef CONFIG_PPC_PMAC 134 if (found_root_goodness) 135 note_bootable_part(state->bdev->bd_dev, found_root, 136 found_root_goodness); 137 #endif 138 139 put_dev_sector(sect); 140 strlcat(state->pp_buf, "\n", PAGE_SIZE); 141 return 1; 142 } 143