Contribute
Register

[Guide] Creating a Custom SSDT for USBInjectAll.kext

Hi Rehabman. I followed your guide and created my own injector, in the format of both SSDT and KEXT.
In the trial, the KEXT can disable the port I do not want to use, which would, otherwise, trigger an error during startup.
However, the SSDT file cannot disable the port.
Personally, I am apt to use SSDT method. In addition, I want to know why SSDT method cannot disable it.
Please let me know if you have a solution. Thanks!
 

Attachments

  • ioreg.zip
    859.1 KB · Views: 64
  • SSDT-UIAC.dsl
    4.1 KB · Views: 97
  • USB_Series8_Injector.kext.zip
    4 KB · Views: 72
Hi Rehabman. I followed your guide and created my own injector, in the format of both SSDT and KEXT.
In the trial, the KEXT can disable the port I do not want to use, which would, otherwise, trigger an error during startup.
However, the SSDT file cannot disable the port.
Personally, I am apt to use SSDT method. In addition, I want to know why SSDT method cannot disable it.
Please let me know if you have a solution. Thanks!

Read post #1, "Problem Reporting".
 
In order to discover which ports need to be in the SSDT, we will use IORegistryExplorer:

- run IORegistryExplorer
- test each port with both USB2 and USB3 devices

Since IORegistryExplorer tracks changes to IOKit objects (existing objects black, new objects in green, disconnected objects in red), we can use the data to determine which ports are actually used.

Moved to this posting.

The issue is that I can't seem to get my IORegExplorer to show me what USB ports are attached to what connectors. When I connect or disconnect from a USB port nothing appears or disappears in the IORegExplorer. But I see the device connected in the Finder.

I'm missing something fundamental - but what?

Also I see in IOReg that there is a EH01, EH02, MCHC, RP06, PR08, SATA, XHC listed under AppleaCPIPCI. Are all these to be counted to the limit of 15?

So if I count fully there are:

EH01 : 8
EH02 : 6
MCHC: 1
RP06 : 1
RP08 : 1
SATA : 1
XHC : 8
-----------
total : 26 ?

And the target is to reduce this to the 15 active ports?

If I've set something up wrong, and if you can correct me, how does one next test the MCHC, RP06, RP08, SATA ports - i.e assuming we get the USB2/USB3 ports identified.

I have attached my .zip file. I echoed the kextstat and other commands to the ascii terminal.output file in the .zip. Think I have everything you asked for.

Guess I'm just missing this entirely.

Finally, I can't see in your instructions explicit directions to uninstall the USBInjectAll.kext, FakePCII.kext and FakePCIID_XHCIMux.kext, AFTER the SSDT is correctly loaded, - but I assume that's what one does?

Oh this is my GA-Z77x-UP5-TH Hachintosh build.

Thanks
 

Attachments

  • Rehabman.zip
    5.3 MB · Views: 68
Last edited by a moderator:
Moved to this posting.

The issue is that I can't seem to get my IORegExplorer to show me what USB ports are attached to what connectors. When I connect or disconnect from a USB port nothing appears or disappears in the IORegExplorer. But I see the device connected in the Finder.

I'm missing something fundamental - but what?

Also I see in IOReg that there is a EH01, EH02, MCHC, RP06, PR08, SATA, XHC listed under AppleaCPIPCI. Are all these to be counted to the limit of 15?

So if I count fully there are:

EH01 : 8
EH02 : 6
MCHC: 1
RP06 : 1
RP08 : 1
SATA : 1
XHC : 8
-----------
total : 26 ?

And the target is to reduce this to the 15 active ports?

If I've set something up wrong, and if you can correct me, how does one next test the MCHC, RP06, RP08, SATA ports - i.e assuming we get the USB2/USB3 ports identified.

I have attached my .zip file. I echoed the kextstat and other commands to the ascii terminal.output file in the .zip. Think I have everything you asked for.

Guess I'm just missing this entirely.

