2 * Copyright (c) 1998-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 #include <IOKit/IOUserClient.h>
38 #include <pexpert/pexpert.h>
39 #include <kern/clock.h>
40 #include <mach/machine.h>
41 #include <uuid/uuid.h>
42 #include <sys/vnode_internal.h>
43 #include <sys/mount.h>
45 // how long to wait for matching root device, secs
47 #define ROOTDEVICETIMEOUT 120
49 #define ROOTDEVICETIMEOUT 60
52 int panic_on_exception_triage
= 0;
54 extern dev_t
mdevadd(int devid
, uint64_t base
, unsigned int size
, int phys
);
55 extern dev_t
mdevlookup(int devid
);
56 extern void mdevremoveall(void);
57 extern int mdevgetrange(int devid
, uint64_t *base
, uint64_t *size
);
58 extern void di_root_ramfile(IORegistryEntry
* entry
);
61 #define IOPOLLED_COREFILE (CONFIG_KDP_INTERACTIVE_DEBUGGING)
63 #if defined(XNU_TARGET_OS_BRIDGE)
65 #define kIOCoreDumpSize 150ULL*1024ULL*1024ULL
66 // leave free space on volume:
67 #define kIOCoreDumpFreeSize 150ULL*1024ULL*1024ULL
68 #define kIOCoreDumpPath "/private/var/internal/kernelcore"
70 #else /* defined(XNU_TARGET_OS_BRIDGE) */
71 #define kIOCoreDumpMinSize 350ULL*1024ULL*1024ULL
72 #define kIOCoreDumpLargeSize 500ULL*1024ULL*1024ULL
73 // leave free space on volume:
74 #define kIOCoreDumpFreeSize 350ULL*1024ULL*1024ULL
75 #define kIOCoreDumpPath "/private/var/vm/kernelcore"
77 #endif /* defined(XNU_TARGET_OS_BRIDGE) */
79 #elif DEVELOPMENT /* CONFIG_EMBEDDED */
80 #define IOPOLLED_COREFILE 1
82 #define kIOCoreDumpSize 0ULL
83 #define kIOCoreDumpFreeSize 0ULL
84 #else /* CONFIG_EMBEDDED */
85 #define IOPOLLED_COREFILE 0
86 #endif /* CONFIG_EMBEDDED */
91 NewKernelCoreMedia(void * target
, void * refCon
,
92 IOService
* newService
,
93 IONotifier
* notifier
);
94 #endif /* IOPOLLED_COREFILE */
96 #if CONFIG_KDP_INTERACTIVE_DEBUGGING
98 * Touched by IOFindBSDRoot() if a RAMDisk is used for the root device.
100 extern uint64_t kdp_core_ramdisk_addr
;
101 extern uint64_t kdp_core_ramdisk_size
;
107 IOService::publishResource("IOBSD");
109 return kIOReturnSuccess
;
113 IOServicePublishResource( const char * property
, boolean_t value
)
116 IOService::publishResource( property
, kOSBooleanTrue
);
118 IOService::getResourceService()->removeProperty( property
);
123 IOServiceWaitForMatchingResource( const char * property
, uint64_t timeout
)
125 OSDictionary
* dict
= 0;
126 IOService
* match
= 0;
127 boolean_t found
= false;
130 dict
= IOService::resourceMatching( property
);
134 match
= IOService::waitForMatchingService( dict
, timeout
);
151 IOCatalogueMatchingDriversPresent( const char * property
)
153 OSDictionary
* dict
= 0;
154 OSOrderedSet
* set
= 0;
155 SInt32 generationCount
= 0;
156 boolean_t found
= false;
159 dict
= OSDictionary::withCapacity(1);
163 dict
->setObject( property
, kOSBooleanTrue
);
164 set
= gIOCatalogue
->findDrivers( dict
, &generationCount
);
165 if (set
&& (set
->getCount() > 0)) {
181 IOBSDNameMatching( const char * name
)
184 const OSSymbol
* str
= 0;
187 dict
= IOService::serviceMatching( gIOServiceKey
);
191 str
= OSSymbol::withCString( name
);
195 dict
->setObject( kIOBSDNameKey
, (OSObject
*) str
);
212 IOUUIDMatching( void )
214 return IOService::resourceMatching( "boot-uuid-media" );
218 IONetworkNamePrefixMatching( const char * prefix
)
220 OSDictionary
* matching
;
221 OSDictionary
* propDict
= 0;
222 const OSSymbol
* str
= 0;
223 char networkType
[128];
226 matching
= IOService::serviceMatching( "IONetworkInterface" );
231 propDict
= OSDictionary::withCapacity(1);
236 str
= OSSymbol::withCString( prefix
);
241 propDict
->setObject( "IOInterfaceNamePrefix", (OSObject
*) str
);
245 // see if we're contrained to netroot off of specific network type
246 if (PE_parse_boot_argn( "network-type", networkType
, 128 )) {
247 str
= OSSymbol::withCString( networkType
);
249 propDict
->setObject( "IONetworkRootType", str
);
255 if (matching
->setObject( gIOPropertyMatchKey
,
256 (OSObject
*) propDict
) != true) {
280 IORegisterNetworkInterface( IOService
* netif
)
282 // A network interface is typically named and registered
283 // with BSD after receiving a request from a user space
284 // "namer". However, for cases when the system needs to
285 // root from the network, this registration task must be
286 // done inside the kernel and completed before the root
287 // device is handed to BSD.
292 OSDictionary
* dict
= 0;
295 enum { kMaxPathLen
= 512 };
298 stack
= IOService::waitForService(
299 IOService::serviceMatching("IONetworkStack"));
304 dict
= OSDictionary::withCapacity(3);
309 zero
= OSNumber::withNumber((UInt64
) 0, 32);
314 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
320 if (netif
->getPath( pathBuf
, &len
, gIOServicePlane
)
325 path
= OSString::withCStringNoCopy( pathBuf
);
330 dict
->setObject( "IOInterfaceUnit", zero
);
331 dict
->setObject( kIOPathMatchKey
, path
);
333 stack
->setProperties( dict
);
346 IOFree(pathBuf
, kMaxPathLen
);
349 return netif
->getProperty( kIOBSDNameKey
) != 0;
353 IOOFPathMatching( const char * path
, char * buf
, int maxLen
)
355 OSDictionary
* matching
= NULL
;
361 len
= strlen( kIODeviceTreePlane
":" );
367 strlcpy( buf
, kIODeviceTreePlane
":", len
+ 1 );
370 len
= strlen( path
);
375 strlcpy( comp
, path
, len
+ 1 );
377 matching
= OSDictionary::withCapacity( 1 );
382 str
= OSString::withCString( buf
);
386 matching
->setObject( kIOPathMatchKey
, str
);
399 static int didRam
= 0;
400 enum { kMaxPathBuf
= 512, kMaxBootVar
= 128 };
403 IOFindBSDRoot( char * rootName
, unsigned int rootNameSize
,
404 dev_t
* root
, u_int32_t
* oflags
)
408 IORegistryEntry
* regEntry
;
409 OSDictionary
* matching
= 0;
416 const char * mediaProperty
= 0;
419 const char * look
= 0;
421 bool debugInfoPrintedOnce
= false;
422 const char * uuidStr
= NULL
;
424 static int mountAttempts
= 0;
428 // stall here for anyone matching on the IOBSD resource to finish (filesystems)
429 matching
= IOService::serviceMatching(gIOResourcesKey
);
431 matching
->setObject(gIOResourceMatchedKey
, gIOBSDKey
);
433 if ((service
= IOService::waitForMatchingService(matching
, 30ULL * kSecondScale
))) {
441 if (mountAttempts
++) {
442 IOLog("mount(%d) failed\n", mountAttempts
);
446 str
= (char *) IOMalloc( kMaxPathBuf
+ kMaxBootVar
);
448 return kIOReturnNoMemory
;
450 rdBootVar
= str
+ kMaxPathBuf
;
452 if (!PE_parse_boot_argn("rd", rdBootVar
, kMaxBootVar
)
453 && !PE_parse_boot_argn("rootdev", rdBootVar
, kMaxBootVar
)) {
458 if ((regEntry
= IORegistryEntry::fromPath( "/chosen", gIODTPlane
))) {
459 di_root_ramfile(regEntry
);
460 data
= OSDynamicCast(OSData
, regEntry
->getProperty( "root-matching" ));
462 matching
= OSDynamicCast(OSDictionary
, OSUnserializeXML((char *)data
->getBytesNoCopy()));
468 data
= (OSData
*) regEntry
->getProperty( "boot-uuid" );
470 uuidStr
= (const char*)data
->getBytesNoCopy();
471 OSString
*uuidString
= OSString::withCString( uuidStr
);
473 // match the boot-args boot-uuid processing below
475 IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr
);
476 IOService::publishResource( "boot-uuid", uuidString
);
477 uuidString
->release();
478 matching
= IOUUIDMatching();
479 mediaProperty
= "boot-uuid-media";
491 // See if we have a RAMDisk property in /chosen/memory-map. If so, make it into a device.
492 // It will become /dev/mdx, where x is 0-f.
495 if (!didRam
) { /* Have we already build this ram disk? */
496 didRam
= 1; /* Remember we did this */
497 if ((regEntry
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
))) { /* Find the map node */
498 data
= (OSData
*)regEntry
->getProperty("RAMDisk"); /* Find the ram disk, if there */
499 if (data
) { /* We found one */
500 uintptr_t *ramdParms
;
501 ramdParms
= (uintptr_t *)data
->getBytesNoCopy(); /* Point to the ram disk base and size */
502 (void)mdevadd(-1, ml_static_ptovirt(ramdParms
[0]) >> 12, ramdParms
[1] >> 12, 0); /* Initialize it and pass back the device number */
504 regEntry
->release(); /* Toss the entry */
509 // Now check if we are trying to root on a memory device
512 if ((rdBootVar
[0] == 'm') && (rdBootVar
[1] == 'd') && (rdBootVar
[3] == 0)) {
513 dchar
= xchar
= rdBootVar
[2]; /* Get the actual device */
514 if ((xchar
>= '0') && (xchar
<= '9')) {
515 xchar
= xchar
- '0'; /* If digit, convert */
517 xchar
= xchar
& ~' '; /* Fold to upper case */
518 if ((xchar
>= 'A') && (xchar
<= 'F')) { /* Is this a valid digit? */
519 xchar
= (xchar
& 0xF) + 9; /* Convert the hex digit */
520 dchar
= dchar
| ' '; /* Fold to lower case */
522 xchar
= -1; /* Show bogus */
525 if (xchar
>= 0) { /* Do we have a valid memory device name? */
526 *root
= mdevlookup(xchar
); /* Find the device number */
527 if (*root
>= 0) { /* Did we find one? */
528 rootName
[0] = 'm'; /* Build root name */
529 rootName
[1] = 'd'; /* Build root name */
530 rootName
[2] = dchar
; /* Build root name */
531 rootName
[3] = 0; /* Build root name */
532 IOLog("BSD root: %s, major %d, minor %d\n", rootName
, major(*root
), minor(*root
));
533 *oflags
= 0; /* Show that this is not network */
535 #if CONFIG_KDP_INTERACTIVE_DEBUGGING
536 /* retrieve final ramdisk range and initialize KDP variables */
537 if (mdevgetrange(xchar
, &kdp_core_ramdisk_addr
, &kdp_core_ramdisk_size
) != 0) {
538 IOLog("Unable to retrieve range for root memory device %d\n", xchar
);
539 kdp_core_ramdisk_addr
= 0;
540 kdp_core_ramdisk_size
= 0;
544 goto iofrootx
; /* Join common exit... */
546 panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar
); /* Not there */
550 if ((!matching
) && rdBootVar
[0]) {
553 if (look
[0] == '*') {
557 if (strncmp( look
, "en", strlen( "en" )) == 0) {
558 matching
= IONetworkNamePrefixMatching( "en" );
559 } else if (strncmp( look
, "uuid", strlen( "uuid" )) == 0) {
561 OSString
*uuidString
;
563 uuid
= (char *)IOMalloc( kMaxBootVar
);
566 if (!PE_parse_boot_argn( "boot-uuid", uuid
, kMaxBootVar
)) {
567 panic( "rd=uuid but no boot-uuid=<value> specified" );
569 uuidString
= OSString::withCString( uuid
);
571 IOService::publishResource( "boot-uuid", uuidString
);
572 uuidString
->release();
573 IOLog( "\nWaiting for boot volume with UUID %s\n", uuid
);
574 matching
= IOUUIDMatching();
575 mediaProperty
= "boot-uuid-media";
577 IOFree( uuid
, kMaxBootVar
);
580 matching
= IOBSDNameMatching( look
);
586 // Match any HFS media
588 matching
= IOService::serviceMatching( "IOMedia" );
589 astring
= OSString::withCStringNoCopy("Apple_HFS");
591 matching
->setObject("Content", astring
);
596 if (gIOKitDebug
& kIOWaitQuietBeforeRoot
) {
597 IOLog( "Waiting for matching to complete\n" );
598 IOService::getPlatform()->waitQuiet();
601 if (true && matching
) {
602 OSSerialize
* s
= OSSerialize::withCapacity( 5 );
604 if (matching
->serialize( s
)) {
605 IOLog( "Waiting on %s\n", s
->text());
611 t
.tv_sec
= ROOTDEVICETIMEOUT
;
614 service
= IOService::waitForService( matching
, &t
);
615 if ((!service
) || (mountAttempts
== 10)) {
616 PE_display_icon( 0, "noroot");
617 IOLog( "Still waiting for root device\n" );
619 if (!debugInfoPrintedOnce
) {
620 debugInfoPrintedOnce
= true;
621 if (gIOKitDebug
& kIOLogDTree
) {
622 IOLog("\nDT plane:\n");
623 IOPrintPlane( gIODTPlane
);
625 if (gIOKitDebug
& kIOLogServiceTree
) {
626 IOLog("\nService plane:\n");
627 IOPrintPlane( gIOServicePlane
);
629 if (gIOKitDebug
& kIOLogMemory
) {
637 if (service
&& mediaProperty
) {
638 service
= (IOService
*)service
->getProperty(mediaProperty
);
644 // If the IOService we matched to is a subclass of IONetworkInterface,
645 // then make sure it has been registered with BSD and has a BSD name
649 && service
->metaCast( "IONetworkInterface" )
650 && !IORegisterNetworkInterface( service
)) {
656 service
->getPath( str
, &len
, gIOServicePlane
);
657 IOLog( "Got boot device = %s\n", str
);
659 iostr
= (OSString
*) service
->getProperty( kIOBSDNameKey
);
661 strlcpy( rootName
, iostr
->getCStringNoCopy(), rootNameSize
);
663 off
= (OSNumber
*) service
->getProperty( kIOBSDMajorKey
);
665 mjr
= off
->unsigned32BitValue();
667 off
= (OSNumber
*) service
->getProperty( kIOBSDMinorKey
);
669 mnr
= off
->unsigned32BitValue();
672 if (service
->metaCast( "IONetworkInterface" )) {
676 IOLog( "Wait for root failed\n" );
677 strlcpy( rootName
, "en0", rootNameSize
);
681 IOLog( "BSD root: %s", rootName
);
683 IOLog(", major %d, minor %d\n", mjr
, mnr
);
688 *root
= makedev( mjr
, mnr
);
691 IOFree( str
, kMaxPathBuf
+ kMaxBootVar
);
694 if ((gIOKitDebug
& (kIOLogDTree
| kIOLogServiceTree
| kIOLogMemory
)) && !debugInfoPrintedOnce
) {
695 IOService::getPlatform()->waitQuiet();
696 if (gIOKitDebug
& kIOLogDTree
) {
697 IOLog("\nDT plane:\n");
698 IOPrintPlane( gIODTPlane
);
700 if (gIOKitDebug
& kIOLogServiceTree
) {
701 IOLog("\nService plane:\n");
702 IOPrintPlane( gIOServicePlane
);
704 if (gIOKitDebug
& kIOLogMemory
) {
709 return kIOReturnSuccess
;
713 IORamDiskBSDRoot(void)
715 char rdBootVar
[kMaxBootVar
];
716 if (PE_parse_boot_argn("rd", rdBootVar
, kMaxBootVar
)
717 || PE_parse_boot_argn("rootdev", rdBootVar
, kMaxBootVar
)) {
718 if ((rdBootVar
[0] == 'm') && (rdBootVar
[1] == 'd') && (rdBootVar
[3] == 0)) {
726 IOSecureBSDRoot(const char * rootName
)
731 IOPlatformExpert
*pe
;
732 OSDictionary
*matching
;
733 const OSSymbol
*functionName
= OSSymbol::withCStringNoCopy("SecureRootName");
735 matching
= IOService::serviceMatching("IOPlatformExpert");
737 pe
= (IOPlatformExpert
*) IOService::waitForMatchingService(matching
, 30ULL * kSecondScale
);
740 // Returns kIOReturnNotPrivileged is the root device is not secure.
741 // Returns kIOReturnUnsupported if "SecureRootName" is not implemented.
742 result
= pe
->callPlatformFunction(functionName
, false, (void *)rootName
, (void *)0, (void *)0, (void *)0);
743 functionName
->release();
744 OSSafeReleaseNULL(pe
);
746 if (result
== kIOReturnNotPrivileged
) {
748 } else if (result
== kIOReturnSuccess
) {
749 // If we are booting with a secure root, and we have the right
750 // boot-arg, we will want to panic on exception triage. This
751 // behavior is intended as a debug aid (we can look at why an
752 // exception occured in the kernel debugger).
753 if (PE_parse_boot_argn("-panic_on_exception_triage", &tmpInt
, sizeof(tmpInt
))) {
754 panic_on_exception_triage
= 1;
758 #endif // CONFIG_EMBEDDED
762 IOBSDRegistryEntryForDeviceTree(char * path
)
764 return IORegistryEntry::fromPath(path
, gIODTPlane
);
768 IOBSDRegistryEntryRelease(void * entry
)
770 IORegistryEntry
* regEntry
= (IORegistryEntry
*)entry
;
779 IOBSDRegistryEntryGetData(void * entry
, char * property_name
,
783 IORegistryEntry
* regEntry
= (IORegistryEntry
*)entry
;
785 data
= (OSData
*) regEntry
->getProperty(property_name
);
787 *packet_length
= data
->getLength();
788 return data
->getBytesNoCopy();
794 IOBSDGetPlatformUUID( uuid_t uuid
, mach_timespec_t timeout
)
796 IOService
* resources
;
799 resources
= IOService::waitForService( IOService::resourceMatching( kIOPlatformUUIDKey
), (timeout
.tv_sec
|| timeout
.tv_nsec
) ? &timeout
: 0 );
800 if (resources
== 0) {
801 return KERN_OPERATION_TIMED_OUT
;
804 string
= (OSString
*) IOService::getPlatform()->getProvider()->getProperty( kIOPlatformUUIDKey
);
806 return KERN_NOT_SUPPORTED
;
809 uuid_parse( string
->getCStringNoCopy(), uuid
);
815 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
817 #include <sys/conf.h>
818 #include <sys/vnode.h>
819 #include <sys/vnode_internal.h>
820 #include <sys/fcntl.h>
821 #include <IOKit/IOPolledInterface.h>
822 #include <IOKit/IOBufferMemoryDescriptor.h>
824 IOPolledFileIOVars
* gIOPolledCoreFileVars
;
825 kern_return_t gIOPolledCoreFileOpenRet
= kIOReturnNotReady
;
826 #if IOPOLLED_COREFILE
829 IOOpenPolledCoreFile(const char * filename
)
833 uint64_t corefile_size_bytes
= 0;
835 if (gIOPolledCoreFileVars
) {
836 return kIOReturnBusy
;
838 if (!IOPolledInterface::gMetaClass
.getInstanceCount()) {
839 return kIOReturnUnsupported
;
843 PE_parse_boot_argn("debug", &debug
, sizeof(debug
));
844 if (DB_DISABLE_LOCAL_CORE
& debug
) {
845 return kIOReturnUnsupported
;
849 unsigned int requested_corefile_size
= 0;
850 if (PE_parse_boot_argn("corefile_size_mb", &requested_corefile_size
, sizeof(requested_corefile_size
))) {
851 IOLog("Boot-args specify %d MB kernel corefile\n", requested_corefile_size
);
853 corefile_size_bytes
= (requested_corefile_size
* 1024ULL * 1024ULL);
859 #if defined(kIOCoreDumpLargeSize)
860 if (0 == corefile_size_bytes
) {
861 // If no custom size was requested and we're on a device with >3GB of DRAM, attempt
862 // to allocate a large corefile otherwise use a small file.
863 if (max_mem
> (3 * 1024ULL * 1024ULL * 1024ULL)) {
864 corefile_size_bytes
= kIOCoreDumpLargeSize
;
865 err
= IOPolledFileOpen(filename
,
867 corefile_size_bytes
, kIOCoreDumpFreeSize
,
869 &gIOPolledCoreFileVars
, NULL
, NULL
, 0);
870 if (kIOReturnSuccess
== err
) {
872 } else if (kIOReturnNoSpace
== err
) {
873 IOLog("Failed to open corefile of size %llu MB (low disk space)",
874 (corefile_size_bytes
/ (1024ULL * 1024ULL)));
875 if (corefile_size_bytes
== kIOCoreDumpMinSize
) {
876 gIOPolledCoreFileOpenRet
= err
;
879 // Try to open a smaller corefile (set size and fall-through)
880 corefile_size_bytes
= kIOCoreDumpMinSize
;
882 IOLog("Failed to open corefile of size %llu MB (returned error 0x%x)\n",
883 (corefile_size_bytes
/ (1024ULL * 1024ULL)), err
);
884 gIOPolledCoreFileOpenRet
= err
;
888 corefile_size_bytes
= kIOCoreDumpMinSize
;
891 #else /* defined(kIOCoreDumpLargeSize) */
892 if (0 == corefile_size_bytes
) {
893 corefile_size_bytes
= kIOCoreDumpSize
;
895 #endif /* defined(kIOCoreDumpLargeSize) */
896 err
= IOPolledFileOpen(filename
,
898 corefile_size_bytes
, kIOCoreDumpFreeSize
,
900 &gIOPolledCoreFileVars
, NULL
, NULL
, 0);
901 if (kIOReturnSuccess
!= err
) {
902 IOLog("Failed to open corefile of size %llu MB (returned error 0x%x)\n",
903 (corefile_size_bytes
/ (1024ULL * 1024ULL)), err
);
904 gIOPolledCoreFileOpenRet
= err
;
909 err
= IOPolledFilePollersSetup(gIOPolledCoreFileVars
, kIOPolledPreflightCoreDumpState
);
910 if (kIOReturnSuccess
!= err
) {
911 IOPolledFileClose(&gIOPolledCoreFileVars
, NULL
, NULL
, 0, 0, 0);
912 IOLog("IOPolledFilePollersSetup for corefile failed with error: 0x%x\n", err
);
913 gIOPolledCoreFileOpenRet
= err
;
915 IOLog("Opened corefile of size %llu MB\n", (corefile_size_bytes
/ (1024ULL * 1024ULL)));
922 IOClosePolledCoreFile(void)
924 gIOPolledCoreFileOpenRet
= kIOReturnNotOpen
;
925 IOPolledFilePollersClose(gIOPolledCoreFileVars
, kIOPolledPostflightCoreDumpState
);
926 IOPolledFileClose(&gIOPolledCoreFileVars
, NULL
, NULL
, 0, 0, 0);
929 static thread_call_t gIOOpenPolledCoreFileTC
;
930 static IONotifier
* gIOPolledCoreFileNotifier
;
931 static IONotifier
* gIOPolledCoreFileInterestNotifier
;
934 KernelCoreMediaInterest(void * target
, void * refCon
,
935 UInt32 messageType
, IOService
* provider
,
936 void * messageArgument
, vm_size_t argSize
)
938 if (kIOMessageServiceIsTerminated
== messageType
) {
939 gIOPolledCoreFileInterestNotifier
->remove();
940 gIOPolledCoreFileInterestNotifier
= 0;
941 IOClosePolledCoreFile();
944 return kIOReturnSuccess
;
948 OpenKernelCoreMedia(thread_call_param_t p0
, thread_call_param_t p1
)
950 IOService
* newService
;
954 newService
= (IOService
*) p1
;
956 if (gIOPolledCoreFileVars
) {
959 string
= OSDynamicCast(OSString
, newService
->getProperty(kIOBSDNameKey
));
963 snprintf(filename
, sizeof(filename
), "/dev/%s", string
->getCStringNoCopy());
964 if (kIOReturnSuccess
!= IOOpenPolledCoreFile(filename
)) {
967 gIOPolledCoreFileInterestNotifier
= newService
->registerInterest(
968 gIOGeneralInterest
, &KernelCoreMediaInterest
, NULL
, 0);
971 newService
->release();
975 NewKernelCoreMedia(void * target
, void * refCon
,
976 IOService
* newService
,
977 IONotifier
* notifier
)
979 static volatile UInt32 onlyOneCorePartition
= 0;
981 if (!OSCompareAndSwap(0, 1, &onlyOneCorePartition
)) {
984 if (gIOPolledCoreFileVars
) {
987 if (!gIOOpenPolledCoreFileTC
) {
990 newService
= newService
->getProvider();
994 newService
->retain();
995 thread_call_enter1(gIOOpenPolledCoreFileTC
, newService
);
1001 #endif /* IOPOLLED_COREFILE */
1004 IOBSDMountChange(struct mount
* mp
, uint32_t op
)
1006 #if IOPOLLED_COREFILE
1008 OSDictionary
* bsdMatching
;
1009 OSDictionary
* mediaMatching
;
1012 if (!gIOPolledCoreFileNotifier
) {
1014 if (!gIOOpenPolledCoreFileTC
) {
1015 gIOOpenPolledCoreFileTC
= thread_call_allocate(&OpenKernelCoreMedia
, NULL
);
1017 bsdMatching
= IOService::serviceMatching("IOMediaBSDClient");
1021 mediaMatching
= IOService::serviceMatching("IOMedia");
1022 string
= OSString::withCStringNoCopy("5361644D-6163-11AA-AA11-00306543ECAC");
1023 if (!string
|| !mediaMatching
) {
1026 mediaMatching
->setObject("Content", string
);
1028 bsdMatching
->setObject(gIOParentMatchKey
, mediaMatching
);
1029 mediaMatching
->release();
1031 gIOPolledCoreFileNotifier
= IOService::addMatchingNotification(
1032 gIOFirstMatchNotification
, bsdMatching
,
1033 &NewKernelCoreMedia
, NULL
, NULL
, -1000);
1045 case kIOMountChangeMount
:
1046 case kIOMountChangeDidResize
:
1048 if (gIOPolledCoreFileVars
) {
1051 flags
= vfs_flags(mp
);
1052 if (MNT_RDONLY
& flags
) {
1055 if (!(MNT_LOCAL
& flags
)) {
1059 vn
= vfs_vnodecovered(mp
);
1063 pathLen
= sizeof(path
);
1064 result
= vn_getpath(vn
, &path
[0], &pathLen
);
1072 #if defined(XNU_TARGET_OS_BRIDGE)
1073 // on bridgeOS systems we put the core in /private/var/internal. We don't
1074 // want to match with /private/var because /private/var/internal is often mounted
1075 // over /private/var
1076 if ((pathLen
- 1) < (int) strlen("/private/var/internal")) {
1080 if (0 != strncmp(path
, kIOCoreDumpPath
, pathLen
- 1)) {
1083 IOOpenPolledCoreFile(kIOCoreDumpPath
);
1086 case kIOMountChangeUnmount
:
1087 case kIOMountChangeWillResize
:
1088 if (gIOPolledCoreFileVars
&& (mp
== kern_file_mount(gIOPolledCoreFileVars
->fileRef
))) {
1089 IOClosePolledCoreFile();
1093 #endif /* CONFIG_EMBEDDED */
1094 #endif /* IOPOLLED_COREFILE */
1097 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1099 extern "C" boolean_t
1100 IOTaskHasEntitlement(task_t task
, const char * entitlement
)
1103 obj
= IOUserClient::copyClientEntitlement(task
, entitlement
);
1108 return obj
!= kOSBooleanFalse
;