New style of AppleHDA.kext patching

Someone at work asked me today how I stop AppleHDA.kext from breaking with (almost) every OS update. Okay. This is probably something that most of you here are interested in so let me share that here as well.

The motherboards I use require patched resource files, being layout-3.xml.zlib and Platforms.xml.zlib Nothing new you say. Right. Most people will need patched files, thanks to people like Toleda, but the neat thing is that I trick AppleHDA into loading the resources files from a dummy kext! Yeah. This is something that you won’t find anywhere else, and it took me some time to figure it out, but this is how I did it:

1) sudo cp -R /S*/L*/Extensions/AppleHDA.kext /S*/L*/Extensions/AppleHDA8Series.kext

2) cd /S*/L*/Extensions/AppleHDA8Series.kext/C*

3) sudo rm -R PlugIns

4) sudo rm -R _CodeSignature

5) sudo rm Resources/*.xml.zlib

6) sudo rm -rf Resources/*.lproj

7) sudo rm version.plist

8) sudo cp ~/Desktop/layout-3.xml.zlib Resources/

Note: Change the path/filename so that it points to the file you need for your motherboard!

9) sudo cp ~/Desktop/Platforms.xml.zlib Resources/

Note: Change the path/filename so that it points to the file you need for your motherboard!

10) sudo rm MacOS/AppleHDA

11) sudo ln -s /System/Library/Extensions/AppleHDA.kext/Contents/MacOS/AppleHDA MacOS/AppleHDA

12) sudo nano Info.plist (change version info from: 2.5.3 into: 9.1.1fc1)

13) sudo touch /S*/L*/Extensions

14) sudo reboot now

The trick is simple. OS X will load AppleHDA8Series.kext before AppleHDA.kext due its name and version info, and that basically stops AppleHDA.kext from loading. Then the binary, the one it finds pointed by the symbolic link, is loaded and that in turn loads the resource files from AppleHDA8Series.kext. The binary also loads/fires up the PlugIns from AppleHDA.kext (or AppleHDA8Series.kext if you prefer that).

This way the bootloader can bin-patch the AppleHDA binary on-the-fly, and when required AppleHDAController for HDMI support, or you can simply skip step 10 and 11 and patch AppleHDA8Series.kext/Contents/MacOS/AppleHDA manually, with whatever command line tool you normally use, but please note that you probably need to change path/filename info in (Perl) scripts as it doesn’t know what to use!

People who need to bin-patch AppleHDAController, for example for HDMI support, can run the following additional terminal commands before proceeding with steps 13 and 14:

*) sudo mkdir PlugIns

*) sudo cp -R /S*/L*/Extensions/AppleHDA.kext/C*/P*/AppleHDAController.kext PlugIns/

*) sudo nano PlugIns/AppleHDAController.kext/C*/Info.plist (change version info from: 2.5.3 into: 9.1.1fc1)

Please note that this should only be required when the boot loader cannot bin-patch AppleHDAController for you!

Oh and let me know if this works for you as well. Thanks!

Update:
Oops. I completely forgot to mention that I also add the CodecData in Info.plist as well (under >IOKitPersonalities/HDA Hardware Config Resource) with a changed CFBundleIdentifier (set to com.apple.driver.AppleHDA) or kextutil will complain about it. This way I have everything tidied up in one file.

Note: I set the layout-id property from (EFI) device-properties instead of a ACPI _DSM method.

Update-2:
Someone asked me (per e-mail) if we can use this trick for other kexts as well. But of course you can! That is the whole idea of this new concept, but since AppleHDA.kext patching is something everyone has to deal with… making it a perfect candidate to show you what to do. Have fun now!

Update-3:
You may have found the following message(s) in: /var/log/system.log

Refusing new kext com.apple.driver.AppleHDA, v2.5.3f1: already have prelinked v9.1.1f1.

And when you copied AppleHDAController.kext into AppleHDA8Series.kext/C*/PlugIns then you will also see this message:

