1/*
2 * Copyright (c) 2000-2007 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#include <libkern/c++/OSContainers.h>
29#include <IOKit/IODeviceTreeSupport.h>
30#include <IOKit/IORegistryEntry.h>
31#include <IOKit/IOCatalogue.h>
32#include <IOKit/IOKitKeysPrivate.h>
33#include <libkern/c++/OSUnserialize.h>
34#include <libkern/OSByteOrder.h>
35#include <libsa/catalogue.h>
36
37extern "C" {
38#include <machine/machine_routines.h>
39#include <mach/host_info.h>
40#include <mach/kmod.h>
41#include <libsa/mkext.h>
42#include <libsa/vers_rsrc.h>
43#include <mach-o/loader.h>
44};
45
46#include <IOKit/IOLib.h>
47
48#include <IOKit/assert.h>
49
50extern "C" {
51extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
52// extern kern_return_t host_info(host_t host,
53//     host_flavor_t flavor,
54//     host_info_t info,
55//     mach_msg_type_number_t  *count);
56extern int grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype);
57// Return the address of the named Mach-O segment from the currently
58// executing 32 bit kernel, or NULL.
59extern struct segment_command *getsegbyname(char *seg_name);
60// Return the address of the named section from the named Mach-O segment
61// from the currently executing 32 bit kernel, or NULL.
62extern struct section *getsectbyname(const char *segname, const char *sectname);
63};
64
65#define LOG_DELAY()
66
67#if 0
68#define VTYELLOW   "\033[33m"
69#define VTRESET    "\033[0m"
70#else
71#define VTYELLOW   ""
72#define VTRESET    ""
73#endif
74
75/*********************************************************************
76*********************************************************************/
77static OSDictionary * gStartupExtensions = 0;
78static OSArray * gBootLoaderObjects = 0;
79extern OSArray * gIOPrelinkedModules;
80
81OSDictionary * getStartupExtensions(void) {
82    if (gStartupExtensions) {
83        return gStartupExtensions;
84    }
85    gStartupExtensions = OSDictionary::withCapacity(1);
86    assert (gStartupExtensions);
87
88    return gStartupExtensions;
89}
90
91/* This array holds objects that are needed to be held around during
92 * boot before kextd starts up. Currently it contains OSData objects
93 * copied from OF entries for mkext archives in device ROMs. Because
94 * the Device Tree support code dumps these after initially handing
95 * them to us, we have to be able to clean them up later.
96 */
97OSArray * getBootLoaderObjects(void) {
98    if (gBootLoaderObjects) {
99        return gBootLoaderObjects;
100    }
101    gBootLoaderObjects = OSArray::withCapacity(1);
102    assert (gBootLoaderObjects);
103
104    return gBootLoaderObjects;
105}
106
107/*********************************************************************
108* This function checks that a driver dict has all the required
109* entries and does a little bit of value checking too.
110*
111* index is nonnegative if the index of an entry from an mkext
112* archive.
113*********************************************************************/
114bool validateExtensionDict(OSDictionary * extension, int index) {
115
116    bool result = true;
117    bool not_a_dict = false;
118    bool id_missing = false;
119    bool is_kernel_resource = false;
120    bool has_executable = false;
121    bool ineligible_for_safe_boot = false;
122    OSString * bundleIdentifier = NULL;    // do not release
123    OSObject * rawValue = NULL;            // do not release
124    OSString * stringValue = NULL;         // do not release
125    OSBoolean * booleanValue = NULL;       // do not release
126    OSDictionary * personalities = NULL;   // do not release
127    OSDictionary * libraries = NULL;       // do not release
128    OSCollectionIterator * keyIterator = NULL;  // must release
129    OSString * key = NULL;                 // do not release
130    VERS_version vers;
131    VERS_version compatible_vers;
132    char namep[16];      // unused but needed for PE_parse_boot_arg()
133
134    // Info dict is a dictionary
135    if (!OSDynamicCast(OSDictionary, extension)) {
136        not_a_dict = true;
137        result = false;
138        goto finish;
139    }
140
141    // CFBundleIdentifier is a string - REQUIRED
142    bundleIdentifier = OSDynamicCast(OSString,
143        extension->getObject("CFBundleIdentifier"));
144    if (!bundleIdentifier) {
145        id_missing = true;
146        result = false;
147        goto finish;
148    }
149
150    // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
151    if (bundleIdentifier->getLength() >= KMOD_MAX_NAME) {
152        result = false;
153        goto finish;
154    }
155
156    // CFBundlePackageType is "KEXT" - REQUIRED
157    stringValue = OSDynamicCast(OSString,
158        extension->getObject("CFBundlePackageType"));
159    if (!stringValue) {
160        result = false;
161        goto finish;
162    }
163    if (!stringValue->isEqualTo("KEXT")) {
164        result = false;
165        goto finish;
166    }
167
168    // CFBundleVersion is a string - REQUIRED
169    stringValue = OSDynamicCast(OSString,
170        extension->getObject("CFBundleVersion"));
171    if (!stringValue) {
172        result = false;
173        goto finish;
174    }
175    // CFBundleVersion is of valid form
176    vers = VERS_parse_string(stringValue->getCStringNoCopy());
177    if (vers < 0) {
178        result = false;
179        goto finish;
180    }
181
182    // OSBundleCompatibleVersion is a string - OPTIONAL
183    rawValue = extension->getObject("OSBundleCompatibleVersion");
184    if (rawValue) {
185        stringValue = OSDynamicCast(OSString, rawValue);
186        if (!stringValue) {
187            result = false;
188            goto finish;
189        }
190
191        // OSBundleCompatibleVersion is of valid form
192        compatible_vers = VERS_parse_string(stringValue->getCStringNoCopy());
193        if (compatible_vers < 0) {
194            result = false;
195            goto finish;
196        }
197
198        // OSBundleCompatibleVersion <= CFBundleVersion
199        if (compatible_vers > vers) {
200            result = false;
201            goto finish;
202        }
203    }
204
205    // CFBundleExecutable is a string - OPTIONAL
206    rawValue = extension->getObject("CFBundleExecutable");
207    if (rawValue) {
208        stringValue = OSDynamicCast(OSString, rawValue);
209        if (!stringValue || stringValue->getLength() == 0) {
210            result = false;
211            goto finish;
212        }
213        has_executable = true;
214    }
215
216    // OSKernelResource is a boolean value - OPTIONAL
217    rawValue = extension->getObject("OSKernelResource");
218    if (rawValue) {
219        booleanValue = OSDynamicCast(OSBoolean, rawValue);
220        if (!booleanValue) {
221            result = false;
222            goto finish;
223        }
224        is_kernel_resource = booleanValue->isTrue();
225    }
226
227    // IOKitPersonalities is a dictionary - OPTIONAL
228    rawValue = extension->getObject("IOKitPersonalities");
229    if (rawValue) {
230        personalities = OSDynamicCast(OSDictionary, rawValue);
231        if (!personalities) {
232            result = false;
233            goto finish;
234        }
235
236        keyIterator = OSCollectionIterator::withCollection(personalities);
237        if (!keyIterator) {
238            IOLog("Error: Failed to allocate iterator for personalities.\n");
239            LOG_DELAY();
240            result = false;
241            goto finish;
242        }
243
244        while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
245            OSDictionary * personality = NULL;  // do not release
246
247            // Each personality is a dictionary
248            personality = OSDynamicCast(OSDictionary,
249                personalities->getObject(key));
250            if (!personality) {
251                result = false;
252                goto finish;
253            }
254
255            //   IOClass exists as a string - REQUIRED
256            if (!OSDynamicCast(OSString, personality->getObject("IOClass"))) {
257                result = false;
258                goto finish;
259            }
260
261            //   IOProviderClass exists as a string - REQUIRED
262            if (!OSDynamicCast(OSString,
263                personality->getObject("IOProviderClass"))) {
264
265                result = false;
266                goto finish;
267            }
268
269            // CFBundleIdentifier is a string - OPTIONAL - INSERT IF ABSENT!
270            rawValue = personality->getObject("CFBundleIdentifier");
271            if (!rawValue) {
272                personality->setObject("CFBundleIdentifier", bundleIdentifier);
273            } else {
274                OSString * personalityID = NULL;    // do not release
275                personalityID = OSDynamicCast(OSString, rawValue);
276                if (!personalityID) {
277                    result = false;
278                    goto finish;
279                } else {
280                    // Length of CFBundleIdentifier is not >= KMOD_MAX_NAME
281                    if (personalityID->getLength() >= KMOD_MAX_NAME) {
282                        result = false;
283                        goto finish;
284                    }
285                }
286            }
287
288            // IOKitDebug is a number - OPTIONAL
289            rawValue = personality->getObject("IOKitDebug");
290            if (rawValue && !OSDynamicCast(OSNumber, rawValue)) {
291                result = false;
292                goto finish;
293            }
294        }
295
296        keyIterator->release();
297        keyIterator = NULL;
298    }
299
300
301    // OSBundleLibraries is a dictionary - REQUIRED if
302    // not kernel resource & has executable
303    //
304    rawValue = extension->getObject("OSBundleLibraries");
305    if (!rawValue && !is_kernel_resource && has_executable) {
306        result = false;
307        goto finish;
308    }
309
310    if (rawValue) {
311        libraries = OSDynamicCast(OSDictionary, rawValue);
312        if (!libraries) {
313            result = false;
314            goto finish;
315        }
316
317        keyIterator = OSCollectionIterator::withCollection(libraries);
318        if (!keyIterator) {
319            IOLog("Error: Failed to allocate iterator for libraries.\n");
320            LOG_DELAY();
321            result = false;
322            goto finish;
323        }
324
325        while ((key = OSDynamicCast(OSString,
326            keyIterator->getNextObject()))) {
327
328            OSString * libraryVersion = NULL;  // do not release
329
330            // Each key's length is not >= KMOD_MAX_NAME
331            if (key->getLength() >= KMOD_MAX_NAME) {
332                result = false;
333                goto finish;
334            }
335
336            libraryVersion = OSDynamicCast(OSString,
337                libraries->getObject(key));
338            if (!libraryVersion) {
339                result = false;
340                goto finish;
341            }
342
343            // Each value is a valid version string
344            vers = VERS_parse_string(libraryVersion->getCStringNoCopy());
345            if (vers < 0) {
346                result = false;
347                goto finish;
348            }
349        }
350
351        keyIterator->release();
352        keyIterator = NULL;
353    }
354
355    // OSBundleRequired, if present, must have a legal value.
356    // If it is not present and if we are safe-booting,
357    // then the kext is not eligible.
358    //
359    rawValue = extension->getObject("OSBundleRequired");
360    if (rawValue) {
361        stringValue = OSDynamicCast(OSString, rawValue);
362        if (!stringValue) {
363            result = false;
364            goto finish;
365        }
366        if (!stringValue->isEqualTo("Root") &&
367            !stringValue->isEqualTo("Local-Root") &&
368            !stringValue->isEqualTo("Network-Root") &&
369            !stringValue->isEqualTo("Safe Boot") &&
370            !stringValue->isEqualTo("Console")) {
371
372            result = false;
373            goto finish;
374        }
375
376    } else if (PE_parse_boot_argn("-x", namep, sizeof (namep))) { /* safe boot */
377        ineligible_for_safe_boot = true;
378        result = false;
379        goto finish;
380    }
381
382
383finish:
384    if (keyIterator)   keyIterator->release();
385
386    if (!result) {
387        if (ineligible_for_safe_boot) {
388            IOLog(VTYELLOW "Skipping extension \"%s\" during safe boot "
389                "(no OSBundleRequired property)\n"
390                VTRESET,
391                bundleIdentifier->getCStringNoCopy());
392        } else if (not_a_dict) {
393            if (index > -1) {
394                IOLog(VTYELLOW "mkext entry %d: " VTRESET, index);
395            } else {
396                IOLog(VTYELLOW "kernel extension " VTRESET);
397            }
398            IOLog(VTYELLOW "info dictionary isn't a dictionary\n"
399                VTRESET);
400        } else if (id_missing) {
401            if (index > -1) {
402                IOLog(VTYELLOW "mkext entry %d: " VTRESET, index);
403            } else {
404                IOLog(VTYELLOW "kernel extension " VTRESET);
405            }
406            IOLog(VTYELLOW "\"CFBundleIdentifier\" property is "
407                "missing or not a string\n"
408                VTRESET);
409        } else {
410            IOLog(VTYELLOW "kernel extension \"%s\": info dictionary is invalid\n"
411                VTRESET, bundleIdentifier->getCStringNoCopy());
412        }
413        LOG_DELAY();
414    }
415
416    return result;
417}
418
419
420/*********************************************************************
421*********************************************************************/
422OSDictionary * compareExtensionVersions(
423    OSDictionary * incumbent,
424    OSDictionary * candidate) {
425
426    OSDictionary * winner = NULL;
427
428    OSDictionary * incumbentPlist = NULL;
429    OSDictionary * candidatePlist = NULL;
430    OSString * incumbentName = NULL;
431    OSString * candidateName = NULL;
432    OSString * incumbentVersionString = NULL;
433    OSString * candidateVersionString = NULL;
434    VERS_version incumbent_vers = 0;
435    VERS_version candidate_vers = 0;
436
437    incumbentPlist = OSDynamicCast(OSDictionary,
438        incumbent->getObject("plist"));
439    candidatePlist = OSDynamicCast(OSDictionary,
440        candidate->getObject("plist"));
441
442    if (!incumbentPlist || !candidatePlist) {
443        IOLog("compareExtensionVersions() called with invalid "
444            "extension dictionaries.\n");
445        LOG_DELAY();
446        winner = NULL;
447        goto finish;
448    }
449
450    incumbentName = OSDynamicCast(OSString,
451        incumbentPlist->getObject("CFBundleIdentifier"));
452    candidateName = OSDynamicCast(OSString,
453        candidatePlist->getObject("CFBundleIdentifier"));
454    incumbentVersionString = OSDynamicCast(OSString,
455        incumbentPlist->getObject("CFBundleVersion"));
456    candidateVersionString = OSDynamicCast(OSString,
457        candidatePlist->getObject("CFBundleVersion"));
458
459    if (!incumbentName || !candidateName ||
460        !incumbentVersionString || !candidateVersionString) {
461
462        IOLog("compareExtensionVersions() called with invalid "
463            "extension dictionaries.\n");
464        LOG_DELAY();
465        winner = NULL;
466        goto finish;
467    }
468
469    if (strcmp(incumbentName->getCStringNoCopy(),
470               candidateName->getCStringNoCopy())) {
471
472        IOLog("compareExtensionVersions() called with different "
473            "extension names (%s and %s).\n",
474            incumbentName->getCStringNoCopy(),
475            candidateName->getCStringNoCopy());
476        LOG_DELAY();
477        winner = NULL;
478        goto finish;
479    }
480
481    incumbent_vers = VERS_parse_string(incumbentVersionString->getCStringNoCopy());
482    if (incumbent_vers < 0) {
483
484        IOLog(VTYELLOW "Error parsing version string for extension %s (%s)\n"
485            VTRESET,
486            incumbentName->getCStringNoCopy(),
487            incumbentVersionString->getCStringNoCopy());
488        LOG_DELAY();
489        winner = NULL;
490        goto finish;
491    }
492
493    candidate_vers = VERS_parse_string(candidateVersionString->getCStringNoCopy());
494    if (candidate_vers < 0) {
495
496        IOLog(VTYELLOW "Error parsing version string for extension %s (%s)\n"
497            VTRESET,
498            candidateName->getCStringNoCopy(),
499            candidateVersionString->getCStringNoCopy());
500        LOG_DELAY();
501        winner = NULL;
502        goto finish;
503     }
504
505    if (candidate_vers > incumbent_vers) {
506        IOLog(VTYELLOW "Replacing extension \"%s\" with newer version "
507            "(%s -> %s).\n" VTRESET,
508            incumbentName->getCStringNoCopy(),
509            incumbentVersionString->getCStringNoCopy(),
510            candidateVersionString->getCStringNoCopy());
511        LOG_DELAY();
512        winner = candidate;
513        goto finish;
514    } else {
515        IOLog(VTYELLOW "Skipping duplicate extension \"%s\" with older/same "
516            " version (%s -> %s).\n" VTRESET,
517            candidateName->getCStringNoCopy(),
518            candidateVersionString->getCStringNoCopy(),
519            incumbentVersionString->getCStringNoCopy());
520        LOG_DELAY();
521        winner = incumbent;
522        goto finish;
523    }
524
525finish:
526
527    // no cleanup, how nice
528    return winner;
529}
530
531
532/*********************************************************************
533* This function merges entries in the mergeFrom dictionary into the
534* mergeInto dictionary. If it returns false, the two dictionaries are
535* not altered. If it returns true, then mergeInto may have new
536* entries; any keys that were already present in mergeInto are
537* removed from mergeFrom, so that the caller can see what was
538* actually merged.
539*********************************************************************/
540bool mergeExtensionDictionaries(OSDictionary * mergeInto,
541    OSDictionary * mergeFrom) {
542
543    bool result = true;
544    OSDictionary * mergeIntoCopy = NULL;       // must release
545    OSDictionary * mergeFromCopy = NULL;       // must release
546    OSCollectionIterator * keyIterator = NULL; // must release
547    OSString * key;                            // don't release
548
549   /* Add 1 to count to guarantee copy can grow (grr).
550    */
551    mergeIntoCopy = OSDictionary::withDictionary(mergeInto,
552        mergeInto->getCount() + 1);
553    if (!mergeIntoCopy) {
554        IOLog("Error: Failed to copy 'into' extensions dictionary "
555            "for merge.\n");
556        LOG_DELAY();
557        result = false;
558        goto finish;
559    }
560
561   /* Add 1 to count to guarantee copy can grow (grr).
562    */
563    mergeFromCopy = OSDictionary::withDictionary(mergeFrom,
564        mergeFrom->getCount() + 1);
565    if (!mergeFromCopy) {
566        IOLog("Error: Failed to copy 'from' extensions dictionary "
567            "for merge.\n");
568        LOG_DELAY();
569        result = false;
570        goto finish;
571    }
572
573    keyIterator = OSCollectionIterator::withCollection(mergeFrom);
574    if (!keyIterator) {
575        IOLog("Error: Failed to allocate iterator for extensions.\n");
576        LOG_DELAY();
577        result = false;
578        goto finish;
579    }
580
581
582   /*****
583    * Loop through "from" dictionary, checking if the identifier already
584    * exists in the "into" dictionary and checking versions if it does.
585    */
586    while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
587        OSDictionary * incumbentExt = OSDynamicCast(OSDictionary,
588            mergeIntoCopy->getObject(key));
589        OSDictionary * candidateExt = OSDynamicCast(OSDictionary,
590            mergeFrom->getObject(key));
591
592        if (!incumbentExt) {
593            if (!mergeIntoCopy->setObject(key, candidateExt)) {
594
595               /* This is a fatal error, so bail.
596                */
597                IOLog("mergeExtensionDictionaries(): Failed to add "
598                    "identifier %s\n",
599                    key->getCStringNoCopy());
600                LOG_DELAY();
601                result = false;
602                goto finish;
603            }
604        } else {
605            OSDictionary * mostRecentExtension =
606                compareExtensionVersions(incumbentExt, candidateExt);
607
608            if (mostRecentExtension == incumbentExt) {
609                mergeFromCopy->removeObject(key);
610            } else if (mostRecentExtension == candidateExt) {
611
612                if (!mergeIntoCopy->setObject(key, candidateExt)) {
613
614                   /* This is a fatal error, so bail.
615                    */
616                    IOLog("mergeExtensionDictionaries(): Failed to add "
617                        "identifier %s\n",
618                        key->getCStringNoCopy());
619                    LOG_DELAY();
620                    result = false;
621                    goto finish;
622                }
623            } else /* should be NULL */ {
624
625               /* This is a nonfatal error, so continue doing others.
626                */
627                IOLog("mergeExtensionDictionaries(): Error comparing "
628                    "versions of duplicate extensions %s.\n",
629                    key->getCStringNoCopy());
630                LOG_DELAY();
631                continue;
632            }
633        }
634    }
635
636finish:
637
638   /* If successful, replace the contents of the original
639    * dictionaries with those of the modified copies.
640    */
641    if (result) {
642        mergeInto->flushCollection();
643        mergeInto->merge(mergeIntoCopy);
644        mergeFrom->flushCollection();
645        mergeFrom->merge(mergeFromCopy);
646    }
647
648    if (mergeIntoCopy) mergeIntoCopy->release();
649    if (mergeFromCopy) mergeFromCopy->release();
650    if (keyIterator)   keyIterator->release();
651
652    return result;
653}
654
655
656/****
657 * These bits are used to parse data made available by bootx.
658 */
659#define BOOTX_KEXT_PREFIX       "Driver-"
660#define BOOTX_MULTIKEXT_PREFIX  "DriversPackage-"
661
662typedef struct MemoryMapFileInfo {
663    UInt32 paddr;
664    UInt32 length;
665} MemoryMapFileInfo;
666
667typedef struct BootxDriverInfo {
668    char *plistAddr;
669    long  plistLength;
670    void *moduleAddr;
671    long  moduleLength;
672} BootxDriverInfo;
673
674typedef struct MkextEntryInfo {
675    vm_address_t  base_address;
676    mkext_file  * fileinfo;
677} MkextEntryInfo;
678
679
680/*********************************************************************
681* This private function reads the data for a single extension from
682* the bootx memory-map's propery dict, returning a dictionary with
683* keys "plist" for the extension's Info.plist as a parsed OSDictionary
684* and "code" for the extension's executable code as an OSData.
685*********************************************************************/
686OSDictionary * readExtension(OSDictionary * propertyDict,
687    const char * memory_map_name) {
688
689    int error = 0;
690    OSData               * bootxDriverDataObject = NULL;
691    OSDictionary         * driverPlist = NULL;
692    OSString             * driverName = NULL;
693    OSData               * driverCode = NULL;
694    OSString             * errorString = NULL;
695    OSDictionary         * driverDict = NULL;
696
697    const MemoryMapFileInfo * driverInfo = 0;
698    BootxDriverInfo * dataBuffer;
699
700    kmod_info_t          * loaded_kmod = NULL;
701
702    bootxDriverDataObject = OSDynamicCast(OSData,
703        propertyDict->getObject(memory_map_name));
704    // don't release bootxDriverDataObject
705
706    if (!bootxDriverDataObject) {
707        IOLog("Error: No driver data object "
708            "for device tree entry \"%s\".\n",
709            memory_map_name);
710        LOG_DELAY();
711        error = 1;
712        goto finish;
713    }
714
715    driverDict = OSDictionary::withCapacity(2);
716    if (!driverDict) {
717        IOLog("Error: Couldn't allocate dictionary "
718            "for device tree entry \"%s\".\n", memory_map_name);
719        LOG_DELAY();
720        error = 1;
721        goto finish;
722    }
723
724    driverInfo = (const MemoryMapFileInfo *)
725        bootxDriverDataObject->getBytesNoCopy(0,
726        sizeof(MemoryMapFileInfo));
727#if defined (__ppc__) || defined (__arm__)
728    dataBuffer = (BootxDriverInfo *)ml_static_ptovirt(driverInfo->paddr);
729#elif defined (__i386__)
730    dataBuffer = (BootxDriverInfo *)ml_boot_ptovirt(driverInfo->paddr);
731    dataBuffer->plistAddr = (char *)ml_boot_ptovirt((vm_address_t)dataBuffer->plistAddr);
732    if (dataBuffer->moduleAddr)
733      dataBuffer->moduleAddr = (void *)ml_boot_ptovirt((vm_address_t)dataBuffer->moduleAddr);
734#else
735#error unsupported architecture
736#endif
737    if (!dataBuffer) {
738        IOLog("Error: No data buffer "
739        "for device tree entry \"%s\".\n", memory_map_name);
740        LOG_DELAY();
741        error = 1;
742        goto finish;
743    }
744
745    driverPlist = OSDynamicCast(OSDictionary,
746        OSUnserializeXML(dataBuffer->plistAddr, &errorString));
747    if (!driverPlist) {
748        IOLog("Error: Couldn't read XML property list "
749            "for device tree entry \"%s\".\n", memory_map_name);
750        LOG_DELAY();
751        if (errorString) {
752            IOLog("XML parse error: %s.\n",
753                errorString->getCStringNoCopy());
754            LOG_DELAY();
755        }
756        error = 1;
757        goto finish;
758    }
759
760
761    driverName = OSDynamicCast(OSString,
762        driverPlist->getObject("CFBundleIdentifier"));  // do not release
763    if (!driverName) {
764        IOLog("Error: Device tree entry \"%s\" has "
765            "no \"CFBundleIdentifier\" property.\n", memory_map_name);
766        LOG_DELAY();
767        error = 1;
768        goto finish;
769    }
770
771   /* Check if kmod is already loaded and is a real loadable one (has
772    * an address).
773    */
774    loaded_kmod = kmod_lookupbyname_locked(driverName->getCStringNoCopy());
775    if (loaded_kmod && loaded_kmod->address) {
776        IOLog("Skipping new extension \"%s\"; an extension named "
777            "\"%s\" is already loaded.\n",
778            driverName->getCStringNoCopy(),
779            loaded_kmod->name);
780        LOG_DELAY();
781        error = 1;
782        goto finish;
783    }
784
785    if (!validateExtensionDict(driverPlist, -1)) {
786        // validateExtensionsDict() logs an error
787        error = 1;
788        goto finish;
789    }
790
791    driverDict->setObject("plist", driverPlist);
792
793   /* It's perfectly okay for a KEXT to have no executable.
794    * Check that moduleAddr is nonzero before attempting to
795    * get one.
796    *
797    * NOTE: The driverCode object is created "no-copy", so
798    * it doesn't own that memory. The memory must be freed
799    * separately from the OSData object (see
800    * clearStartupExtensionsAndLoaderInfo() at the end of this file).
801    */
802    if (dataBuffer->moduleAddr && dataBuffer->moduleLength) {
803        driverCode = OSData::withBytesNoCopy(dataBuffer->moduleAddr,
804            dataBuffer->moduleLength);
805        if (!driverCode) {
806            IOLog("Error: Couldn't allocate data object "
807                "to hold code for device tree entry \"%s\".\n",
808                memory_map_name);
809            LOG_DELAY();
810            error = 1;
811            goto finish;
812        }
813
814        if (driverCode) {
815            driverDict->setObject("code", driverCode);
816        }
817    }
818
819finish:
820
821    if (loaded_kmod) {
822        kfree(loaded_kmod, sizeof(kmod_info_t));
823    }
824
825    // do not release bootxDriverDataObject
826    // do not release driverName
827
828    if (driverPlist) {
829        driverPlist->release();
830    }
831    if (errorString) {
832        errorString->release();
833    }
834    if (driverCode) {
835        driverCode->release();
836    }
837    if (error) {
838        if (driverDict) {
839            driverDict->release();
840            driverDict = NULL;
841        }
842    }
843    return driverDict;
844}
845
846
847/*********************************************************************
848* Used to uncompress a single file entry in an mkext archive.
849*
850* The OSData returned does not own its memory! You must deallocate
851* that memory using kmem_free() before releasing the OSData().
852*********************************************************************/
853static bool uncompressFile(u_int8_t *base_address, mkext_file * fileinfo,
854		           /* out */ OSData ** file) {
855
856    bool result = true;
857    kern_return_t kern_result;
858    u_int8_t * uncompressed_file = 0; // kmem_free() on error
859    OSData * uncompressedFile = 0;    // returned
860    size_t uncompressed_size = 0;
861
862    size_t offset = OSSwapBigToHostInt32(fileinfo->offset);
863    size_t compsize = OSSwapBigToHostInt32(fileinfo->compsize);
864    size_t realsize = OSSwapBigToHostInt32(fileinfo->realsize);
865    time_t modifiedsecs = OSSwapBigToHostInt32(fileinfo->modifiedsecs);
866
867    *file = 0;
868
869   /* If these four fields are zero there's no file, but that isn't
870    * an error.
871    */
872    if (offset == 0 && compsize == 0 &&
873        realsize == 0 && modifiedsecs == 0) {
874        goto finish;
875    }
876
877    // Add 1 for '\0' to terminate XML string!
878    kern_result = kmem_alloc(kernel_map, (vm_offset_t *)&uncompressed_file,
879        realsize + 1);
880    if (kern_result != KERN_SUCCESS) {
881        IOLog("Error: Couldn't allocate data buffer "
882              "to uncompress file.\n");
883        LOG_DELAY();
884        result = false;
885        goto finish;
886    }
887
888    uncompressedFile = OSData::withBytesNoCopy(uncompressed_file,
889        realsize + 1);
890    if (!uncompressedFile) {
891        IOLog("Error: Couldn't allocate data object "
892              "to uncompress file.\n");
893        LOG_DELAY();
894        result = false;
895        goto finish;
896    }
897
898    if (compsize != 0) {
899        uncompressed_size = decompress_lzss(uncompressed_file,
900            base_address + offset,
901            compsize);
902        if (uncompressed_size != realsize) {
903            IOLog("Error: Uncompressed file is not the length "
904                  "recorded.\n");
905            LOG_DELAY();
906            result = false;
907            goto finish;
908        }
909        uncompressed_file[uncompressed_size] = '\0';
910    } else {
911        bcopy(base_address + offset, uncompressed_file,
912            realsize);
913        uncompressed_file[realsize] = '\0';
914    }
915
916    *file = uncompressedFile;
917
918finish:
919    if (!result) {
920        if (uncompressed_file) {
921            kmem_free(kernel_map, (vm_address_t)uncompressed_file,
922                realsize + 1);
923        }
924        if (uncompressedFile) {
925            uncompressedFile->release();
926            *file = 0;
927        }
928    }
929    return result;
930}
931
932bool uncompressModule(OSData *compData, /* out */ OSData ** file) {
933
934    const MkextEntryInfo *info = (const MkextEntryInfo *) compData->getBytesNoCopy();
935
936    return uncompressFile((u_int8_t *) info->base_address,
937			  info->fileinfo, file);
938}
939
940
941/*********************************************************************
942* Does the work of pulling extensions out of an mkext archive located
943* in memory.
944*********************************************************************/
945bool extractExtensionsFromArchive(const MemoryMapFileInfo * mkext_file_info,
946    bool vaddr,
947    OSDictionary * extensions) {
948
949    bool result = true;
950
951    u_int8_t     * crc_address = 0;
952    u_int32_t      checksum;
953    mkext_header * mkext_data = 0;   // don't free
954    mkext_kext   * onekext_data = 0; // don't free
955    mkext_file   * plist_file = 0;   // don't free
956    mkext_file   * module_file = 0;  // don't free
957    kmod_info_t  * loaded_kmod = 0;  // must free
958
959    OSData       * driverPlistDataObject = 0; // must release
960    OSDictionary * driverPlist = 0;  // must release
961    OSData       * driverCode = 0;   // must release
962    OSDictionary * driverDict = 0;   // must release
963    OSString     * moduleName = 0;   // don't release
964    OSString     * errorString = NULL;  // must release
965
966    OSData         * moduleInfo = 0;  // must release
967    MkextEntryInfo   module_info;
968
969    IORegistryEntry * root;
970    OSData * checksumObj;
971
972    if (vaddr) {
973	// addExtensionsFromArchive passes a kernel virtual address
974	mkext_data = (mkext_header *)mkext_file_info->paddr;
975    } else {
976#if defined (__ppc__) || defined (__arm__)
977	mkext_data = (mkext_header *)ml_static_ptovirt(mkext_file_info->paddr);
978#elif defined (__i386__)
979	mkext_data = (mkext_header *)ml_boot_ptovirt(mkext_file_info->paddr);
980#else
981#error unsupported architecture
982#endif
983    }
984
985    if (OSSwapBigToHostInt32(mkext_data->magic) != MKEXT_MAGIC ||
986        OSSwapBigToHostInt32(mkext_data->signature) != MKEXT_SIGN) {
987        IOLog("Error: Extension archive has invalid magic or signature.\n");
988        LOG_DELAY();
989        result = false;
990        goto finish;
991    }
992
993    if (OSSwapBigToHostInt32(mkext_data->length) != mkext_file_info->length) {
994        IOLog("Error: Mismatch between extension archive & "
995            "recorded length.\n");
996        LOG_DELAY();
997        result = false;
998        goto finish;
999    }
1000
1001    crc_address = (u_int8_t *)&mkext_data->version;
1002    checksum = adler32(crc_address,
1003        (unsigned int)mkext_data +
1004        OSSwapBigToHostInt32(mkext_data->length) - (unsigned int)crc_address);
1005
1006    if (OSSwapBigToHostInt32(mkext_data->adler32) != checksum) {
1007        IOLog("Error: Extension archive has a bad checksum.\n");
1008        LOG_DELAY();
1009        result = false;
1010        goto finish;
1011    }
1012
1013    root = IORegistryEntry::getRegistryRoot();
1014    assert(root);
1015    checksumObj = OSData::withBytes((void *)&checksum,
1016        sizeof(checksum));
1017    assert(checksumObj);
1018    if (checksumObj) {
1019        root->setProperty(kIOStartupMkextCRC, checksumObj);
1020        checksumObj->release();
1021    }
1022
1023   /* If the MKEXT archive isn't fat, check that the CPU type & subtype
1024    * match that of the running kernel.
1025    */
1026    if (OSSwapBigToHostInt32(mkext_data->cputype) != (UInt32)CPU_TYPE_ANY) {
1027        kern_return_t          kresult = KERN_FAILURE;
1028        host_basic_info_data_t hostinfo;
1029        host_info_t            hostinfo_ptr = (host_info_t)&hostinfo;
1030        mach_msg_type_number_t count = sizeof(hostinfo)/sizeof(integer_t);
1031
1032        kresult = host_info((host_t)1, HOST_BASIC_INFO,
1033            hostinfo_ptr, &count);
1034        if (kresult != KERN_SUCCESS) {
1035            IOLog("Error: Couldn't get current host info.\n");
1036            LOG_DELAY();
1037            result = false;
1038            goto finish;
1039        }
1040        if ((UInt32)hostinfo.cpu_type !=
1041            OSSwapBigToHostInt32(mkext_data->cputype)) {
1042
1043            IOLog("Error: Extension archive doesn't contain software "
1044                "for this computer's CPU type.\n");
1045            LOG_DELAY();
1046            result = false;
1047            goto finish;
1048        }
1049        if (!grade_binary(OSSwapBigToHostInt32(mkext_data->cputype),
1050			  OSSwapBigToHostInt32(mkext_data->cpusubtype))) {
1051            IOLog("Error: Extension archive doesn't contain software "
1052                "for this computer's CPU subtype.\n");
1053            LOG_DELAY();
1054            result = false;
1055            goto finish;
1056        }
1057    }
1058
1059    for (unsigned int i = 0;
1060         i < OSSwapBigToHostInt32(mkext_data->numkexts);
1061         i++) {
1062
1063        if (loaded_kmod) {
1064            kfree(loaded_kmod, sizeof(kmod_info_t));
1065            loaded_kmod = 0;
1066        }
1067
1068        if (driverPlistDataObject) {
1069            kmem_free(kernel_map,
1070                (unsigned int)driverPlistDataObject->getBytesNoCopy(),
1071                driverPlistDataObject->getLength());
1072
1073            driverPlistDataObject->release();
1074            driverPlistDataObject = NULL;
1075        }
1076        if (driverPlist) {
1077            driverPlist->release();
1078            driverPlist = NULL;
1079        }
1080        if (driverCode) {
1081            driverCode->release();
1082            driverCode = NULL;
1083        }
1084        if (driverDict) {
1085            driverDict->release();
1086            driverDict = NULL;
1087        }
1088        if (errorString) {
1089            errorString->release();
1090            errorString = NULL;
1091        }
1092
1093        onekext_data = &mkext_data->kext[i];
1094        plist_file = &onekext_data->plist;
1095        module_file = &onekext_data->module;
1096
1097        if (!uncompressFile((u_int8_t *)mkext_data, plist_file,
1098            &driverPlistDataObject)) {
1099
1100            IOLog("Error: couldn't uncompress plist file "
1101                "from multikext archive entry %d.\n", i);
1102            LOG_DELAY();
1103            continue;
1104        }
1105
1106        if (!driverPlistDataObject) {
1107            IOLog("Error: No property list present "
1108                "for multikext archive entry %d.\n", i);
1109            LOG_DELAY();
1110            continue;
1111        } else {
1112            driverPlist = OSDynamicCast(OSDictionary,
1113                OSUnserializeXML(
1114                    (const char *)driverPlistDataObject->getBytesNoCopy(),
1115                    &errorString));
1116            if (!driverPlist) {
1117                IOLog("Error: Couldn't read XML property list "
1118                      "for multikext archive entry %d.\n", i);
1119                LOG_DELAY();
1120                if (errorString) {
1121                    IOLog("XML parse error: %s.\n",
1122                        errorString->getCStringNoCopy());
1123                    LOG_DELAY();
1124                }
1125                continue;
1126            }
1127
1128            if (!validateExtensionDict(driverPlist, i)) {
1129                // validateExtensionsDict() logs an error
1130                continue;
1131            }
1132
1133        }
1134
1135       /* Get the extension's module name. This is used to record
1136        * the extension.
1137        */
1138        moduleName = OSDynamicCast(OSString,
1139            driverPlist->getObject("CFBundleIdentifier"));  // do not release
1140        if (!moduleName) {
1141            IOLog("Error: Multikext archive entry %d has "
1142                "no \"CFBundleIdentifier\" property.\n", i);
1143            LOG_DELAY();
1144            continue; // assume a kext config error & continue
1145        }
1146
1147       /* Check if kmod is already loaded and is a real loadable one (has
1148        * an address).
1149        */
1150        loaded_kmod = kmod_lookupbyname_locked(moduleName->getCStringNoCopy());
1151        if (loaded_kmod && loaded_kmod->address) {
1152            IOLog("Skipping new extension \"%s\"; an extension named "
1153                "\"%s\" is already loaded.\n",
1154                moduleName->getCStringNoCopy(),
1155                loaded_kmod->name);
1156            continue;
1157        }
1158
1159
1160        driverDict = OSDictionary::withCapacity(2);
1161        if (!driverDict) {
1162            IOLog("Error: Couldn't allocate dictionary "
1163                  "for multikext archive entry %d.\n", i);
1164            LOG_DELAY();
1165            result = false;
1166            goto finish;
1167        }
1168
1169        driverDict->setObject("plist", driverPlist);
1170
1171       /*****
1172        * Prepare an entry to hold the mkext entry info for the
1173        * compressed binary module, if there is one. If all four fields
1174        * of the module entry are zero, there isn't one.
1175        */
1176        if (!(loaded_kmod && loaded_kmod->address) && (OSSwapBigToHostInt32(module_file->offset) ||
1177            OSSwapBigToHostInt32(module_file->compsize) ||
1178            OSSwapBigToHostInt32(module_file->realsize) ||
1179            OSSwapBigToHostInt32(module_file->modifiedsecs))) {
1180
1181            moduleInfo = OSData::withCapacity(sizeof(MkextEntryInfo));
1182            if (!moduleInfo) {
1183                IOLog("Error: Couldn't allocate data object "
1184                      "for multikext archive entry %d.\n", i);
1185                LOG_DELAY();
1186                result = false;
1187                goto finish;
1188            }
1189
1190            module_info.base_address = (vm_address_t)mkext_data;
1191            module_info.fileinfo = module_file;
1192
1193            if (!moduleInfo->appendBytes(&module_info, sizeof(module_info))) {
1194                IOLog("Error: Couldn't record info "
1195                      "for multikext archive entry %d.\n", i);
1196                LOG_DELAY();
1197                result = false;
1198                goto finish;
1199            }
1200
1201            driverDict->setObject("compressedCode", moduleInfo);
1202        }
1203
1204        OSDictionary * incumbentExt = OSDynamicCast(OSDictionary,
1205            extensions->getObject(moduleName));
1206
1207        if (!incumbentExt) {
1208            extensions->setObject(moduleName, driverDict);
1209        } else {
1210            OSDictionary * mostRecentExtension =
1211                compareExtensionVersions(incumbentExt, driverDict);
1212
1213            if (mostRecentExtension == incumbentExt) {
1214                /* Do nothing, we've got the most recent. */
1215            } else if (mostRecentExtension == driverDict) {
1216                if (!extensions->setObject(moduleName, driverDict)) {
1217
1218                   /* This is a fatal error, so bail.
1219                    */
1220                    IOLog("extractExtensionsFromArchive(): Failed to add "
1221                        "identifier %s\n",
1222                        moduleName->getCStringNoCopy());
1223                    LOG_DELAY();
1224                    result = false;
1225                    goto finish;
1226                }
1227            } else /* should be NULL */ {
1228
1229               /* This is a nonfatal error, so continue.
1230                */
1231                IOLog("extractExtensionsFromArchive(): Error comparing "
1232                    "versions of duplicate extensions %s.\n",
1233                    moduleName->getCStringNoCopy());
1234                LOG_DELAY();
1235                continue;
1236            }
1237        }
1238    }
1239
1240finish:
1241
1242    if (loaded_kmod) kfree(loaded_kmod, sizeof(kmod_info_t));
1243    if (driverPlistDataObject) {
1244        kmem_free(kernel_map,
1245            (unsigned int)driverPlistDataObject->getBytesNoCopy(),
1246            driverPlistDataObject->getLength());
1247        driverPlistDataObject->release();
1248    }
1249    if (driverPlist) driverPlist->release();
1250    if (driverCode)  driverCode->release();
1251    if (moduleInfo)  moduleInfo->release();
1252    if (driverDict)  driverDict->release();
1253    if (errorString) errorString->release();
1254
1255    return result;
1256}
1257
1258/*********************************************************************
1259*
1260*********************************************************************/
1261bool readExtensions(OSDictionary * propertyDict,
1262    const char * memory_map_name,
1263    OSDictionary * extensions) {
1264
1265    bool result = true;
1266    OSData * mkextDataObject = 0;      // don't release
1267    const MemoryMapFileInfo * mkext_file_info = 0; // don't free
1268
1269    mkextDataObject = OSDynamicCast(OSData,
1270        propertyDict->getObject(memory_map_name));
1271    // don't release mkextDataObject
1272
1273    if (!mkextDataObject) {
1274        IOLog("Error: No mkext data object "
1275            "for device tree entry \"%s\".\n",
1276            memory_map_name);
1277        LOG_DELAY();
1278        result = false;
1279        goto finish;
1280    }
1281
1282    mkext_file_info = (const MemoryMapFileInfo *)mkextDataObject->getBytesNoCopy();
1283    if (!mkext_file_info) {
1284        result = false;
1285        goto finish;
1286    }
1287
1288    result = extractExtensionsFromArchive(mkext_file_info, false /*physical*/, extensions);
1289
1290finish:
1291
1292    if (!result && extensions) {
1293        extensions->flushCollection();
1294    }
1295
1296    return result;
1297}
1298
1299
1300/*********************************************************************
1301* Adds the personalities for an extensions dictionary to the global
1302* IOCatalogue.
1303*********************************************************************/
1304bool addPersonalities(OSDictionary * extensions) {
1305    bool result = true;
1306    OSCollectionIterator * keyIterator = NULL;  // must release
1307    OSString             * key;          // don't release
1308    OSDictionary * driverDict = NULL;    // don't release
1309    OSDictionary * driverPlist = NULL;   // don't release
1310    OSDictionary * thisDriverPersonalities = NULL;  // don't release
1311    OSArray      * allDriverPersonalities = NULL;   // must release
1312
1313    allDriverPersonalities = OSArray::withCapacity(1);
1314    if (!allDriverPersonalities) {
1315        IOLog("Error: Couldn't allocate personality dictionary.\n");
1316        LOG_DELAY();
1317        result = false;
1318        goto finish;
1319    }
1320
1321   /* Record all personalities found so that they can be
1322    * added to the catalogue.
1323    * Note: Not all extensions have personalities.
1324    */
1325
1326    keyIterator = OSCollectionIterator::withCollection(extensions);
1327    if (!keyIterator) {
1328        IOLog("Error: Couldn't allocate iterator to record personalities.\n");
1329        LOG_DELAY();
1330        result = false;
1331        goto finish;
1332    }
1333
1334    while ( ( key = OSDynamicCast(OSString,
1335              keyIterator->getNextObject() ))) {
1336
1337        driverDict = OSDynamicCast(OSDictionary,
1338            extensions->getObject(key));
1339        driverPlist = OSDynamicCast(OSDictionary,
1340            driverDict->getObject("plist"));
1341        thisDriverPersonalities = OSDynamicCast(OSDictionary,
1342            driverPlist->getObject("IOKitPersonalities"));
1343
1344        if (thisDriverPersonalities) {
1345            OSCollectionIterator * pIterator;
1346            OSString * locakKey;
1347            pIterator = OSCollectionIterator::withCollection(
1348                thisDriverPersonalities);
1349            if (!pIterator) {
1350                IOLog("Error: Couldn't allocate iterator "
1351                    "to record extension personalities.\n");
1352                LOG_DELAY();
1353                continue;
1354            }
1355            while ( (locakKey = OSDynamicCast(OSString,
1356                     pIterator->getNextObject())) ) {
1357
1358                OSDictionary * personality = OSDynamicCast(
1359                    OSDictionary,
1360                    thisDriverPersonalities->getObject(locakKey));
1361                if (personality) {
1362                    allDriverPersonalities->setObject(personality);
1363                }
1364            }
1365            pIterator->release();
1366        }
1367    } /* extract personalities */
1368
1369
1370   /* Add all personalities found to the IOCatalogue,
1371    * but don't start matching.
1372    */
1373    gIOCatalogue->addDrivers(allDriverPersonalities, false);
1374
1375finish:
1376
1377    if (allDriverPersonalities) allDriverPersonalities->release();
1378    if (keyIterator) keyIterator->release();
1379
1380    return result;
1381}
1382
1383
1384/*********************************************************************
1385* Called from IOCatalogue to add extensions from an mkext archive.
1386* This function makes a copy of the mkext object passed in because
1387* the device tree support code dumps it after calling us (indirectly
1388* through the IOCatalogue).
1389*********************************************************************/
1390bool addExtensionsFromArchive(OSData * mkextDataObject) {
1391    bool result = true;
1392
1393    OSDictionary * startupExtensions = NULL;  // don't release
1394    OSArray      * bootLoaderObjects = NULL;  // don't release
1395    OSDictionary * extensions = NULL;         // must release
1396    MemoryMapFileInfo mkext_file_info;
1397    OSCollectionIterator * keyIterator = NULL;   // must release
1398    OSString             * key = NULL;           // don't release
1399
1400    startupExtensions = getStartupExtensions();
1401    if (!startupExtensions) {
1402        IOLog("Can't record extension archive; there is no"
1403            " extensions dictionary.\n");
1404        LOG_DELAY();
1405        result = false;
1406        goto finish;
1407    }
1408
1409    bootLoaderObjects = getBootLoaderObjects();
1410    if (! bootLoaderObjects) {
1411        IOLog("Error: Couldn't allocate array to hold temporary objects.\n");
1412        LOG_DELAY();
1413        result = false;
1414        goto finish;
1415    }
1416
1417    extensions = OSDictionary::withCapacity(2);
1418    if (!extensions) {
1419        IOLog("Error: Couldn't allocate dictionary to unpack "
1420            "extension archive.\n");
1421        LOG_DELAY();
1422        result = false;
1423        goto finish;
1424    }
1425
1426    mkext_file_info.paddr = (UInt32)mkextDataObject->getBytesNoCopy();
1427    mkext_file_info.length = mkextDataObject->getLength();
1428
1429   /* Save the local mkext data object so that we can deallocate it later.
1430    */
1431    bootLoaderObjects->setObject(mkextDataObject);
1432
1433    result = extractExtensionsFromArchive(&mkext_file_info, true /*virtual*/, extensions);
1434    if (!result) {
1435        IOLog("Error: Failed to extract extensions from archive.\n");
1436        LOG_DELAY();
1437        result = false;
1438        goto finish;
1439    }
1440
1441    result = mergeExtensionDictionaries(startupExtensions, extensions);
1442    if (!result) {
1443        IOLog("Error: Failed to merge new extensions into existing set.\n");
1444        LOG_DELAY();
1445        goto finish;
1446    }
1447
1448    result = addPersonalities(extensions);
1449    if (!result) {
1450        IOLog("Error: Failed to add personalities for extensions extracted "
1451            "from archive.\n");
1452        LOG_DELAY();
1453        result = false;
1454        goto finish;
1455    }
1456
1457finish:
1458
1459    if (!result) {
1460        IOLog("Error: Failed to record extensions from archive.\n");
1461        LOG_DELAY();
1462    } else {
1463        keyIterator = OSCollectionIterator::withCollection(
1464            extensions);
1465
1466        if (keyIterator) {
1467            while ( (key = OSDynamicCast(OSString,
1468                     keyIterator->getNextObject())) ) {
1469
1470                IOLog("Added extension \"%s\" from archive.\n",
1471                    key->getCStringNoCopy());
1472                LOG_DELAY();
1473            }
1474            keyIterator->release();
1475        }
1476    }
1477
1478    if (extensions) extensions->release();
1479
1480    return result;
1481}
1482
1483
1484/*********************************************************************
1485* This function builds dictionaries for the startup extensions
1486* put into memory by bootx, recording each in the startup extensions
1487* dictionary. The dictionary format is this:
1488*
1489* {
1490*     "plist" = (the extension's Info.plist as an OSDictionary)
1491*     "code"  = (an OSData containing the executable file)
1492* }
1493*
1494* This function returns true if any extensions were found and
1495* recorded successfully, or if there are no start extensions,
1496* and false if an unrecoverable error occurred. An error reading
1497* a single extension is not considered fatal, and this function
1498* will simply skip the problematic extension to try the next one.
1499*********************************************************************/
1500
1501bool recordStartupExtensions(void) {
1502    bool result = true;
1503    OSDictionary         * startupExtensions = NULL; // must release
1504    OSDictionary         * existingExtensions = NULL; // don't release
1505    OSDictionary         * mkextExtensions = NULL;   // must release
1506    IORegistryEntry      * bootxMemoryMap = NULL;    // must release
1507    OSDictionary         * propertyDict = NULL;      // must release
1508    OSCollectionIterator * keyIterator = NULL;       // must release
1509    OSString             * key = NULL;               // don't release
1510
1511    OSDictionary * newDriverDict = NULL;  // must release
1512    OSDictionary * driverPlist = NULL; // don't release
1513
1514    struct section * infosect;
1515    struct section * symsect;
1516    unsigned int     prelinkedCount = 0;
1517
1518    existingExtensions = getStartupExtensions();
1519    if (!existingExtensions) {
1520        IOLog("Error: There is no dictionary for startup extensions.\n");
1521        LOG_DELAY();
1522        result = false;
1523        goto finish;
1524    }
1525
1526    startupExtensions = OSDictionary::withCapacity(1);
1527    if (!startupExtensions) {
1528        IOLog("Error: Couldn't allocate dictionary "
1529            "to record startup extensions.\n");
1530        LOG_DELAY();
1531        result = false;
1532        goto finish;
1533    }
1534
1535    // --
1536    // add any prelinked modules as startup extensions
1537
1538    infosect   = getsectbyname("__PRELINK", "__info");
1539    symsect    = getsectbyname("__PRELINK", "__symtab");
1540    if (infosect && infosect->addr && infosect->size
1541     && symsect && symsect->addr && symsect->size) do
1542    {
1543	gIOPrelinkedModules = OSDynamicCast(OSArray,
1544	    OSUnserializeXML((const char *) infosect->addr, NULL));
1545
1546	if (!gIOPrelinkedModules)
1547	    break;
1548	for( unsigned int idx = 0;
1549		(propertyDict = OSDynamicCast(OSDictionary, gIOPrelinkedModules->getObject(idx)));
1550		idx++)
1551	{
1552	    enum { kPrelinkReservedCount = 4 };
1553
1554           /* Get the extension's module name. This is used to record
1555            * the extension. Do *not* release the moduleName.
1556            */
1557            OSString * moduleName = OSDynamicCast(OSString,
1558                propertyDict->getObject("CFBundleIdentifier"));
1559            if (!moduleName) {
1560                IOLog("Error: Prelinked module entry has "
1561                    "no \"CFBundleIdentifier\" property.\n");
1562                LOG_DELAY();
1563                continue;
1564            }
1565
1566           /* Add the kext, & its plist.
1567            */
1568	    newDriverDict = OSDictionary::withCapacity(4);
1569	    assert(newDriverDict);
1570	    newDriverDict->setObject("plist", propertyDict);
1571	    startupExtensions->setObject(moduleName, newDriverDict);
1572	    newDriverDict->release();
1573
1574           /* Add the code if present.
1575            */
1576	    OSData * data = OSDynamicCast(OSData, propertyDict->getObject("OSBundlePrelink"));
1577            if (data) {
1578		if (data->getLength() < (kPrelinkReservedCount * sizeof(UInt32))) {
1579		    IOLog("Error: Prelinked module entry has "
1580			"invalid \"OSBundlePrelink\" property.\n");
1581		    LOG_DELAY();
1582		    continue;
1583		}
1584		const UInt32 * prelink;
1585		prelink = (const UInt32 *) data->getBytesNoCopy();
1586		kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
1587		// end of "file" is end of symbol sect
1588		data = OSData::withBytesNoCopy((void *) kmod_info->address,
1589			    symsect->addr + symsect->size - kmod_info->address);
1590		newDriverDict->setObject("code", data);
1591		data->release();
1592		prelinkedCount++;
1593                continue;
1594            }
1595           /* Add the symbols if present.
1596            */
1597	    OSNumber * num = OSDynamicCast(OSNumber, propertyDict->getObject("OSBundlePrelinkSymbols"));
1598            if (num) {
1599		UInt32 offset = num->unsigned32BitValue();
1600		data = OSData::withBytesNoCopy((void *) (symsect->addr + offset), symsect->size - offset);
1601		newDriverDict->setObject("code", data);
1602		data->release();
1603		prelinkedCount++;
1604                continue;
1605	    }
1606	}
1607	if (gIOPrelinkedModules)
1608	    IOLog("%d prelinked modules\n", prelinkedCount);
1609
1610	// free __info
1611	vm_offset_t
1612	virt = ml_static_ptovirt(infosect->addr);
1613	if( virt) {
1614	    ml_static_mfree(virt, infosect->size);
1615	}
1616	newDriverDict = NULL;
1617    }
1618    while (false);
1619    // --
1620
1621    bootxMemoryMap =
1622        IORegistryEntry::fromPath(
1623            "/chosen/memory-map", // path
1624            gIODTPlane            // plane
1625            );
1626    // return value is retained so be sure to release it
1627
1628    if (!bootxMemoryMap) {
1629        IOLog("Error: Couldn't read booter memory map.\n");
1630        LOG_DELAY();
1631        result = false;
1632        goto finish;
1633    }
1634
1635    propertyDict = bootxMemoryMap->dictionaryWithProperties();
1636    if (!propertyDict) {
1637        IOLog("Error: Couldn't get property dictionary "
1638            "from memory map.\n");
1639        LOG_DELAY();
1640        result = false;
1641        goto finish;
1642    }
1643
1644    keyIterator = OSCollectionIterator::withCollection(propertyDict);
1645    if (!keyIterator) {
1646        IOLog("Error: Couldn't allocate iterator for driver images.\n");
1647        LOG_DELAY();
1648        result = false;
1649        goto finish;
1650    }
1651
1652    while ( (key = OSDynamicCast(OSString,
1653             keyIterator->getNextObject())) ) {
1654       /* Clear newDriverDict & mkextExtensions upon entry to the loop,
1655        * handling both successful and unsuccessful iterations.
1656        */
1657        if (newDriverDict) {
1658            newDriverDict->release();
1659            newDriverDict = NULL;
1660        }
1661        if (mkextExtensions) {
1662            mkextExtensions->release();
1663            mkextExtensions = NULL;
1664        }
1665
1666        const char * keyValue = key->getCStringNoCopy();
1667
1668        if ( !strncmp(keyValue, BOOTX_KEXT_PREFIX,
1669              strlen(BOOTX_KEXT_PREFIX)) ) {
1670
1671           /* Read the extension from the bootx-supplied memory.
1672            */
1673            newDriverDict = readExtension(propertyDict, keyValue);
1674            if (!newDriverDict) {
1675                IOLog("Error: Couldn't read data "
1676                    "for device tree entry \"%s\".\n", keyValue);
1677                LOG_DELAY();
1678                continue;
1679            }
1680
1681
1682           /* Preprare to record the extension by getting its info plist.
1683            */
1684            driverPlist = OSDynamicCast(OSDictionary,
1685                newDriverDict->getObject("plist"));
1686            if (!driverPlist) {
1687                IOLog("Error: Extension in device tree entry \"%s\" "
1688                    "has no property list.\n", keyValue);
1689                LOG_DELAY();
1690                continue;
1691            }
1692
1693
1694           /* Get the extension's module name. This is used to record
1695            * the extension. Do *not* release the moduleName.
1696            */
1697            OSString * moduleName = OSDynamicCast(OSString,
1698                driverPlist->getObject("CFBundleIdentifier"));
1699            if (!moduleName) {
1700                IOLog("Error: Device tree entry \"%s\" has "
1701                    "no \"CFBundleIdentifier\" property.\n", keyValue);
1702                LOG_DELAY();
1703                continue;
1704            }
1705
1706
1707           /* All has gone well so far, so record the extension under
1708            * its module name, checking for an existing duplicate.
1709            *
1710            * Do not release moduleName, as it's part of the extension's
1711            * plist.
1712            */
1713            OSDictionary * incumbentExt = OSDynamicCast(OSDictionary,
1714                startupExtensions->getObject(moduleName));
1715
1716            if (!incumbentExt) {
1717                startupExtensions->setObject(moduleName, newDriverDict);
1718            } else {
1719                OSDictionary * mostRecentExtension =
1720                    compareExtensionVersions(incumbentExt, newDriverDict);
1721
1722                if (mostRecentExtension == incumbentExt) {
1723                    /* Do nothing, we've got the most recent. */
1724                } else if (mostRecentExtension == newDriverDict) {
1725                    if (!startupExtensions->setObject(moduleName,
1726                         newDriverDict)) {
1727
1728                       /* This is a fatal error, so bail.
1729                        */
1730                        IOLog("recordStartupExtensions(): Failed to add "
1731                            "identifier %s\n",
1732                            moduleName->getCStringNoCopy());
1733                        LOG_DELAY();
1734                        result = false;
1735                        goto finish;
1736                    }
1737                } else /* should be NULL */ {
1738
1739                   /* This is a nonfatal error, so continue.
1740                    */
1741                    IOLog("recordStartupExtensions(): Error comparing "
1742                        "versions of duplicate extensions %s.\n",
1743                        moduleName->getCStringNoCopy());
1744                    LOG_DELAY();
1745                    continue;
1746                }
1747            }
1748
1749
1750        } else if ( !strncmp(keyValue, BOOTX_MULTIKEXT_PREFIX,
1751              strlen(BOOTX_MULTIKEXT_PREFIX)) ) {
1752
1753            mkextExtensions = OSDictionary::withCapacity(10);
1754            if (!mkextExtensions) {
1755                IOLog("Error: Couldn't allocate dictionary to unpack "
1756                    "multi-extension archive.\n");
1757                LOG_DELAY();
1758                result = false;
1759                goto finish;  // allocation failure is fatal for this routine
1760            }
1761            if (!readExtensions(propertyDict, keyValue, mkextExtensions)) {
1762                IOLog("Error: Couldn't unpack multi-extension archive.\n");
1763                LOG_DELAY();
1764                continue;
1765            } else {
1766                if (!mergeExtensionDictionaries(startupExtensions,
1767                     mkextExtensions)) {
1768
1769                    IOLog("Error: Failed to merge new extensions into "
1770                        "existing set.\n");
1771                    LOG_DELAY();
1772                    result = false;
1773                    goto finish;  // merge error is fatal for this routine
1774                }
1775            }
1776        }
1777
1778        // Do not release key.
1779
1780    } /* while ( (key = OSDynamicCast(OSString, ...) ) ) */
1781
1782    if (!mergeExtensionDictionaries(existingExtensions, startupExtensions)) {
1783        IOLog("Error: Failed to merge new extensions into existing set.\n");
1784        LOG_DELAY();
1785        result = false;
1786        goto finish;
1787    }
1788
1789    result = addPersonalities(startupExtensions);
1790    if (!result) {
1791        IOLog("Error: Failed to add personalities for extensions extracted "
1792            "from archive.\n");
1793        LOG_DELAY();
1794        result = false;
1795        goto finish;
1796    }
1797
1798finish:
1799
1800    // reused so clear first!
1801    if (keyIterator) {
1802        keyIterator->release();
1803        keyIterator = 0;
1804    }
1805
1806    if (!result) {
1807        IOLog("Error: Failed to record startup extensions.\n");
1808        LOG_DELAY();
1809    } else {
1810#if DEBUG
1811        keyIterator = OSCollectionIterator::withCollection(
1812            startupExtensions);
1813
1814        if (keyIterator) {
1815            while ( (key = OSDynamicCast(OSString,
1816                     keyIterator->getNextObject())) ) {
1817
1818                IOLog("Found extension \"%s\".\n",
1819                    key->getCStringNoCopy());
1820                LOG_DELAY();
1821            }
1822            keyIterator->release();
1823            keyIterator = 0;
1824        }
1825#endif /* DEBUG */
1826    }
1827
1828    if (newDriverDict)     newDriverDict->release();
1829    if (propertyDict)      propertyDict->release();
1830    if (bootxMemoryMap)    bootxMemoryMap->release();
1831    if (mkextExtensions)   mkextExtensions->release();
1832    if (startupExtensions) startupExtensions->release();
1833
1834    return result;
1835}
1836
1837
1838/*********************************************************************
1839* This function removes an entry from the dictionary of startup
1840* extensions. It's used when an extension can't be loaded, for
1841* whatever reason. For drivers, this allows another matching driver
1842* to be loaded, so that, for example, a driver for the root device
1843* can be found.
1844*********************************************************************/
1845void removeStartupExtension(const char * extensionName) {
1846    OSDictionary * startupExtensions = NULL;      // don't release
1847    OSDictionary * extensionDict = NULL;          // don't release
1848    OSDictionary * extensionPlist = NULL;         // don't release
1849    OSDictionary * extensionPersonalities = NULL; // don't release
1850    OSDictionary * personality = NULL;            // don't release
1851    OSCollectionIterator * keyIterator = NULL;    // must release
1852    OSString     * key = NULL;                    // don't release
1853
1854    startupExtensions = getStartupExtensions();
1855    if (!startupExtensions) goto finish;
1856
1857
1858   /* Find the extension's entry in the dictionary of
1859    * startup extensions.
1860    */
1861    extensionDict = OSDynamicCast(OSDictionary,
1862        startupExtensions->getObject(extensionName));
1863    if (!extensionDict) goto finish;
1864
1865    extensionPlist = OSDynamicCast(OSDictionary,
1866        extensionDict->getObject("plist"));
1867    if (!extensionPlist) goto finish;
1868
1869    extensionPersonalities = OSDynamicCast(OSDictionary,
1870        extensionPlist->getObject("IOKitPersonalities"));
1871    if (!extensionPersonalities) goto finish;
1872
1873   /* If it was there, remove it from the catalogue proper
1874    * by calling removeDrivers(). Pass true for the second
1875    * argument to trigger a new round of matching, and
1876    * then remove the extension from the dictionary of startup
1877    * extensions.
1878    */
1879    keyIterator = OSCollectionIterator::withCollection(
1880        extensionPersonalities);
1881    if (!keyIterator) {
1882        IOLog("Error: Couldn't allocate iterator to scan"
1883            " personalities for %s.\n", extensionName);
1884        LOG_DELAY();
1885    }
1886
1887    while ((key = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
1888        personality = OSDynamicCast(OSDictionary,
1889            extensionPersonalities->getObject(key));
1890
1891
1892        if (personality) {
1893            gIOCatalogue->removeDrivers(personality, true);
1894        }
1895    }
1896
1897    startupExtensions->removeObject(extensionName);
1898
1899finish:
1900
1901    if (keyIterator) keyIterator->release();
1902    return;
1903}
1904
1905/*********************************************************************
1906* FIXME: This function invalidates the globals gStartupExtensions and
1907* FIXME: ...gBootLoaderObjects without setting them to NULL. Since
1908* FIXME: ...the code itself is immediately unloaded, there may not be
1909* FIXME: ...any reason to worry about that!
1910*********************************************************************/
1911void clearStartupExtensionsAndLoaderInfo(void)
1912{
1913    OSDictionary * startupExtensions = NULL;  // must release
1914    OSArray      * bootLoaderObjects = NULL;  // must release
1915
1916    IORegistryEntry      * bootxMemoryMap = NULL;    // must release
1917    OSDictionary         * propertyDict = NULL;      // must release
1918    OSCollectionIterator * keyIterator = NULL;       // must release
1919    OSString             * key = NULL;               // don't release
1920
1921   /*****
1922    * Drop any temporarily held data objects.
1923    */
1924    bootLoaderObjects = getBootLoaderObjects();
1925    if (bootLoaderObjects) {
1926        bootLoaderObjects->release();
1927    }
1928
1929   /****
1930    * If any "code" entries in driver dictionaries are accompanied
1931    * by "compressedCode" entries, then those data objects were
1932    * created based of of kmem_alloc()'ed memory, which must be
1933    * freed specially.
1934    */
1935    startupExtensions = getStartupExtensions();
1936    if (startupExtensions) {
1937        keyIterator =
1938            OSCollectionIterator::withCollection(startupExtensions);
1939        if (!keyIterator) {
1940            IOLog("Error: Couldn't allocate iterator for startup "
1941                "extensions.\n");
1942            LOG_DELAY();
1943            goto memory_map;  // bail to the memory_map label
1944        }
1945
1946        while ( (key = OSDynamicCast(OSString,
1947                 keyIterator->getNextObject())) ) {
1948
1949            OSDictionary * driverDict = 0;
1950            OSData * codeData = 0;
1951
1952            driverDict = OSDynamicCast(OSDictionary,
1953                startupExtensions->getObject(key));
1954            if (driverDict) {
1955                codeData = OSDynamicCast(OSData,
1956                    driverDict->getObject("code"));
1957
1958                if (codeData &&
1959                    driverDict->getObject("compressedCode")) {
1960
1961                    kmem_free(kernel_map,
1962                       (unsigned int)codeData->getBytesNoCopy(),
1963                        codeData->getLength());
1964                }
1965            }
1966        }
1967
1968        keyIterator->release();
1969        startupExtensions->release();
1970    }
1971
1972memory_map:
1973
1974   /****
1975    * Go through the device tree's memory map and remove any driver
1976    * data entries.
1977    */
1978    bootxMemoryMap =
1979        IORegistryEntry::fromPath(
1980            "/chosen/memory-map", // path
1981            gIODTPlane            // plane
1982            );
1983    // return value is retained so be sure to release it
1984
1985    if (!bootxMemoryMap) {
1986        IOLog("Error: Couldn't read booter memory map.\n");
1987        LOG_DELAY();
1988        goto finish;
1989    }
1990
1991    propertyDict = bootxMemoryMap->dictionaryWithProperties();
1992    if (!propertyDict) {
1993        IOLog("Error: Couldn't get property dictionary "
1994            "from memory map.\n");
1995        LOG_DELAY();
1996        goto finish;
1997    }
1998
1999    keyIterator = OSCollectionIterator::withCollection(propertyDict);
2000    if (!keyIterator) {
2001        IOLog("Error: Couldn't allocate iterator for driver images.\n");
2002        LOG_DELAY();
2003        goto finish;
2004    }
2005
2006    while ( (key = OSDynamicCast(OSString,
2007             keyIterator->getNextObject())) ) {
2008
2009        const char * keyValue = key->getCStringNoCopy();
2010
2011        if ( !strncmp(keyValue, BOOTX_KEXT_PREFIX,
2012                  strlen(BOOTX_KEXT_PREFIX)) ||
2013             !strncmp(keyValue, BOOTX_MULTIKEXT_PREFIX,
2014                  strlen(BOOTX_MULTIKEXT_PREFIX)) ) {
2015
2016            OSData            * bootxDriverDataObject = NULL;
2017            const MemoryMapFileInfo * driverInfo = 0;
2018
2019            bootxDriverDataObject = OSDynamicCast(OSData,
2020                propertyDict->getObject(keyValue));
2021            // don't release bootxDriverDataObject
2022
2023            if (!bootxDriverDataObject) {
2024                continue;
2025            }
2026            driverInfo = (const MemoryMapFileInfo *)
2027                bootxDriverDataObject->getBytesNoCopy(0,
2028                sizeof(MemoryMapFileInfo));
2029            IODTFreeLoaderInfo((char *)keyValue,
2030                (void *)driverInfo->paddr,
2031                (int)driverInfo->length);
2032        }
2033    }
2034
2035finish:
2036    if (bootxMemoryMap) bootxMemoryMap->release();
2037    if (propertyDict)   propertyDict->release();
2038    if (keyIterator)    keyIterator->release();
2039
2040    return;
2041}
2042