]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOCDStorage / IOCDPartitionScheme.cpp
CommitLineData
1c79356b
A
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/IOLib.h>
26#include <IOKit/storage/IOCDPartitionScheme.h>
27
28#define super IOPartitionScheme
29OSDefineMetaClassAndStructors(IOCDPartitionScheme, IOPartitionScheme);
30
31// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32
33#define kIOCDPartitionSchemeContentTable "Content Table"
34
35// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
36
37IOCDMedia * IOCDPartitionScheme::getProvider() const
38{
39 //
40 // Obtain this object's provider. We override the superclass's method
41 // to return a more specific subclass of OSObject -- IOCDMedia. This
42 // method serves simply as a convenience to subclass developers.
43 //
44
45 return (IOCDMedia *) IOService::getProvider();
46}
47
48// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49
50bool IOCDPartitionScheme::init(OSDictionary * properties = 0)
51{
52 //
53 // Initialize this object's minimal state.
54 //
55
56 // State our assumptions.
57
58 assert(sizeof(CDTOC) == 4); // (compiler/platform check)
59 assert(sizeof(CDTOCDescriptor) == 11); // (compiler/platform check)
60
61 // Ask our superclass' opinion.
62
63 if (super::init(properties) == false) return false;
64
65 // Initialize our state.
66
67 _partitions = 0;
68
69 return true;
70}
71
72// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
73
74void IOCDPartitionScheme::free()
75{
76 //
77 // Free all of this object's outstanding resources.
78 //
79
80 if ( _partitions ) _partitions->release();
81
82 super::free();
83}
84
85// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86
87IOService * IOCDPartitionScheme::probe(IOService * provider, SInt32 * score)
88{
89 //
90 // Determine whether the provider media contains CD partitions.
91 //
92
93 // State our assumptions.
94
95 assert(OSDynamicCast(IOCDMedia, provider));
96
97 // Ask superclass' opinion.
98
99 if (super::probe(provider, score) == 0) return 0;
100
101 // Scan the provider media for CD partitions.
102
103 _partitions = scan(score);
104
105 return ( _partitions ) ? this : 0;
106}
107
108// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
109
110bool IOCDPartitionScheme::start(IOService * provider)
111{
112 //
113 // Publish the new media objects which represent our partitions.
114 //
115
116 IOMedia * partition;
117 OSIterator * partitionIterator;
118
119 // State our assumptions.
120
121 assert(_partitions);
122
123 // Ask our superclass' opinion.
124
125 if ( super::start(provider) == false ) return false;
126
127 // Attach and register the new media objects representing our partitions.
128
129 partitionIterator = OSCollectionIterator::withCollection(_partitions);
130 if ( partitionIterator == 0 ) return false;
131
132 while ( (partition = (IOMedia *) partitionIterator->getNextObject()) )
133 {
134 if ( partition->attach(this) )
135 {
136 partition->registerService();
137 }
138 }
139
140 partitionIterator->release();
141
142 return true;
143}
144
145// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146
147OSSet * IOCDPartitionScheme::scan(SInt32 * score)
148{
149 //
150 // Scan the provider media for CD partitions (in TOC). Returns the set
151 // of media objects representing each of the partitions (the retain for
152 // the set is passed to the caller), or null should no CD partitions be
153 // found. The default probe score can be adjusted up or down, based on
154 // the confidence of the scan.
155 //
156
157 struct CDSession
158 {
159 UInt32 isFormX:1;
160 UInt32 leadOut;
161 };
162
163 struct CDTrack
164 {
165 UInt32 block;
166 CDSectorSize blockSize;
167 CDSectorType blockType;
168 CDTOCDescriptor * descriptor;
169 UInt32 session:8;
170 };
171
172 #define kCDSessionMaxIndex 0x63
173
174 #define kCDTrackMinIndex 0x01
175 #define kCDTrackMaxIndex 0x63
176
177 IOBufferMemoryDescriptor * buffer = 0;
178 IOCDMedia * media = getProvider();
179 UInt64 mediaBlockSize = media->getPreferredBlockSize();
180 bool mediaIsOpen = false;
181 OSSet * partitions = 0;
182 CDSession * sessions = 0;
183 UInt32 sessionMinIndex = kCDSessionMaxIndex + 1;
184 UInt32 sessionMaxIndex = 0;
185 CDTOC * toc = 0;
186 UInt32 tocCount = 0;
187 CDTrack * tracks = 0;
188 UInt32 trackMinIndex = kCDTrackMaxIndex + 1;
189 UInt32 trackMaxIndex = 0;
190 CDTrack * trackMaxLinked = 0;
191
192 // State our assumptions.
193
194 assert(mediaBlockSize == kCDSectorSizeWhole);
195
196 // Determine whether this media is formatted.
197
198 if ( media->isFormatted() == false ) goto scanErr;
199
200 // Allocate a buffer large enough to hold a whole 2352-byte sector.
201
202 buffer = IOBufferMemoryDescriptor::withCapacity(
203 /* capacity */ mediaBlockSize,
204 /* withDirection */ kIODirectionIn );
205 if ( buffer == 0 ) goto scanErr;
206
207 // Allocate a set to hold the set of media objects representing partitions.
208
209 partitions = OSSet::withCapacity(2);
210 if ( partitions == 0 ) goto scanErr;
211
212 // Open the media with read access.
213
214 mediaIsOpen = media->open(this, 0, kIOStorageAccessReader);
215 if ( mediaIsOpen == false ) goto scanErr;
216
217 // Obtain the table of contents.
218
219 toc = media->getTOC();
220 if ( toc == 0 ) goto scanErr;
221
222 tocCount = (toc->length - sizeof(UInt16)) / sizeof(CDTOCDescriptor);
223
224 // Allocate a list large enough to hold information about each session.
225
226 sessions = IONew(CDSession, kCDSessionMaxIndex + 1);
227 if ( sessions == 0 ) goto scanErr;
228
229 bzero(sessions, (kCDSessionMaxIndex + 1) * sizeof(CDSession));
230
231 // Allocate a list large enough to hold information about each track.
232
233 tracks = IONew(CDTrack, kCDTrackMaxIndex + 1);
234 if ( tracks == 0 ) goto scanErr;
235
236 bzero(tracks, (kCDTrackMaxIndex + 1) * sizeof(CDTrack));
237
238 // Scan the table of contents, gathering information about the sessions
239 // and tracks on the CD, but without making assumptions about the order
240 // of the entries in the table.
241
242 for ( unsigned index = 0; index < tocCount; index++ )
243 {
244 CDTOCDescriptor * descriptor = toc->descriptors + index;
245
246 // Determine whether this is an audio or data track descriptor.
247
248 if ( descriptor->point >= kCDTrackMinIndex &&
249 descriptor->point <= kCDTrackMaxIndex &&
250 descriptor->adr == 0x01 &&
251 descriptor->session <= kCDSessionMaxIndex )
252 {
253 CDTrack * track = tracks + descriptor->point;
254
255 // Record the relevant information about this track.
256
257 track->block = CDConvertMSFToLBA(descriptor->p);
258 track->descriptor = descriptor;
259 track->session = descriptor->session;
260
261 if ( (descriptor->control & 0x04) ) // (data track?)
262 {
263 track->blockSize = kCDSectorSizeMode1;
264 track->blockType = kCDSectorTypeMode1;
265 }
266 else // (audio track?)
267 {
268 track->blockSize = kCDSectorSizeCDDA;
269 track->blockType = kCDSectorTypeCDDA;
270 }
271
272 trackMinIndex = min(descriptor->point, trackMinIndex);
273 trackMaxIndex = max(descriptor->point, trackMaxIndex);
274 }
275
276 // Determine whether this is a lead-in (A0) descriptor.
277
278 else if ( descriptor->point == 0xA0 &&
279 descriptor->adr == 0x01 &&
280 descriptor->session <= kCDSessionMaxIndex )
281 {
282 CDSession * session = sessions + descriptor->session;
283
284 // Record whether the session has "form 1" or "form 2" tracks.
285
286 session->isFormX = (descriptor->p.second) ? true : false;
287 }
288
289 // Determine whether this is a lead-out (A2) descriptor.
290
291 else if ( descriptor->point == 0xA2 &&
292 descriptor->adr == 0x01 &&
293 descriptor->session <= kCDSessionMaxIndex )
294 {
295 CDSession * session = sessions + descriptor->session;
296
297 // Record the position of the session lead-out.
298
299 session->leadOut = CDConvertMSFToLBA(descriptor->p);
300
301 sessionMinIndex = min(descriptor->session, sessionMinIndex);
302 sessionMaxIndex = max(descriptor->session, sessionMaxIndex);
303 }
304 }
305
306 if ( sessionMinIndex > kCDSessionMaxIndex ) // (no sessions?)
307 {
308 goto scanErr;
309 }
310
311 if ( trackMinIndex > kCDTrackMaxIndex ) // (no tracks?)
312 {
313 goto scanErr;
314 }
315
316 // Pre-scan the ordered list of tracks.
317
318 for ( unsigned index = trackMinIndex; index <= trackMaxIndex; index++ )
319 {
320 CDTrack * track = tracks + index;
321
322 // Validate the existence of this track (and its session).
323
324 if ( track->descriptor == 0 || sessions[track->session].leadOut == 0 )
325 {
326 goto scanErr;
327 }
328
329 // Determine the block type, and linkage requirement, for this track.
330
331 if ( track->blockType == kCDSectorTypeMode1 ) // (data track?)
332 {
333 IOReturn status;
334
335 // Read a whole sector from the data track into our buffer.
336
337///m:2333367:workaround:commented:start
338// status = media->read( /* client */ this,
339///m:2333367:workaround:commented:stop
340///m:2333367:workaround:added:start
341 status = media->IOStorage::read( /* client */ this,
342///m:2333367:workaround:added:stop
343 /* byteStart */ track->block * mediaBlockSize,
344 /* buffer */ buffer );
345
346 if ( status == kIOReturnSuccess )
347 {
348 UInt8 * sector = (UInt8 *) buffer->getBytesNoCopy();
349
350 // Determine whether this is a "mode 2" data track.
351
352 if ( sector[15] == 0x02 )
353 {
354 // Determine whether this is a "mode 2 formless",
355 // "mode 2 form 1" or "mode 2 form 2" data track.
356
357 if ( sessions[track->session].isFormX )
358 {
359 if ( (sector[18] & 0x20) )
360 {
361 track->blockSize = kCDSectorSizeMode2Form2;
362 track->blockType = kCDSectorTypeMode2Form2;
363 }
364 else
365 {
366 track->blockSize = kCDSectorSizeMode2Form1;
367 track->blockType = kCDSectorTypeMode2Form1;
368
369 // Determine whether this is a linked data track.
370
371 if ( track->block && memcmp(sector + 24, "ER", 2) )
372 {
373 trackMaxLinked = track;
374 }
375 }
376 }
377 else
378 {
379 track->blockSize = kCDSectorSizeMode2;
380 track->blockType = kCDSectorTypeMode2;
381 }
382 }
383
384 // Determine whether this is a linked "mode 1" data track.
385
386 else if ( track->block && memcmp(sector + 16, "ER", 2) )
387 {
388 trackMaxLinked = track;
389 }
390 }
391 }
392 }
393
394 // Create a media object to represent the linked data tracks, the hidden
395 // pre-gap-area data track, or even both, if it is applicable to this CD.
396
397 if ( trackMaxLinked || tracks[trackMinIndex].block )
398 {
399 CDTOCDescriptor descriptor;
400 UInt32 trackBlockNext;
401 CDSectorSize trackBlockSize;
402 CDSectorType trackBlockType;
403 UInt64 trackSize;
404
405 descriptor.session = sessionMinIndex;
406 descriptor.control = 0x04;
407 descriptor.adr = 0x01;
408 descriptor.tno = 0x00;
409 descriptor.point = 0x00;
410 descriptor.address.minute = 0x00;
411 descriptor.address.second = 0x00;
412 descriptor.address.frame = 0x00;
413 descriptor.zero = 0x00;
414 descriptor.p = CDConvertLBAToMSF(0);
415
416 if ( trackMaxLinked )
417 {
418 descriptor.session = sessionMaxIndex;
419 descriptor.control = trackMaxLinked->descriptor->control;
420
421 trackBlockNext = sessions[sessionMaxIndex].leadOut;
422 trackBlockSize = trackMaxLinked->blockSize;
423 trackBlockType = trackMaxLinked->blockType;
424 }
425 else
426 {
427 trackBlockNext = tracks[trackMinIndex].block;
428 trackBlockSize = kCDSectorSizeMode1;
429 trackBlockType = kCDSectorTypeMode1;
430 }
431
432 trackSize = trackBlockNext * trackBlockSize;
433
434 // Create a media object to represent this partition.
435
436 IOMedia * newMedia = instantiateMediaObject(
437 /* partition */ &descriptor,
438 /* partitionSize */ trackSize,
439 /* partitionBlockSize */ trackBlockSize,
440 /* partitionBlockType */ trackBlockType,
441 /* toc */ toc );
442
443 if ( newMedia )
444 {
445 partitions->setObject(newMedia);
446 newMedia->release();
447 }
448 }
449
450 // Scan the ordered list of tracks.
451
452 for ( unsigned index = trackMinIndex; index <= trackMaxIndex; index++ )
453 {
454 CDTrack * track = tracks + index;
455 UInt32 trackBlockNext;
456 UInt64 trackSize;
457
458 // Determine whether this is a linked data track (skipped).
459
460 if ( ( trackMaxLinked ) &&
461 ( track->blockType == kCDSectorTypeMode1 ||
462 track->blockType == kCDSectorTypeMode2Form1 ) )
463 {
464 continue;
465 }
466
467 // Determine where the partitions ends.
468
469 if ( index < trackMaxIndex && track->session == (track + 1)->session )
470 {
471 trackBlockNext = (track + 1)->block;
472 }
473 else
474 {
475 trackBlockNext = sessions[track->session].leadOut;
476 }
477
478 if ( track->block >= trackBlockNext )
479 {
480 goto scanErr;
481 }
482
483 trackSize = (trackBlockNext - track->block) * track->blockSize;
484
485 // Determine whether the partition is corrupt (fatal).
486
487 if ( isPartitionCorrupt( /* partition */ track->descriptor,
488 /* partitionSize */ trackSize,
489 /* partitionBlockSize */ track->blockSize,
490 /* partitionBlockType */ track->blockType,
491 /* toc */ toc ) )
492 {
493 goto scanErr;
494 }
495
496 // Determine whether the partition is invalid (skipped).
497
498 if ( isPartitionInvalid( /* partition */ track->descriptor,
499 /* partitionSize */ trackSize,
500 /* partitionBlockSize */ track->blockSize,
501 /* partitionBlockType */ track->blockType,
502 /* toc */ toc ) )
503 {
504 continue;
505 }
506
507 // Create a media object to represent this partition.
508
509 IOMedia * newMedia = instantiateMediaObject(
510 /* partition */ track->descriptor,
511 /* partitionSize */ trackSize,
512 /* partitionBlockSize */ track->blockSize,
513 /* partitionBlockType */ track->blockType,
514 /* toc */ toc );
515
516 if ( newMedia )
517 {
518 partitions->setObject(newMedia);
519 newMedia->release();
520 }
521 }
522
523 // Release our resources.
524
525 media->close(this);
526 buffer->release();
527 IODelete(tracks, CDTrack, kCDTrackMaxIndex + 1);
528 IODelete(sessions, CDSession, kCDSessionMaxIndex + 1);
529
530 return partitions;
531
532scanErr:
533
534 // Release our resources.
535
536 if ( mediaIsOpen ) media->close(this);
537 if ( partitions ) partitions->release();
538 if ( buffer ) buffer->release();
539 if ( tracks ) IODelete(tracks, CDTrack, kCDTrackMaxIndex + 1);
540 if ( sessions ) IODelete(sessions, CDSession, kCDSessionMaxIndex + 1);
541
542 return 0;
543}
544
545// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
546
547bool IOCDPartitionScheme::isPartitionCorrupt(
548 CDTOCDescriptor * /* partition */ ,
549 UInt64 /* partitionSize */ ,
550 UInt32 /* partitionBlockSize */ ,
551 CDSectorType /* partitionBlockType */ ,
552 CDTOC * /* toc */ )
553{
554 //
555 // Ask whether the given partition appears to be corrupt. A partition that
556 // is corrupt will cause the failure of the CD partition scheme altogether.
557 //
558
559 return false;
560}
561
562// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
563
564bool IOCDPartitionScheme::isPartitionInvalid(
565 CDTOCDescriptor * partition,
566 UInt64 partitionSize,
567 UInt32 partitionBlockSize,
568 CDSectorType partitionBlockType,
569 CDTOC * toc )
570{
571 //
572 // Ask whether the given partition appears to be invalid. A partition that
573 // is invalid will cause it to be skipped in the scan, but will not cause a
574 // failure of the CD partition scheme.
575 //
576
577 IOMedia * media = getProvider();
578 UInt64 mediaBlockSize = media->getPreferredBlockSize();
579 UInt64 partitionBase = 0;
580
581 // Compute the relative byte position and size of the new partition,
582 // relative to the provider media's natural blocking factor of 2352.
583
584 partitionBase = CDConvertMSFToLBA(partition->p) * mediaBlockSize;
585 partitionSize = (partitionSize / partitionBlockSize) * mediaBlockSize;
586
587 // Determine whether the partition begins before the 00:02:00 mark.
588
589 if ( partition->p.minute == 0 && partition->p.second < 2 ) return true;
590
591 // Determine whether the partition leaves the confines of the container.
592
593 if ( partitionBase + partitionSize > media->getSize() ) return true;
594
595 return false;
596}
597
598// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
599
600IOMedia * IOCDPartitionScheme::instantiateMediaObject(
601 CDTOCDescriptor * partition,
602 UInt64 partitionSize,
603 UInt32 partitionBlockSize,
604 CDSectorType partitionBlockType,
605 CDTOC * toc )
606{
607 //
608 // Instantiate a new media object to represent the given partition.
609 //
610
611 IOMedia * media = getProvider();
612 UInt64 partitionBase = 0;
613 char * partitionHint = 0;
614
615 // Compute the relative byte position of the new partition and encode it
616 // into the designated "logical space", given the partition's block type.
617 //
618 // 0x0000000000 through 0x00FFFFFFFF is the "don't care" space.
619 // 0x0100000000 through 0x01FFFFFFFF is the "audio" space.
620 // 0x0200000000 through 0x02FFFFFFFF is the "mode 1" space.
621 // 0x0300000000 through 0x03FFFFFFFF is the "mode 2 formless" space.
622 // 0x0400000000 through 0x04FFFFFFFF is the "mode 2 form 1" space.
623 // 0x0500000000 through 0x05FFFFFFFF is the "mode 2 form 2" space.
624
625 partitionBase = CDConvertMSFToLBA(partition->p) * partitionBlockSize;
626 partitionBase += ((UInt64) partitionBlockType) << 32;
627
628 // Look up a type for the new partition.
629
630 OSDictionary * hintTable = OSDynamicCast(
631 /* type */ OSDictionary,
632 /* instance */ getProperty(kIOCDPartitionSchemeContentTable) );
633
634 if ( hintTable )
635 {
636 char hintIndex[5];
637 OSString * hintValue;
638
639 sprintf(hintIndex, "0x%02X", partitionBlockType & 0xFF);
640
641 hintValue = OSDynamicCast(OSString, hintTable->getObject(hintIndex));
642
643 if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy();
644 }
645
646 // Create the new media object.
647
648 IOMedia * newMedia = instantiateDesiredMediaObject(
649 /* partition */ partition,
650 /* partitionSize */ partitionSize,
651 /* partitionBlockSize */ partitionBlockSize,
652 /* partitionBlockType */ partitionBlockType,
653 /* toc */ toc );
654
655 if ( newMedia )
656 {
657 if ( newMedia->init(
658 /* base */ partitionBase,
659 /* size */ partitionSize,
660 /* preferredBlockSize */ partitionBlockSize,
661 /* isEjectable */ media->isEjectable(),
662 /* isWhole */ false,
663 /* isWritable */ media->isWritable(),
664 /* contentHint */ partitionHint ) )
665 {
666 // Set a name for this partition.
667
668 char name[24];
669 sprintf(name, "Untitled %d", partition->point);
670 newMedia->setName(name);
671
672 // Set a location value (the partition number) for this partition.
673
674 char location[12];
675 sprintf(location, "%d", partition->point);
676 newMedia->setLocation(location);
677
678 // Set the "Partition ID" key for this partition.
679
680 newMedia->setProperty(kIOMediaPartitionIDKey, partition->point, 32);
681
682 // Set the "Session ID" key for this partition.
683
684 newMedia->setProperty(kIOMediaSessionIDKey, partition->session, 32);
685 }
686 else
687 {
688 newMedia->release();
689 newMedia = 0;
690 }
691 }
692
693 return newMedia;
694}
695
696// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
697
698IOMedia * IOCDPartitionScheme::instantiateDesiredMediaObject(
699 CDTOCDescriptor * /* partition */ ,
700 UInt64 /* partitionSize */ ,
701 UInt32 /* partitionBlockSize */ ,
702 CDSectorType /* partitionBlockType */ ,
703 CDTOC * /* toc */ )
704{
705 //
706 // Allocate a new media object (called from instantiateMediaObject).
707 //
708
709 return new IOMedia;
710}
711
712// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
713
714void IOCDPartitionScheme::read( IOService * client,
715 UInt64 byteStart,
716 IOMemoryDescriptor * buffer,
717 IOStorageCompletion completion )
718{
719 //
720 // Read data from the storage object at the specified byte offset into the
721 // specified buffer, asynchronously. When the read completes, the caller
722 // will be notified via the specified completion action.
723 //
724 // The buffer will be retained for the duration of the read.
725 //
726 // For the CD partition scheme, we convert the read from a partition
727 // object into the appropriate readCD command to our provider media.
728 //
729
730 getProvider()->readCD( /* client */ this,
731 /* byteStart */ (byteStart & 0xFFFFFFFF),
732 /* buffer */ buffer,
733 /* sectorArea */ (CDSectorArea) kCDSectorAreaUser,
734 /* sectorType */ (CDSectorType) (byteStart >> 32),
735 /* completion */ completion );
736}
737
738// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
739
740OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 0);
741
742// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
743
744OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 1);
745
746// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
747
748OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 2);
749
750// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
751
752OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 3);
753
754// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
755
756OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 4);
757
758// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
759
760OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 5);
761
762// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
763
764OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 6);
765
766// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
767
768OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 7);
769
770// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
771
772OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 8);
773
774// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
775
776OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 9);
777
778// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
779
780OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 10);
781
782// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
783
784OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 11);
785
786// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
787
788OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 12);
789
790// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
791
792OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 13);
793
794// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
795
796OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 14);
797
798// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
799
800OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 15);