]> git.saurik.com Git - apple/xnu.git/blob - iokit/bsddev/IOKitBSDInit.cpp
895f27b986fe2c1107991ca9540746ea680e6991
[apple/xnu.git] / iokit / bsddev / IOKitBSDInit.cpp
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
35 extern "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
44 extern dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys);
45 extern dev_t mdevlookup(int devid);
46 extern void mdevremoveall(void);
47
48 kern_return_t
49 IOKitBSDInit( void )
50 {
51 IOService::publishResource("IOBSD");
52
53 return( kIOReturnSuccess );
54 }
55
56 OSDictionary * 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
84 OSDictionary * IOUUIDMatching( void )
85 {
86 return IOService::resourceMatching( "boot-uuid-media" );
87 }
88
89
90 OSDictionary * 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
112 OSDictionary * 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 strcpy( buf, kIODeviceTreePlane ":" );
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 strncpy( comp, path, len );
142 comp[ len ] = 0;
143
144 matching = IOService::serviceMatching( "IONetworkInterface" );
145 if( !matching)
146 continue;
147 dict = IOService::addLocation( matching );
148 if( !dict)
149 continue;
150
151 str = OSString::withCString( buf );
152 if( !str)
153 continue;
154 dict->setObject( kIOPathMatchKey, str );
155 str->release();
156
157 return( matching );
158
159 } while( false );
160
161 if( matching)
162 matching->release();
163
164 return( 0 );
165 }
166
167 OSDictionary * IONetworkNamePrefixMatching( const char * prefix )
168 {
169 OSDictionary * matching;
170 OSDictionary * propDict = 0;
171 const OSSymbol * str = 0;
172 char networkType[128];
173
174 do {
175 matching = IOService::serviceMatching( "IONetworkInterface" );
176 if ( matching == 0 )
177 continue;
178
179 propDict = OSDictionary::withCapacity(1);
180 if ( propDict == 0 )
181 continue;
182
183 str = OSSymbol::withCString( prefix );
184 if ( str == 0 )
185 continue;
186
187 propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str );
188 str->release();
189 str = 0;
190
191 // see if we're contrained to netroot off of specific network type
192 if(PE_parse_boot_argn( "network-type", networkType, 128 ))
193 {
194 str = OSSymbol::withCString( networkType );
195 if(str)
196 {
197 propDict->setObject( "IONetworkRootType", str);
198 str->release();
199 str = 0;
200 }
201 }
202
203 if ( matching->setObject( gIOPropertyMatchKey,
204 (OSObject *) propDict ) != true )
205 continue;
206
207 propDict->release();
208 propDict = 0;
209
210 return( matching );
211
212 } while ( false );
213
214 if ( matching ) matching->release();
215 if ( propDict ) propDict->release();
216 if ( str ) str->release();
217
218 return( 0 );
219 }
220
221 static bool IORegisterNetworkInterface( IOService * netif )
222 {
223 // A network interface is typically named and registered
224 // with BSD after receiving a request from a user space
225 // "namer". However, for cases when the system needs to
226 // root from the network, this registration task must be
227 // done inside the kernel and completed before the root
228 // device is handed to BSD.
229
230 IOService * stack;
231 OSNumber * zero = 0;
232 OSString * path = 0;
233 OSDictionary * dict = 0;
234 char * pathBuf = 0;
235 int len;
236 enum { kMaxPathLen = 512 };
237
238 do {
239 stack = IOService::waitForService(
240 IOService::serviceMatching("IONetworkStack") );
241 if ( stack == 0 ) break;
242
243 dict = OSDictionary::withCapacity(3);
244 if ( dict == 0 ) break;
245
246 zero = OSNumber::withNumber((UInt64) 0, 32);
247 if ( zero == 0 ) break;
248
249 pathBuf = (char *) IOMalloc( kMaxPathLen );
250 if ( pathBuf == 0 ) break;
251
252 len = kMaxPathLen;
253 if ( netif->getPath( pathBuf, &len, gIOServicePlane )
254 == false ) break;
255
256 path = OSString::withCStringNoCopy( pathBuf );
257 if ( path == 0 ) break;
258
259 dict->setObject( "IOInterfaceUnit", zero );
260 dict->setObject( kIOPathMatchKey, path );
261
262 stack->setProperties( dict );
263 }
264 while ( false );
265
266 if ( zero ) zero->release();
267 if ( path ) path->release();
268 if ( dict ) dict->release();
269 if ( pathBuf ) IOFree(pathBuf, kMaxPathLen);
270
271 return ( netif->getProperty( kIOBSDNameKey ) != 0 );
272 }
273
274 OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen )
275 {
276 const char * look;
277 const char * alias;
278 char * comp;
279 long unit = -1;
280 long partition = -1;
281 long lun = -1;
282 char c;
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 maxLen -= strlen( "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" );
321 maxLen -= ( alias ? strlen( alias ) : 0 ) + (look - path);
322 maxLen -= strlen( "/@hhhhhhhh,hhhhhhhh:dddddddddd';}" );
323
324 if( maxLen > 0) {
325 sprintf( buf, "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" );
326 comp = buf + strlen( buf );
327
328 if( alias) {
329 strcpy( comp, alias );
330 comp += strlen( alias );
331 }
332
333 if ( (look - path)) {
334 strncpy( comp, path, look - path);
335 comp += look - path;
336 }
337
338 if ( lun != -1 )
339 {
340 sprintf ( comp, "/@%lx,%lx:%ld';}", unit, lun, partition );
341 }
342 else
343 {
344 sprintf( comp, "/@%lx:%ld';}", unit, partition );
345 }
346 } else
347 continue;
348
349 return( OSDynamicCast(OSDictionary, OSUnserialize( buf, 0 )) );
350
351 } while( false );
352
353 return( 0 );
354 }
355
356 OSDictionary * IOOFPathMatching( const char * path, char * buf, int maxLen )
357 {
358 OSDictionary * matching;
359 OSString * str;
360 char * comp;
361 int len;
362
363 /* need to look up path, get device type,
364 call matching help based on device type */
365
366 matching = IODiskMatching( path, buf, maxLen );
367 if( matching)
368 return( matching );
369
370 do {
371
372 len = strlen( kIODeviceTreePlane ":" );
373 maxLen -= len;
374 if( maxLen < 0)
375 continue;
376
377 strcpy( buf, kIODeviceTreePlane ":" );
378 comp = buf + len;
379
380 len = strlen( path );
381 maxLen -= len;
382 if( maxLen < 0)
383 continue;
384 strncpy( comp, path, len );
385 comp[ len ] = 0;
386
387 matching = OSDictionary::withCapacity( 1 );
388 if( !matching)
389 continue;
390
391 str = OSString::withCString( buf );
392 if( !str)
393 continue;
394 matching->setObject( kIOPathMatchKey, str );
395 str->release();
396
397 return( matching );
398
399 } while( false );
400
401 if( matching)
402 matching->release();
403
404 return( 0 );
405 }
406
407 IOService * IOFindMatchingChild( IOService * service )
408 {
409 // find a matching child service
410 IOService * child = 0;
411 OSIterator * iter = service->getClientIterator();
412 if ( iter ) {
413 while( ( child = (IOService *) iter->getNextObject() ) ) {
414 OSDictionary * dict = OSDictionary::withCapacity( 1 );
415 if( dict == 0 ) {
416 iter->release();
417 return 0;
418 }
419 const OSSymbol * str = OSSymbol::withCString( "Apple_HFS" );
420 if( str == 0 ) {
421 dict->release();
422 iter->release();
423 return 0;
424 }
425 dict->setObject( "Content", (OSObject *)str );
426 str->release();
427 if ( child->compareProperty( dict, "Content" ) ) {
428 dict->release();
429 break;
430 }
431 dict->release();
432 IOService * subchild = IOFindMatchingChild( child );
433 if ( subchild ) {
434 child = subchild;
435 break;
436 }
437 }
438 iter->release();
439 }
440 return child;
441 }
442
443 static int didRam = 0;
444
445 kern_return_t IOFindBSDRoot( char * rootName,
446 dev_t * root, u_int32_t * oflags )
447 {
448 mach_timespec_t t;
449 IOService * service;
450 IORegistryEntry * regEntry;
451 OSDictionary * matching = 0;
452 OSString * iostr;
453 OSNumber * off;
454 OSData * data = 0;
455 UInt32 *ramdParms = 0;
456
457 UInt32 flags = 0;
458 int mnr, mjr;
459 bool findHFSChild = false;
460 char * mediaProperty = 0;
461 char * rdBootVar;
462 enum { kMaxPathBuf = 512, kMaxBootVar = 128 };
463 char * str;
464 const char * look = 0;
465 int len;
466 bool forceNet = false;
467 bool debugInfoPrintedOnce = false;
468 const char * uuidStr = NULL;
469
470 static int mountAttempts = 0;
471
472 int xchar, dchar;
473
474
475 if( mountAttempts++)
476 IOSleep( 5 * 1000 );
477
478 str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar );
479 if( !str)
480 return( kIOReturnNoMemory );
481 rdBootVar = str + kMaxPathBuf;
482
483 if (!PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar )
484 && !PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar ))
485 rdBootVar[0] = 0;
486
487 do {
488 if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) {
489 data = OSDynamicCast(OSData, regEntry->getProperty( "root-matching" ));
490 if (data) {
491 matching = OSDynamicCast(OSDictionary, OSUnserializeXML((char *)data->getBytesNoCopy()));
492 if (matching) {
493 continue;
494 }
495 }
496
497 data = (OSData *) regEntry->getProperty( "boot-uuid" );
498 if( data) {
499 uuidStr = (const char*)data->getBytesNoCopy();
500 OSString *uuidString = OSString::withCString( uuidStr );
501
502 // match the boot-args boot-uuid processing below
503 if( uuidString) {
504 IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr);
505 IOService::publishResource( "boot-uuid", uuidString );
506 uuidString->release();
507 matching = IOUUIDMatching();
508 mediaProperty = "boot-uuid-media";
509 regEntry->release();
510 continue;
511 } else {
512 uuidStr = NULL;
513 }
514 }
515
516 // else try for an OF Path
517 data = (OSData *) regEntry->getProperty( "rootpath" );
518 regEntry->release();
519 if( data) continue;
520 }
521 if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) {
522 data = (OSData *) regEntry->getProperty( "boot-file" );
523 regEntry->release();
524 if( data) continue;
525 }
526 } while( false );
527
528 if( data && !uuidStr)
529 look = (const char *) data->getBytesNoCopy();
530
531 if( rdBootVar[0] == '*') {
532 look = rdBootVar + 1;
533 forceNet = false;
534 } else {
535 if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) {
536 forceNet = (0 != regEntry->getProperty( "net-boot" ));
537 regEntry->release();
538 }
539 }
540
541
542
543 //
544 // See if we have a RAMDisk property in /chosen/memory-map. If so, make it into a device.
545 // It will become /dev/mdx, where x is 0-f.
546 //
547
548 if(!didRam) { /* Have we already build this ram disk? */
549 didRam = 1; /* Remember we did this */
550 if((regEntry = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ))) { /* Find the map node */
551 data = (OSData *)regEntry->getProperty("RAMDisk"); /* Find the ram disk, if there */
552 if(data) { /* We found one */
553
554 ramdParms = (UInt32 *)data->getBytesNoCopy(); /* Point to the ram disk base and size */
555 (void)mdevadd(-1, ramdParms[0] >> 12, ramdParms[1] >> 12, 0); /* Initialize it and pass back the device number */
556 }
557 regEntry->release(); /* Toss the entry */
558 }
559 }
560
561 //
562 // Now check if we are trying to root on a memory device
563 //
564
565 if((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) {
566 dchar = xchar = rdBootVar[2]; /* Get the actual device */
567 if((xchar >= '0') && (xchar <= '9')) xchar = xchar - '0'; /* If digit, convert */
568 else {
569 xchar = xchar & ~' '; /* Fold to upper case */
570 if((xchar >= 'A') && (xchar <= 'F')) { /* Is this a valid digit? */
571 xchar = (xchar & 0xF) + 9; /* Convert the hex digit */
572 dchar = dchar | ' '; /* Fold to lower case */
573 }
574 else xchar = -1; /* Show bogus */
575 }
576 if(xchar >= 0) { /* Do we have a valid memory device name? */
577 *root = mdevlookup(xchar); /* Find the device number */
578 if(*root >= 0) { /* Did we find one? */
579
580 rootName[0] = 'm'; /* Build root name */
581 rootName[1] = 'd'; /* Build root name */
582 rootName[2] = dchar; /* Build root name */
583 rootName[3] = 0; /* Build root name */
584 IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root));
585 *oflags = 0; /* Show that this is not network */
586 goto iofrootx; /* Join common exit... */
587 }
588 panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar); /* Not there */
589 }
590 }
591
592 if( look) {
593 // from OpenFirmware path
594 IOLog("From path: \"%s\", ", look);
595
596 if (!matching) {
597 if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) ) {
598 matching = IONetworkMatching( look, str, kMaxPathBuf );
599 } else {
600 matching = IODiskMatching( look, str, kMaxPathBuf );
601 }
602 }
603 }
604
605 if( (!matching) && rdBootVar[0] ) {
606 // by BSD name
607 look = rdBootVar;
608 if( look[0] == '*')
609 look++;
610
611 if ( strncmp( look, "en", strlen( "en" )) == 0 ) {
612 matching = IONetworkNamePrefixMatching( "en" );
613 } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) {
614 matching = IOCDMatching();
615 findHFSChild = true;
616 } else if ( strncmp( look, "uuid", strlen( "uuid" )) == 0 ) {
617 char *uuid;
618 OSString *uuidString;
619
620 uuid = (char *)IOMalloc( kMaxBootVar );
621
622 if ( uuid ) {
623 if (!PE_parse_boot_argn( "boot-uuid", uuid, kMaxBootVar )) {
624 panic( "rd=uuid but no boot-uuid=<value> specified" );
625 }
626 uuidString = OSString::withCString( uuid );
627 if ( uuidString ) {
628 IOService::publishResource( "boot-uuid", uuidString );
629 uuidString->release();
630 IOLog( "\nWaiting for boot volume with UUID %s\n", uuid );
631 matching = IOUUIDMatching();
632 mediaProperty = "boot-uuid-media";
633 }
634 IOFree( uuid, kMaxBootVar );
635 }
636 } else {
637 matching = IOBSDNameMatching( look );
638 }
639 }
640
641 if( !matching) {
642 OSString * astring;
643 // Match any HFS media
644
645 matching = IOService::serviceMatching( "IOMedia" );
646 astring = OSString::withCStringNoCopy("Apple_HFS");
647 if ( astring ) {
648 matching->setObject("Content", astring);
649 astring->release();
650 }
651 }
652
653 if( true && matching) {
654 OSSerialize * s = OSSerialize::withCapacity( 5 );
655
656 if( matching->serialize( s )) {
657 IOLog( "Waiting on %s\n", s->text() );
658 s->release();
659 }
660 }
661
662 do {
663 t.tv_sec = ROOTDEVICETIMEOUT;
664 t.tv_nsec = 0;
665 matching->retain();
666 service = IOService::waitForService( matching, &t );
667 if( (!service) || (mountAttempts == 10)) {
668 PE_display_icon( 0, "noroot");
669 IOLog( "Still waiting for root device\n" );
670
671 if( !debugInfoPrintedOnce) {
672 debugInfoPrintedOnce = true;
673 if( gIOKitDebug & kIOLogDTree) {
674 IOLog("\nDT plane:\n");
675 IOPrintPlane( gIODTPlane );
676 }
677 if( gIOKitDebug & kIOLogServiceTree) {
678 IOLog("\nService plane:\n");
679 IOPrintPlane( gIOServicePlane );
680 }
681 if( gIOKitDebug & kIOLogMemory)
682 IOPrintMemory();
683 }
684 }
685 } while( !service);
686 matching->release();
687
688 if ( service && findHFSChild ) {
689 bool waiting = true;
690 // wait for children services to finish registering
691 while ( waiting ) {
692 t.tv_sec = ROOTDEVICETIMEOUT;
693 t.tv_nsec = 0;
694 if ( service->waitQuiet( &t ) == kIOReturnSuccess ) {
695 waiting = false;
696 } else {
697 IOLog( "Waiting for child registration\n" );
698 }
699 }
700 // look for a subservice with an Apple_HFS child
701 IOService * subservice = IOFindMatchingChild( service );
702 if ( subservice ) service = subservice;
703 } else if ( service && mediaProperty ) {
704 service = (IOService *)service->getProperty(mediaProperty);
705 }
706
707 mjr = 0;
708 mnr = 0;
709
710 // If the IOService we matched to is a subclass of IONetworkInterface,
711 // then make sure it has been registered with BSD and has a BSD name
712 // assigned.
713
714 if ( service
715 && service->metaCast( "IONetworkInterface" )
716 && !IORegisterNetworkInterface( service ) )
717 {
718 service = 0;
719 }
720
721 if( service) {
722
723 len = kMaxPathBuf;
724 service->getPath( str, &len, gIOServicePlane );
725 IOLog( "Got boot device = %s\n", str );
726
727 iostr = (OSString *) service->getProperty( kIOBSDNameKey );
728 if( iostr)
729 strcpy( rootName, iostr->getCStringNoCopy() );
730 off = (OSNumber *) service->getProperty( kIOBSDMajorKey );
731 if( off)
732 mjr = off->unsigned32BitValue();
733 off = (OSNumber *) service->getProperty( kIOBSDMinorKey );
734 if( off)
735 mnr = off->unsigned32BitValue();
736
737 if( service->metaCast( "IONetworkInterface" ))
738 flags |= 1;
739
740 } else {
741
742 IOLog( "Wait for root failed\n" );
743 strcpy( rootName, "en0");
744 flags |= 1;
745 }
746
747 IOLog( "BSD root: %s", rootName );
748 if( mjr)
749 IOLog(", major %d, minor %d\n", mjr, mnr );
750 else
751 IOLog("\n");
752
753 *root = makedev( mjr, mnr );
754 *oflags = flags;
755
756 IOFree( str, kMaxPathBuf + kMaxBootVar );
757
758 iofrootx:
759 if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) {
760
761 IOService::getPlatform()->waitQuiet();
762 if( gIOKitDebug & kIOLogDTree) {
763 IOLog("\nDT plane:\n");
764 IOPrintPlane( gIODTPlane );
765 }
766 if( gIOKitDebug & kIOLogServiceTree) {
767 IOLog("\nService plane:\n");
768 IOPrintPlane( gIOServicePlane );
769 }
770 if( gIOKitDebug & kIOLogMemory)
771 IOPrintMemory();
772 }
773
774 return( kIOReturnSuccess );
775 }
776
777 void IOSecureBSDRoot(const char * rootName)
778 {
779 #if CONFIG_EMBEDDED
780 IOReturn result;
781 IOPlatformExpert *pe;
782 const OSSymbol *functionName = OSSymbol::withCStringNoCopy("SecureRootName");
783
784 while ((pe = IOService::getPlatform()) == 0) IOSleep(1 * 1000);
785
786 // Returns kIOReturnNotPrivileged is the root device is not secure.
787 // Returns kIOReturnUnsupported if "SecureRootName" is not implemented.
788 result = pe->callPlatformFunction(functionName, false, (void *)rootName, (void *)0, (void *)0, (void *)0);
789
790 functionName->release();
791
792 if (result == kIOReturnNotPrivileged) mdevremoveall();
793 #endif
794 }
795
796 void *
797 IOBSDRegistryEntryForDeviceTree(char * path)
798 {
799 return (IORegistryEntry::fromPath(path, gIODTPlane));
800 }
801
802 void
803 IOBSDRegistryEntryRelease(void * entry)
804 {
805 IORegistryEntry * regEntry = (IORegistryEntry *)entry;
806
807 if (regEntry)
808 regEntry->release();
809 return;
810 }
811
812 const void *
813 IOBSDRegistryEntryGetData(void * entry, char * property_name,
814 int * packet_length)
815 {
816 OSData * data;
817 IORegistryEntry * regEntry = (IORegistryEntry *)entry;
818
819 data = (OSData *) regEntry->getProperty(property_name);
820 if (data) {
821 *packet_length = data->getLength();
822 return (data->getBytesNoCopy());
823 }
824 return (NULL);
825 }
826
827 kern_return_t IOBSDGetPlatformUUID( uuid_t uuid, mach_timespec_t timeout )
828 {
829 IOService * resources;
830 OSString * string;
831
832 resources = IOService::waitForService( IOService::resourceMatching( kIOPlatformUUIDKey ), &timeout );
833 if ( resources == 0 ) return KERN_OPERATION_TIMED_OUT;
834
835 string = ( OSString * ) IOService::getPlatform( )->getProvider( )->getProperty( kIOPlatformUUIDKey );
836 if ( string == 0 ) return KERN_NOT_SUPPORTED;
837
838 uuid_parse( string->getCStringNoCopy( ), uuid );
839
840 return KERN_SUCCESS;
841 }
842
843 } /* extern "C" */