/src/util-linux/libblkid/src/partitions/mac.c
Line | Count | Source (jump to first uncovered line) |
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 | 172 | #define MAC_PARTITION_MAGIC 0x504d |
18 | 84 | #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 */ |
45 | | } __attribute__((packed)); |
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 */ |
57 | | } __attribute__((packed)); |
58 | | |
59 | | static inline const unsigned char *get_mac_block( |
60 | | blkid_probe pr, |
61 | | uint16_t block_size, |
62 | | uint32_t num) |
63 | 209 | { |
64 | 209 | return blkid_probe_get_buffer(pr, (uint64_t) num * block_size, block_size); |
65 | 209 | } |
66 | | |
67 | | static inline int has_part_signature(struct mac_partition *p) |
68 | 86 | { |
69 | 86 | return be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC || |
70 | 86 | be16_to_cpu(p->signature) == MAC_PARTITION_MAGIC_OLD; |
71 | 86 | } |
72 | | |
73 | | static int probe_mac_pt(blkid_probe pr, |
74 | | const struct blkid_idmag *mag __attribute__((__unused__))) |
75 | 236 | { |
76 | 236 | struct mac_driver_desc *md; |
77 | 236 | struct mac_partition *p; |
78 | 236 | blkid_parttable tab = NULL; |
79 | 236 | blkid_partlist ls; |
80 | 236 | uint16_t block_size; |
81 | 236 | uint16_t ssf; /* sector size fragment */ |
82 | 236 | uint32_t nblks, nprts, i; |
83 | | |
84 | | |
85 | | /* The driver descriptor record is always located at physical block 0, |
86 | | * the first block on the disk. |
87 | | */ |
88 | 236 | md = (struct mac_driver_desc *) blkid_probe_get_sector(pr, 0); |
89 | 236 | if (!md) { |
90 | 6 | if (errno) |
91 | 0 | return -errno; |
92 | 6 | goto nothing; |
93 | 6 | } |
94 | | |
95 | 230 | block_size = be16_to_cpu(md->block_size); |
96 | 230 | if (block_size < sizeof(struct mac_partition)) |
97 | 21 | goto nothing; |
98 | | |
99 | | /* The partition map always begins at physical block 1, |
100 | | * the second block on the disk. |
101 | | */ |
102 | 209 | p = (struct mac_partition *) get_mac_block(pr, block_size, 1); |
103 | 209 | if (!p) { |
104 | 123 | if (errno) |
105 | 0 | return -errno; |
106 | 123 | goto nothing; |
107 | 123 | } |
108 | | |
109 | | /* check the first partition signature */ |
110 | 86 | if (!has_part_signature(p)) |
111 | 83 | goto nothing; |
112 | | |
113 | 3 | if (blkid_partitions_need_typeonly(pr)) |
114 | | /* caller does not ask for details about partitions */ |
115 | 3 | return 0; |
116 | | |
117 | 0 | ls = blkid_probe_get_partlist(pr); |
118 | 0 | if (!ls) |
119 | 0 | goto nothing; |
120 | | |
121 | 0 | tab = blkid_partlist_new_parttable(ls, "mac", 0); |
122 | 0 | if (!tab) |
123 | 0 | goto err; |
124 | | |
125 | 0 | ssf = block_size / 512; |
126 | 0 | nblks = be32_to_cpu(p->map_count); |
127 | 0 | if (nblks > 256) { |
128 | 0 | nprts = 256; |
129 | 0 | DBG(LOWPROBE, ul_debug( |
130 | 0 | "mac: map_count too large, entry[0]: %u, " |
131 | 0 | "enforcing limit of %u", nblks, nprts)); |
132 | 0 | } else |
133 | 0 | nprts = nblks; |
134 | |
|
135 | 0 | for (i = 0; i < nprts; ++i) { |
136 | 0 | blkid_partition par; |
137 | 0 | uint32_t start; |
138 | 0 | uint32_t size; |
139 | |
|
140 | 0 | p = (struct mac_partition *) get_mac_block(pr, block_size, i + 1); |
141 | 0 | if (!p) { |
142 | 0 | if (errno) |
143 | 0 | return -errno; |
144 | 0 | goto nothing; |
145 | 0 | } |
146 | 0 | if (!has_part_signature(p)) |
147 | 0 | goto nothing; |
148 | | |
149 | 0 | if (be32_to_cpu(p->map_count) != nblks) { |
150 | 0 | DBG(LOWPROBE, ul_debug( |
151 | 0 | "mac: inconsistent map_count in partition map, " |
152 | 0 | "entry[0]: %u, entry[%u]: %u", |
153 | 0 | nblks, i, |
154 | 0 | be32_to_cpu(p->map_count))); |
155 | 0 | } |
156 | | |
157 | | /* |
158 | | * note that libparted ignores some mac partitions according to |
159 | | * the partition name (e.g. "Apple_Free" or "Apple_Void"). We |
160 | | * follows Linux kernel and all partitions are visible |
161 | | */ |
162 | |
|
163 | 0 | start = be32_to_cpu(p->start_block) * ssf; |
164 | 0 | size = be32_to_cpu(p->block_count) * ssf; |
165 | |
|
166 | 0 | par = blkid_partlist_add_partition(ls, tab, start, size); |
167 | 0 | if (!par) |
168 | 0 | goto err; |
169 | | |
170 | 0 | blkid_partition_set_name(par, (unsigned char *) p->name, |
171 | 0 | sizeof(p->name)); |
172 | |
|
173 | 0 | blkid_partition_set_type_string(par, (unsigned char *) p->type, |
174 | 0 | sizeof(p->type)); |
175 | 0 | } |
176 | | |
177 | 0 | return BLKID_PROBE_OK; |
178 | | |
179 | 233 | nothing: |
180 | 233 | return BLKID_PROBE_NONE; |
181 | 0 | err: |
182 | 0 | return -ENOMEM; |
183 | 0 | } |
184 | | |
185 | | /* |
186 | | * Mac disk always begin with "Driver Descriptor Record" |
187 | | * (struct mac_driver_desc) and magic 0x4552. |
188 | | */ |
189 | | const struct blkid_idinfo mac_pt_idinfo = |
190 | | { |
191 | | .name = "mac", |
192 | | .probefunc = probe_mac_pt, |
193 | | .magics = |
194 | | { |
195 | | /* big-endian magic string */ |
196 | | { .magic = "\x45\x52", .len = 2 }, |
197 | | { NULL } |
198 | | } |
199 | | }; |
200 | | |