Finally, I can't see in your instructions explicit directions to uninstall the USBInjectAll.kext, FakePCII.kext and FakePCIID_XHCIMux.kext, AFTER the SSDT is correctly loaded, - but I assume that's what one does?

Oh this is my GA-Z77x-UP5-TH Hachintosh build.

Thanks

In ioreg, you will find already connected devices in black, newly connected devices in green, and disconnected devices in red.
Don't make the mistake of using search. Just look at the EH01/EH02/XHC nodes in the left hand IOService tree.

The port limit is per controller, not system wide.

Hint: If there are no explicit instructions to do something, it is not what you should be doing. Keep in mind the title of this thread "custom SSDT for USBInjectAll.kext". Given the word 'for', it would not make much sense to delete USBInjectAll.kext, would it?
 
Overview

One of the serious issues most users will face with 10.11.x (and later, including 10.12.x) is the new USB stack in OS X/macOS. It has a much heavier reliance on ACPI, and as a result is much more likely to expose bugs in your ACPI implementation of _PLD, and _UPC.

It is covered in detail in my guide: https://www.tonymacx86.com/threads/guide-10-11-usb-changes-and-solutions.173616/

You should be familiar with the writeup above before attempting a custom SSDT.

Many tend to over-simplify the problem, and, for example, believe they can simply apply the port-limit patch and install USBInjectAll.kext and be done with it. In fact, the port limit patch is known to cause problems (it causes access outside a fixed array bounds). Somewhat alarming is the fact that Multibeast includes the port limit patch without mention of its problems.

