|
|
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: #include <IOKit/IOBSD.h> ! 23: #include <IOKit/IOLib.h> ! 24: #include <IOKit/IOService.h> ! 25: #include <IOKit/IODeviceTreeSupport.h> ! 26: #include <IOKit/IOKitKeys.h> ! 27: #include <IOKit/storage/IOMedia.h> ! 28: ! 29: #include <sys/disklabel.h> ! 30: ! 31: extern "C" { ! 32: ! 33: #include <pexpert/pexpert.h> ! 34: #include <kern/clock.h> ! 35: ! 36: // how long to wait for matching root device, secs ! 37: #define ROOTDEVICETIMEOUT 60 ! 38: ! 39: ! 40: kern_return_t ! 41: IOKitBSDInit( void ) ! 42: { ! 43: IOLog("IOKitBSDInit\n"); ! 44: ! 45: IOService::publishResource("IOBSD"); ! 46: ! 47: return( kIOReturnSuccess ); ! 48: } ! 49: ! 50: OSDictionary * IOBSDNameMatching( const char * name ) ! 51: { ! 52: OSDictionary * dict; ! 53: const OSSymbol * str = 0; ! 54: ! 55: do { ! 56: ! 57: dict = IOService::serviceMatching( gIOServiceKey ); ! 58: if( !dict) ! 59: continue; ! 60: str = OSSymbol::withCString( name ); ! 61: if( !str) ! 62: continue; ! 63: dict->setObject( kIOBSDName, (OSObject *) str ); ! 64: str->release(); ! 65: ! 66: return( dict ); ! 67: ! 68: } while( false ); ! 69: ! 70: if( dict) ! 71: dict->release(); ! 72: if( str) ! 73: str->release(); ! 74: ! 75: return( 0 ); ! 76: } ! 77: ! 78: OSDictionary * IONetworkMatching( const char * path, ! 79: char * buf, int maxLen ) ! 80: { ! 81: OSDictionary * matching = 0; ! 82: OSDictionary * dict; ! 83: OSString * str; ! 84: char * comp; ! 85: const char * skip; ! 86: int len; ! 87: ! 88: do { ! 89: ! 90: len = strlen( kIODeviceTreePlane ":" ); ! 91: maxLen -= len; ! 92: if( maxLen < 0) ! 93: continue; ! 94: ! 95: strcpy( buf, kIODeviceTreePlane ":" ); ! 96: comp = buf + len; ! 97: ! 98: // remove parameters following ':' from the path ! 99: skip = strchr( path, ':'); ! 100: if( !skip) ! 101: continue; ! 102: ! 103: len = skip - path; ! 104: maxLen -= len; ! 105: if( maxLen < 0) ! 106: continue; ! 107: strncpy( comp, path, len ); ! 108: comp[ len ] = 0; ! 109: ! 110: matching = IOService::serviceMatching( "IONetworkInterface" ); ! 111: if( !matching) ! 112: continue; ! 113: dict = IOService::addLocation( matching ); ! 114: if( !dict) ! 115: continue; ! 116: ! 117: str = OSString::withCString( buf ); ! 118: if( !str) ! 119: continue; ! 120: dict->setObject( kIOPathMatchKey, str ); ! 121: str->release(); ! 122: ! 123: return( matching ); ! 124: ! 125: } while( false ); ! 126: ! 127: if( matching) ! 128: matching->release(); ! 129: ! 130: return( 0 ); ! 131: } ! 132: ! 133: OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) ! 134: { ! 135: OSDictionary * matching = 0; ! 136: const char * look; ! 137: const char * skip; ! 138: const char * alias; ! 139: char * comp; ! 140: UInt32 unit = 0x99; ! 141: UInt32 partition = 0xaa; ! 142: int len; ! 143: char c; ! 144: ! 145: // scan the tail of the path for "@unit:partition" ! 146: do { ! 147: // Have to get the full path to the controller - an alias may ! 148: // tell us next to nothing, like "hd:8" ! 149: skip = path; ! 150: alias = IORegistryEntry::dealiasPath( &skip, gIODTPlane ); ! 151: ! 152: look = skip + strlen( skip); ! 153: c = ':'; ! 154: while( c && (look != skip)) { ! 155: if( *(--look) == c) { ! 156: if( c == ':') { ! 157: partition = strtol( look + 1, 0, 0 ); ! 158: c = '@'; ! 159: } else if( c == '@') { ! 160: unit = strtol( look + 1, 0, 16 ); ! 161: c = '/'; ! 162: } else if( c == '/') ! 163: c = 0; ! 164: } ! 165: ! 166: if( alias && (look == skip)) { ! 167: skip = alias; ! 168: look = skip + strlen( skip); ! 169: alias = 0; ! 170: } ! 171: } ! 172: if( c) ! 173: continue; ! 174: ! 175: #define diskMatch1 \ ! 176: "{" \ ! 177: kIOProviderClassKey"=IOMedia;" \ ! 178: "'IOPath Separator'=':';" \ ! 179: "'IOPath Extension'='%ld';" \ ! 180: kIOLocationMatchKey"={" \ ! 181: "IOUnit=%ld:32;" \ ! 182: kIOLocationMatchKey"={" \ ! 183: kIOPathMatchKey"='" ! 184: #define diskMatch2 \ ! 185: "';" \ ! 186: "};" \ ! 187: "};" \ ! 188: "}" ! 189: ! 190: sprintf( buf, diskMatch1, partition, unit ); ! 191: ! 192: len = strlen( buf ); ! 193: comp = buf + len; ! 194: ! 195: maxLen -= len; ! 196: maxLen -= (look - skip) + strlen( kIODeviceTreePlane) + 1; ! 197: if( alias) { ! 198: len = strlen( alias ); ! 199: maxLen -= len; ! 200: } ! 201: if( maxLen > 0) { ! 202: strcpy( comp, kIODeviceTreePlane); ! 203: comp += strlen( kIODeviceTreePlane); ! 204: *(comp++) = ':'; ! 205: if( alias) { ! 206: strcpy( comp, alias ); ! 207: comp += len; ! 208: } ! 209: len = look - skip; ! 210: strncpy( comp, skip, len); ! 211: comp += len; ! 212: } else ! 213: continue; ! 214: ! 215: strcpy( comp, diskMatch2 ); ! 216: ! 217: matching = OSDynamicCast(OSDictionary, OSUnserialize( buf, 0 )); ! 218: if (!matching) ! 219: continue; ! 220: ! 221: return( matching ); ! 222: ! 223: } while( false ); ! 224: ! 225: if( matching) ! 226: matching->release(); ! 227: ! 228: return( 0 ); ! 229: } ! 230: ! 231: kern_return_t IOFindBSDRoot( char * rootName, ! 232: dev_t * root, u_int32_t * oflags ) ! 233: { ! 234: mach_timespec_t t; ! 235: IOService * service; ! 236: IORegistryEntry * regEntry; ! 237: OSDictionary * matching = 0; ! 238: OSString * iostr; ! 239: OSNumber * off; ! 240: OSData * data = 0; ! 241: ! 242: UInt32 flags = 0; ! 243: int minor, major; ! 244: char * rdBootVar; ! 245: enum { kMaxPathBuf = 512, kMaxBootVar = 128 }; ! 246: char * str; ! 247: const char * look = 0; ! 248: int len; ! 249: bool forceNet = false; ! 250: ! 251: static int mountAttempts = 0; ! 252: ! 253: if( mountAttempts++) ! 254: IOSleep( 5 * 1000 ); ! 255: ! 256: str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar ); ! 257: if( !str) ! 258: return( kIOReturnNoMemory ); ! 259: rdBootVar = str + kMaxPathBuf; ! 260: ! 261: if (!PE_parse_boot_arg("rd", rdBootVar ) ! 262: && !PE_parse_boot_arg("rootdev", rdBootVar )) ! 263: rdBootVar[0] = 0; ! 264: ! 265: do { ! 266: if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) { ! 267: data = (OSData *) regEntry->getProperty( "rootpath" ); ! 268: regEntry->release(); ! 269: if( data) ! 270: continue; ! 271: } ! 272: if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) { ! 273: data = (OSData *) regEntry->getProperty( "boot-file" ); ! 274: regEntry->release(); ! 275: if( data) ! 276: continue; ! 277: } ! 278: } while( false ); ! 279: ! 280: if( data) ! 281: look = (const char *) data->getBytesNoCopy(); ! 282: ! 283: if( rdBootVar[0] == '*') { ! 284: look = rdBootVar + 1; ! 285: forceNet = false; ! 286: } else { ! 287: if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) { ! 288: forceNet = (0 != regEntry->getProperty( "net-boot" )); ! 289: regEntry->release(); ! 290: } ! 291: } ! 292: ! 293: if( look) { ! 294: // from OpenFirmware path ! 295: IOLog("From path: \"%s\", ", look); ! 296: ! 297: if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) ) ! 298: matching = IONetworkMatching( look, str, kMaxPathBuf ); ! 299: else ! 300: matching = IODiskMatching( look, str, kMaxPathBuf ); ! 301: } ! 302: ! 303: if( (!matching) && rdBootVar[0] ) { ! 304: // by BSD name ! 305: look = rdBootVar; ! 306: if( look[0] == '*') ! 307: look++; ! 308: matching = IOBSDNameMatching( look ); ! 309: } ! 310: ! 311: if( !matching) { ! 312: OSString * astring; ! 313: // any UFS ! 314: matching = IOService::serviceMatching( "IOMedia" ); ! 315: astring = OSString::withCStringNoCopy("Apple_UFS"); ! 316: if ( astring ) { ! 317: matching->setObject(kIOMediaContent, astring); ! 318: astring->release(); // XXX -- svail: added. ! 319: } ! 320: } ! 321: ! 322: if( true && matching) { ! 323: OSSerialize * s = OSSerialize::withCapacity( 5 ); ! 324: ! 325: if( matching->serialize( s )) { ! 326: IOLog( "Waiting on %s\n", s->text() ); ! 327: s->release(); ! 328: } ! 329: } ! 330: ! 331: IOService::waitForService(IOService::serviceMatching("IOMediaBSDClient")); ! 332: ! 333: do { ! 334: t.tv_sec = ROOTDEVICETIMEOUT; ! 335: t.tv_nsec = 0; ! 336: matching->retain(); ! 337: service = IOService::waitForService( matching, &t ); ! 338: if( (!service) || (mountAttempts == 10)) { ! 339: PE_display_icon( 0, "noroot"); ! 340: IOLog( "Still waiting for root device\n" ); ! 341: } ! 342: } while( !service); ! 343: matching->release(); ! 344: ! 345: major = 0; ! 346: minor = 0; ! 347: ! 348: if( service) { ! 349: ! 350: len = kMaxPathBuf; ! 351: service->getPath( str, &len, gIOServicePlane ); ! 352: IOLog( "Got boot device = %s\n", str ); ! 353: ! 354: iostr = (OSString *) service->getProperty( kIOBSDName ); ! 355: if( iostr) ! 356: strcpy( rootName, iostr->getCStringNoCopy() ); ! 357: off = (OSNumber *) service->getProperty( kIOBSDMajor ); ! 358: if( off) ! 359: major = off->unsigned32BitValue(); ! 360: off = (OSNumber *) service->getProperty( kIOBSDMinor ); ! 361: if( off) ! 362: minor = off->unsigned32BitValue(); ! 363: ! 364: if( service->metaCast( "IONetworkInterface" )) ! 365: flags |= 1; ! 366: ! 367: } else { ! 368: ! 369: IOLog( "Wait for root failed\n" ); ! 370: strcpy( rootName, "en0"); ! 371: flags |= 1; ! 372: } ! 373: ! 374: IOLog( "BSD root: %s", rootName ); ! 375: if( major) ! 376: IOLog(", major %d, minor %d\n", major, minor ); ! 377: else ! 378: IOLog("\n"); ! 379: ! 380: *root = makedev( major, minor ); ! 381: *oflags = flags; ! 382: ! 383: IOFree( str, kMaxPathBuf + kMaxBootVar ); ! 384: ! 385: if( gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) { ! 386: ! 387: IOSleep(10 * 1000); ! 388: // IOService::getPlatform()->waitQuiet(); ! 389: if( gIOKitDebug & kIOLogDTree) { ! 390: IOLog("\nDT plane:\n"); ! 391: IOPrintPlane( gIODTPlane ); ! 392: } ! 393: if( gIOKitDebug & kIOLogServiceTree) { ! 394: IOLog("\nService plane:\n"); ! 395: IOPrintPlane( gIOServicePlane ); ! 396: } ! 397: if( gIOKitDebug & kIOLogMemory) ! 398: IOPrintMemory(); ! 399: } ! 400: ! 401: return( kIOReturnSuccess ); ! 402: } ! 403: ! 404: } /* extern "C" */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.