The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/bsddev/IOKitBSDInit.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1998-2011 Apple 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/IOCatalogue.h>
   32 #include <IOKit/IODeviceTreeSupport.h>
   33 #include <IOKit/IOKitKeys.h>
   34 #include <IOKit/IOPlatformExpert.h>
   35 
   36 extern "C" {
   37 
   38 #include <pexpert/pexpert.h>
   39 #include <kern/clock.h>
   40 #include <uuid/uuid.h>
   41 
   42 // how long to wait for matching root device, secs
   43 #if DEBUG
   44 #define ROOTDEVICETIMEOUT       120
   45 #else
   46 #define ROOTDEVICETIMEOUT       60
   47 #endif
   48 
   49 extern dev_t mdevadd(int devid, uint64_t base, unsigned int size, int phys);
   50 extern dev_t mdevlookup(int devid);
   51 extern void mdevremoveall(void);
   52 extern void di_root_ramfile(IORegistryEntry * entry);
   53 
   54 kern_return_t
   55 IOKitBSDInit( void )
   56 {
   57     IOService::publishResource("IOBSD");
   58 
   59     return( kIOReturnSuccess );
   60 }
   61 
   62 void
   63 IOServicePublishResource( const char * property, boolean_t value )
   64 {
   65     if ( value)
   66         IOService::publishResource( property, kOSBooleanTrue );
   67     else
   68         IOService::getResourceService()->removeProperty( property );
   69 }
   70 
   71 boolean_t
   72 IOServiceWaitForMatchingResource( const char * property, uint64_t timeout )
   73 {
   74     OSDictionary *      dict = 0;
   75     IOService *         match = 0;
   76     boolean_t           found = false;
   77     
   78     do {
   79         
   80         dict = IOService::resourceMatching( property );
   81         if( !dict)
   82             continue;
   83         match = IOService::waitForMatchingService( dict, timeout );
   84         if ( match)
   85             found = true;
   86         
   87     } while( false );
   88     
   89     if( dict)
   90         dict->release();
   91     if( match)
   92         match->release();
   93     
   94     return( found );
   95 }
   96 
   97 boolean_t
   98 IOCatalogueMatchingDriversPresent( const char * property )
   99 {
  100     OSDictionary *      dict = 0;
  101     OSOrderedSet *      set = 0;
  102     SInt32              generationCount = 0;
  103     boolean_t           found = false;
  104     
  105     do {
  106         
  107         dict = OSDictionary::withCapacity(1);
  108         if( !dict)
  109             continue;
  110         dict->setObject( property, kOSBooleanTrue );
  111         set = gIOCatalogue->findDrivers( dict, &generationCount );
  112         if ( set && (set->getCount() > 0))
  113             found = true;
  114         
  115     } while( false );
  116     
  117     if( dict)
  118         dict->release();
  119     if( set)
  120         set->release();
  121     
  122     return( found );
  123 }
  124 
  125 OSDictionary * IOBSDNameMatching( const char * name )
  126 {
  127     OSDictionary *      dict;
  128     const OSSymbol *    str = 0;
  129 
  130     do {
  131 
  132         dict = IOService::serviceMatching( gIOServiceKey );
  133         if( !dict)
  134             continue;
  135         str = OSSymbol::withCString( name );
  136         if( !str)
  137             continue;
  138         dict->setObject( kIOBSDNameKey, (OSObject *) str );
  139         str->release();
  140 
  141         return( dict );
  142 
  143     } while( false );
  144 
  145     if( dict)
  146         dict->release();
  147     if( str)
  148         str->release();
  149 
  150     return( 0 );
  151 }
  152 
  153 OSDictionary * IOUUIDMatching( void )
  154 {
  155     return IOService::resourceMatching( "boot-uuid-media" );
  156 }
  157 
  158 OSDictionary * IONetworkNamePrefixMatching( const char * prefix )
  159 {
  160     OSDictionary *       matching;
  161     OSDictionary *   propDict = 0;
  162     const OSSymbol * str      = 0;
  163         char networkType[128];
  164         
  165     do {
  166         matching = IOService::serviceMatching( "IONetworkInterface" );
  167         if ( matching == 0 )
  168             continue;
  169 
  170         propDict = OSDictionary::withCapacity(1);
  171         if ( propDict == 0 )
  172             continue;
  173 
  174         str = OSSymbol::withCString( prefix );
  175         if ( str == 0 )
  176             continue;
  177 
  178         propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str );
  179         str->release();
  180         str = 0;
  181 
  182                 // see if we're contrained to netroot off of specific network type
  183                 if(PE_parse_boot_argn( "network-type", networkType, 128 ))
  184                 {
  185                         str = OSSymbol::withCString( networkType );
  186                         if(str)
  187                         {
  188                                 propDict->setObject( "IONetworkRootType", str);
  189                                 str->release();
  190                                 str = 0;
  191                         }
  192                 }
  193 
  194         if ( matching->setObject( gIOPropertyMatchKey,
  195                                   (OSObject *) propDict ) != true )
  196             continue;
  197 
  198         propDict->release();
  199         propDict = 0;
  200 
  201         return( matching );
  202 
  203     } while ( false );
  204 
  205     if ( matching ) matching->release();
  206     if ( propDict ) propDict->release();
  207     if ( str      ) str->release();
  208 
  209     return( 0 );
  210 }
  211 
  212 static bool IORegisterNetworkInterface( IOService * netif )
  213 {
  214     // A network interface is typically named and registered
  215     // with BSD after receiving a request from a user space
  216     // "namer". However, for cases when the system needs to
  217     // root from the network, this registration task must be
  218     // done inside the kernel and completed before the root
  219     // device is handed to BSD.
  220 
  221     IOService *    stack;
  222     OSNumber *     zero    = 0;
  223     OSString *     path    = 0;
  224     OSDictionary * dict    = 0;
  225     char *         pathBuf = 0;
  226     int            len;
  227     enum { kMaxPathLen = 512 };
  228 
  229     do {
  230         stack = IOService::waitForService(
  231                 IOService::serviceMatching("IONetworkStack") );
  232         if ( stack == 0 ) break;
  233 
  234         dict = OSDictionary::withCapacity(3);
  235         if ( dict == 0 ) break;
  236 
  237         zero = OSNumber::withNumber((UInt64) 0, 32);
  238         if ( zero == 0 ) break;
  239 
  240         pathBuf = (char *) IOMalloc( kMaxPathLen );
  241         if ( pathBuf == 0 ) break;
  242 
  243         len = kMaxPathLen;
  244         if ( netif->getPath( pathBuf, &len, gIOServicePlane )
  245              == false ) break;
  246 
  247         path = OSString::withCStringNoCopy( pathBuf );
  248         if ( path == 0 ) break;
  249 
  250         dict->setObject( "IOInterfaceUnit", zero );
  251         dict->setObject( kIOPathMatchKey,   path );
  252 
  253         stack->setProperties( dict );
  254     }
  255     while ( false );
  256 
  257     if ( zero ) zero->release();
  258     if ( path ) path->release();
  259     if ( dict ) dict->release();
  260     if ( pathBuf ) IOFree(pathBuf, kMaxPathLen);
  261 
  262         return ( netif->getProperty( kIOBSDNameKey ) != 0 );
  263 }
  264 
  265 OSDictionary * IOOFPathMatching( const char * path, char * buf, int maxLen )
  266 {
  267     OSDictionary *      matching;
  268     OSString *          str;
  269     char *              comp;
  270     int                 len;
  271 
  272     do {
  273 
  274         len = strlen( kIODeviceTreePlane ":" );
  275         maxLen -= len;
  276         if( maxLen <= 0)
  277             continue;
  278 
  279         strlcpy( buf, kIODeviceTreePlane ":", len + 1 );
  280         comp = buf + len;
  281 
  282         len = strlen( path );
  283         maxLen -= len;
  284         if( maxLen <= 0)
  285             continue;
  286         strlcpy( comp, path, len + 1 );
  287 
  288         matching = OSDictionary::withCapacity( 1 );
  289         if( !matching)
  290             continue;
  291 
  292         str = OSString::withCString( buf );
  293         if( !str)
  294             continue;
  295         matching->setObject( kIOPathMatchKey, str );
  296         str->release();
  297 
  298         return( matching );
  299 
  300     } while( false );
  301 
  302     if( matching)
  303         matching->release();
  304 
  305     return( 0 );
  306 }
  307 
  308 static int didRam = 0;
  309 
  310 kern_return_t IOFindBSDRoot( char * rootName, unsigned int rootNameSize,
  311                                 dev_t * root, u_int32_t * oflags )
  312 {
  313     mach_timespec_t     t;
  314     IOService *         service;
  315     IORegistryEntry *   regEntry;
  316     OSDictionary *      matching = 0;
  317     OSString *          iostr;
  318     OSNumber *          off;
  319     OSData *            data = 0;
  320 
  321     UInt32              flags = 0;
  322     int                 mnr, mjr;
  323     const char *        mediaProperty = 0;
  324     char *              rdBootVar;
  325     enum {              kMaxPathBuf = 512, kMaxBootVar = 128 };
  326     char *              str;
  327     const char *        look = 0;
  328     int                 len;
  329     bool                debugInfoPrintedOnce = false;
  330     const char *        uuidStr = NULL;
  331 
  332     static int          mountAttempts = 0;
  333                                 
  334     int xchar, dchar;
  335                                     
  336 
  337     if( mountAttempts++)
  338         IOSleep( 5 * 1000 );
  339 
  340     str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar );
  341     if( !str)
  342         return( kIOReturnNoMemory );
  343     rdBootVar = str + kMaxPathBuf;
  344 
  345     if (!PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar )
  346      && !PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar ))
  347         rdBootVar[0] = 0;
  348 
  349     do {
  350         if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) {
  351             di_root_ramfile(regEntry);
  352             data = OSDynamicCast(OSData, regEntry->getProperty( "root-matching" ));
  353             if (data) {
  354                matching = OSDynamicCast(OSDictionary, OSUnserializeXML((char *)data->getBytesNoCopy()));
  355                 if (matching) {
  356                     continue;
  357                 }
  358             }
  359 
  360             data = (OSData *) regEntry->getProperty( "boot-uuid" );
  361             if( data) {
  362                 uuidStr = (const char*)data->getBytesNoCopy();
  363                 OSString *uuidString = OSString::withCString( uuidStr );
  364 
  365                 // match the boot-args boot-uuid processing below
  366                 if( uuidString) {
  367                     IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr);
  368                     IOService::publishResource( "boot-uuid", uuidString );
  369                     uuidString->release();
  370                     matching = IOUUIDMatching();
  371                     mediaProperty = "boot-uuid-media";
  372                     regEntry->release();
  373                     continue;
  374                 } else {
  375                     uuidStr = NULL;
  376                 }
  377             }
  378             regEntry->release();
  379         }
  380     } while( false );
  381 
  382 //
  383 //      See if we have a RAMDisk property in /chosen/memory-map.  If so, make it into a device.
  384 //      It will become /dev/mdx, where x is 0-f. 
  385 //
  386 
  387         if(!didRam) {                                                                                           /* Have we already build this ram disk? */
  388                 didRam = 1;                                                                                             /* Remember we did this */
  389                 if((regEntry = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ))) {        /* Find the map node */
  390                         data = (OSData *)regEntry->getProperty("RAMDisk");      /* Find the ram disk, if there */
  391                         if(data) {                                                                                      /* We found one */
  392                                 UInt32          *ramdParms = 0;
  393                                 ramdParms = (UInt32 *)data->getBytesNoCopy();   /* Point to the ram disk base and size */
  394                                 (void)mdevadd(-1, ml_static_ptovirt(ramdParms[0]) >> 12, ramdParms[1] >> 12, 0);        /* Initialize it and pass back the device number */
  395                         }
  396                         regEntry->release();                                                            /* Toss the entry */
  397                 }
  398         }
  399         
  400 //
  401 //      Now check if we are trying to root on a memory device
  402 //
  403 
  404         if((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) {
  405                 dchar = xchar = rdBootVar[2];                                                   /* Get the actual device */
  406                 if((xchar >= '') && (xchar <= '9')) xchar = xchar - '';       /* If digit, convert */
  407                 else {
  408                         xchar = xchar & ~' ';                                                           /* Fold to upper case */
  409                         if((xchar >= 'A') && (xchar <= 'F')) {                          /* Is this a valid digit? */
  410                                 xchar = (xchar & 0xF) + 9;                                              /* Convert the hex digit */
  411                                 dchar = dchar | ' ';                                                    /* Fold to lower case */
  412                         }
  413                         else xchar = -1;                                                                        /* Show bogus */
  414                 }
  415                 if(xchar >= 0) {                                                                                /* Do we have a valid memory device name? */
  416                         *root = mdevlookup(xchar);                                                      /* Find the device number */
  417                         if(*root >= 0) {                                                                        /* Did we find one? */
  418 
  419                                 rootName[0] = 'm';                                                              /* Build root name */
  420                                 rootName[1] = 'd';                                                              /* Build root name */
  421                                 rootName[2] = dchar;                                                    /* Build root name */
  422                                 rootName[3] = 0;                                                                /* Build root name */
  423                                 IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root));
  424                                 *oflags = 0;                                                                    /* Show that this is not network */
  425                                 goto iofrootx;                                                                  /* Join common exit... */
  426                         }
  427                         panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar); /* Not there */
  428                 }
  429         }
  430 
  431       if( (!matching) && rdBootVar[0] ) {
  432         // by BSD name
  433         look = rdBootVar;
  434         if( look[0] == '*')
  435             look++;
  436     
  437         if ( strncmp( look, "en", strlen( "en" )) == 0 ) {
  438             matching = IONetworkNamePrefixMatching( "en" );
  439         } else if ( strncmp( look, "uuid", strlen( "uuid" )) == 0 ) {
  440             char *uuid;
  441             OSString *uuidString;
  442 
  443             uuid = (char *)IOMalloc( kMaxBootVar );
  444                   
  445             if ( uuid ) {
  446                 if (!PE_parse_boot_argn( "boot-uuid", uuid, kMaxBootVar )) {
  447                     panic( "rd=uuid but no boot-uuid=<value> specified" ); 
  448                 } 
  449                 uuidString = OSString::withCString( uuid );
  450                 if ( uuidString ) {
  451                     IOService::publishResource( "boot-uuid", uuidString );
  452                     uuidString->release();
  453                     IOLog( "\nWaiting for boot volume with UUID %s\n", uuid );
  454                     matching = IOUUIDMatching();
  455                     mediaProperty = "boot-uuid-media";
  456                 }
  457                 IOFree( uuid, kMaxBootVar );
  458             }
  459         } else {
  460             matching = IOBSDNameMatching( look );
  461         }
  462     }
  463 
  464     if( !matching) {
  465         OSString * astring;
  466         // Match any HFS media
  467         
  468         matching = IOService::serviceMatching( "IOMedia" );
  469         astring = OSString::withCStringNoCopy("Apple_HFS");
  470         if ( astring ) {
  471             matching->setObject("Content", astring);
  472             astring->release();
  473         }
  474     }
  475 
  476     if( true && matching) {
  477         OSSerialize * s = OSSerialize::withCapacity( 5 );
  478 
  479         if( matching->serialize( s )) {
  480             IOLog( "Waiting on %s\n", s->text() );
  481             s->release();
  482         }
  483     }
  484 
  485     do {
  486         t.tv_sec = ROOTDEVICETIMEOUT;
  487         t.tv_nsec = 0;
  488         matching->retain();
  489         service = IOService::waitForService( matching, &t );
  490         if( (!service) || (mountAttempts == 10)) {
  491             PE_display_icon( 0, "noroot");
  492             IOLog( "Still waiting for root device\n" );
  493 
  494             if( !debugInfoPrintedOnce) {
  495                 debugInfoPrintedOnce = true;
  496                 if( gIOKitDebug & kIOLogDTree) {
  497                     IOLog("\nDT plane:\n");
  498                     IOPrintPlane( gIODTPlane );
  499                 }
  500                 if( gIOKitDebug & kIOLogServiceTree) {
  501                     IOLog("\nService plane:\n");
  502                     IOPrintPlane( gIOServicePlane );
  503                 }
  504                 if( gIOKitDebug & kIOLogMemory)
  505                     IOPrintMemory();
  506             }
  507         }
  508     } while( !service);
  509     matching->release();
  510 
  511     if ( service && mediaProperty ) {
  512         service = (IOService *)service->getProperty(mediaProperty);
  513     }
  514 
  515     mjr = 0;
  516     mnr = 0;
  517 
  518     // If the IOService we matched to is a subclass of IONetworkInterface,
  519     // then make sure it has been registered with BSD and has a BSD name
  520     // assigned.
  521 
  522     if ( service
  523     &&   service->metaCast( "IONetworkInterface" )
  524     &&   !IORegisterNetworkInterface( service ) )
  525     {
  526         service = 0;
  527     }
  528 
  529     if( service) {
  530 
  531         len = kMaxPathBuf;
  532         service->getPath( str, &len, gIOServicePlane );
  533         IOLog( "Got boot device = %s\n", str );
  534 
  535         iostr = (OSString *) service->getProperty( kIOBSDNameKey );
  536         if( iostr)
  537             strlcpy( rootName, iostr->getCStringNoCopy(), rootNameSize );
  538         off = (OSNumber *) service->getProperty( kIOBSDMajorKey );
  539         if( off)
  540             mjr = off->unsigned32BitValue();
  541         off = (OSNumber *) service->getProperty( kIOBSDMinorKey );
  542         if( off)
  543             mnr = off->unsigned32BitValue();
  544 
  545         if( service->metaCast( "IONetworkInterface" ))
  546             flags |= 1;
  547 
  548     } else {
  549 
  550         IOLog( "Wait for root failed\n" );
  551         strlcpy( rootName, "en0", rootNameSize );
  552         flags |= 1;
  553     }
  554 
  555     IOLog( "BSD root: %s", rootName );
  556     if( mjr)
  557         IOLog(", major %d, minor %d\n", mjr, mnr );
  558     else
  559         IOLog("\n");
  560 
  561     *root = makedev( mjr, mnr );
  562     *oflags = flags;
  563 
  564     IOFree( str,  kMaxPathBuf + kMaxBootVar );
  565 
  566 iofrootx:
  567     if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) {
  568 
  569         IOService::getPlatform()->waitQuiet();
  570         if( gIOKitDebug & kIOLogDTree) {
  571             IOLog("\nDT plane:\n");
  572             IOPrintPlane( gIODTPlane );
  573         }
  574         if( gIOKitDebug & kIOLogServiceTree) {
  575             IOLog("\nService plane:\n");
  576             IOPrintPlane( gIOServicePlane );
  577         }
  578         if( gIOKitDebug & kIOLogMemory)
  579             IOPrintMemory();
  580     }
  581 
  582     return( kIOReturnSuccess );
  583 }
  584 
  585 void IOSecureBSDRoot(const char * rootName)
  586 {
  587 #if CONFIG_EMBEDDED
  588     IOReturn         result;
  589     IOPlatformExpert *pe;
  590     const OSSymbol   *functionName = OSSymbol::withCStringNoCopy("SecureRootName");
  591     
  592     while ((pe = IOService::getPlatform()) == 0) IOSleep(1 * 1000);
  593     
  594     // Returns kIOReturnNotPrivileged is the root device is not secure.
  595     // Returns kIOReturnUnsupported if "SecureRootName" is not implemented.
  596     result = pe->callPlatformFunction(functionName, false, (void *)rootName, (void *)0, (void *)0, (void *)0);
  597     
  598     functionName->release();
  599     
  600     if (result == kIOReturnNotPrivileged) mdevremoveall();
  601 #endif
  602 }
  603 
  604 void *
  605 IOBSDRegistryEntryForDeviceTree(char * path)
  606 {
  607     return (IORegistryEntry::fromPath(path, gIODTPlane));
  608 }
  609 
  610 void
  611 IOBSDRegistryEntryRelease(void * entry)
  612 {
  613     IORegistryEntry * regEntry = (IORegistryEntry *)entry;
  614 
  615     if (regEntry)
  616         regEntry->release();
  617     return;
  618 }
  619 
  620 const void *
  621 IOBSDRegistryEntryGetData(void * entry, char * property_name, 
  622                           int * packet_length)
  623 {
  624     OSData *            data;
  625     IORegistryEntry *   regEntry = (IORegistryEntry *)entry;
  626 
  627     data = (OSData *) regEntry->getProperty(property_name);
  628     if (data) {
  629         *packet_length = data->getLength();
  630         return (data->getBytesNoCopy());
  631     }
  632     return (NULL);
  633 }
  634 
  635 kern_return_t IOBSDGetPlatformUUID( uuid_t uuid, mach_timespec_t timeout )
  636 {
  637     IOService * resources;
  638     OSString *  string;
  639 
  640     resources = IOService::waitForService( IOService::resourceMatching( kIOPlatformUUIDKey ), ( timeout.tv_sec || timeout.tv_nsec ) ? &timeout : 0 );
  641     if ( resources == 0 ) return KERN_OPERATION_TIMED_OUT;
  642 
  643     string = ( OSString * ) IOService::getPlatform( )->getProvider( )->getProperty( kIOPlatformUUIDKey );
  644     if ( string == 0 ) return KERN_NOT_SUPPORTED;
  645 
  646     uuid_parse( string->getCStringNoCopy( ), uuid );
  647 
  648     return KERN_SUCCESS;
  649 }
  650 
  651 kern_return_t IOBSDGetPlatformSerialNumber( char *serial_number_str, u_int32_t len )
  652 {
  653     OSDictionary * platform_dict;
  654     IOService *platform;
  655     OSString *  string;
  656 
  657     if (len < 1) {
  658             return 0;
  659     }
  660     serial_number_str[0] = '\0';
  661 
  662     platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" );
  663     if (platform_dict == NULL) {
  664             return KERN_NOT_SUPPORTED;
  665     }
  666 
  667     platform = IOService::waitForService( platform_dict );
  668     if (platform) {
  669             string = ( OSString * ) platform->getProperty( kIOPlatformSerialNumberKey );
  670             if ( string == 0 ) {
  671                     return KERN_NOT_SUPPORTED;
  672             } else {
  673                     strlcpy( serial_number_str, string->getCStringNoCopy( ), len );
  674             }
  675     }
  676     
  677     return KERN_SUCCESS;
  678 }
  679 
  680 dev_t IOBSDGetMediaWithUUID( const char *uuid_cstring, char *bsd_name, int bsd_name_len, int timeout)
  681 {
  682     dev_t dev = 0;
  683     OSDictionary *dictionary;
  684     OSString *uuid_string;
  685 
  686     if (bsd_name_len < 1) {
  687         return 0;
  688     }
  689     bsd_name[0] = '\0';
  690     
  691     dictionary = IOService::serviceMatching( "IOMedia" );
  692     if( dictionary ) {
  693         uuid_string = OSString::withCString( uuid_cstring );
  694         if( uuid_string ) {
  695             IOService *service;
  696             mach_timespec_t tv = { timeout, 0 };    // wait up to "timeout" seconds for the device
  697 
  698             dictionary->setObject( "UUID", uuid_string );
  699             dictionary->retain();
  700             service = IOService::waitForService( dictionary, &tv );
  701             if( service ) {
  702                 OSNumber *dev_major = (OSNumber *) service->getProperty( kIOBSDMajorKey );
  703                 OSNumber *dev_minor = (OSNumber *) service->getProperty( kIOBSDMinorKey );
  704                 OSString *iostr = (OSString *) service->getProperty( kIOBSDNameKey );
  705 
  706                 if( iostr)
  707                     strlcpy( bsd_name, iostr->getCStringNoCopy(), bsd_name_len );
  708 
  709                 if ( dev_major && dev_minor )
  710                     dev = makedev( dev_major->unsigned32BitValue(), dev_minor->unsigned32BitValue() );
  711             }
  712             uuid_string->release();
  713         }
  714         dictionary->release();
  715     }
  716 
  717     return dev;
  718 }
  719 
  720 
  721 void IOBSDIterateMediaWithContent(const char *content_uuid_cstring, int (*func)(const char *bsd_dev_name, const char *uuid_str, void *arg), void *arg)
  722 {
  723     OSDictionary *dictionary;
  724     OSString *content_uuid_string;
  725 
  726     dictionary = IOService::serviceMatching( "IOMedia" );
  727     if( dictionary ) {
  728         content_uuid_string = OSString::withCString( content_uuid_cstring );
  729         if( content_uuid_string ) {
  730             IOService *service;
  731             OSIterator *iter;
  732 
  733             dictionary->setObject( "Content", content_uuid_string );
  734             dictionary->retain();
  735 
  736             iter = IOService::getMatchingServices(dictionary);
  737             while (iter && (service = (IOService *)iter->getNextObject())) {
  738                     if( service ) {
  739                             OSString *iostr = (OSString *) service->getProperty( kIOBSDNameKey );
  740                             OSString *uuidstr = (OSString *) service->getProperty( "UUID" );
  741                             const char *uuid;
  742 
  743                             if( iostr) {
  744                                     if (uuidstr) {
  745                                             uuid = uuidstr->getCStringNoCopy();
  746                                     } else {
  747                                             uuid = "00000000-0000-0000-0000-000000000000";
  748                                     }
  749 
  750                                     // call the callback
  751                                     if (func && func(iostr->getCStringNoCopy(), uuid, arg) == 0) {
  752                                             break;
  753                                     }
  754                             }
  755                     }
  756             }
  757             if (iter)
  758                     iter->release();
  759             
  760             content_uuid_string->release();
  761         }
  762         dictionary->release();
  763     }
  764 }
  765 
  766 
  767 int IOBSDIsMediaEjectable( const char *cdev_name )
  768 {
  769     int ret = 0;
  770     OSDictionary *dictionary;
  771     OSString *dev_name;
  772 
  773     if (strncmp(cdev_name, "/dev/", 5) == 0) {
  774             cdev_name += 5;
  775     }
  776 
  777     dictionary = IOService::serviceMatching( "IOMedia" );
  778     if( dictionary ) {
  779         dev_name = OSString::withCString( cdev_name );
  780         if( dev_name ) {
  781             IOService *service;
  782             mach_timespec_t tv = { 5, 0 };    // wait up to "timeout" seconds for the device
  783 
  784             dictionary->setObject( kIOBSDNameKey, dev_name );
  785             dictionary->retain();
  786             service = IOService::waitForService( dictionary, &tv );
  787             if( service ) {
  788                 OSBoolean *ejectable = (OSBoolean *) service->getProperty( "Ejectable" );
  789 
  790                 if( ejectable ) {
  791                         ret = (int)ejectable->getValue();
  792                 }
  793 
  794             }
  795             dev_name->release();
  796         }
  797         dictionary->release();
  798     }
  799 
  800     return ret;
  801 }
  802 
  803 } /* extern "C" */

Cache object: 8d4e6c4a3c9dc3c5af99c8d211173a0b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.