The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOCatalogue.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1998-2006 Apple Computer, 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 Computer, Inc.  All rights reserved. 
   30  *
   31  * HISTORY
   32  *
   33  */
   34 /*
   35  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
   36  * support for mandatory and extensible security protections.  This notice
   37  * is included in support of clause 2.2 (b) of the Apple Public License,
   38  * Version 2.0.
   39  */
   40 
   41 #include <IOKit/IODeviceTreeSupport.h>
   42 #include <IOKit/IOService.h>
   43 #include <libkern/c++/OSContainers.h>
   44 #include <IOKit/IOCatalogue.h>
   45 #include <libkern/c++/OSUnserialize.h>
   46 extern "C" {
   47 #include <machine/machine_routines.h>
   48 #include <mach/kmod.h>
   49 #include <mach-o/mach_header.h>
   50 #include <kern/host.h>
   51 #include <security/mac_data.h>
   52 };
   53 
   54 #include <IOKit/IOLib.h>
   55 
   56 #include <IOKit/assert.h>
   57 
   58 
   59 extern "C" {
   60 int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
   61 extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
   62 /* operates on 32 bit segments */
   63 extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment);
   64 };
   65 
   66 
   67 /*****
   68  * At startup these function pointers are set to use the libsa in-kernel
   69  * linker for recording and loading kmods. Once the root filesystem
   70  * is available, the kmod_load_function pointer gets switched to point
   71  * at the kmod_load_extension() function built into the kernel, and the
   72  * others are set to zero. Those two functions must *always* be checked
   73  * before being invoked.
   74  */
   75 extern "C" {
   76 kern_return_t (*kmod_load_function)(char *extension_name) =
   77     &kmod_load_extension;
   78 bool (*record_startup_extensions_function)(void) = 0;
   79 bool (*add_from_mkext_function)(OSData * mkext) = 0;
   80 void (*remove_startup_extension_function)(const char * name) = 0;
   81 };
   82 
   83 
   84 /*****
   85  * A few parts of IOCatalogue require knowledge of
   86  * whether the in-kernel linker is present. This
   87  * variable is set by libsa's bootstrap code.
   88  */
   89 int kernelLinkerPresent = 0;
   90 
   91 #define kModuleKey "CFBundleIdentifier"
   92 
   93 #define super OSObject
   94 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
   95 
   96 #define CATALOGTEST 0
   97 
   98 IOCatalogue    * gIOCatalogue;
   99 const OSSymbol * gIOClassKey;
  100 const OSSymbol * gIOProbeScoreKey;
  101 const OSSymbol * gIOModuleIdentifierKey;
  102 OSSet *          gIOCatalogModuleRequests;
  103 OSSet *          gIOCatalogCacheMisses;
  104 OSSet *          gIOCatalogROMMkexts;
  105 IOLock *         gIOCatalogLock;
  106 IOLock *         gIOKLDLock;
  107 
  108 /*********************************************************************
  109 *********************************************************************/
  110 
  111 OSArray * gIOPrelinkedModules = 0;
  112 
  113 extern "C" kern_return_t
  114 kmod_create_internal(
  115             kmod_info_t *info,
  116             kmod_t *id);
  117 
  118 extern "C" kern_return_t
  119 kmod_destroy_internal(kmod_t id);
  120 
  121 extern "C" kern_return_t
  122 kmod_start_or_stop(
  123     kmod_t id,
  124     int start,
  125     kmod_args_t *data,
  126     mach_msg_type_number_t *dataCount);
  127 
  128 extern "C" kern_return_t kmod_retain(kmod_t id);
  129 extern "C" kern_return_t kmod_release(kmod_t id);
  130 
  131 #if CONFIG_MACF_KEXT
  132 /* MAC Framework support */
  133 
  134 /* 
  135  * define IOC_DEBUG to display run-time debugging information
  136  * #define IOC_DEBUG 1
  137  */
  138 
  139 #ifdef IOC_DEBUG
  140 #define DPRINTF(x)      printf x
  141 #else
  142 #define IOC_DEBUG
  143 #define DPRINTF(x)
  144 #endif
  145 
  146 static bool
  147 primitive_type(OSObject *obj)
  148 {
  149     const OSMetaClass *typeID;
  150 
  151     typeID = OSTypeIDInst(obj);
  152     if (typeID == OSTypeID(OSString) || typeID == OSTypeID(OSNumber) ||
  153         typeID == OSTypeID(OSBoolean) || typeID == OSTypeID(OSData))
  154         return(true);
  155     else
  156         return(false);
  157 }
  158 
  159 static int
  160 primitive_type_length(OSObject *obj)
  161 {
  162     const OSMetaClass *typeID;
  163     int len;
  164 
  165     typeID = OSTypeIDInst(obj);
  166     if (typeID == OSTypeID(OSString)) {
  167         OSString * stringObj = OSDynamicCast(OSString, obj);
  168         len = stringObj->getLength() + 1;
  169     }
  170     else if (typeID == OSTypeID(OSNumber)) {
  171         len = sizeof("4294967295");     /* UINT32_MAX */
  172     }
  173     else if (typeID == OSTypeID(OSBoolean)) {
  174         OSBoolean * boolObj = OSDynamicCast(OSBoolean, obj);
  175         len = boolObj->isTrue() ? sizeof("true") : sizeof("false");
  176     }
  177     else if (typeID == OSTypeID(OSData)) {
  178         OSData * dataObj = OSDynamicCast(OSData, obj);
  179         len = dataObj->getLength();
  180     }
  181     else {
  182         len = 0;
  183     }
  184     return(len);
  185 }
  186 
  187 static void
  188 primitive_type_collect(struct mac_module_data_element *element, OSObject *value)
  189 {
  190     const OSMetaClass *typeID;
  191 
  192     typeID = OSTypeIDInst(value);
  193     if (typeID == OSTypeID(OSString)) {
  194         OSString *stringObj = OSDynamicCast(OSString, value);
  195         element->value_type = MAC_DATA_TYPE_PRIMITIVE;
  196         element->value_size = stringObj->getLength() + 1;
  197         DPRINTF(("osdict: string %s size %d\n", 
  198             stringObj->getCStringNoCopy(), element->value_size));
  199         memcpy(element->value, stringObj->getCStringNoCopy(),
  200             element->value_size);
  201     } else if (typeID == OSTypeID(OSNumber)) {
  202         OSNumber *numberObj = OSDynamicCast(OSNumber, value);
  203         element->value_type = MAC_DATA_TYPE_PRIMITIVE;
  204         element->value_size = sprintf(element->value, "%u",
  205             numberObj->unsigned32BitValue()) + 1;
  206     } else if (typeID == OSTypeID(OSBoolean)) {
  207         OSBoolean *boolObj = OSDynamicCast(OSBoolean, value);
  208         element->value_type = MAC_DATA_TYPE_PRIMITIVE;
  209         if (boolObj->isTrue()) {
  210             strcpy(element->value, "true");
  211             element->value_size = 5;
  212         } else {
  213             strcpy(element->value, "false");
  214             element->value_size = 6;
  215         }
  216     } else if (typeID == OSTypeID(OSData)) {
  217         OSData *dataObj = OSDynamicCast(OSData, value);
  218         element->value_type = MAC_DATA_TYPE_PRIMITIVE;
  219         element->value_size = dataObj->getLength();
  220         DPRINTF(("osdict: data size %d\n", dataObj->getLength()));
  221         memcpy(element->value, dataObj->getBytesNoCopy(),
  222             element->value_size);
  223     }
  224 }
  225 
  226 /*********************************************************************
  227 * This function takes an OSDictionary and returns a struct mac_module_data
  228 * list.
  229 *********************************************************************/
  230 struct mac_module_data *
  231 osdict_encode(OSDictionary *dict)
  232 {
  233     const OSMetaClass * typeID;             // don't release
  234     OSString * key = NULL;                  // don't release
  235     OSCollectionIterator * keyIterator = 0; // must release
  236     struct mac_module_data * module_data = 0;
  237     struct mac_module_data_element * element;
  238     unsigned int strtabsize = 0;
  239     unsigned int listtabsize = 0;
  240     unsigned int dicttabsize = 0;
  241     unsigned int nkeys = 0;
  242     unsigned int datalen;
  243     char *strtab = NULL;
  244     char *listtab = NULL;
  245     char *dicttab = NULL;
  246     vm_offset_t data_addr;
  247 
  248     keyIterator = OSCollectionIterator::withCollection(dict);
  249     if (!keyIterator)
  250         goto finish;
  251 
  252     /* Iterate over OSModuleData to figure out total size */
  253     while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) {
  254 
  255         // Get the key's value and determine its type
  256         OSObject * value = dict->getObject(key);
  257         if (!value)
  258             continue;
  259 
  260         typeID = OSTypeIDInst(value);
  261         if (primitive_type(value)) {
  262             strtabsize += primitive_type_length(value);
  263         }
  264         else if (typeID == OSTypeID(OSArray)) {
  265             unsigned int k, cnt, nents;
  266             OSArray *arrayObj = OSDynamicCast(OSArray, value);
  267 
  268             nents = 0;
  269             cnt = arrayObj->getCount();
  270             for (k = 0; k < cnt; k++) {
  271                 value = arrayObj->getObject(k);
  272                 typeID = OSTypeIDInst(value);
  273                 if (primitive_type(value)) {
  274                     listtabsize += primitive_type_length(value);
  275                     nents++;
  276                 }
  277                 else if (typeID == OSTypeID(OSDictionary)) {
  278                     unsigned int dents;
  279                     OSDictionary *dictObj;
  280                     OSString *dictkey;
  281                     OSCollectionIterator *dictIterator;
  282 
  283                     dents = 0;
  284                     dictObj = OSDynamicCast(OSDictionary, value);
  285                     dictIterator = OSCollectionIterator::withCollection(dictObj);
  286                     if (!dictIterator)
  287                         goto finish;
  288                     while ((dictkey = OSDynamicCast(OSString,
  289                                               dictIterator->getNextObject()))) {
  290                         OSObject *dictvalue;
  291 
  292                         dictvalue = dictObj->getObject(dictkey);
  293                         if (!dictvalue)
  294                             continue;
  295                         if (primitive_type(dictvalue)) {
  296                             strtabsize += primitive_type_length(dictvalue);
  297                         }
  298                         else {
  299                             continue;   /* Only handle primitive types here.  */
  300                         }
  301                         /*
  302                          * Allow for the "arraynnn/" prefix in the key length.
  303                          */
  304                         strtabsize += dictkey->getLength() + 1;
  305                         dents++;
  306                     }
  307                     dictIterator->release();
  308                     if (dents-- > 0) {
  309                         dicttabsize += sizeof(struct mac_module_data_list) +
  310                             dents * sizeof(struct mac_module_data_element);
  311                         nents++;
  312                     }
  313                 }
  314                 else {
  315                     continue;           /* Skip everything else.              */
  316                 }
  317             }
  318             if (nents == 0)
  319                 continue;
  320             listtabsize += sizeof(struct mac_module_data_list) +
  321                 (nents - 1) * sizeof(struct mac_module_data_element);
  322         }
  323         else {
  324             continue;           /* skip anything else */
  325         }
  326         strtabsize += key->getLength() + 1;
  327         nkeys++;
  328     }
  329     if (nkeys == 0)
  330         goto finish;
  331 
  332     /*
  333      * Allocate and fill in the module data structures.
  334      */
  335     datalen = sizeof(struct mac_module_data) +
  336         sizeof(mac_module_data_element) * (nkeys - 1) +
  337         strtabsize + listtabsize + dicttabsize;
  338     DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n", 
  339             datalen, strtabsize, listtabsize, dicttabsize));
  340     if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS)
  341         goto finish;
  342     module_data = (mac_module_data *)data_addr;
  343     module_data->base_addr = data_addr;
  344     module_data->size = datalen;
  345     module_data->count = nkeys;
  346     strtab = (char *)&module_data->data[nkeys];
  347     listtab = strtab + strtabsize;
  348     dicttab = listtab + listtabsize;
  349     DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n", 
  350             data_addr, strtab, listtab, dicttab, data_addr + datalen));
  351 
  352     keyIterator->reset();
  353     nkeys = 0;
  354     element = &module_data->data[0];
  355     DPRINTF(("osdict: element %p\n", element));
  356     while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) {
  357 
  358         // Get the key's value and determine its type
  359         OSObject * value = dict->getObject(key);
  360         if (!value)
  361             continue;
  362 
  363         /* Store key */
  364         DPRINTF(("osdict: element @%p\n", element));
  365         element->key = strtab;
  366         element->key_size = key->getLength() + 1;
  367         DPRINTF(("osdict: key %s size %d @%p\n", key->getCStringNoCopy(), element->key_size, strtab));
  368         memcpy(element->key, key->getCStringNoCopy(), element->key_size);
  369 
  370         typeID = OSTypeIDInst(value);
  371         if (primitive_type(value)) {
  372             /* Store value */
  373             element->value = element->key + element->key_size;
  374             DPRINTF(("osdict: primitive element value %p\n", element->value));
  375             primitive_type_collect(element, value);
  376             strtab += element->key_size + element->value_size;
  377             DPRINTF(("osdict: new strtab %p\n", strtab));
  378         }
  379         else if (typeID == OSTypeID(OSArray)) {
  380             unsigned int k, cnt, nents;
  381             char *astrtab;
  382             struct mac_module_data_list *arrayhd;
  383             struct mac_module_data_element *ele;
  384             OSArray *arrayObj = OSDynamicCast(OSArray, value);
  385 
  386             element->value = listtab;
  387             DPRINTF(("osdict: array element value %p\n", element->value));
  388             element->value_type = MAC_DATA_TYPE_ARRAY;
  389             arrayhd = (struct mac_module_data_list *)element->value;
  390             arrayhd->type = 0;
  391             DPRINTF(("osdict: arrayhd %p\n", arrayhd));
  392             nents = 0;
  393             astrtab = strtab + element->key_size;
  394             ele = &(arrayhd->list[0]);
  395             cnt = arrayObj->getCount();
  396             for (k = 0; k < cnt; k++) {
  397                 value = arrayObj->getObject(k);
  398                 DPRINTF(("osdict: array ele %d @%p\n", nents, ele));
  399                 ele->key = NULL;
  400                 ele->key_size = 0;
  401                 typeID = OSTypeIDInst(value);
  402                 if (primitive_type(value)) {
  403                     if (arrayhd->type != 0 &&
  404                         arrayhd->type != MAC_DATA_TYPE_PRIMITIVE)
  405                         continue;
  406                     arrayhd->type = MAC_DATA_TYPE_PRIMITIVE;
  407                     ele->value = astrtab;
  408                     primitive_type_collect(ele, value);
  409                     astrtab += ele->value_size;
  410                     DPRINTF(("osdict: array new astrtab %p\n", astrtab));
  411                 }
  412                 else if (typeID == OSTypeID(OSDictionary)) {
  413                     unsigned int dents;
  414                     char *dstrtab;
  415                     OSDictionary *dictObj;
  416                     OSString *dictkey;
  417                     OSCollectionIterator *dictIterator;
  418                     struct mac_module_data_list *dicthd;
  419                     struct mac_module_data_element *dele;
  420 
  421                     if (arrayhd->type != 0 &&
  422                         arrayhd->type != MAC_DATA_TYPE_DICT)
  423                         continue;
  424                     dictObj = OSDynamicCast(OSDictionary, value);
  425                     dictIterator = OSCollectionIterator::withCollection(dictObj);
  426                     if (!dictIterator)
  427                         goto finish;
  428                     DPRINTF(("osdict: dict\n"));
  429                     ele->value = dicttab;
  430                     ele->value_type = MAC_DATA_TYPE_DICT;
  431                     dicthd = (struct mac_module_data_list *)ele->value;
  432                     DPRINTF(("osdict: dicthd %p\n", dicthd));
  433                     dstrtab = astrtab;
  434                     dents = 0;
  435                     while ((dictkey = OSDynamicCast(OSString,
  436                                               dictIterator->getNextObject()))) {
  437                         OSObject *dictvalue;
  438 
  439                         dictvalue = dictObj->getObject(dictkey);
  440                         if (!dictvalue)
  441                             continue;
  442                         dele = &(dicthd->list[dents]);
  443                         DPRINTF(("osdict: dict ele %d @%p\n", dents, dele));
  444                         if (primitive_type(dictvalue)) {
  445                             dele->key = dstrtab;
  446                             dele->key_size = dictkey->getLength() + 1;
  447                             DPRINTF(("osdict: dictkey %s size %d @%p\n",
  448                                 dictkey->getCStringNoCopy(), dictkey->getLength(), dstrtab));
  449                             memcpy(dele->key, dictkey->getCStringNoCopy(),
  450                                 dele->key_size);
  451                             dele->value = dele->key + dele->key_size;
  452                             primitive_type_collect(dele, dictvalue);
  453                             dstrtab += dele->key_size + dele->value_size;
  454                             DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab));
  455                         }
  456                         else {
  457                             continue;   /* Only handle primitive types here.  */
  458                         }
  459                         dents++;
  460                     }
  461                     dictIterator->release();
  462                     if (dents == 0)
  463                         continue;
  464                     arrayhd->type = MAC_DATA_TYPE_DICT;
  465                     ele->value_size = sizeof(struct mac_module_data_list) +
  466                         (dents - 1) * sizeof(struct mac_module_data_element);
  467                     DPRINTF(("osdict: dict ele size %d ents %d\n", ele->value_size, dents));
  468                     dicttab += ele->value_size;
  469                     DPRINTF(("osdict: new dicttab %p\n", dicttab));
  470                     dicthd->count = dents;
  471                     astrtab = dstrtab;
  472                 }
  473                 else {
  474                     continue;           /* Skip everything else.              */
  475                 }
  476                 nents++;
  477                 ele++;
  478             }
  479             if (nents == 0)
  480                 continue;
  481             element->value_size = sizeof(struct mac_module_data_list) +
  482                 (nents - 1) * sizeof(struct mac_module_data_element);
  483             listtab += element->value_size;
  484             DPRINTF(("osdict: new listtab %p\n", listtab));
  485             arrayhd->count = nents;
  486             strtab = astrtab;
  487             DPRINTF(("osdict: new strtab %p\n", strtab));
  488         }
  489         else {
  490             continue;           /* skip anything else */
  491         }
  492         element++;
  493     }
  494     DPRINTF(("module_data list @%p, key %p value %p\n",
  495         module_data, module_data->data[0].key, module_data->data[0].value));
  496 finish:
  497     if (keyIterator)
  498         keyIterator->release();
  499     return(module_data);
  500 }
  501 
  502 /*********************************************************************
  503 * This function takes a plist and looks for an OSModuleData dictionary.
  504 * If it is found, an encoded copy is returned.
  505 *********************************************************************/
  506 kmod_args_t
  507 get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen)
  508 {
  509 
  510     OSDictionary * kextModuleData = 0;      // don't release
  511     struct mac_module_data * module_data = 0;
  512     vm_map_copy_t copy = 0;
  513 
  514     kextModuleData = OSDynamicCast(OSDictionary,
  515         kextPlist->getObject("OSModuleData"));
  516     if (!kextModuleData)
  517         goto finish;
  518 
  519     module_data = osdict_encode(kextModuleData);
  520     if (!module_data)
  521         goto finish;
  522     *datalen = module_data->size;
  523     /*
  524      * Make a CoW copy of data and free the original.  The copy is
  525      * consumed by a call to vm_map_copyout() in kmod_start_or_stop().
  526      */
  527     vm_map_copyin(kernel_map, (vm_offset_t)module_data, *datalen, FALSE, &copy);
  528     kmem_free(kernel_map, (vm_offset_t)module_data, *datalen);
  529     DPRINTF(("get_module_data: copy @ %p\n", copy));
  530 finish:
  531     return (kmod_args_t)copy;
  532 }
  533 #endif /* MAC */
  534 
  535 static 
  536 kern_return_t start_prelink_module(UInt32 moduleIndex)
  537 {
  538     kern_return_t  kr = KERN_SUCCESS;
  539     UInt32 *       togo;
  540     SInt32         count, where, end;
  541     UInt32 *       prelink;
  542     SInt32         next, lastDep;
  543     OSData *       data;
  544     OSString *     str;
  545     OSDictionary * dict;
  546 
  547     OSArray *
  548     prelinkedModules = gIOPrelinkedModules;
  549 
  550     togo    = IONew(UInt32, prelinkedModules->getCount());
  551     togo[0] = moduleIndex;
  552     count   = 1;
  553 
  554     for (next = 0; next < count; next++)
  555     {
  556         dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
  557 
  558         data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
  559         if (!data)
  560         {
  561             // already started or no code
  562             if (togo[next] == moduleIndex)
  563             {
  564                 kr = KERN_FAILURE;
  565                 break;
  566             }
  567             continue;
  568         }
  569         prelink = (UInt32 *) data->getBytesNoCopy();
  570         lastDep = OSReadBigInt32(prelink, 12);
  571         for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
  572         {
  573             UInt32 depIdx = OSReadBigInt32(prelink, idx) - 1;
  574 
  575             for (where = next + 1;
  576                  (where < count) && (togo[where] > depIdx);
  577                  where++)       {}
  578 
  579             if (where != count)
  580             {
  581                 if (togo[where] == depIdx)
  582                     continue;
  583                 for (end = count; end != where; end--)
  584                     togo[end] = togo[end - 1];
  585             }
  586             count++;
  587             togo[where] = depIdx;
  588         }
  589     }
  590 
  591     if (KERN_SUCCESS != kr)
  592         return kr;
  593 
  594     for (next = (count - 1); next >= 0; next--)
  595     {
  596         dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
  597 
  598         data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
  599         if (!data)
  600             continue;
  601         prelink = (UInt32 *) data->getBytesNoCopy();
  602     
  603         kmod_t id;
  604         kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
  605 
  606         kr = kmod_create_internal(kmod_info, &id);
  607         if (KERN_SUCCESS != kr)
  608             break;
  609 
  610         lastDep = OSReadBigInt32(prelink, 12);
  611         for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
  612         {
  613             OSDictionary * depDict;
  614             kmod_info_t *  depInfo;
  615 
  616             depDict = (OSDictionary *) prelinkedModules->getObject(OSReadBigInt32(prelink, idx) - 1);
  617             str = OSDynamicCast(OSString, depDict->getObject(kModuleKey));
  618             depInfo = kmod_lookupbyname_locked(str->getCStringNoCopy());
  619             if (depInfo)
  620             {
  621                 kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id));
  622                 kfree(depInfo, sizeof(kmod_info_t));
  623             } else
  624                 IOLog("%s: NO DEP %s\n", kmod_info->name, str->getCStringNoCopy());
  625         }
  626         dict->removeObject("OSBundlePrelink");
  627 
  628         if (kmod_info->start)
  629             kr = kmod_start_or_stop(kmod_info->id, 1, 0, 0);
  630     }
  631 
  632     IODelete(togo, UInt32, prelinkedModules->getCount());
  633 
  634     return kr;
  635 }
  636 
  637 /*********************************************************************
  638 * This is a function that IOCatalogue calls in order to load a kmod.
  639 *********************************************************************/
  640 
  641 static 
  642 kern_return_t kmod_load_from_cache_sym(const OSSymbol * kmod_name)
  643 {
  644     OSArray *      prelinkedModules = gIOPrelinkedModules;
  645     kern_return_t  result = KERN_FAILURE;
  646     OSDictionary * dict;
  647     OSObject *     ident;
  648     UInt32         idx;
  649 
  650     if (!gIOPrelinkedModules)
  651         return KERN_FAILURE;
  652 
  653     for (idx = 0; 
  654          (dict = (OSDictionary *) prelinkedModules->getObject(idx));
  655          idx++)
  656     {
  657         if ((ident = dict->getObject(kModuleKey))
  658          && kmod_name->isEqualTo(ident))
  659             break;
  660     }
  661     if (dict) 
  662     {
  663         if (kernelLinkerPresent && dict->getObject("OSBundleDefer"))
  664         {
  665             kmod_load_extension((char *) kmod_name->getCStringNoCopy());
  666             result = kIOReturnOffline;
  667         }
  668         else
  669             result = start_prelink_module(idx);
  670     }
  671 
  672     return result;
  673 }
  674 
  675 extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_request)
  676 {
  677     bool                ret, cacheMiss = false;
  678     kern_return_t       kr;
  679     const OSSymbol *    sym = 0;
  680     kmod_info_t *       kmod_info;
  681 
  682     if (!moduleName)
  683         return false;
  684 
  685     /* To make sure this operation completes even if a bad extension needs
  686     * to be removed, take the kld lock for this whole block, spanning the
  687     * kmod_load_function() and remove_startup_extension_function() calls.
  688     */
  689     IOLockLock(gIOKLDLock);
  690     do
  691     {
  692         // Is the module already loaded?
  693         ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName)));
  694         if (ret) {
  695             kfree(kmod_info, sizeof(kmod_info_t));
  696             break;
  697         }
  698         sym = OSSymbol::withCString(moduleName);
  699         if (!sym) {
  700             ret = false;
  701             break;
  702         }
  703 
  704         kr = kmod_load_from_cache_sym(sym);
  705         ret = (kIOReturnSuccess == kr);
  706         cacheMiss = !ret;
  707         if (ret || !make_request || (kr == kIOReturnOffline))
  708             break;
  709 
  710         // If the module hasn't been loaded, then load it.
  711         if (!kmod_load_function) {
  712             IOLog("IOCatalogue: %s cannot be loaded "
  713                 "(kmod load function not set).\n",
  714                 moduleName);
  715             ret = true;
  716             break;
  717         }
  718 
  719         kr = kmod_load_function((char *)moduleName);
  720 
  721         if (ret != kIOReturnSuccess) {
  722             IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName);
  723 
  724             /* If the extension couldn't be loaded this time,
  725             * make it unavailable so that no more requests are
  726             * made in vain. This also enables other matching
  727             * extensions to have a chance.
  728             */
  729             if (kernelLinkerPresent && remove_startup_extension_function) {
  730                 (*remove_startup_extension_function)(moduleName);
  731             }
  732             ret = false;
  733 
  734         } else if (kernelLinkerPresent) {
  735             // If kern linker is here, the driver is actually loaded,
  736             // so return true.
  737             ret = true;
  738 
  739         } else {
  740             // kern linker isn't here, a request has been queued
  741             // but the module isn't necessarily loaded yet, so stall.
  742             ret = false;
  743         }
  744     }
  745     while (false);
  746 
  747     IOLockUnlock(gIOKLDLock);
  748 
  749     if (sym)
  750     {
  751         IOLockLock(gIOCatalogLock);
  752         gIOCatalogModuleRequests->setObject(sym);
  753         if (cacheMiss)
  754             gIOCatalogCacheMisses->setObject(sym);
  755         IOLockUnlock(gIOCatalogLock);
  756     }
  757 
  758     return ret;
  759 }
  760 
  761 extern "C" kern_return_t kmod_unload_cache(void)
  762 {
  763     OSArray *      prelinkedModules = gIOPrelinkedModules;
  764     kern_return_t  result = KERN_FAILURE;
  765     OSDictionary * dict;
  766     UInt32         idx;
  767     UInt32 *       prelink;
  768     OSData *       data;
  769 
  770     if (!gIOPrelinkedModules)
  771         return KERN_SUCCESS;
  772 
  773     IOLockLock(gIOKLDLock);
  774     for (idx = 0; 
  775          (dict = (OSDictionary *) prelinkedModules->getObject(idx));
  776          idx++)
  777     {
  778         data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
  779         if (!data)
  780             continue;
  781         prelink = (UInt32 *) data->getBytesNoCopy();
  782     
  783         kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
  784         vm_offset_t
  785         virt = ml_static_ptovirt(kmod_info->address);
  786         if( virt) {
  787             ml_static_mfree(virt, kmod_info->size);
  788         }
  789     }
  790 
  791     gIOPrelinkedModules->release();
  792     gIOPrelinkedModules = 0;
  793 
  794     IOLockUnlock(gIOKLDLock);
  795 
  796     return result;
  797 }
  798 
  799 extern "C" kern_return_t kmod_load_from_cache(const char * kmod_name)
  800 {
  801     kern_return_t kr;
  802     const OSSymbol * sym = OSSymbol::withCStringNoCopy(kmod_name);
  803 
  804     if (sym)
  805     {
  806         kr = kmod_load_from_cache_sym(sym);
  807         sym->release();
  808     }
  809     else
  810         kr = kIOReturnNoMemory;
  811 
  812     return kr;
  813 }
  814 
  815 /*********************************************************************
  816 *********************************************************************/
  817 
  818 static void UniqueProperties( OSDictionary * dict )
  819 {
  820     OSString             * data;
  821 
  822     data = OSDynamicCast( OSString, dict->getObject( gIOClassKey ));
  823     if( data) {
  824         const OSSymbol *classSymbol = OSSymbol::withString(data);
  825 
  826         dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
  827         classSymbol->release();
  828     }
  829 
  830     data = OSDynamicCast( OSString, dict->getObject( gIOMatchCategoryKey ));
  831     if( data) {
  832         const OSSymbol *classSymbol = OSSymbol::withString(data);
  833 
  834         dict->setObject( gIOMatchCategoryKey, (OSSymbol *) classSymbol);
  835         classSymbol->release();
  836     }
  837 }
  838 
  839 void IOCatalogue::initialize( void )
  840 {
  841     OSArray              * array;
  842     OSString             * errorString;
  843     bool                   rc;
  844 
  845     extern const char * gIOKernelConfigTables;
  846 
  847     array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
  848     if (!array && errorString) {
  849         IOLog("KernelConfigTables syntax error: %s\n",
  850                 errorString->getCStringNoCopy());
  851         errorString->release();
  852     }
  853 
  854     gIOClassKey              = OSSymbol::withCStringNoCopy( kIOClassKey );
  855     gIOProbeScoreKey         = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
  856     gIOModuleIdentifierKey   = OSSymbol::withCStringNoCopy( kModuleKey );
  857     gIOCatalogModuleRequests = OSSet::withCapacity(16);
  858     gIOCatalogCacheMisses    = OSSet::withCapacity(16);
  859     gIOCatalogROMMkexts      = OSSet::withCapacity(4);
  860 
  861     assert( array && gIOClassKey && gIOProbeScoreKey 
  862             && gIOModuleIdentifierKey && gIOCatalogModuleRequests);
  863 
  864     gIOCatalogue = new IOCatalogue;
  865     assert(gIOCatalogue);
  866     rc = gIOCatalogue->init(array);
  867     assert(rc);
  868     array->release();
  869 }
  870 
  871 // Initialize the IOCatalog object.
  872 bool IOCatalogue::init(OSArray * initArray)
  873 {
  874     OSDictionary         * dict;
  875     
  876     if ( !super::init() )
  877         return false;
  878 
  879     generation = 1;
  880     
  881     array = initArray;
  882     array->retain();
  883     kernelTables = OSCollectionIterator::withCollection( array );
  884 
  885     gIOCatalogLock = IOLockAlloc();
  886     gIOKLDLock     = IOLockAlloc();
  887 
  888     lock     = gIOCatalogLock;
  889     kld_lock = gIOKLDLock;
  890 
  891     kernelTables->reset();
  892     while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
  893         UniqueProperties(dict);
  894         if( 0 == dict->getObject( gIOClassKey ))
  895             IOLog("Missing or bad \"%s\" key\n",
  896                     gIOClassKey->getCStringNoCopy());
  897     }
  898 
  899 #if CATALOGTEST
  900     AbsoluteTime deadline;
  901     clock_interval_to_deadline( 1000, kMillisecondScale );
  902     thread_call_func_delayed( ping, this, deadline );
  903 #endif
  904 
  905     return true;
  906 }
  907 
  908 // Release all resources used by IOCatalogue and deallocate.
  909 // This will probably never be called.
  910 void IOCatalogue::free( void )
  911 {
  912     if ( array )
  913         array->release();
  914 
  915     if ( kernelTables )
  916         kernelTables->release();
  917     
  918     super::free();
  919 }
  920 
  921 #if CATALOGTEST
  922 
  923 static int hackLimit;
  924 
  925 enum { kDriversPerIter = 4 };
  926 
  927 void IOCatalogue::ping( thread_call_param_t arg, thread_call_param_t)
  928 {
  929     IOCatalogue          * self = (IOCatalogue *) arg;
  930     OSOrderedSet         * set;
  931     OSDictionary         * table;
  932     int                    newLimit;
  933 
  934     set = OSOrderedSet::withCapacity( 1 );
  935 
  936     IOLockLock( &self->lock );
  937 
  938     for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
  939         table = (OSDictionary *) self->array->getObject(
  940                                         hackLimit + newLimit );
  941         if( table) {
  942             set->setLastObject( table );
  943 
  944             OSSymbol * sym = (OSSymbol *) table->getObject( gIOClassKey );
  945             kprintf("enabling %s\n", sym->getCStringNoCopy());
  946 
  947         } else {
  948             newLimit--;
  949             break;
  950         }
  951     }
  952 
  953     IOService::catalogNewDrivers( set );
  954 
  955     hackLimit += newLimit;
  956     self->generation++;
  957 
  958     IOLockUnlock( &self->lock );
  959 
  960     if( kDriversPerIter == newLimit) {
  961         AbsoluteTime deadline;
  962         clock_interval_to_deadline( 500, kMillisecondScale );
  963         thread_call_func_delayed( ping, this, deadline );
  964     }
  965 }
  966 #endif
  967 
  968 OSOrderedSet * IOCatalogue::findDrivers( IOService * service,
  969                                         SInt32 * generationCount )
  970 {
  971     OSDictionary         * nextTable;
  972     OSOrderedSet         * set;
  973     OSString             * imports;
  974 
  975     set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
  976                                       (void *)gIOProbeScoreKey );
  977     if( !set )
  978         return( 0 );
  979 
  980     IOLockLock( lock );
  981     kernelTables->reset();
  982 
  983 #if CATALOGTEST
  984     int hackIndex = 0;
  985 #endif
  986     while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
  987 #if CATALOGTEST
  988         if( hackIndex++ > hackLimit)
  989             break;
  990 #endif
  991         imports = OSDynamicCast( OSString,
  992                         nextTable->getObject( gIOProviderClassKey ));
  993         if( imports && service->metaCast( imports ))
  994             set->setObject( nextTable );
  995     }
  996 
  997     *generationCount = getGenerationCount();
  998 
  999     IOLockUnlock( lock );
 1000 
 1001     return( set );
 1002 }
 1003 
 1004 // Is personality already in the catalog?
 1005 OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching,
 1006                                          SInt32 * generationCount)
 1007 {
 1008     OSDictionary         * dict;
 1009     OSOrderedSet         * set;
 1010 
 1011     UniqueProperties(matching);
 1012 
 1013     set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
 1014                                       (void *)gIOProbeScoreKey );
 1015 
 1016     IOLockLock( lock );
 1017     kernelTables->reset();
 1018     while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
 1019 
 1020        /* This comparison must be done with only the keys in the
 1021         * "matching" dict to enable general searches.
 1022         */
 1023         if ( dict->isEqualTo(matching, matching) )
 1024             set->setObject(dict);
 1025     }
 1026     *generationCount = getGenerationCount();
 1027     IOLockUnlock( lock );
 1028 
 1029     return set;
 1030 }
 1031 
 1032 // Add a new personality to the set if it has a unique IOResourceMatchKey value.
 1033 // XXX -- svail: This should be optimized.
 1034 // esb - There doesn't seem like any reason to do this - it causes problems
 1035 // esb - when there are more than one loadable driver matching on the same provider class
 1036 static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
 1037 {
 1038     set->setObject(dict);
 1039 }
 1040 
 1041 // Add driver config tables to catalog and start matching process.
 1042 bool IOCatalogue::addDrivers(OSArray * drivers,
 1043                               bool doNubMatching )
 1044 {
 1045     OSCollectionIterator * iter;
 1046     OSDictionary         * dict;
 1047     OSOrderedSet         * set;
 1048     OSArray              * persons;
 1049     OSString             * moduleName;
 1050     bool                   ret;
 1051 
 1052     ret = true;
 1053     persons = OSDynamicCast(OSArray, drivers);
 1054     if ( !persons )
 1055         return false;
 1056 
 1057     iter = OSCollectionIterator::withCollection( persons );
 1058     if (!iter )
 1059         return false;
 1060     
 1061     set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
 1062                                       (void *)gIOProbeScoreKey );
 1063     if ( !set ) {
 1064         iter->release();
 1065         return false;
 1066     }
 1067 
 1068     IOLockLock( lock );
 1069     while ( (dict = (OSDictionary *) iter->getNextObject()) )
 1070     {
 1071         if ((moduleName = OSDynamicCast(OSString, dict->getObject("OSBundleModuleDemand"))))
 1072         {
 1073             IOLockUnlock( lock );
 1074             ret = kmod_load_request(moduleName->getCStringNoCopy(), false);
 1075             IOLockLock( lock );
 1076             ret = true;
 1077         }
 1078         else
 1079         {
 1080             SInt count;
 1081             
 1082             UniqueProperties( dict );
 1083     
 1084             // Add driver personality to catalogue.
 1085             count = array->getCount();
 1086             while ( count-- ) {
 1087                 OSDictionary * driver;
 1088     
 1089                 // Be sure not to double up on personalities.
 1090                 driver = (OSDictionary *)array->getObject(count);
 1091     
 1092             /* Unlike in other functions, this comparison must be exact!
 1093                 * The catalogue must be able to contain personalities that
 1094                 * are proper supersets of others.
 1095                 * Do not compare just the properties present in one driver
 1096                 * pesonality or the other.
 1097                 */
 1098                 if (dict->isEqualTo(driver))
 1099                     break;
 1100             }
 1101             if (count >= 0)
 1102                 // its a dup
 1103                 continue;
 1104             
 1105             ret = array->setObject( dict );
 1106             if (!ret)
 1107                 break;
 1108     
 1109             AddNewImports( set, dict );
 1110         }
 1111     }
 1112     // Start device matching.
 1113     if (doNubMatching && (set->getCount() > 0)) {
 1114         IOService::catalogNewDrivers( set );
 1115         generation++;
 1116     }
 1117     IOLockUnlock( lock );
 1118 
 1119     set->release();
 1120     iter->release();
 1121     
 1122     return ret;
 1123 }
 1124 
 1125 // Remove drivers from the catalog which match the
 1126 // properties in the matching dictionary.
 1127 bool IOCatalogue::removeDrivers( OSDictionary * matching,
 1128                                  bool doNubMatching)
 1129 {
 1130     OSCollectionIterator * tables;
 1131     OSDictionary         * dict;
 1132     OSOrderedSet         * set;
 1133     OSArray              * arrayCopy;
 1134 
 1135     if ( !matching )
 1136         return false;
 1137 
 1138     set = OSOrderedSet::withCapacity(10,
 1139                                      IOServiceOrdering,
 1140                                      (void *)gIOProbeScoreKey);
 1141     if ( !set )
 1142         return false;
 1143 
 1144     arrayCopy = OSArray::withCapacity(100);
 1145     if ( !arrayCopy ) {
 1146         set->release();
 1147         return false;
 1148     }
 1149     
 1150     tables = OSCollectionIterator::withCollection(arrayCopy);
 1151     arrayCopy->release();
 1152     if ( !tables ) {
 1153         set->release();
 1154         return false;
 1155     }
 1156 
 1157     UniqueProperties( matching );
 1158 
 1159     IOLockLock( lock );
 1160     kernelTables->reset();
 1161     arrayCopy->merge(array);
 1162     array->flushCollection();
 1163     tables->reset();
 1164     while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
 1165 
 1166        /* This comparison must be done with only the keys in the
 1167         * "matching" dict to enable general searches.
 1168         */
 1169         if ( dict->isEqualTo(matching, matching) ) {
 1170             AddNewImports( set, dict );
 1171             continue;
 1172         }
 1173 
 1174         array->setObject(dict);
 1175     }
 1176     // Start device matching.
 1177     if ( doNubMatching && (set->getCount() > 0) ) {
 1178         IOService::catalogNewDrivers(set);
 1179         generation++;
 1180     }
 1181     IOLockUnlock( lock );
 1182     
 1183     set->release();
 1184     tables->release();
 1185     
 1186     return true;
 1187 }
 1188 
 1189 // Return the generation count.
 1190 SInt32 IOCatalogue::getGenerationCount( void ) const
 1191 {
 1192     return( generation );
 1193 }
 1194 
 1195 bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
 1196 {
 1197     return isModuleLoaded(moduleName->getCStringNoCopy());
 1198 }
 1199 
 1200 bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
 1201 {
 1202     return (kmod_load_request(moduleName, true));
 1203 }
 1204 
 1205 // Check to see if module has been loaded already.
 1206 bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
 1207 {
 1208     OSString             * moduleName = NULL;
 1209 
 1210     if ( !driver )
 1211         return false;
 1212 
 1213     moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
 1214     if ( moduleName )
 1215         return isModuleLoaded(moduleName);
 1216 
 1217    /* If a personality doesn't hold the "CFBundleIdentifier" key
 1218     * it is assumed to be an "in-kernel" driver.
 1219     */
 1220     return true;
 1221 }
 1222 
 1223 // This function is called after a module has been loaded.
 1224 void IOCatalogue::moduleHasLoaded( OSString * moduleName )
 1225 {
 1226     OSDictionary         * dict;
 1227 
 1228     dict = OSDictionary::withCapacity(2);
 1229     dict->setObject(gIOModuleIdentifierKey, moduleName);
 1230     startMatching(dict);
 1231     dict->release();
 1232 }
 1233 
 1234 void IOCatalogue::moduleHasLoaded( const char * moduleName )
 1235 {
 1236     OSString             * name;
 1237 
 1238     name = OSString::withCString(moduleName);
 1239     moduleHasLoaded(name);
 1240     name->release();
 1241 }
 1242 
 1243 IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
 1244 {
 1245     kmod_info_t          * k_info = 0;
 1246     kern_return_t          ret;
 1247     const char           * name;
 1248 
 1249     ret = kIOReturnBadArgument;
 1250     if ( moduleName ) {
 1251         name = moduleName->getCStringNoCopy();
 1252         k_info = kmod_lookupbyname_locked((char *)name);
 1253         if ( k_info && (k_info->reference_count < 1) ) {
 1254             if ( k_info->stop &&
 1255                  !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
 1256 
 1257                 kfree(k_info, sizeof(kmod_info_t));
 1258                 return ret;
 1259            }
 1260             
 1261            ret = kmod_destroy(host_priv_self(), k_info->id);
 1262         }
 1263     }
 1264  
 1265     if (k_info) {
 1266         kfree(k_info, sizeof(kmod_info_t));
 1267     }
 1268 
 1269     return ret;
 1270 }
 1271 
 1272 static IOReturn _terminateDrivers( OSDictionary * matching )
 1273 {
 1274     OSDictionary         * dict;
 1275     OSIterator           * iter;
 1276     IOService            * service;
 1277     IOReturn               ret;
 1278 
 1279     if ( !matching )
 1280         return kIOReturnBadArgument;
 1281 
 1282     ret = kIOReturnSuccess;
 1283     dict = 0;
 1284     iter = IORegistryIterator::iterateOver(gIOServicePlane,
 1285                                 kIORegistryIterateRecursively);
 1286     if ( !iter )
 1287         return kIOReturnNoMemory;
 1288 
 1289     UniqueProperties( matching );
 1290 
 1291     // terminate instances.
 1292     do {
 1293         iter->reset();
 1294         while( (service = (IOService *)iter->getNextObject()) ) {
 1295             dict = service->getPropertyTable();
 1296             if ( !dict )
 1297                 continue;
 1298 
 1299            /* Terminate only for personalities that match the matching dictionary.
 1300             * This comparison must be done with only the keys in the
 1301             * "matching" dict to enable general matching.
 1302             */
 1303             if ( !dict->isEqualTo(matching, matching) )
 1304                  continue;
 1305 
 1306             if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
 1307                 ret = kIOReturnUnsupported;
 1308                 break;
 1309             }
 1310         }
 1311     } while( !service && !iter->isValid());
 1312     iter->release();
 1313 
 1314     return ret;
 1315 }
 1316 
 1317 static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
 1318 {
 1319     OSCollectionIterator * tables;
 1320     OSDictionary         * dict;
 1321     OSArray              * arrayCopy;
 1322     IOReturn               ret = kIOReturnSuccess;
 1323 
 1324     // remove configs from catalog.
 1325 
 1326     arrayCopy = OSArray::withCapacity(100);
 1327     if ( !arrayCopy )
 1328         return kIOReturnNoMemory;
 1329 
 1330     tables = OSCollectionIterator::withCollection(arrayCopy);
 1331     arrayCopy->release();
 1332     if ( !tables )
 1333         return kIOReturnNoMemory;
 1334 
 1335     arrayCopy->merge(array);
 1336     array->flushCollection();
 1337     tables->reset();
 1338     while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
 1339 
 1340        /* Remove from the catalogue's array any personalities
 1341         * that match the matching dictionary.
 1342         * This comparison must be done with only the keys in the
 1343         * "matching" dict to enable general matching.
 1344         */
 1345         if ( dict->isEqualTo(matching, matching) )
 1346             continue;
 1347 
 1348         array->setObject(dict);
 1349     }
 1350 
 1351     tables->release();
 1352 
 1353     return ret;
 1354 }
 1355 
 1356 IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
 1357 {
 1358     IOReturn ret;
 1359 
 1360     ret = _terminateDrivers(matching);
 1361     IOLockLock( lock );
 1362     if (kIOReturnSuccess == ret)
 1363         ret = _removeDrivers(array, matching);
 1364     kernelTables->reset();
 1365     IOLockUnlock( lock );
 1366 
 1367     return ret;
 1368 }
 1369 
 1370 IOReturn IOCatalogue::terminateDriversForModule(
 1371                                       OSString * moduleName,
 1372                                       bool unload )
 1373 {
 1374     IOReturn ret;
 1375     OSDictionary * dict;
 1376 
 1377     dict = OSDictionary::withCapacity(1);
 1378     if ( !dict )
 1379         return kIOReturnNoMemory;
 1380 
 1381     dict->setObject(gIOModuleIdentifierKey, moduleName);
 1382 
 1383     ret = _terminateDrivers(dict);
 1384     IOLockLock( lock );
 1385     if (kIOReturnSuccess == ret)
 1386         ret = _removeDrivers(array, dict);
 1387     kernelTables->reset();
 1388 
 1389     // Unload the module itself.
 1390     if ( unload && ret == kIOReturnSuccess ) {
 1391         // Do kmod stop first.
 1392         ret = unloadModule(moduleName);
 1393     }
 1394 
 1395     IOLockUnlock( lock );
 1396 
 1397     dict->release();
 1398 
 1399     return ret;
 1400 }
 1401 
 1402 IOReturn IOCatalogue::terminateDriversForModule(
 1403                                       const char * moduleName,
 1404                                       bool unload )
 1405 {
 1406     OSString * name;
 1407     IOReturn ret;
 1408 
 1409     name = OSString::withCString(moduleName);
 1410     if ( !name )
 1411         return kIOReturnNoMemory;
 1412 
 1413     ret = terminateDriversForModule(name, unload);
 1414     name->release();
 1415 
 1416     return ret;
 1417 }
 1418 
 1419 bool IOCatalogue::startMatching( OSDictionary * matching )
 1420 {
 1421     OSDictionary         * dict;
 1422     OSOrderedSet         * set;
 1423     
 1424     if ( !matching )
 1425         return false;
 1426 
 1427     set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
 1428                                      (void *)gIOProbeScoreKey);
 1429     if ( !set )
 1430         return false;
 1431 
 1432     IOLockLock( lock );
 1433     kernelTables->reset();
 1434 
 1435     while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
 1436 
 1437        /* This comparison must be done with only the keys in the
 1438         * "matching" dict to enable general matching.
 1439         */
 1440         if ( dict->isEqualTo(matching, matching) )
 1441             AddNewImports(set, dict);
 1442     }
 1443     // Start device matching.
 1444     if ( set->getCount() > 0 ) {
 1445         IOService::catalogNewDrivers(set);
 1446         generation++;
 1447     }
 1448 
 1449     IOLockUnlock( lock );
 1450 
 1451     set->release();
 1452 
 1453     return true;
 1454 }
 1455 
 1456 void IOCatalogue::reset(void)
 1457 {
 1458     IOLog("Resetting IOCatalogue.\n");
 1459 }
 1460 
 1461 bool IOCatalogue::serialize(OSSerialize * s) const
 1462 {
 1463     if ( !s )
 1464         return false;
 1465 
 1466     return super::serialize(s);
 1467 }
 1468 
 1469 bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
 1470 {
 1471     kern_return_t kr = kIOReturnSuccess;
 1472 
 1473     switch ( kind )
 1474     {
 1475         case kIOCatalogGetContents:
 1476             if (!array->serialize(s))
 1477                 kr = kIOReturnNoMemory;
 1478             break;
 1479 
 1480         case kIOCatalogGetModuleDemandList:
 1481             IOLockLock( lock );
 1482             if (!gIOCatalogModuleRequests->serialize(s))
 1483                 kr = kIOReturnNoMemory;
 1484             IOLockUnlock( lock );
 1485             break;
 1486 
 1487         case kIOCatalogGetCacheMissList:
 1488             IOLockLock( lock );
 1489             if (!gIOCatalogCacheMisses->serialize(s))
 1490                 kr = kIOReturnNoMemory;
 1491             IOLockUnlock( lock );
 1492             break;
 1493 
 1494         case kIOCatalogGetROMMkextList:
 1495             IOLockLock( lock );
 1496 
 1497             if (!gIOCatalogROMMkexts || !gIOCatalogROMMkexts->getCount())
 1498                 kr = kIOReturnNoResources;
 1499             else if (!gIOCatalogROMMkexts->serialize(s))
 1500                 kr = kIOReturnNoMemory;
 1501 
 1502             if (gIOCatalogROMMkexts)
 1503             {
 1504                 gIOCatalogROMMkexts->release();
 1505                 gIOCatalogROMMkexts = 0;
 1506             }
 1507 
 1508             IOLockUnlock( lock );
 1509             break;
 1510 
 1511         default:
 1512             kr = kIOReturnBadArgument;
 1513             break;
 1514     }
 1515 
 1516     return kr;
 1517 }
 1518 
 1519 
 1520 bool IOCatalogue::recordStartupExtensions(void) {
 1521     bool result = false;
 1522 
 1523     IOLockLock(kld_lock);
 1524     if (kernelLinkerPresent && record_startup_extensions_function) {
 1525         result = (*record_startup_extensions_function)();
 1526     } else {
 1527         IOLog("Can't record startup extensions; "
 1528             "kernel linker is not present.\n");
 1529         result = false;
 1530     }
 1531     IOLockUnlock(kld_lock);
 1532 
 1533     return result;
 1534 }
 1535 
 1536 
 1537 /*********************************************************************
 1538 * This function operates on sections retrieved from the currently running
 1539 * 32 bit mach kernel.
 1540 *********************************************************************/
 1541 bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
 1542 {
 1543     OSData * copyData;
 1544     bool result = false;
 1545     bool prelinked;
 1546 
 1547    /* The mkext we've been handed (or the data it references) can go away,
 1548     * so we need to make a local copy to keep around as long as it might
 1549     * be needed.
 1550     */
 1551     copyData = OSData::withData(mkext);
 1552     if (copyData)
 1553     {
 1554         struct section * infosect;
 1555     
 1556         infosect  = getsectbyname("__PRELINK", "__info");
 1557         prelinked = (infosect && infosect->addr && infosect->size);
 1558 
 1559         IOLockLock(kld_lock);
 1560 
 1561         if (gIOCatalogROMMkexts)
 1562             gIOCatalogROMMkexts->setObject(copyData);
 1563 
 1564         if (prelinked) {
 1565             result = true;
 1566         } else if (kernelLinkerPresent && add_from_mkext_function) {
 1567             result = (*add_from_mkext_function)(copyData);
 1568         } else {
 1569             IOLog("Can't add startup extensions from archive; "
 1570                 "kernel linker is not present.\n");
 1571             result = false;
 1572         }
 1573 
 1574         IOLockUnlock(kld_lock);
 1575 
 1576         copyData->release();
 1577     }
 1578 
 1579     return result;
 1580 }
 1581 
 1582 /*********************************************************************
 1583 * This function clears out all references to the in-kernel linker,
 1584 * frees the list of startup extensions in extensionDict, and
 1585 * deallocates the kernel's __KLD segment to reclaim that memory.
 1586 *
 1587 * The segments it operates on are strictly 32 bit segments.
 1588 *********************************************************************/
 1589 kern_return_t IOCatalogue::removeKernelLinker(void) {
 1590     kern_return_t result = KERN_SUCCESS;
 1591     struct segment_command * segmentLE, *segmentKLD;
 1592     boolean_t   keepsyms = FALSE;
 1593 #if __ppc__ || __arm__
 1594     char * dt_segment_name;
 1595     void * segment_paddress;
 1596     int    segment_size;
 1597 #endif
 1598 
 1599    /* This must be the very first thing done by this function.
 1600     */
 1601     IOLockLock(kld_lock);
 1602 
 1603 
 1604    /* If the kernel linker isn't here, that's automatically
 1605     * a success.
 1606     */
 1607     if (!kernelLinkerPresent) {
 1608         result = KERN_SUCCESS;
 1609         goto finish;
 1610     }
 1611 
 1612     PE_parse_boot_arg("keepsyms", &keepsyms);
 1613  
 1614     IOLog("Jettisoning kernel linker.\n");
 1615 
 1616     kernelLinkerPresent = 0;
 1617 
 1618    /* Set the kmod_load_extension function as the means for loading
 1619     * a kernel extension.
 1620     */
 1621     kmod_load_function = &kmod_load_extension;
 1622 
 1623     record_startup_extensions_function = 0;
 1624     add_from_mkext_function = 0;
 1625     remove_startup_extension_function = 0;
 1626 
 1627 
 1628    /* Invoke destructors for the __KLD and __LINKEDIT segments.
 1629     * Do this for all segments before actually freeing their
 1630     * memory so that any cross-dependencies (not that there
 1631     * should be any) are handled.
 1632     */
 1633     segmentKLD = getsegbyname("__KLD");
 1634     if (!segmentKLD) {
 1635         IOLog("error removing kernel linker: can't find __KLD segment\n");
 1636         result = KERN_FAILURE;
 1637         goto finish;
 1638     }
 1639     OSRuntimeUnloadCPPForSegment(segmentKLD);
 1640 
 1641 #if __ppc__ || __arm__
 1642    /* Free the memory that was set up by bootx.
 1643     */
 1644     dt_segment_name = "Kernel-__KLD";
 1645     if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
 1646         IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
 1647             (int)segment_size);
 1648     }
 1649 #elif __i386__
 1650     /* On x86, use the mapping data from the segment load command to
 1651      * unload KLD directly, unless the keepsyms boot-arg was enabled.
 1652      * This may invalidate any assumptions about  "avail_start"
 1653      * defining the lower bound for valid physical addresses.
 1654      */
 1655     if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize)
 1656             ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize);
 1657 #else
 1658 #error arch
 1659 #endif
 1660 
 1661     struct section * sect;
 1662     sect = getsectbyname("__PRELINK", "__symtab");
 1663     if (sect && sect->addr) {
 1664         ml_static_mfree(sect->addr, sect->size);
 1665     }
 1666 
 1667 finish:
 1668 
 1669    /* This must be the very last thing done before returning.
 1670     */
 1671     IOLockUnlock(kld_lock);
 1672 
 1673     return result;
 1674 }
 1675 
 1676 /*********************************************************************
 1677 * This function stops the catalogue from making kextd requests during
 1678 * shutdown.
 1679 *********************************************************************/
 1680 void IOCatalogue::disableExternalLinker(void) {
 1681     IOLockLock(gIOKLDLock);
 1682    /* If kmod_load_extension (the kextd requester function) is in use,
 1683     * disable new module requests.
 1684     */
 1685     if (kmod_load_function == &kmod_load_extension) {
 1686         kmod_load_function = NULL;
 1687     }
 1688 
 1689     IOLockUnlock(gIOKLDLock);
 1690 }
 1691 
 1692 extern "C"
 1693 void jettison_kernel_linker(void)
 1694 {
 1695     if (gIOCatalogue != NULL)
 1696         gIOCatalogue->removeKernelLinker();
 1697 }

Cache object: 79b0d0140e0cb5848aa3ba96139667cf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.