Overview
The purpose of this guide is to explain how to use the class-code spoof technique to keep un-patched IONVMeFamily.kext (incompatible with most PC NVMe SSDs) from loading such that HackrNVMeFamily can be used along side it in EFI/Clover/kexts or installed to the system volume (/Library/Extensions, /System/Library/Extensions).
I first published the technique on insanelymac:
http://www.insanelymac.com/forum/to...er-macos-sierra-is-ready/page-29#entry2322636
You should be familiar with the patch_nvme.sh script as discussed in the patch-nvme README on github:
https://github.com/RehabMan/patch-nvme
Although there are many ways to patch IONVMeFamily, only the class-code spoof and HackrNVMeFamily is to be discussed here. It is my opinion that it is the best way. Keeping this post focused only on this single technique, used from installation through post-installation, is the least confusing way to approach the topic.
There are two different ways to implement the class-code spoof:
- SSDT with _DSM method to inject the modified class-code
OR
- using config.plist/Devices/Arbitrary to inject the modified class-code
Because using config.plist/Devices/Arbitrary precludes use of some commonly used Clover features (config.plist/Graphics/Inject), this post will discuss only the SSDT method.
Assumptions:
- installation of Windows on the target
- running install of macOS/OS X (same version as you plan for the target) on existing hack or Mac
- basic config.plist editing skills
- basic MaciASL usage
- basic Clover knowledge
- basic knowledge of installing/injecting kexts
Determining the ACPI path of your NVMe device(s)
In order to create an SSDT to inject class-code, you must know the ACPI path that describes where your SSD is located in ACPI namespace. You can use Windows Device Manager, or advanced users can determine it from ioreg. Both methods are described at the insanelymac link provided in the patch-nvme README.
Because this guide is intended to be used prior to installation, it will use Windows Device Manager. You will find your NVMe device in Windows Device Manager under "Storage Controllers" -> "Standard NVM Express Controller". Right click and choose Properties. Then click on the "Details" tab. Then find "BIOS device name" within the "Property" dropdown. Select it. Your NVMe SSD ACPI path will be displayed in the "Value" box.
View attachment 226134
If you have more than one NVMe SSD, you must find the ACPI path for each one.
Note: It is also possible that your SSD has no ACPI identity. I don't have such a computer at the moment (and the situation is probably rare), but in that case you may be able to determine only the ACPI identity of the parent (in the case of my NUC, the parent is _SB.PCI0.RP13), and slightly different SSDT would have to be created.
Creating SSDT-NVMe-Pcc.aml
Below you'll find a template you can use for your own SSDT that injects class-code. This is the actual SSDT that I use on my NUC6i7KYK with a Samsung 950 Pro NVMe SSD:
Code:
// Inject bogus class-code for NVMe SSD to prevent IONVMeFamily.kext from loading
DefinitionBlock("", "SSDT", 2, "hack", "NVMe-Pcc", 0)
{
External(_SB.PCI0.RP13.PXSX, DeviceObj)
Method(_SB.PCI0.RP13.PXSX._DSM, 4)
{
If (!Arg2) { Return (Buffer() { 0x03 } ) }
Return(Package()
{
"class-code", Buffer() { 0xff, 0x08, 0x01, 0x00 },
})
}
}
//EOF
The path shown above _SB.PCI0.RP13.PXSX is the path that my NUC6i7KYK uses. You will notice the same path was shown in the image from Windows Device Manager. You will need to replace both instances of it in the above SSDT to match the path for your own NVMe SSD.
If your SSD had no ACPI identity (eg. no ACPI identity for the M.2 port/device), you would need to create one. For example, if the OEM had left out the PXSX identity, it would have been required that I add one:
Code:
// Inject bogus class-code for NVMe SSD to prevent IONVMeFamily.kext from loading
DefinitionBlock("", "SSDT", 2, "hack", "NVMe-Pcc", 0)
{
External(_SB.PCI0.RP13, DeviceObj)
// Add PXSX device under RP13
Device(_SB.PCI0.RP13.PXSX) { Name(_ADR, 0) }
/// Now we can inject the method at RP13.PXSX
Method(_SB.PCI0.RP13.PXSX._DSM, 4)
{
If (!Arg2) { Return (Buffer() { 0x03 } ) }
Return(Package()
{
"class-code", Buffer() { 0xff, 0x08, 0x01, 0x00 },
})
}
}
//EOF
I don't know what is displayed in Windows Device Manager in that case, although it is predictable what ioreg would look like. Of course, the idea here is to create the SSD before installing macOS, so let me know if you have a situation with no ACPI identity for the SSD.
And if you have multiple NVMe SSDs, you must create a _DSM method for each. For example, my NUC also has a M.2 port at RP09 for an SSD. Currently, I have an SM951/AHCI installed there, so it is not NVMe. But if it was an NVMe drive, my SSDT would have to modified to include a _DSM method for it as well:
Code:
// Inject bogus class-code for NVMe SSD to prevent IONVMeFamily.kext from loading
DefinitionBlock("", "SSDT", 2, "hack", "NVMe-Pcc", 0)
{
External(_SB.PCI0.RP09.PXSX, DeviceObj)
Method(_SB.PCI0.RP09.PXSX._DSM, 4)
{
If (!Arg2) { Return (Buffer() { 0x03 } ) }
Return(Package()
{
"class-code", Buffer() { 0xff, 0x08, 0x01, 0x00 },
})
}
External(_SB.PCI0.RP13.PXSX, DeviceObj)
Method(_SB.PCI0.RP13.PXSX._DSM, 4)
{
If (!Arg2) { Return (Buffer() { 0x03 } ) }
Return(Package()
{
"class-code", Buffer() { 0xff, 0x08, 0x01, 0x00 },
})
}
}
//EOF
In order to use this SSDT, you must compile it as AML. You can use my version of MaciASL, which is linked from my ACPI patching guide:
https://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/
Use File.Save As, "SSDT-NVMe-Pcc.aml", Format: ACPI Machine Language Binary. Save to a location you can find, such as your desktop.
Now you can copy the SSDT-NVMe-Pcc.aml file such that Clover can load it. If you're preparing your USB, you'll place it on the EFI for USB, otherwise it will be on the EFI for your boot drive. In any case, it goes to EFI/Clover/ACPI/patched/SSDT-NVMe-Pcc.aml.
Note: If you're using config.plist/ACPI/SortedOrder (to set SSDT load order for patched OEM SSDTs), you must be certain SSDT-NVMe-Pcc.aml is in the SortedOrder list. When SortedOrder is specified, SSDTs in ACPI/patched that are not in SortedOrder are ignored by Clover. For most desktop scenarios and laptop scenarios where Clover ACPI hotpatching is being used, SortedOrder will not be specified and copying the file to ACPI/patched is sufficient to cause it be loaded.
Existing _DSM methods
It is possible your OEM already defined a _DSM method at the ACPI path that defines your NVMe SSD in ACPI namespace. ACPI does not allow duplicate symbols at the same path, so if you have an existing _DSM, the _DSM we are trying to add via SSDT-NVMe-Pcc.aml will be ignored.
Although you can patch DSDT (or any OEM SSDT that may have the offending _DSM), I like to use a Clover patch to rename all _DSM methods to XDSM. Clover ACPI patches are specified at config.plist/ACPI/DSDT/Patches.
An entry for _DSM->XDSM would be:
Comment: Change all _DSM to XDSM
Find: <5f44534d>
Replace: <5844534d>
As it appears in Xcode:
View attachment 226136
Renaming all _DSM to XDSM insures no existing _DSM at the NVMe SSD path. The _DSM injection via SSDT-NVMe-Pcc.aml will not work if there is an existing _DSM at that path.
You can find the _DSM to XDSM patch in config_patches.plist in the patch-nvme github project. It makes for easy copy/paste into your own config.plist.
Creating HackrNVMeFamily*.kext with the spoofed class-code
This is described in the patch-nvme README quite clearly, but here is a quick overview with special attention to the --spoof option.
As per patch-nvme README, we must make a copy of the github project:
Code:
mkdir ~/Projects
cd Projects
git clone https://github.com/RehabMan/patch-nvme.git patch-nvme.git
cd patch-nvme.git
Since your NVMe SSD will not be using the standard class-code, but instead a non-standard one, the resulting HackrNVMeFamily*.kext must use the non-standard IOPCIClassMatch instead of the standard one.
To do this we use the --spoof option. For example, to create HackrNVMeFamily for 10.12.2:
Code:
cd ~/Projects/patch-nvme.git
./patch_nvme.sh --spoof 10_12_2
The result will be HackrNVMeFamily-10_12_2.kext which can be placed in EFI/Clover/kexts/Other for injection via Clover (installer or recovery scenario), or installed to the system volume (post-install scenario).
You can install kexts easily with Terminal. For example, to install the generated HackrNVMeFamily-10_12_2.kext:
Code:
cd ~/Projects/patch-nvme.git
sudo cp -R HackrNVMeFamily-10_12_2.kext /Library/Extensions
You can rebuild cache to verify cache can be built without error:
Summary
To use the resulting HackrNVMeFamily*.kext:
- make sure the SSDT-NVMe-Pcc.aml is in EFI/Clover/ACPI/patched
- make sure existing _DSM methods at the NVMe SSD ACPI path are renamed or deleted
- install the HackrNVMeFamily*.kext or inject it via EFI/Clover/kexts
By using the SSDT, we inject a bogus class-code such that IONVMeFamily.kext does not match and therefore does not load. But because of the modified IOPCIClassMatch in the HackrNVMeFamily Info.plist created by the patch_nvme.sh script with the --spoof option, it does match on the modified class-code, and is patched for the 512 byte block size used by typical PC NVMe SSDs.
By using the class-code spoof from the very beginning, you're using the same mechanism during installation and post-installation. And once the class-code spoof is implemented, there is never any chance of IONVMeFamily.kext causing a problem. Updating is simplified as well, since you can most likely use the previous HackrNVMeFamily for the updated system until you have a chance to create a new HackrNVMeFamily after the update. And because IONVMeFamily was never deleted, it is always easy to create the new HackrNVMeFamily*.kext after the update is complete and the patch set for that version is available.
Problem Reporting
Provide a detailed and concise description of the problem.
If your drive is not recognized by the macOS/OS X installer or you are getting a panic...
Provide image from Windows Device Manager showing the ACPI namespace path of your SSD.
Attach EFI/Clover folder
as ZIP (press F4 at main Clover screen before collecting). Please
eliminate 'themes' directory. Provide only EFI/Clover, not the entire EFI folder.