The fact: Using the port limit patch is not a long term solution. For reliable USB (assuming your ACPI implementation of _PLD and _UPC is broken... and you don't want to fix it), you must implement a custom SSDT for USBInjectAll.kext that configures your ports on XHC such that the port limit patch is not needed, and each UsbConnnector value is correct for each port.

Not only does a custom SSDT allow you to avoid the port limit patch, disabling USB ports that are not used, can have some power saving properties, and can avoid bugs with sleep, restart, or shutdown.

This guide will show how this is done.

The process consists of the following steps:
- preparation for port discovery
- port discovery
- creating custom SSDT for USBInjectAll.kext
- testing/verification

The MaciASL used by this guide is available here: https://bitbucket.org/RehabMan/os-x-maciasl-patchmatic/downloads/
Make sure you have ACPI 6.1 selected in MaciASL->Preferences->iASL.


Preparation for port discovery

In order to create a custom SSDT that contains the correct data for a given computer's USB arrangement, we must first discover all the ports that need to be enabled. Once we know which ports are used, we can eliminate the unused ports.

In order to discover the ports, we need to be certain all ports are enabled.

Requirements:
- EHC1->EH01 and EHC2->EH02 rename (in config.plist), if applicable (your chipset may not have EHCI, or it may be disabled)
- XHCI controller must be named XHC (for most PCs it is default)
- port limit patch (in config.plist)
- install USBInjectAll.kext (install to the system volume)
- if you plan to use it, install FakePCIID.kext + FakePCIID_XHCIMux.kext
- if you have an existing SSDT for USBInjectAll, use -uia_ignore_rmcf
- XHCI injector kext, if required (200-series need XHCI-200-series-injector.kext)

The EHCx renames and port limit patches are available in config_patches.plist (https://github.com/RehabMan/OS-X-USB-Inject-All/raw/master/config_patches.plist) in the USBInjectAll.kext repository. Use copy/paste from a plist editor to get them into your own config.plist.

The EHCx renames look like this in Xcode:
View attachment 228080

The port limit patches look like this in Xcode:
View attachment 228081

The -uia_ignore_rmcf is added to config.plist/Boot/Arguments:
View attachment 228083

After preparing for port discovery, you should check in ioreg that all ports are injected for your chipset on both EHCI and XHCI controllers.

This is what full injection looks like on my NUC6i7KYK (Skylake).
You can see the same ports are injected as provided in the 'ports' dictionary from USBInjectAll.kext:
View attachment 228140

And here is what it looks like on my Lenovo u430 using FakePCIID_XHCIMux.kext.
Note they are the same as the ports provided by USBInjectAll.kext.

XHC:
View attachment 228103

EH01:
View attachment 228104

Once you have all ports being injected, you can proceed to the next step where you will determine which ports are actually needed.


Port discovery

In order to discover which ports need to be in the SSDT, we will use IORegistryExplorer:

- run IORegistryExplorer
- test each port with both USB2 and USB3 devices

Since IORegistryExplorer tracks changes to IOKit objects (existing objects black, new objects in green, disconnected objects in red), we can use the data to determine which ports are actually used.

IORegistryExplorer.app can be downloaded from the attachment at this thread: http://www.tonymacx86.com/audio/58368-guide-how-make-copy-ioreg.html

After you download and extract IORegistryExplorer.app, run it. And keep it running throughout the test.

Test each port by inserting a USB2 device, then remove it, then insert a USB3 device and remove it. If you look carefully while you insert and remove the devices you can see which ports are assigned to which physical port (you will see the changes in ioreg).

Note: If you have a USB3 hub it can make it easier to test each port. Since a USB3 hub connects to both the USB3 pins and the USB2 pins of a USB3 port (and can be used in a USB2-only port), and it requires no action to eject properly, you will find it much quicker to use a USB3 hub instead of a set of USB2/USB3 memory sticks. In the examples that follow, I'm using a USB3 hub to test ports.

Note that to test each port properly, you may need to move any USB keyboard or mouse device around so that you can test each port with both USB2 and USB3 (or USB3 hub).

On my NUC6i7KYK, this is XHC before starting to test the USB ports:
View attachment 228141

You can see that only the HS03 port is being used. The HS03 port happens to be where my Dell U3011 USB hub is plugged in, which also happens to have my USB keyboard/mouse dongle. The HS09 is the internal bluetooth controller.

After testing all ports:
View attachment 228142

I usually monitor ioreg as I plug and unplug devices so I know where the ports are located physically.
As you can see, the following ports are used:
HS01/SS01: USB3 front left
HS02/SS02: USB3 front right
HS03/SS03: USB3 rear bottom
HS04/SS04: USB3 rear top
HS09: bluetooth

Note that the SSxx ports will have a corresponding HSxx port. The SSxx port (or SSPx) is used when you plug in a USB3 device. The HSxx port is used when you plug in a USB2 device. USB2 only ports will use only HSxx.

So, although the controller used on this Skylake computer has the potential for 26 ports (HS01-HS14, SS01-SS10, USR1, USR2), only 9 ports are connected. We can eliminate HS05-HS08, HS10-HS14, SS05-SS10, USR1, and USR2.

Let's take a look at the test results for my Lenovo u430 (using FakePCIID_XHCIMux.kext).

Before testing:
View attachment 228112

View attachment 228111

After testing all ports:
View attachment 228113

View attachment 228114

Ports used (EH01/HUB1/XHC):
PR11: internal hub
HP11: touchscreen
HP12/SSP1: USB3 left
HP14: USB2 far right
HP15: USB2 near right
HP15: camera
HP16: bluetooth

Or, if we remove FakePCIID_XHCIMux.kext:

Before testing:
View attachment 228116

View attachment 228117

After testing:
View attachment 228122

View attachment 228123

Ports used (only on XHC):
HS01: touchscreen
HS02/SSP1: USB3 left
HS02: USB2 far right
HS03: USB2 near right
HS05: camera
HS06: bluetooth

As you can see, FakePCIID_XHCIMux.kext has the effect of moving all HSxx ports to EHCI (to the internal hub on EH01.PR11).

After you have collected the data in IORegistryExplorer, and you are certain that is accurate, you are now prepared to create a custom SSDT based on the data you have obtained in ioreg.


Creating custom SSDT for USBInjectAll.kext

USBInjectAll.kext is coded in a data driven way. Nothing is hard-coded in the kext code itself. All data is contained in the Info.plist. When USBInjectAll.kext starts, matching on EH01/EH02/XHC, or the internal hubs connected to EH01/EH02 port 1, it consults the configuration data in Info.plist as related to the device it has attached to and injects the data it finds there. But an SSDT can be used to override the data in the Info.plist.

A template is provided in the USBInjectAll.kext github repo, SSDT-UIAC-ALL.dsl, which has overrides for all the data already in the USBInjectAll.kext Info.plist. You could compile SSDT-UIAC-ALL.dsl to SSDT-UIAC-ALL.aml (File Save As, format: ACPI Machine Language Binary in MaciASL) and place it in ACPI/patched, and although all the data in the Info.plist will be overridden by the SSDT, no net change would be observed, as the data in SSDT-UIAC-ALL.dsl is the same as the data already in the USBInjectAll.kext Info.plist.

In order to effect our changes, we must modify the SSDT-UIAC-ALL.dsl so it contains only the ports we need.

The steps are as follows:
- use SSDT-UIAC-ALL.dsl as a template (https://github.com/RehabMan/OS-X-USB-Inject-All/raw/master/SSDT-UIAC-ALL.dsl)
- remove configuration sections that don't apply to the target hardware
- remove ports from the various sections that are not needed
- change UsbConnector values to match phyisical hardware/ports

The first step is to eliminate configuration data from SSDT-UIAC-ALL.dsl that don't apply to the target hardware and USB configuration.

For example, if no ports are active on EH01/EH02 or the related USB hubs (on PR11/PR21), you can eliminate the configuration data for EH01/EH02/HUB1/HUB2. In the case of Skylake, it has no EHCI controllers, so EH01/EH02/HUB1/HUB2 configuration can automatically be removed. Same would be true if you're disabling EHCI either via BIOS or ACPI (covered later). And you can eliminate any XHC configuration that does not match your XHC device-id. Look in ioreg to find your XHC device-id.

For example, you can see that the NUC6i7KYK uses 0xa12f:
View attachment 228093

So, for the NUC's XHC, it will match against the data for "8086_a12f" in the SSDT-UIAC-ALL.dsl. We can eliminate all other XHC configuration data.

For the NUC6i7KYK, we end up with this starter template:
Code:
// Initial trimmed SSDT-UIAC.dsl for NUC6i7KYK
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "8086_a12f", Package()
            {
                "port-count", Buffer() { 26, 0, 0, 0 },
                "ports", Package()
                {
                    "HS01", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HS02", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HS03", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HS04", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HS05", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 5, 0, 0, 0 },
                    },
                    "HS06", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 6, 0, 0, 0 },
                    },
                    "HS07", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 7, 0, 0, 0 },
                    },
                    "HS08", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 8, 0, 0, 0 },
                    },
                    "HS09", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 9, 0, 0, 0 },
                    },
                    "HS10", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 10, 0, 0, 0 },
                    },
                    "HS11", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 11, 0, 0, 0 },
                    },
                    "HS12", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 12, 0, 0, 0 },
                    },
                    "HS13", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 13, 0, 0, 0 },
                    },
                    "HS14", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 14, 0, 0, 0 },
                    },
                    "SS01", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 17, 0, 0, 0 },
                    },
                    "SS02", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 18, 0, 0, 0 },
                    },
                    "SS03", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 19, 0, 0, 0 },
                    },
                    "SS04", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 20, 0, 0, 0 },
                    },
                    "SS05", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 21, 0, 0, 0 },
                    },
                    "SS06", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 22, 0, 0, 0 },
                    },
                    "SS07", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 23, 0, 0, 0 },
                    },
                    "SS08", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 24, 0, 0, 0 },
                    },
                    "SS09", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 25, 0, 0, 0 },
                    },
                    "SS10", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 26, 0, 0, 0 },
                    },
                    "USR1", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 15, 0, 0, 0 },
                    },
                    "USR2", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 16, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

