/[pearpc]/src/io/prom/fs/part.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/io/prom/fs/part.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 15204 byte(s)
import upstream CVS
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     }

  ViewVC Help
Powered by ViewVC 1.1.26