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