Refusing new kext com.apple.driver.AppleHDAController, v2.5.3f1: already have prelinked v9.1.1f1.

Two completely harmless messages. In my view a small price for being able to skip AppleHDA updates. Not to mention that you can copy other kexts like FakeSMC.kext and the one for your network adapter(s) into PlugIns as well. This way you combine several kexts into one. Making one platform specific kext to make updates and re-installations a heck of a lot easier, as all you have to copy is one single kext, but make sure it loads AppleHDA8Series.kext, or whatever it is you use, or your hack won’t even boot anymore!!!

Edit:
This is the XML snippet that I have in: AppleHDA8Series.kext/Contents/Info.plist

		<dict>
			<key>CFBundleIdentifier</key>
			<string>com.apple.driver.AppleHDA</string>
			<key>HDAConfigDefault</key>
			<array>
				<dict>
					<key>CodecID</key>
					<integer>283904146</integer>
					<key>ConfigData</key>					<data>IUccECFHHUAhRx4RIUcfASFXHCAhVx0QIVceASFXHwEhZxzwIWcdACFnHgAhZx9AIXcc8CF3HQAhdx4AIXcfQCGHHEAhhx2QIYceoSGHH5AhlxxQIZcdkCGXHoEhlx8CIaccYCGnHTAhpx6BIacfASG3HHAhtx1AIbceISG3HwIh5xyQIecdYSHnHksh5x8BIfcc8CH3HQAh9x4AIfcfQCEXHPAhFx0AIRceACEXH0A=</data>
					<key>FuncGroup</key>
					<integer>1</integer>
					<key>LayoutID</key>
					<integer>3</integer>
				</dict>
			</array>
			<key>IOClass</key>
			<string>AppleHDAHardwareConfigDriver</string>
			<key>IOMatchCategory</key>
			<string>AppleHDAHardwareConfigDriver</string>
			<key>IOProviderClass</key>
			<string>AppleHDAHardwareConfigDriverLoader</string>
			<key>PostConstructionInitialization</key>
			<array>
				<dict>
					<key>CodecID</key>
					<integer>283904146</integer>
					<key>Layouts</key>
					<array>
						<integer>1</integer>
						<integer>2</integer>
						<integer>3</integer>
					</array>
					<key>widgets</key>
					<array>
						<dict>
							<key>MicAttributes</key>
							<integer>28</integer>
							<key>MicInfo</key>
							<string>Sampled on rising edge</string>
							<key>NodeID</key>
							<integer>39</integer>
							<key>PinConfigDefault</key>
							<integer>2426405136</integer>
						</dict>
					</array>
				</dict>
			</array>
		</dict>

Please note that I set the PinConfigurations property from pre-configured (EFI) device-properties in: /Extra/EFI/MacPro61.bin – this is a RevoBoot only feature – simply because setting device-properties from the boot loader is much faster, be it less flexible, but I don’t have to care about that for my setup.

Edit: No. I thought that I did it that way, but apparently not. Oops.

Update-4:
A number of people – Toleda among others – reported that AppleHDAHardwareConfigDriver.kext wasn’t loading, or not at every startup. At first I couldn’t reproduce it myself, but I think to have found a workaround for this, in my view, Apple bug. Here’s what I did:

1) cd /S*/L*/Extensions/AppleHDA8Series.kext/C*

2) sudo mkdir PlugIns (but only in case you don’t already have it)

3) cd PlugIns

4) sudo mkdir -p AppleHDAHardwareConfigDriver.kext/Contents

5) cd AppleHDAHardwareConfigDriver.kext/Contents

6) sudo cp /S*/L*/Extensions/AppleHDA.kext/C*/P*/AppleHDAHardwareConfigDriver.kext/C*/Info.plist .

7) Added the following snippet to the plist:

<dict>
	<key>CodecID</key>
	<integer>283904146</integer>
	<key>ConfigData</key>
	<data>IUccECFHHUAhRx4RIUcfASFXHCAhVx0QIVceASFXHwEhZxzwIWcdACFnHgAhZx9AIXcc8CF3HQAhdx4AIXcfQCGHHEAhhx2QIYceoSGHH5AhlxxQIZcdkCGXHoEhlx8CIaccYCGnHTAhpx6BIacfASG3HHAhtx1AIbceISG3HwIh5xyQIecdYSHnHksh5x8BIfcc8CH3HQAh9x4AIfcfQCEXHPAhFx0AIRceACEXH0A=</data>
	<key>FuncGroup</key>
	<integer>1</integer>
	<key>LayoutID</key>
	<integer>3</integer>
</dict>

Your snippet will most likely be different since ConfigData is missing here, but that is because I set the PinConfigurations property from EFI device-properties.

Edit: No. I thought that I did it that way, but apparently not. I did in fact add the ConfigData there. Like everyone else. Oops.

8) Then I removed all other CodecID related data from the plist and went on with the next step

9) sudo mkdir MacOS

10) cd MacOS

11) sudo ln -s /System/Library/Extensions/AppleHDA.kext/Contents/PlugIns/AppleHDAHardwareConfigDriver.kext/Contents/MacOS/AppleHDAHardwareConfigDriver AppleHDAHardwareConfigDriver

12) sudo touch /S*/L*/Extensions

13) sudo reboot now

What we do here is simple. We use another symbolic link, this time to another binary file, and we copy the Info.plist which we use for our edits.

Edit: If this workaround isn’t working for you, then add a IOProbeScore like so:

<string>AppleHDAHardwareConfigDriverLoader</string>
<key>IOProbeScore</key>
<integer>2000</integer>

Just the two last lines of course 😉

40 thoughts on “New style of AppleHDA.kext patching

      • No sir, it only deleles *.lproj, which are actually folders. The Resources folder is not deleted. Also, we miss this before creating symbolic link:
        sudo rm MacOS/AppleHDA

        Your method + kext patching by Clover bootloader help me forget about AppleHDA after update. Thank you.

  1. Pingback: OS X Mavericks 10.9.2 Seeded | Pike's Universum

  2. My AppleHDA needs a custom AppleHDAHardwareConfigDriver.kext info.plist to make inputs/outputs work correctly, do you know how I could load that kext with the modified plist? tried to add it to PlugIns folder of the dummy hda kext but it doesn’t work…

    • Sure. You can either add the HDA Hardware Config Resource data to AppleHDA8Series.kext/C*/Info.plist or add it to AppleHDA8Series.kext/C*/PlugIns/AppleHDAHardwareConfigDriver.kext/C*/Info.plist – people in need of a patched binary can use the latter when their boot loader can’t handle it.

      • Tried both combinations and doesn’t work…
        The dummy kext never injects the data and generic ones are used instead.
        In case of AppleHDAHardwareConfigDriver.kext with plist only it doesn’t load (I dont’t need binhack just info.plist).
        On the other hand zlib files load probably.

      • In that case you are doing something wrong. I have no idea what, yet, but since I don’t even know the version of OS X and AppleHDA.kext that you using… I have to guess. Feel free to e-mail me the dummy kext (see ssdtPRGen.sh for my e-mail address).

      • I have the exact same problem and I’m 100% sure my kext is alright, since it didn’t work with one I mad and with one that was made by somebody who actually got it working for his machine. When I use patched info.plist in HardwareConfigDriver (and optionally dummy kext), everything is fine – but once I use stock HardwareConfigDriver and put the modified “HDA Hardware Config Resource” section only in the dummy’s plist, Audio is broken. I tried around for 2 hours, it is definitely fact, that the HardwareConfig kext uses stock info.plist instead of the dummy’s. I hope you will find the problem, since this concept saves a LOT of time and would make my OS X 100% vanilla 🙂

        I’m on OS X 10.9.1 by the way and run the latest Clover boot loader, which also patches the AppleHDA bin. Thanks and merry christmas!

      • Without the AppleHDA8Series.kext/Contents/Info.plist I cannot help you. Feel free to add a link to the file so that I can look at it.

        Some people told me that for them it doesn’t work all the time, only so many startups. What we have to do now is to figure out why, but it looks like a bug in Apple code. We need a working workaround. Will keep you and everyone else posted.

        Someone who set the audio properties as EFI device-properties confirmed that a sleep/wake cycle made audio work for him. Even when SystemProfiler reported that the AppleHardwareConfigDriver.kext wasn’t loaded!

      • I have Emailed you my kext.
        Do you know how to inject AppleHDAHArdwareConfigDriver.kext’s info.plist using EFI strings?

      • I solved my problem by renaming the dummy kext into something coming before “AppleHDA”. But now there’s another problem: I’m on OS X 10.9.1 and it prefers Apple-signed kexts. So, when I use Apple-signed AppleHDA.kext, it loads it, no matter if the other’s version is higher. However, when I delete “_CodeSignature” from AppleHDA.kext, the dummy loads with no additional message it log. When I have a proper, Apple-signed AppleHDA in S/L/E, along with the dummy, it shows the message you stated in your post (“Refusing new kext com.apple.driver.AppleHDA, v2.5.3f1: already have prelinked v9.1.1f1.”) with reverse version numbers. I have no idea why this happens, since it worked only a few hours earlier, but OS X definitely prefers Apple-signed kexts for me. Is there any other way than signing up as a developer and signing kexts? Thank you in advance!

      • I will try to reproduce this when I have soem time, but right now I am too busy with other stuff, like updating ssdtPRGen.sh and dpEdit.sh (and write new blog posts).

  3. I finally got this to work after playing around with it several times which took a whole day along with the help of Toleda’s hack that works with my inboard sound. Here’s my recommendation to save the LOT of hard time that other people may have after making the dummy kext, of course for those who use ALC8xx at least (Pike, please feel free to include this under your blog if you’d like):

    Steps 8, 9, 13, and 14 can be skipped if you download the relevant file needed here for your sound board, but please do all the other required steps beforehand: https://github.com/toleda?tab=repositories
    From there, we’ll have to change a couple of things with a text editor
    – The .command file you will use (example: -85 or -91 will be for 10.8.5 or 10.9.1, respectively); in here, you will want to change the text which says “AppleHDA.kext” to “AppleHDA8Series.kext” – or whatever it is you use, as Pike mentioned. Once that’s done, execute the command file that you have edited.
    – Though it says “Finished, restart required.”, before we do that let’s change the Info.plist file for our kext(s) under /System/Library/Extensions/AppleHDA8Series.kext/Contents/PlugIns
    – Under there, change each Info.plist version number info from 2.x.x to 9.1.1
    – Once all of that’s done, you can restart.

    If you want to go the extra mile for a true vanilla experience as each update rolls out (I just tested this on my machine, therefore please let me know if this works for you), you can make a logout hook for it. To do this, you’ll need to use the terminal (this is for my case as an example, yours may be different):
    sudo defaults write com.apple.loginwindow LogoutHook ~/.logouthook
    echo $’#!/bin/bash\nperl -pi -e \’s|\x8b\x19\xd4\x11|\x89\x08\xec\x10|g\’ /System/Library/Extensions/AppleHDA8Series.kext/Contents/MacOS/AppleHDA\nchown -R root:wheel /System/Library/Extensions/AppleHDA8Series.kext\nrm -fr /System/Library/Caches/*\ntouch /System/Library/Extensions’ > ~/.logouthook
    Note: My string is “\’s|\x8b\x19\xd4\x11|\x89\x08\xec\x10|g\'” since I’m using ALC889, check inside your .command file for the string you need.
    chmod +x ~/.logouthook

    – Done!

    What a logout hook does is that every time you logout in any way (this includes restarts and shutdowns), any command that lies within the logout hook will execute in that instance. What does this mean for you? To put it simply as a perfect example here, I updated to 10.9.2 (the one seeded for Apple developers) and of course it broke my audio, but my dummy kext still exists along with the needed library files! Therefore, I needed to bin-patch yet again which of course may annoy people all the time (I know at least it does to me), so why not automate it when a user logs out. That is the purpose of this nifty script that Apple has, so okay, take the advantage of it!

    Pike, please let me know of thoughts as well. Since it is your blog after all, please make modifications that you see fit.

    • There are many ways to automate a patch-script, but it should always check if it needs to be executed or that it can bail out early. I mean the way you do it now will always run the commands. Even when you don’t need it. You don’t want that.

      • Fair enough Pike,

        I changed it this way so that it’s much cleaner:
        echo $’#!/bin/bash\nif grep -o \’\x8b\x19\xd4\x11\’ /System/Library/Extensions/AppleHDA8Series.kext/Contents/MacOS/AppleHDA\nthen\nperl -pi -e \’s|\x8b\x19\xd4\x11|\x89\x08\xec\x10|g\’ /System/Library/Extensions/AppleHDA8Series.kext/Contents/MacOS/AppleHDA\nchown -R root:wheel /System/Library/Extensions/AppleHDA8Series.kext\nrm -fr /System/Library/Caches/*\ntouch /System/Library/Extensions\nfi’ > ~/.logouthook

        Note: The hex strings (\x89\x08\xec\x10 or \x8b\x19\xd4\x11) will show up as encoded strings, and it would be better to change them back to the readable hex codes; I would at least do that in the grep check so that the command can execute if needed.

  4. Pingback: New style of AppleHDA.kext patching (take III) | Pike's Universum

  5. Thanks. It works OK

    I made a kext for my board using this article.

    Edit by Pike: Sorry. I have removed the link to your dropbox account because links to copyrighted material are prohibited here.

  6. Hey Pikeralpha,

    I don’t know if this is something I could use and frankly I am not sure how to use it as I only read through it quickly. I am trying to get HDMI audio working on my Mac Pro 2,1 with a GTX570. It works fine when I am using a boot loader like Clover (and have HDMIAudio.kext installed) or when I am running Windows. Also, it used to work with the HDMIAudio.kext installed but after updating to 10.9.3 (booted with Tiamo’s boot.efi) it stopped working. I would love to find a way to get HDMI audio back, especially when using the new boot.efi you have been working on for Yosemite.

    • Do you have the source code of HDMIAudio.kext? If not, ask the author for it. I could use it to see what it does. Probably just setting some properties, but that’s something to find out when we have the source code.

      And with Clover the kext is still working, or do you use GPU/HDMI patches in Clover?

      I would also love to get two IORegistryExplorer dumps (working/broken HDMI audio). That may help (see scripts in Github repositories for e-mail address).

  7. On my Laptop, Acer Aspire 5741g with Realtek ALC272, AppleHDA on-the-fly patching work very well. Thanks for all the hardwork! 🙂

    But if I put DummyHDA.kext on CLOVER/kext/10.10 this not work.
    1-I wanna know why fail?
    2-Any posible solution to put DummyHDA kext outside S/L/E?

    Thanks!

    • Sorry. I do not use clover and I don’t know how it works. I mean. I know that it can inject kexts but when it does and how is unknown to me. I also have no intention to get this functional with clover because it was not developed for clover.

      Note: I may have to look into this after RevoEFI is released, some time next year, but not now.

  8. Then is it not possible to use it with SIP fully enabled? I have tried to place it inside /Extra/Extensions as described in your SIP bypass article and also created a symlink of /System/Library/Extensions/AppleHDA.kext in /Extra/Extensions but it did loaded with SIP fully enabled.

Leave a comment