]>
Commit | Line | Data |
---|---|---|
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 | #include <IOKit/assert.h> | |
24 | #include <IOKit/IOBufferMemoryDescriptor.h> | |
25 | #include <IOKit/IODeviceTreeSupport.h> | |
26 | #include <IOKit/IOLib.h> | |
27 | #include <IOKit/storage/IOApplePartitionScheme.h> | |
28 | #include <libkern/OSByteOrder.h> | |
29 | ||
30 | #define super IOPartitionScheme | |
31 | OSDefineMetaClassAndStructors(IOApplePartitionScheme, IOPartitionScheme); | |
32 | ||
33 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
34 | // Notes | |
35 | // | |
36 | // o the on-disk structure's fields are: 16-bit packed, big-endian formatted | |
37 | // o the dpme_pblock_start and dpme_pblocks block values are: | |
38 | // o for media without a driver map: | |
39 | // o natural block size based | |
40 | // o for media with a driver map: | |
41 | // o driver map block size based, unless the driver map block size is 2048 | |
42 | // and a valid partition entry exists at a 512 byte offset into the disk, | |
43 | // in which case, assume a 512 byte block size, except for the partition | |
44 | // entries that lie on a 2048 byte multiple and are one of the following | |
45 | // types: Apple_Patches, Apple_Driver, Apple_Driver43, Apple_Driver43_CD, | |
46 | // Apple_Driver_ATA, Apple_Driver_ATAPI; in which case, we assume a 2048 | |
47 | // byte block size (for the one partition) | |
48 | // o the dpme_pblock_start block value is relative to the media container | |
49 | // | |
50 | ||
51 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
52 | ||
53 | #define kIOApplePartitionSchemeContentTable "Content Table" | |
54 | ||
55 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
56 | ||
57 | bool IOApplePartitionScheme::init(OSDictionary * properties = 0) | |
58 | { | |
59 | // | |
60 | // Initialize this object's minimal state. | |
61 | // | |
62 | ||
63 | // State our assumptions. | |
64 | ||
65 | assert(sizeof(dpme) == 512); // (compiler/platform check) | |
66 | assert(sizeof(DDMap) == 8); // (compiler/platform check) | |
67 | assert(sizeof(Block0) == 512); // (compiler/platform check) | |
68 | ||
69 | // Ask our superclass' opinion. | |
70 | ||
71 | if (super::init(properties) == false) return false; | |
72 | ||
73 | // Initialize our state. | |
74 | ||
75 | _partitions = 0; | |
76 | ||
77 | return true; | |
78 | } | |
79 | ||
80 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
81 | ||
82 | void IOApplePartitionScheme::free() | |
83 | { | |
84 | // | |
85 | // Free all of this object's outstanding resources. | |
86 | // | |
87 | ||
88 | if ( _partitions ) _partitions->release(); | |
89 | ||
90 | super::free(); | |
91 | } | |
92 | ||
93 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
94 | ||
95 | IOService * IOApplePartitionScheme::probe(IOService * provider, SInt32 * score) | |
96 | { | |
97 | // | |
98 | // Determine whether the provider media contains an Apple partition map. | |
99 | // | |
100 | ||
101 | // State our assumptions. | |
102 | ||
103 | assert(OSDynamicCast(IOMedia, provider)); | |
104 | ||
105 | // Ask superclass' opinion. | |
106 | ||
107 | if (super::probe(provider, score) == 0) return 0; | |
108 | ||
109 | // Scan the provider media for an Apple partition map. | |
110 | ||
111 | _partitions = scan(score); | |
112 | ||
113 | return ( _partitions ) ? this : 0; | |
114 | } | |
115 | ||
116 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
117 | ||
118 | bool IOApplePartitionScheme::start(IOService * provider) | |
119 | { | |
120 | // | |
121 | // Publish the new media objects which represent our partitions. | |
122 | // | |
123 | ||
124 | IOMedia * partition; | |
125 | OSIterator * partitionIterator; | |
126 | ||
127 | // State our assumptions. | |
128 | ||
129 | assert(_partitions); | |
130 | ||
131 | // Ask our superclass' opinion. | |
132 | ||
133 | if ( super::start(provider) == false ) return false; | |
134 | ||
135 | // Attach and register the new media objects representing our partitions. | |
136 | ||
137 | partitionIterator = OSCollectionIterator::withCollection(_partitions); | |
138 | if ( partitionIterator == 0 ) return false; | |
139 | ||
140 | while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) | |
141 | { | |
142 | if ( partition->attach(this) ) | |
143 | { | |
144 | attachMediaObjectToDeviceTree(partition); | |
145 | ||
146 | partition->registerService(); | |
147 | } | |
148 | } | |
149 | ||
150 | partitionIterator->release(); | |
151 | ||
152 | return true; | |
153 | } | |
154 | ||
155 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
156 | ||
157 | void IOApplePartitionScheme::stop(IOService * provider) | |
158 | { | |
159 | // | |
160 | // Clean up after the media objects we published before terminating. | |
161 | // | |
162 | ||
163 | IOMedia * partition; | |
164 | OSIterator * partitionIterator; | |
165 | ||
166 | // State our assumptions. | |
167 | ||
168 | assert(_partitions); | |
169 | ||
170 | // Detach the media objects we previously attached to the device tree. | |
171 | ||
172 | partitionIterator = OSCollectionIterator::withCollection(_partitions); | |
173 | ||
174 | if ( partitionIterator ) | |
175 | { | |
176 | while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) | |
177 | { | |
178 | detachMediaObjectFromDeviceTree(partition); | |
179 | } | |
180 | ||
181 | partitionIterator->release(); | |
182 | } | |
183 | ||
184 | super::stop(provider); | |
185 | } | |
186 | ||
187 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
188 | ||
189 | OSSet * IOApplePartitionScheme::scan(SInt32 * score) | |
190 | { | |
191 | // | |
192 | // Scan the provider media for an Apple partition map. Returns the set | |
193 | // of media objects representing each of the partitions (the retain for | |
194 | // the set is passed to the caller), or null should no partition map be | |
195 | // found. The default probe score can be adjusted up or down, based on | |
196 | // the confidence of the scan. | |
197 | // | |
198 | ||
199 | IOBufferMemoryDescriptor * buffer = 0; | |
200 | UInt32 bufferReadAt = 0; | |
201 | UInt32 bufferSize = 0; | |
202 | UInt32 dpmeBlockSize = 0; | |
203 | UInt32 dpmeCount = 0; | |
204 | UInt32 dpmeID = 0; | |
205 | dpme * dpmeMap = 0; | |
206 | UInt32 dpmeMaxCount = 0; | |
207 | bool dpmeOldSchool = false; | |
208 | Block0 * driverMap = 0; | |
209 | IOMedia * media = getProvider(); | |
210 | UInt64 mediaBlockSize = media->getPreferredBlockSize(); | |
211 | bool mediaIsOpen = false; | |
212 | OSSet * partitions = 0; | |
213 | IOReturn status = kIOReturnError; | |
214 | ||
215 | // Determine whether this media is formatted. | |
216 | ||
217 | if ( media->isFormatted() == false ) goto scanErr; | |
218 | ||
219 | // Determine whether this media has an appropriate block size. | |
220 | ||
221 | if ( (mediaBlockSize % sizeof(dpme)) ) goto scanErr; | |
222 | ||
223 | // Allocate a buffer large enough to hold one map, rounded to a media block. | |
224 | ||
225 | bufferSize = IORound(max(sizeof(Block0), sizeof(dpme)), mediaBlockSize); | |
226 | buffer = IOBufferMemoryDescriptor::withCapacity( | |
227 | /* capacity */ bufferSize, | |
228 | /* withDirection */ kIODirectionIn ); | |
229 | if ( buffer == 0 ) goto scanErr; | |
230 | ||
231 | // Allocate a set to hold the set of media objects representing partitions. | |
232 | ||
233 | partitions = OSSet::withCapacity(8); | |
234 | if ( partitions == 0 ) goto scanErr; | |
235 | ||
236 | // Open the media with read access. | |
237 | ||
238 | mediaIsOpen = media->open(this, 0, kIOStorageAccessReader); | |
239 | if ( mediaIsOpen == false ) goto scanErr; | |
240 | ||
241 | // Read the driver map into our buffer. | |
242 | ||
243 | bufferReadAt = 0; | |
244 | ||
245 | ///m:2333367:workaround:commented:start | |
246 | // status = media->read(this, bufferReadAt, buffer); | |
247 | ///m:2333367:workaround:commented:stop | |
248 | ///m:2333367:workaround:added:start | |
249 | status = media->IOStorage::read(this, bufferReadAt, buffer); | |
250 | ///m:2333367:workaround:added:stop | |
251 | if ( status != kIOReturnSuccess ) goto scanErr; | |
252 | ||
253 | driverMap = (Block0 *) buffer->getBytesNoCopy(); | |
254 | ||
255 | // Determine the official block size to use to scan the partition entries. | |
256 | ||
257 | dpmeBlockSize = mediaBlockSize; // (natural block size) | |
258 | ||
259 | if ( driverMap->sbSig == BLOCK0_SIGNATURE ) | |
260 | { | |
261 | dpmeBlockSize = driverMap->sbBlkSize; // (driver map block size) | |
262 | ||
263 | // Determine whether we have an old school partition map, where there is | |
264 | // a partition entry at a 512 byte offset into the disk, even though the | |
265 | // driver map block size is 2048. | |
266 | ||
267 | if ( dpmeBlockSize == 2048 ) | |
268 | { | |
269 | if ( bufferSize >= sizeof(Block0) + sizeof(dpme) ) // (in buffer?) | |
270 | { | |
271 | dpmeMap = (dpme *) (driverMap + 1); | |
272 | } | |
273 | else // (not in buffer) | |
274 | { | |
275 | // Read the partition entry at byte offset 512 into our buffer. | |
276 | ||
277 | bufferReadAt = sizeof(dpme); | |
278 | ||
279 | ///m:2333367:workaround:commented:start | |
280 | // status = media->read(this, bufferReadAt, buffer); | |
281 | ///m:2333367:workaround:commented:stop | |
282 | ///m:2333367:workaround:added:start | |
283 | status = media->IOStorage::read(this, bufferReadAt, buffer); | |
284 | ///m:2333367:workaround:added:stop | |
285 | if ( status != kIOReturnSuccess ) goto scanErr; | |
286 | ||
287 | dpmeMap = (dpme *) buffer->getBytesNoCopy(); | |
288 | } | |
289 | ||
290 | // Determine whether the partition entry signature is present. | |
291 | ||
292 | if (OSSwapBigToHostInt16(dpmeMap->dpme_signature) == DPME_SIGNATURE) | |
293 | { | |
294 | dpmeBlockSize = sizeof(dpme); // (old school block size) | |
295 | dpmeOldSchool = true; | |
296 | } | |
297 | } | |
298 | ||
299 | // Increase the probe score when a driver map is detected, since we are | |
300 | // more confident in the match when it is present. This will eliminate | |
301 | // conflicts with FDisk when it shares the same block as the driver map. | |
302 | ||
303 | *score += 2000; | |
304 | } | |
305 | ||
306 | // Scan the media for Apple partition entries. | |
307 | ||
308 | for ( dpmeID = 1, dpmeCount = 1; dpmeID <= dpmeCount; dpmeID++ ) | |
309 | { | |
310 | UInt32 partitionBlockSize = dpmeBlockSize; | |
311 | ||
312 | // Determine whether we've exhausted the current buffer of entries. | |
313 | ||
314 | if ( dpmeID * dpmeBlockSize + sizeof(dpme) > bufferReadAt + bufferSize ) | |
315 | { | |
316 | // Read the next partition entry into our buffer. | |
317 | ||
318 | bufferReadAt = dpmeID * dpmeBlockSize; | |
319 | ||
320 | ///m:2333367:workaround:commented:start | |
321 | // status = media->read(this, bufferReadAt, buffer); | |
322 | ///m:2333367:workaround:commented:stop | |
323 | ///m:2333367:workaround:added:start | |
324 | status = media->IOStorage::read(this, bufferReadAt, buffer); | |
325 | ///m:2333367:workaround:added:stop | |
326 | if ( status != kIOReturnSuccess ) goto scanErr; | |
327 | } | |
328 | ||
329 | dpmeMap = (dpme *) ( ((UInt8 *) buffer->getBytesNoCopy()) + | |
330 | (dpmeID * dpmeBlockSize) - bufferReadAt ); | |
331 | ||
332 | // Determine whether the partition entry signature is present. | |
333 | ||
334 | if ( OSSwapBigToHostInt16(dpmeMap->dpme_signature) != DPME_SIGNATURE ) | |
335 | { | |
336 | goto scanErr; | |
337 | } | |
338 | ||
339 | // Obtain an accurate number of entries in the partition map. | |
340 | ||
341 | if ( !strcmp(dpmeMap->dpme_type, "Apple_partition_map") || | |
342 | !strcmp(dpmeMap->dpme_type, "Apple_Partition_Map") || | |
343 | !strcmp(dpmeMap->dpme_type, "Apple_patition_map" ) ) | |
344 | { | |
345 | dpmeCount = OSSwapBigToHostInt32(dpmeMap->dpme_map_entries); | |
346 | dpmeMaxCount = OSSwapBigToHostInt32(dpmeMap->dpme_pblocks); | |
347 | } | |
348 | else if ( dpmeCount == 1 ) | |
349 | { | |
350 | dpmeCount = OSSwapBigToHostInt32(dpmeMap->dpme_map_entries); | |
351 | } | |
352 | ||
353 | // Obtain an accurate block size for an old school partition map. | |
354 | ||
355 | if ( dpmeOldSchool && (dpmeID % 4) == 0 ) | |
356 | { | |
357 | if ( !strcmp(dpmeMap->dpme_type, "Apple_Driver" ) || | |
358 | !strcmp(dpmeMap->dpme_type, "Apple_Driver43" ) || | |
359 | !strcmp(dpmeMap->dpme_type, "Apple_Driver43_CD" ) || | |
360 | !strcmp(dpmeMap->dpme_type, "Apple_Driver_ATA" ) || | |
361 | !strcmp(dpmeMap->dpme_type, "Apple_Driver_ATAPI") || | |
362 | !strcmp(dpmeMap->dpme_type, "Apple_Patches" ) ) | |
363 | { | |
364 | partitionBlockSize = 2048; | |
365 | } | |
366 | } | |
367 | ||
368 | // Determine whether the partition is corrupt (fatal). | |
369 | ||
370 | if ( isPartitionCorrupt( | |
371 | /* partition */ dpmeMap, | |
372 | /* partitionID */ dpmeID, | |
373 | /* partitionBlockSize */ partitionBlockSize ) ) | |
374 | { | |
375 | goto scanErr; | |
376 | } | |
377 | ||
378 | // Determine whether the partition is invalid (skipped). | |
379 | ||
380 | if ( isPartitionInvalid( | |
381 | /* partition */ dpmeMap, | |
382 | /* partitionID */ dpmeID, | |
383 | /* partitionBlockSize */ partitionBlockSize ) ) | |
384 | { | |
385 | continue; | |
386 | } | |
387 | ||
388 | // Create a media object to represent this partition. | |
389 | ||
390 | IOMedia * newMedia = instantiateMediaObject( | |
391 | /* partition */ dpmeMap, | |
392 | /* partitionID */ dpmeID, | |
393 | /* partitionBlockSize */ partitionBlockSize ); | |
394 | ||
395 | if ( newMedia ) | |
396 | { | |
397 | partitions->setObject(newMedia); | |
398 | newMedia->release(); | |
399 | } | |
400 | } | |
401 | ||
402 | // Determine whether we ever came accross an Apple_partition_map partition. | |
403 | ||
404 | if ( dpmeMaxCount == 0 ) goto scanErr; | |
405 | ||
406 | // Release our resources. | |
407 | ||
408 | media->close(this); | |
409 | buffer->release(); | |
410 | ||
411 | return partitions; | |
412 | ||
413 | scanErr: | |
414 | ||
415 | // Release our resources. | |
416 | ||
417 | if ( mediaIsOpen ) media->close(this); | |
418 | if ( partitions ) partitions->release(); | |
419 | if ( buffer ) buffer->release(); | |
420 | ||
421 | return 0; | |
422 | } | |
423 | ||
424 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
425 | ||
426 | bool IOApplePartitionScheme::isPartitionCorrupt( | |
427 | dpme * /* partition */ , | |
428 | UInt32 /* partitionID */ , | |
429 | UInt32 /* partitionBlockSize */ ) | |
430 | { | |
431 | // | |
432 | // Ask whether the given partition appears to be corrupt. A partition that | |
433 | // is corrupt will cause the failure of the Apple partition map recognition | |
434 | // altogether. | |
435 | // | |
436 | ||
437 | return false; | |
438 | } | |
439 | ||
440 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
441 | ||
442 | bool IOApplePartitionScheme::isPartitionInvalid( dpme * partition, | |
443 | UInt32 partitionID, | |
444 | UInt32 partitionBlockSize ) | |
445 | { | |
446 | // | |
447 | // Ask whether the given partition appears to be invalid. A partition that | |
448 | // is invalid will cause it to be skipped in the scan, but will not cause a | |
449 | // failure of the Apple partition map recognition. | |
450 | // | |
451 | ||
452 | IOMedia * media = getProvider(); | |
453 | UInt64 partitionBase = 0; | |
454 | UInt64 partitionSize = 0; | |
455 | ||
456 | // Compute the relative byte position and size of the new partition. | |
457 | ||
458 | partitionBase = OSSwapBigToHostInt32(partition->dpme_pblock_start); | |
459 | partitionSize = OSSwapBigToHostInt32(partition->dpme_pblocks); | |
460 | partitionBase *= partitionBlockSize; | |
461 | partitionSize *= partitionBlockSize; | |
462 | ||
463 | // Determine whether the partition is a placeholder. | |
464 | ||
465 | if ( partitionSize == 0 ) return true; | |
466 | ||
467 | // Determine whether the partition starts at (or past) the end-of-media. | |
468 | ||
469 | if ( partitionBase >= media->getSize() ) return true; | |
470 | ||
471 | return false; | |
472 | } | |
473 | ||
474 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
475 | ||
476 | IOMedia * IOApplePartitionScheme::instantiateMediaObject( | |
477 | dpme * partition, | |
478 | UInt32 partitionID, | |
479 | UInt32 partitionBlockSize ) | |
480 | { | |
481 | // | |
482 | // Instantiate a new media object to represent the given partition. | |
483 | // | |
484 | ||
485 | IOMedia * media = getProvider(); | |
486 | UInt64 mediaBlockSize = media->getPreferredBlockSize(); | |
487 | UInt64 partitionBase = 0; | |
488 | char * partitionHint = partition->dpme_type; | |
489 | bool partitionIsWritable = media->isWritable(); | |
490 | char * partitionName = partition->dpme_name; | |
491 | UInt64 partitionSize = 0; | |
492 | ||
493 | // Compute the relative byte position and size of the new partition. | |
494 | ||
495 | partitionBase = OSSwapBigToHostInt32(partition->dpme_pblock_start); | |
496 | partitionSize = OSSwapBigToHostInt32(partition->dpme_pblocks); | |
497 | partitionBase *= partitionBlockSize; | |
498 | partitionSize *= partitionBlockSize; | |
499 | ||
500 | // Clip the size of the new partition if it extends past the end-of-media. | |
501 | ||
502 | if ( partitionBase + partitionSize > media->getSize() ) | |
503 | { | |
504 | partitionSize = media->getSize() - partitionBase; | |
505 | } | |
506 | ||
507 | // Look up a type for the new partition. | |
508 | ||
509 | OSDictionary * hintTable = OSDynamicCast( | |
510 | /* type */ OSDictionary, | |
511 | /* instance */ getProperty(kIOApplePartitionSchemeContentTable) ); | |
512 | ||
513 | if ( hintTable ) | |
514 | { | |
515 | OSString * hintValue = OSDynamicCast( | |
516 | /* type */ OSString, | |
517 | /* instance */ hintTable->getObject(partitionHint) ); | |
518 | ||
519 | if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy(); | |
520 | } | |
521 | ||
522 | // Look up a name for the new partition. | |
523 | ||
524 | while ( *partitionName == ' ' ) { partitionName++; } | |
525 | ||
526 | if ( *partitionName == 0 ) partitionName = 0; | |
527 | ||
528 | // Determine whether the new partition type is Apple_Free, which we choose | |
529 | // not to publish because it is an internal concept to the partition map. | |
530 | ||
531 | if ( !strcmp(partitionHint, "Apple_Free") ) return 0; | |
532 | ||
533 | // Determine whether the new partition is read-only. | |
534 | // | |
535 | // Note that we treat the misspelt Apple_patition_map entries as equivalent | |
536 | // to Apple_partition_map entries due to the messed up CDs noted in 2513960. | |
537 | ||
538 | if ( !strcmp(partition->dpme_type, "Apple_partition_map") || | |
539 | !strcmp(partition->dpme_type, "Apple_Partition_Map") || | |
540 | !strcmp(partition->dpme_type, "Apple_patition_map" ) || | |
541 | ( ((partition->dpme_flags & DPME_FLAGS_WRITABLE) == 0) && | |
542 | ((partition->dpme_flags & DPME_FLAGS_VALID ) != 0) ) ) | |
543 | { | |
544 | partitionIsWritable = false; | |
545 | } | |
546 | ||
547 | // Create the new media object. | |
548 | ||
549 | IOMedia * newMedia = instantiateDesiredMediaObject( | |
550 | /* partition */ partition, | |
551 | /* partitionID */ partitionID, | |
552 | /* partitionBlockSize */ partitionBlockSize ); | |
553 | ||
554 | if ( newMedia ) | |
555 | { | |
556 | if ( newMedia->init( | |
557 | /* base */ partitionBase, | |
558 | /* size */ partitionSize, | |
559 | /* preferredBlockSize */ mediaBlockSize, | |
560 | /* isEjectable */ media->isEjectable(), | |
561 | /* isWhole */ false, | |
562 | /* isWritable */ partitionIsWritable, | |
563 | /* contentHint */ partitionHint ) ) | |
564 | { | |
565 | // Set a name for this partition. | |
566 | ||
567 | char name[24]; | |
568 | sprintf(name, "Untitled %ld", partitionID); | |
569 | newMedia->setName(partitionName ? partitionName : name); | |
570 | ||
571 | // Set a location value (the partition number) for this partition. | |
572 | ||
573 | char location[12]; | |
574 | sprintf(location, "%ld", partitionID); | |
575 | newMedia->setLocation(location); | |
576 | ||
577 | // Set the "Partition ID" key for this partition. | |
578 | ||
579 | newMedia->setProperty(kIOMediaPartitionIDKey, partitionID, 32); | |
580 | } | |
581 | else | |
582 | { | |
583 | newMedia->release(); | |
584 | newMedia = 0; | |
585 | } | |
586 | } | |
587 | ||
588 | return newMedia; | |
589 | } | |
590 | ||
591 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
592 | ||
593 | IOMedia * IOApplePartitionScheme::instantiateDesiredMediaObject( | |
594 | dpme * partition, | |
595 | UInt32 partitionID, | |
596 | UInt32 partitionBlockSize ) | |
597 | { | |
598 | // | |
599 | // Allocate a new media object (called from instantiateMediaObject). | |
600 | // | |
601 | ||
602 | return new IOMedia; | |
603 | } | |
604 | ||
605 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
606 | ||
607 | bool IOApplePartitionScheme::attachMediaObjectToDeviceTree( IOMedia * media ) | |
608 | { | |
609 | // | |
610 | // Attach the given media object to the device tree plane. | |
611 | // | |
612 | ||
613 | IOService * service; | |
614 | SInt32 unit = -1; | |
615 | ||
616 | for ( service = this; service; service = service->getProvider() ) | |
617 | { | |
618 | OSNumber * number; | |
619 | ||
620 | if ( (number = OSDynamicCast(OSNumber, service->getProperty("IOUnit")))) | |
621 | { | |
622 | unit = number->unsigned32BitValue(); | |
623 | } | |
624 | ||
625 | if ( service->inPlane(gIODTPlane) ) | |
626 | { | |
627 | IORegistryEntry * child; | |
628 | IORegistryIterator * children; | |
629 | ||
630 | if ( unit == -1 ) break; | |
631 | ||
632 | children = IORegistryIterator::iterateOver(service, gIODTPlane); | |
633 | ||
634 | if ( children == 0 ) break; | |
635 | ||
636 | while ( (child = children->getNextObject()) ) | |
637 | { | |
638 | const char * location = child->getLocation(gIODTPlane); | |
639 | const char * name = child->getName(gIODTPlane); | |
640 | ||
641 | if ( name == 0 || strcmp(name, "" ) != 0 || | |
642 | location == 0 || strchr(location, ':') == 0 ) | |
643 | { | |
644 | child->detachAll(gIODTPlane); | |
645 | } | |
646 | } | |
647 | ||
648 | children->release(); | |
649 | ||
650 | if ( media->attachToParent(service, gIODTPlane) ) | |
651 | { | |
652 | char location[ sizeof("hhhhhhhh:dddddddddd") ]; | |
653 | ||
654 | sprintf(location, "%lx:", unit); | |
655 | strcat(location, media->getLocation()); | |
656 | media->setLocation(location, gIODTPlane); | |
657 | media->setName("", gIODTPlane); | |
658 | ||
659 | return true; | |
660 | } | |
661 | ||
662 | break; | |
663 | } | |
664 | } | |
665 | ||
666 | return false; | |
667 | } | |
668 | ||
669 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
670 | ||
671 | void IOApplePartitionScheme::detachMediaObjectFromDeviceTree( IOMedia * media ) | |
672 | { | |
673 | // | |
674 | // Detach the given media object from the device tree plane. | |
675 | // | |
676 | ||
677 | IORegistryEntry * parent; | |
678 | ||
679 | if ( (parent = media->getParentEntry(gIODTPlane)) ) | |
680 | { | |
681 | media->detachFromParent(parent, gIODTPlane); | |
682 | } | |
683 | } | |
684 | ||
685 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
686 | ||
687 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 0); | |
688 | ||
689 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
690 | ||
691 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 1); | |
692 | ||
693 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
694 | ||
695 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 2); | |
696 | ||
697 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
698 | ||
699 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 3); | |
700 | ||
701 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
702 | ||
703 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 4); | |
704 | ||
705 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
706 | ||
707 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 5); | |
708 | ||
709 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
710 | ||
711 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 6); | |
712 | ||
713 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
714 | ||
715 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 7); | |
716 | ||
717 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
718 | ||
719 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 8); | |
720 | ||
721 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
722 | ||
723 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 9); | |
724 | ||
725 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
726 | ||
727 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 10); | |
728 | ||
729 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
730 | ||
731 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 11); | |
732 | ||
733 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
734 | ||
735 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 12); | |
736 | ||
737 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
738 | ||
739 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 13); | |
740 | ||
741 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
742 | ||
743 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 14); | |
744 | ||
745 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
746 | ||
747 | OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 15); |