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