1 /* 2 * Copyright (c) 1998-2019 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * Copyright (c) 1998 Apple Inc. All rights reserved. 30 * 31 * HISTORY 32 * 33 */ 34 35 36 #ifndef _IOKIT_IOCATALOGUE_H 37 #define _IOKIT_IOCATALOGUE_H 38 39 #include <libkern/c++/OSPtr.h> 40 #include <libkern/c++/OSObject.h> 41 #include <libkern/c++/OSCollectionIterator.h> 42 #include <libkern/c++/OSArray.h> 43 #include <libkern/c++/OSDictionary.h> 44 #include <IOKit/IOLocks.h> 45 #include <sys/cdefs.h> 46 47 #include <IOKit/IOKitServer.h> 48 49 class IOService; 50 51 extern OSPtr<const OSSymbol> gIOModuleIdentifierKey; 52 extern OSPtr<const OSSymbol> gIOModuleIdentifierKernelKey; 53 54 55 /*! 56 * @class IOCatalogue 57 * @abstract In-kernel database for IOKit driver personalities. 58 * @discussion The IOCatalogue is a database which contains all IOKit driver personalities. IOService uses this resource when matching devices to their associated drivers. 59 */ 60 class IOCatalogue : public OSObject 61 { 62 OSDeclareDefaultStructors(IOCatalogue); 63 64 private: 65 IORWLock * lock; 66 SInt32 generation; 67 OSPtr<OSDictionary> personalities; 68 OSArray * arrayForPersonality(OSDictionary * dict); 69 void addPersonality(OSDictionary * dict); 70 71 public: 72 /*! 73 * @function initialize 74 * @abstract Creates and initializes the database object and poputates it with in-kernel driver personalities. 75 */ 76 static void initialize( void ); 77 78 /*! 79 * @function init 80 * @abstract Initializes the database object. 81 * @param initArray The initial array of driver personalities to populate the database. 82 */ 83 bool init( OSArray * initArray ); 84 85 /*! 86 * @function free 87 * @abstract Cleans up the database and deallocates memory allocated at initialization. This is never called in normal operation of the system. 88 */ 89 void free( void ) APPLE_KEXT_OVERRIDE; 90 91 /*! 92 * @function findDrivers 93 * @abstract This is the primary entry point for IOService. 94 * @param service The service 95 * @param generationCount Returns a reference to the generation count of the database. The generation count increases only when personalities are added to the database *and* IOService matching has been initiated. 96 * @result Returns an ordered set of driver personalities ranked on probe-scores. The ordered set must be released by the receiver. 97 */ 98 OSPtr<OSOrderedSet> findDrivers( IOService * service, SInt32 * generationCount ); 99 100 /*! 101 * @function findDrivers 102 * @abstract A more general purpose interface which allows one to retreive driver personalities based the intersection of the 'matching' dictionary and the personality's own property list. 103 * @param matching A dictionary containing only keys and values which are to be used for matching. For example, a matching dictionary containing 'IOProviderClass'='IOPCIDevice' will return all personalities with an IOProviderClass key and a value of IOPCIDevice. 104 * @param generationCount Returns a reference to the current generation of the database. The generation count increases only when personalities are added to the database *and* IOService matching has been initiated. 105 * @result Returns an ordered set of driver personalities ranked on probe-scores. The ordered set must be released by the receiver. 106 */ 107 OSPtr<OSOrderedSet> findDrivers( OSDictionary * matching, SInt32 * generationCount ); 108 109 /*! 110 * @function addDrivers 111 * @abstract Adds an array of driver personalities to the database. 112 * @param array Array of driver personalities to be added to the database. 113 * @param doNubMatching Start matching process after personalities have been added. 114 * @result Returns true if driver personality was added to the database successfully. Failure is due to a memory allocation failure. 115 */ 116 bool addDrivers( OSArray * array, bool doNubMatching = true ); 117 118 /*! 119 * @function removeDrivers 120 * @abstract Remove driver personalities from the database based on matching information provided. 121 * @param matching A dictionary whose keys and values are used for matching personalities in the database. For example, a matching dictionary containing a 'IOProviderClass' key with the value 'IOPCIDevice' will remove all personalities which have the key 'IOProviderClass' equal to 'IOPCIDevice'. 122 * @param doNubMatching Start matching process after personalities have been removed. Matching criteria is based on IOProviderClass of those personalities which were removed. This is to allow drivers which haven't been matched to match against NUB's which were blocked by the previous personalities. 123 * @result Returns true if personality was removed successfully. Failure is due to a memory allocation failure. 124 */ 125 bool removeDrivers( OSDictionary * matching, bool doNubMatching = true ); 126 127 #if XNU_KERNEL_PRIVATE 128 bool removeDrivers(bool doNubMatching, bool (^shouldRemove)(OSDictionary *personality)); 129 #endif /* XNU_KERNEL_PRIVATE */ 130 131 /*! 132 * @function exchangeDrivers 133 * @abstract Remove driver personalities from the database based on matching information provided and adds an array of driver personalities to the database atomically. 134 * @param matchingForRemove A dictionary whose keys and values are used for matching personalities in the database. For example, a matching dictionary containing a 'IOProviderClass' key with the value 'IOPCIDevice' will remove all personalities which have the key 'IOProviderClass' equal to 'IOPCIDevice'. 135 * @param personalitiesToAdd Array of driver personalities to be added to the database. 136 * @param doNubMatching Start matching process after personalities have been exchanged. Matching criteria is based on IOProviderClass of those personalities which were removed and added. This is to allow drivers which haven't been matched to match against NUB's which were blocked by the previous personalities. 137 * @result Returns true if personalities were exchanged successfully. Failure is due to a memory allocation failure. 138 */ 139 bool exchangeDrivers(OSDictionary * matchingForRemove, OSArray * personalitiesToAdd, bool doNubMatching = true); 140 141 142 /*! 143 * @function getGenerationCount 144 * @abstract Get the current generation count of the database. 145 */ 146 SInt32 getGenerationCount( void ) const; 147 148 /*! 149 * @function isModuleLoaded 150 * @abstract Reports if a kernel module has been loaded for a particular personality. 151 * @param driver A driver personality's property list. 152 * @param kextRef A reference to the kext getting loaded. 153 * @result Returns true if the associated kernel module has been loaded into the kernel for a particular driver personality on which it depends. 154 */ 155 bool isModuleLoaded( OSDictionary * driver, OSObject ** kextRef ) const; 156 157 bool isModuleLoaded( OSDictionary * driver, OSSharedPtr<OSObject>& kextRef ) const; 158 159 /*! 160 * @function moduleHasLoaded 161 * @abstract Callback function called after a IOKit dependent kernel module is loaded. 162 * @param name Name of the kernel module. 163 */ 164 void moduleHasLoaded( const OSSymbol * name ); 165 166 /*! 167 * @function moduleHasLoaded 168 * @abstract Callback function called after a IOKit dependent kernel module is loaded. 169 * @param name Name of the kernel module. 170 */ 171 void moduleHasLoaded( const char * name ); 172 173 /*! 174 * @function personalityIsBoot 175 */ 176 bool personalityIsBoot(OSDictionary * match); 177 178 /*! 179 * @function terminateDrivers 180 * @abstract Terminates all instances of a driver which match the contents of the matching dictionary. Does not unload module. 181 * @param matching A dictionary whose keys and values are used for matching personalities in the database. For example, a matching dictionary containing a 'IOProviderClass' key with the value 'IOPCIDevice' will cause termination for all instances whose personalities have the key 'IOProviderClass' equal to 'IOPCIDevice'. 182 */ 183 IOReturn terminateDrivers( OSDictionary * matching ); 184 185 /*! 186 * @function terminateDriversForModule 187 * @abstract Terminates all instances of a driver which depends on a particular module and unloads the module. 188 * @param moduleName Name of the module which is used to determine which driver instances to terminate and unload. 189 * @param unload Flag to cause the actual unloading of the module. 190 * @param asynchronous Whether to terminate drivers asynchronously. Optional parameter, defaults to false. 191 */ 192 IOReturn terminateDriversForModule( OSString * moduleName, bool unload = true, bool asynchronous = false); 193 194 /*! 195 * @function terminateDriversForModule 196 * @abstract Terminates all instances of a driver which depends on a particular module and unloads the module. 197 * @param moduleName Name of the module which is used to determine which driver instances to terminate and unload. 198 * @param unload Flag to cause the actual unloading of the module. 199 * @param asynchronous Whether to terminate drivers asynchronously. Optional parameter, defaults to false. 200 */ 201 IOReturn terminateDriversForModule( const char * moduleName, bool unload = true, bool asynchronous = false); 202 #if XNU_KERNEL_PRIVATE 203 IOReturn terminateDrivers(OSDictionary * matching, io_name_t className, bool asynchronous); 204 205 IOReturn terminateDriversForUserspaceReboot(); 206 207 IOReturn resetAfterUserspaceReboot(); 208 #endif /* XNU_KERNEL_PRIVATE */ 209 210 /*! 211 * @function startMatching 212 * @abstract Restarts IOService matching. 213 * @param identifier All IOService objects with this bundle indentifier are rematched. 214 */ 215 bool startMatching( const OSSymbol * identifier ); 216 217 // deprecated, for bin compat 218 #if defined(__i386__) || defined(__x86_64__) 219 bool startMatching( OSDictionary * matching ); 220 #endif 221 222 /*! 223 * @function reset 224 * @abstract Return the Catalogue to its initial state. 225 * @discussion 226 * Should only be used by kextd just before it sends all kext personalities down during a rescan. 227 */ 228 void reset(void); 229 230 /*! 231 * @function resetAndAddDrivers 232 * @abstract Replace personalities in IOCatalog with those provided. 233 * @discussion 234 * Resets the catalogue with a new set of drivers, preserving matching originals to keep wired memory usage down. 235 */ 236 bool resetAndAddDrivers(OSArray * drivers, bool doNubMatching = true); 237 238 /*! 239 * @function serialize 240 * @abstract Serializes the catalog for transport to the user. 241 * @param s The serializer object. 242 * @result Returns false if unable to serialize database, most likely due to memory shortage. 243 */ 244 virtual bool serialize(OSSerialize * s) const APPLE_KEXT_OVERRIDE; 245 246 bool serializeData(IOOptionBits kind, OSSerialize * s) const; 247 248 /* This stuff is no longer used at all we keep it around for i386 249 * binary compatibility only. Symbols are no longer exported. 250 */ 251 252 private: 253 254 /*! 255 * @function unloadModule 256 * @abstract Unloads the reqested module if no driver instances are currently depending on it. 257 * @param moduleName An OSString containing the name of the module to unload. 258 */ 259 IOReturn unloadModule( OSString * moduleName ) const; 260 261 IOReturn _removeDrivers(OSDictionary * matching); 262 }; 263 264 extern OSPtr<const OSSymbol> gIOClassKey; 265 extern OSPtr<const OSSymbol> gIOProbeScoreKey; 266 extern OSPtr<IOCatalogue> gIOCatalogue; 267 268 #endif /* ! _IOKIT_IOCATALOGUE_H */ 269