Unload kext which still has instances - macos

I'm updating the driver of one of my devices and would like to kextunload the old driver and kextload the new one so a restart isn't required anymore.
After the installation I try:
sudo kextunload /System/Library/Extensions/Driver.kext
The error which happens looks like this:
(kernel) Can't unload kext com.driver.Driver; classes have instances:
(kernel) Kext com.driver.Driver class com_driver_Driver_USBAudioDevice has 1 instance.
Failed to unload com.driver.Driver - (libkern/kext) kext is in use or retained (cannot unload).
The device is not present in ioreg.
How can I find out what this instance is which prevents me from unloading the driver?

If you call the command kextstat, it will display a list of all the loaded kernel extensions with info like this one:-
115 3 0xffffff7f814f4000 0x32000 0x32000 com.apple.iokit.IOAudioFamily (1.8.9fc11) <114 5 4 3 1>
The first number (115) is the id of the kernel extension.
At the end, the set of numbers <114 5 4 3 1> are the other kernel extension ids that are being referenced by this particular kext.
If you match the id of your kext to any of those listed in another, then that is a reference that kextunload is referring to.
Also note that when writing any code in the kernel, globals variables are global across the whole kernel, so if you've declared any that may not have a unique name and is used by another kext, I have found this to cause a similar issue. The solution here is to prepend any globals with a reverse company URI (e.g. com_apple_globalVarName).

The accepted answer is incorrect. The trailing numbers at the end of output from kextstat are NOT a listing of the kexts dependent on this one.
They ARE a list of the kexts that this kext is dependent upon.
Using the same example kext as the other answer, com.apple.iokit.IOAudioFamily, I show the following:
~ root# kmutil showloaded -b com.apple.iokit.IOAudioFamily
No variant specified, falling back to release
Index Refs Address Size Wired Name (Version) UUID <Linked Against>
152 3 0xffffff7f9922c000 0x1e000 0x1e000 com.apple.iokit.IOAudioFamily (340.2) 2BC68A45-C1C1-30D1-A7A2-B911CFDB04F2 <151 7 6 3 1>
(Note: I am using kmutil showloaded instead of kextstat as the later is deprecated.)
Breaking this output down we see:
A Refs count of 3 indicates that 3 other kexts "refer" (or link against) this kext.
The <Linked Against> list indicates the Index of other kexts that this kext is dependent upon.
To specifically answer your question, you need to find the other kexts that have your kext's Index listed in their <Linked Against> listing.
Continuing our example with the com.apple.iokit.IOAudioFamily kext we can look at all loaded kexts and search for any referencing index 152 by running: kmutil showloaded | grep '<.*152.*>'
~ root# kmutil showloaded | grep '<.*152.*>'
No variant specified, falling back to release
153 0 0xffffff7f99023000 0x52000 0x52000 com.apple.driver.AppleUSBAudio (416.2) D9A996CC-8118-3E85-B019-F756AC2A4689 <152 150 114 24 23 16 8 7 6 3 1>
190 0 0xffffff7f97a97000 0x5f000 0x5f000 com.apple.driver.AppleGFXHDA (140.3) EED41AF8-3465-37CC-AB65-DB85BD71B595 <152 144 134 16 9 8 7 6 3 1>
219 0 0xffffff7f990ad000 0x3000 0x3000 com.apple.driver.AudioAUUC (1.70) 5C4939F8-12C1-39BF-AD87-8456A450BCF7 <152 134 16 15 9 7 6 3 1>
As you can see, the three kexts that reference (or are Linked Against) com.apple.iokit.IOAudioFamily are:
com.apple.driver.AppleUSBAudio
com.apple.driver.AppleGFXHDA
com.apple.driver.AudioAUUC
You would need to unload these three kexts (and any kexts that they are referenced by in turn) before you could unload the original.

Related

Error when trying to create and mount a new HFS volume (in order to test filter scheme driver)

