Annotation of XNU/iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.