]>
git.saurik.com Git - apple/xnu.git/blob - iokit/bsddev/IOKitBSDInit.cpp
b161dbf608157cd1c10ba21a7ecaa1949bf0c713
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/storage/IOMedia.h>
28 #include <IOKit/network/IONetworkStack.h>
29 #include <IOKit/network/IONetworkInterface.h>
30 #include <IOKit/IOPlatformExpert.h>
32 #include <sys/disklabel.h>
36 #include <pexpert/pexpert.h>
37 #include <kern/clock.h>
39 // how long to wait for matching root device, secs
40 #define ROOTDEVICETIMEOUT 60
46 IOLog("IOKitBSDInit\n");
48 IOService::publishResource("IOBSD");
50 return( kIOReturnSuccess
);
53 OSDictionary
* IOBSDNameMatching( const char * name
)
56 const OSSymbol
* str
= 0;
60 dict
= IOService::serviceMatching( gIOServiceKey
);
63 str
= OSSymbol::withCString( name
);
66 dict
->setObject( kIOBSDNameKey
, (OSObject
*) str
);
81 OSDictionary
* IONetworkMatching( const char * path
,
82 char * buf
, int maxLen
)
84 OSDictionary
* matching
= 0;
93 len
= strlen( kIODeviceTreePlane
":" );
98 strcpy( buf
, kIODeviceTreePlane
":" );
101 // remove parameters following ':' from the path
102 skip
= strchr( path
, ':');
110 strncpy( comp
, path
, len
);
113 matching
= IOService::serviceMatching( "IONetworkInterface" );
116 dict
= IOService::addLocation( matching
);
120 str
= OSString::withCString( buf
);
123 dict
->setObject( kIOPathMatchKey
, str
);
136 OSDictionary
* IONetworkNamePrefixMatching( const char * prefix
)
138 OSDictionary
* matching
;
139 OSDictionary
* propDict
= 0;
140 const OSSymbol
* str
= 0;
143 matching
= IOService::serviceMatching( "IONetworkInterface" );
147 propDict
= OSDictionary::withCapacity(1);
151 str
= OSSymbol::withCString( prefix
);
155 propDict
->setObject( kIOInterfaceNamePrefix
, (OSObject
*) str
);
159 if ( matching
->setObject( gIOPropertyMatchKey
,
160 (OSObject
*) propDict
) != true )
170 if ( matching
) matching
->release();
171 if ( propDict
) propDict
->release();
172 if ( str
) str
->release();
177 static bool IORegisterNetworkInterface( IONetworkInterface
* netif
)
179 IONetworkStack
* stack
;
181 if (( stack
= IONetworkStack::getNetworkStack() ))
183 stack
->registerInterface( netif
, netif
->getNamePrefix() );
186 return ( netif
->getProperty( kIOBSDNameKey
) != 0 );
189 static void IORegisterPrimaryNetworkInterface()
191 IONetworkStack
* stack
;
193 if (( stack
= IONetworkStack::getNetworkStack() ))
195 stack
->registerPrimaryInterface( true );
199 OSDictionary
* IODiskMatching( const char * path
, char * buf
, int maxLen
)
208 // scan the tail of the path for "@unit:partition"
210 // Have to get the full path to the controller - an alias may
211 // tell us next to nothing, like "hd:8"
212 alias
= IORegistryEntry::dealiasPath( &path
, gIODTPlane
);
214 look
= path
+ strlen( path
);
216 while( look
!= path
) {
217 if( *(--look
) == c
) {
219 partition
= strtol( look
+ 1, 0, 0 );
221 } else if( c
== '@') {
222 unit
= strtol( look
+ 1, 0, 16 );
224 } else if( c
== '/') {
230 if( alias
&& (look
== path
)) {
232 look
= path
+ strlen( path
);
236 if( c
|| unit
== -1 || partition
== -1)
239 maxLen
-= strlen( "{" kIOPathMatchKey
"='" kIODeviceTreePlane
":" );
240 maxLen
-= ( alias
? strlen( alias
) : 0 ) + (look
- path
);
241 maxLen
-= strlen( "/@hhhhhhhh:dddddddddd';}" );
244 sprintf( buf
, "{" kIOPathMatchKey
"='" kIODeviceTreePlane
":" );
245 comp
= buf
+ strlen( buf
);
248 strcpy( comp
, alias
);
249 comp
+= strlen( alias
);
252 if ( (look
- path
)) {
253 strncpy( comp
, path
, look
- path
);
257 sprintf( comp
, "/@%lx:%ld';}", unit
, partition
);
261 return( OSDynamicCast(OSDictionary
, OSUnserialize( buf
, 0 )) );
268 OSDictionary
* IOOFPathMatching( const char * path
, char * buf
, int maxLen
)
270 /* need to look up path, get device type,
271 call matching help based on device type */
273 return( IODiskMatching( path
, buf
, maxLen
));
277 kern_return_t
IOFindBSDRoot( char * rootName
,
278 dev_t
* root
, u_int32_t
* oflags
)
282 IORegistryEntry
* regEntry
;
283 OSDictionary
* matching
= 0;
291 enum { kMaxPathBuf
= 512, kMaxBootVar
= 128 };
293 const char * look
= 0;
295 bool forceNet
= false;
297 static int mountAttempts
= 0;
302 str
= (char *) IOMalloc( kMaxPathBuf
+ kMaxBootVar
);
304 return( kIOReturnNoMemory
);
305 rdBootVar
= str
+ kMaxPathBuf
;
307 if (!PE_parse_boot_arg("rd", rdBootVar
)
308 && !PE_parse_boot_arg("rootdev", rdBootVar
))
312 if( (regEntry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
))) {
313 data
= (OSData
*) regEntry
->getProperty( "rootpath" );
318 if( (regEntry
= IORegistryEntry::fromPath( "/options", gIODTPlane
))) {
319 data
= (OSData
*) regEntry
->getProperty( "boot-file" );
327 look
= (const char *) data
->getBytesNoCopy();
329 if( rdBootVar
[0] == '*') {
330 look
= rdBootVar
+ 1;
333 if( (regEntry
= IORegistryEntry::fromPath( "/", gIODTPlane
))) {
334 forceNet
= (0 != regEntry
->getProperty( "net-boot" ));
340 // from OpenFirmware path
341 IOLog("From path: \"%s\", ", look
);
343 if( forceNet
|| (0 == strncmp( look
, "enet", strlen( "enet" ))) )
344 matching
= IONetworkMatching( look
, str
, kMaxPathBuf
);
346 matching
= IODiskMatching( look
, str
, kMaxPathBuf
);
349 if( (!matching
) && rdBootVar
[0] ) {
355 if ( strncmp( look
, "en", strlen( "en" )) == 0 )
356 matching
= IONetworkNamePrefixMatching( "en" );
358 matching
= IOBSDNameMatching( look
);
364 matching
= IOService::serviceMatching( "IOMedia" );
365 astring
= OSString::withCStringNoCopy("Apple_UFS");
367 matching
->setObject(kIOMediaContentKey
, astring
);
372 if( true && matching
) {
373 OSSerialize
* s
= OSSerialize::withCapacity( 5 );
375 if( matching
->serialize( s
)) {
376 IOLog( "Waiting on %s\n", s
->text() );
381 IOService::waitForService(IOService::serviceMatching("IOMediaBSDClient"));
384 t
.tv_sec
= ROOTDEVICETIMEOUT
;
387 service
= IOService::waitForService( matching
, &t
);
388 if( (!service
) || (mountAttempts
== 10)) {
389 PE_display_icon( 0, "noroot");
390 IOLog( "Still waiting for root device\n" );
398 // If the IOService we matched to is a subclass of IONetworkInterface,
399 // then make sure it has been registered with BSD and has a BSD name
403 && service
->metaCast( "IONetworkInterface" )
404 && !IORegisterNetworkInterface( (IONetworkInterface
*) service
) )
408 IORegisterPrimaryNetworkInterface();
413 service
->getPath( str
, &len
, gIOServicePlane
);
414 IOLog( "Got boot device = %s\n", str
);
416 iostr
= (OSString
*) service
->getProperty( kIOBSDNameKey
);
418 strcpy( rootName
, iostr
->getCStringNoCopy() );
419 off
= (OSNumber
*) service
->getProperty( kIOBSDMajorKey
);
421 major
= off
->unsigned32BitValue();
422 off
= (OSNumber
*) service
->getProperty( kIOBSDMinorKey
);
424 minor
= off
->unsigned32BitValue();
426 if( service
->metaCast( "IONetworkInterface" ))
431 IOLog( "Wait for root failed\n" );
432 strcpy( rootName
, "en0");
436 IOLog( "BSD root: %s", rootName
);
438 IOLog(", major %d, minor %d\n", major
, minor
);
442 *root
= makedev( major
, minor
);
445 IOFree( str
, kMaxPathBuf
+ kMaxBootVar
);
447 if( gIOKitDebug
& (kIOLogDTree
| kIOLogServiceTree
| kIOLogMemory
)) {
450 // IOService::getPlatform()->waitQuiet();
451 if( gIOKitDebug
& kIOLogDTree
) {
452 IOLog("\nDT plane:\n");
453 IOPrintPlane( gIODTPlane
);
455 if( gIOKitDebug
& kIOLogServiceTree
) {
456 IOLog("\nService plane:\n");
457 IOPrintPlane( gIOServicePlane
);
459 if( gIOKitDebug
& kIOLogMemory
)
463 return( kIOReturnSuccess
);