Annotation of XNU/iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp, revision 1.1.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.