]> git.saurik.com Git - apple/xnu.git/blobdiff - libsa/catalogue.cpp
xnu-792.22.5.tar.gz
[apple/xnu.git] / libsa / catalogue.cpp
index 82ae948b0d38bf10b7984304bd5344b7c20d10f5..8d8b019db91a2b446c14a426c471940929cb2c6b 100644 (file)
@@ -1,16 +1,19 @@
 /*
  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <libkern/c++/OSContainers.h>
 #include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/IORegistryEntry.h>
 #include <IOKit/IOCatalogue.h>
+#include <IOKit/IOKitKeysPrivate.h>
 #include <libkern/c++/OSUnserialize.h>
 #include <libkern/OSByteOrder.h>
 #include <libsa/catalogue.h>
@@ -45,17 +49,17 @@ extern "C" {
 
 extern "C" {
 extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
-extern kern_return_t host_info(host_t host,
-    host_flavor_t flavor,
-    host_info_t info,
-    mach_msg_type_number_t  *count);
-extern int check_cpu_subtype(cpu_subtype_t cpu_subtype);
-extern struct section *
-getsectbyname(
-    char *segname,
-    char *sectname);
-extern struct segment_command *
-getsegbyname(char *seg_name);
+// extern kern_return_t host_info(host_t host,
+//     host_flavor_t flavor,
+//     host_info_t info,
+//     mach_msg_type_number_t  *count);
+extern int grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype);
+// Return the address of the named Mach-O segment from the currently
+// executing 32 bit kernel, or NULL.
+extern struct segment_command *getsegbyname(char *seg_name);
+// Return the address of the named section from the named Mach-O segment
+// from the currently executing 32 bit kernel, or NULL.
+extern struct section *getsectbyname(char *segname, char *sectname);
 };
 
 #define LOG_DELAY()
@@ -114,6 +118,7 @@ bool validateExtensionDict(OSDictionary * extension, int index) {
     bool id_missing = false;
     bool is_kernel_resource = false;
     bool has_executable = false;
+    bool ineligible_for_safe_boot = false;
     OSString * bundleIdentifier = NULL;    // do not release
     OSObject * rawValue = NULL;            // do not release
     OSString * stringValue = NULL;         // do not release
@@ -124,6 +129,7 @@ bool validateExtensionDict(OSDictionary * extension, int index) {
     OSString * key = NULL;                 // do not release
     VERS_version vers;
     VERS_version compatible_vers;
+    char namep[16];      // unused but needed for PE_parse_boot_arg()
 
     // Info dict is a dictionary
     if (!OSDynamicCast(OSDictionary, extension)) {
@@ -346,9 +352,10 @@ bool validateExtensionDict(OSDictionary * extension, int index) {
         keyIterator = NULL;
     }
 
-    // OSBundleRequired is a legal value - *not* required at boot time
-    // so we can do install CDs and the like with mkext files containing
-    // all normally-used drivers.
+    // OSBundleRequired, if present, must have a legal value.
+    // If it is not present and if we are safe-booting,
+    // then the kext is not eligible.
+    //
     rawValue = extension->getObject("OSBundleRequired");
     if (rawValue) {
         stringValue = OSDynamicCast(OSString, rawValue);
@@ -366,6 +373,10 @@ bool validateExtensionDict(OSDictionary * extension, int index) {
             goto finish;
         }
 
+    } else if (PE_parse_boot_arg("-x", namep)) { /* safe boot */
+        ineligible_for_safe_boot = true;
+        result = false;
+        goto finish;
     }
 
 