In the case of the NUC6i7KYK, it matches against a section in SSDT-UIAC-ALL.dsl that matches specifically against "8086_a12f". Some XHC devices will match against only part of the device-id. For example, the u430 device-id is 0x9c31. As there is no specific configuration for "8086_9c31", it will match against "8086_9xxx". Always use the template data that has the most specific match for your device-id. For example, if your device-id is 0x9cb1, you should use the template data for "8086_9cb1", not "8086_9xxx".

After you trim the template down to include only the configuration sections you need, now it is time to further trim the data to eliminate unused ports. As you recall, the NUC6i7KYK uses only HS01-HS04, HS09, and SS01-SS04.

The resulting SSDT-UIAC.dsl for NUC6i7KYK with only the ports we need:
Code:
// Port trimmed SSDT-UIAC.dsl for NUC6i7KYK
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "8086_a12f", Package()
            {
                "port-count", Buffer() { 26, 0, 0, 0 },
                "ports", Package()
                {
                    "HS01", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HS02", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HS03", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HS04", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HS09", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 9, 0, 0, 0 },
                    },
                    "SS01", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 17, 0, 0, 0 },
                    },
                    "SS02", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 18, 0, 0, 0 },
                    },
                    "SS03", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 19, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

We can comment each port based on notes we took about each:
Code:
// Port trimmed with port comments SSDT-UIAC.dsl for NUC6i7KYK
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "8086_a12f", Package()
            {
                "port-count", Buffer() { 26, 0, 0, 0 },
                "ports", Package()
                {
                    "HS01", Package() // HS USB3 front left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HS02", Package() // HS USB3 front right
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HS03", Package() // HS USB3 rear bottom
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HS04", Package() // HS USB3 rear top
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HS09", Package() // bluetooth
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 9, 0, 0, 0 },
                    },
                    "SS01", Package() // SS USB3 front left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 17, 0, 0, 0 },
                    },
                    "SS02", Package() // SS USB3 front right
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 18, 0, 0, 0 },
                    },
                    "SS03", Package() // SS USB3 rear bottom
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 19, 0, 0, 0 },
                    },
                    "SS04", Package() // SS USB3 rear top
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 20, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

