|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22:
23: //
24: // Notes:
25: // -----
26: // o the on-disk fdisk structure is packed for i386 and has little endian fields
27: //
28: // o the relsect block value is relative to the containing media's boundary,
29: // and the implicit block size is the drive's hard block size
30: //
31: // o the numsect block value's implicit block size is the drive's hard block
32: // size
33: //
34: // Policies:
35: // --------
36: // o the default probe score of the fdisk partition scheme is 1100, only if
37: // it contains one or more valid partitions
38: //
39:
40: #include <IOKit/assert.h>
41: #include <IOKit/IOLib.h>
42: #include <IOKit/storage/IOFDiskPartitionScheme.h>
43: #include <libkern/OSByteOrder.h>
44:
45: #define super IOPartitionScheme
46: OSDefineMetaClassAndStructors(IOFDiskPartitionScheme, IOPartitionScheme);
47:
48: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49: // FDisk Partition Types
50:
51: static struct { UInt8 type; char * name; } partitionTypes[] =
52: {
53: { 0x01, "DOS_FAT_12" },
54: { 0x04, "DOS_FAT_16_S" },
55: { 0x05, "DOS_Extended" },
56: { 0x06, "DOS_FAT_16" },
57: { 0x07, "Windows_NTFS" },
58: { 0x0a, "Boot_Manager" },
59: { 0x0b, "DOS_FAT_32" },
60: { 0x0c, "Windows_FAT_32" },
61: { 0x0e, "Windows_FAT_16" },
62: { 0x0f, "Windows_Extended" },
63: { 0x11, "DOS_FAT_12_Hidden" },
64: { 0x14, "DOS_FAT_16_S_Hidden" },
65: { 0x16, "DOS_FAT_16_Hidden" },
66: { 0x17, "Windows_NTFS_Hidden" },
67: { 0x1b, "DOS_FAT_32_Hidden" },
68: { 0x1c, "Windows_FAT_32_Hidden" },
69: { 0x1e, "Windows_FAT_16_Hidden" },
70: { 0x63, "UNIX" },
71: { 0x82, "Linux_Swap" },
72: { 0x83, "Linux_Ext2FS" },
73: { 0x84, "Hibernation" },
74: { 0x85, "Linux_Extended" },
75: { 0x86, "Windows_FAT_16_FT" },
76: { 0x87, "Windows_NTFS_FT" },
77: { 0xa5, "FreeBSD" },
78: { 0xa6, "OpenBSD" },
79: { 0xa7, "Apple_Rhapsody_UFS" },
80: { 0xa8, "Apple_UFS" },
81: { 0xa9, "NetBSD" },
82: { 0xab, "Apple_Boot" },
83: { 0xb7, "BSDI" },
84: { 0xb8, "BSDI_Swap" },
85: { 0xc6, "Windows_FAT_16_FT_Corrupt" },
86: { 0xc7, "Windows_NTFS_FT_Corrupt" },
87: { 0xeb, "BeOS" },
88: { 0xf2, "DOS_Secondary" },
89: { 0xfd, "Linux_RAID" },
90: { 0x00, 0 }
91: };
92:
93: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94:
95: bool IOFDiskPartitionScheme::init(OSDictionary * properties = 0)
96: {
97: //
98: // Initialize this object's minimal state.
99: //
100:
101: if (super::init(properties) == false) return false;
102:
103: _buffer = 0;
104: _bufferSize = 0;
105:
106: // Validate the compiled size of our important fixed-size structures.
107:
108: assert(sizeof(fdisk_part) == 16);
109: assert(sizeof(disk_blk0) == 512);
110:
111: return true;
112: }
113:
114: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
115:
116: void IOFDiskPartitionScheme::free()
117: {
118: //
119: // Free all of this object's outstanding resources.
120: //
121:
122: if (_buffer) _buffer->release();
123:
124: super::free();
125: }
126:
127: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128:
129: IOService * IOFDiskPartitionScheme::probe(IOService * provider, SInt32 * score)
130: {
131: //
132: // Determine whether the provider media contains an fdisk partition map. If
133: // it does, we return "this" to indicate success, otherwise we return zero.
134: //
135:
136: IOMedia * media = (IOMedia *) provider;
137:
138: // State our assumptions.
139:
140: assert(OSDynamicCast(IOMedia, provider));
141:
142: // Ask superclass' opinion about this probe.
143:
144: if (super::probe(provider, score) == 0) return 0;
145:
146: // Determine whether this media object is unformatted.
147:
148: if (media->isFormatted() == false) return 0;
149:
150: // Determine whether this media's block size is below our assumed minimum.
151:
152: if (media->getPreferredBlockSize() < sizeof(disk_blk0)) return 0;
153:
154: // Allocate a buffer large enough to hold one media block.
155:
156: _bufferSize = media->getPreferredBlockSize();
157: _buffer = IOBufferMemoryDescriptor::withCapacity(_bufferSize,
158: kIODirectionIn);
159:
160: if (_buffer == 0) return 0;
161:
162: // Search for a valid fdisk partition on the provider media.
163:
164: return identify(media) ? this : 0;
165: }
166:
167: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168:
169: bool IOFDiskPartitionScheme::start(IOService * provider)
170: {
171: //
172: // This method is called once we have been attached to the media object. We
173: // generate the new media objects that will represent our partitions here.
174: //
175:
176: disk_blk0 * blockZero;
177: IOMedia * media = (IOMedia *) provider;
178: bool success = false;
179:
180: // State our assumptions.
181:
182: assert(_buffer);
183:
184: // Ask our superclass' opinion.
185:
186: if ( !super::start(provider) ) return false;
187:
188: // Scan through all the partition entries.
189:
190: blockZero = (disk_blk0 *) _buffer->getBytesNoCopy();
191:
192: for ( unsigned index = 0; index < DISK_NPART; index++ )
193: {
194: // Skip all null partition entries (have system id of 0).
195:
196: if ( blockZero->parts[index].systid == 0 )
197: continue; // (skip)
198:
199: // Compute the relative position and size of the new partition.
200:
201: UInt64 base = OSSwapLittleToHostInt32(blockZero->parts[index].relsect) *
202: media->getPreferredBlockSize();
203: UInt64 size = OSSwapLittleToHostInt32(blockZero->parts[index].numsect) *
204: media->getPreferredBlockSize();
205:
206: if ( base == 0 || size == 0 )
207: continue; // (skip)
208:
209: // Look up a name and a type for this partition.
210:
211: const char * aName = "Untitled";
212: const char * aHint = 0;
213:
214: for (unsigned n = 0; partitionTypes[n].type; n++)
215: {
216: if ( blockZero->parts[index].systid == partitionTypes[n].type )
217: {
218: aHint = partitionTypes[n].name;
219: break;
220: }
221: }
222:
223: // Ensure the partition definition does not leave the confines of
224: // the containing media (they were absolute values after all).
225:
226: if ( base + size > media->getSize() )
227: {
228: IOLog("%s on %s: \"%s\" (partition %d) exceeds confines of "
229: "containing media.\n",
230: getName(), media->getName(), aName, index+1);
231: continue; // (skip)
232: }
233:
234: // Create the new media object.
235:
236: IOMedia * newMedia = new IOMedia;
237:
238: if ( !newMedia ||
239: !newMedia->init( // base (bytes; relative to provider media)
240: base,
241: // size (bytes)
242: size,
243: // natural block size (bytes)
244: media->getPreferredBlockSize(),
245: // is ejectable
246: media->isEjectable(),
247: // is whole
248: false,
249: // is writable
250: media->isWritable(),
251: // content hint
252: aHint ) ||
253: !newMedia->attach(this) )
254: {
255: IOLog("%s on %s: Unable to create media object for \"%s\" "
256: "(partition %d).\n",
257: getName(), media->getName(), aName, index + 1);
258:
259: if ( newMedia ) newMedia->release();
260: continue; // (skip)
261: }
262:
263: newMedia->setName(aName);
264:
265: // Set a location value (the partition number) for this partition.
266:
267: char location[12];
268: sprintf(location, "%d", index + 1);
269: newMedia->setLocation(location);
270:
271: // Create the "Partition ID" key.
272:
273: newMedia->setProperty(kIOMediaPartitionID, index + 1, 32);
274:
275: // Register the media object with the matching system.
276:
277: newMedia->registerService();
278:
279: // Release our retain on the new media object (in registry).
280:
281: newMedia->release();
282:
283: success = true;
284: } // (for all partition entries)
285:
286: // Release our buffer now that we no longer need it.
287:
288: _buffer->release();
289:
290: _buffer = 0;
291: _bufferSize = 0;
292:
293: // Return success if we found at least one partition.
294:
295: return success;
296: }
297:
298: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
299:
300: bool IOFDiskPartitionScheme::identify(IOMedia * media)
301: {
302: //
303: // Searches for the existence of an fdisk partition map on the given media.
304: //
305:
306: bool success = false;
307:
308: // State our assumptions.
309:
310: assert(_buffer);
311:
312: // Open the media object for access.
313:
314: if ( media->open(this, 0, kAccessReader) == false ) return false;
315:
316: // Read the first block into our buffer.
317:
318: _buffer->setDirection(kIODirectionIn); // (a read)
319: _buffer->setLength(_bufferSize); // (transfer one full block)
320:
321: if ( media->read(this, 0, _buffer) == kIOReturnSuccess )
322: {
323: // Determine whether the partition map signature 0xAA55 is present.
324:
325: disk_blk0 * blockZero = (disk_blk0 *) _buffer->getBytesNoCopy();
326:
327: if ( OSSwapLittleToHostInt16(blockZero->signature) == DISK_SIGNATURE )
328: {
329: // Note that media created by Mac OS X Server and OpenStep on i386
330: // machines have a valid, but EMPTY, fdisk structure co-existing
331: // with a valid NeXT label (at the second location). We resolve
332: // the conflict by returning success only for the fdisk structures
333: // that do contain partitions.
334:
335: for ( unsigned index = 0; index < DISK_NPART; index++ )
336: {
337: if ( blockZero->parts[index].systid )
338: {
339: // We found a used partition entry; set success.
340: success = true;
341: break;
342: }
343: }
344: }
345: }
346:
347: // Close the media object we opened earlier.
348:
349: media->close(this);
350:
351: return success;
352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.