X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..3903760236c30e3b5ace7a4eefac3a269d68957c:/iokit/bsddev/IOKitBSDInit.cpp diff --git a/iokit/bsddev/IOKitBSDInit.cpp b/iokit/bsddev/IOKitBSDInit.cpp index 9b08bb834..a35aa5495 100644 --- a/iokit/bsddev/IOKitBSDInit.cpp +++ b/iokit/bsddev/IOKitBSDInit.cpp @@ -32,6 +32,7 @@ #include #include #include +#include extern "C" { @@ -39,6 +40,7 @@ extern "C" { #include #include #include +#include // how long to wait for matching root device, secs #if DEBUG @@ -47,11 +49,40 @@ extern "C" { #define ROOTDEVICETIMEOUT 60 #endif +int panic_on_exception_triage = 0; + extern dev_t mdevadd(int devid, uint64_t base, unsigned int size, int phys); extern dev_t mdevlookup(int devid); extern void mdevremoveall(void); +extern int mdevgetrange(int devid, uint64_t *base, uint64_t *size); extern void di_root_ramfile(IORegistryEntry * entry); + +#if DEVELOPMENT +#define IOPOLLED_COREFILE 1 +// no sizing +#define kIOCoreDumpSize 0ULL +#define kIOCoreDumpFreeSize 0ULL +#else +#define IOPOLLED_COREFILE 0 +#endif + + +#if IOPOLLED_COREFILE +static bool +NewKernelCoreMedia(void * target, void * refCon, + IOService * newService, + IONotifier * notifier); +#endif /* IOPOLLED_COREFILE */ + +#if CONFIG_KDP_INTERACTIVE_DEBUGGING +/* + * Touched by IOFindBSDRoot() if a RAMDisk is used for the root device. + */ +extern uint64_t kdp_core_ramdisk_addr; +extern uint64_t kdp_core_ramdisk_size; +#endif + kern_return_t IOKitBSDInit( void ) { @@ -333,10 +364,25 @@ kern_return_t IOFindBSDRoot( char * rootName, unsigned int rootNameSize, static int mountAttempts = 0; int xchar, dchar; - + + // stall here for anyone matching on the IOBSD resource to finish (filesystems) + matching = IOService::serviceMatching(gIOResourcesKey); + assert(matching); + matching->setObject(gIOResourceMatchedKey, gIOBSDKey); + + if ((service = IOService::waitForMatchingService(matching, 30ULL * kSecondScale))) { + service->release(); + } else { + IOLog("!BSD\n"); + } + matching->release(); + matching = NULL; if( mountAttempts++) + { + IOLog("mount(%d) failed\n", mountAttempts); IOSleep( 5 * 1000 ); + } str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar ); if( !str) @@ -416,13 +462,22 @@ kern_return_t IOFindBSDRoot( char * rootName, unsigned int rootNameSize, if(xchar >= 0) { /* Do we have a valid memory device name? */ *root = mdevlookup(xchar); /* Find the device number */ if(*root >= 0) { /* Did we find one? */ - rootName[0] = 'm'; /* Build root name */ rootName[1] = 'd'; /* Build root name */ rootName[2] = dchar; /* Build root name */ rootName[3] = 0; /* Build root name */ IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root)); *oflags = 0; /* Show that this is not network */ + +#if CONFIG_KDP_INTERACTIVE_DEBUGGING + /* retrieve final ramdisk range and initialize KDP variables */ + if (mdevgetrange(xchar, &kdp_core_ramdisk_addr, &kdp_core_ramdisk_size) != 0) { + IOLog("Unable to retrieve range for root memory device %d\n", xchar); + kdp_core_ramdisk_addr = 0; + kdp_core_ramdisk_size = 0; + } +#endif + goto iofrootx; /* Join common exit... */ } panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar); /* Not there */ @@ -651,115 +706,160 @@ kern_return_t IOBSDGetPlatformUUID( uuid_t uuid, mach_timespec_t timeout ) return KERN_SUCCESS; } -kern_return_t IOBSDGetPlatformSerialNumber( char *serial_number_str, u_int32_t len ) +} /* extern "C" */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include +#include +#include +#include + +IOPolledFileIOVars * gIOPolledCoreFileVars; + +#if IOPOLLED_COREFILE + +static IOReturn +IOOpenPolledCoreFile(const char * filename) { - OSDictionary * platform_dict; - IOService *platform; - OSString * string; + IOReturn err; + unsigned int debug; + + if (gIOPolledCoreFileVars) return (kIOReturnBusy); + if (!IOPolledInterface::gMetaClass.getInstanceCount()) return (kIOReturnUnsupported); + + debug = 0; + PE_parse_boot_argn("debug", &debug, sizeof (debug)); + if (DB_DISABLE_LOCAL_CORE & debug) return (kIOReturnUnsupported); - if (len < 1) { - return 0; + err = IOPolledFileOpen(filename, kIOCoreDumpSize, kIOCoreDumpFreeSize, + NULL, 0, + &gIOPolledCoreFileVars, NULL, NULL, 0); + if (kIOReturnSuccess != err) return (err); + + err = IOPolledFilePollersSetup(gIOPolledCoreFileVars, kIOPolledPreflightCoreDumpState); + if (kIOReturnSuccess != err) + { + IOPolledFileClose(&gIOPolledCoreFileVars, NULL, NULL, 0, 0, 0); } - serial_number_str[0] = '\0'; - platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" ); - if (platform_dict == NULL) { - return KERN_NOT_SUPPORTED; + return (err); +} + +static void +IOClosePolledCoreFile(void) +{ + IOPolledFilePollersClose(gIOPolledCoreFileVars, kIOPolledPostflightCoreDumpState); + IOPolledFileClose(&gIOPolledCoreFileVars, NULL, NULL, 0, 0, 0); +} + +static thread_call_t gIOOpenPolledCoreFileTC; +static IONotifier * gIOPolledCoreFileNotifier; +static IONotifier * gIOPolledCoreFileInterestNotifier; + +static IOReturn +KernelCoreMediaInterest(void * target, void * refCon, + UInt32 messageType, IOService * provider, + void * messageArgument, vm_size_t argSize ) +{ + if (kIOMessageServiceIsTerminated == messageType) + { + gIOPolledCoreFileInterestNotifier->remove(); + gIOPolledCoreFileInterestNotifier = 0; + IOClosePolledCoreFile(); } - platform = IOService::waitForService( platform_dict ); - if (platform) { - string = ( OSString * ) platform->getProperty( kIOPlatformSerialNumberKey ); - if ( string == 0 ) { - return KERN_NOT_SUPPORTED; - } else { - strlcpy( serial_number_str, string->getCStringNoCopy( ), len ); - } + return (kIOReturnSuccess); +} + +static void +OpenKernelCoreMedia(thread_call_param_t p0, thread_call_param_t p1) +{ + IOService * newService; + OSString * string; + char filename[16]; + + newService = (IOService *) p1; + do + { + if (gIOPolledCoreFileVars) break; + string = OSDynamicCast(OSString, newService->getProperty(kIOBSDNameKey)); + if (!string) break; + snprintf(filename, sizeof(filename), "/dev/%s", string->getCStringNoCopy()); + if (kIOReturnSuccess != IOOpenPolledCoreFile(filename)) break; + gIOPolledCoreFileInterestNotifier = newService->registerInterest( + gIOGeneralInterest, &KernelCoreMediaInterest, NULL, 0); } - - return KERN_SUCCESS; + while (false); + + newService->release(); } -void IOBSDIterateMediaWithContent(const char *content_uuid_cstring, int (*func)(const char *bsd_dev_name, const char *uuid_str, void *arg), void *arg) +static bool +NewKernelCoreMedia(void * target, void * refCon, + IOService * newService, + IONotifier * notifier) { - OSDictionary *dictionary; - OSString *content_uuid_string; - - dictionary = IOService::serviceMatching( "IOMedia" ); - if( dictionary ) { - content_uuid_string = OSString::withCString( content_uuid_cstring ); - if( content_uuid_string ) { - IOService *service; - OSIterator *iter; - - dictionary->setObject( "Content", content_uuid_string ); - dictionary->retain(); - - iter = IOService::getMatchingServices(dictionary); - while (iter && (service = (IOService *)iter->getNextObject())) { - if( service ) { - OSString *iostr = (OSString *) service->getProperty( kIOBSDNameKey ); - OSString *uuidstr = (OSString *) service->getProperty( "UUID" ); - const char *uuid; - - if( iostr) { - if (uuidstr) { - uuid = uuidstr->getCStringNoCopy(); - } else { - uuid = "00000000-0000-0000-0000-000000000000"; - } - - // call the callback - if (func && func(iostr->getCStringNoCopy(), uuid, arg) == 0) { - break; - } - } - } - } - if (iter) - iter->release(); - - content_uuid_string->release(); - } - dictionary->release(); + static volatile UInt32 onlyOneCorePartition = 0; + do + { + if (!OSCompareAndSwap(0, 1, &onlyOneCorePartition)) break; + if (gIOPolledCoreFileVars) break; + if (!gIOOpenPolledCoreFileTC) break; + newService = newService->getProvider(); + if (!newService) break; + newService->retain(); + thread_call_enter1(gIOOpenPolledCoreFileTC, newService); } + while (false); + + return (false); } +#endif /* IOPOLLED_COREFILE */ -int IOBSDIsMediaEjectable( const char *cdev_name ) +extern "C" void +IOBSDMountChange(struct mount * mp, uint32_t op) { - int ret = 0; - OSDictionary *dictionary; - OSString *dev_name; +#if IOPOLLED_COREFILE + + OSDictionary * bsdMatching; + OSDictionary * mediaMatching; + OSString * string; - if (strncmp(cdev_name, "/dev/", 5) == 0) { - cdev_name += 5; + if (!gIOPolledCoreFileNotifier) do + { + if (!gIOOpenPolledCoreFileTC) gIOOpenPolledCoreFileTC = thread_call_allocate(&OpenKernelCoreMedia, NULL); + bsdMatching = IOService::serviceMatching("IOMediaBSDClient"); + if (!bsdMatching) break; + mediaMatching = IOService::serviceMatching("IOMedia"); + string = OSString::withCStringNoCopy("5361644D-6163-11AA-AA11-00306543ECAC"); + if (!string || !mediaMatching) break; + mediaMatching->setObject("Content", string); + string->release(); + bsdMatching->setObject(gIOParentMatchKey, mediaMatching); + mediaMatching->release(); + + gIOPolledCoreFileNotifier = IOService::addMatchingNotification( + gIOFirstMatchNotification, bsdMatching, + &NewKernelCoreMedia, NULL, NULL, -1000); } + while (false); - dictionary = IOService::serviceMatching( "IOMedia" ); - if( dictionary ) { - dev_name = OSString::withCString( cdev_name ); - if( dev_name ) { - IOService *service; - mach_timespec_t tv = { 5, 0 }; // wait up to "timeout" seconds for the device - - dictionary->setObject( kIOBSDNameKey, dev_name ); - dictionary->retain(); - service = IOService::waitForService( dictionary, &tv ); - if( service ) { - OSBoolean *ejectable = (OSBoolean *) service->getProperty( "Ejectable" ); - - if( ejectable ) { - ret = (int)ejectable->getValue(); - } +#endif /* IOPOLLED_COREFILE */ +} - } - dev_name->release(); - } - dictionary->release(); - } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - return ret; +extern "C" boolean_t +IOTaskHasEntitlement(task_t task, const char * entitlement) +{ + OSObject * obj; + obj = IOUserClient::copyClientEntitlement(task, entitlement); + if (!obj) return (false); + obj->release(); + return (obj != kOSBooleanFalse); } -} /* extern "C" */