And we should change the UsbConnector values to match the type of port. The defaults are not always correct (USBInjectAll has no way to know what the correct value is).

Common port connector types are USB2 = 0, USB3 = 3, internal = 255.

HSxx ports that are connected to a USB3 port should be marked UsbConnector=3, not UsbConnector=0.

Note: Read the ACPI spec for more valid values (_UPC).

In the case of the NUC6i7KYK, only HS09 needs adjusting. Since the bluetooth controller is internal, it should be 255.

The final SSDT-UIAC.dsl is:
Code:
// Port trimmed with port comments and correct UsbConnector SSDT-UIAC.dsl for NUC6i7KYK
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "8086_a12f", Package()
            {
                "port-count", Buffer() { 26, 0, 0, 0 },
                "ports", Package()
                {
                    "HS01", Package() // HS USB3 front left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HS02", Package() // HS USB3 front right
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HS03", Package() // HS USB3 rear bottom
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HS04", Package() // HS USB3 rear top
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HS09", Package() // bluetooth
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 9, 0, 0, 0 },
                    },
                    "SS01", Package() // SS USB3 front left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 17, 0, 0, 0 },
                    },
                    "SS02", Package() // SS USB3 front right
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 18, 0, 0, 0 },
                    },
                    "SS03", Package() // SS USB3 rear bottom
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 19, 0, 0, 0 },
                    },
                    "SS04", Package() // SS USB3 rear top
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 20, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

Now we are ready to compile this file and place it in EFI/Clover/ACPI/patched. In MaciASL, you can compile as AML by using File -> Save As, format: ACPI Machine Language Binary. Save it to a location you know how to navigate to (desktop). Then mount your EFI partition and copy it to EFI/Clover/ACPI/patched. I suggest using SSDT-UIAC.aml for the name.

Note: If you're using config.plist/ACPI/SortedOrder, you must insure that the new SSDT is listed in SortedOrder. If SortedOrder is specified, Clover will load only those SSDTs listed in SortedOrder.