I am trying to test a IO kit sample app that implements a filter scheme. See section 10.7.10 here for context. As the source there is hard to cut and paste (and when I tried I got errors), I am using the source from here which builds.
In the last figure on that page (1038) it has a series of steps for creating and mounting a new HFS volume. The idea is to see that the KEXT is working and doing encryption. I have built the sample KEXT and tested with it, but I always get "No mountable file systems" error when I make the "open" call. I have verified the KEXT is properly loaded.
If I remove the "-partitionType" I am able to manipulate the volume normally (though this doesn't involve the KEXT).
Can someone please suggest what might be going wrong here?
Part of my confusion in figure 1038's script is the "detach" command that is run before the open. It fails for me, but I am not sure if that is what is causing the "open" after it to fail, or is unrelated.
$ sudo kextload /System/Library/Extensions/IOKitDriverTestApp.kext/
$ hdiutil create -size 32m -partitionType osxbook_HFS /tmp/crypto.dmg
created: /tmp/crypto.dmg
$ hdiutil attach -nomount /tmp/crypto.dmg
/dev/disk2 Apple_partition_scheme
/dev/disk2s1 Apple_partition_map
/dev/disk2s2 osxbook_HFS
$ diskutil list
/dev/disk0 (internal, physical):
[cut]
/dev/disk1 (synthesized):
[cut]
/dev/disk2 (disk image):
#: TYPE NAME SIZE IDENTIFIER
0: Apple_partition_scheme +33.6 MB disk2
1: Apple_partition_map 32.3 KB disk2s1
2: osxbook_HFS 33.5 MB disk2s2
$ newfs_hfs -v Crypto /dev/rdisk2s2
Initialized /dev/rdisk2s2 as a 32 MB case-insensitive HFS Plus volume
$ hdiutil detach /dev/disk2
hdiutil: detach failed - No such file or directory
$ open /tmp/crypto.dmg
==> Get popup window with error "crypto.dmg" "No mountable file systems"
UPDATE: the question originally targeted the case when the KEXT was not loaded. Since I got that to work I changed it to reflect the case with the KEXT, which is more important anyway.
UPDATE2: It seems that eventually the kext is getting unloaded (possibly crashing). Sometimes it seems around the time of the "open", sometimes after. I tried adding statements like IOLog("CSD: init"), but none of them show up in the system log or console log. Looking for how else I can triage this (without needing a separate machine).
UPDATE3: Below is the output of when I try to start the KEXT. There are a bunch of warnings but since I have the signing check disabled I think it is still loading. Also I see it loaded via kextstat.
The other strange thing is I don't see any signs of this KEXT in the output of "ioreg", nor do I see any of the print statements from IOLog().
My-MacBook-Pro:Extensions myuser$ sudo kextutil -v /System/Library/Extensions/IOKitDriverTestApp.kext/
Defaulting to kernel file '/System/Library/Kernels/kernel'
Kext with invalid signatured (-67050) allowed: <OSKext 0x7fa53703ec70 [0x7fff8fe6faf0]> { URL = "file:///System/Library/Extensions/IOKitDriverTestApp.kext/", ID = "com.osxbook.driver.IOKitDriverTestApp" }
Code Signing Failure: code signature is invalid
Warnings:
Personality CFBundleIdentifier differs from containing kext's (not necessarily a mistake, but rarely done):
SimpleCryptoDisk
Personality CFBundleIdentifier names a kext that can't be found:
'SimpleCryptoDisk' -> 'com.osxbook.driver.SimpleCryptoDisk'
Warnings:
Personality CFBundleIdentifier differs from containing kext's (not necessarily a mistake, but rarely done):
SimpleCryptoDisk
Personality CFBundleIdentifier names a kext that can't be found:
'SimpleCryptoDisk' -> 'com.osxbook.driver.SimpleCryptoDisk'
/System/Library/Extensions/IOKitDriverTestApp.kext appears to be loadable (not including linkage for on-disk libraries).
Loading /System/Library/Extensions/IOKitDriverTestApp.kext.
/System/Library/Extensions/IOKitDriverTestApp.kext successfully loaded (or already loaded).
Invalid signature -67050 for kext <OSKext 0x7fa53703ec70 [0x7fff8fe6faf0]> { URL = "file:///System/Library/Extensions/IOKitDriverTestApp.kext/", ID = "com.osxbook.driver.IOKitDriverTestApp" }
UPDATE4: I adjusted the bundle ID in the plist so it matches, and now it is not giving the "names a kext that can't be found" error:
My-MacBook-Pro:Debug myuser$ sudo kextutil -v /System/Library/Extensions/IOKitDriverTestApp.kext/
Password:
Defaulting to kernel file '/System/Library/Kernels/kernel'
Kext with invalid signatured (-67050) allowed: <OSKext 0x7f8be663ecf0 [0x7fff866bcaf0]> { URL = "file:///System/Library/Extensions/IOKitDriverTestApp.kext/", ID = "com.osxbook.driver.IOKitDriverTestApp" }
Code Signing Failure: code signature is invalid
/System/Library/Extensions/IOKitDriverTestApp.kext appears to be loadable (not including linkage for on-disk libraries).
Loading /System/Library/Extensions/IOKitDriverTestApp.kext.
/System/Library/Extensions/IOKitDriverTestApp.kext successfully loaded (or already loaded).
Invalid signature -67050 for kext <OSKext 0x7f8be663ecf0 [0x7fff866bcaf0]> { URL = "file:///System/Library/Extensions/IOKitDriverTestApp.kext/", ID = "com.osxbook.driver.IOKitDriverTestApp" }
UPDATE5:
Now my OS consistently crashes every time I load the KEXT and then execute "hdiutil attach -nomount /tmp/crypto.dmg" (after creating /tmp/crypto.dmg).
It seems clear my KEXT is running now, but for some reason I still don't see the IOLog() statements anywhere. Will have to look through the system logs and see if there is any indication why it is crashing.
UPDATE6: I have been able to get a symbolicated kernel panic, but it is pointing to a different KEXT (which I don't think I have the source too). Below is the relevant part of it.
I tried using another version of the same test KEXT (here) without any changes (I have removed the IOLog() statements for now since they weren't showing up).
I see a note this was tested on Mac OS 10.6, but has anyone gotten this sample to work on 10.13.16 (High Sierra)?
...
0xffffff800c94f540 : 0xffffff800cb8776f mach_kernel : _kernel_trap + 0x70f
0xffffff800c94f6b0 : 0xffffff800ca1e1e0 mach_kernel : _return_from_trap + 0xe0
0xffffff800c94f6d0 : 0xffffff7f8d527251 com.apple.iokit.IOStorageFamily : __ZN9IOStorage8completeEP19IOStorageCompletioniy + 0x27
0xffffff81f7a4b980 : 0xffffff7f8d51a0c4 com.apple.iokit.IOStorageFamily : __ZN20IOBlockStorageDriver24prepareRequestCompletionEPvS0_iy + 0xc2
0xffffff81f7a4b9e0 : 0xffffff7f903afa7a com.apple.driver.DiskImages : __ZN13IOHDIXCommand8completeEiy + 0x26
0xffffff81f7a4ba00 : 0xffffff7f903adbfe com.apple.driver.DiskImages : __ZN22IOHDIXHDDriveOutKernel12processReplyEPK13HDIReplyOOL64P18IOMemoryDescriptor + 0x2be
0xffffff81f7a4ba60 : 0xffffff7f903aee9b com.apple.driver.DiskImages : __ZN32IOHDIXHDDriveOutKernelUserClient14processReply64EPK13HDIReplyOOL64 + 0xd3
0xffffff81f7a4bac0 : 0xffffff800d0c3959 mach_kernel : _shim_io_connect_method_structureI_structureO + 0x1c9
0xffffff81f7a4bb20 : 0xffffff800d0c1ae0 mach_kernel : __ZN12IOUserClient14externalMethodEjP25IOExternalMethodArgumentsP24IOExternalMethodDispatchP8OSObjectPv + 0x340
0xffffff81f7a4bb70 : 0xffffff800d0ca567 mach_kernel : _is_io_connect_method + 0x217
...
UPDATE7: I gave up on trying to use the SimpleCryptoDisk.cpp test app and started from scratch, adding a little bit of code at a time. I've had some success (the driver starts and I can see logging), though I don't really have anything working yet.
If I get stuck on this I may post another question, but I'll go ahead and mark pmdj's answer as correct since he answered my original question.
If anyone knows of a modified version of SimpleCryptoDisk that works on High Sierra I'd still like to know, however.
To answer your original questions:
[Why "No mountable file systems" when not loading the kext and using partition type "osxbook_HFS"]
As you can see, the Apple Partition Scheme uses arbitrary text strings for identifying partition type. macOS uses this string verbatim as the "content hint" which selects which file system type to attempt to automount on that volume. The HFS+ file system is only looking for Apple_HFS (and Apple_HFSX for case-sensitive)
The idea behind the kext is that it itself matches the newly defined content hint and publishes a new storage nub object which in turn has the HFS+ content hint for the filesystem to pick up.
Why hdiutil detach was failing
$ hdiutil detach /dev/disk2
hdiutil: detach failed - No such file or directory
On current versions of macOS, you need to rewrite the command as either:
$ hdiutil detach disk2
or
$ hdiutil detach /Volumes/VOLUMENAME
I can't immediately answer your current question of why it's not working with the kext, but I can suggest you look at whether your kext is behaving as expected with regard to the IO Registry. Check with IORegistryExplorer or ioreg whether it's matching the volume with the special partition type, and whether it's creating and registering the virtual (decrypted) volume with the Apple_HFS content hint. Add the ioreg output (ioreg -w 0 -lirc YOUR_DRIVERS_CLASSNAME) to your question if unsure.

Is there a known issue relating to Windows 7 Kernel Symbols?

I have a few Windows 7 machines that I am not able to read their memory dumps. I found something that I suspect may be related, but am not positive:
https://twitter.com/aionescu/status/634028737458114560
I also found this: http://support.microsoft.com/kb/2528507
However, the scenario message regarding wow64exts given in the doc is not seen in any of my dumps. I also cannot apply that hotfix at this time to test it. So I'm just looking for some more information or opinions.
I'm able to open any other OS dump as well as my own system's Windows 7 dump, but there are 2 other machines that run Win 7 and it's telling me I have the wrong kernel symbols.
I have tried clearing out my symbol cache, reinstalled the Windows SDK, and also tried to open the dumps on two other machines with the same result. If it matters, the crash is manually created using the scroll lock method.
Symbol path: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;
Seeing these errors: followed by "Type referenced: nt!_KPRCB"
Does anyone know about the issue mentioned by Alex in the twitter link and if it's possibly related to what I'm seeing?
Update 2015-10-22:
With the Microsoft patch day (2015-10-13) and KB3088195, symbols are available again.
However, symbols for the broken version have not been provided, so below may still be useful.
Microsoft has already published "good" symbols for ntdll in the past, containing type information like _TEB or _KPRCB. Starting from mid of July 2015, Microsoft has still published symbols for ntdll, but not containing that information.
So it depends on the version of ntdll whether you get type information or not. Old dumps referencing an old version of ntdll will download old PDBs containing type information while new dumps reference new versions of ntdll and WinDbg (or any other debugger) downloads PDBs without type information.
Could Microsoft remove type information of "good" symbols retroactively, thus making them "bad"?
Yes. As described in this answer, there is a tool to remove type information from existing PDBs. Doing that and replacing the PDB would result in such an effect.
Can Microsoft publish the "good" version of those PDBs which are currently "bad"?
That's hard to tell, since we don't know whether Microsoft has kept a copy of the "good" version so they could replace the "bad" version on the symbol server with the "good" one. Rebuilding ntdll from the same source code and thus creating new PDBs sounds possible, but the PDB gets a new time stamp and checksum. This can potentially be corrected manually, especially be Microsoft, since they should have the knowledge about the PDB internal format, but IMHO it's unlikely they'll do that. Things may go wrong and MS will hardly have tests to guarantee the correctness of such a thing.
So what can I do?
IMHO you can do nothing to really correct the situation.
You could assume that the types in ntdll have not changed so much. This would allow you to take an older version of wntdll.pdb and the new version of ntdll.dll and apply ChkMatch -m to it. This will copy the timestamp and checksum from the DLL to the PDB. After you did that (in an empty folder), replace the existing wntdll.pdb in your symbols directory with the hacked one.
WinDbg walkthrough (with output shortened to relevant things). I am using the latest version of wntdll.pdb I could find on my PC.
WARNING: doing the following may fix the type information but will likely destroy the correctness of the callstacks. Since any changes in the implementation (which are likely for security fixes) will change the method offsets.
0:005> dt nt!_PEB
*************************************************************************
*** ***
*** Either you specified an unqualified symbol, or your debugger ***
...
*** Type referenced: nt!_PEB ***
*** ***
*************************************************************************
Symbol nt!_PEB not found.
0:005> lm m ntdll
start end module name
773f0000 77570000 ntdll (pdb symbols) e:\debug\symbols\wntdll.pdb\FA9C48F9C11D4E0894B8970DECD92C972\wntdll.pdb
0:005> .shell cmd /c copy C:\Windows\SysWOW64\ntdll.dll e:\debug\temp\ntdllhack\ntdll.dll
1 file(s) copied.
0:005> .shell cmd /c copy "E:\Windows SDk\8.0\Debuggers\x86\sym\wntdll.pdb\B081677DFC724CC4AC53992627BEEA242\wntdll.pdb" e:\debug\temp\ntdllhack\wntdll.pdb
1 file(s) copied.
0:005> .shell cmd /c E:\debug\temp\ntdllhack\chkmatch.exe -m E:\debug\temp\ntdllhack\ntdll.dll E:\debug\temp\ntdllhack\wntdll.pdb
...
Executable: E:\debug\temp\ntdllhack\ntdll.dll
Debug info file: E:\debug\temp\ntdllhack\wntdll.pdb
Executable:
TimeDateStamp: 55a69e20
Debug info: 2 ( CodeView )
TimeStamp: 55a68c18 Characteristics: 0 MajorVer: 0 MinorVer: 0
Size: 35 RVA: 000e63e0 FileOffset: 000d67e0
CodeView format: RSDS
Signature: {fa9c48f9-c11d-4e08-94b8-970decd92c97} Age: 2
PdbFile: wntdll.pdb
Debug info: 10 ( Unknown )
TimeStamp: 55a68c18 Characteristics: 0 MajorVer: 565 MinorVer: 6526
Size: 4 RVA: 000e63dc FileOffset: 000d67dc
Debug information file:
Format: PDB 7.00
Signature: {b081677d-fc72-4cc4-ac53-992627beea24} Age: 4
Writing to the debug information file...
Result: Success.
0:005> .shell cmd /c copy E:\debug\temp\ntdllhack\wntdll.pdb E:\debug\symbols\wntdll.pdb\FA9C48F9C11D4E0894B8970DECD92C972\wntdll.pdb
1 file(s) copied.
0:005> .reload
Reloading current modules
.............................
0:005> dt nt!_PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
...
0:005> !heap -s
LFH Key : 0x219ab08b
Termination on corruption : DISABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
Virtual block: 00920000 - 00920000 (size 00000000)
Virtual block: 02c60000 - 02c60000 (size 00000000)
Virtual block: 02e10000 - 02e10000 (size 00000000)
...
Note: using ChkMatch like this has the benefit that you do not need to turn on .symopt- 100, since that option would affect all PDB files, and you would not find potential other symbol issues. If you don't mind using .symopt, you could simply copy an old wntdll.PDB over the new one.
The issue is now fixed according to Microsoft and Microsoft told me that you should clear your symbol cache to get the new PDBs, otherwise Windbg would use the old Symbols which miss the information.

What does "kernel tainted" mean?

My OS is Fedora 17. Recently, kernel tainted warning "kernel bug at kernel/auditsc.c:1772!-abrt" occurs:
This problem should not be reported (it is likely a known problem). A kernel problem occurred, but your kernel has been tainted (flags:GD). Kernel maintainers are unable to diagnose tainted reports.
Then, I get the following:
# cat /proc/sys/kernel/tainted
128
# dmesg | grep -i taint
[ 8306.955523] Pid: 4511, comm: chrome Tainted: G D 3.9.10-100.fc17.i686.PAE #1 Dell Inc.
[ 8307.366310] Pid: 4571, comm: chrome Tainted: G D 3.9.10-100.fc17.i686.PAE #1 Dell Inc.
It seems that the value "128" is much serious:
128 – The system has died.
How about this warning? Since chrome is flagged as the "Tainted" source, anybody also meet this matter?
To (over) simplify, 'tainted' means that the kernel is in a state other than what it would be in if it were built fresh from the open source origin and used in a way that it had been intended. It is a way of flagging a kernel to warn people (e.g., developers) that there may be unknown reasons for it to be unreliable, and that debugging it may be difficult or impossible.
In this case, 'GD' means that all modules are licensed as GPL or compatible (ie not proprietary), and that a crash or BUG() occurred.
The reasons are listed below:
See: oops-tracing.txt
---------------------------------------------------------------------------
Tainted kernels:
Some oops reports contain the string 'Tainted: ' after the program
counter. This indicates that the kernel has been tainted by some
mechanism. The string is followed by a series of position-sensitive
characters, each representing a particular tainted value.
1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
any proprietary module has been loaded. Modules without a
MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
insmod as GPL compatible are assumed to be proprietary.
2: 'F' if any module was force loaded by "insmod -f", ' ' if all
modules were loaded normally.
3: 'S' if the oops occurred on an SMP kernel running on hardware that
hasn't been certified as safe to run multiprocessor.
Currently this occurs only on various Athlons that are not
SMP capable.
4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
modules were unloaded normally.
5: 'M' if any processor has reported a Machine Check Exception,
' ' if no Machine Check Exceptions have occurred.
6: 'B' if a page-release function has found a bad page reference or
some unexpected page flags.
7: 'U' if a user or user application specifically requested that the
Tainted flag be set, ' ' otherwise.
8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
9: 'A' if the ACPI table has been overridden.
10: 'W' if a warning has previously been issued by the kernel.
(Though some warnings may set more specific taint flags.)
11: 'C' if a staging driver has been loaded.
12: 'I' if the kernel is working around a severe bug in the platform
firmware (BIOS or similar).
13: 'O' if an externally-built ("out-of-tree") module has been loaded.
14: 'E' if an unsigned module has been loaded in a kernel supporting
module signature.
15: 'L' if a soft lockup has previously occurred on the system.
16: 'K' if the kernel has been live patched.
The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is
unloaded, the tainted value remains to indicate that the kernel is not
trustworthy.
Also showing numbers for the content of /proc/sys/kernel/tainted file:
Non-zero if the kernel has been tainted. Numeric values, which can be
ORed together. The letters are seen in "Tainted" line of Oops reports.
1 (P): A module with a non-GPL license has been loaded, this
includes modules with no license.
Set by modutils >= 2.4.9 and module-init-tools.
2 (F): A module was force loaded by insmod -f.
Set by modutils >= 2.4.9 and module-init-tools.
4 (S): Unsafe SMP processors: SMP with CPUs not designed for SMP.
8 (R): A module was forcibly unloaded from the system by rmmod -f.
16 (M): A hardware machine check error occurred on the system.
32 (B): A bad page was discovered on the system.
64 (U): The user has asked that the system be marked "tainted". This
could be because they are running software that directly modifies
the hardware, or for other reasons.
128 (D): The system has died.
256 (A): The ACPI DSDT has been overridden with one supplied by the user
instead of using the one provided by the hardware.
512 (W): A kernel warning has occurred.
1024 (C): A module from drivers/staging was loaded.
2048 (I): The system is working around a severe firmware bug.
4096 (O): An out-of-tree module has been loaded.
8192 (E): An unsigned module has been loaded in a kernel supporting module
signature.
16384 (L): A soft lockup has previously occurred on the system.
32768 (K): The kernel has been live patched.
65536 (X): Auxiliary taint, defined and used by for distros.
131072 (T): The kernel was built with the struct randomization plugin.
Source: https://www.kernel.org/doc/Documentation/sysctl/kernel.txt
Credit: https://askubuntu.com/questions/248470/what-does-the-kernel-taint-value-mean

how do you build DTrace on Mac OS X?

I'm trying to build the dtrace target in the Xcode project using the
advice here:
http://osx86.boeaja.info/2009/10/building-xnu-kernel-on-snow-leopard/
But I get:
libproc.m:24:49: error: CoreSymbolication/CoreSymbolication.h: No such
file or directory
I realize CoreSymbolication is a private framework, but Apple must
make this header available somewhere in order for me to build dtrace,
right? Can someone point me to the necessary files to build dtrace?
As you probably figured out, Apple only has to release parts of the kernel which are taken from other open-source projects, and that doesn't include the userland libraries that they build on top of the kernel. CoreSymbolication/CoreSymbolication.h sounds a lot like a userspace header for Obj-C though, so you can probably build the kernel DTrace utilities without it. (Although I could very well be wrong.)
I would guess it's being used for symbol identification in the userland dtrace(1m) command. If only there was a tool that could help us figure this out... :-D
# dtrace -n 'pid$target:CoreSymbolication::entry {}' -c 'dtrace -ln syscall::write:entry'
dtrace: description 'pid$target:CoreSymbolication::entry ' matched 246 probes
ID PROVIDER MODULE FUNCTION NAME
147 syscall write entry
dtrace: pid 88089 has exited
CPU ID FUNCTION:NAME
2 6538 CSSymbolOwnerGetRegionWithName:entry
2 5014 CSSymbolOwnerForeachRegionWithName:entry
2 5078 CSRegionForeachSymbol:entry
2 6495 CSSymbolicatorGetSymbolOwnerWithUUIDAtTime:entry
2 6493 CSSymbolicatorForeachSymbolOwnerWithUUIDAtTime:entry
2 6494 CSSymbolicatorForeachSymbolOwnerWithCFUUIDBytesAtTime:entry
2 5048 CSSymbolOwnerGetDataFlags:entry
2 6538 CSSymbolOwnerGetRegionWithName:entry
2 5014 CSSymbolOwnerForeachRegionWithName:entry
2 5078 CSRegionForeachSymbol:entry
2 5092 CSSymbolIsExternal:entry
2 5092 CSSymbolIsExternal:entry
...
It looks like the library is in use by the dtrace command, anyway.

How does Linux Kernel know where to look for driver firmware?

I'm compiling a custom kernel under Ubuntu and I'm running into the problem that my kernel doesn't seem to know where to look for firmware. Under Ubuntu 8.04, firmware is tied to kernel version the same way driver modules are. For example, kernel 2.6.24-24-generic stores its kernel modules in:
/lib/modules/2.6.24-24-generic
and its firmware in:
/lib/firmware/2.6.24-24-generic
When I compile the 2.6.24-24-generic Ubuntu kernel according the "Alternate Build Method: The Old-Fashioned Debian Way" I get the appropriate modules directory and all my devices work except those requiring firmware such as my Intel wireless card (ipw2200 module).
The kernel log shows for example that when ipw2200 tries to load the firmware the kernel subsystem controlling the loading of firmware is unable to locate it:
ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2
errno-base.h defines this as:
#define ENOENT 2 /* No such file or directory */
(The function returning ENOENT puts a minus in front of it.)
I tried creating a symlink in /lib/firmware where my kernel's name pointed to the 2.6.24-24-generic directory, however this resulted in the same error. This firmware is non-GPL, provided by Intel and packed by Ubuntu. I don't believe it has any actual tie to a particular kernel version. cmp shows that the versions in the various directories are identical.
So how does the kernel know where to look for firmware?
Update
I found this solution to the exact problem I'm having, however it no longer works as Ubuntu has eliminated /etc/hotplug.d and no longer stores its firmware in /usr/lib/hotplug/firmware.
Update2
Some more research turned up some more answers. Up until version 92 of udev, the program firmware_helper was the way firmware got loaded. Starting with udev 93 this program was replaced with a script named firmware.sh providing identical functionality as far as I can tell. Both of these hardcode the firmware path to /lib/firmware. Ubuntu still seems to be using the /lib/udev/firmware_helper binary.
The name of the firmware file is passed to firmware_helper in the environment variable $FIRMWARE which is concatenated to the path /lib/firmware and used to load the firmware.
The actual request to load the firmware is made by the driver (ipw2200 in my case) via the system call:
request_firmware(..., "ipw2200-bss.fw", ...);
Now somewhere in between the driver calling request_firmware and firmware_helper looking at the $FIRMWARE environment variable, the kernel package name is getting prepended to the firmware name.
So who's doing it?
From the kernel's perspective, see /usr/src/linux/Documentation/firmware_class/README:
kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
userspace:
- /sys/class/firmware/xxx/{loading,data} appear.
- hotplug gets called with a firmware identifier in $FIRMWARE
and the usual hotplug environment.
- hotplug: echo 1 > /sys/class/firmware/xxx/loading
kernel: Discard any previous partial load.
userspace:
- hotplug: cat appropriate_firmware_image > \
/sys/class/firmware/xxx/data
kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
comes in.
userspace:
- hotplug: echo 0 > /sys/class/firmware/xxx/loading
kernel: request_firmware() returns and the driver has the firmware
image in fw_entry->{data,size}. If something went wrong
request_firmware() returns non-zero and fw_entry is set to
NULL.
kernel(driver): Driver code calls release_firmware(fw_entry) releasing
the firmware image and any related resource.
The kernel doesn't actually load any firmware at all. It simply informs userspace, "I want a firmware by the name of xxx", and waits for userspace to pipe the firmware image back to the kernel.
Now, on Ubuntu 8.04,
$ grep firmware /etc/udev/rules.d/80-program.rules
# Load firmware on demand
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper"
so as you've discovered, udev is configured to run firmware_helper when the kernel asks for firmware.
$ apt-get source udev
Reading package lists... Done
Building dependency tree
Reading state information... Done
Need to get 312kB of source archives.
Get:1 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (dsc) [716B]
Get:2 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (tar) [245kB]
Get:3 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (diff) [65.7kB]
Fetched 312kB in 1s (223kB/s)
gpg: Signature made Tue 14 Apr 2009 05:31:34 PM EDT using DSA key ID 17063E6D
gpg: Can't check signature: public key not found
dpkg-source: extracting udev in udev-117
dpkg-source: unpacking udev_117.orig.tar.gz
dpkg-source: applying ./udev_117-8ubuntu0.2.diff.gz
$ cd udev-117/
$ cat debian/patches/80-extras-firmware.patch
If you read the source, you'll find that Ubuntu wrote a firmware_helper which is hard-coded to first look for /lib/modules/$(uname -r)/$FIRMWARE, then /lib/modules/$FIRMWARE, and no other locations. Translating it to sh, it does approximately this:
echo -n 1 > /sys/$DEVPATH/loading
cat /lib/firmware/$(uname -r)/$FIRMWARE > /sys/$DEVPATH/data \
|| cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data
if [ $? = 0 ]; then
echo -n 1 > /sys/$DEVPATH/loading
echo -n -1 > /sys/$DEVPATH/loading
fi
which is exactly the format the kernel expects.
To make a long story short: Ubuntu's udev package has customizations that always look in /lib/firmware/$(uname -r) first. This policy is being handled in userspace.
Wow this is very useful information and it led me to the solution for my problem when making a custom USB kernel module for a device requiring firmware.
Basically, every Ubuntu brings a new rehash of hal,sysfs,devfs,udev,and so on...and things just change. In fact I read they stopped using hal.
So let's reverse engineer this yet again so it's pertinent to the latest [Ubuntu] systems.
On Ubuntu Lucid (the latest at time of writing), /lib/udev/rules.d/50-firmware.rules is used. This file calls the binary /lib/udev/firmware, where magic happens.
Listing: /lib/udev/rules.d/50-firmware.rules
# firmware-class requests, copies files into the kernel
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}"
The magic should be something along these lines (source: Linux Device Drivers, 3rd Ed., Ch. 14: The Linux Device Model):
echo 1 to loading
copy firmware to data
on failure, echo -1 to loading and halt firmware loading process
echo 0 to loading (signal the kernel)
then, a specific kernel module receives the data and pushes it to the device
If you look at Lucid's source page for udev, in udev-151/extras/firmware/firmware.c, the source for that firmware /lib/udev/firmware binary, that's exactly what goes on.
Excerpt: Lucid source, udev-151/extras/firmware/firmware.c
util_strscpyl(datapath, sizeof(datapath), udev_get_sys_path(udev), devpath, "/data", NULL);
if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) {
err(udev, "error sending firmware '%s' to device\n", firmware);
set_loading(udev, loadpath, "-1");
rc = 4;
goto exit;
};
set_loading(udev, loadpath, "0");
Additionally, many devices use an Intel HEX format (textish files containing checksum and other stuff) (wiki it i have no reputation and no ability to link). The kernel program ihex2fw (called from Makefile in kernel_source/lib/firmware on .HEX files) converts these HEX files to an arbitrary-designed binary format that the Linux kernel then picks up with request_ihex_firmware, because they thought reading text files in the kernel was silly (it would slow things down).
On current Linux systems, this is handled via udev and the firmware.agent.
Linux 3.5.7 Gentoo, I have the same issue.
SOLVED:
emerge ipw2200-firmware
Then go to /usr/src/linux
make menucofig
on device driver, remove all wirless drivers don't needed, set Intell 2200 as module and recompile.
make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault

Resources