]> git.saurik.com Git - apple/xnu.git/blame - iokit/bsddev/IOKitBSDInit.cpp
xnu-1228.15.4.tar.gz
[apple/xnu.git] / iokit / bsddev / IOKitBSDInit.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
1c79356b
A
33#include <IOKit/IOPlatformExpert.h>
34
1c79356b
A
35extern "C" {
36
37#include <pexpert/pexpert.h>
38#include <kern/clock.h>
2d21ac55 39#include <uuid/uuid.h>
1c79356b
A
40
41// how long to wait for matching root device, secs
42#define ROOTDEVICETIMEOUT 60
43
55e303ae
A
44extern dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys);
45extern dev_t mdevlookup(int devid);
4a3eedf9 46extern void mdevremoveall(void);
1c79356b
A
47
48kern_return_t
49IOKitBSDInit( void )
50{
1c79356b
A
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
91447636
A
84OSDictionary * IOUUIDMatching( void )
85{
86 return IOService::resourceMatching( "boot-uuid-media" );
87}
88
89
55e303ae 90OSDictionary * IOCDMatching( void )
0b4e3aa0
A
91{
92 OSDictionary * dict;
93 const OSSymbol * str;
55e303ae
A
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 );
0b4e3aa0
A
110}
111
1c79356b
A
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;
cf7d32b8 126 if( maxLen <= 0)
1c79356b
A
127 continue;
128
cf7d32b8 129 strlcpy( buf, kIODeviceTreePlane ":", len + 1 );
1c79356b
A
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;
cf7d32b8 139 if( maxLen <= 0)
1c79356b 140 continue;
cf7d32b8 141 strlcpy( comp, path, len + 1 );
1c79356b
A
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;
2d21ac55
A
171 char networkType[128];
172
1c79356b
A
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
0b4e3aa0 186 propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str );
1c79356b
A
187 str->release();
188 str = 0;
189
2d21ac55
A
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
1c79356b
A
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
0b4e3aa0 220static bool IORegisterNetworkInterface( IOService * netif )
1c79356b 221{
0b4e3aa0
A
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 };
1c79356b 236
0b4e3aa0
A
237 do {
238 stack = IOService::waitForService(
239 IOService::serviceMatching("IONetworkStack") );
240 if ( stack == 0 ) break;
1c79356b 241
0b4e3aa0
A
242 dict = OSDictionary::withCapacity(3);
243 if ( dict == 0 ) break;
1c79356b 244
0b4e3aa0
A
245 zero = OSNumber::withNumber((UInt64) 0, 32);
246 if ( zero == 0 ) break;
1c79356b 247
0b4e3aa0
A
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 );
1c79356b
A
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;
55e303ae 280 long lun = -1;
1c79356b 281 char c;
cf7d32b8 282 int len;
1c79356b
A
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 );
55e303ae 289
1c79356b
A
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 == '@') {
91447636
A
298 unit = strtol( look + 1, &comp, 16 );
299
300 if( *comp == ',') {
301 lun = strtol( comp + 1, 0, 16 );
55e303ae
A
302 }
303
1c79356b
A
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;
55e303ae 319
cf7d32b8
A
320 len = strlen( "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" );
321 maxLen -= len;
322 if( maxLen <= 0)
323 continue;
1c79356b 324
cf7d32b8
A
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 }
55e303ae 347
cf7d32b8
A
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 }
55e303ae 366
1c79356b
A
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{
91447636
A
376 OSDictionary * matching;
377 OSString * str;
378 char * comp;
379 int len;
380
1c79356b
A
381 /* need to look up path, get device type,
382 call matching help based on device type */
383
91447636
A
384 matching = IODiskMatching( path, buf, maxLen );
385 if( matching)
386 return( matching );
387
388 do {
389
390 len = strlen( kIODeviceTreePlane ":" );
391 maxLen -= len;
cf7d32b8 392 if( maxLen <= 0)
91447636
A
393 continue;
394
cf7d32b8 395 strlcpy( buf, kIODeviceTreePlane ":", len + 1 );
91447636
A
396 comp = buf + len;
397
398 len = strlen( path );
399 maxLen -= len;
cf7d32b8 400 if( maxLen <= 0)
91447636 401 continue;
cf7d32b8 402 strlcpy( comp, path, len + 1 );
91447636
A
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 );
1c79356b 417
91447636
A
418 if( matching)
419 matching->release();
420
421 return( 0 );
1c79356b
A
422}
423
55e303ae
A
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
cf7d32b8 462kern_return_t IOFindBSDRoot( char * rootName, unsigned int rootNameSize,
1c79356b
A
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;
55e303ae 472 UInt32 *ramdParms = 0;
1c79356b
A
473
474 UInt32 flags = 0;
2d21ac55 475 int mnr, mjr;
55e303ae 476 bool findHFSChild = false;
91447636 477 char * mediaProperty = 0;
1c79356b
A
478 char * rdBootVar;
479 enum { kMaxPathBuf = 512, kMaxBootVar = 128 };
480 char * str;
481 const char * look = 0;
482 int len;
483 bool forceNet = false;
0b4e3aa0 484 bool debugInfoPrintedOnce = false;
91447636 485 const char * uuidStr = NULL;
1c79356b
A
486
487 static int mountAttempts = 0;
55e303ae 488
91447636 489 int xchar, dchar;
55e303ae 490
1c79356b
A
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
2d21ac55
A
500 if (!PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar )
501 && !PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar ))
1c79356b
A
502 rdBootVar[0] = 0;
503
504 do {
91447636 505 if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) {
0c530ab8
A
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
91447636
A
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;
55e303ae 530 }
91447636
A
531 }
532
533 // else try for an OF Path
534 data = (OSData *) regEntry->getProperty( "rootpath" );
535 regEntry->release();
536 if( data) continue;
537 }
1c79356b 538 if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) {
91447636
A
539 data = (OSData *) regEntry->getProperty( "boot-file" );
540 regEntry->release();
541 if( data) continue;
542 }
1c79356b
A
543 } while( false );
544
91447636 545 if( data && !uuidStr)
1c79356b
A
546 look = (const char *) data->getBytesNoCopy();
547
548 if( rdBootVar[0] == '*') {
549 look = rdBootVar + 1;
55e303ae 550 forceNet = false;
1c79356b
A
551 } else {
552 if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) {
553 forceNet = (0 != regEntry->getProperty( "net-boot" ));
55e303ae
A
554 regEntry->release();
555 }
de355530 556 }
d7e50217 557
55e303ae
A
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
1c79356b
A
609 if( look) {
610 // from OpenFirmware path
611 IOLog("From path: \"%s\", ", look);
612
0c530ab8
A
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 }
0b4e3aa0 619 }
1c79356b 620 }
55e303ae
A
621
622 if( (!matching) && rdBootVar[0] ) {
1c79356b
A
623 // by BSD name
624 look = rdBootVar;
625 if( look[0] == '*')
626 look++;
627
0b4e3aa0
A
628 if ( strncmp( look, "en", strlen( "en" )) == 0 ) {
629 matching = IONetworkNamePrefixMatching( "en" );
55e303ae
A
630 } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) {
631 matching = IOCDMatching();
632 findHFSChild = true;
91447636
A
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 ) {
2d21ac55 640 if (!PE_parse_boot_argn( "boot-uuid", uuid, kMaxBootVar )) {
91447636
A
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 }
0b4e3aa0
A
653 } else {
654 matching = IOBSDNameMatching( look );
655 }
1c79356b
A
656 }
657
658 if( !matching) {
2d21ac55
A
659 OSString * astring;
660 // Match any HFS media
661
1c79356b 662 matching = IOService::serviceMatching( "IOMedia" );
55e303ae 663 astring = OSString::withCStringNoCopy("Apple_HFS");
1c79356b 664 if ( astring ) {
0b4e3aa0 665 matching->setObject("Content", astring);
1c79356b
A
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
1c79356b
A
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" );
0b4e3aa0
A
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 }
1c79356b
A
701 }
702 } while( !service);
703 matching->release();
704
55e303ae
A
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;
91447636 720 } else if ( service && mediaProperty ) {
0c530ab8 721 service = (IOService *)service->getProperty(mediaProperty);
55e303ae
A
722 }
723
2d21ac55
A
724 mjr = 0;
725 mnr = 0;
1c79356b
A
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" )
0b4e3aa0 733 && !IORegisterNetworkInterface( service ) )
1c79356b
A
734 {
735 service = 0;
736 }
1c79356b
A
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)
cf7d32b8 746 strlcpy( rootName, iostr->getCStringNoCopy(), rootNameSize );
1c79356b
A
747 off = (OSNumber *) service->getProperty( kIOBSDMajorKey );
748 if( off)
2d21ac55 749 mjr = off->unsigned32BitValue();
1c79356b
A
750 off = (OSNumber *) service->getProperty( kIOBSDMinorKey );
751 if( off)
2d21ac55 752 mnr = off->unsigned32BitValue();
1c79356b
A
753
754 if( service->metaCast( "IONetworkInterface" ))
755 flags |= 1;
756
757 } else {
758
759 IOLog( "Wait for root failed\n" );
cf7d32b8 760 strlcpy( rootName, "en0", rootNameSize );
1c79356b
A
761 flags |= 1;
762 }
763
764 IOLog( "BSD root: %s", rootName );
2d21ac55
A
765 if( mjr)
766 IOLog(", major %d, minor %d\n", mjr, mnr );
1c79356b
A
767 else
768 IOLog("\n");
769
2d21ac55 770 *root = makedev( mjr, mnr );
1c79356b
A
771 *oflags = flags;
772
773 IOFree( str, kMaxPathBuf + kMaxBootVar );
774
55e303ae 775iofrootx:
0b4e3aa0 776 if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) {
1c79356b 777
0b4e3aa0 778 IOService::getPlatform()->waitQuiet();
1c79356b
A
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
2d21ac55
A
794void IOSecureBSDRoot(const char * rootName)
795{
796#if CONFIG_EMBEDDED
4a3eedf9 797 IOReturn result;
2d21ac55 798 IOPlatformExpert *pe;
4a3eedf9 799 const OSSymbol *functionName = OSSymbol::withCStringNoCopy("SecureRootName");
2d21ac55
A
800
801 while ((pe = IOService::getPlatform()) == 0) IOSleep(1 * 1000);
802
4a3eedf9
A
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);
2d21ac55
A
806
807 functionName->release();
4a3eedf9
A
808
809 if (result == kIOReturnNotPrivileged) mdevremoveall();
2d21ac55
A
810#endif
811}
812
9bccf70c
A
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
2d21ac55
A
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
e2fac8b1
A
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
1c79356b 897} /* extern "C" */