After you have copied the SSDT to ACPI/patched, you are ready to test. If it does not work (ports missing, port discovery done incorrectly, wrong template used, etc), you can always use -uia_ignore_rmcf to disable the override code in SSDT, and then check your work.

Once your SSDT is working, you can remove or disable the port limit patch.

As you can see from the image below from the NUCi7KYK, we now have just the ports that we need injected and are well under the 15-port limit:
View attachment 228145

Lenovo u430 example with EH01 and HUB1

Since Skylake doesn't have an EHCI controller, we only needed to customize for XHC. The Lenovo u430 uses an 8-series chipset, therefore it has an EHCI controller. Although it can be disabled (which I actually do for my u430 in real use), this walk through will keep it enabled as a way of demonstrating EHCI and the related hub configuration.

Just as we did with the Skylake NUC6, we start by removing all configuration sections not needed from SSDT-UIAC-ALL for the Lenovo u430 based on the data we collected with FakePCIID_XHCIMux.kext. The XHC controller is 0x9c31, so we need only "8086_9xxx" for the XHC configuration, and we need EH01 and HUB1 for the ports on the EHCI controller and related hub.

The resulting trimmed SSDT is:
Code:
// Initial trim SSDT-UIAC.dsl for u430
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")

        Name(RMCF, Package()
        {
            "HUB1", Package()
            {
                "port-count", Buffer() { 8, 0, 0, 0 },
                "ports", Package()
                {
                    "HP11", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HP12", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HP13", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HP14", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HP15", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 5, 0, 0, 0 },
                    },
                    "HP16", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 6, 0, 0, 0 },
                    },
                    "HP17", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 7, 0, 0, 0 },
                    },
                    "HP18", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 8, 0, 0, 0 },
                    },
                },
            },
            "EH01", Package()
            {
                "port-count", Buffer() { 8, 0, 0, 0 },
                "ports", Package()
                {
                    "PR11", Package()
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "PR12", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "PR13", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "PR14", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "PR15", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 5, 0, 0, 0 },
                    },
                    "PR16", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 6, 0, 0, 0 },
                    },
                    "PR17", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 7, 0, 0, 0 },
                    },
                    "PR18", Package()
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 8, 0, 0, 0 },
                    },
                },
            },
            "8086_9xxx", Package()
            {
                "port-count", Buffer() { 13, 0, 0, 0 },
                "ports", Package()
                {
                    "HS01", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HS02", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HS03", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HS04", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HS05", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 5, 0, 0, 0 },
                    },
                    "HS06", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 6, 0, 0, 0 },
                    },
                    "HS07", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 7, 0, 0, 0 },
                    },
                    "HS08", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 8, 0, 0, 0 },
                    },
                    "HS09", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 9, 0, 0, 0 },
                    },
                    "SSP1", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 10, 0, 0, 0 },
                    },
                    "SSP2", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 11, 0, 0, 0 },
                    },
                    "SSP3", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 12, 0, 0, 0 },
                    },
                    "SSP4", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 13, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

If we installed that SSDT unmodified at this point, because all possible ports are included, we would have same result as without it.

Also note it is good practice for the XHC configuration to change to the actual device id, in this case "8086_9c31". In this case, either will work "8086_9xxx" or "8086_9c31", but using a specific configuration identifier helps identify the specific XHC device this SSDT was made for.

Note: You can also use "XHC".

