1*42e22086SApple OSS Distributions /*
2*42e22086SApple OSS Distributions * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
3*42e22086SApple OSS Distributions *
4*42e22086SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*42e22086SApple OSS Distributions *
6*42e22086SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*42e22086SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*42e22086SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*42e22086SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*42e22086SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*42e22086SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*42e22086SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*42e22086SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*42e22086SApple OSS Distributions *
15*42e22086SApple OSS Distributions * Please obtain a copy of the License at
16*42e22086SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*42e22086SApple OSS Distributions *
18*42e22086SApple OSS Distributions * The Original Code and all software distributed under the License are
19*42e22086SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*42e22086SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*42e22086SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*42e22086SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*42e22086SApple OSS Distributions * Please see the License for the specific language governing rights and
24*42e22086SApple OSS Distributions * limitations under the License.
25*42e22086SApple OSS Distributions *
26*42e22086SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*42e22086SApple OSS Distributions */
28*42e22086SApple OSS Distributions #include <IOKit/IOBSD.h>
29*42e22086SApple OSS Distributions #include <IOKit/IOLib.h>
30*42e22086SApple OSS Distributions #include <IOKit/IOService.h>
31*42e22086SApple OSS Distributions #include <IOKit/IOCatalogue.h>
32*42e22086SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
33*42e22086SApple OSS Distributions #include <IOKit/IOKitKeys.h>
34*42e22086SApple OSS Distributions #include <IOKit/IONVRAM.h>
35*42e22086SApple OSS Distributions #include <IOKit/IOPlatformExpert.h>
36*42e22086SApple OSS Distributions #include <IOKit/IOUserClient.h>
37*42e22086SApple OSS Distributions #include <libkern/c++/OSAllocation.h>
38*42e22086SApple OSS Distributions
39*42e22086SApple OSS Distributions extern "C" {
40*42e22086SApple OSS Distributions #include <libkern/amfi/amfi.h>
41*42e22086SApple OSS Distributions #include <sys/codesign.h>
42*42e22086SApple OSS Distributions #include <vm/pmap.h>
43*42e22086SApple OSS Distributions #include <vm/vm_map.h>
44*42e22086SApple OSS Distributions #include <pexpert/pexpert.h>
45*42e22086SApple OSS Distributions #include <kern/clock.h>
46*42e22086SApple OSS Distributions #if CONFIG_KDP_INTERACTIVE_DEBUGGING
47*42e22086SApple OSS Distributions #include <kern/debug.h>
48*42e22086SApple OSS Distributions #endif
49*42e22086SApple OSS Distributions #include <mach/machine.h>
50*42e22086SApple OSS Distributions #include <uuid/uuid.h>
51*42e22086SApple OSS Distributions #include <sys/vnode_internal.h>
52*42e22086SApple OSS Distributions #include <sys/mount.h>
53*42e22086SApple OSS Distributions #include <corecrypto/ccsha2.h>
54*42e22086SApple OSS Distributions
55*42e22086SApple OSS Distributions // how long to wait for matching root device, secs
56*42e22086SApple OSS Distributions #if DEBUG
57*42e22086SApple OSS Distributions #define ROOTDEVICETIMEOUT 120
58*42e22086SApple OSS Distributions #else
59*42e22086SApple OSS Distributions #define ROOTDEVICETIMEOUT 60
60*42e22086SApple OSS Distributions #endif
61*42e22086SApple OSS Distributions
62*42e22086SApple OSS Distributions extern dev_t mdevadd(int devid, uint64_t base, unsigned int size, int phys);
63*42e22086SApple OSS Distributions extern dev_t mdevlookup(int devid);
64*42e22086SApple OSS Distributions extern void mdevremoveall(void);
65*42e22086SApple OSS Distributions extern int mdevgetrange(int devid, uint64_t *base, uint64_t *size);
66*42e22086SApple OSS Distributions extern void di_root_ramfile(IORegistryEntry * entry);
67*42e22086SApple OSS Distributions extern int IODTGetDefault(const char *key, void *infoAddr, unsigned int infoSize);
68*42e22086SApple OSS Distributions extern boolean_t cpuid_vmm_present(void);
69*42e22086SApple OSS Distributions
70*42e22086SApple OSS Distributions #define ROUNDUP(a, b) (((a) + ((b) - 1)) & (~((b) - 1)))
71*42e22086SApple OSS Distributions
72*42e22086SApple OSS Distributions #define IOPOLLED_COREFILE (CONFIG_KDP_INTERACTIVE_DEBUGGING)
73*42e22086SApple OSS Distributions
74*42e22086SApple OSS Distributions #if defined(XNU_TARGET_OS_BRIDGE)
75*42e22086SApple OSS Distributions #define kIOCoreDumpPath "/private/var/internal/kernelcore"
76*42e22086SApple OSS Distributions #elif defined(XNU_TARGET_OS_OSX)
77*42e22086SApple OSS Distributions #define kIOCoreDumpPath "/System/Volumes/VM/kernelcore"
78*42e22086SApple OSS Distributions #else
79*42e22086SApple OSS Distributions #define kIOCoreDumpPath "/private/var/vm/kernelcore"
80*42e22086SApple OSS Distributions #endif
81*42e22086SApple OSS Distributions
82*42e22086SApple OSS Distributions #define SYSTEM_NVRAM_PREFIX "40A0DDD2-77F8-4392-B4A3-1E7304206516:"
83*42e22086SApple OSS Distributions
84*42e22086SApple OSS Distributions #if CONFIG_KDP_INTERACTIVE_DEBUGGING
85*42e22086SApple OSS Distributions /*
86*42e22086SApple OSS Distributions * Touched by IOFindBSDRoot() if a RAMDisk is used for the root device.
87*42e22086SApple OSS Distributions */
88*42e22086SApple OSS Distributions extern uint64_t kdp_core_ramdisk_addr;
89*42e22086SApple OSS Distributions extern uint64_t kdp_core_ramdisk_size;
90*42e22086SApple OSS Distributions
91*42e22086SApple OSS Distributions /*
92*42e22086SApple OSS Distributions * A callback to indicate that the polled-mode corefile is now available.
93*42e22086SApple OSS Distributions */
94*42e22086SApple OSS Distributions extern kern_return_t kdp_core_polled_io_polled_file_available(IOCoreFileAccessCallback access_data, void *access_context, void *recipient_context);
95*42e22086SApple OSS Distributions
96*42e22086SApple OSS Distributions /*
97*42e22086SApple OSS Distributions * A callback to indicate that the polled-mode corefile is no longer available.
98*42e22086SApple OSS Distributions */
99*42e22086SApple OSS Distributions extern kern_return_t kdp_core_polled_io_polled_file_unavailable(void);
100*42e22086SApple OSS Distributions #endif
101*42e22086SApple OSS Distributions
102*42e22086SApple OSS Distributions #if IOPOLLED_COREFILE
103*42e22086SApple OSS Distributions static void IOOpenPolledCoreFile(thread_call_param_t __unused, thread_call_param_t corefilename);
104*42e22086SApple OSS Distributions
105*42e22086SApple OSS Distributions thread_call_t corefile_open_call = NULL;
106*42e22086SApple OSS Distributions #endif
107*42e22086SApple OSS Distributions
108*42e22086SApple OSS Distributions kern_return_t
IOKitBSDInit(void)109*42e22086SApple OSS Distributions IOKitBSDInit( void )
110*42e22086SApple OSS Distributions {
111*42e22086SApple OSS Distributions IOService::publishResource("IOBSD");
112*42e22086SApple OSS Distributions
113*42e22086SApple OSS Distributions #if IOPOLLED_COREFILE
114*42e22086SApple OSS Distributions corefile_open_call = thread_call_allocate_with_options(IOOpenPolledCoreFile, NULL, THREAD_CALL_PRIORITY_KERNEL, THREAD_CALL_OPTIONS_ONCE);
115*42e22086SApple OSS Distributions #endif
116*42e22086SApple OSS Distributions
117*42e22086SApple OSS Distributions return kIOReturnSuccess;
118*42e22086SApple OSS Distributions }
119*42e22086SApple OSS Distributions
120*42e22086SApple OSS Distributions void
IOServicePublishResource(const char * property,boolean_t value)121*42e22086SApple OSS Distributions IOServicePublishResource( const char * property, boolean_t value )
122*42e22086SApple OSS Distributions {
123*42e22086SApple OSS Distributions if (value) {
124*42e22086SApple OSS Distributions IOService::publishResource( property, kOSBooleanTrue );
125*42e22086SApple OSS Distributions } else {
126*42e22086SApple OSS Distributions IOService::getResourceService()->removeProperty( property );
127*42e22086SApple OSS Distributions }
128*42e22086SApple OSS Distributions }
129*42e22086SApple OSS Distributions
130*42e22086SApple OSS Distributions boolean_t
IOServiceWaitForMatchingResource(const char * property,uint64_t timeout)131*42e22086SApple OSS Distributions IOServiceWaitForMatchingResource( const char * property, uint64_t timeout )
132*42e22086SApple OSS Distributions {
133*42e22086SApple OSS Distributions OSDictionary * dict = NULL;
134*42e22086SApple OSS Distributions IOService * match = NULL;
135*42e22086SApple OSS Distributions boolean_t found = false;
136*42e22086SApple OSS Distributions
137*42e22086SApple OSS Distributions do {
138*42e22086SApple OSS Distributions dict = IOService::resourceMatching( property );
139*42e22086SApple OSS Distributions if (!dict) {
140*42e22086SApple OSS Distributions continue;
141*42e22086SApple OSS Distributions }
142*42e22086SApple OSS Distributions match = IOService::waitForMatchingService( dict, timeout );
143*42e22086SApple OSS Distributions if (match) {
144*42e22086SApple OSS Distributions found = true;
145*42e22086SApple OSS Distributions }
146*42e22086SApple OSS Distributions } while (false);
147*42e22086SApple OSS Distributions
148*42e22086SApple OSS Distributions if (dict) {
149*42e22086SApple OSS Distributions dict->release();
150*42e22086SApple OSS Distributions }
151*42e22086SApple OSS Distributions if (match) {
152*42e22086SApple OSS Distributions match->release();
153*42e22086SApple OSS Distributions }
154*42e22086SApple OSS Distributions
155*42e22086SApple OSS Distributions return found;
156*42e22086SApple OSS Distributions }
157*42e22086SApple OSS Distributions
158*42e22086SApple OSS Distributions boolean_t
IOCatalogueMatchingDriversPresent(const char * property)159*42e22086SApple OSS Distributions IOCatalogueMatchingDriversPresent( const char * property )
160*42e22086SApple OSS Distributions {
161*42e22086SApple OSS Distributions OSDictionary * dict = NULL;
162*42e22086SApple OSS Distributions OSOrderedSet * set = NULL;
163*42e22086SApple OSS Distributions SInt32 generationCount = 0;
164*42e22086SApple OSS Distributions boolean_t found = false;
165*42e22086SApple OSS Distributions
166*42e22086SApple OSS Distributions do {
167*42e22086SApple OSS Distributions dict = OSDictionary::withCapacity(1);
168*42e22086SApple OSS Distributions if (!dict) {
169*42e22086SApple OSS Distributions continue;
170*42e22086SApple OSS Distributions }
171*42e22086SApple OSS Distributions dict->setObject( property, kOSBooleanTrue );
172*42e22086SApple OSS Distributions set = gIOCatalogue->findDrivers( dict, &generationCount );
173*42e22086SApple OSS Distributions if (set && (set->getCount() > 0)) {
174*42e22086SApple OSS Distributions found = true;
175*42e22086SApple OSS Distributions }
176*42e22086SApple OSS Distributions } while (false);
177*42e22086SApple OSS Distributions
178*42e22086SApple OSS Distributions if (dict) {
179*42e22086SApple OSS Distributions dict->release();
180*42e22086SApple OSS Distributions }
181*42e22086SApple OSS Distributions if (set) {
182*42e22086SApple OSS Distributions set->release();
183*42e22086SApple OSS Distributions }
184*42e22086SApple OSS Distributions
185*42e22086SApple OSS Distributions return found;
186*42e22086SApple OSS Distributions }
187*42e22086SApple OSS Distributions
188*42e22086SApple OSS Distributions OSDictionary *
IOBSDNameMatching(const char * name)189*42e22086SApple OSS Distributions IOBSDNameMatching( const char * name )
190*42e22086SApple OSS Distributions {
191*42e22086SApple OSS Distributions OSDictionary * dict;
192*42e22086SApple OSS Distributions const OSSymbol * str = NULL;
193*42e22086SApple OSS Distributions
194*42e22086SApple OSS Distributions do {
195*42e22086SApple OSS Distributions dict = IOService::serviceMatching( gIOServiceKey );
196*42e22086SApple OSS Distributions if (!dict) {
197*42e22086SApple OSS Distributions continue;
198*42e22086SApple OSS Distributions }
199*42e22086SApple OSS Distributions str = OSSymbol::withCString( name );
200*42e22086SApple OSS Distributions if (!str) {
201*42e22086SApple OSS Distributions continue;
202*42e22086SApple OSS Distributions }
203*42e22086SApple OSS Distributions dict->setObject( kIOBSDNameKey, (OSObject *) str );
204*42e22086SApple OSS Distributions str->release();
205*42e22086SApple OSS Distributions
206*42e22086SApple OSS Distributions return dict;
207*42e22086SApple OSS Distributions } while (false);
208*42e22086SApple OSS Distributions
209*42e22086SApple OSS Distributions if (dict) {
210*42e22086SApple OSS Distributions dict->release();
211*42e22086SApple OSS Distributions }
212*42e22086SApple OSS Distributions if (str) {
213*42e22086SApple OSS Distributions str->release();
214*42e22086SApple OSS Distributions }
215*42e22086SApple OSS Distributions
216*42e22086SApple OSS Distributions return NULL;
217*42e22086SApple OSS Distributions }
218*42e22086SApple OSS Distributions
219*42e22086SApple OSS Distributions OSDictionary *
IOUUIDMatching(void)220*42e22086SApple OSS Distributions IOUUIDMatching( void )
221*42e22086SApple OSS Distributions {
222*42e22086SApple OSS Distributions return IOService::resourceMatching( "boot-uuid-media" );
223*42e22086SApple OSS Distributions }
224*42e22086SApple OSS Distributions
225*42e22086SApple OSS Distributions OSDictionary *
IONetworkNamePrefixMatching(const char * prefix)226*42e22086SApple OSS Distributions IONetworkNamePrefixMatching( const char * prefix )
227*42e22086SApple OSS Distributions {
228*42e22086SApple OSS Distributions OSDictionary * matching;
229*42e22086SApple OSS Distributions OSDictionary * propDict = NULL;
230*42e22086SApple OSS Distributions const OSSymbol * str = NULL;
231*42e22086SApple OSS Distributions char networkType[128];
232*42e22086SApple OSS Distributions
233*42e22086SApple OSS Distributions do {
234*42e22086SApple OSS Distributions matching = IOService::serviceMatching( "IONetworkInterface" );
235*42e22086SApple OSS Distributions if (matching == NULL) {
236*42e22086SApple OSS Distributions continue;
237*42e22086SApple OSS Distributions }
238*42e22086SApple OSS Distributions
239*42e22086SApple OSS Distributions propDict = OSDictionary::withCapacity(1);
240*42e22086SApple OSS Distributions if (propDict == NULL) {
241*42e22086SApple OSS Distributions continue;
242*42e22086SApple OSS Distributions }
243*42e22086SApple OSS Distributions
244*42e22086SApple OSS Distributions str = OSSymbol::withCString( prefix );
245*42e22086SApple OSS Distributions if (str == NULL) {
246*42e22086SApple OSS Distributions continue;
247*42e22086SApple OSS Distributions }
248*42e22086SApple OSS Distributions
249*42e22086SApple OSS Distributions propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str );
250*42e22086SApple OSS Distributions str->release();
251*42e22086SApple OSS Distributions str = NULL;
252*42e22086SApple OSS Distributions
253*42e22086SApple OSS Distributions // see if we're contrained to netroot off of specific network type
254*42e22086SApple OSS Distributions if (PE_parse_boot_argn( "network-type", networkType, 128 )) {
255*42e22086SApple OSS Distributions str = OSSymbol::withCString( networkType );
256*42e22086SApple OSS Distributions if (str) {
257*42e22086SApple OSS Distributions propDict->setObject( "IONetworkRootType", str);
258*42e22086SApple OSS Distributions str->release();
259*42e22086SApple OSS Distributions str = NULL;
260*42e22086SApple OSS Distributions }
261*42e22086SApple OSS Distributions }
262*42e22086SApple OSS Distributions
263*42e22086SApple OSS Distributions if (matching->setObject( gIOPropertyMatchKey,
264*42e22086SApple OSS Distributions (OSObject *) propDict ) != true) {
265*42e22086SApple OSS Distributions continue;
266*42e22086SApple OSS Distributions }
267*42e22086SApple OSS Distributions
268*42e22086SApple OSS Distributions propDict->release();
269*42e22086SApple OSS Distributions propDict = NULL;
270*42e22086SApple OSS Distributions
271*42e22086SApple OSS Distributions return matching;
272*42e22086SApple OSS Distributions } while (false);
273*42e22086SApple OSS Distributions
274*42e22086SApple OSS Distributions if (matching) {
275*42e22086SApple OSS Distributions matching->release();
276*42e22086SApple OSS Distributions }
277*42e22086SApple OSS Distributions if (propDict) {
278*42e22086SApple OSS Distributions propDict->release();
279*42e22086SApple OSS Distributions }
280*42e22086SApple OSS Distributions if (str) {
281*42e22086SApple OSS Distributions str->release();
282*42e22086SApple OSS Distributions }
283*42e22086SApple OSS Distributions
284*42e22086SApple OSS Distributions return NULL;
285*42e22086SApple OSS Distributions }
286*42e22086SApple OSS Distributions
287*42e22086SApple OSS Distributions static bool
IORegisterNetworkInterface(IOService * netif)288*42e22086SApple OSS Distributions IORegisterNetworkInterface( IOService * netif )
289*42e22086SApple OSS Distributions {
290*42e22086SApple OSS Distributions // A network interface is typically named and registered
291*42e22086SApple OSS Distributions // with BSD after receiving a request from a user space
292*42e22086SApple OSS Distributions // "namer". However, for cases when the system needs to
293*42e22086SApple OSS Distributions // root from the network, this registration task must be
294*42e22086SApple OSS Distributions // done inside the kernel and completed before the root
295*42e22086SApple OSS Distributions // device is handed to BSD.
296*42e22086SApple OSS Distributions
297*42e22086SApple OSS Distributions IOService * stack;
298*42e22086SApple OSS Distributions OSNumber * zero = NULL;
299*42e22086SApple OSS Distributions OSString * path = NULL;
300*42e22086SApple OSS Distributions OSDictionary * dict = NULL;
301*42e22086SApple OSS Distributions OSDataAllocation<char> pathBuf;
302*42e22086SApple OSS Distributions int len;
303*42e22086SApple OSS Distributions enum { kMaxPathLen = 512 };
304*42e22086SApple OSS Distributions
305*42e22086SApple OSS Distributions do {
306*42e22086SApple OSS Distributions stack = IOService::waitForService(
307*42e22086SApple OSS Distributions IOService::serviceMatching("IONetworkStack"));
308*42e22086SApple OSS Distributions if (stack == NULL) {
309*42e22086SApple OSS Distributions break;
310*42e22086SApple OSS Distributions }
311*42e22086SApple OSS Distributions
312*42e22086SApple OSS Distributions dict = OSDictionary::withCapacity(3);
313*42e22086SApple OSS Distributions if (dict == NULL) {
314*42e22086SApple OSS Distributions break;
315*42e22086SApple OSS Distributions }
316*42e22086SApple OSS Distributions
317*42e22086SApple OSS Distributions zero = OSNumber::withNumber((UInt64) 0, 32);
318*42e22086SApple OSS Distributions if (zero == NULL) {
319*42e22086SApple OSS Distributions break;
320*42e22086SApple OSS Distributions }
321*42e22086SApple OSS Distributions
322*42e22086SApple OSS Distributions pathBuf = OSDataAllocation<char>( kMaxPathLen, OSAllocateMemory );
323*42e22086SApple OSS Distributions if (!pathBuf) {
324*42e22086SApple OSS Distributions break;
325*42e22086SApple OSS Distributions }
326*42e22086SApple OSS Distributions
327*42e22086SApple OSS Distributions len = kMaxPathLen;
328*42e22086SApple OSS Distributions if (netif->getPath( pathBuf.data(), &len, gIOServicePlane )
329*42e22086SApple OSS Distributions == false) {
330*42e22086SApple OSS Distributions break;
331*42e22086SApple OSS Distributions }
332*42e22086SApple OSS Distributions
333*42e22086SApple OSS Distributions path = OSString::withCStringNoCopy(pathBuf.data());
334*42e22086SApple OSS Distributions if (path == NULL) {
335*42e22086SApple OSS Distributions break;
336*42e22086SApple OSS Distributions }
337*42e22086SApple OSS Distributions
338*42e22086SApple OSS Distributions dict->setObject( "IOInterfaceUnit", zero );
339*42e22086SApple OSS Distributions dict->setObject( kIOPathMatchKey, path );
340*42e22086SApple OSS Distributions
341*42e22086SApple OSS Distributions stack->setProperties( dict );
342*42e22086SApple OSS Distributions }while (false);
343*42e22086SApple OSS Distributions
344*42e22086SApple OSS Distributions if (zero) {
345*42e22086SApple OSS Distributions zero->release();
346*42e22086SApple OSS Distributions }
347*42e22086SApple OSS Distributions if (path) {
348*42e22086SApple OSS Distributions path->release();
349*42e22086SApple OSS Distributions }
350*42e22086SApple OSS Distributions if (dict) {
351*42e22086SApple OSS Distributions dict->release();
352*42e22086SApple OSS Distributions }
353*42e22086SApple OSS Distributions
354*42e22086SApple OSS Distributions return netif->getProperty( kIOBSDNameKey ) != NULL;
355*42e22086SApple OSS Distributions }
356*42e22086SApple OSS Distributions
357*42e22086SApple OSS Distributions OSDictionary *
IOOFPathMatching(const char * path,char * buf,int maxLen)358*42e22086SApple OSS Distributions IOOFPathMatching( const char * path, char * buf, int maxLen )
359*42e22086SApple OSS Distributions {
360*42e22086SApple OSS Distributions OSDictionary * matching = NULL;
361*42e22086SApple OSS Distributions OSString * str;
362*42e22086SApple OSS Distributions char * comp;
363*42e22086SApple OSS Distributions int len;
364*42e22086SApple OSS Distributions
365*42e22086SApple OSS Distributions do {
366*42e22086SApple OSS Distributions len = ((int) strlen( kIODeviceTreePlane ":" ));
367*42e22086SApple OSS Distributions maxLen -= len;
368*42e22086SApple OSS Distributions if (maxLen <= 0) {
369*42e22086SApple OSS Distributions continue;
370*42e22086SApple OSS Distributions }
371*42e22086SApple OSS Distributions
372*42e22086SApple OSS Distributions strlcpy( buf, kIODeviceTreePlane ":", len + 1 );
373*42e22086SApple OSS Distributions comp = buf + len;
374*42e22086SApple OSS Distributions
375*42e22086SApple OSS Distributions len = ((int) strnlen( path, INT_MAX ));
376*42e22086SApple OSS Distributions maxLen -= len;
377*42e22086SApple OSS Distributions if (maxLen <= 0) {
378*42e22086SApple OSS Distributions continue;
379*42e22086SApple OSS Distributions }
380*42e22086SApple OSS Distributions strlcpy( comp, path, len + 1 );
381*42e22086SApple OSS Distributions
382*42e22086SApple OSS Distributions matching = OSDictionary::withCapacity( 1 );
383*42e22086SApple OSS Distributions if (!matching) {
384*42e22086SApple OSS Distributions continue;
385*42e22086SApple OSS Distributions }
386*42e22086SApple OSS Distributions
387*42e22086SApple OSS Distributions str = OSString::withCString( buf );
388*42e22086SApple OSS Distributions if (!str) {
389*42e22086SApple OSS Distributions continue;
390*42e22086SApple OSS Distributions }
391*42e22086SApple OSS Distributions matching->setObject( kIOPathMatchKey, str );
392*42e22086SApple OSS Distributions str->release();
393*42e22086SApple OSS Distributions
394*42e22086SApple OSS Distributions return matching;
395*42e22086SApple OSS Distributions } while (false);
396*42e22086SApple OSS Distributions
397*42e22086SApple OSS Distributions if (matching) {
398*42e22086SApple OSS Distributions matching->release();
399*42e22086SApple OSS Distributions }
400*42e22086SApple OSS Distributions
401*42e22086SApple OSS Distributions return NULL;
402*42e22086SApple OSS Distributions }
403*42e22086SApple OSS Distributions
404*42e22086SApple OSS Distributions static int didRam = 0;
405*42e22086SApple OSS Distributions enum { kMaxPathBuf = 512, kMaxBootVar = 128 };
406*42e22086SApple OSS Distributions
407*42e22086SApple OSS Distributions bool
IOGetBootUUID(char * uuid)408*42e22086SApple OSS Distributions IOGetBootUUID(char *uuid)
409*42e22086SApple OSS Distributions {
410*42e22086SApple OSS Distributions IORegistryEntry *entry;
411*42e22086SApple OSS Distributions OSData *uuid_data = NULL;
412*42e22086SApple OSS Distributions bool result = false;
413*42e22086SApple OSS Distributions
414*42e22086SApple OSS Distributions if ((entry = IORegistryEntry::fromPath("/chosen", gIODTPlane))) {
415*42e22086SApple OSS Distributions uuid_data = (OSData *)entry->getProperty("boot-uuid");
416*42e22086SApple OSS Distributions if (uuid_data) {
417*42e22086SApple OSS Distributions unsigned int length = uuid_data->getLength();
418*42e22086SApple OSS Distributions if (length <= sizeof(uuid_string_t)) {
419*42e22086SApple OSS Distributions /* ensure caller's buffer is fully initialized: */
420*42e22086SApple OSS Distributions bzero(uuid, sizeof(uuid_string_t));
421*42e22086SApple OSS Distributions /* copy the content of uuid_data->getBytesNoCopy() into uuid */
422*42e22086SApple OSS Distributions memcpy(uuid, uuid_data->getBytesNoCopy(), length);
423*42e22086SApple OSS Distributions /* guarantee nul-termination: */
424*42e22086SApple OSS Distributions uuid[sizeof(uuid_string_t) - 1] = '\0';
425*42e22086SApple OSS Distributions result = true;
426*42e22086SApple OSS Distributions } else {
427*42e22086SApple OSS Distributions uuid = NULL;
428*42e22086SApple OSS Distributions }
429*42e22086SApple OSS Distributions }
430*42e22086SApple OSS Distributions OSSafeReleaseNULL(entry);
431*42e22086SApple OSS Distributions }
432*42e22086SApple OSS Distributions return result;
433*42e22086SApple OSS Distributions }
434*42e22086SApple OSS Distributions
435*42e22086SApple OSS Distributions bool
IOGetApfsPrebootUUID(char * uuid)436*42e22086SApple OSS Distributions IOGetApfsPrebootUUID(char *uuid)
437*42e22086SApple OSS Distributions {
438*42e22086SApple OSS Distributions IORegistryEntry *entry;
439*42e22086SApple OSS Distributions OSData *uuid_data = NULL;
440*42e22086SApple OSS Distributions bool result = false;
441*42e22086SApple OSS Distributions
442*42e22086SApple OSS Distributions if ((entry = IORegistryEntry::fromPath("/chosen", gIODTPlane))) {
443*42e22086SApple OSS Distributions uuid_data = (OSData *)entry->getProperty("apfs-preboot-uuid");
444*42e22086SApple OSS Distributions
445*42e22086SApple OSS Distributions if (uuid_data) {
446*42e22086SApple OSS Distributions unsigned int length = uuid_data->getLength();
447*42e22086SApple OSS Distributions if (length <= sizeof(uuid_string_t)) {
448*42e22086SApple OSS Distributions /* ensure caller's buffer is fully initialized: */
449*42e22086SApple OSS Distributions bzero(uuid, sizeof(uuid_string_t));
450*42e22086SApple OSS Distributions /* copy the content of uuid_data->getBytesNoCopy() into uuid */
451*42e22086SApple OSS Distributions memcpy(uuid, uuid_data->getBytesNoCopy(), length);
452*42e22086SApple OSS Distributions /* guarantee nul-termination: */
453*42e22086SApple OSS Distributions uuid[sizeof(uuid_string_t) - 1] = '\0';
454*42e22086SApple OSS Distributions result = true;
455*42e22086SApple OSS Distributions } else {
456*42e22086SApple OSS Distributions uuid = NULL;
457*42e22086SApple OSS Distributions }
458*42e22086SApple OSS Distributions }
459*42e22086SApple OSS Distributions OSSafeReleaseNULL(entry);
460*42e22086SApple OSS Distributions }
461*42e22086SApple OSS Distributions return result;
462*42e22086SApple OSS Distributions }
463*42e22086SApple OSS Distributions
464*42e22086SApple OSS Distributions bool
IOGetAssociatedApfsVolgroupUUID(char * uuid)465*42e22086SApple OSS Distributions IOGetAssociatedApfsVolgroupUUID(char *uuid)
466*42e22086SApple OSS Distributions {
467*42e22086SApple OSS Distributions IORegistryEntry *entry;
468*42e22086SApple OSS Distributions OSData *uuid_data = NULL;
469*42e22086SApple OSS Distributions bool result = false;
470*42e22086SApple OSS Distributions
471*42e22086SApple OSS Distributions if ((entry = IORegistryEntry::fromPath("/chosen", gIODTPlane))) {
472*42e22086SApple OSS Distributions uuid_data = (OSData *)entry->getProperty("associated-volume-group");
473*42e22086SApple OSS Distributions
474*42e22086SApple OSS Distributions if (uuid_data) {
475*42e22086SApple OSS Distributions unsigned int length = uuid_data->getLength();
476*42e22086SApple OSS Distributions
477*42e22086SApple OSS Distributions if (length <= sizeof(uuid_string_t)) {
478*42e22086SApple OSS Distributions /* ensure caller's buffer is fully initialized: */
479*42e22086SApple OSS Distributions bzero(uuid, sizeof(uuid_string_t));
480*42e22086SApple OSS Distributions /* copy the content of uuid_data->getBytesNoCopy() into uuid */
481*42e22086SApple OSS Distributions memcpy(uuid, uuid_data->getBytesNoCopy(), length);
482*42e22086SApple OSS Distributions /* guarantee nul-termination: */
483*42e22086SApple OSS Distributions uuid[sizeof(uuid_string_t) - 1] = '\0';
484*42e22086SApple OSS Distributions result = true;
485*42e22086SApple OSS Distributions } else {
486*42e22086SApple OSS Distributions uuid = NULL;
487*42e22086SApple OSS Distributions }
488*42e22086SApple OSS Distributions }
489*42e22086SApple OSS Distributions OSSafeReleaseNULL(entry);
490*42e22086SApple OSS Distributions }
491*42e22086SApple OSS Distributions return result;
492*42e22086SApple OSS Distributions }
493*42e22086SApple OSS Distributions
494*42e22086SApple OSS Distributions bool
IOGetBootObjectsPath(char * path_prefix)495*42e22086SApple OSS Distributions IOGetBootObjectsPath(char *path_prefix)
496*42e22086SApple OSS Distributions {
497*42e22086SApple OSS Distributions IORegistryEntry *entry;
498*42e22086SApple OSS Distributions OSData *path_prefix_data = NULL;
499*42e22086SApple OSS Distributions bool result = false;
500*42e22086SApple OSS Distributions
501*42e22086SApple OSS Distributions if ((entry = IORegistryEntry::fromPath("/chosen", gIODTPlane))) {
502*42e22086SApple OSS Distributions path_prefix_data = (OSData *)entry->getProperty("boot-objects-path");
503*42e22086SApple OSS Distributions
504*42e22086SApple OSS Distributions if (path_prefix_data) {
505*42e22086SApple OSS Distributions unsigned int length = path_prefix_data->getLength();
506*42e22086SApple OSS Distributions
507*42e22086SApple OSS Distributions if (length <= MAXPATHLEN) {
508*42e22086SApple OSS Distributions /* ensure caller's buffer is fully initialized: */
509*42e22086SApple OSS Distributions bzero(path_prefix, MAXPATHLEN);
510*42e22086SApple OSS Distributions /* copy the content of path_prefix_data->getBytesNoCopy() into path_prefix */
511*42e22086SApple OSS Distributions memcpy(path_prefix, path_prefix_data->getBytesNoCopy(), length);
512*42e22086SApple OSS Distributions /* guarantee nul-termination: */
513*42e22086SApple OSS Distributions path_prefix[MAXPATHLEN - 1] = '\0';
514*42e22086SApple OSS Distributions result = true;
515*42e22086SApple OSS Distributions } else {
516*42e22086SApple OSS Distributions path_prefix = NULL;
517*42e22086SApple OSS Distributions }
518*42e22086SApple OSS Distributions }
519*42e22086SApple OSS Distributions OSSafeReleaseNULL(entry);
520*42e22086SApple OSS Distributions }
521*42e22086SApple OSS Distributions return result;
522*42e22086SApple OSS Distributions }
523*42e22086SApple OSS Distributions
524*42e22086SApple OSS Distributions
525*42e22086SApple OSS Distributions bool
IOGetBootManifestHash(char * hash_data,size_t * hash_data_size)526*42e22086SApple OSS Distributions IOGetBootManifestHash(char *hash_data, size_t *hash_data_size)
527*42e22086SApple OSS Distributions {
528*42e22086SApple OSS Distributions IORegistryEntry *entry = NULL;
529*42e22086SApple OSS Distributions OSData *manifest_hash_data = NULL;
530*42e22086SApple OSS Distributions bool result = false;
531*42e22086SApple OSS Distributions
532*42e22086SApple OSS Distributions if ((entry = IORegistryEntry::fromPath("/chosen", gIODTPlane))) {
533*42e22086SApple OSS Distributions manifest_hash_data = (OSData *)entry->getProperty("boot-manifest-hash");
534*42e22086SApple OSS Distributions if (manifest_hash_data) {
535*42e22086SApple OSS Distributions unsigned int length = manifest_hash_data->getLength();
536*42e22086SApple OSS Distributions /* hashed with SHA2-384 or SHA1, the boot manifest hash should be 48 Bytes or less */
537*42e22086SApple OSS Distributions if ((length <= CCSHA384_OUTPUT_SIZE) && (*hash_data_size >= CCSHA384_OUTPUT_SIZE)) {
538*42e22086SApple OSS Distributions /* ensure caller's buffer is fully initialized: */
539*42e22086SApple OSS Distributions bzero(hash_data, CCSHA384_OUTPUT_SIZE);
540*42e22086SApple OSS Distributions /* copy the content of manifest_hash_data->getBytesNoCopy() into hash_data */
541*42e22086SApple OSS Distributions memcpy(hash_data, manifest_hash_data->getBytesNoCopy(), length);
542*42e22086SApple OSS Distributions *hash_data_size = length;
543*42e22086SApple OSS Distributions result = true;
544*42e22086SApple OSS Distributions } else {
545*42e22086SApple OSS Distributions hash_data = NULL;
546*42e22086SApple OSS Distributions *hash_data_size = 0;
547*42e22086SApple OSS Distributions }
548*42e22086SApple OSS Distributions }
549*42e22086SApple OSS Distributions OSSafeReleaseNULL(entry);
550*42e22086SApple OSS Distributions }
551*42e22086SApple OSS Distributions
552*42e22086SApple OSS Distributions return result;
553*42e22086SApple OSS Distributions }
554*42e22086SApple OSS Distributions
555*42e22086SApple OSS Distributions /*
556*42e22086SApple OSS Distributions * Set NVRAM to boot into the right flavor of Recovery,
557*42e22086SApple OSS Distributions * optionally passing a UUID of a volume that failed to boot.
558*42e22086SApple OSS Distributions * If `reboot` is true, reboot immediately.
559*42e22086SApple OSS Distributions *
560*42e22086SApple OSS Distributions * Returns true if `mode` was understood, false otherwise.
561*42e22086SApple OSS Distributions * (Does not return if `reboot` is true.)
562*42e22086SApple OSS Distributions */
563*42e22086SApple OSS Distributions boolean_t
IOSetRecoveryBoot(bsd_bootfail_mode_t mode,uuid_t volume_uuid,boolean_t reboot)564*42e22086SApple OSS Distributions IOSetRecoveryBoot(bsd_bootfail_mode_t mode, uuid_t volume_uuid, boolean_t reboot)
565*42e22086SApple OSS Distributions {
566*42e22086SApple OSS Distributions IODTNVRAM *nvram = NULL;
567*42e22086SApple OSS Distributions const OSSymbol *boot_command_sym = NULL;
568*42e22086SApple OSS Distributions OSString *boot_command_recover = NULL;
569*42e22086SApple OSS Distributions
570*42e22086SApple OSS Distributions if (mode == BSD_BOOTFAIL_SEAL_BROKEN) {
571*42e22086SApple OSS Distributions const char *boot_mode = "ssv-seal-broken";
572*42e22086SApple OSS Distributions uuid_string_t volume_uuid_str;
573*42e22086SApple OSS Distributions
574*42e22086SApple OSS Distributions // Set `recovery-broken-seal-uuid = <volume_uuid>`.
575*42e22086SApple OSS Distributions if (volume_uuid) {
576*42e22086SApple OSS Distributions uuid_unparse_upper(volume_uuid, volume_uuid_str);
577*42e22086SApple OSS Distributions
578*42e22086SApple OSS Distributions if (!PEWriteNVRAMProperty(SYSTEM_NVRAM_PREFIX "recovery-broken-seal-uuid",
579*42e22086SApple OSS Distributions volume_uuid_str, sizeof(uuid_string_t))) {
580*42e22086SApple OSS Distributions IOLog("Failed to write recovery-broken-seal-uuid to NVRAM.\n");
581*42e22086SApple OSS Distributions }
582*42e22086SApple OSS Distributions }
583*42e22086SApple OSS Distributions
584*42e22086SApple OSS Distributions // Set `recovery-boot-mode = ssv-seal-broken`.
585*42e22086SApple OSS Distributions if (!PEWriteNVRAMProperty(SYSTEM_NVRAM_PREFIX "recovery-boot-mode", boot_mode,
586*42e22086SApple OSS Distributions (const unsigned int) strlen(boot_mode))) {
587*42e22086SApple OSS Distributions IOLog("Failed to write recovery-boot-mode to NVRAM.\n");
588*42e22086SApple OSS Distributions }
589*42e22086SApple OSS Distributions } else if (mode == BSD_BOOTFAIL_MEDIA_MISSING) {
590*42e22086SApple OSS Distributions const char *boot_picker_reason = "missing-boot-media";
591*42e22086SApple OSS Distributions
592*42e22086SApple OSS Distributions // Set `boot-picker-bringup-reason = missing-boot-media`.
593*42e22086SApple OSS Distributions if (!PEWriteNVRAMProperty(SYSTEM_NVRAM_PREFIX "boot-picker-bringup-reason",
594*42e22086SApple OSS Distributions boot_picker_reason, (const unsigned int) strlen(boot_picker_reason))) {
595*42e22086SApple OSS Distributions IOLog("Failed to write boot-picker-bringup-reason to NVRAM.\n");
596*42e22086SApple OSS Distributions }
597*42e22086SApple OSS Distributions
598*42e22086SApple OSS Distributions // Set `boot-command = recover-system`.
599*42e22086SApple OSS Distributions
600*42e22086SApple OSS Distributions // Construct an OSSymbol and an OSString to be the (key, value) pair
601*42e22086SApple OSS Distributions // we write to NVRAM. Unfortunately, since our value must be an OSString
602*42e22086SApple OSS Distributions // instead of an OSData, we cannot use PEWriteNVRAMProperty() here.
603*42e22086SApple OSS Distributions boot_command_sym = OSSymbol::withCStringNoCopy(SYSTEM_NVRAM_PREFIX "boot-command");
604*42e22086SApple OSS Distributions boot_command_recover = OSString::withCStringNoCopy("recover-system");
605*42e22086SApple OSS Distributions if (boot_command_sym == NULL || boot_command_recover == NULL) {
606*42e22086SApple OSS Distributions IOLog("Failed to create boot-command strings.\n");
607*42e22086SApple OSS Distributions goto do_reboot;
608*42e22086SApple OSS Distributions }
609*42e22086SApple OSS Distributions
610*42e22086SApple OSS Distributions // Wait for NVRAM to be readable...
611*42e22086SApple OSS Distributions nvram = OSDynamicCast(IODTNVRAM, IOService::waitForService(
612*42e22086SApple OSS Distributions IOService::serviceMatching("IODTNVRAM")));
613*42e22086SApple OSS Distributions if (nvram == NULL) {
614*42e22086SApple OSS Distributions IOLog("Failed to acquire IODTNVRAM object.\n");
615*42e22086SApple OSS Distributions goto do_reboot;
616*42e22086SApple OSS Distributions }
617*42e22086SApple OSS Distributions
618*42e22086SApple OSS Distributions // Wait for NVRAM to be writable...
619*42e22086SApple OSS Distributions if (!IOServiceWaitForMatchingResource("IONVRAM", UINT64_MAX)) {
620*42e22086SApple OSS Distributions IOLog("Failed to wait for IONVRAM service.\n");
621*42e22086SApple OSS Distributions // attempt the work anyway...
622*42e22086SApple OSS Distributions }
623*42e22086SApple OSS Distributions
624*42e22086SApple OSS Distributions // Write the new boot-command to NVRAM, and sync if successful.
625*42e22086SApple OSS Distributions if (!nvram->setProperty(boot_command_sym, boot_command_recover)) {
626*42e22086SApple OSS Distributions IOLog("Failed to save new boot-command to NVRAM.\n");
627*42e22086SApple OSS Distributions } else {
628*42e22086SApple OSS Distributions nvram->sync();
629*42e22086SApple OSS Distributions }
630*42e22086SApple OSS Distributions } else {
631*42e22086SApple OSS Distributions IOLog("Unknown mode: %d\n", mode);
632*42e22086SApple OSS Distributions return false;
633*42e22086SApple OSS Distributions }
634*42e22086SApple OSS Distributions
635*42e22086SApple OSS Distributions // Clean up and reboot!
636*42e22086SApple OSS Distributions do_reboot:
637*42e22086SApple OSS Distributions if (boot_command_recover != NULL) {
638*42e22086SApple OSS Distributions boot_command_recover->release();
639*42e22086SApple OSS Distributions }
640*42e22086SApple OSS Distributions
641*42e22086SApple OSS Distributions if (boot_command_sym != NULL) {
642*42e22086SApple OSS Distributions boot_command_sym->release();
643*42e22086SApple OSS Distributions }
644*42e22086SApple OSS Distributions
645*42e22086SApple OSS Distributions if (reboot) {
646*42e22086SApple OSS Distributions IOLog("\nAbout to reboot into Recovery!\n");
647*42e22086SApple OSS Distributions (void)PEHaltRestart(kPERestartCPU);
648*42e22086SApple OSS Distributions }
649*42e22086SApple OSS Distributions
650*42e22086SApple OSS Distributions return true;
651*42e22086SApple OSS Distributions }
652*42e22086SApple OSS Distributions
653*42e22086SApple OSS Distributions kern_return_t
IOFindBSDRoot(char * rootName,unsigned int rootNameSize,dev_t * root,u_int32_t * oflags)654*42e22086SApple OSS Distributions IOFindBSDRoot( char * rootName, unsigned int rootNameSize,
655*42e22086SApple OSS Distributions dev_t * root, u_int32_t * oflags )
656*42e22086SApple OSS Distributions {
657*42e22086SApple OSS Distributions mach_timespec_t t;
658*42e22086SApple OSS Distributions IOService * service;
659*42e22086SApple OSS Distributions IORegistryEntry * regEntry;
660*42e22086SApple OSS Distributions OSDictionary * matching = NULL;
661*42e22086SApple OSS Distributions OSString * iostr;
662*42e22086SApple OSS Distributions OSNumber * off;
663*42e22086SApple OSS Distributions OSData * data = NULL;
664*42e22086SApple OSS Distributions
665*42e22086SApple OSS Distributions UInt32 flags = 0;
666*42e22086SApple OSS Distributions int mnr, mjr;
667*42e22086SApple OSS Distributions const char * mediaProperty = NULL;
668*42e22086SApple OSS Distributions char * rdBootVar;
669*42e22086SApple OSS Distributions OSDataAllocation<char> str;
670*42e22086SApple OSS Distributions const char * look = NULL;
671*42e22086SApple OSS Distributions int len;
672*42e22086SApple OSS Distributions bool debugInfoPrintedOnce = false;
673*42e22086SApple OSS Distributions bool needNetworkKexts = false;
674*42e22086SApple OSS Distributions const char * uuidStr = NULL;
675*42e22086SApple OSS Distributions
676*42e22086SApple OSS Distributions static int mountAttempts = 0;
677*42e22086SApple OSS Distributions
678*42e22086SApple OSS Distributions int xchar, dchar;
679*42e22086SApple OSS Distributions
680*42e22086SApple OSS Distributions // stall here for anyone matching on the IOBSD resource to finish (filesystems)
681*42e22086SApple OSS Distributions matching = IOService::serviceMatching(gIOResourcesKey);
682*42e22086SApple OSS Distributions assert(matching);
683*42e22086SApple OSS Distributions matching->setObject(gIOResourceMatchedKey, gIOBSDKey);
684*42e22086SApple OSS Distributions
685*42e22086SApple OSS Distributions if ((service = IOService::waitForMatchingService(matching, 30ULL * kSecondScale))) {
686*42e22086SApple OSS Distributions OSSafeReleaseNULL(service);
687*42e22086SApple OSS Distributions } else {
688*42e22086SApple OSS Distributions IOLog("!BSD\n");
689*42e22086SApple OSS Distributions }
690*42e22086SApple OSS Distributions matching->release();
691*42e22086SApple OSS Distributions matching = NULL;
692*42e22086SApple OSS Distributions
693*42e22086SApple OSS Distributions if (mountAttempts++) {
694*42e22086SApple OSS Distributions IOLog("mount(%d) failed\n", mountAttempts);
695*42e22086SApple OSS Distributions IOSleep( 5 * 1000 );
696*42e22086SApple OSS Distributions }
697*42e22086SApple OSS Distributions
698*42e22086SApple OSS Distributions str = OSDataAllocation<char>( kMaxPathBuf + kMaxBootVar, OSAllocateMemory );
699*42e22086SApple OSS Distributions if (!str) {
700*42e22086SApple OSS Distributions return kIOReturnNoMemory;
701*42e22086SApple OSS Distributions }
702*42e22086SApple OSS Distributions rdBootVar = str.data() + kMaxPathBuf;
703*42e22086SApple OSS Distributions
704*42e22086SApple OSS Distributions if (!PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar )
705*42e22086SApple OSS Distributions && !PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar )) {
706*42e22086SApple OSS Distributions rdBootVar[0] = 0;
707*42e22086SApple OSS Distributions }
708*42e22086SApple OSS Distributions
709*42e22086SApple OSS Distributions if ((regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) {
710*42e22086SApple OSS Distributions do {
711*42e22086SApple OSS Distributions di_root_ramfile(regEntry);
712*42e22086SApple OSS Distributions OSObject* unserializedContainer = NULL;
713*42e22086SApple OSS Distributions data = OSDynamicCast(OSData, regEntry->getProperty( "root-matching" ));
714*42e22086SApple OSS Distributions if (data) {
715*42e22086SApple OSS Distributions unserializedContainer = OSUnserializeXML((char *)data->getBytesNoCopy());
716*42e22086SApple OSS Distributions matching = OSDynamicCast(OSDictionary, unserializedContainer);
717*42e22086SApple OSS Distributions if (matching) {
718*42e22086SApple OSS Distributions continue;
719*42e22086SApple OSS Distributions }
720*42e22086SApple OSS Distributions }
721*42e22086SApple OSS Distributions OSSafeReleaseNULL(unserializedContainer);
722*42e22086SApple OSS Distributions
723*42e22086SApple OSS Distributions data = (OSData *) regEntry->getProperty( "boot-uuid" );
724*42e22086SApple OSS Distributions if (data) {
725*42e22086SApple OSS Distributions uuidStr = (const char*)data->getBytesNoCopy();
726*42e22086SApple OSS Distributions OSString *uuidString = OSString::withCString( uuidStr );
727*42e22086SApple OSS Distributions
728*42e22086SApple OSS Distributions // match the boot-args boot-uuid processing below
729*42e22086SApple OSS Distributions if (uuidString) {
730*42e22086SApple OSS Distributions IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr);
731*42e22086SApple OSS Distributions IOService::publishResource( "boot-uuid", uuidString );
732*42e22086SApple OSS Distributions uuidString->release();
733*42e22086SApple OSS Distributions matching = IOUUIDMatching();
734*42e22086SApple OSS Distributions mediaProperty = "boot-uuid-media";
735*42e22086SApple OSS Distributions continue;
736*42e22086SApple OSS Distributions } else {
737*42e22086SApple OSS Distributions uuidStr = NULL;
738*42e22086SApple OSS Distributions }
739*42e22086SApple OSS Distributions }
740*42e22086SApple OSS Distributions } while (false);
741*42e22086SApple OSS Distributions OSSafeReleaseNULL(regEntry);
742*42e22086SApple OSS Distributions }
743*42e22086SApple OSS Distributions
744*42e22086SApple OSS Distributions //
745*42e22086SApple OSS Distributions // See if we have a RAMDisk property in /chosen/memory-map. If so, make it into a device.
746*42e22086SApple OSS Distributions // It will become /dev/mdx, where x is 0-f.
747*42e22086SApple OSS Distributions //
748*42e22086SApple OSS Distributions
749*42e22086SApple OSS Distributions if (!didRam) { /* Have we already build this ram disk? */
750*42e22086SApple OSS Distributions didRam = 1; /* Remember we did this */
751*42e22086SApple OSS Distributions if ((regEntry = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ))) { /* Find the map node */
752*42e22086SApple OSS Distributions data = (OSData *)regEntry->getProperty("RAMDisk"); /* Find the ram disk, if there */
753*42e22086SApple OSS Distributions if (data) { /* We found one */
754*42e22086SApple OSS Distributions uintptr_t *ramdParms;
755*42e22086SApple OSS Distributions ramdParms = (uintptr_t *)data->getBytesNoCopy(); /* Point to the ram disk base and size */
756*42e22086SApple OSS Distributions #if __LP64__
757*42e22086SApple OSS Distributions #define MAX_PHYS_RAM (((uint64_t)UINT_MAX) << 12)
758*42e22086SApple OSS Distributions if (ramdParms[1] > MAX_PHYS_RAM) {
759*42e22086SApple OSS Distributions panic("ramdisk params");
760*42e22086SApple OSS Distributions }
761*42e22086SApple OSS Distributions #endif /* __LP64__ */
762*42e22086SApple OSS Distributions (void)mdevadd(-1, ml_static_ptovirt(ramdParms[0]) >> 12, (unsigned int) (ramdParms[1] >> 12), 0); /* Initialize it and pass back the device number */
763*42e22086SApple OSS Distributions }
764*42e22086SApple OSS Distributions regEntry->release(); /* Toss the entry */
765*42e22086SApple OSS Distributions }
766*42e22086SApple OSS Distributions }
767*42e22086SApple OSS Distributions
768*42e22086SApple OSS Distributions //
769*42e22086SApple OSS Distributions // Now check if we are trying to root on a memory device
770*42e22086SApple OSS Distributions //
771*42e22086SApple OSS Distributions
772*42e22086SApple OSS Distributions if ((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) {
773*42e22086SApple OSS Distributions dchar = xchar = rdBootVar[2]; /* Get the actual device */
774*42e22086SApple OSS Distributions if ((xchar >= '0') && (xchar <= '9')) {
775*42e22086SApple OSS Distributions xchar = xchar - '0'; /* If digit, convert */
776*42e22086SApple OSS Distributions } else {
777*42e22086SApple OSS Distributions xchar = xchar & ~' '; /* Fold to upper case */
778*42e22086SApple OSS Distributions if ((xchar >= 'A') && (xchar <= 'F')) { /* Is this a valid digit? */
779*42e22086SApple OSS Distributions xchar = (xchar & 0xF) + 9; /* Convert the hex digit */
780*42e22086SApple OSS Distributions dchar = dchar | ' '; /* Fold to lower case */
781*42e22086SApple OSS Distributions } else {
782*42e22086SApple OSS Distributions xchar = -1; /* Show bogus */
783*42e22086SApple OSS Distributions }
784*42e22086SApple OSS Distributions }
785*42e22086SApple OSS Distributions if (xchar >= 0) { /* Do we have a valid memory device name? */
786*42e22086SApple OSS Distributions OSSafeReleaseNULL(matching);
787*42e22086SApple OSS Distributions *root = mdevlookup(xchar); /* Find the device number */
788*42e22086SApple OSS Distributions if (*root >= 0) { /* Did we find one? */
789*42e22086SApple OSS Distributions rootName[0] = 'm'; /* Build root name */
790*42e22086SApple OSS Distributions rootName[1] = 'd'; /* Build root name */
791*42e22086SApple OSS Distributions rootName[2] = (char) dchar; /* Build root name */
792*42e22086SApple OSS Distributions rootName[3] = 0; /* Build root name */
793*42e22086SApple OSS Distributions IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root));
794*42e22086SApple OSS Distributions *oflags = 0; /* Show that this is not network */
795*42e22086SApple OSS Distributions
796*42e22086SApple OSS Distributions #if CONFIG_KDP_INTERACTIVE_DEBUGGING
797*42e22086SApple OSS Distributions /* retrieve final ramdisk range and initialize KDP variables */
798*42e22086SApple OSS Distributions if (mdevgetrange(xchar, &kdp_core_ramdisk_addr, &kdp_core_ramdisk_size) != 0) {
799*42e22086SApple OSS Distributions IOLog("Unable to retrieve range for root memory device %d\n", xchar);
800*42e22086SApple OSS Distributions kdp_core_ramdisk_addr = 0;
801*42e22086SApple OSS Distributions kdp_core_ramdisk_size = 0;
802*42e22086SApple OSS Distributions }
803*42e22086SApple OSS Distributions #endif
804*42e22086SApple OSS Distributions
805*42e22086SApple OSS Distributions goto iofrootx; /* Join common exit... */
806*42e22086SApple OSS Distributions }
807*42e22086SApple OSS Distributions panic("IOFindBSDRoot: specified root memory device, %s, has not been configured", rdBootVar); /* Not there */
808*42e22086SApple OSS Distributions }
809*42e22086SApple OSS Distributions }
810*42e22086SApple OSS Distributions
811*42e22086SApple OSS Distributions if ((!matching) && rdBootVar[0]) {
812*42e22086SApple OSS Distributions // by BSD name
813*42e22086SApple OSS Distributions look = rdBootVar;
814*42e22086SApple OSS Distributions if (look[0] == '*') {
815*42e22086SApple OSS Distributions look++;
816*42e22086SApple OSS Distributions }
817*42e22086SApple OSS Distributions
818*42e22086SApple OSS Distributions if (strncmp( look, "en", strlen( "en" )) == 0) {
819*42e22086SApple OSS Distributions matching = IONetworkNamePrefixMatching( "en" );
820*42e22086SApple OSS Distributions needNetworkKexts = true;
821*42e22086SApple OSS Distributions } else if (strncmp( look, "uuid", strlen( "uuid" )) == 0) {
822*42e22086SApple OSS Distributions OSDataAllocation<char> uuid( kMaxBootVar, OSAllocateMemory );
823*42e22086SApple OSS Distributions
824*42e22086SApple OSS Distributions if (uuid) {
825*42e22086SApple OSS Distributions OSString *uuidString;
826*42e22086SApple OSS Distributions
827*42e22086SApple OSS Distributions if (!PE_parse_boot_argn( "boot-uuid", uuid.data(), kMaxBootVar )) {
828*42e22086SApple OSS Distributions panic( "rd=uuid but no boot-uuid=<value> specified" );
829*42e22086SApple OSS Distributions }
830*42e22086SApple OSS Distributions uuidString = OSString::withCString(uuid.data());
831*42e22086SApple OSS Distributions if (uuidString) {
832*42e22086SApple OSS Distributions IOService::publishResource( "boot-uuid", uuidString );
833*42e22086SApple OSS Distributions uuidString->release();
834*42e22086SApple OSS Distributions IOLog("\nWaiting for boot volume with UUID %s\n", uuid.data());
835*42e22086SApple OSS Distributions matching = IOUUIDMatching();
836*42e22086SApple OSS Distributions mediaProperty = "boot-uuid-media";
837*42e22086SApple OSS Distributions }
838*42e22086SApple OSS Distributions }
839*42e22086SApple OSS Distributions } else {
840*42e22086SApple OSS Distributions matching = IOBSDNameMatching( look );
841*42e22086SApple OSS Distributions }
842*42e22086SApple OSS Distributions }
843*42e22086SApple OSS Distributions
844*42e22086SApple OSS Distributions if (!matching) {
845*42e22086SApple OSS Distributions OSString * astring;
846*42e22086SApple OSS Distributions // Match any HFS media
847*42e22086SApple OSS Distributions
848*42e22086SApple OSS Distributions matching = IOService::serviceMatching( "IOMedia" );
849*42e22086SApple OSS Distributions assert(matching);
850*42e22086SApple OSS Distributions astring = OSString::withCStringNoCopy("Apple_HFS");
851*42e22086SApple OSS Distributions if (astring) {
852*42e22086SApple OSS Distributions matching->setObject("Content", astring);
853*42e22086SApple OSS Distributions astring->release();
854*42e22086SApple OSS Distributions }
855*42e22086SApple OSS Distributions }
856*42e22086SApple OSS Distributions
857*42e22086SApple OSS Distributions if (gIOKitDebug & kIOWaitQuietBeforeRoot) {
858*42e22086SApple OSS Distributions IOLog( "Waiting for matching to complete\n" );
859*42e22086SApple OSS Distributions IOService::getPlatform()->waitQuiet();
860*42e22086SApple OSS Distributions }
861*42e22086SApple OSS Distributions
862*42e22086SApple OSS Distributions if (matching) {
863*42e22086SApple OSS Distributions OSSerialize * s = OSSerialize::withCapacity( 5 );
864*42e22086SApple OSS Distributions
865*42e22086SApple OSS Distributions if (matching->serialize( s )) {
866*42e22086SApple OSS Distributions IOLog( "Waiting on %s\n", s->text());
867*42e22086SApple OSS Distributions }
868*42e22086SApple OSS Distributions s->release();
869*42e22086SApple OSS Distributions }
870*42e22086SApple OSS Distributions
871*42e22086SApple OSS Distributions char namep[8];
872*42e22086SApple OSS Distributions if (needNetworkKexts
873*42e22086SApple OSS Distributions || PE_parse_boot_argn("-s", namep, sizeof(namep))) {
874*42e22086SApple OSS Distributions IOService::startDeferredMatches();
875*42e22086SApple OSS Distributions }
876*42e22086SApple OSS Distributions
877*42e22086SApple OSS Distributions do {
878*42e22086SApple OSS Distributions t.tv_sec = ROOTDEVICETIMEOUT;
879*42e22086SApple OSS Distributions t.tv_nsec = 0;
880*42e22086SApple OSS Distributions matching->retain();
881*42e22086SApple OSS Distributions service = IOService::waitForService( matching, &t );
882*42e22086SApple OSS Distributions if ((!service) || (mountAttempts == 10)) {
883*42e22086SApple OSS Distributions #if !XNU_TARGET_OS_OSX || !defined(__arm64__)
884*42e22086SApple OSS Distributions PE_display_icon( 0, "noroot");
885*42e22086SApple OSS Distributions IOLog( "Still waiting for root device\n" );
886*42e22086SApple OSS Distributions #endif
887*42e22086SApple OSS Distributions
888*42e22086SApple OSS Distributions if (!debugInfoPrintedOnce) {
889*42e22086SApple OSS Distributions debugInfoPrintedOnce = true;
890*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogDTree) {
891*42e22086SApple OSS Distributions IOLog("\nDT plane:\n");
892*42e22086SApple OSS Distributions IOPrintPlane( gIODTPlane );
893*42e22086SApple OSS Distributions }
894*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogServiceTree) {
895*42e22086SApple OSS Distributions IOLog("\nService plane:\n");
896*42e22086SApple OSS Distributions IOPrintPlane( gIOServicePlane );
897*42e22086SApple OSS Distributions }
898*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogMemory) {
899*42e22086SApple OSS Distributions IOPrintMemory();
900*42e22086SApple OSS Distributions }
901*42e22086SApple OSS Distributions }
902*42e22086SApple OSS Distributions
903*42e22086SApple OSS Distributions #if XNU_TARGET_OS_OSX && defined(__arm64__)
904*42e22086SApple OSS Distributions // The disk isn't found - have the user pick from System Recovery.
905*42e22086SApple OSS Distributions (void)IOSetRecoveryBoot(BSD_BOOTFAIL_MEDIA_MISSING, NULL, true);
906*42e22086SApple OSS Distributions #elif XNU_TARGET_OS_IOS
907*42e22086SApple OSS Distributions panic("Failed to mount root device");
908*42e22086SApple OSS Distributions #endif
909*42e22086SApple OSS Distributions }
910*42e22086SApple OSS Distributions } while (!service);
911*42e22086SApple OSS Distributions
912*42e22086SApple OSS Distributions OSSafeReleaseNULL(matching);
913*42e22086SApple OSS Distributions
914*42e22086SApple OSS Distributions if (service && mediaProperty) {
915*42e22086SApple OSS Distributions service = (IOService *)service->getProperty(mediaProperty);
916*42e22086SApple OSS Distributions }
917*42e22086SApple OSS Distributions
918*42e22086SApple OSS Distributions mjr = 0;
919*42e22086SApple OSS Distributions mnr = 0;
920*42e22086SApple OSS Distributions
921*42e22086SApple OSS Distributions // If the IOService we matched to is a subclass of IONetworkInterface,
922*42e22086SApple OSS Distributions // then make sure it has been registered with BSD and has a BSD name
923*42e22086SApple OSS Distributions // assigned.
924*42e22086SApple OSS Distributions
925*42e22086SApple OSS Distributions if (service
926*42e22086SApple OSS Distributions && service->metaCast( "IONetworkInterface" )
927*42e22086SApple OSS Distributions && !IORegisterNetworkInterface( service )) {
928*42e22086SApple OSS Distributions service = NULL;
929*42e22086SApple OSS Distributions }
930*42e22086SApple OSS Distributions
931*42e22086SApple OSS Distributions if (service) {
932*42e22086SApple OSS Distributions len = kMaxPathBuf;
933*42e22086SApple OSS Distributions service->getPath( str.data(), &len, gIOServicePlane );
934*42e22086SApple OSS Distributions IOLog("Got boot device = %s\n", str.data());
935*42e22086SApple OSS Distributions
936*42e22086SApple OSS Distributions iostr = (OSString *) service->getProperty( kIOBSDNameKey );
937*42e22086SApple OSS Distributions if (iostr) {
938*42e22086SApple OSS Distributions strlcpy( rootName, iostr->getCStringNoCopy(), rootNameSize );
939*42e22086SApple OSS Distributions }
940*42e22086SApple OSS Distributions off = (OSNumber *) service->getProperty( kIOBSDMajorKey );
941*42e22086SApple OSS Distributions if (off) {
942*42e22086SApple OSS Distributions mjr = off->unsigned32BitValue();
943*42e22086SApple OSS Distributions }
944*42e22086SApple OSS Distributions off = (OSNumber *) service->getProperty( kIOBSDMinorKey );
945*42e22086SApple OSS Distributions if (off) {
946*42e22086SApple OSS Distributions mnr = off->unsigned32BitValue();
947*42e22086SApple OSS Distributions }
948*42e22086SApple OSS Distributions
949*42e22086SApple OSS Distributions if (service->metaCast( "IONetworkInterface" )) {
950*42e22086SApple OSS Distributions flags |= 1;
951*42e22086SApple OSS Distributions }
952*42e22086SApple OSS Distributions } else {
953*42e22086SApple OSS Distributions IOLog( "Wait for root failed\n" );
954*42e22086SApple OSS Distributions strlcpy( rootName, "en0", rootNameSize );
955*42e22086SApple OSS Distributions flags |= 1;
956*42e22086SApple OSS Distributions }
957*42e22086SApple OSS Distributions
958*42e22086SApple OSS Distributions IOLog( "BSD root: %s", rootName );
959*42e22086SApple OSS Distributions if (mjr) {
960*42e22086SApple OSS Distributions IOLog(", major %d, minor %d\n", mjr, mnr );
961*42e22086SApple OSS Distributions } else {
962*42e22086SApple OSS Distributions IOLog("\n");
963*42e22086SApple OSS Distributions }
964*42e22086SApple OSS Distributions
965*42e22086SApple OSS Distributions *root = makedev( mjr, mnr );
966*42e22086SApple OSS Distributions *oflags = flags;
967*42e22086SApple OSS Distributions
968*42e22086SApple OSS Distributions iofrootx:
969*42e22086SApple OSS Distributions
970*42e22086SApple OSS Distributions IOService::setRootMedia(service);
971*42e22086SApple OSS Distributions
972*42e22086SApple OSS Distributions if ((gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) {
973*42e22086SApple OSS Distributions IOService::getPlatform()->waitQuiet();
974*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogDTree) {
975*42e22086SApple OSS Distributions IOLog("\nDT plane:\n");
976*42e22086SApple OSS Distributions IOPrintPlane( gIODTPlane );
977*42e22086SApple OSS Distributions }
978*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogServiceTree) {
979*42e22086SApple OSS Distributions IOLog("\nService plane:\n");
980*42e22086SApple OSS Distributions IOPrintPlane( gIOServicePlane );
981*42e22086SApple OSS Distributions }
982*42e22086SApple OSS Distributions if (gIOKitDebug & kIOLogMemory) {
983*42e22086SApple OSS Distributions IOPrintMemory();
984*42e22086SApple OSS Distributions }
985*42e22086SApple OSS Distributions }
986*42e22086SApple OSS Distributions
987*42e22086SApple OSS Distributions return kIOReturnSuccess;
988*42e22086SApple OSS Distributions }
989*42e22086SApple OSS Distributions
990*42e22086SApple OSS Distributions void
IOSetImageBoot(void)991*42e22086SApple OSS Distributions IOSetImageBoot(void)
992*42e22086SApple OSS Distributions {
993*42e22086SApple OSS Distributions // this will unhide all IOMedia, without waiting for kernelmanagement to start
994*42e22086SApple OSS Distributions IOService::setRootMedia(NULL);
995*42e22086SApple OSS Distributions }
996*42e22086SApple OSS Distributions
997*42e22086SApple OSS Distributions bool
IORamDiskBSDRoot(void)998*42e22086SApple OSS Distributions IORamDiskBSDRoot(void)
999*42e22086SApple OSS Distributions {
1000*42e22086SApple OSS Distributions char rdBootVar[kMaxBootVar];
1001*42e22086SApple OSS Distributions if (PE_parse_boot_argn("rd", rdBootVar, kMaxBootVar )
1002*42e22086SApple OSS Distributions || PE_parse_boot_argn("rootdev", rdBootVar, kMaxBootVar )) {
1003*42e22086SApple OSS Distributions if ((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) {
1004*42e22086SApple OSS Distributions return true;
1005*42e22086SApple OSS Distributions }
1006*42e22086SApple OSS Distributions }
1007*42e22086SApple OSS Distributions return false;
1008*42e22086SApple OSS Distributions }
1009*42e22086SApple OSS Distributions
1010*42e22086SApple OSS Distributions void
IOSecureBSDRoot(const char * rootName)1011*42e22086SApple OSS Distributions IOSecureBSDRoot(const char * rootName)
1012*42e22086SApple OSS Distributions {
1013*42e22086SApple OSS Distributions #if CONFIG_SECURE_BSD_ROOT
1014*42e22086SApple OSS Distributions IOReturn result;
1015*42e22086SApple OSS Distributions IOPlatformExpert *pe;
1016*42e22086SApple OSS Distributions OSDictionary *matching;
1017*42e22086SApple OSS Distributions const OSSymbol *functionName = OSSymbol::withCStringNoCopy("SecureRootName");
1018*42e22086SApple OSS Distributions
1019*42e22086SApple OSS Distributions matching = IOService::serviceMatching("IOPlatformExpert");
1020*42e22086SApple OSS Distributions assert(matching);
1021*42e22086SApple OSS Distributions pe = (IOPlatformExpert *) IOService::waitForMatchingService(matching, 30ULL * kSecondScale);
1022*42e22086SApple OSS Distributions matching->release();
1023*42e22086SApple OSS Distributions assert(pe);
1024*42e22086SApple OSS Distributions // Returns kIOReturnNotPrivileged is the root device is not secure.
1025*42e22086SApple OSS Distributions // Returns kIOReturnUnsupported if "SecureRootName" is not implemented.
1026*42e22086SApple OSS Distributions result = pe->callPlatformFunction(functionName, false, (void *)rootName, (void *)NULL, (void *)NULL, (void *)NULL);
1027*42e22086SApple OSS Distributions functionName->release();
1028*42e22086SApple OSS Distributions OSSafeReleaseNULL(pe);
1029*42e22086SApple OSS Distributions
1030*42e22086SApple OSS Distributions if (result == kIOReturnNotPrivileged) {
1031*42e22086SApple OSS Distributions mdevremoveall();
1032*42e22086SApple OSS Distributions }
1033*42e22086SApple OSS Distributions
1034*42e22086SApple OSS Distributions #endif // CONFIG_SECURE_BSD_ROOT
1035*42e22086SApple OSS Distributions }
1036*42e22086SApple OSS Distributions
1037*42e22086SApple OSS Distributions void *
IOBSDRegistryEntryForDeviceTree(char * path)1038*42e22086SApple OSS Distributions IOBSDRegistryEntryForDeviceTree(char * path)
1039*42e22086SApple OSS Distributions {
1040*42e22086SApple OSS Distributions return IORegistryEntry::fromPath(path, gIODTPlane);
1041*42e22086SApple OSS Distributions }
1042*42e22086SApple OSS Distributions
1043*42e22086SApple OSS Distributions void
IOBSDRegistryEntryRelease(void * entry)1044*42e22086SApple OSS Distributions IOBSDRegistryEntryRelease(void * entry)
1045*42e22086SApple OSS Distributions {
1046*42e22086SApple OSS Distributions IORegistryEntry * regEntry = (IORegistryEntry *)entry;
1047*42e22086SApple OSS Distributions
1048*42e22086SApple OSS Distributions if (regEntry) {
1049*42e22086SApple OSS Distributions regEntry->release();
1050*42e22086SApple OSS Distributions }
1051*42e22086SApple OSS Distributions return;
1052*42e22086SApple OSS Distributions }
1053*42e22086SApple OSS Distributions
1054*42e22086SApple OSS Distributions const void *
IOBSDRegistryEntryGetData(void * entry,char * property_name,int * packet_length)1055*42e22086SApple OSS Distributions IOBSDRegistryEntryGetData(void * entry, char * property_name,
1056*42e22086SApple OSS Distributions int * packet_length)
1057*42e22086SApple OSS Distributions {
1058*42e22086SApple OSS Distributions OSData * data;
1059*42e22086SApple OSS Distributions IORegistryEntry * regEntry = (IORegistryEntry *)entry;
1060*42e22086SApple OSS Distributions
1061*42e22086SApple OSS Distributions data = (OSData *) regEntry->getProperty(property_name);
1062*42e22086SApple OSS Distributions if (data) {
1063*42e22086SApple OSS Distributions *packet_length = data->getLength();
1064*42e22086SApple OSS Distributions return data->getBytesNoCopy();
1065*42e22086SApple OSS Distributions }
1066*42e22086SApple OSS Distributions return NULL;
1067*42e22086SApple OSS Distributions }
1068*42e22086SApple OSS Distributions
1069*42e22086SApple OSS Distributions kern_return_t
IOBSDGetPlatformUUID(uuid_t uuid,mach_timespec_t timeout)1070*42e22086SApple OSS Distributions IOBSDGetPlatformUUID( uuid_t uuid, mach_timespec_t timeout )
1071*42e22086SApple OSS Distributions {
1072*42e22086SApple OSS Distributions IOService * resources;
1073*42e22086SApple OSS Distributions OSString * string;
1074*42e22086SApple OSS Distributions
1075*42e22086SApple OSS Distributions resources = IOService::waitForService( IOService::resourceMatching( kIOPlatformUUIDKey ), (timeout.tv_sec || timeout.tv_nsec) ? &timeout : NULL );
1076*42e22086SApple OSS Distributions if (resources == NULL) {
1077*42e22086SApple OSS Distributions return KERN_OPERATION_TIMED_OUT;
1078*42e22086SApple OSS Distributions }
1079*42e22086SApple OSS Distributions
1080*42e22086SApple OSS Distributions string = (OSString *) IOService::getPlatform()->getProvider()->getProperty( kIOPlatformUUIDKey );
1081*42e22086SApple OSS Distributions if (string == NULL) {
1082*42e22086SApple OSS Distributions return KERN_NOT_SUPPORTED;
1083*42e22086SApple OSS Distributions }
1084*42e22086SApple OSS Distributions
1085*42e22086SApple OSS Distributions uuid_parse( string->getCStringNoCopy(), uuid );
1086*42e22086SApple OSS Distributions
1087*42e22086SApple OSS Distributions return KERN_SUCCESS;
1088*42e22086SApple OSS Distributions }
1089*42e22086SApple OSS Distributions } /* extern "C" */
1090*42e22086SApple OSS Distributions
1091*42e22086SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1092*42e22086SApple OSS Distributions
1093*42e22086SApple OSS Distributions #include <sys/conf.h>
1094*42e22086SApple OSS Distributions #include <sys/lock.h>
1095*42e22086SApple OSS Distributions #include <sys/vnode.h>
1096*42e22086SApple OSS Distributions #include <sys/vnode_if.h>
1097*42e22086SApple OSS Distributions #include <sys/vnode_internal.h>
1098*42e22086SApple OSS Distributions #include <sys/fcntl.h>
1099*42e22086SApple OSS Distributions #include <sys/fsctl.h>
1100*42e22086SApple OSS Distributions #include <sys/mount.h>
1101*42e22086SApple OSS Distributions #include <IOKit/IOPolledInterface.h>
1102*42e22086SApple OSS Distributions #include <IOKit/IOBufferMemoryDescriptor.h>
1103*42e22086SApple OSS Distributions
1104*42e22086SApple OSS Distributions // see HFSIOC_VOLUME_STATUS in APFS/HFS
1105*42e22086SApple OSS Distributions #define HFS_IOCTL_VOLUME_STATUS _IOR('h', 24, u_int32_t)
1106*42e22086SApple OSS Distributions
1107*42e22086SApple OSS Distributions LCK_GRP_DECLARE(gIOPolledCoreFileGrp, "polled_corefile");
1108*42e22086SApple OSS Distributions LCK_MTX_DECLARE(gIOPolledCoreFileMtx, &gIOPolledCoreFileGrp);
1109*42e22086SApple OSS Distributions
1110*42e22086SApple OSS Distributions IOPolledFileIOVars * gIOPolledCoreFileVars;
1111*42e22086SApple OSS Distributions kern_return_t gIOPolledCoreFileOpenRet = kIOReturnNotReady;
1112*42e22086SApple OSS Distributions IOPolledCoreFileMode_t gIOPolledCoreFileMode = kIOPolledCoreFileModeNotInitialized;
1113*42e22086SApple OSS Distributions
1114*42e22086SApple OSS Distributions #if IOPOLLED_COREFILE
1115*42e22086SApple OSS Distributions
1116*42e22086SApple OSS Distributions #if defined(XNU_TARGET_OS_BRIDGE)
1117*42e22086SApple OSS Distributions // On bridgeOS allocate a 150MB corefile and leave 150MB free
1118*42e22086SApple OSS Distributions #define kIOCoreDumpSize 150ULL*1024ULL*1024ULL
1119*42e22086SApple OSS Distributions #define kIOCoreDumpFreeSize 150ULL*1024ULL*1024ULL
1120*42e22086SApple OSS Distributions
1121*42e22086SApple OSS Distributions #elif !defined(XNU_TARGET_OS_OSX) /* defined(XNU_TARGET_OS_BRIDGE) */
1122*42e22086SApple OSS Distributions // On embedded devices with >3GB DRAM we allocate a 500MB corefile
1123*42e22086SApple OSS Distributions // otherwise allocate a 350MB corefile. Leave 350 MB free
1124*42e22086SApple OSS Distributions
1125*42e22086SApple OSS Distributions #define kIOCoreDumpMinSize 350ULL*1024ULL*1024ULL
1126*42e22086SApple OSS Distributions #define kIOCoreDumpLargeSize 500ULL*1024ULL*1024ULL
1127*42e22086SApple OSS Distributions
1128*42e22086SApple OSS Distributions #define kIOCoreDumpFreeSize 350ULL*1024ULL*1024ULL
1129*42e22086SApple OSS Distributions
1130*42e22086SApple OSS Distributions #else /* defined(XNU_TARGET_OS_BRIDGE) */
1131*42e22086SApple OSS Distributions // on macOS devices allocate a corefile sized at 1GB / 32GB of DRAM,
1132*42e22086SApple OSS Distributions // fallback to a 1GB corefile and leave at least 1GB free
1133*42e22086SApple OSS Distributions #define kIOCoreDumpMinSize 1024ULL*1024ULL*1024ULL
1134*42e22086SApple OSS Distributions #define kIOCoreDumpIncrementalSize 1024ULL*1024ULL*1024ULL
1135*42e22086SApple OSS Distributions
1136*42e22086SApple OSS Distributions #define kIOCoreDumpFreeSize 1024ULL*1024ULL*1024ULL
1137*42e22086SApple OSS Distributions
1138*42e22086SApple OSS Distributions // on older macOS devices we allocate a 1MB file at boot
1139*42e22086SApple OSS Distributions // to store a panic time stackshot
1140*42e22086SApple OSS Distributions #define kIOStackshotFileSize 1024ULL*1024ULL
1141*42e22086SApple OSS Distributions
1142*42e22086SApple OSS Distributions #endif /* defined(XNU_TARGET_OS_BRIDGE) */
1143*42e22086SApple OSS Distributions
1144*42e22086SApple OSS Distributions static IOPolledCoreFileMode_t
GetCoreFileMode()1145*42e22086SApple OSS Distributions GetCoreFileMode()
1146*42e22086SApple OSS Distributions {
1147*42e22086SApple OSS Distributions if (on_device_corefile_enabled()) {
1148*42e22086SApple OSS Distributions return kIOPolledCoreFileModeCoredump;
1149*42e22086SApple OSS Distributions } else if (panic_stackshot_to_disk_enabled()) {
1150*42e22086SApple OSS Distributions return kIOPolledCoreFileModeStackshot;
1151*42e22086SApple OSS Distributions } else {
1152*42e22086SApple OSS Distributions return kIOPolledCoreFileModeDisabled;
1153*42e22086SApple OSS Distributions }
1154*42e22086SApple OSS Distributions }
1155*42e22086SApple OSS Distributions
1156*42e22086SApple OSS Distributions static void
IOCoreFileGetSize(uint64_t * ideal_size,uint64_t * fallback_size,uint64_t * free_space_to_leave,IOPolledCoreFileMode_t mode)1157*42e22086SApple OSS Distributions IOCoreFileGetSize(uint64_t *ideal_size, uint64_t *fallback_size, uint64_t *free_space_to_leave, IOPolledCoreFileMode_t mode)
1158*42e22086SApple OSS Distributions {
1159*42e22086SApple OSS Distributions unsigned int requested_corefile_size = 0;
1160*42e22086SApple OSS Distributions
1161*42e22086SApple OSS Distributions *ideal_size = *fallback_size = *free_space_to_leave = 0;
1162*42e22086SApple OSS Distributions
1163*42e22086SApple OSS Distributions // If a custom size was requested, override the ideal and requested sizes
1164*42e22086SApple OSS Distributions if (PE_parse_boot_argn("corefile_size_mb", &requested_corefile_size,
1165*42e22086SApple OSS Distributions sizeof(requested_corefile_size))) {
1166*42e22086SApple OSS Distributions IOLog("Boot-args specify %d MB kernel corefile\n", requested_corefile_size);
1167*42e22086SApple OSS Distributions
1168*42e22086SApple OSS Distributions *ideal_size = *fallback_size = (requested_corefile_size * 1024ULL * 1024ULL);
1169*42e22086SApple OSS Distributions return;
1170*42e22086SApple OSS Distributions }
1171*42e22086SApple OSS Distributions
1172*42e22086SApple OSS Distributions unsigned int status_flags = 0;
1173*42e22086SApple OSS Distributions int error = VNOP_IOCTL(rootvnode, HFS_IOCTL_VOLUME_STATUS, (caddr_t)&status_flags, 0,
1174*42e22086SApple OSS Distributions vfs_context_kernel());
1175*42e22086SApple OSS Distributions if (!error) {
1176*42e22086SApple OSS Distributions if (status_flags & (VQ_VERYLOWDISK | VQ_LOWDISK | VQ_NEARLOWDISK)) {
1177*42e22086SApple OSS Distributions IOLog("Volume is low on space. Not allocating kernel corefile.\n");
1178*42e22086SApple OSS Distributions return;
1179*42e22086SApple OSS Distributions }
1180*42e22086SApple OSS Distributions } else {
1181*42e22086SApple OSS Distributions IOLog("Couldn't retrieve volume status. Error %d\n", error);
1182*42e22086SApple OSS Distributions }
1183*42e22086SApple OSS Distributions
1184*42e22086SApple OSS Distributions #if defined(XNU_TARGET_OS_BRIDGE)
1185*42e22086SApple OSS Distributions #pragma unused(mode)
1186*42e22086SApple OSS Distributions *ideal_size = *fallback_size = kIOCoreDumpSize;
1187*42e22086SApple OSS Distributions *free_space_to_leave = kIOCoreDumpFreeSize;
1188*42e22086SApple OSS Distributions #elif !defined(XNU_TARGET_OS_OSX) /* defined(XNU_TARGET_OS_BRIDGE) */
1189*42e22086SApple OSS Distributions #pragma unused(mode)
1190*42e22086SApple OSS Distributions *ideal_size = *fallback_size = kIOCoreDumpMinSize;
1191*42e22086SApple OSS Distributions
1192*42e22086SApple OSS Distributions if (max_mem > (3 * 1024ULL * 1024ULL * 1024ULL)) {
1193*42e22086SApple OSS Distributions *ideal_size = kIOCoreDumpLargeSize;
1194*42e22086SApple OSS Distributions }
1195*42e22086SApple OSS Distributions
1196*42e22086SApple OSS Distributions *free_space_to_leave = kIOCoreDumpFreeSize;
1197*42e22086SApple OSS Distributions #else /* defined(XNU_TARGET_OS_BRIDGE) */
1198*42e22086SApple OSS Distributions if (mode == kIOPolledCoreFileModeCoredump) {
1199*42e22086SApple OSS Distributions *ideal_size = *fallback_size = kIOCoreDumpMinSize;
1200*42e22086SApple OSS Distributions if (kIOCoreDumpIncrementalSize != 0 && max_mem > (32 * 1024ULL * 1024ULL * 1024ULL)) {
1201*42e22086SApple OSS Distributions *ideal_size = ((ROUNDUP(max_mem, (32 * 1024ULL * 1024ULL * 1024ULL)) / (32 * 1024ULL * 1024ULL * 1024ULL)) * kIOCoreDumpIncrementalSize);
1202*42e22086SApple OSS Distributions }
1203*42e22086SApple OSS Distributions *free_space_to_leave = kIOCoreDumpFreeSize;
1204*42e22086SApple OSS Distributions } else if (mode == kIOPolledCoreFileModeStackshot) {
1205*42e22086SApple OSS Distributions *ideal_size = *fallback_size = *free_space_to_leave = kIOStackshotFileSize;
1206*42e22086SApple OSS Distributions }
1207*42e22086SApple OSS Distributions #endif /* defined(XNU_TARGET_OS_BRIDGE) */
1208*42e22086SApple OSS Distributions
1209*42e22086SApple OSS Distributions return;
1210*42e22086SApple OSS Distributions }
1211*42e22086SApple OSS Distributions
1212*42e22086SApple OSS Distributions static IOReturn
IOAccessCoreFileData(void * context,boolean_t write,uint64_t offset,int length,void * buffer)1213*42e22086SApple OSS Distributions IOAccessCoreFileData(void *context, boolean_t write, uint64_t offset, int length, void *buffer)
1214*42e22086SApple OSS Distributions {
1215*42e22086SApple OSS Distributions errno_t vnode_error = 0;
1216*42e22086SApple OSS Distributions vfs_context_t vfs_context;
1217*42e22086SApple OSS Distributions vnode_t vnode_ptr = (vnode_t) context;
1218*42e22086SApple OSS Distributions
1219*42e22086SApple OSS Distributions vfs_context = vfs_context_kernel();
1220*42e22086SApple OSS Distributions vnode_error = vn_rdwr(write ? UIO_WRITE : UIO_READ, vnode_ptr, (caddr_t)buffer, length, offset,
1221*42e22086SApple OSS Distributions UIO_SYSSPACE, IO_SWAP_DISPATCH | IO_SYNC | IO_NOCACHE | IO_UNIT, vfs_context_ucred(vfs_context), NULL, vfs_context_proc(vfs_context));
1222*42e22086SApple OSS Distributions
1223*42e22086SApple OSS Distributions if (vnode_error) {
1224*42e22086SApple OSS Distributions IOLog("Failed to %s the corefile. Error %d\n", write ? "write to" : "read from", vnode_error);
1225*42e22086SApple OSS Distributions return kIOReturnError;
1226*42e22086SApple OSS Distributions }
1227*42e22086SApple OSS Distributions
1228*42e22086SApple OSS Distributions return kIOReturnSuccess;
1229*42e22086SApple OSS Distributions }
1230*42e22086SApple OSS Distributions
1231*42e22086SApple OSS Distributions static void
IOOpenPolledCoreFile(thread_call_param_t __unused,thread_call_param_t corefilename)1232*42e22086SApple OSS Distributions IOOpenPolledCoreFile(thread_call_param_t __unused, thread_call_param_t corefilename)
1233*42e22086SApple OSS Distributions {
1234*42e22086SApple OSS Distributions assert(corefilename != NULL);
1235*42e22086SApple OSS Distributions
1236*42e22086SApple OSS Distributions IOReturn err;
1237*42e22086SApple OSS Distributions char *filename = (char *) corefilename;
1238*42e22086SApple OSS Distributions uint64_t corefile_size_bytes = 0, corefile_fallback_size_bytes = 0, free_space_to_leave_bytes = 0;
1239*42e22086SApple OSS Distributions IOPolledCoreFileMode_t mode_to_init = GetCoreFileMode();
1240*42e22086SApple OSS Distributions
1241*42e22086SApple OSS Distributions if (gIOPolledCoreFileVars) {
1242*42e22086SApple OSS Distributions return;
1243*42e22086SApple OSS Distributions }
1244*42e22086SApple OSS Distributions if (!IOPolledInterface::gMetaClass.getInstanceCount()) {
1245*42e22086SApple OSS Distributions return;
1246*42e22086SApple OSS Distributions }
1247*42e22086SApple OSS Distributions
1248*42e22086SApple OSS Distributions if (gIOPolledCoreFileMode == kIOPolledCoreFileModeUnlinked) {
1249*42e22086SApple OSS Distributions return;
1250*42e22086SApple OSS Distributions }
1251*42e22086SApple OSS Distributions
1252*42e22086SApple OSS Distributions if (mode_to_init == kIOPolledCoreFileModeDisabled) {
1253*42e22086SApple OSS Distributions gIOPolledCoreFileMode = kIOPolledCoreFileModeDisabled;
1254*42e22086SApple OSS Distributions return;
1255*42e22086SApple OSS Distributions }
1256*42e22086SApple OSS Distributions
1257*42e22086SApple OSS Distributions // We'll overwrite this once we open the file, we update this to mark that we have made
1258*42e22086SApple OSS Distributions // it past initialization
1259*42e22086SApple OSS Distributions gIOPolledCoreFileMode = kIOPolledCoreFileModeClosed;
1260*42e22086SApple OSS Distributions
1261*42e22086SApple OSS Distributions IOCoreFileGetSize(&corefile_size_bytes, &corefile_fallback_size_bytes, &free_space_to_leave_bytes, mode_to_init);
1262*42e22086SApple OSS Distributions
1263*42e22086SApple OSS Distributions if (corefile_size_bytes == 0 && corefile_fallback_size_bytes == 0) {
1264*42e22086SApple OSS Distributions gIOPolledCoreFileMode = kIOPolledCoreFileModeUnlinked;
1265*42e22086SApple OSS Distributions return;
1266*42e22086SApple OSS Distributions }
1267*42e22086SApple OSS Distributions
1268*42e22086SApple OSS Distributions do {
1269*42e22086SApple OSS Distributions err = IOPolledFileOpen(filename, kIOPolledFileCreate, corefile_size_bytes, free_space_to_leave_bytes,
1270*42e22086SApple OSS Distributions NULL, 0, &gIOPolledCoreFileVars, NULL, NULL, NULL);
1271*42e22086SApple OSS Distributions if (kIOReturnSuccess == err) {
1272*42e22086SApple OSS Distributions break;
1273*42e22086SApple OSS Distributions } else if (kIOReturnNoSpace == err) {
1274*42e22086SApple OSS Distributions IOLog("Failed to open corefile of size %llu MB (low disk space)",
1275*42e22086SApple OSS Distributions (corefile_size_bytes / (1024ULL * 1024ULL)));
1276*42e22086SApple OSS Distributions if (corefile_size_bytes == corefile_fallback_size_bytes) {
1277*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = err;
1278*42e22086SApple OSS Distributions return;
1279*42e22086SApple OSS Distributions }
1280*42e22086SApple OSS Distributions } else {
1281*42e22086SApple OSS Distributions IOLog("Failed to open corefile of size %llu MB (returned error 0x%x)\n",
1282*42e22086SApple OSS Distributions (corefile_size_bytes / (1024ULL * 1024ULL)), err);
1283*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = err;
1284*42e22086SApple OSS Distributions return;
1285*42e22086SApple OSS Distributions }
1286*42e22086SApple OSS Distributions
1287*42e22086SApple OSS Distributions err = IOPolledFileOpen(filename, kIOPolledFileCreate, corefile_fallback_size_bytes, free_space_to_leave_bytes,
1288*42e22086SApple OSS Distributions NULL, 0, &gIOPolledCoreFileVars, NULL, NULL, NULL);
1289*42e22086SApple OSS Distributions if (kIOReturnSuccess != err) {
1290*42e22086SApple OSS Distributions IOLog("Failed to open corefile of size %llu MB (returned error 0x%x)\n",
1291*42e22086SApple OSS Distributions (corefile_fallback_size_bytes / (1024ULL * 1024ULL)), err);
1292*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = err;
1293*42e22086SApple OSS Distributions return;
1294*42e22086SApple OSS Distributions }
1295*42e22086SApple OSS Distributions } while (false);
1296*42e22086SApple OSS Distributions
1297*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = IOPolledFilePollersSetup(gIOPolledCoreFileVars, kIOPolledPreflightCoreDumpState);
1298*42e22086SApple OSS Distributions if (kIOReturnSuccess != gIOPolledCoreFileOpenRet) {
1299*42e22086SApple OSS Distributions IOPolledFileClose(&gIOPolledCoreFileVars, 0, NULL, 0, 0, 0, false);
1300*42e22086SApple OSS Distributions IOLog("IOPolledFilePollersSetup for corefile failed with error: 0x%x\n", err);
1301*42e22086SApple OSS Distributions } else {
1302*42e22086SApple OSS Distributions IOLog("Opened corefile of size %llu MB\n", (corefile_size_bytes / (1024ULL * 1024ULL)));
1303*42e22086SApple OSS Distributions gIOPolledCoreFileMode = mode_to_init;
1304*42e22086SApple OSS Distributions }
1305*42e22086SApple OSS Distributions
1306*42e22086SApple OSS Distributions // Provide the "polled file available" callback with a temporary way to read from the file
1307*42e22086SApple OSS Distributions (void) IOProvideCoreFileAccess(kdp_core_polled_io_polled_file_available, NULL);
1308*42e22086SApple OSS Distributions
1309*42e22086SApple OSS Distributions return;
1310*42e22086SApple OSS Distributions }
1311*42e22086SApple OSS Distributions
1312*42e22086SApple OSS Distributions kern_return_t
IOProvideCoreFileAccess(IOCoreFileAccessRecipient recipient,void * recipient_context)1313*42e22086SApple OSS Distributions IOProvideCoreFileAccess(IOCoreFileAccessRecipient recipient, void *recipient_context)
1314*42e22086SApple OSS Distributions {
1315*42e22086SApple OSS Distributions kern_return_t error = kIOReturnSuccess;
1316*42e22086SApple OSS Distributions errno_t vnode_error = 0;
1317*42e22086SApple OSS Distributions vfs_context_t vfs_context;
1318*42e22086SApple OSS Distributions vnode_t vnode_ptr;
1319*42e22086SApple OSS Distributions
1320*42e22086SApple OSS Distributions if (!recipient) {
1321*42e22086SApple OSS Distributions return kIOReturnBadArgument;
1322*42e22086SApple OSS Distributions }
1323*42e22086SApple OSS Distributions
1324*42e22086SApple OSS Distributions if (kIOReturnSuccess != gIOPolledCoreFileOpenRet) {
1325*42e22086SApple OSS Distributions return kIOReturnNotReady;
1326*42e22086SApple OSS Distributions }
1327*42e22086SApple OSS Distributions
1328*42e22086SApple OSS Distributions // Open the kernel corefile
1329*42e22086SApple OSS Distributions vfs_context = vfs_context_kernel();
1330*42e22086SApple OSS Distributions vnode_error = vnode_open(kIOCoreDumpPath, (FREAD | FWRITE | O_NOFOLLOW), 0600, 0, &vnode_ptr, vfs_context);
1331*42e22086SApple OSS Distributions if (vnode_error) {
1332*42e22086SApple OSS Distributions IOLog("Failed to open the corefile. Error %d\n", vnode_error);
1333*42e22086SApple OSS Distributions return kIOReturnError;
1334*42e22086SApple OSS Distributions }
1335*42e22086SApple OSS Distributions
1336*42e22086SApple OSS Distributions // Call the recipient function
1337*42e22086SApple OSS Distributions error = recipient(IOAccessCoreFileData, (void *)vnode_ptr, recipient_context);
1338*42e22086SApple OSS Distributions
1339*42e22086SApple OSS Distributions // Close the kernel corefile
1340*42e22086SApple OSS Distributions vnode_close(vnode_ptr, FREAD | FWRITE, vfs_context);
1341*42e22086SApple OSS Distributions
1342*42e22086SApple OSS Distributions return error;
1343*42e22086SApple OSS Distributions }
1344*42e22086SApple OSS Distributions
1345*42e22086SApple OSS Distributions static void
IOClosePolledCoreFile(void)1346*42e22086SApple OSS Distributions IOClosePolledCoreFile(void)
1347*42e22086SApple OSS Distributions {
1348*42e22086SApple OSS Distributions // Notify kdp core that the corefile is no longer available
1349*42e22086SApple OSS Distributions (void) kdp_core_polled_io_polled_file_unavailable();
1350*42e22086SApple OSS Distributions
1351*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = kIOReturnNotOpen;
1352*42e22086SApple OSS Distributions gIOPolledCoreFileMode = kIOPolledCoreFileModeClosed;
1353*42e22086SApple OSS Distributions IOPolledFilePollersClose(gIOPolledCoreFileVars, kIOPolledPostflightCoreDumpState);
1354*42e22086SApple OSS Distributions IOPolledFileClose(&gIOPolledCoreFileVars, 0, NULL, 0, 0, 0, false);
1355*42e22086SApple OSS Distributions }
1356*42e22086SApple OSS Distributions
1357*42e22086SApple OSS Distributions static void
IOUnlinkPolledCoreFile(void)1358*42e22086SApple OSS Distributions IOUnlinkPolledCoreFile(void)
1359*42e22086SApple OSS Distributions {
1360*42e22086SApple OSS Distributions // Notify kdp core that the corefile is no longer available
1361*42e22086SApple OSS Distributions (void) kdp_core_polled_io_polled_file_unavailable();
1362*42e22086SApple OSS Distributions
1363*42e22086SApple OSS Distributions gIOPolledCoreFileOpenRet = kIOReturnNotOpen;
1364*42e22086SApple OSS Distributions gIOPolledCoreFileMode = kIOPolledCoreFileModeUnlinked;
1365*42e22086SApple OSS Distributions IOPolledFilePollersClose(gIOPolledCoreFileVars, kIOPolledPostflightCoreDumpState);
1366*42e22086SApple OSS Distributions IOPolledFileClose(&gIOPolledCoreFileVars, 0, NULL, 0, 0, 0, true);
1367*42e22086SApple OSS Distributions }
1368*42e22086SApple OSS Distributions
1369*42e22086SApple OSS Distributions #endif /* IOPOLLED_COREFILE */
1370*42e22086SApple OSS Distributions
1371*42e22086SApple OSS Distributions extern "C" void
IOBSDMountChange(struct mount * mp,uint32_t op)1372*42e22086SApple OSS Distributions IOBSDMountChange(struct mount * mp, uint32_t op)
1373*42e22086SApple OSS Distributions {
1374*42e22086SApple OSS Distributions #if IOPOLLED_COREFILE
1375*42e22086SApple OSS Distributions uint64_t flags;
1376*42e22086SApple OSS Distributions char path[128];
1377*42e22086SApple OSS Distributions int pathLen;
1378*42e22086SApple OSS Distributions vnode_t vn;
1379*42e22086SApple OSS Distributions int result;
1380*42e22086SApple OSS Distributions
1381*42e22086SApple OSS Distributions lck_mtx_lock(&gIOPolledCoreFileMtx);
1382*42e22086SApple OSS Distributions
1383*42e22086SApple OSS Distributions switch (op) {
1384*42e22086SApple OSS Distributions case kIOMountChangeMount:
1385*42e22086SApple OSS Distributions case kIOMountChangeDidResize:
1386*42e22086SApple OSS Distributions
1387*42e22086SApple OSS Distributions if (gIOPolledCoreFileVars) {
1388*42e22086SApple OSS Distributions break;
1389*42e22086SApple OSS Distributions }
1390*42e22086SApple OSS Distributions flags = vfs_flags(mp);
1391*42e22086SApple OSS Distributions if (MNT_RDONLY & flags) {
1392*42e22086SApple OSS Distributions break;
1393*42e22086SApple OSS Distributions }
1394*42e22086SApple OSS Distributions if (!(MNT_LOCAL & flags)) {
1395*42e22086SApple OSS Distributions break;
1396*42e22086SApple OSS Distributions }
1397*42e22086SApple OSS Distributions
1398*42e22086SApple OSS Distributions vn = vfs_vnodecovered(mp);
1399*42e22086SApple OSS Distributions if (!vn) {
1400*42e22086SApple OSS Distributions break;
1401*42e22086SApple OSS Distributions }
1402*42e22086SApple OSS Distributions pathLen = sizeof(path);
1403*42e22086SApple OSS Distributions result = vn_getpath(vn, &path[0], &pathLen);
1404*42e22086SApple OSS Distributions vnode_put(vn);
1405*42e22086SApple OSS Distributions if (0 != result) {
1406*42e22086SApple OSS Distributions break;
1407*42e22086SApple OSS Distributions }
1408*42e22086SApple OSS Distributions if (!pathLen) {
1409*42e22086SApple OSS Distributions break;
1410*42e22086SApple OSS Distributions }
1411*42e22086SApple OSS Distributions #if defined(XNU_TARGET_OS_BRIDGE)
1412*42e22086SApple OSS Distributions // on bridgeOS systems we put the core in /private/var/internal. We don't
1413*42e22086SApple OSS Distributions // want to match with /private/var because /private/var/internal is often mounted
1414*42e22086SApple OSS Distributions // over /private/var
1415*42e22086SApple OSS Distributions if ((pathLen - 1) < (int) strlen("/private/var/internal")) {
1416*42e22086SApple OSS Distributions break;
1417*42e22086SApple OSS Distributions }
1418*42e22086SApple OSS Distributions #endif
1419*42e22086SApple OSS Distributions if (0 != strncmp(path, kIOCoreDumpPath, pathLen - 1)) {
1420*42e22086SApple OSS Distributions break;
1421*42e22086SApple OSS Distributions }
1422*42e22086SApple OSS Distributions
1423*42e22086SApple OSS Distributions thread_call_enter1(corefile_open_call, (void *) kIOCoreDumpPath);
1424*42e22086SApple OSS Distributions break;
1425*42e22086SApple OSS Distributions
1426*42e22086SApple OSS Distributions case kIOMountChangeUnmount:
1427*42e22086SApple OSS Distributions case kIOMountChangeWillResize:
1428*42e22086SApple OSS Distributions if (gIOPolledCoreFileVars && (mp == kern_file_mount(gIOPolledCoreFileVars->fileRef))) {
1429*42e22086SApple OSS Distributions thread_call_cancel_wait(corefile_open_call);
1430*42e22086SApple OSS Distributions IOClosePolledCoreFile();
1431*42e22086SApple OSS Distributions }
1432*42e22086SApple OSS Distributions break;
1433*42e22086SApple OSS Distributions }
1434*42e22086SApple OSS Distributions
1435*42e22086SApple OSS Distributions lck_mtx_unlock(&gIOPolledCoreFileMtx);
1436*42e22086SApple OSS Distributions #endif /* IOPOLLED_COREFILE */
1437*42e22086SApple OSS Distributions }
1438*42e22086SApple OSS Distributions
1439*42e22086SApple OSS Distributions extern "C" void
IOBSDLowSpaceUnlinkKernelCore(void)1440*42e22086SApple OSS Distributions IOBSDLowSpaceUnlinkKernelCore(void)
1441*42e22086SApple OSS Distributions {
1442*42e22086SApple OSS Distributions #if IOPOLLED_COREFILE
1443*42e22086SApple OSS Distributions lck_mtx_lock(&gIOPolledCoreFileMtx);
1444*42e22086SApple OSS Distributions if (gIOPolledCoreFileVars) {
1445*42e22086SApple OSS Distributions thread_call_cancel_wait(corefile_open_call);
1446*42e22086SApple OSS Distributions IOUnlinkPolledCoreFile();
1447*42e22086SApple OSS Distributions }
1448*42e22086SApple OSS Distributions lck_mtx_unlock(&gIOPolledCoreFileMtx);
1449*42e22086SApple OSS Distributions #endif
1450*42e22086SApple OSS Distributions }
1451*42e22086SApple OSS Distributions
1452*42e22086SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1453*42e22086SApple OSS Distributions
1454*42e22086SApple OSS Distributions extern "C"
1455*42e22086SApple OSS Distributions OS_ALWAYS_INLINE
1456*42e22086SApple OSS Distributions boolean_t
IOCurrentTaskHasStringEntitlement(const char * entitlement,const char * value)1457*42e22086SApple OSS Distributions IOCurrentTaskHasStringEntitlement(const char *entitlement, const char *value)
1458*42e22086SApple OSS Distributions {
1459*42e22086SApple OSS Distributions return IOTaskHasStringEntitlement(NULL, entitlement, value);
1460*42e22086SApple OSS Distributions }
1461*42e22086SApple OSS Distributions
1462*42e22086SApple OSS Distributions extern "C" boolean_t
IOTaskHasStringEntitlement(task_t task,const char * entitlement,const char * value)1463*42e22086SApple OSS Distributions IOTaskHasStringEntitlement(task_t task, const char *entitlement, const char *value)
1464*42e22086SApple OSS Distributions {
1465*42e22086SApple OSS Distributions if (task == kernel_task) {
1466*42e22086SApple OSS Distributions return false;
1467*42e22086SApple OSS Distributions } else if (!entitlement || !value) {
1468*42e22086SApple OSS Distributions return false;
1469*42e22086SApple OSS Distributions }
1470*42e22086SApple OSS Distributions
1471*42e22086SApple OSS Distributions size_t name_length = strnlen(entitlement, CE_MAX_KEY_SIZE);
1472*42e22086SApple OSS Distributions if (name_length >= CE_MAX_KEY_SIZE) {
1473*42e22086SApple OSS Distributions printf("entitlement name length exceeds maximum allowed\n");
1474*42e22086SApple OSS Distributions return false;
1475*42e22086SApple OSS Distributions }
1476*42e22086SApple OSS Distributions
1477*42e22086SApple OSS Distributions size_t value_length = strnlen(value, CE_MAX_KEY_SIZE);
1478*42e22086SApple OSS Distributions if (value_length >= CE_MAX_KEY_SIZE) {
1479*42e22086SApple OSS Distributions printf("entitlement value length exceeds maximum allowed\n");
1480*42e22086SApple OSS Distributions return false;
1481*42e22086SApple OSS Distributions }
1482*42e22086SApple OSS Distributions
1483*42e22086SApple OSS Distributions CEQuery_t query = {
1484*42e22086SApple OSS Distributions CESelectDictValueDynamic((const uint8_t*)entitlement, name_length),
1485*42e22086SApple OSS Distributions CEIsDynamicStringAllowed((const uint8_t*)value, value_length)
1486*42e22086SApple OSS Distributions };
1487*42e22086SApple OSS Distributions
1488*42e22086SApple OSS Distributions #if PMAP_CS_ENABLE && !CONFIG_X86_64_COMPAT
1489*42e22086SApple OSS Distributions
1490*42e22086SApple OSS Distributions /*
1491*42e22086SApple OSS Distributions * If we have PMAP_CS available and code signing is enabled, then we perform
1492*42e22086SApple OSS Distributions * the entitlement check in the PPL.
1493*42e22086SApple OSS Distributions *
1494*42e22086SApple OSS Distributions * Note that the security benefits of doing so are questionable. The PPL has
1495*42e22086SApple OSS Distributions * already locked down the entitlements blob, so we could simply have XNU go
1496*42e22086SApple OSS Distributions * through the locked entitlements blob instead of switching into the PPL to
1497*42e22086SApple OSS Distributions * perform the check. Afterall, the entitlement will be enforced by XNU and
1498*42e22086SApple OSS Distributions * not the PPL, so trapping into the PPL for the check means little.
1499*42e22086SApple OSS Distributions *
1500*42e22086SApple OSS Distributions * Nevertheless, this is kept around to be consistent with how some of the
1501*42e22086SApple OSS Distributions * other interfaces perform their entitlement checks.
1502*42e22086SApple OSS Distributions */
1503*42e22086SApple OSS Distributions
1504*42e22086SApple OSS Distributions if (pmap_cs_enabled()) {
1505*42e22086SApple OSS Distributions if (task == NULL || task == current_task()) {
1506*42e22086SApple OSS Distributions /* NULL task implies current_task */
1507*42e22086SApple OSS Distributions return pmap_query_entitlements(NULL, query, 2, NULL);
1508*42e22086SApple OSS Distributions }
1509*42e22086SApple OSS Distributions
1510*42e22086SApple OSS Distributions vm_map_t task_map = get_task_map_reference(task);
1511*42e22086SApple OSS Distributions if (task_map) {
1512*42e22086SApple OSS Distributions pmap_t pmap = vm_map_get_pmap(task_map);
1513*42e22086SApple OSS Distributions if (pmap && pmap_query_entitlements(pmap, query, 2, NULL)) {
1514*42e22086SApple OSS Distributions vm_map_deallocate(task_map);
1515*42e22086SApple OSS Distributions return true;
1516*42e22086SApple OSS Distributions }
1517*42e22086SApple OSS Distributions vm_map_deallocate(task_map);
1518*42e22086SApple OSS Distributions }
1519*42e22086SApple OSS Distributions return false;
1520*42e22086SApple OSS Distributions }
1521*42e22086SApple OSS Distributions
1522*42e22086SApple OSS Distributions #endif
1523*42e22086SApple OSS Distributions
1524*42e22086SApple OSS Distributions /* AMFI interface needs to be available */
1525*42e22086SApple OSS Distributions if (amfi == NULL) {
1526*42e22086SApple OSS Distributions panic("CoreEntitlements: (IOTask): AMFI interface not available");
1527*42e22086SApple OSS Distributions }
1528*42e22086SApple OSS Distributions
1529*42e22086SApple OSS Distributions if (task == NULL) {
1530*42e22086SApple OSS Distributions /* NULL task implies current_task */
1531*42e22086SApple OSS Distributions task = current_task();
1532*42e22086SApple OSS Distributions }
1533*42e22086SApple OSS Distributions
1534*42e22086SApple OSS Distributions proc_t p = (proc_t)get_bsdtask_info(task);
1535*42e22086SApple OSS Distributions if (p == NULL) {
1536*42e22086SApple OSS Distributions /* Cannot proceed if we don't have a proc structure */
1537*42e22086SApple OSS Distributions return false;
1538*42e22086SApple OSS Distributions }
1539*42e22086SApple OSS Distributions
1540*42e22086SApple OSS Distributions struct cs_blob* csblob = csproc_get_blob(p);
1541*42e22086SApple OSS Distributions if (csblob == NULL) {
1542*42e22086SApple OSS Distributions /* Cannot proceed if process doesn't have a code signature */
1543*42e22086SApple OSS Distributions return false;
1544*42e22086SApple OSS Distributions }
1545*42e22086SApple OSS Distributions
1546*42e22086SApple OSS Distributions void* osents = csblob_os_entitlements_get(csblob);
1547*42e22086SApple OSS Distributions if (osents == NULL) {
1548*42e22086SApple OSS Distributions return false;
1549*42e22086SApple OSS Distributions }
1550*42e22086SApple OSS Distributions
1551*42e22086SApple OSS Distributions CEError_t ce_err = amfi->CoreEntitlements.kQueryCannotBeSatisfied;
1552*42e22086SApple OSS Distributions ce_err = amfi->OSEntitlements_query(osents, (uint8_t*)csblob_get_cdhash(csblob), query, 2);
1553*42e22086SApple OSS Distributions
1554*42e22086SApple OSS Distributions return ce_err == amfi->CoreEntitlements.kNoError;
1555*42e22086SApple OSS Distributions }
1556*42e22086SApple OSS Distributions
1557*42e22086SApple OSS Distributions extern "C"
1558*42e22086SApple OSS Distributions OS_ALWAYS_INLINE
1559*42e22086SApple OSS Distributions boolean_t
IOCurrentTaskHasEntitlement(const char * entitlement)1560*42e22086SApple OSS Distributions IOCurrentTaskHasEntitlement(const char * entitlement)
1561*42e22086SApple OSS Distributions {
1562*42e22086SApple OSS Distributions return IOTaskHasEntitlement(NULL, entitlement);
1563*42e22086SApple OSS Distributions }
1564*42e22086SApple OSS Distributions
1565*42e22086SApple OSS Distributions extern "C" boolean_t
IOTaskHasEntitlement(task_t task,const char * entitlement)1566*42e22086SApple OSS Distributions IOTaskHasEntitlement(task_t task, const char * entitlement)
1567*42e22086SApple OSS Distributions {
1568*42e22086SApple OSS Distributions // Don't do this
1569*42e22086SApple OSS Distributions if (task == kernel_task || entitlement == NULL) {
1570*42e22086SApple OSS Distributions return false;
1571*42e22086SApple OSS Distributions }
1572*42e22086SApple OSS Distributions size_t entlen = strlen(entitlement);
1573*42e22086SApple OSS Distributions CEQuery_t query = {
1574*42e22086SApple OSS Distributions CESelectDictValueDynamic((const uint8_t*)entitlement, entlen),
1575*42e22086SApple OSS Distributions CEMatchBool(true)
1576*42e22086SApple OSS Distributions };
1577*42e22086SApple OSS Distributions
1578*42e22086SApple OSS Distributions #if PMAP_CS_ENABLE && !CONFIG_X86_64_COMPAT
1579*42e22086SApple OSS Distributions if (pmap_cs_enabled()) {
1580*42e22086SApple OSS Distributions if (task == NULL || task == current_task()) {
1581*42e22086SApple OSS Distributions // NULL task means current task, which translated to the current pmap
1582*42e22086SApple OSS Distributions return pmap_query_entitlements(NULL, query, 2, NULL);
1583*42e22086SApple OSS Distributions }
1584*42e22086SApple OSS Distributions vm_map_t task_map = get_task_map_reference(task);
1585*42e22086SApple OSS Distributions if (task_map) {
1586*42e22086SApple OSS Distributions pmap_t pmap = vm_map_get_pmap(task_map);
1587*42e22086SApple OSS Distributions if (pmap && pmap_query_entitlements(pmap, query, 2, NULL)) {
1588*42e22086SApple OSS Distributions vm_map_deallocate(task_map);
1589*42e22086SApple OSS Distributions return true;
1590*42e22086SApple OSS Distributions }
1591*42e22086SApple OSS Distributions vm_map_deallocate(task_map);
1592*42e22086SApple OSS Distributions }
1593*42e22086SApple OSS Distributions return false;
1594*42e22086SApple OSS Distributions }
1595*42e22086SApple OSS Distributions #endif
1596*42e22086SApple OSS Distributions if (task == NULL) {
1597*42e22086SApple OSS Distributions task = current_task();
1598*42e22086SApple OSS Distributions }
1599*42e22086SApple OSS Distributions
1600*42e22086SApple OSS Distributions proc_t p = (proc_t)get_bsdtask_info(task);
1601*42e22086SApple OSS Distributions
1602*42e22086SApple OSS Distributions if (p == NULL) {
1603*42e22086SApple OSS Distributions return false;
1604*42e22086SApple OSS Distributions }
1605*42e22086SApple OSS Distributions
1606*42e22086SApple OSS Distributions struct cs_blob* csblob = csproc_get_blob(p);
1607*42e22086SApple OSS Distributions if (csblob == NULL) {
1608*42e22086SApple OSS Distributions return false;
1609*42e22086SApple OSS Distributions }
1610*42e22086SApple OSS Distributions
1611*42e22086SApple OSS Distributions void* osents = csblob_os_entitlements_get(csblob);
1612*42e22086SApple OSS Distributions if (osents == NULL) {
1613*42e22086SApple OSS Distributions return false;
1614*42e22086SApple OSS Distributions }
1615*42e22086SApple OSS Distributions
1616*42e22086SApple OSS Distributions if (!amfi) {
1617*42e22086SApple OSS Distributions panic("CoreEntitlements: (IOTask): No AMFI\n");
1618*42e22086SApple OSS Distributions }
1619*42e22086SApple OSS Distributions
1620*42e22086SApple OSS Distributions return amfi->OSEntitlements_query(osents, (uint8_t*)csblob_get_cdhash(csblob), query, 2) == amfi->CoreEntitlements.kNoError;
1621*42e22086SApple OSS Distributions }
1622*42e22086SApple OSS Distributions
1623*42e22086SApple OSS Distributions extern "C" boolean_t
IOVnodeHasEntitlement(vnode_t vnode,int64_t off,const char * entitlement)1624*42e22086SApple OSS Distributions IOVnodeHasEntitlement(vnode_t vnode, int64_t off, const char *entitlement)
1625*42e22086SApple OSS Distributions {
1626*42e22086SApple OSS Distributions OSObject * obj;
1627*42e22086SApple OSS Distributions off_t offset = (off_t)off;
1628*42e22086SApple OSS Distributions
1629*42e22086SApple OSS Distributions obj = IOUserClient::copyClientEntitlementVnode(vnode, offset, entitlement);
1630*42e22086SApple OSS Distributions if (!obj) {
1631*42e22086SApple OSS Distributions return false;
1632*42e22086SApple OSS Distributions }
1633*42e22086SApple OSS Distributions obj->release();
1634*42e22086SApple OSS Distributions return obj != kOSBooleanFalse;
1635*42e22086SApple OSS Distributions }
1636*42e22086SApple OSS Distributions
1637*42e22086SApple OSS Distributions extern "C" char *
IOVnodeGetEntitlement(vnode_t vnode,int64_t off,const char * entitlement)1638*42e22086SApple OSS Distributions IOVnodeGetEntitlement(vnode_t vnode, int64_t off, const char *entitlement)
1639*42e22086SApple OSS Distributions {
1640*42e22086SApple OSS Distributions OSObject *obj = NULL;
1641*42e22086SApple OSS Distributions OSString *str = NULL;
1642*42e22086SApple OSS Distributions size_t len;
1643*42e22086SApple OSS Distributions char *value = NULL;
1644*42e22086SApple OSS Distributions off_t offset = (off_t)off;
1645*42e22086SApple OSS Distributions
1646*42e22086SApple OSS Distributions obj = IOUserClient::copyClientEntitlementVnode(vnode, offset, entitlement);
1647*42e22086SApple OSS Distributions if (obj != NULL) {
1648*42e22086SApple OSS Distributions str = OSDynamicCast(OSString, obj);
1649*42e22086SApple OSS Distributions if (str != NULL) {
1650*42e22086SApple OSS Distributions len = str->getLength() + 1;
1651*42e22086SApple OSS Distributions value = (char *)kalloc_data(len, Z_WAITOK);
1652*42e22086SApple OSS Distributions strlcpy(value, str->getCStringNoCopy(), len);
1653*42e22086SApple OSS Distributions }
1654*42e22086SApple OSS Distributions obj->release();
1655*42e22086SApple OSS Distributions }
1656*42e22086SApple OSS Distributions return value;
1657*42e22086SApple OSS Distributions }
1658*42e22086SApple OSS Distributions
1659*42e22086SApple OSS Distributions extern "C"
1660*42e22086SApple OSS Distributions OS_ALWAYS_INLINE
1661*42e22086SApple OSS Distributions char *
IOCurrentTaskGetEntitlement(const char * entitlement)1662*42e22086SApple OSS Distributions IOCurrentTaskGetEntitlement(const char * entitlement)
1663*42e22086SApple OSS Distributions {
1664*42e22086SApple OSS Distributions return IOTaskGetEntitlement(current_task(), entitlement);
1665*42e22086SApple OSS Distributions }
1666*42e22086SApple OSS Distributions
1667*42e22086SApple OSS Distributions extern "C" char *
IOTaskGetEntitlement(task_t task,const char * entitlement)1668*42e22086SApple OSS Distributions IOTaskGetEntitlement(task_t task, const char * entitlement)
1669*42e22086SApple OSS Distributions {
1670*42e22086SApple OSS Distributions OSObject * obj = NULL;
1671*42e22086SApple OSS Distributions OSDictionary * entitlements = NULL;
1672*42e22086SApple OSS Distributions OSString * str = NULL;
1673*42e22086SApple OSS Distributions size_t len = 0;
1674*42e22086SApple OSS Distributions char * value = NULL;
1675*42e22086SApple OSS Distributions
1676*42e22086SApple OSS Distributions if (task == kernel_task || task == NULL || entitlement == NULL) {
1677*42e22086SApple OSS Distributions goto finish;
1678*42e22086SApple OSS Distributions }
1679*42e22086SApple OSS Distributions
1680*42e22086SApple OSS Distributions entitlements = IOUserClient::copyClientEntitlements(task);
1681*42e22086SApple OSS Distributions if (entitlements == NULL) {
1682*42e22086SApple OSS Distributions goto finish;
1683*42e22086SApple OSS Distributions }
1684*42e22086SApple OSS Distributions
1685*42e22086SApple OSS Distributions obj = entitlements->getObject(entitlement);
1686*42e22086SApple OSS Distributions str = OSDynamicCast(OSString, obj);
1687*42e22086SApple OSS Distributions if (str != NULL) {
1688*42e22086SApple OSS Distributions len = str->getLength() + 1;
1689*42e22086SApple OSS Distributions value = (char *)kalloc_data(len, (zalloc_flags_t)(Z_ZERO | Z_WAITOK | Z_NOFAIL));
1690*42e22086SApple OSS Distributions strlcpy(value, str->getCStringNoCopy(), len);
1691*42e22086SApple OSS Distributions }
1692*42e22086SApple OSS Distributions
1693*42e22086SApple OSS Distributions finish:
1694*42e22086SApple OSS Distributions OSSafeReleaseNULL(entitlements);
1695*42e22086SApple OSS Distributions
1696*42e22086SApple OSS Distributions return value;
1697*42e22086SApple OSS Distributions }
1698