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