So, after removing ports that are not used, and changing the XHC configuration identifier to "8086_9c31":
Code:
// Port trimmed SSDT-UIAC.dsl for u430
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "HUB1", Package()
            {
                "port-count", Buffer() { 8, 0, 0, 0 },
                "ports", Package()
                {
                    "HP11", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                    "HP12", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 2, 0, 0, 0 },
                    },
                    "HP13", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 3, 0, 0, 0 },
                    },
                    "HP14", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 4, 0, 0, 0 },
                    },
                    "HP15", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 5, 0, 0, 0 },
                    },
                    "HP16", Package()
                    {
                        //"UsbConnector", 0,
                        "portType", 2,
                        "port", Buffer() { 6, 0, 0, 0 },
                    },
                },
            },
            "EH01", Package()
            {
                "port-count", Buffer() { 8, 0, 0, 0 },
                "ports", Package()
                {
                    "PR11", Package()
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 1, 0, 0, 0 },
                    },
                },
            },
            "8086_9c31", Package()
            {
                "port-count", Buffer() { 13, 0, 0, 0 },
                "ports", Package()
                {
                    "SSP1", Package()
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 10, 0, 0, 0 },
                    },
                },
            },
        })
    }
}
//EOF

In this case, there is no need to modify any of the UsbConnector values, since they are already set correctly. The USB Hub driver in macOS/OS X does not use UsbConnector and we don't really understand the purpose of portType. You can experiment with different values if you need to. Refer to the hub driver Info.plist in IOUSBHostFamily.kext/Contents/PlugIns/AppleUSBHub.kext/Contents/Info.plist for ideas.

Note: If anyone has a Sierra or El Capitan ioreg from a MacPro6,1, MacBookPro8,1, MacBookPro6,1, iMac13,x, or MacBookPro8,3 along with information about the physical hub ports where portType=2 or portType=0 is used, please share.

After we install this SSDT, remove -uia_ignore_rmcf, we can verify in ioreg and test that all ports work.

Here we have images of the ports injected on EH01, HUB1, and XHC:
View attachment 228099

View attachment 228100

Note that for my Lenovo u430, I decided to disable the EHCI controller and have everything on XHC. FakePCIID_XHCIMux.kext is not installed.

The resulting SSDT is as follows (in this SSDT, I used "XHC" instead of "8086_9xxx" or "8086_9c31" just to show it is possible):
Code:
// With EHCI disabled, SSDT-UIAC.dsl for u430
DefinitionBlock ("", "SSDT", 2, "hack", "UIAC", 0)
{
    Device(UIAC)
    {
        Name(_HID, "UIA00000")
        Name(RMCF, Package()
        {
            "XHC", Package()
            {
                //"port-count", Buffer() { 0x0d, 0, 0, 0},
                "ports", Package()
                {
                    "HS01", Package() // touchscreen
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 0x01, 0, 0, 0 },
                    },
                    "HS02", Package() // HS USB3 left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 0x02, 0, 0, 0 },
                    },
                    "HS03", Package() // USB2 far right
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 0x03, 0, 0, 0 },
                    },
                    "HS04", Package() // USB2 near right
                    {
                        "UsbConnector", 0,
                        "port", Buffer() { 0x04, 0, 0, 0 },
                    },
                    "HS05", Package() // camera
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 0x05, 0, 0, 0 },
                    },
                    "HS06", Package() // bluetooth
                    {
                        "UsbConnector", 255,
                        "port", Buffer() { 0x06, 0, 0, 0 },
                    },
                    "SSP1", Package() // SS USB3 left
                    {
                        "UsbConnector", 3,
                        "port", Buffer() { 0x0a, 0, 0, 0 },
                    },
                },
            },
        })
    }

//
// Disabling EHCI #1
//
    External(_SB.PCI0, DeviceObj)
    External(_SB.PCI0.LPCB, DeviceObj)
    External(_SB.PCI0.EH01, DeviceObj)
    Scope(_SB.PCI0)
    {
        // registers needed for disabling EHC#1
        Scope(EH01)
        {
            OperationRegion(PSTS, PCI_Config, 0x54, 2)
            Field(PSTS, WordAcc, NoLock, Preserve)
            {
                PSTE, 2  // bits 2:0 are power state
            }
        }
        Scope(LPCB)
        {
            OperationRegion(RMLP, PCI_Config, 0xF0, 4)
            Field(RMLP, DWordAcc, NoLock, Preserve)
            {
                RCB1, 32, // Root Complex Base Address
            }
            // address is in bits 31:14
            OperationRegion(FDM1, SystemMemory, Add(And(RCB1,Not(Subtract(ShiftLeft(1,14),1))),0x3418), 4)
            Field(FDM1, DWordAcc, NoLock, Preserve)
            {
                ,15,    // skip first 15 bits
                FDE1,1, // should be bit 15 (0-based) (FD EHCI#1)
            }
        }
        Device(RMD1)
        {
            //Name(_ADR, 0)
            Name(_HID, "RMD10000")
            Method(_INI)
            {
                // disable EHCI#1
                // put EHCI#1 in D3hot (sleep mode)
                Store(3, ^^EH01.PSTE)
                // disable EHCI#1 PCI space
                Store(1, ^^LPCB.FDE1)
            }
        }
    }
}
//EOF

