2 * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #ifndef _LIBKERN_OSKEXT_H
30 #define _LIBKERN_OSKEXT_H
33 #include <kern/thread_call.h>
34 #include <libkern/OSKextLibPrivate.h>
35 #include <libkern/kernel_mach_header.h>
36 #include <libkern/kxld.h>
37 #include <mach/kmod.h>
39 #ifdef XNU_KERNEL_PRIVATE
40 #include <kern/thread_call.h>
41 #endif /* XNU_KERNEL_PRIVATE */
44 #include <libkern/OSKextLib.h>
45 #include <libkern/OSKextLibPrivate.h>
46 #include <libkern/c++/OSObject.h>
47 #include <libkern/c++/OSContainers.h>
48 #include <IOKit/IOLocks.h>
50 /*********************************************************************
51 * C functions used for callbacks.
52 *********************************************************************/
53 #ifdef XNU_KERNEL_PRIVATE
55 void osdata_kmem_free(void * ptr
, unsigned int length
);
56 void osdata_phys_free(void * ptr
, unsigned int length
);
57 void osdata_vm_deallocate(void * ptr
, unsigned int length
);
59 #endif /* XNU_KERNEL_PRIVATE */
61 /*********************************************************************
62 * C Function Prototypes for Friend Declarations.
63 *********************************************************************/
70 OSKextLogSpec msgLogSpec
,
71 const char * format
, ...)
72 __attribute__((format(printf
, 3, 4)));
76 OSKextLogSpec msgLogSpec
,
80 #ifdef XNU_KERNEL_PRIVATE
81 void OSKextRemoveKextBootstrap(void);
82 void IOSystemShutdownNotification(void);
84 kern_return_t
OSRuntimeInitializeCPP(
85 kmod_info_t
* kmodInfo
,
87 kern_return_t
OSRuntimeFinalizeCPP(
88 kmod_info_t
* kmodInfo
,
91 kern_return_t
is_io_catalog_send_data(
92 mach_port_t masterPort
,
95 mach_msg_type_number_t inDataCount
,
96 kern_return_t
* result
);
98 void kmod_dump_log(vm_offset_t
*, unsigned int, boolean_t
);
101 #endif /* XNU_KERNEL_PRIVATE */
104 /********************************************************************/
110 struct list_head
*prev
;
111 struct list_head
*next
;
114 struct OSKextGrabPgoStruct
{
120 struct list_head list_head
;
124 #define container_of(ptr,type,member) ((type*)(((uintptr_t)ptr) - offsetof(type, member)))
126 /********************************************************************/
128 #if XNU_KERNEL_PRIVATE
132 vm_allocation_site_t site
;
136 struct OSKextActiveAccount
139 uintptr_t address_end
;
140 OSKextAccount
* account
;
142 typedef struct OSKextActiveAccount OSKextActiveAccount
;
144 #endif /* XNU_KERNEL_PRIVATE */
149 /********************************************************************/
150 class OSKext
: public OSObject
152 OSDeclareDefaultStructors(OSKext
)
155 /**************************************/
156 #pragma mark Friend Declarations
157 /**************************************/
159 friend class IOCatalogue
;
160 friend class KLDBootstrap
;
161 friend class OSMetaClass
;
163 friend int OSKextGrabPgoData(uuid_t uuid
,
170 #ifdef XNU_KERNEL_PRIVATE
171 friend void OSKextVLog(
173 OSKextLogSpec msgLogSpec
,
177 friend void OSKextRemoveKextBootstrap(void);
178 friend void IOSystemShutdownNotification(void);
179 friend OSReturn
OSKextUnloadKextWithLoadTag(uint32_t);
181 friend kern_return_t
kext_request(
182 host_priv_t hostPriv
,
183 /* in only */ uint32_t clientLogSpec
,
184 /* in only */ vm_offset_t requestIn
,
185 /* in only */ mach_msg_type_number_t requestLengthIn
,
186 /* out only */ vm_offset_t
* responseOut
,
187 /* out only */ mach_msg_type_number_t
* responseLengthOut
,
188 /* out only */ vm_offset_t
* logDataOut
,
189 /* out only */ mach_msg_type_number_t
* logDataLengthOut
,
190 /* out only */ kern_return_t
* op_result
);
192 friend kxld_addr_t
kern_allocate(
194 KXLDAllocateFlags
* flags
,
197 friend void kxld_log_shim(
198 KXLDLogSubsystem subsystem
,
204 friend void _OSKextConsiderUnloads(
205 __unused thread_call_param_t p0
,
206 __unused thread_call_param_t p1
);
208 friend kern_return_t
OSRuntimeInitializeCPP(
209 kmod_info_t
* kmodInfo
,
211 friend kern_return_t
OSRuntimeFinalizeCPP(
212 kmod_info_t
* kmodInfo
,
215 friend kern_return_t
is_io_catalog_send_data(
216 mach_port_t masterPort
,
219 mach_msg_type_number_t inDataCount
,
220 kern_return_t
* result
);
222 friend void kmod_panic_dump(vm_offset_t
*, unsigned int);
223 friend void kmod_dump_log(vm_offset_t
*, unsigned int, boolean_t
);
224 friend void kext_dump_panic_lists(int (*printf_func
)(const char * fmt
, ...));
227 #endif /* XNU_KERNEL_PRIVATE */
231 /*************************
233 *************************/
234 OSDictionary
* infoDict
;
236 const OSSymbol
* bundleID
;
237 OSString
* path
; // not necessarily correct :-/
238 OSString
* executableRelPath
; // relative to bundle
240 OSKextVersion version
; // parsed
241 OSKextVersion compatibleVersion
; // parsed
243 /* These fields are required for tracking loaded kexts and
244 * will always have values for a loaded kext.
246 OSKextLoadTag loadTag
; // 'id' from old kmod_info;
247 // kOSKextInvalidLoadTag invalid
248 kmod_info_t
* kmod_info
; // address into linkedExec./alloced for interface
250 OSArray
* dependencies
; // kernel resource does not have any;
251 // links directly to kernel
253 /* Only real kexts have these; interface kexts do not.
255 OSData
* linkedExecutable
;
256 OSSet
* metaClasses
; // for C++/OSMetaClass kexts
258 /* Only interface kexts have these; non-interface kexts can get at them
259 * in the linked Executable.
261 OSData
* interfaceUUID
;
264 unsigned int loggingEnabled
:1;
266 unsigned int hasAllDependencies
:1;
267 unsigned int hasBleedthrough
:1;
269 unsigned int interface
:1;
270 unsigned int kernelComponent
:1;
271 unsigned int prelinked
:1;
272 unsigned int loaded
:1;
273 unsigned int dtraceInitialized
:1;
274 unsigned int starting
:1;
275 unsigned int started
:1;
276 unsigned int stopping
:1;
277 unsigned int unloading
:1;
279 unsigned int autounloadEnabled
:1;
280 unsigned int delayAutounload
:1; // for development
282 unsigned int CPPInitialized
:1;
283 unsigned int jettisonLinkeditSeg
:1;
286 struct list_head pendingPgoHead
;
287 uuid_t instance_uuid
;
288 OSKextAccount
* account
;
291 /**************************************/
292 #pragma mark Private Functions
293 /**************************************/
296 #ifdef XNU_KERNEL_PRIVATE
297 /* Startup/shutdown phases.
300 static void initialize(void);
301 static OSDictionary
* copyKexts(void);
302 static OSReturn
removeKextBootstrap(void);
303 static void willShutdown(void); // called by IOPMrootDomain on shutdown
304 #endif /* XNU_KERNEL_PRIVATE */
307 /* Called by power management at sleep/shutdown.
309 static bool setLoadEnabled(bool flag
);
310 static bool setUnloadEnabled(bool flag
);
311 static bool setAutounloadsEnabled(bool flag
);
312 static bool setKernelRequestsEnabled(bool flag
);
314 // all getters subject to race condition, caller beware
315 static bool getLoadEnabled(void);
316 static bool getUnloadEnabled(void);
317 static bool getAutounloadEnabled(void);
318 static bool getKernelRequestsEnabled(void);
320 /* Instance life cycle.
322 static OSKext
* withBooterData(
323 OSString
* deviceTreeName
,
324 OSData
* booterData
);
325 virtual bool initWithBooterData(
326 OSString
* deviceTreeName
,
327 OSData
* booterData
);
329 static OSKext
* withPrelinkedInfoDict(
330 OSDictionary
* infoDict
);
331 virtual bool initWithPrelinkedInfoDict(
332 OSDictionary
* infoDict
);
334 static OSKext
* withMkext2Info(
335 OSDictionary
* anInfoDict
,
337 virtual bool initWithMkext2Info(
338 OSDictionary
* anInfoDict
,
341 virtual bool setInfoDictionaryAndPath(
342 OSDictionary
* aDictionary
,
344 virtual bool setExecutable(
345 OSData
* anExecutable
,
346 OSData
* externalData
= NULL
,
347 bool externalDataIsMkext
= false);
348 virtual bool registerIdentifier(void);
350 virtual void free(void) APPLE_KEXT_OVERRIDE
;
352 static OSReturn
removeKext(
354 bool terminateServicesAndRemovePersonalitiesFlag
= false);
356 virtual bool isInExcludeList(void);
360 static OSReturn
readMkextArchive(
362 uint32_t * checksumPtr
= NULL
);
363 static OSReturn
readMkext2Archive(
365 OSDictionary
** mkextPlistOut
,
366 uint32_t * checksumPtr
= NULL
);
367 virtual OSData
* createMkext2FileEntry(
369 OSNumber
* offsetNum
,
370 const char * entryName
);
371 virtual OSData
* extractMkext2FileData(
374 uint32_t compressedSize
,
379 virtual bool resolveDependencies(
380 OSArray
* loopStack
= NULL
); // priv/prot
381 virtual bool addBleedthroughDependencies(OSArray
* anArray
);
382 virtual bool flushDependencies(bool forceFlag
= false); // priv/prot
383 virtual uint32_t getNumDependencies(void);
384 virtual OSArray
* getDependencies(void);
386 /* User-space requests (load/generic).
388 static OSReturn
loadFromMkext(
389 OSKextLogSpec clientLogSpec
,
391 uint32_t mkextBufferLength
,
393 uint32_t * logInfoLengthOut
);
394 static OSReturn
handleRequest(
395 host_priv_t hostPriv
,
396 OSKextLogSpec clientLogSpec
,
397 char * requestBuffer
,
398 uint32_t requestLength
,
400 uint32_t * responseLengthOut
,
402 uint32_t * logInfoLengthOut
);
403 static OSReturn
serializeLogInfo(
404 OSArray
* logInfoArray
,
406 uint32_t * logInfoLengthOut
);
410 virtual OSReturn
load(
411 OSKextExcludeLevel startOpt
= kOSKextExcludeNone
,
412 OSKextExcludeLevel startMatchingOpt
= kOSKextExcludeAll
,
413 OSArray
* personalityNames
= NULL
); // priv/prot
414 virtual OSReturn
unload(void);
415 virtual OSReturn
queueKextNotification(
416 const char * notificationName
,
417 OSString
* kextIdentifier
);
419 static void recordIdentifierRequest(
420 OSString
* kextIdentifier
);
422 virtual OSReturn
slidePrelinkedExecutable(void);
423 virtual OSReturn
loadExecutable(void);
424 virtual void jettisonLinkeditSegment(void);
425 virtual void jettisonDATASegmentPadding(void);
426 static void considerDestroyingLinkContext(void);
427 virtual OSData
* getExecutable(void);
428 virtual void setLinkedExecutable(OSData
* anExecutable
);
431 friend void OSKextRegisterKextsWithDTrace(void);
432 static void registerKextsWithDTrace(void);
433 virtual void registerWithDTrace(void);
434 virtual void unregisterWithDTrace(void);
435 #endif /* CONFIG_DTRACE */
437 virtual OSReturn
start(bool startDependenciesFlag
= true);
438 virtual OSReturn
stop(void);
439 virtual OSReturn
setVMAttributes(bool protect
, bool wire
);
440 virtual boolean_t
segmentShouldBeWired(kernel_segment_command_t
*seg
);
441 virtual OSReturn
validateKextMapping(bool startFlag
);
442 virtual boolean_t
verifySegmentMapping(kernel_segment_command_t
*seg
);
444 static OSArray
* copyAllKextPersonalities(
445 bool filterSafeBootFlag
= false);
447 static void setPrelinkedPersonalities(OSArray
* personalitiesArray
);
449 static void sendAllKextPersonalitiesToCatalog(
450 bool startMatching
= false);
451 virtual OSReturn
sendPersonalitiesToCatalog(
452 bool startMatching
= false,
453 OSArray
* personalityNames
= NULL
);
455 static bool canUnloadKextWithIdentifier(
456 OSString
* kextIdentifier
,
457 bool checkClassesFlag
= true);
459 static OSReturn
autounloadKext(OSKext
* aKext
);
461 /* Sync with user space.
463 static OSReturn
pingKextd(void);
465 /* Getting info about loaded kexts (kextstat).
467 static OSDictionary
* copyLoadedKextInfo(
468 OSArray
* kextIdentifiers
= NULL
,
469 OSArray
* keys
= NULL
);
470 virtual OSDictionary
* copyInfo(OSArray
* keys
= NULL
);
472 /* Logging to user space.
474 static OSKextLogSpec
setUserSpaceLogFilter(
475 OSKextLogSpec userLogSpec
,
476 bool captureFlag
= false);
477 static OSArray
* clearUserSpaceLogFilter(void);
478 static OSKextLogSpec
getUserSpaceLogFilter(void);
480 /* OSMetaClasses defined by kext.
482 virtual OSReturn
addClass(
483 OSMetaClass
* aClass
,
484 uint32_t numClasses
);
485 virtual OSReturn
removeClass(
486 OSMetaClass
* aClass
);
487 virtual bool hasOSMetaClassInstances(void);
488 virtual OSSet
* getMetaClasses(void);
489 static void reportOSMetaClassInstances(
490 const char * kextIdentifier
,
491 OSKextLogSpec msgLogSpec
);
492 virtual void reportOSMetaClassInstances(
493 OSKextLogSpec msgLogSpec
);
495 /* Resource requests and other callback stuff.
497 static OSReturn
dispatchResource(OSDictionary
* requestDict
);
499 static OSReturn
dequeueCallbackForRequestTag(
500 OSKextRequestTag requestTag
,
501 OSDictionary
** callbackRecordOut
);
502 static OSReturn
dequeueCallbackForRequestTag(
503 OSNumber
* requestTagNum
,
504 OSDictionary
** callbackRecordOut
);
505 static void invokeRequestCallback(
506 OSDictionary
* callbackRecord
,
507 OSReturn requestResult
);
508 virtual void invokeOrCancelRequestCallbacks(
509 OSReturn callbackResult
,
510 bool invokeFlag
= true);
511 virtual uint32_t countRequestCallbacks(void);
515 static void printKextsInBacktrace(
518 int (* printf_func
)(const char *fmt
, ...),
521 static boolean_t
summaryIsInBacktrace(
522 OSKextLoadedKextSummary
* summary
,
525 static void printSummary(
526 OSKextLoadedKextSummary
* summary
,
527 int (* printf_func
)(const char *fmt
, ...),
530 static int saveLoadedKextPanicListTyped(
536 static void saveLoadedKextPanicList(void);
537 void savePanicString(bool isLoading
);
538 static void printKextPanicLists(int (*printf_func
)(const char *fmt
, ...));
540 /* Kext summary support.
542 static void updateLoadedKextSummaries(void);
543 void updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
);
544 void updateActiveAccount(OSKextActiveAccount
*account
);
546 /* C++ Initialization.
548 virtual void setCPPInitialized(bool initialized
=true);
553 /**************************************/
554 #pragma mark Public Functions
555 /**************************************/
558 // caller must release
559 static OSKext
* lookupKextWithIdentifier(const char * kextIdentifier
);
560 static OSKext
* lookupKextWithIdentifier(OSString
* kextIdentifier
);
561 static OSKext
* lookupKextWithLoadTag(OSKextLoadTag aTag
);
562 static OSKext
* lookupKextWithAddress(vm_address_t address
);
563 static OSKext
* lookupKextWithUUID(uuid_t uuid
);
565 kernel_section_t
*lookupSection(const char *segname
, const char*secname
);
567 static bool isKextWithIdentifierLoaded(const char * kextIdentifier
);
569 static OSReturn
loadKextWithIdentifier(
570 const char * kextIdentifier
,
571 Boolean allowDeferFlag
= true,
572 Boolean delayAutounloadFlag
= false,
573 OSKextExcludeLevel startOpt
= kOSKextExcludeNone
,
574 OSKextExcludeLevel startMatchingOpt
= kOSKextExcludeAll
,
575 OSArray
* personalityNames
= NULL
);
576 static OSReturn
loadKextWithIdentifier(
577 OSString
* kextIdentifier
,
578 Boolean allowDeferFlag
= true,
579 Boolean delayAutounloadFlag
= false,
580 OSKextExcludeLevel startOpt
= kOSKextExcludeNone
,
581 OSKextExcludeLevel startMatchingOpt
= kOSKextExcludeAll
,
582 OSArray
* personalityNames
= NULL
);
583 static OSReturn
removeKextWithIdentifier(
584 const char * kextIdentifier
,
585 bool terminateServicesAndRemovePersonalitiesFlag
= false);
586 static OSReturn
removeKextWithLoadTag(
587 OSKextLoadTag loadTag
,
588 bool terminateServicesAndRemovePersonalitiesFlag
= false);
590 static OSReturn
requestResource(
591 const char * kextIdentifier
,
592 const char * resourceName
,
593 OSKextRequestResourceCallback callback
,
595 OSKextRequestTag
* requestTagOut
);
596 static OSReturn
cancelRequest(
597 OSKextRequestTag requestTag
,
600 static void considerUnloads(Boolean rescheduleOnlyFlag
= false);
601 static void flushNonloadedKexts(Boolean flushPrelinkedKexts
);
602 static void setKextdActive(Boolean active
= true);
603 static void setDeferredLoadSucceeded(Boolean succeeded
= true);
604 static void considerRebuildOfPrelinkedKernel(void);
605 static void createExcludeListFromBooterData(
606 OSDictionary
* theDictionary
,
607 OSCollectionIterator
* theIterator
);
608 static void createExcludeListFromPrelinkInfo(OSArray
* theInfoArray
);
610 virtual bool setAutounloadEnabled(bool flag
);
612 virtual const OSSymbol
* getIdentifier(void);
613 virtual const char * getIdentifierCString(void);
614 virtual OSKextVersion
getVersion(void);
615 virtual OSKextVersion
getCompatibleVersion(void);
616 virtual bool isLibrary(void);
617 virtual bool isCompatibleWithVersion(OSKextVersion aVersion
);
618 virtual OSObject
* getPropertyForHostArch(const char * key
);
620 virtual OSKextLoadTag
getLoadTag(void);
621 virtual void getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
);
622 virtual OSData
* copyUUID(void);
623 virtual OSArray
* copyPersonalitiesArray(void);
625 /* This removes personalities naming the kext (by CFBundleIdentifier),
626 * not all personalities defined by the kext (IOPersonalityPublisher or CFBundleIdentifier).
628 virtual void removePersonalitiesFromCatalog(void);
630 /* Converts common string-valued properties to OSSymbols for lower memory consumption.
632 static void uniquePersonalityProperties(OSDictionary
* personalityDict
);
634 virtual bool declaresExecutable(void); // might be missing
635 virtual bool isInterface(void);
636 virtual bool isKernel(void);
637 virtual bool isKernelComponent(void);
638 virtual bool isExecutable(void);
639 virtual bool isLoadableInSafeBoot(void);
640 virtual bool isPrelinked(void);
641 virtual bool isLoaded(void);
642 virtual bool isStarted(void);
643 virtual bool isCPPInitialized(void);
647 #endif /* !_LIBKERN_OSKEXT_H */