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