Don't expect to understand the code under "Disabling EHCI #1" unless you have had a good read of the ACPI specification and the Intel 8-series chipset datasheet.

Here is the result with everything on XHC (no EH01 to be found in ioreg):
View attachment 228125


Problem Reporting

If you have a problem, please describe the problem clearly, make sure your profile accurately describes your hardware and provide all the data as requested in the FAQ.

Read FAQ, "Problem Reporting"
https://www.tonymacx86.com/threads/faq-read-first-laptop-frequent-questions.164990/


Compress all files as ZIP. Do not use external links. Attach all files using site attachments only.

@RehabMan Thanks so much for writing this guide!
I'm sorry for the basic question, but I can't find the answer anywhere.
What if the Port "number" in ioReg is something like "0a" or "0e" rather than a number like most others.
How do I write it in my SSDT in MaciASL?
 
@RehabMan Thanks so much for writing this guide!
I'm sorry for the basic question, but I can't find the answer anywhere.
What if the Port "number" in ioReg is something like "0a" or "0e" rather than a number like most others.
How do I write it in my SSDT in MaciASL?

There is no need to change the "port" address assignments.
They are already correct in SSDT-UIAC-ALL.dsl.
Any change to the port addresses would be incorrect.
 
There is no need to change the "port" address assignments.
They are already correct in SSDT-UIAC-ALL.dsl.
Any change to the port addresses would be incorrect.
Okay.. but what about ports that don't have a port number, and have a letter instead, as I mentioned.
I should just use the numbers already listed in the SSDT-UIAC-ALL.dsl even though they don't appear to match?
 
Okay.. but what about ports that don't have a port number, and have a letter instead, as I mentioned.
I should just use the numbers already listed in the SSDT-UIAC-ALL.dsl even though they don't appear to match?

I think you are confused.
Hexadecimal (base 16) is just another way (as compared to decimal, base 10) to represent numbers:
https://en.wikipedia.org/wiki/Hexadecimal
If humans had 16 fingers instead of 10, we would be perfectly comfortable with hexadecimal and confused by decimal.

Again: The numbers in SSDT-UIAC-ALL.dsl are correct. You should not change them.
 
Thanks for the reply.

The key is as you say NOT to search but to open the explore to the AppleACPIPCI tree node and watch the ports change color as one inserts and removes devices.

The port limit is per controller, not system wide.

But my explorer window shows these controllers and ports on each controller:
EH01 : 8
EH02 : 6
MCHC: 1
RP06 : 1
RP08 : 1
SATA : 1
XHC : 8

Since no controller has MORE than 15 ports, then is it correct to say that this MB does not need any special SSDT to limit any port on all the controllers?

OR - is it true to say - I should still write the SSDT to limit the ports to the actual list of ports on the MB's controllers - I just don't have to disable any ports?

But as you say I need to leave the USBInjectAll.kext, FakePCII.kext and FakePCIID_XHCIMux.kext installed, with no further changes?

Thanks
 
i am trying to follow this guide but i do not know what to do if my USB device is listed as this:
RP05@1C,4 instead of XHC@14.

other ports are under the XHC@14 but some are on this strange one.
using Z270 chipset
full
 
Back
Top