/*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
extern "C" {
int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
-extern void OSRuntimeUnloadCPPForSegment(
- struct segment_command * segment);
+/* operates on 32 bit segments */
+extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment);
};
if (depInfo)
{
kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id));
- kfree((vm_offset_t) depInfo, sizeof(kmod_info_t));
+ kfree(depInfo, sizeof(kmod_info_t));
} else
IOLog("%s: NO DEP %s\n", kmod_info->name, str->getCStringNoCopy());
}
// Is the module already loaded?
ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName)));
if (ret) {
- kfree((vm_offset_t) kmod_info, sizeof(kmod_info_t));
+ kfree(kmod_info, sizeof(kmod_info_t));
break;
}
sym = OSSymbol::withCString(moduleName);
IOLog("IOCatalogue: %s cannot be loaded "
"(kmod load function not set).\n",
moduleName);
+ ret = true;
break;
}
// Initialize the IOCatalog object.
bool IOCatalogue::init(OSArray * initArray)
{
- IORegistryEntry * entry;
OSDictionary * dict;
if ( !super::init() )
thread_call_func_delayed( ping, this, deadline );
#endif
- entry = IORegistryEntry::getRegistryRoot();
- if ( entry )
- entry->setProperty(kIOCatalogueKey, this);
-
return true;
}
if ( k_info->stop &&
!((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
- kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
+ kfree(k_info, sizeof(kmod_info_t));
return ret;
}
}
if (k_info) {
- kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
+ kfree(k_info, sizeof(kmod_info_t));
}
return ret;
}
-static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching )
+static IOReturn _terminateDrivers( OSDictionary * matching )
{
- OSCollectionIterator * tables;
OSDictionary * dict;
OSIterator * iter;
- OSArray * arrayCopy;
IOService * service;
IOReturn ret;
} while( !service && !iter->isValid());
iter->release();
+ return ret;
+}
+
+static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
+{
+ OSCollectionIterator * tables;
+ OSDictionary * dict;
+ OSArray * arrayCopy;
+ IOReturn ret = kIOReturnSuccess;
+
// remove configs from catalog.
- if ( ret != kIOReturnSuccess )
- return ret;
arrayCopy = OSArray::withCapacity(100);
if ( !arrayCopy )
{
IOReturn ret;
- ret = kIOReturnSuccess;
+ ret = _terminateDrivers(matching);
IOLockLock( lock );
- ret = _terminateDrivers(array, matching);
+ if (kIOReturnSuccess == ret)
+ ret = _removeDrivers(array, matching);
kernelTables->reset();
IOLockUnlock( lock );
dict->setObject(gIOModuleIdentifierKey, moduleName);
+ ret = _terminateDrivers(dict);
IOLockLock( lock );
-
- ret = _terminateDrivers(array, dict);
+ if (kIOReturnSuccess == ret)
+ ret = _removeDrivers(array, dict);
kernelTables->reset();
// Unload the module itself.
bool IOCatalogue::serialize(OSSerialize * s) const
{
- bool ret;
-
if ( !s )
return false;
- IOLockLock( lock );
-
- ret = array->serialize(s);
-
- IOLockUnlock( lock );
-
- return ret;
+ return super::serialize(s);
}
bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
/*********************************************************************
+* This function operates on sections retrieved from the currently running
+* 32 bit mach kernel.
*********************************************************************/
bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
{
return result;
}
-
/*********************************************************************
* This function clears out all references to the in-kernel linker,
* frees the list of startup extensions in extensionDict, and
* deallocates the kernel's __KLD segment to reclaim that memory.
+*
+* The segments it operates on are strictly 32 bit segments.
*********************************************************************/
kern_return_t IOCatalogue::removeKernelLinker(void) {
kern_return_t result = KERN_SUCCESS;
- struct segment_command * segment;
+ struct segment_command * segmentLE, *segmentKLD;
+ boolean_t keepsyms = FALSE;
+#if __ppc__
char * dt_segment_name;
void * segment_paddress;
int segment_size;
+#endif
/* This must be the very first thing done by this function.
*/
goto finish;
}
+ PE_parse_boot_arg("keepsyms", &keepsyms);
+
IOLog("Jettisoning kernel linker.\n");
kernelLinkerPresent = 0;
* memory so that any cross-dependencies (not that there
* should be any) are handled.
*/
- segment = getsegbyname("__KLD");
- if (!segment) {
+ segmentKLD = getsegbyname("__KLD");
+ if (!segmentKLD) {
IOLog("error removing kernel linker: can't find %s segment\n",
"__KLD");
result = KERN_FAILURE;
goto finish;
}
- OSRuntimeUnloadCPPForSegment(segment);
+ OSRuntimeUnloadCPPForSegment(segmentKLD);
- segment = getsegbyname("__LINKEDIT");
- if (!segment) {
+ segmentLE = getsegbyname("__LINKEDIT");
+ if (!segmentLE) {
IOLog("error removing kernel linker: can't find %s segment\n",
"__LINKEDIT");
result = KERN_FAILURE;
goto finish;
}
- OSRuntimeUnloadCPPForSegment(segment);
-
-
+ OSRuntimeUnloadCPPForSegment(segmentLE);
+#if __ppc__
/* Free the memory that was set up by bootx.
*/
dt_segment_name = "Kernel-__KLD";
IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
(int)segment_size);
}
-
+#elif __i386__
+ /* On x86, use the mapping data from the segment load command to
+ * unload KLD and LINKEDIT directly, unless the keepsyms boot-arg
+ * was enabled. This may invalidate any assumptions about
+ * "avail_start" defining the lower bound for valid physical addresses.
+ */
+ if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize)
+ ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize);
+#else
+#error arch
+#endif
+#if __ppc__
dt_segment_name = "Kernel-__LINKEDIT";
if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
(int)segment_size);
}
+#elif __i386__
+ if (!keepsyms && segmentLE->vmaddr && segmentLE->vmsize)
+ ml_static_mfree(segmentLE->vmaddr, segmentLE->vmsize);
+#else
+#error arch
+#endif
struct section * sect;
sect = getsectbyname("__PRELINK", "__symtab");
return result;
}
+
+/*********************************************************************
+* This function stops the catalogue from making kextd requests during
+* shutdown.
+*********************************************************************/
+void IOCatalogue::disableExternalLinker(void) {
+ IOLockLock(gIOKLDLock);
+ /* If kmod_load_extension (the kextd requester function) is in use,
+ * disable new module requests.
+ */
+ if (kmod_load_function == &kmod_load_extension) {
+ kmod_load_function = NULL;
+ }
+
+ IOLockUnlock(gIOKLDLock);
+}
+