+ registryRoot = IORegistryEntry::getRegistryRoot();
+ assert(registryRoot);
+
+ prelinkCountObj = OSNumber::withNumber(
+ (unsigned long long)infoDictArray->getCount(),
+ 8 * sizeof(uint32_t));
+ assert(prelinkCountObj);
+ if (prelinkCountObj) {
+ registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
+ }
+
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogProgressLevel |
+ kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
+ kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
+ "%u prelinked kexts",
+ infoDictArray->getCount());
+
+#if CONFIG_KEXT_BASEMENT
+ /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
+ * special VM region during OSKext init time, so we can free the whole
+ * segment now.
+ */
+ ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
+#endif /* __x86_64__ */
+
+ /* Free the prelink info segment, we're done with it.
+ */
+ prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
+ if (prelinkInfoSegment) {
+ ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
+ (vm_size_t)prelinkInfoSegment->vmsize);
+ }
+
+finish:
+ OSSafeReleaseNULL(errorString);
+ OSSafeReleaseNULL(parsedXML);
+ OSSafeReleaseNULL(theKernel);
+ OSSafeReleaseNULL(prelinkCountObj);
+ return;
+}
+
+static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount)
+{
+ int i;
+
+ for (i = 0; i < segCount; i++) {
+ vm_offset_t myAddr = *(segAddrs + i);
+ unsigned long mySize = *(segSizes + i);
+
+ if (theAddr >= myAddr && theAddr < (myAddr + mySize)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/*********************************************************************
+*********************************************************************/
+#define BOOTER_KEXT_PREFIX "Driver-"
+
+typedef struct _DeviceTreeBuffer {
+ uint32_t paddr;
+ uint32_t length;
+} _DeviceTreeBuffer;
+
+void
+KLDBootstrap::readBooterExtensions(void)
+{
+ IORegistryEntry * booterMemoryMap = NULL; // must release
+ OSDictionary * propertyDict = NULL; // must release
+ OSCollectionIterator * keyIterator = NULL; // must release
+ OSString * deviceTreeName = NULL; // do not release
+
+ const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free
+ char * booterDataPtr = NULL; // do not free
+ OSData * booterData = NULL; // must release
+
+ OSKext * aKext = NULL; // must release
+
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogProgressLevel |
+ kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
+ "Reading startup extensions from booter memory.");
+
+ booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
+
+ if (!booterMemoryMap) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
+ "Can't read booter memory map.");
+ goto finish;
+ }
+
+ propertyDict = booterMemoryMap->dictionaryWithProperties();
+ if (!propertyDict) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogDirectoryScanFlag,
+ "Can't get property dictionary from memory map.");
+ goto finish;
+ }
+
+ keyIterator = OSCollectionIterator::withCollection(propertyDict);
+ if (!keyIterator) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogGeneralFlag,
+ "Can't allocate iterator for driver images.");
+ goto finish;
+ }
+
+ /* Create dictionary of excluded kexts
+ */
+#ifndef CONFIG_EMBEDDED
+ OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
+#endif
+ keyIterator->reset();
+
+ while ( ( deviceTreeName =
+ OSDynamicCast(OSString, keyIterator->getNextObject() ))) {
+
+ const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
+ OSData * deviceTreeEntry = OSDynamicCast(OSData,
+ propertyDict->getObject(deviceTreeName));
+
+ /* Clear out the booterData from the prior iteration.
+ */
+ OSSafeReleaseNULL(booterData);
+
+ /* If there is no entry for the name, we can't do much with it. */
+ if (!deviceTreeEntry) {
+ continue;
+ }
+
+ /* Make sure it is a kext */
+ if (strncmp(devTreeNameCString,
+ BOOTER_KEXT_PREFIX,
+ CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
+ continue;
+ }
+
+ deviceTreeBuffer = (const _DeviceTreeBuffer *)
+ deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
+ if (!deviceTreeBuffer) {
+ /* We can't get to the data, so we can't do anything,
+ * not even free it from physical memory (if it's there).
+ */
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogDirectoryScanFlag,
+ "Device tree entry %s has NULL pointer.",
+ devTreeNameCString);
+ goto finish; // xxx - continue, panic?
+ }
+
+ booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
+ if (!booterDataPtr) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogDirectoryScanFlag,
+ "Can't get virtual address for device tree entry %s.",
+ devTreeNameCString);
+ goto finish;
+ }
+
+ /* Wrap the booter data buffer in an OSData and set a dealloc function
+ * so it will take care of the physical memory when freed. Kexts will
+ * retain the booterData for as long as they need it. Remove the entry
+ * from the booter memory map after this is done.
+ */
+ booterData = OSData::withBytesNoCopy(booterDataPtr,
+ deviceTreeBuffer->length);
+ if (!booterData) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogGeneralFlag,
+ "Error - Can't allocate OSData wrapper for device tree entry %s.",
+ devTreeNameCString);
+ goto finish;
+ }
+ booterData->setDeallocFunction(osdata_phys_free);
+
+ /* Create the kext for the entry, then release it, because the
+ * kext system keeps them around until explicitly removed.
+ * Any creation/registration failures are already logged for us.
+ */
+ OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
+ OSSafeReleaseNULL(newKext);
+
+ booterMemoryMap->removeProperty(deviceTreeName);
+
+ } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
+
+finish:
+
+ OSSafeReleaseNULL(booterMemoryMap);
+ OSSafeReleaseNULL(propertyDict);
+ OSSafeReleaseNULL(keyIterator);
+ OSSafeReleaseNULL(booterData);
+ OSSafeReleaseNULL(aKext);
+ return;
+}
+
+/*********************************************************************
+*********************************************************************/
+#define COM_APPLE "com.apple."
+
+void
+KLDBootstrap::loadSecurityExtensions(void)
+{
+ OSDictionary * extensionsDict = NULL; // must release
+ OSCollectionIterator * keyIterator = NULL; // must release
+ OSString * bundleID = NULL; // don't release
+ OSKext * theKext = NULL; // don't release
+ OSBoolean * isSecurityKext = NULL; // don't release
+
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogStepLevel |
+ kOSKextLogLoadFlag,
+ "Loading security extensions.");
+
+ extensionsDict = OSKext::copyKexts();
+ if (!extensionsDict) {
+ return;
+ }
+
+ keyIterator = OSCollectionIterator::withCollection(extensionsDict);
+ if (!keyIterator) {
+ OSKextLog(/* kext */ NULL,
+ kOSKextLogErrorLevel |
+ kOSKextLogGeneralFlag,
+ "Failed to allocate iterator for security extensions.");
+ goto finish;
+ }
+
+ while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {