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