1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include <IOKit/IOBSD.h> 29#include <IOKit/IOLib.h> 30#include <IOKit/IOService.h> 31#include <IOKit/IODeviceTreeSupport.h> 32#include <IOKit/IOKitKeys.h> 33#include <IOKit/IOPlatformExpert.h> 34 35extern "C" { 36 37#include <pexpert/pexpert.h> 38#include <kern/clock.h> 39#include <uuid/uuid.h> 40 41// how long to wait for matching root device, secs 42#define ROOTDEVICETIMEOUT 60 43 44extern dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys); 45extern dev_t mdevlookup(int devid); 46extern void mdevremoveall(void); 47 48kern_return_t 49IOKitBSDInit( void ) 50{ 51 IOService::publishResource("IOBSD"); 52 53 return( kIOReturnSuccess ); 54} 55 56OSDictionary * IOBSDNameMatching( const char * name ) 57{ 58 OSDictionary * dict; 59 const OSSymbol * str = 0; 60 61 do { 62 63 dict = IOService::serviceMatching( gIOServiceKey ); 64 if( !dict) 65 continue; 66 str = OSSymbol::withCString( name ); 67 if( !str) 68 continue; 69 dict->setObject( kIOBSDNameKey, (OSObject *) str ); 70 str->release(); 71 72 return( dict ); 73 74 } while( false ); 75 76 if( dict) 77 dict->release(); 78 if( str) 79 str->release(); 80 81 return( 0 ); 82} 83 84OSDictionary * IOUUIDMatching( void ) 85{ 86 return IOService::resourceMatching( "boot-uuid-media" ); 87} 88 89 90OSDictionary * IOCDMatching( void ) 91{ 92 OSDictionary * dict; 93 const OSSymbol * str; 94 95 dict = IOService::serviceMatching( "IOMedia" ); 96 if( dict == 0 ) { 97 IOLog("Unable to find IOMedia\n"); 98 return 0; 99 } 100 101 str = OSSymbol::withCString( "CD_ROM_Mode_1" ); 102 if( str == 0 ) { 103 dict->release(); 104 return 0; 105 } 106 107 dict->setObject( "Content Hint", (OSObject *)str ); 108 str->release(); 109 return( dict ); 110} 111 112OSDictionary * IONetworkMatching( const char * path, 113 char * buf, int maxLen ) 114{ 115 OSDictionary * matching = 0; 116 OSDictionary * dict; 117 OSString * str; 118 char * comp; 119 const char * skip; 120 int len; 121 122 do { 123 124 len = strlen( kIODeviceTreePlane ":" ); 125 maxLen -= len; 126 if( maxLen <= 0) 127 continue; 128 129 strlcpy( buf, kIODeviceTreePlane ":", len + 1 ); 130 comp = buf + len; 131 132 // remove parameters following ':' from the path 133 skip = strchr( path, ':'); 134 if( !skip) 135 continue; 136 137 len = skip - path; 138 maxLen -= len; 139 if( maxLen <= 0) 140 continue; 141 strlcpy( comp, path, len + 1 ); 142 143 matching = IOService::serviceMatching( "IONetworkInterface" ); 144 if( !matching) 145 continue; 146 dict = IOService::addLocation( matching ); 147 if( !dict) 148 continue; 149 150 str = OSString::withCString( buf ); 151 if( !str) 152 continue; 153 dict->setObject( kIOPathMatchKey, str ); 154 str->release(); 155 156 return( matching ); 157 158 } while( false ); 159 160 if( matching) 161 matching->release(); 162 163 return( 0 ); 164} 165 166OSDictionary * IONetworkNamePrefixMatching( const char * prefix ) 167{ 168 OSDictionary * matching; 169 OSDictionary * propDict = 0; 170 const OSSymbol * str = 0; 171 char networkType[128]; 172 173 do { 174 matching = IOService::serviceMatching( "IONetworkInterface" ); 175 if ( matching == 0 ) 176 continue; 177 178 propDict = OSDictionary::withCapacity(1); 179 if ( propDict == 0 ) 180 continue; 181 182 str = OSSymbol::withCString( prefix ); 183 if ( str == 0 ) 184 continue; 185 186 propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str ); 187 str->release(); 188 str = 0; 189 190 // see if we're contrained to netroot off of specific network type 191 if(PE_parse_boot_argn( "network-type", networkType, 128 )) 192 { 193 str = OSSymbol::withCString( networkType ); 194 if(str) 195 { 196 propDict->setObject( "IONetworkRootType", str); 197 str->release(); 198 str = 0; 199 } 200 } 201 202 if ( matching->setObject( gIOPropertyMatchKey, 203 (OSObject *) propDict ) != true ) 204 continue; 205 206 propDict->release(); 207 propDict = 0; 208 209 return( matching ); 210 211 } while ( false ); 212 213 if ( matching ) matching->release(); 214 if ( propDict ) propDict->release(); 215 if ( str ) str->release(); 216 217 return( 0 ); 218} 219 220static bool IORegisterNetworkInterface( IOService * netif ) 221{ 222 // A network interface is typically named and registered 223 // with BSD after receiving a request from a user space 224 // "namer". However, for cases when the system needs to 225 // root from the network, this registration task must be 226 // done inside the kernel and completed before the root 227 // device is handed to BSD. 228 229 IOService * stack; 230 OSNumber * zero = 0; 231 OSString * path = 0; 232 OSDictionary * dict = 0; 233 char * pathBuf = 0; 234 int len; 235 enum { kMaxPathLen = 512 }; 236 237 do { 238 stack = IOService::waitForService( 239 IOService::serviceMatching("IONetworkStack") ); 240 if ( stack == 0 ) break; 241 242 dict = OSDictionary::withCapacity(3); 243 if ( dict == 0 ) break; 244 245 zero = OSNumber::withNumber((UInt64) 0, 32); 246 if ( zero == 0 ) break; 247 248 pathBuf = (char *) IOMalloc( kMaxPathLen ); 249 if ( pathBuf == 0 ) break; 250 251 len = kMaxPathLen; 252 if ( netif->getPath( pathBuf, &len, gIOServicePlane ) 253 == false ) break; 254 255 path = OSString::withCStringNoCopy( pathBuf ); 256 if ( path == 0 ) break; 257 258 dict->setObject( "IOInterfaceUnit", zero ); 259 dict->setObject( kIOPathMatchKey, path ); 260 261 stack->setProperties( dict ); 262 } 263 while ( false ); 264 265 if ( zero ) zero->release(); 266 if ( path ) path->release(); 267 if ( dict ) dict->release(); 268 if ( pathBuf ) IOFree(pathBuf, kMaxPathLen); 269 270 return ( netif->getProperty( kIOBSDNameKey ) != 0 ); 271} 272 273OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) 274{ 275 const char * look; 276 const char * alias; 277 char * comp; 278 long unit = -1; 279 long partition = -1; 280 long lun = -1; 281 char c; 282 int len; 283 284 // scan the tail of the path for "@unit:partition" 285 do { 286 // Have to get the full path to the controller - an alias may 287 // tell us next to nothing, like "hd:8" 288 alias = IORegistryEntry::dealiasPath( &path, gIODTPlane ); 289 290 look = path + strlen( path); 291 c = ':'; 292 while( look != path) { 293 if( *(--look) == c) { 294 if( c == ':') { 295 partition = strtol( look + 1, 0, 0 ); 296 c = '@'; 297 } else if( c == '@') { 298 unit = strtol( look + 1, &comp, 16 ); 299 300 if( *comp == ',') { 301 lun = strtol( comp + 1, 0, 16 ); 302 } 303 304 c = '/'; 305 } else if( c == '/') { 306 c = 0; 307 break; 308 } 309 } 310 311 if( alias && (look == path)) { 312 path = alias; 313 look = path + strlen( path); 314 alias = 0; 315 } 316 } 317 if( c || unit == -1 || partition == -1) 318 continue; 319 320 len = strlen( "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" ); 321 maxLen -= len; 322 if( maxLen <= 0) 323 continue; 324 325 snprintf( buf, len + 1, "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" ); 326 comp = buf + len; 327 328 if( alias) { 329 len = strlen( alias ); 330 maxLen -= len; 331 if( maxLen <= 0) 332 continue; 333 334 strlcpy( comp, alias, len + 1 ); 335 comp += len; 336 } 337 338 if ( (look - path)) { 339 len = (look - path); 340 maxLen -= len; 341 if( maxLen <= 0) 342 continue; 343 344 strlcpy( comp, path, len + 1 ); 345 comp += len; 346 } 347 348 if ( lun != -1 ) 349 { 350 len = strlen( "/@hhhhhhhh,hhhhhhhh:dddddddddd';}" ); 351 maxLen -= len; 352 if( maxLen <= 0) 353 continue; 354 355 snprintf( comp, len + 1, "/@%lx,%lx:%ld';}", unit, lun, partition ); 356 } 357 else 358 { 359 len = strlen( "/@hhhhhhhh:dddddddddd';}" ); 360 maxLen -= len; 361 if( maxLen <= 0) 362 continue; 363 364 snprintf( comp, len + 1, "/@%lx:%ld';}", unit, partition ); 365 } 366 367 return( OSDynamicCast(OSDictionary, OSUnserialize( buf, 0 )) ); 368 369 } while( false ); 370 371 return( 0 ); 372} 373 374OSDictionary * IOOFPathMatching( const char * path, char * buf, int maxLen ) 375{ 376 OSDictionary * matching; 377 OSString * str; 378 char * comp; 379 int len; 380 381 /* need to look up path, get device type, 382 call matching help based on device type */ 383 384 matching = IODiskMatching( path, buf, maxLen ); 385 if( matching) 386 return( matching ); 387 388 do { 389 390 len = strlen( kIODeviceTreePlane ":" ); 391 maxLen -= len; 392 if( maxLen <= 0) 393 continue; 394 395 strlcpy( buf, kIODeviceTreePlane ":", len + 1 ); 396 comp = buf + len; 397 398 len = strlen( path ); 399 maxLen -= len; 400 if( maxLen <= 0) 401 continue; 402 strlcpy( comp, path, len + 1 ); 403 404 matching = OSDictionary::withCapacity( 1 ); 405 if( !matching) 406 continue; 407 408 str = OSString::withCString( buf ); 409 if( !str) 410 continue; 411 matching->setObject( kIOPathMatchKey, str ); 412 str->release(); 413 414 return( matching ); 415 416 } while( false ); 417 418 if( matching) 419 matching->release(); 420 421 return( 0 ); 422} 423 424IOService * IOFindMatchingChild( IOService * service ) 425{ 426 // find a matching child service 427 IOService * child = 0; 428 OSIterator * iter = service->getClientIterator(); 429 if ( iter ) { 430 while( ( child = (IOService *) iter->getNextObject() ) ) { 431 OSDictionary * dict = OSDictionary::withCapacity( 1 ); 432 if( dict == 0 ) { 433 iter->release(); 434 return 0; 435 } 436 const OSSymbol * str = OSSymbol::withCString( "Apple_HFS" ); 437 if( str == 0 ) { 438 dict->release(); 439 iter->release(); 440 return 0; 441 } 442 dict->setObject( "Content", (OSObject *)str ); 443 str->release(); 444 if ( child->compareProperty( dict, "Content" ) ) { 445 dict->release(); 446 break; 447 } 448 dict->release(); 449 IOService * subchild = IOFindMatchingChild( child ); 450 if ( subchild ) { 451 child = subchild; 452 break; 453 } 454 } 455 iter->release(); 456 } 457 return child; 458} 459 460static int didRam = 0; 461 462kern_return_t IOFindBSDRoot( char * rootName, unsigned int rootNameSize, 463 dev_t * root, u_int32_t * oflags ) 464{ 465 mach_timespec_t t; 466 IOService * service; 467 IORegistryEntry * regEntry; 468 OSDictionary * matching = 0; 469 OSString * iostr; 470 OSNumber * off; 471 OSData * data = 0; 472 UInt32 *ramdParms = 0; 473 474 UInt32 flags = 0; 475 int mnr, mjr; 476 bool findHFSChild = false; 477 char * mediaProperty = 0; 478 char * rdBootVar; 479 enum { kMaxPathBuf = 512, kMaxBootVar = 128 }; 480 char * str; 481 const char * look = 0; 482 int len; 483 bool forceNet = false; 484 bool debugInfoPrintedOnce = false; 485 const char * uuidStr = NULL; 486 487 static int mountAttempts = 0; 488 489 int xchar, dchar; 490 491 492 if( mountAttempts++) 493 IOSleep( 5 * 1000 ); 494 495 str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar ); 496 if( !str) 497 return( kIOReturnNoMemory ); 498 rdBootVar = str + kMaxPathBuf; 499 500 if (!PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar ) 501 && !PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar )) 502 rdBootVar[0] = 0; 503 504 do { 505 if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) { 506 data = OSDynamicCast(OSData, regEntry->getProperty( "root-matching" )); 507 if (data) { 508 matching = OSDynamicCast(OSDictionary, OSUnserializeXML((char *)data->getBytesNoCopy())); 509 if (matching) { 510 continue; 511 } 512 } 513 514 data = (OSData *) regEntry->getProperty( "boot-uuid" ); 515 if( data) { 516 uuidStr = (const char*)data->getBytesNoCopy(); 517 OSString *uuidString = OSString::withCString( uuidStr ); 518 519 // match the boot-args boot-uuid processing below 520 if( uuidString) { 521 IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr); 522 IOService::publishResource( "boot-uuid", uuidString ); 523 uuidString->release(); 524 matching = IOUUIDMatching(); 525 mediaProperty = "boot-uuid-media"; 526 regEntry->release(); 527 continue; 528 } else { 529 uuidStr = NULL; 530 } 531 } 532 533 // else try for an OF Path 534 data = (OSData *) regEntry->getProperty( "rootpath" ); 535 regEntry->release(); 536 if( data) continue; 537 } 538 if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) { 539 data = (OSData *) regEntry->getProperty( "boot-file" ); 540 regEntry->release(); 541 if( data) continue; 542 } 543 } while( false ); 544 545 if( data && !uuidStr) 546 look = (const char *) data->getBytesNoCopy(); 547 548 if( rdBootVar[0] == '*') { 549 look = rdBootVar + 1; 550 forceNet = false; 551 } else { 552 if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) { 553 forceNet = (0 != regEntry->getProperty( "net-boot" )); 554 regEntry->release(); 555 } 556 } 557 558 559 560// 561// See if we have a RAMDisk property in /chosen/memory-map. If so, make it into a device. 562// It will become /dev/mdx, where x is 0-f. 563// 564 565 if(!didRam) { /* Have we already build this ram disk? */ 566 didRam = 1; /* Remember we did this */ 567 if((regEntry = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ))) { /* Find the map node */ 568 data = (OSData *)regEntry->getProperty("RAMDisk"); /* Find the ram disk, if there */ 569 if(data) { /* We found one */ 570 571 ramdParms = (UInt32 *)data->getBytesNoCopy(); /* Point to the ram disk base and size */ 572 (void)mdevadd(-1, ramdParms[0] >> 12, ramdParms[1] >> 12, 0); /* Initialize it and pass back the device number */ 573 } 574 regEntry->release(); /* Toss the entry */ 575 } 576 } 577 578// 579// Now check if we are trying to root on a memory device 580// 581 582 if((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) { 583 dchar = xchar = rdBootVar[2]; /* Get the actual device */ 584 if((xchar >= '0') && (xchar <= '9')) xchar = xchar - '0'; /* If digit, convert */ 585 else { 586 xchar = xchar & ~' '; /* Fold to upper case */ 587 if((xchar >= 'A') && (xchar <= 'F')) { /* Is this a valid digit? */ 588 xchar = (xchar & 0xF) + 9; /* Convert the hex digit */ 589 dchar = dchar | ' '; /* Fold to lower case */ 590 } 591 else xchar = -1; /* Show bogus */ 592 } 593 if(xchar >= 0) { /* Do we have a valid memory device name? */ 594 *root = mdevlookup(xchar); /* Find the device number */ 595 if(*root >= 0) { /* Did we find one? */ 596 597 rootName[0] = 'm'; /* Build root name */ 598 rootName[1] = 'd'; /* Build root name */ 599 rootName[2] = dchar; /* Build root name */ 600 rootName[3] = 0; /* Build root name */ 601 IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root)); 602 *oflags = 0; /* Show that this is not network */ 603 goto iofrootx; /* Join common exit... */ 604 } 605 panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar); /* Not there */ 606 } 607 } 608 609 if( look) { 610 // from OpenFirmware path 611 IOLog("From path: \"%s\", ", look); 612 613 if (!matching) { 614 if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) ) { 615 matching = IONetworkMatching( look, str, kMaxPathBuf ); 616 } else { 617 matching = IODiskMatching( look, str, kMaxPathBuf ); 618 } 619 } 620 } 621 622 if( (!matching) && rdBootVar[0] ) { 623 // by BSD name 624 look = rdBootVar; 625 if( look[0] == '*') 626 look++; 627 628 if ( strncmp( look, "en", strlen( "en" )) == 0 ) { 629 matching = IONetworkNamePrefixMatching( "en" ); 630 } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) { 631 matching = IOCDMatching(); 632 findHFSChild = true; 633 } else if ( strncmp( look, "uuid", strlen( "uuid" )) == 0 ) { 634 char *uuid; 635 OSString *uuidString; 636 637 uuid = (char *)IOMalloc( kMaxBootVar ); 638 639 if ( uuid ) { 640 if (!PE_parse_boot_argn( "boot-uuid", uuid, kMaxBootVar )) { 641 panic( "rd=uuid but no boot-uuid=<value> specified" ); 642 } 643 uuidString = OSString::withCString( uuid ); 644 if ( uuidString ) { 645 IOService::publishResource( "boot-uuid", uuidString ); 646 uuidString->release(); 647 IOLog( "\nWaiting for boot volume with UUID %s\n", uuid ); 648 matching = IOUUIDMatching(); 649 mediaProperty = "boot-uuid-media"; 650 } 651 IOFree( uuid, kMaxBootVar ); 652 } 653 } else { 654 matching = IOBSDNameMatching( look ); 655 } 656 } 657 658 if( !matching) { 659 OSString * astring; 660 // Match any HFS media 661 662 matching = IOService::serviceMatching( "IOMedia" ); 663 astring = OSString::withCStringNoCopy("Apple_HFS"); 664 if ( astring ) { 665 matching->setObject("Content", astring); 666 astring->release(); 667 } 668 } 669 670 if( true && matching) { 671 OSSerialize * s = OSSerialize::withCapacity( 5 ); 672 673 if( matching->serialize( s )) { 674 IOLog( "Waiting on %s\n", s->text() ); 675 s->release(); 676 } 677 } 678 679 do { 680 t.tv_sec = ROOTDEVICETIMEOUT; 681 t.tv_nsec = 0; 682 matching->retain(); 683 service = IOService::waitForService( matching, &t ); 684 if( (!service) || (mountAttempts == 10)) { 685 PE_display_icon( 0, "noroot"); 686 IOLog( "Still waiting for root device\n" ); 687 688 if( !debugInfoPrintedOnce) { 689 debugInfoPrintedOnce = true; 690 if( gIOKitDebug & kIOLogDTree) { 691 IOLog("\nDT plane:\n"); 692 IOPrintPlane( gIODTPlane ); 693 } 694 if( gIOKitDebug & kIOLogServiceTree) { 695 IOLog("\nService plane:\n"); 696 IOPrintPlane( gIOServicePlane ); 697 } 698 if( gIOKitDebug & kIOLogMemory) 699 IOPrintMemory(); 700 } 701 } 702 } while( !service); 703 matching->release(); 704 705 if ( service && findHFSChild ) { 706 bool waiting = true; 707 // wait for children services to finish registering 708 while ( waiting ) { 709 t.tv_sec = ROOTDEVICETIMEOUT; 710 t.tv_nsec = 0; 711 if ( service->waitQuiet( &t ) == kIOReturnSuccess ) { 712 waiting = false; 713 } else { 714 IOLog( "Waiting for child registration\n" ); 715 } 716 } 717 // look for a subservice with an Apple_HFS child 718 IOService * subservice = IOFindMatchingChild( service ); 719 if ( subservice ) service = subservice; 720 } else if ( service && mediaProperty ) { 721 service = (IOService *)service->getProperty(mediaProperty); 722 } 723 724 mjr = 0; 725 mnr = 0; 726 727 // If the IOService we matched to is a subclass of IONetworkInterface, 728 // then make sure it has been registered with BSD and has a BSD name 729 // assigned. 730 731 if ( service 732 && service->metaCast( "IONetworkInterface" ) 733 && !IORegisterNetworkInterface( service ) ) 734 { 735 service = 0; 736 } 737 738 if( service) { 739 740 len = kMaxPathBuf; 741 service->getPath( str, &len, gIOServicePlane ); 742 IOLog( "Got boot device = %s\n", str ); 743 744 iostr = (OSString *) service->getProperty( kIOBSDNameKey ); 745 if( iostr) 746 strlcpy( rootName, iostr->getCStringNoCopy(), rootNameSize ); 747 off = (OSNumber *) service->getProperty( kIOBSDMajorKey ); 748 if( off) 749 mjr = off->unsigned32BitValue(); 750 off = (OSNumber *) service->getProperty( kIOBSDMinorKey ); 751 if( off) 752 mnr = off->unsigned32BitValue(); 753 754 if( service->metaCast( "IONetworkInterface" )) 755 flags |= 1; 756 757 } else { 758 759 IOLog( "Wait for root failed\n" ); 760 strlcpy( rootName, "en0", rootNameSize ); 761 flags |= 1; 762 } 763 764 IOLog( "BSD root: %s", rootName ); 765 if( mjr) 766 IOLog(", major %d, minor %d\n", mjr, mnr ); 767 else 768 IOLog("\n"); 769 770 *root = makedev( mjr, mnr ); 771 *oflags = flags; 772 773 IOFree( str, kMaxPathBuf + kMaxBootVar ); 774 775iofrootx: 776 if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) { 777 778 IOService::getPlatform()->waitQuiet(); 779 if( gIOKitDebug & kIOLogDTree) { 780 IOLog("\nDT plane:\n"); 781 IOPrintPlane( gIODTPlane ); 782 } 783 if( gIOKitDebug & kIOLogServiceTree) { 784 IOLog("\nService plane:\n"); 785 IOPrintPlane( gIOServicePlane ); 786 } 787 if( gIOKitDebug & kIOLogMemory) 788 IOPrintMemory(); 789 } 790 791 return( kIOReturnSuccess ); 792} 793 794void IOSecureBSDRoot(const char * rootName) 795{ 796#if CONFIG_EMBEDDED 797 IOReturn result; 798 IOPlatformExpert *pe; 799 const OSSymbol *functionName = OSSymbol::withCStringNoCopy("SecureRootName"); 800 801 while ((pe = IOService::getPlatform()) == 0) IOSleep(1 * 1000); 802 803 // Returns kIOReturnNotPrivileged is the root device is not secure. 804 // Returns kIOReturnUnsupported if "SecureRootName" is not implemented. 805 result = pe->callPlatformFunction(functionName, false, (void *)rootName, (void *)0, (void *)0, (void *)0); 806 807 functionName->release(); 808 809 if (result == kIOReturnNotPrivileged) mdevremoveall(); 810#endif 811} 812 813void * 814IOBSDRegistryEntryForDeviceTree(char * path) 815{ 816 return (IORegistryEntry::fromPath(path, gIODTPlane)); 817} 818 819void 820IOBSDRegistryEntryRelease(void * entry) 821{ 822 IORegistryEntry * regEntry = (IORegistryEntry *)entry; 823 824 if (regEntry) 825 regEntry->release(); 826 return; 827} 828 829const void * 830IOBSDRegistryEntryGetData(void * entry, char * property_name, 831 int * packet_length) 832{ 833 OSData * data; 834 IORegistryEntry * regEntry = (IORegistryEntry *)entry; 835 836 data = (OSData *) regEntry->getProperty(property_name); 837 if (data) { 838 *packet_length = data->getLength(); 839 return (data->getBytesNoCopy()); 840 } 841 return (NULL); 842} 843 844kern_return_t IOBSDGetPlatformUUID( uuid_t uuid, mach_timespec_t timeout ) 845{ 846 IOService * resources; 847 OSString * string; 848 849 resources = IOService::waitForService( IOService::resourceMatching( kIOPlatformUUIDKey ), &timeout ); 850 if ( resources == 0 ) return KERN_OPERATION_TIMED_OUT; 851 852 string = ( OSString * ) IOService::getPlatform( )->getProvider( )->getProperty( kIOPlatformUUIDKey ); 853 if ( string == 0 ) return KERN_NOT_SUPPORTED; 854 855 uuid_parse( string->getCStringNoCopy( ), uuid ); 856 857 return KERN_SUCCESS; 858} 859 860 861int IOBSDIsMediaEjectable( const char *cdev_name ) 862{ 863 int ret = 0; 864 OSDictionary *dictionary; 865 OSString *dev_name; 866 867 if (strncmp(cdev_name, "/dev/", 5) == 0) { 868 cdev_name += 5; 869 } 870 871 dictionary = IOService::serviceMatching( "IOMedia" ); 872 if( dictionary ) { 873 dev_name = OSString::withCString( cdev_name ); 874 if( dev_name ) { 875 IOService *service; 876 mach_timespec_t tv = { 5, 0 }; // wait up to "timeout" seconds for the device 877 878 dictionary->setObject( kIOBSDNameKey, dev_name ); 879 dictionary->retain(); 880 service = IOService::waitForService( dictionary, &tv ); 881 if( service ) { 882 OSBoolean *ejectable = (OSBoolean *) service->getProperty( "Ejectable" ); 883 884 if( ejectable ) { 885 ret = (int)ejectable->getValue(); 886 } 887 888 } 889 dev_name->release(); 890 } 891 dictionary->release(); 892 } 893 894 return ret; 895} 896 897} /* extern "C" */ 898