@@ -373,19 +384,24 @@ finish:
     if (keyIterator)   keyIterator->release();
 
     if (!result) {
-        if (not_a_dict) {
+        if (ineligible_for_safe_boot) {
+            IOLog(VTYELLOW "Skipping extension \"%s\" during safe boot "
+                "(no OSBundleRequired property)\n"
+                VTRESET,
+                bundleIdentifier->getCStringNoCopy());
+        } else if (not_a_dict) {
             if (index > -1) {
-                IOLog(VTYELLOW "mkext entry %d:." VTRESET, index);
+                IOLog(VTYELLOW "mkext entry %d: " VTRESET, index);
             } else {
-                IOLog(VTYELLOW "kernel extension" VTRESET);
+                IOLog(VTYELLOW "kernel extension " VTRESET);
             }
             IOLog(VTYELLOW "info dictionary isn't a dictionary\n"
                 VTRESET);
         } else if (id_missing) {
             if (index > -1) {
-                IOLog(VTYELLOW "mkext entry %d:." VTRESET, index);
+                IOLog(VTYELLOW "mkext entry %d: " VTRESET, index);
             } else {
-                IOLog(VTYELLOW "kernel extension" VTRESET);
+                IOLog(VTYELLOW "kernel extension " VTRESET);
             }
             IOLog(VTYELLOW "\"CFBundleIdentifier\" property is "
                 "missing or not a string\n"
@@ -708,8 +724,16 @@ OSDictionary * readExtension(OSDictionary * propertyDict,
     driverInfo = (MemoryMapFileInfo *)
         bootxDriverDataObject->getBytesNoCopy(0,
         sizeof(MemoryMapFileInfo));
-    dataBuffer = (BootxDriverInfo *)ml_static_ptovirt(
-        driverInfo->paddr);
+#if defined (__ppc__)
+    dataBuffer = (BootxDriverInfo *)ml_static_ptovirt(driverInfo->paddr);
+#elif defined (__i386__)
+    dataBuffer = (BootxDriverInfo *)ml_boot_ptovirt(driverInfo->paddr);
+    dataBuffer->plistAddr = (char *)ml_boot_ptovirt((vm_address_t)dataBuffer->plistAddr);
+    if (dataBuffer->moduleAddr)
+      dataBuffer->moduleAddr = (void *)ml_boot_ptovirt((vm_address_t)dataBuffer->moduleAddr);
+#else
+#error unsupported architecture
+#endif
     if (!dataBuffer) {
         IOLog("Error: No data buffer "
         "for device tree entry \"%s\".\n", memory_map_name);
@@ -795,7 +819,7 @@ OSDictionary * readExtension(OSDictionary * propertyDict,
 finish:
 
     if (loaded_kmod) {
-        kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t));
+        kfree(loaded_kmod, sizeof(kmod_info_t));
     }
 
     // do not release bootxDriverDataObject
@@ -941,8 +965,14 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info,
     OSData         * moduleInfo = 0;  // must release
     MkextEntryInfo   module_info;
 
-    mkext_data = (mkext_header *)mkext_file_info->paddr;
 
+#if defined (__ppc__)
+    mkext_data = (mkext_header *)mkext_file_info->paddr;
+#elif defined (__i386__)
+    mkext_data = (mkext_header *)ml_boot_ptovirt(mkext_file_info->paddr);
+#else
+#error unsupported architecture
+#endif
     if (OSSwapBigToHostInt32(mkext_data->magic) != MKEXT_MAGIC ||
         OSSwapBigToHostInt32(mkext_data->signature) != MKEXT_SIGN) {
         IOLog("Error: Extension archive has invalid magic or signature.\n");
@@ -971,6 +1001,16 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info,
         goto finish;
     }
 
+    IORegistryEntry * root = IORegistryEntry::getRegistryRoot();
+    assert(root);
+    OSData * checksumObj = OSData::withBytes((void *)&checksum,
+        sizeof(checksum));
+    assert(checksumObj);
+    if (checksumObj) {
+        root->setProperty(kIOStartupMkextCRC, checksumObj);
+        checksumObj->release();
+    }
+
    /* If the MKEXT archive isn't fat, check that the CPU type & subtype
     * match that of the running kernel.
     */
@@ -997,7 +1037,8 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info,
             result = false;
             goto finish;
         }
-        if (!check_cpu_subtype(OSSwapBigToHostInt32(mkext_data->cpusubtype))) {
+        if (!grade_binary(OSSwapBigToHostInt32(mkext_data->cputype),
+                         OSSwapBigToHostInt32(mkext_data->cpusubtype))) {
             IOLog("Error: Extension archive doesn't contain software "
                 "for this computer's CPU subtype.\n");
             LOG_DELAY();
@@ -1011,7 +1052,7 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info,
          i++) {
 
         if (loaded_kmod) {
-            kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t));
+            kfree(loaded_kmod, sizeof(kmod_info_t));
             loaded_kmod = 0;
         }
 
@@ -1189,7 +1230,7 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info,
 
 finish:
 
-    if (loaded_kmod) kfree((unsigned int)loaded_kmod, sizeof(kmod_info_t));
+    if (loaded_kmod) kfree(loaded_kmod, sizeof(kmod_info_t));
     if (driverPlistDataObject) {
         kmem_free(kernel_map,
             (unsigned int)driverPlistDataObject->getBytesNoCopy(),
@@ -1293,7 +1334,7 @@ bool addPersonalities(OSDictionary * extensions) {
 
         if (thisDriverPersonalities) {
             OSCollectionIterator * pIterator;
-            OSString * key;
+            OSString * locakKey;
             pIterator = OSCollectionIterator::withCollection(
                 thisDriverPersonalities);
             if (!pIterator) {
@@ -1302,12 +1343,12 @@ bool addPersonalities(OSDictionary * extensions) {
                 LOG_DELAY();
                 continue;
             }
-            while ( (key = OSDynamicCast(OSString,
+            while ( (locakKey = OSDynamicCast(OSString,
                      pIterator->getNextObject())) ) {
 
                 OSDictionary * personality = OSDynamicCast(
                     OSDictionary,
-                    thisDriverPersonalities->getObject(key));
+                    thisDriverPersonalities->getObject(locakKey));
                 if (personality) {
                     allDriverPersonalities->setObject(personality);
                 }