I am writing a customised mass storage kernel extension for Mac, subclassed from the IOSCSIPeripheralDeviceType05 logical unit driver. I have got as far as compiling a .kext file, which passes kextutil -n -t ..., but I cannot load it for testing.
I have a non-zero IOKitDebug field in the .plist, and the GetDeviceConfiguration looks like this:
IOReturn
com_MyCompany_driver_MyDriver::GetDeviceConfiguration( void )
{
IOLog( "MyDriver overriding GetConfiguration\n" );
return super::GetDeviceConfiguration();
}
However when I copy it into /System/Library/Extensions/ and execute it with kextutil /System/Library/Extension/MyDriver.kext, nothing happens, and nothing appears in /var/log/system.log.
How do I load this .kext to be able to debug it?
First, don't put extensions in /SLE while developing them. That's asking for trouble, as it can cause the extension to be loaded automatically. This could cause the system to become unbootable. Just copy to, e.g. /tmp/ and use kextutil to load it from there.
Second, put some debug output in com_MyCompany_driver_MyDriver::init() as that's the first thing that'll get called.
Third, your problem is likely the device matching. If the device is already matched by an existing driver at the time of loading your kext, yours won't be considered. If you can't hot-plug the device and you can't unload the existing driver before loading yours, you may need to install the kext in SLE to be loaded on boot after all. If you're still having matching trouble, post some details of the device you're trying to match (ioreg/IORegistryExplorer output) and the matching dictionary from your info.plist.
Related
https://www.kernel.org/doc/html/latest/admin-guide/acpi/ssdt-overlays.html gives the following method to load an overlay
cd /config/acpi/table
mkdir my_ssdt
cat ~/ssdt.aml > my_ssdt/aml
This method only works once. Once I have loaded the aml file, I can't reload it.
[ 1901.153829] ACPI configfs: table already loaded
Is there a way to unload the aml file? At the moment, I am trying to load a enumerate the device using ACPI.
Being new to ACPI and Overlays, am updating the asl file to fix issues, and recompiling and attempting to load.
But once the module is loaded, the kernel does not seem to apply the overlay again forcing me to reload the and then re-check.
So is there a way to reload the re-genrated aml file?
The kernel documentation indeed doesn't describe this moment. However, if you look into the source code of ACPI ConfigFS support you may see that it supports dropping items. It is a basic stuff by ConfigFS API, namely reaction to rmdir() system call. So, it means that simple removing the folder is what you need in order to unload the table:
rm -rf /sys/kernel/config/acpi/table/my_ssdt
Note, this is a debug feature and not guaranteed to work properly on all possible type of tables. In kernel only SPI, I2C and platform devices can be unbound.
Also note, that unloading tables wasn't in the kernel till the commit Unload SSDT on configfs entry removal appears.
I have a device which loads a small 'safe mode' Yocto image from coreboot, then selects a larger image to load, and performs a kexec to load that image. Typically this works, but in rare cases the target image's file system has been corrupted and kernel panics on boot.
Since the device will eventually be deployed into locations that are difficult to access, I was hoping to find a way to recover from any kernel panic without having to physically reboot the device.
To fix this, I added an init script using "init=/sbin/init.sh" in the kexec command line when the new kernel is loaded, and I added a recovery kernel load using "kexec --load-panic" in the init script on the 2nd file system. This method successfully recovers kernel panics that happen late in the boot process, but I encountered a file system which was trashed in a particular way so that the kernel panic would occur before the init script gets launched. Since the init script isn't executed, the panic kernel never gets loaded, and the device must be power cycled.
To fix this, I tried adding the recovery kernel into the initial small kernel loaded by coreboot, but it appears to only handle kernel panics that occur before the "kexec --exec" command loads the new kernel.
I'm trying to figure out what is the best way to solve this. For example, I could add validation before I kexec to the new image. I currently check that the file system can be mounted, that its kernel file and the init script are present. If anyone knows which other files are necessary to get to the init script, I could add them to my validation.
Alternatively, is there a way to load the new kernel and kexec to it with the recovery kernel "--load-panic" parameter already loaded?
I tried putting both the kexec --load and --load-panic in the same line, but that doesn't work.
Any recommendation is greatly appreciated.
I have a working OSX kernel extension which I would like to be automatically loaded at boot time as early as possible. The kext is using KAUTH for monitoring access on a specific path so it seems to me there won't be anything that will request it to be loaded into the kernel. In this case, copying it in /Library/Extensions (at least since Yosemite this is the recommended path for third-party extensions) won't solve my problem.
Is there a possibility to achieve this, whether or not by modifying the code or through some auxiliary configuration?
I already read about using a launchd daemon to use kextload in order to load the extension, as specified in this question, but in my case, I want it to be loaded as early as possible.
Update:
I am using a "generic" kernel extension (linked against BSD library) and not an I/O Kit based one.
I want my extension to be loaded before launchd is started.
You don't explicitly state it in the question, but I infer from the context that you're using a "generic" kernel extension (in contrast to an I/O kit based one)? These are only loaded either because another kext depends on them, or because they are explicitly loaded via kextutil/kextload or the KextManager API.
Contrast this to I/O Kit kexts, which are loaded on-demand when one of their personality dictionaries matches a registered service in the IO registry. This is usually for driving specific devices, but various non-hardware-dependent system services use the mechanism to match the 'IOResources' nub (documentation) which turns up during early boot so any kexts listing it as a provider for a personality also get loaded on boot.
So the solution would be to modify your kext to provide an IOService which matches the IOResources nub. The service itself doesn't really need to do anything if your userspace component already uses another interface to communicate with the kext.
If you don't want to change the kext's code itself, you could possibly create a dummy kext which does this, but declares your main kext as a dependency. This latter method isn't particularly elegant, but should work if for some reason modifying the existing kext is not possible. (Although you'll likely need to modify the info.plist)
If the kext is derived from IOKit and resides in /Library/Extensions clear the cache and it will be automatically loaded at boot. You clear the cache by calling
kextcache -f -update-volume /
I'm attempting to write an application that talks to a custom USB device. We have written a driver (kext) that is automatically loaded when the USB device is attached to the computer. It is installed into the appropriate location (/System/Library/Extensions & /Library/Extensions) during the installation process.
In my application (.app), I need to be able to confirm that this kext is installed and is loadable on the user's computer.
My initial thought was to use the "System" command and get the result of "kextstat | grep mykext". However, kextstat only shows the kernel extensions that are loaded. (It's possible the application can be launched before the user has attached the USB device).
The only other thing that I can think of is to use "kextfind | grep mykext" to determine if the kext exists, however, I don't know if it is loadable or not. (ie. it could exist, but someone messed with the plist file, and now the signature fails, so it won't ever be loaded)
I know that it's possible, because Apple's System Profiler is able to list all of the extensions, if they are loaded, and if they are loadable.
From the kextutil man page:
kextutil prints diagnostic information about kexts by default, but some options cause certain tests to be skipped. To ensure that all tests are performed, use the -print-diagnostics (-t) option. The -print-diagnostics option is typically used with -no-load (-n) after a load failure to pinpoint a problem. It can be used with any other set of options, however.
Note: when the -no-load (-n) option is used then sudo (root user) isn't required.
I have a PCI driver for a FPGA card that installs and works fine.However, we have a need to clean up our system without rebooting which includes unloading this driver.
When starting again (without rebooting) the driver is re-installed. I have found that when I do this process (install/uninstall) multiple times, on the 5th unload of the driver the directory associated with the device just disappears.
lspci command can no longer find my device because of a bad link. I have to reboot to get the device directory (/sys/bus/pci/devices/00000:04:00.0) to show up again.
With some experimentation and reducing the driver down to the bare minimum I discovered that if I do not do a call to pci_enable_device(..) function in my pci_probe_method, then I am able to install/uninstall the driver multiple times without error.
Of course, I need to call this method before I can do anything with the device but I wanted to be sure it was not some other of the more complex initialization I am doing was causing the problem.
I have verified that my call to pci_disable_device() is being called in the pci_remove_method(). I should be able to enable and disable a PCI device indefinitely, right? Any help in figuring out what is happening would be appreciated.
The actual solution to this problem was to eliminate an extraneous call I had to pci_dev_put(..). I did not notice this before when submitting the question. This was leftover from when this driver was not using the pci_probe() method to discover this device. So, executing this call in the exit routine caused the structure for this device to go away after 5 calls. So for now this problem is solved.