|
|
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.