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 |
} |