]>
git.saurik.com Git - apple/xnu.git/blob - iokit/bsddev/IOKitBSDInit.cpp
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
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/IOPlatformExpert.h>
29 #include <sys/disklabel.h>
33 #include <pexpert/pexpert.h>
34 #include <kern/clock.h>
36 // how long to wait for matching root device, secs
37 #define ROOTDEVICETIMEOUT 60
43 IOLog("IOKitBSDInit\n");
45 IOService::publishResource("IOBSD");
47 return( kIOReturnSuccess
);
50 OSDictionary
* IOBSDNameMatching( const char * name
)
53 const OSSymbol
* str
= 0;
57 dict
= IOService::serviceMatching( gIOServiceKey
);
60 str
= OSSymbol::withCString( name
);
63 dict
->setObject( kIOBSDNameKey
, (OSObject
*) str
);
78 OSDictionary
* IOCDMatching( const char * name
)
83 dict
= IOService::serviceMatching( "IOMedia" );
85 IOLog("Unable to find IOMedia\n");
89 str
= OSSymbol::withCString( "CD_ROM_Mode_1" );
95 dict
->setObject( "Content", (OSObject
*)str
);
100 OSDictionary
* IONetworkMatching( const char * path
,
101 char * buf
, int maxLen
)
103 OSDictionary
* matching
= 0;
112 len
= strlen( kIODeviceTreePlane
":" );
117 strcpy( buf
, kIODeviceTreePlane
":" );
120 // remove parameters following ':' from the path
121 skip
= strchr( path
, ':');
129 strncpy( comp
, path
, len
);
132 matching
= IOService::serviceMatching( "IONetworkInterface" );
135 dict
= IOService::addLocation( matching
);
139 str
= OSString::withCString( buf
);
142 dict
->setObject( kIOPathMatchKey
, str
);
155 OSDictionary
* IONetworkNamePrefixMatching( const char * prefix
)
157 OSDictionary
* matching
;
158 OSDictionary
* propDict
= 0;
159 const OSSymbol
* str
= 0;
162 matching
= IOService::serviceMatching( "IONetworkInterface" );
166 propDict
= OSDictionary::withCapacity(1);
170 str
= OSSymbol::withCString( prefix
);
174 propDict
->setObject( "IOInterfaceNamePrefix", (OSObject
*) str
);
178 if ( matching
->setObject( gIOPropertyMatchKey
,
179 (OSObject
*) propDict
) != true )
189 if ( matching
) matching
->release();
190 if ( propDict
) propDict
->release();
191 if ( str
) str
->release();
196 static bool IORegisterNetworkInterface( IOService
* netif
)
198 // A network interface is typically named and registered
199 // with BSD after receiving a request from a user space
200 // "namer". However, for cases when the system needs to
201 // root from the network, this registration task must be
202 // done inside the kernel and completed before the root
203 // device is handed to BSD.
208 OSDictionary
* dict
= 0;
211 enum { kMaxPathLen
= 512 };
214 stack
= IOService::waitForService(
215 IOService::serviceMatching("IONetworkStack") );
216 if ( stack
== 0 ) break;
218 dict
= OSDictionary::withCapacity(3);
219 if ( dict
== 0 ) break;
221 zero
= OSNumber::withNumber((UInt64
) 0, 32);
222 if ( zero
== 0 ) break;
224 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
225 if ( pathBuf
== 0 ) break;
228 if ( netif
->getPath( pathBuf
, &len
, gIOServicePlane
)
231 path
= OSString::withCStringNoCopy( pathBuf
);
232 if ( path
== 0 ) break;
234 dict
->setObject( "IOInterfaceUnit", zero
);
235 dict
->setObject( kIOPathMatchKey
, path
);
237 stack
->setProperties( dict
);
241 if ( zero
) zero
->release();
242 if ( path
) path
->release();
243 if ( dict
) dict
->release();
244 if ( pathBuf
) IOFree(pathBuf
, kMaxPathLen
);
246 return ( netif
->getProperty( kIOBSDNameKey
) != 0 );
249 OSDictionary
* IODiskMatching( const char * path
, char * buf
, int maxLen
)
258 // scan the tail of the path for "@unit:partition"
260 // Have to get the full path to the controller - an alias may
261 // tell us next to nothing, like "hd:8"
262 alias
= IORegistryEntry::dealiasPath( &path
, gIODTPlane
);
264 look
= path
+ strlen( path
);
266 while( look
!= path
) {
267 if( *(--look
) == c
) {
269 partition
= strtol( look
+ 1, 0, 0 );
271 } else if( c
== '@') {
272 unit
= strtol( look
+ 1, 0, 16 );
274 } else if( c
== '/') {
280 if( alias
&& (look
== path
)) {
282 look
= path
+ strlen( path
);
286 if( c
|| unit
== -1 || partition
== -1)
289 maxLen
-= strlen( "{" kIOPathMatchKey
"='" kIODeviceTreePlane
":" );
290 maxLen
-= ( alias
? strlen( alias
) : 0 ) + (look
- path
);
291 maxLen
-= strlen( "/@hhhhhhhh:dddddddddd';}" );
294 sprintf( buf
, "{" kIOPathMatchKey
"='" kIODeviceTreePlane
":" );
295 comp
= buf
+ strlen( buf
);
298 strcpy( comp
, alias
);
299 comp
+= strlen( alias
);
302 if ( (look
- path
)) {
303 strncpy( comp
, path
, look
- path
);
307 sprintf( comp
, "/@%lx:%ld';}", unit
, partition
);
311 return( OSDynamicCast(OSDictionary
, OSUnserialize( buf
, 0 )) );
318 OSDictionary
* IOOFPathMatching( const char * path
, char * buf
, int maxLen
)
320 /* need to look up path, get device type,
321 call matching help based on device type */
323 return( IODiskMatching( path
, buf
, maxLen
));
327 kern_return_t
IOFindBSDRoot( char * rootName
,
328 dev_t
* root
, u_int32_t
* oflags
)
332 IORegistryEntry
* regEntry
;
333 OSDictionary
* matching
= 0;
341 enum { kMaxPathBuf
= 512, kMaxBootVar
= 128 };
343 const char * look
= 0;
345 bool forceNet
= false;
346 bool debugInfoPrintedOnce
= false;
348 static int mountAttempts
= 0;
353 str
= (char *) IOMalloc( kMaxPathBuf
+ kMaxBootVar
);
355 return( kIOReturnNoMemory
);
356 rdBootVar
= str
+ kMaxPathBuf
;
358 if (!PE_parse_boot_arg("rd", rdBootVar
)
359 && !PE_parse_boot_arg("rootdev", rdBootVar
))
363 if( (regEntry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
))) {
364 data
= (OSData
*) regEntry
->getProperty( "rootpath" );
369 if( (regEntry
= IORegistryEntry::fromPath( "/options", gIODTPlane
))) {
370 data
= (OSData
*) regEntry
->getProperty( "boot-file" );
378 look
= (const char *) data
->getBytesNoCopy();
380 if( rdBootVar
[0] == '*') {
381 look
= rdBootVar
+ 1;
384 if( (regEntry
= IORegistryEntry::fromPath( "/", gIODTPlane
))) {
385 forceNet
= (0 != regEntry
->getProperty( "net-boot" ));
391 // from OpenFirmware path
392 IOLog("From path: \"%s\", ", look
);
394 if( forceNet
|| (0 == strncmp( look
, "enet", strlen( "enet" ))) ) {
395 matching
= IONetworkMatching( look
, str
, kMaxPathBuf
);
397 matching
= IODiskMatching( look
, str
, kMaxPathBuf
);
401 if( (!matching
) && rdBootVar
[0] ) {
407 if ( strncmp( look
, "en", strlen( "en" )) == 0 ) {
408 matching
= IONetworkNamePrefixMatching( "en" );
409 } else if ( strncmp( look
, "cdrom", strlen( "cdrom" )) == 0 ) {
410 matching
= IOCDMatching( look
);
412 matching
= IOBSDNameMatching( look
);
419 matching
= IOService::serviceMatching( "IOMedia" );
420 astring
= OSString::withCStringNoCopy("Apple_UFS");
422 matching
->setObject("Content", astring
);
427 if( true && matching
) {
428 OSSerialize
* s
= OSSerialize::withCapacity( 5 );
430 if( matching
->serialize( s
)) {
431 IOLog( "Waiting on %s\n", s
->text() );
437 t
.tv_sec
= ROOTDEVICETIMEOUT
;
440 service
= IOService::waitForService( matching
, &t
);
441 if( (!service
) || (mountAttempts
== 10)) {
442 PE_display_icon( 0, "noroot");
443 IOLog( "Still waiting for root device\n" );
445 if( !debugInfoPrintedOnce
) {
446 debugInfoPrintedOnce
= true;
447 if( gIOKitDebug
& kIOLogDTree
) {
448 IOLog("\nDT plane:\n");
449 IOPrintPlane( gIODTPlane
);
451 if( gIOKitDebug
& kIOLogServiceTree
) {
452 IOLog("\nService plane:\n");
453 IOPrintPlane( gIOServicePlane
);
455 if( gIOKitDebug
& kIOLogMemory
)
465 // If the IOService we matched to is a subclass of IONetworkInterface,
466 // then make sure it has been registered with BSD and has a BSD name
470 && service
->metaCast( "IONetworkInterface" )
471 && !IORegisterNetworkInterface( service
) )
479 service
->getPath( str
, &len
, gIOServicePlane
);
480 IOLog( "Got boot device = %s\n", str
);
482 iostr
= (OSString
*) service
->getProperty( kIOBSDNameKey
);
484 strcpy( rootName
, iostr
->getCStringNoCopy() );
485 off
= (OSNumber
*) service
->getProperty( kIOBSDMajorKey
);
487 major
= off
->unsigned32BitValue();
488 off
= (OSNumber
*) service
->getProperty( kIOBSDMinorKey
);
490 minor
= off
->unsigned32BitValue();
492 if( service
->metaCast( "IONetworkInterface" ))
497 IOLog( "Wait for root failed\n" );
498 strcpy( rootName
, "en0");
502 IOLog( "BSD root: %s", rootName
);
504 IOLog(", major %d, minor %d\n", major
, minor
);
508 *root
= makedev( major
, minor
);
511 IOFree( str
, kMaxPathBuf
+ kMaxBootVar
);
513 if( (gIOKitDebug
& (kIOLogDTree
| kIOLogServiceTree
| kIOLogMemory
)) && !debugInfoPrintedOnce
) {
515 IOService::getPlatform()->waitQuiet();
516 if( gIOKitDebug
& kIOLogDTree
) {
517 IOLog("\nDT plane:\n");
518 IOPrintPlane( gIODTPlane
);
520 if( gIOKitDebug
& kIOLogServiceTree
) {
521 IOLog("\nService plane:\n");
522 IOPrintPlane( gIOServicePlane
);
524 if( gIOKitDebug
& kIOLogMemory
)
528 return( kIOReturnSuccess
);
532 IOBSDRegistryEntryForDeviceTree(char * path
)
534 return (IORegistryEntry::fromPath(path
, gIODTPlane
));
538 IOBSDRegistryEntryRelease(void * entry
)
540 IORegistryEntry
* regEntry
= (IORegistryEntry
*)entry
;
548 IOBSDRegistryEntryGetData(void * entry
, char * property_name
,
552 IORegistryEntry
* regEntry
= (IORegistryEntry
*)entry
;
554 data
= (OSData
*) regEntry
->getProperty(property_name
);
556 *packet_length
= data
->getLength();
557 return (data
->getBytesNoCopy());