1 |
dpavlin |
1 |
/* |
2 |
|
|
* PearPC |
3 |
|
|
* part.cc |
4 |
|
|
* |
5 |
|
|
* Copyright (C) 2003 Sebastian Biallas (sb@biallas.net) |
6 |
|
|
* |
7 |
|
|
* Some ideas and code from yaboot/fs.c |
8 |
|
|
* Copyright Ethan Beson and Benjamin Herrenschmidt |
9 |
|
|
* |
10 |
|
|
* This program is free software; you can redistribute it and/or modify |
11 |
|
|
* it under the terms of the GNU General Public License version 2 as |
12 |
|
|
* published by the Free Software Foundation. |
13 |
|
|
* |
14 |
|
|
* This program is distributed in the hope that it will be useful, |
15 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 |
|
|
* GNU General Public License for more details. |
18 |
|
|
* |
19 |
|
|
* You should have received a copy of the GNU General Public License |
20 |
|
|
* along with this program; if not, write to the Free Software |
21 |
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 |
|
|
*/ |
23 |
|
|
// for HFS+ info: |
24 |
|
|
// http://developer.apple.com/technotes/tn/tn1150.html |
25 |
|
|
// |
26 |
|
|
// for HFS-MDB info: |
27 |
|
|
// http://developer.apple.com/documentation/Carbon/Reference/File_Manager/file_manager/data_type_62.html |
28 |
|
|
|
29 |
|
|
#include <cstring> |
30 |
|
|
|
31 |
|
|
#include "debug/tracers.h" |
32 |
|
|
#include "tools/endianess.h" |
33 |
|
|
#include "tools/snprintf.h" |
34 |
|
|
#include "tools/except.h" |
35 |
|
|
#include "part.h" |
36 |
|
|
#include "hfs.h" |
37 |
|
|
#include "hfsplus.h" |
38 |
|
|
|
39 |
|
|
#define APPLE_PARTITION_STATUS_BOOTABLE 8 |
40 |
|
|
|
41 |
|
|
#define APPLE_DRIVER_MAGIC MAGIC16("ER") |
42 |
|
|
#define APPLE_PARTITION_MAGIC MAGIC16("PM") |
43 |
|
|
|
44 |
|
|
struct ApplePartition { |
45 |
|
|
uint16 signature; |
46 |
|
|
uint16 res; |
47 |
|
|
uint32 map_count; |
48 |
|
|
uint32 start_block; |
49 |
|
|
uint32 block_count; |
50 |
|
|
char name[32]; |
51 |
|
|
char type[32]; |
52 |
|
|
uint32 data_start; |
53 |
|
|
uint32 data_count; |
54 |
|
|
uint32 status; |
55 |
|
|
uint32 boot_start; |
56 |
|
|
uint32 boot_size; |
57 |
|
|
uint32 boot_load; |
58 |
|
|
uint32 boot_load2; |
59 |
|
|
uint32 boot_entry; |
60 |
|
|
uint32 boot_entry2; |
61 |
|
|
uint32 boot_cksum; |
62 |
|
|
char processor[16]; |
63 |
|
|
}; |
64 |
|
|
|
65 |
|
|
byte ApplePartition_struct[]= { |
66 |
|
|
STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, |
67 |
|
|
STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST, |
68 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
69 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
70 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
71 |
|
|
|
72 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
73 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
74 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
75 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
76 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
77 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
78 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
79 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
80 |
|
|
|
81 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
82 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
83 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
84 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
85 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
86 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
87 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
88 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
89 |
|
|
|
90 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
91 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
92 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
93 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
94 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
95 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
96 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
97 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
98 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
99 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
100 |
|
|
|
101 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
102 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
103 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
104 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
105 |
|
|
0, |
106 |
|
|
}; |
107 |
|
|
|
108 |
|
|
/* |
109 |
|
|
* |
110 |
|
|
*/ |
111 |
|
|
#define ACTIVE_FLAG 0x80 |
112 |
|
|
|
113 |
|
|
#define EXTENDED 0x05 |
114 |
|
|
#define LINUX_PARTITION 0x81 |
115 |
|
|
#define LINUX_SWAP 0x82 |
116 |
|
|
#define LINUX_NATIVE 0x83 |
117 |
|
|
#define LINUX_EXTENDED 0x85 |
118 |
|
|
|
119 |
|
|
struct FDiskPartition { |
120 |
|
|
uint8 boot_ind; |
121 |
|
|
uint8 head; |
122 |
|
|
uint8 sector; |
123 |
|
|
uint8 cyl; |
124 |
|
|
uint8 sys_ind; |
125 |
|
|
uint8 end_head; |
126 |
|
|
uint8 end_sector; |
127 |
|
|
uint8 end_cyl; |
128 |
|
|
uint32 start; |
129 |
|
|
uint32 size; |
130 |
|
|
}; |
131 |
|
|
|
132 |
|
|
byte FDiskPartition_struct[] = { |
133 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
134 |
|
|
STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, STRUCT_ENDIAN_8, |
135 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
136 |
|
|
STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST, |
137 |
|
|
0, |
138 |
|
|
}; |
139 |
|
|
|
140 |
|
|
/* |
141 |
|
|
* |
142 |
|
|
*/ |
143 |
|
|
PartitionEntry::PartitionEntry(int partnum, const char *aName, const char *aType, uint64 aOffset, |
144 |
|
|
uint64 aLength) |
145 |
|
|
{ |
146 |
|
|
mPartNum = partnum; |
147 |
|
|
mName = strdup(aName); |
148 |
|
|
mType = strdup(aType); |
149 |
|
|
mOffset = aOffset; |
150 |
|
|
mLength = aLength; |
151 |
|
|
mBootMethod = BM_none; |
152 |
|
|
mInstantiateBootFile = NULL; |
153 |
|
|
mInstantiateBootFilePrivData = NULL; |
154 |
|
|
mInstantiateFileSystem = NULL; |
155 |
|
|
mBootImageLoadAddr = 0; |
156 |
|
|
mBootImageEntrypoint = 0; |
157 |
|
|
} |
158 |
|
|
|
159 |
|
|
PartitionEntry::~PartitionEntry() |
160 |
|
|
{ |
161 |
|
|
if (mInstantiateBootFilePrivData) free(mInstantiateBootFilePrivData); |
162 |
|
|
free(mName); |
163 |
|
|
free(mType); |
164 |
|
|
} |
165 |
|
|
|
166 |
|
|
/* |
167 |
|
|
* |
168 |
|
|
*/ |
169 |
|
|
PartitionMap::PartitionMap(File *aDevice, uint aDeviceBlocksize) |
170 |
|
|
{ |
171 |
|
|
mEntries = new Array(true); |
172 |
|
|
mDevice = aDevice; |
173 |
|
|
mDeviceBlocksize = aDeviceBlocksize; |
174 |
|
|
addPartition(-1, "raw disk", "raw", 0, 0); |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
PartitionMap::~PartitionMap() |
178 |
|
|
{ |
179 |
|
|
delete mEntries; |
180 |
|
|
} |
181 |
|
|
|
182 |
|
|
Enumerator *PartitionMap::getPartitions() |
183 |
|
|
{ |
184 |
|
|
return mEntries; |
185 |
|
|
} |
186 |
|
|
|
187 |
|
|
void PartitionMap::getType(String &result) |
188 |
|
|
{ |
189 |
|
|
result = "raw"; |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
PartitionEntry *PartitionMap::addPartition(int partnum, const char *name, const char *type, uint64 offset, uint64 length) |
193 |
|
|
{ |
194 |
|
|
PartitionEntry *e = new PartitionEntry(partnum, name, type, offset, length); |
195 |
|
|
mEntries->insert(e); |
196 |
|
|
return e; |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
/***/ |
200 |
|
|
struct FDiskInstantiateBootFilePrivData { |
201 |
|
|
FileOfs mStart; |
202 |
|
|
FileOfs mLen; |
203 |
|
|
}; |
204 |
|
|
|
205 |
|
|
static File *FDiskInstantiateBootFile(File *aDevice, void *priv) |
206 |
|
|
{ |
207 |
|
|
FDiskInstantiateBootFilePrivData *p = (FDiskInstantiateBootFilePrivData*)priv; |
208 |
|
|
return new CroppedFile(aDevice, true, p->mStart, p->mLen); |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
/* |
212 |
|
|
* |
213 |
|
|
*/ |
214 |
|
|
PartitionMapFDisk::PartitionMapFDisk(File *aDevice, uint aDeviceBlocksize) |
215 |
|
|
:PartitionMap(aDevice, aDeviceBlocksize) |
216 |
|
|
{ |
217 |
|
|
byte buffer[IDE_MAX_BLOCK_SIZE]; |
218 |
|
|
FDiskPartition *fdisk_part = (FDiskPartition *)&buffer[0x1be]; |
219 |
|
|
|
220 |
|
|
uint blocksize = aDeviceBlocksize; |
221 |
|
|
if (blocksize <= 1) blocksize = 512; |
222 |
|
|
aDevice->seek(0); |
223 |
|
|
if (aDevice->read(buffer, blocksize) != blocksize) throw Exception(); |
224 |
|
|
|
225 |
|
|
IO_PROM_FS_TRACE("# boot head sect cyl. type head sect cyl. start size\n"); |
226 |
|
|
// IO_PROM_FS_TRACE("1 12 12 12 12 12 12 12 12 1234 1234\n"); |
227 |
|
|
|
228 |
|
|
for (int partition = 1; partition <= 4; partition++, fdisk_part++) { |
229 |
|
|
createHostStructx(fdisk_part, sizeof *fdisk_part, FDiskPartition_struct, little_endian); |
230 |
|
|
|
231 |
|
|
IO_PROM_FS_TRACE("%d %02x %02x %02x %02x %02x %02x %02x %02x %04lx %04lx\n", |
232 |
|
|
partition, |
233 |
|
|
fdisk_part->boot_ind, |
234 |
|
|
fdisk_part->head, fdisk_part->sector, fdisk_part->cyl, |
235 |
|
|
fdisk_part->sys_ind, |
236 |
|
|
fdisk_part->end_head, fdisk_part->end_sector, fdisk_part->end_cyl, |
237 |
|
|
fdisk_part->start, fdisk_part->size); |
238 |
|
|
|
239 |
|
|
// FIXME: add extended partition support here |
240 |
|
|
|
241 |
|
|
char *type; |
242 |
|
|
switch (fdisk_part->sys_ind) { |
243 |
|
|
|
244 |
|
|
case 0x00: |
245 |
|
|
type = NULL; |
246 |
|
|
break; |
247 |
|
|
case LINUX_PARTITION: |
248 |
|
|
case LINUX_NATIVE: |
249 |
|
|
type = "Linux"; |
250 |
|
|
break; |
251 |
|
|
case LINUX_SWAP: |
252 |
|
|
type = "swap"; |
253 |
|
|
break; |
254 |
|
|
default: |
255 |
|
|
IO_PROM_FS_TRACE("Found unknown partition type: %02x\n",fdisk_part->sys_ind); |
256 |
|
|
type = "unknown"; |
257 |
|
|
break; |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
char name[20]; |
261 |
|
|
ht_snprintf(name, sizeof name, "partition %d", partition); |
262 |
|
|
|
263 |
|
|
if (type != NULL) { |
264 |
|
|
PartitionEntry *partEnt = addPartition(partition, name, type, |
265 |
|
|
fdisk_part->start * blocksize, |
266 |
|
|
fdisk_part->size * blocksize); |
267 |
|
|
|
268 |
|
|
if (fdisk_part->boot_ind & ACTIVE_FLAG) |
269 |
|
|
{ |
270 |
|
|
partEnt->mBootMethod = BM_chrp; |
271 |
|
|
|
272 |
|
|
FDiskInstantiateBootFilePrivData *priv = |
273 |
|
|
(FDiskInstantiateBootFilePrivData*) |
274 |
|
|
malloc(sizeof (FDiskInstantiateBootFilePrivData)); |
275 |
|
|
priv->mStart = fdisk_part->start * blocksize; |
276 |
|
|
priv->mLen = fdisk_part->size * blocksize; |
277 |
|
|
|
278 |
|
|
partEnt->mInstantiateBootFile = FDiskInstantiateBootFile; |
279 |
|
|
partEnt->mInstantiateBootFilePrivData = priv; |
280 |
|
|
partEnt->mInstantiateFileSystem = NULL; |
281 |
|
|
} |
282 |
|
|
} |
283 |
|
|
} |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
void PartitionMapFDisk::getType(String &result) |
287 |
|
|
{ |
288 |
|
|
result = "fdisk"; |
289 |
|
|
} |
290 |
|
|
|
291 |
|
|
PartitionMapFDiskSingle::PartitionMapFDiskSingle(File *aDevice, uint aDeviceBlocksize, const char *type) |
292 |
|
|
:PartitionMap(aDevice, aDeviceBlocksize) |
293 |
|
|
{ |
294 |
|
|
uint64 offset = 0; |
295 |
|
|
uint64 length = aDevice->getSize(); |
296 |
|
|
|
297 |
|
|
PartitionEntry *partEnt = addPartition(1, "unknown", type, offset, length); |
298 |
|
|
|
299 |
|
|
FDiskInstantiateBootFilePrivData *priv = |
300 |
|
|
(FDiskInstantiateBootFilePrivData*) |
301 |
|
|
malloc(sizeof (FDiskInstantiateBootFilePrivData)); |
302 |
|
|
priv->mStart = offset; |
303 |
|
|
priv->mLen = length; |
304 |
|
|
|
305 |
|
|
partEnt->mBootMethod = BM_chrp; |
306 |
|
|
partEnt->mInstantiateBootFile = FDiskInstantiateBootFile; |
307 |
|
|
partEnt->mInstantiateBootFilePrivData = priv; |
308 |
|
|
partEnt->mInstantiateFileSystem = NULL; |
309 |
|
|
|
310 |
|
|
} |
311 |
|
|
|
312 |
|
|
void PartitionMapFDiskSingle::getType(String &result) |
313 |
|
|
{ |
314 |
|
|
result = "fdisk"; |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
/***/ |
318 |
|
|
struct RawInstantiateBootFilePrivData { |
319 |
|
|
FileOfs mStart; |
320 |
|
|
FileOfs mLen; |
321 |
|
|
}; |
322 |
|
|
|
323 |
|
|
static File *RawInstantiateBootFile(File *aDevice, void *priv) |
324 |
|
|
{ |
325 |
|
|
RawInstantiateBootFilePrivData *p = (RawInstantiateBootFilePrivData*)priv; |
326 |
|
|
return new CroppedFile(aDevice, true, p->mStart, p->mLen); |
327 |
|
|
} |
328 |
|
|
|
329 |
|
|
/***/ |
330 |
|
|
PartitionMapApple::PartitionMapApple(File *aDevice, uint aDeviceBlocksize) |
331 |
|
|
:PartitionMap(aDevice, aDeviceBlocksize) |
332 |
|
|
{ |
333 |
|
|
byte buffer[IDE_MAX_BLOCK_SIZE]; |
334 |
|
|
ApplePartition *apple_part = (ApplePartition *)&buffer; |
335 |
|
|
uint blocksize = mDeviceBlocksize; |
336 |
|
|
/*if (blocksize <= 1)*/ blocksize = 512; |
337 |
|
|
aDevice->seek(0); |
338 |
|
|
if (aDevice->read(buffer, blocksize) != blocksize) throw Exception(); |
339 |
|
|
|
340 |
|
|
createHostStructx(apple_part, sizeof *apple_part, ApplePartition_struct, big_endian); |
341 |
|
|
|
342 |
|
|
if (apple_part->signature != APPLE_DRIVER_MAGIC) throw Exception(); |
343 |
|
|
|
344 |
|
|
IO_PROM_FS_TRACE("New Apple partition map, (physical) blocksize %d/0x%08x\n", blocksize, blocksize); |
345 |
|
|
int map_size = 1; |
346 |
|
|
IO_PROM_FS_TRACE("name type status start +data datasize +boot bootsize bootload bootentry\n"); |
347 |
|
|
// IO_PROM_FS_TRACE("0123456789123456 0123456789123456 12345678 12345678 12345678 12345678 12345678 12345678 12345678 12345678\n"); |
348 |
|
|
for (int block = 1; block < map_size + 1; block++) { |
349 |
|
|
aDevice->seek(block*blocksize); |
350 |
|
|
if (aDevice->read(buffer, blocksize) != blocksize) continue; |
351 |
|
|
|
352 |
|
|
createHostStructx(apple_part, sizeof *apple_part, ApplePartition_struct, big_endian); |
353 |
|
|
|
354 |
|
|
if (apple_part->signature != APPLE_PARTITION_MAGIC) throw Exception(); |
355 |
|
|
|
356 |
|
|
if (block == 1) map_size = apple_part->map_count; |
357 |
|
|
|
358 |
|
|
PartitionEntry *partEnt = addPartition(block, apple_part->name, apple_part->type, |
359 |
|
|
(apple_part->start_block+apple_part->data_start) * blocksize, |
360 |
|
|
apple_part->data_count * blocksize); |
361 |
|
|
|
362 |
|
|
IO_PROM_FS_TRACE("%-16s %-16s %08x %08x %08x %08x %08x %08x %08x %08x\n", |
363 |
|
|
apple_part->name, |
364 |
|
|
apple_part->type, |
365 |
|
|
apple_part->status, |
366 |
|
|
apple_part->start_block*blocksize, |
367 |
|
|
apple_part->data_start*blocksize, |
368 |
|
|
apple_part->data_count*blocksize, |
369 |
|
|
apple_part->boot_start*blocksize, |
370 |
|
|
apple_part->boot_size, |
371 |
|
|
apple_part->boot_load, |
372 |
|
|
apple_part->boot_entry); |
373 |
|
|
|
374 |
|
|
// Try HFS |
375 |
|
|
if (tryBootHFS(aDevice, blocksize, apple_part->start_block*blocksize, partEnt)) |
376 |
|
|
continue; |
377 |
|
|
// Try HFS+ |
378 |
|
|
if (tryBootHFSPlus(aDevice, blocksize, apple_part->start_block*blocksize, partEnt)) |
379 |
|
|
continue; |
380 |
|
|
// Try boot via partition info. |
381 |
|
|
if (apple_part->boot_size && apple_part->boot_load && apple_part->boot_entry) { |
382 |
|
|
partEnt->mBootMethod = BM_direct; |
383 |
|
|
|
384 |
|
|
RawInstantiateBootFilePrivData *priv = |
385 |
|
|
(RawInstantiateBootFilePrivData*) |
386 |
|
|
malloc(sizeof (RawInstantiateBootFilePrivData)); |
387 |
|
|
priv->mStart = apple_part->start_block*blocksize |
388 |
|
|
+ apple_part->boot_start*blocksize; |
389 |
|
|
priv->mLen = apple_part->boot_size; |
390 |
|
|
|
391 |
|
|
partEnt->mInstantiateBootFile = RawInstantiateBootFile; |
392 |
|
|
partEnt->mInstantiateBootFilePrivData = priv; |
393 |
|
|
partEnt->mInstantiateFileSystem = NULL; |
394 |
|
|
|
395 |
|
|
partEnt->mBootImageLoadAddr = apple_part->boot_load; |
396 |
|
|
partEnt->mBootImageEntrypoint = apple_part->boot_entry; |
397 |
|
|
continue; |
398 |
|
|
} |
399 |
|
|
} |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
void PartitionMapApple::getType(String &result) |
403 |
|
|
{ |
404 |
|
|
result = "apple"; |
405 |
|
|
} |
406 |
|
|
|
407 |
|
|
PartitionMapAppleSingle::PartitionMapAppleSingle(File *aDevice, uint aDeviceBlocksize, const char *type) |
408 |
|
|
:PartitionMap(aDevice, aDeviceBlocksize) |
409 |
|
|
{ |
410 |
|
|
uint64 offset = 0; |
411 |
|
|
uint64 length = aDevice->getSize(); |
412 |
|
|
|
413 |
|
|
PartitionEntry *partEnt = addPartition(1, "unknown", type, offset, length); |
414 |
|
|
|
415 |
|
|
if (tryBootHFS(aDevice, aDeviceBlocksize, offset, partEnt)) |
416 |
|
|
; |
417 |
|
|
else if (tryBootHFSPlus(aDevice, aDeviceBlocksize, offset, partEnt)) |
418 |
|
|
; |
419 |
|
|
} |
420 |
|
|
|
421 |
|
|
void PartitionMapAppleSingle::getType(String &result) |
422 |
|
|
{ |
423 |
|
|
result = "apple"; |
424 |
|
|
} |
425 |
|
|
|
426 |
|
|
/* |
427 |
|
|
* |
428 |
|
|
*/ |
429 |
|
|
PartitionMap *partitions_get_map(File *aDevice, uint aDeviceBlocksize) |
430 |
|
|
{ |
431 |
|
|
byte buffer[IDE_MAX_BLOCK_SIZE]; |
432 |
|
|
byte signature[2]; |
433 |
|
|
uint blocksize = aDeviceBlocksize; |
434 |
|
|
if (blocksize <= 1) blocksize = 512; |
435 |
|
|
aDevice->seek(0); |
436 |
|
|
if (aDevice->read(buffer, blocksize) != blocksize) { |
437 |
|
|
IO_PROM_FS_TRACE("device read failed while probing partitions\n"); |
438 |
|
|
return new PartitionMap(aDevice, aDeviceBlocksize); |
439 |
|
|
} |
440 |
|
|
// look for partition maps |
441 |
|
|
if (blocksize >= 2 && buffer[0] == 0x45 && buffer[1] == 0x52) { |
442 |
|
|
IO_PROM_FS_TRACE("this looks like a Apple partition map to me...\n"); |
443 |
|
|
|
444 |
|
|
try { |
445 |
|
|
return new PartitionMapApple(aDevice, aDeviceBlocksize); |
446 |
|
|
} catch (const Exception &e) { |
447 |
|
|
String s; |
448 |
|
|
e.reason(s); |
449 |
|
|
IO_PROM_FS_TRACE("exception probing Apple partitions: %y\n", &s); |
450 |
|
|
} |
451 |
|
|
} |
452 |
|
|
if (blocksize >= 512 && buffer[510] == 0x55 && buffer[511] == 0xaa) { |
453 |
|
|
IO_PROM_FS_TRACE("this looks like a FDisk partition map to me...\n"); |
454 |
|
|
|
455 |
|
|
try { |
456 |
|
|
return new PartitionMapFDisk(aDevice, aDeviceBlocksize); |
457 |
|
|
} catch (const Exception &e) { |
458 |
|
|
String s; |
459 |
|
|
e.reason(s); |
460 |
|
|
IO_PROM_FS_TRACE("exception probing fdisk partitions: %y\n", &s); |
461 |
|
|
} |
462 |
|
|
} |
463 |
|
|
// look for raw partitions |
464 |
|
|
aDevice->seek(0x400); |
465 |
|
|
if (aDevice->read(signature, 2) == 2) { |
466 |
|
|
if (signature[0] == 0x42 && signature[1] == 0x44) { |
467 |
|
|
IO_PROM_FS_TRACE("this looks like a single HFS partition to me...\n"); |
468 |
|
|
|
469 |
|
|
try { |
470 |
|
|
return new PartitionMapAppleSingle(aDevice, aDeviceBlocksize, "Apple_HFS"); |
471 |
|
|
} catch (const Exception &e) { |
472 |
|
|
String s; |
473 |
|
|
e.reason(s); |
474 |
|
|
IO_PROM_FS_TRACE("exception probing HFS partition: %y\n", &s); |
475 |
|
|
} |
476 |
|
|
} |
477 |
|
|
if (signature[0] == 0x48 && (signature[1] == 0x2b || signature[2] == 0x58)) { |
478 |
|
|
IO_PROM_FS_TRACE("this looks like a single HFS+ partition to me...\n"); |
479 |
|
|
|
480 |
|
|
try { |
481 |
|
|
return new PartitionMapAppleSingle(aDevice, aDeviceBlocksize, "Apple_HFS"); |
482 |
|
|
} catch (const Exception &e) { |
483 |
|
|
String s; |
484 |
|
|
e.reason(s); |
485 |
|
|
IO_PROM_FS_TRACE("exception probing HFS+ partition: %y\n", &s); |
486 |
|
|
} |
487 |
|
|
} |
488 |
|
|
} |
489 |
|
|
aDevice->seek(0x438); |
490 |
|
|
if (aDevice->read(signature, 2) == 2) { |
491 |
|
|
if (signature[0] == 0x53 && signature[1] == 0xef) { |
492 |
|
|
IO_PROM_FS_TRACE("this looks like a single ext2 partition to me...\n"); |
493 |
|
|
|
494 |
|
|
try { |
495 |
|
|
return new PartitionMapFDiskSingle(aDevice, aDeviceBlocksize, "ext2"); |
496 |
|
|
} catch (const Exception &e) { |
497 |
|
|
String s; |
498 |
|
|
e.reason(s); |
499 |
|
|
IO_PROM_FS_TRACE("exception probing ext2 partition: %y\n", &s); |
500 |
|
|
} |
501 |
|
|
} |
502 |
|
|
} |
503 |
|
|
|
504 |
|
|
IO_PROM_FS_TRACE("probe found no partitions in %d bytes block\n",blocksize); |
505 |
|
|
return new PartitionMap(aDevice, aDeviceBlocksize); |
506 |
|
|
} |