]>
Commit | Line | Data |
---|---|---|
5c9204dc KZ |
1 | /* |
2 | * mac partitions parsing code | |
3 | * | |
4 | * Copyright (C) 2009 Karel Zak <kzak@redhat.com> | |
5 | * | |
6 | * This file may be redistributed under the terms of the | |
7 | * GNU Lesser General Public License. | |
8 | * | |
9 | */ | |
10 | #include <stdio.h> | |
11 | #include <string.h> | |
12 | #include <stdlib.h> | |
13 | #include <stdint.h> | |
14 | ||
15 | #include "partitions.h" | |
16 | ||
17 | #define MAC_PARTITION_MAGIC 0x504d | |
18 | #define MAC_PARTITION_MAGIC_OLD 0x5453 | |
19 | ||
20 | /* | |
21 | * Mac partition entry | |
22 | * http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-126.html | |
23 | */ | |
24 | struct mac_partition { | |
25 | uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */ | |
26 | uint16_t reserved; /* reserved */ | |
27 | uint32_t map_count; /* # blocks in partition map */ | |
28 | uint32_t start_block; /* absolute starting block # of partition */ | |
29 | uint32_t block_count; /* number of blocks in partition */ | |
30 | char name[32]; /* partition name */ | |
31 | char type[32]; /* string type description */ | |
32 | uint32_t data_start; /* rel block # of first data block */ | |
33 | uint32_t data_count; /* number of data blocks */ | |
34 | uint32_t status; /* partition status bits */ | |
35 | uint32_t boot_start; /* first logical block of boot code */ | |
36 | uint32_t boot_size; /* size of boot code, in bytes */ | |
37 | uint32_t boot_load; /* boot code load address */ | |
38 | uint32_t boot_load2; /* reserved */ | |
39 | uint32_t boot_entry; /* boot code entry point */ | |
40 | uint32_t boot_entry2; /* reserved */ | |
41 | uint32_t boot_cksum; /* boot code checksum */ | |
42 | char processor[16]; /* identifies ISA of boot */ | |
43 | ||
44 | /* there is more stuff after this that we don't need */ | |
11854e2e | 45 | } __attribute__((packed)); |
5c9204dc KZ |
46 | |
47 | /* | |
48 | * Driver descriptor structure, in block 0 | |
49 | * http://developer.apple.com/legacy/mac/library/documentation/mac/Devices/Devices-121.html | |
50 | */ | |
51 | struct mac_driver_desc { | |
52 | uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */ | |
53 | uint16_t block_size; /* block size of the device */ | |
54 | uint32_t block_count; /* number of blocks on the device */ | |
55 | ||
56 | /* there is more stuff after this that we don't need */ | |
11854e2e | 57 | } __attribute__((packed)); |
5c9204dc KZ |
58 | |
59 | static inline unsigned char *get_mac_block( | |
60 | blkid_probe pr, | |
0459a7b3 | 61 | uint16_t block_size, |
5c9204dc KZ |
62 | uint32_t num) |
63 | { | |
f12cd8d1 | 64 | return blkid_probe_get_buffer(pr, (uint64_t) num * block_size, block_size); |
5c9204dc KZ |
65 | } |
66 | ||
67 | static inline int has_part_signature(struct mac_partition *p) | |
68 | { | |
69 | return be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC || | |
70 | be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC_OLD; | |
71 | } | |
72 | ||
01fb8c00 KZ |
73 | static int probe_mac_pt(blkid_probe pr, |
74 | const struct blkid_idmag *mag __attribute__((__unused__))) | |
5c9204dc KZ |
75 | { |
76 | struct mac_driver_desc *md; | |
77 | struct mac_partition *p; | |
78 | blkid_parttable tab = NULL; | |
79 | blkid_partlist ls; | |
0459a7b3 | 80 | uint16_t block_size; |
5c9204dc | 81 | uint16_t ssf; /* sector size fragment */ |
01fb8c00 | 82 | uint32_t nblks, i; |
5c9204dc KZ |
83 | |
84 | ||
85 | /* The driver descriptor record is always located at physical block 0, | |
86 | * the first block on the disk. | |
87 | */ | |
88 | md = (struct mac_driver_desc *) blkid_probe_get_sector(pr, 0); | |
37f40602 HR |
89 | if (!md) { |
90 | if (errno) | |
91 | return -errno; | |
5c9204dc | 92 | goto nothing; |
37f40602 | 93 | } |
5c9204dc | 94 | |
0459a7b3 | 95 | block_size = be16_to_cpu(md->block_size); |
5c9204dc KZ |
96 | |
97 | /* The partition map always begins at physical block 1, | |
98 | * the second block on the disk. | |
99 | */ | |
0459a7b3 | 100 | p = (struct mac_partition *) get_mac_block(pr, block_size, 1); |
37f40602 HR |
101 | if (!p) { |
102 | if (errno) | |
103 | return -errno; | |
5c9204dc | 104 | goto nothing; |
37f40602 | 105 | } |
5c9204dc KZ |
106 | |
107 | /* check the first partition signature */ | |
108 | if (!has_part_signature(p)) | |
109 | goto nothing; | |
110 | ||
111 | if (blkid_partitions_need_typeonly(pr)) | |
112 | /* caller does not ask for details about partitions */ | |
113 | return 0; | |
114 | ||
115 | ls = blkid_probe_get_partlist(pr); | |
116 | if (!ls) | |
37f40602 | 117 | goto nothing; |
5c9204dc KZ |
118 | |
119 | tab = blkid_partlist_new_parttable(ls, "mac", 0); | |
120 | if (!tab) | |
121 | goto err; | |
122 | ||
0459a7b3 | 123 | ssf = block_size / 512; |
5c9204dc KZ |
124 | nblks = be32_to_cpu(p->map_count); |
125 | ||
126 | for (i = 1; i <= nblks; ++i) { | |
127 | blkid_partition par; | |
128 | uint32_t start; | |
129 | uint32_t size; | |
130 | ||
0459a7b3 | 131 | p = (struct mac_partition *) get_mac_block(pr, block_size, i); |
37f40602 HR |
132 | if (!p) { |
133 | if (errno) | |
134 | return -errno; | |
5c9204dc | 135 | goto nothing; |
37f40602 | 136 | } |
5c9204dc KZ |
137 | if (!has_part_signature(p)) |
138 | goto nothing; | |
139 | ||
140 | if (be32_to_cpu(p->map_count) != nblks) { | |
c62a6311 | 141 | DBG(LOWPROBE, ul_debug( |
9e930041 | 142 | "mac: inconsistent map_count in partition map, " |
37f40602 | 143 | "entry[0]: %d, entry[%d]: %d", |
5c9204dc KZ |
144 | nblks, i - 1, |
145 | be32_to_cpu(p->map_count))); | |
146 | } | |
147 | ||
148 | /* | |
149 | * note that libparted ignores some mac partitions according to | |
150 | * the partition name (e.g. "Apple_Free" or "Apple_Void"). We | |
151 | * follows Linux kernel and all partitions are visible | |
152 | */ | |
153 | ||
154 | start = be32_to_cpu(p->start_block) * ssf; | |
155 | size = be32_to_cpu(p->block_count) * ssf; | |
156 | ||
c2dacc61 | 157 | par = blkid_partlist_add_partition(ls, tab, start, size); |
5c9204dc KZ |
158 | if (!par) |
159 | goto err; | |
160 | ||
161 | blkid_partition_set_name(par, (unsigned char *) p->name, | |
162 | sizeof(p->name)); | |
0e8a8065 KZ |
163 | |
164 | blkid_partition_set_type_string(par, (unsigned char *) p->type, | |
165 | sizeof(p->type)); | |
5c9204dc KZ |
166 | } |
167 | ||
37f40602 | 168 | return BLKID_PROBE_OK; |
5c9204dc KZ |
169 | |
170 | nothing: | |
37f40602 | 171 | return BLKID_PROBE_NONE; |
5c9204dc | 172 | err: |
37f40602 | 173 | return -ENOMEM; |
5c9204dc KZ |
174 | } |
175 | ||
176 | /* | |
177 | * Mac disk always begin with "Driver Descriptor Record" | |
178 | * (struct mac_driver_desc) and magic 0x4552. | |
179 | */ | |
180 | const struct blkid_idinfo mac_pt_idinfo = | |
181 | { | |
182 | .name = "mac", | |
183 | .probefunc = probe_mac_pt, | |
184 | .magics = | |
185 | { | |
186 | /* big-endian magic string */ | |
187 | { .magic = "\x45\x52", .len = 2 }, | |
188 | { NULL } | |
189 | } | |
190 | }; | |
191 |