Loading...
libsa/bootstrap.cpp xnu-3248.50.21 xnu-2422.100.13
--- xnu/xnu-3248.50.21/libsa/bootstrap.cpp
+++ xnu/xnu-2422.100.13/libsa/bootstrap.cpp
@@ -131,6 +131,9 @@
     void readPrelinkedExtensions(
         kernel_section_t * prelinkInfoSect);
     void readBooterExtensions(void);
+    OSReturn readMkextExtensions(
+        OSString * deviceTreeName,
+        OSData   * deviceTreeData);
     
     OSReturn loadKernelComponentKexts(void);
     void     loadKernelExternalComponents(void);
@@ -253,7 +256,7 @@
             "Can't find prelinked kexts' text segment.");
         goto finish;
     }
-
+    
 #if KASLR_KEXT_DEBUG
     unsigned long   scratchSize;
     vm_offset_t     scratchAddr;
@@ -455,6 +458,7 @@
 /*********************************************************************
 *********************************************************************/
 #define BOOTER_KEXT_PREFIX   "Driver-"
+#define BOOTER_MKEXT_PREFIX  "DriversPackage-"
 
 typedef struct _DeviceTreeBuffer {
     uint32_t paddr;
@@ -478,7 +482,7 @@
     OSKextLog(/* kext */ NULL,
         kOSKextLogProgressLevel |
         kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
-        "Reading startup extensions from booter memory.");
+        "Reading startup extensions/mkexts from booter memory.");
     
     booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
 
@@ -516,6 +520,7 @@
     while ( ( deviceTreeName =
         OSDynamicCast(OSString, keyIterator->getNextObject() ))) {
 
+        boolean_t isMkext = FALSE;
         const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
         OSData * deviceTreeEntry = OSDynamicCast(OSData,
             propertyDict->getObject(deviceTreeName));
@@ -529,10 +534,18 @@
             continue;
         }
 
-        /* Make sure it is a kext */
-        if (strncmp(devTreeNameCString,
-                    BOOTER_KEXT_PREFIX,
-                    CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
+        /* Make sure it is either a kext or an mkext */
+        if (!strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
+            CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
+
+            isMkext = FALSE;
+
+        } else if (!strncmp(devTreeNameCString, BOOTER_MKEXT_PREFIX,
+            CONST_STRLEN(BOOTER_MKEXT_PREFIX))) {
+
+            isMkext = TRUE;
+
+        } else {
             continue;
         }
 
@@ -555,7 +568,7 @@
             OSKextLog(/* kext */ NULL,
                 kOSKextLogErrorLevel |
                 kOSKextLogDirectoryScanFlag,
-                "Can't get virtual address for device tree entry %s.",
+                "Can't get virtual address for device tree mkext entry %s.",
                 devTreeNameCString);
             goto finish;
         }
@@ -577,12 +590,16 @@
         }
         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);
-        OSSafeRelease(newKext);
+        if (isMkext) {
+            readMkextExtensions(deviceTreeName, booterData);
+        } else {
+           /* 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);
+            OSSafeRelease(newKext);
+        }
 
         booterMemoryMap->removeProperty(deviceTreeName);
 
@@ -596,6 +613,49 @@
     OSSafeRelease(booterData);
     OSSafeRelease(aKext);
     return;
+}
+
+/*********************************************************************
+*********************************************************************/
+OSReturn
+KLDBootstrap::readMkextExtensions(
+    OSString   * deviceTreeName,
+    OSData     * booterData)
+{
+    OSReturn result = kOSReturnError;
+
+    uint32_t          checksum;
+    IORegistryEntry * registryRoot = NULL;  // do not release
+    OSData          * checksumObj  = NULL;   // must release
+
+    OSKextLog(/* kext */ NULL,
+        kOSKextLogStepLevel |
+        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
+        "Reading startup mkext archive from device tree entry %s.",
+        deviceTreeName->getCStringNoCopy());
+
+   /* If we successfully read the archive,
+    * then save the mkext's checksum in the IORegistry.
+    * assumes we'll only ever have one mkext to boot
+    */
+    result = OSKext::readMkextArchive(booterData, &checksum);
+    if (result == kOSReturnSuccess) {
+
+        OSKextLog(/* kext */ NULL,
+            kOSKextLogProgressLevel |
+            kOSKextLogArchiveFlag,
+            "Startup mkext archive has checksum 0x%x.", (int)checksum);
+
+        registryRoot = IORegistryEntry::getRegistryRoot();
+        assert(registryRoot);
+        checksumObj = OSData::withBytes((void *)&checksum, sizeof(checksum));
+        assert(checksumObj);
+        if (checksumObj) {
+            registryRoot->setProperty(kOSStartupMkextCRC, checksumObj);
+        }
+    }
+    
+    return result;
 }
 
 /*********************************************************************