Jump to content

ThunderBolt Drivers


406 posts in this topic

Recommended Posts

Interested in other thoughts about the difference between ThunderBolt Drivers.

 

I have a Designare EX w/ the TB3 USBC DSL6540 Controller. In Ubuntu16.04 and Win10, hotswap works and all device detected.

 

Yet in OSX, even with DSDT I can get all devices detected, yet they do not load appropriate `ThunderBolt Drivers`. Which are responsible for enumerating the attached devices and determining whether it is `PCI-HotPlugCapable`, among other things. Behavior of Thunderbolt from DSL6540 in OSX is radically different. Yet on a New Emoji-Bar laptop the same controller works perfectly. So there's obviously a missing component here. Perhaps Macbook Configures the ThunderBolt controller before the operating system, unlike Linux/Windows. 

 

The Most Documentation I have other than the Linux Source.

https://developer.apple.com/library/content/documentation/HardwareDrivers/Conceptual/ThunderboltDevGuide/Basics01/Basics01.html

 

Attached in example of Linux Source of Thunderbolt Drivers.

http://elixir.free-electrons.com/linux/latest/source/drivers/thunderbolt/nhi.c

Link to comment
Share on other sites

Made great headway so far. ThunderBolt3 with Working Hotswap. ACPI Compared to a Macbook (Emoji-enabled). Haven't tested all devices, but blackmagic, maxx-digital, g-tech all have shown good results mounting well after startup.

  • Like 1
Link to comment
Share on other sites

Would like to share your experiences with mine. So far i got a working SSDT for my Gigabyte Thunderbolt3 AlpineRidge PCIe card.

As you can see in the screenshots, that all connectected hardware was detected correctly and supposed to be connected via Thunderbolt:

 

Registry Explorer:

IORegistry_Explorer.jpg

and see it in System Information Viewer:

 

System_Information_PCI.png

System_Information_SATA.png

only under Thunderbolt Entry it says: "Thunderbolt: no drivers loaded" :-(

Connected to the card is one CalDigit Thunderbolt dock and one LaCie RuggedThunder drive. Both connected via Apple Thunderbolt3-to-Thunderbolt2 adaptor.

Attached you will find my SSDT for the Gigabytecard.

Tbt31.aml.zip

  • Like 2
Link to comment
Share on other sites

Yes This is the same place I'm stuck.

 

Have you tried adding the XHCI Device? As soon as I add XHC2 to the TB Bus in DSDT, I get a Thunderbolt Bus Detected in SysProfiler, but I'm overloaded with Kernel messages about AppleXHCIPCI power state failed.

 

I think proper detection is related to USB3.1, I also noticed that the 3.1 Port on my Motherboard is connected to DSB2 in your photo


This is the device I'm adding, compared to EmojiBook Pro( Now known as %ebp)

                        Device (XHC2)
                        {
                            Name (_ADR, Zero)
                            Name (SDPC, Zero)
                            Method (_PRW, 0, NotSerialized)
                            {
                                Return (Package (0x02)
                                {
                                    0x6D, 
                                    0x03
                                })
                            }

                            Method (_DSM, 4, NotSerialized)
                            {
                                If (LEqual (U2OP, One))
                                {
                                    Store (Package (0x06)
                                        {
                                            "USBBusNumber", 
                                            Zero, 
                                            "AAPL,xhci-clock-id", 
                                            One, 
                                            "UsbCompanionControllerPresent", 
                                            One
                                        }, Local0)
                                }
                                Else
                                {
                                    Store (Package (0x04)
                                        {
                                            "USBBusNumber", 
                                            Zero, 
                                            "AAPL,xhci-clock-id", 
                                            One
                                        }, Local0)
                                }

                                DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
                                Return (Local0)
                            }

 

 

Adding the Dev/Ven to NHI IOPCIPrimaryMatch does nothing.. But you'll noticed right away that IOThunderboltPort@5 is now in ioreg.


Maybe it's related to X99 XHCI Injector Kext. I keep getting Closer to the Thunderbolt Bus when I start adding more devices to XHC2/3 like DEV0 and RHUB

post-1239620-0-48084700-1495031688_thumb.jpg

Link to comment
Share on other sites

  • 4 weeks later...

Dear both,
I also try to have a fully functionnal Thunderbolt on my hackintosh…
 
First my machine is:
 
Motherboard: ASUS x99 Sabertooth bios 3701
CPU: Intel® Core i7-5820K CPU @ 3.30GHz
RAM: 32GB 2133 MHZ DDR4
GFX: Nvidia GeForce GTX 1080 Ti with 378.05.05.15f01 drivers
OS: 10.12.5

Definition: iMac14,2

Clover: 4061 with OsxAptioFix2Drv-free2000.efi, Test2-2016.efi, EmuVariableUefi-64.efi
Thunderbolt Gigabyte GC-Alpine Ridge
Thunderbolt chain: AlpineRidge - > Apple TBT3->TBT2 adapter -> Blackmagic Design Ultrastudio 4k -> Blackmagic Design Production Cinema 4k

Out of the box Thunderbolt has a sort of working out of the box if I boot first to windows and reboot to Mac OS.

I tried to incorporate "Mork vom Ork" tbt31.dsl in my DSDT.dsl . I choose in the DSDT for avoiding the use of external objects and be sure the compilation is OK.

First problem is that my Thunderbolt 3 adapter is connected to \_SB.PCI0.BR3A so I've change your references to \_SB.PCI0.RP17 to my BR3A…
 
but after that I still got some problems:
 
Second problem (line 53115)  my RTC doesn't have ISTB (and it is under _SB.PCI0LPC0)
object so I simplified the initialization

            If (TBBT) //RONAN ORIGINAL If (LAnd (TBBT, LNot (\_SB.PCI0.LPCB.RTC.ISTB)))
            {
                \_SB.PCI0.BR3A.UPSB.DSB0.NHI0._EJ0 (One)
            }
            ElseIf (LNot (TBBT))
            {
                RMC1 ()
            }

Third problem is my PCI objects don't have PXSX So I remove the initialization wich is obviously stupid!

            Device (UPSB)
            {
                Name (_ADR, Zero)  // _ADR: Address
                Method (_INI, 0, NotSerialized)  // _INI: Initialize
                {
                    //RONAN Store (0x0F, \_SB.PCI0.BR3A.PXSX._ADR)
                }

So now my system is booting, but I'm still cannot switch on my Thunderbolt peripherals after system boot.

Also my USB3.1 is not working on the GC-Alpine USB-C ports, I'll try to add the XHC2 device under my USPB device.

 

Capture_d_e_cran_2017-06-11_a_09.30.27.p

DSDT.dsl.zip

Link to comment
Share on other sites

As proposed by remote.syst3m I added the XHC2.

I choose to add it under the DSB2 device since on my MacBookPro13,3 (Macbook Pro Touch 15) this device appears there.

 

				Device (XHC2)
				{
					Name (_ADR, Zero)
					Name (SDPC, Zero)
					Method (_PRW, 0, NotSerialized)
					{
						Return (Package (0x02)
						{
							0x6D, 
							0x03
						})
					}

					Method (_DSM, 4, NotSerialized)
					{
						//RONAN If (LEqual (U2OP, One))
                         If (One)
						{
							Store (Package (0x06)
								{
									"USBBusNumber", 
									Zero, 
									"AAPL,xhci-clock-id", 
									One, 
									"UsbCompanionControllerPresent", 
									One
								}, Local0)
						}
						Else
						{
							Store (Package (0x04)
								{
									"USBBusNumber", 
									Zero, 
									"AAPL,xhci-clock-id", 
									One
								}, Local0)
						}

						DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
						Return (Local0)
					}
				}
after that the USB-C port works as a USB3.1 port also (with hotplug OK)

This is the IOReg after switching on my Thunderbolt 2 device (Blackmagic Design Ultrastudio 4) on the first TBT3 port after complete boot, and connect a USB3.1 device (Lexar Workflow CR1) on the second TBT3 port (obviously working now as USB3.1)

Capture_d_e_cran_2017-06-11_a_14.59.34.p

 

But still no Thunderbolt Hotplug and still under Thunderbolt Entry: "Thunderbolt: no drivers loaded" 

Perhaps it could not work with iMac14,2 wich definition do you use? I also tried the newest iMac18,2 wich has a TBT3 controller without success.

Also I need to find a solution for my UPSB initialization if someone can help me…

DSDT.dsl.zip

Link to comment
Share on other sites

  • 4 weeks later...

I use Macpro6,1. I have not tried another profile.

 

I got it working better from fully defining the XHCI2/3. As for Thunderbolt driver not loading, I have the same. The only time I can get them to load is when I have an XHCI2/3 Error and the system is very slow, Kernel Logs on XHCI2/3 every 1 second. Hotswap does not work like this.

Link to comment
Share on other sites

  • 3 weeks later...

I use Macpro6,1. I have not tried another profile.

 

I got it working better from fully defining the XHCI2/3. As for Thunderbolt driver not loading, I have the same. The only time I can get them to load is when I have an XHCI2/3 Error and the system is very slow, Kernel Logs on XHCI2/3 every 1 second. Hotswap does not work like this.

I stop trying to get it working, the "not loaded" is not an issue but hotplug is the major problem. I think the problem is that the firmware is not uploaded to the thunderbolt chip

Link to comment
Share on other sites

  • 4 months later...

I think we need to understand what data is written to UEFI when Tb hardware gets recognized on windows first. This is the only mistery and the only clue we have something is not working the usual wzu

Link to comment
Share on other sites

Do we need hot plug? Can we manually tell macOS to rescan the PCI bus?

 

First, setup some boot arguments.

sudo boot-args="debug=0x144 pci=0x45"
"debug=0x144" is required by pciutils (lspci, setpci). I use the version at https://github.com/gittup/pciutils(just use "sudo make install"). There is a version of lspci that uses it's own kernel extension instead of Apple's AppleACPIPlatformExpert so that it doesn't require sudo or the debug flags, but that version is out of date (doesn't show PCI Express 3.0 information). I don't know exactly which flags pciutils requires because AppleACPIPlatformExpert is not open source, but 0x144 is the sugestion given in the error message if you don't have the flags.

 

The debug= flags are listed at https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/kern/debug.h.auto.html

and described at https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KernelProgramming/build/build.html

0x144 is DB_LOG_PI_SCRN + DB_ARP + DB_NMI

 

The pci= flags are listed at https://opensource.apple.com/source/IOPCIFamily/IOPCIFamily-320.1.1/IOKit/pci/IOPCIConfigurator.h.auto.html

Use pci= to set flags and npci= to clear flags. I think we only care about kIOPCIConfiguratorIOLog. KPrintf is for serial port or firewire kprintf, but you can set some of the "debug=" flags to make IOLog also go to kprintf (I think one or both of DB_PRT and DB_KPRT).

 

The io= flags are listed at https://opensource.apple.com/source/xnu/xnu-4570.1.46/iokit/IOKit/IOKitDebug.h.auto.html

 

You can find more flags by googling

PE_parse_boot_argn site:opensource.apple.com
You can find usage of flags be googling

"PE_parse_boot_argn pci" site:opensource.apple.com
Maybe IOThunderboltFamily.kext has it's own flags? You would have to disassemble it and look for calls to PE_parse_boot_argn.

 

Once you enable the kIOPCIConfiguratorIOLog flag, restart the computer. Open Terminal.app, and start streaming the log using a command like this:

log stream --style syslog --predicate 'not senderImagePath ENDSWITH "/IOUSBHostFamily" and processImagePath ENDSWITH "/kernel"'
Execute that command. press Command-K to clear the Terminal window before you do something that you want to log. Unplug a Thunderbolt device. Copy the contents of the terminal window to a text file. Connect a Thunderbolt device. Copy the contents of the terminal window to another text file.

 

The results using a Mac with Thunderbolt should give a clue how a workaround for hot plug may be created. The IOPCIFamily is open source. Hopefully we don't need to go into the IOThunderboltFamily which is not open source.

 

I've attached results from a Thunderbolt 2 MacBook Pro which has a Thunderbolt 1 FireWire adapter and a Thunderbolt 1 Ethernet adapter.

 

So I think you could make a kext with a user client that can be called from a user space command line app to force a PCI rescan. I suppose you could use the setpci command to see if there is actually anything to scan (vendor id and device id should not be FFFF for new devices). First you must set the primary bus, secondary bus, and subordinate bus. This won't work if Thunderbolt requires some other setup before new devices are presented on the bus.

 

setpci only works for pci configuration space (4096 bytes of registers). I think a kext with a user client that can read and write to different base registers of a pci device may be helpful. With such a kext, I would make a script to read / set the registers described by the Linux drivers (firmware versions, security level, etc.) to better understand its workings.

 

I've attached a script that uses setpci to dump the pci device tree. It's similar to the "lspci -t -vnn" command except it shows information about the upstream and downstream switches and the max and current link speed, link width (g1 = gen 1, etc.). The included example output shows a OWC Thunderbolt 2 Dock connected to a OWC Thunderbolt 3 Dock. Sometimes, if they don't appear in macOS (the NHI may not appear either), I boot into Windows, unplug the cable, reconnect it, make sure they appear in Windows Device Manager or the Intel Thunderbolt sofware list of devices, and restart into MacOS.

 

Another thing that needs investigation, besides ACPI is UEFI. Use UEFITool to get UEFI from a firmware update. Use Universal-IFR-Extractor to get the list of Thunderbolt variables in the forms packages. Then search the UEFI for code that uses those variables. This probably involves searching UEFI for the GUIDs of the involved protocols.

 

It might be interesting to add Internal Form Represention (IFR) code to Clover to dump such information (like F4 does for DSDT and SSDT). I don't know enough about the Human Interface Infrastructure Specification (HII) to know if that's possible.

MacBook Pro (Retina, 15-inch, Mid 2015).zip

pcitree.zip

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

Thanks joevt, very helpful information.

 

I'd like to pool resources. thunderbolt references, datasheets, and documentation is scarce.

 

 

Here is my NHI0

 

                        Device (NHI0)
                        {
                            Name (_ADR, Zero)
                            Name (_STR, Unicode ("Thunderbolt"))
                            Method (_DSM, 4, NotSerialized)
                            {
                                Store (Package (0x03)
                                    {
                                        "power-save",
                                        One,
                                        Buffer (One)
                                        {
                                            0x00
                                        }
                                    }, Local0)
                                DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))
                                Return (Local0)
                            }
                        }

In the Ioreg of a macbook 13,1 I see some additional properties I will try to inject properties more specific to Thunderbolt.

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

Thanks joevt, very helpful information.

 

I'd like to pool resources. thunderbolt references, datasheets, and documentation is scarce.

 

 

Here is my NHI0

 

                        Device (NHI0)

                        {

                            Name (_ADR, Zero)

                            Name (_STR, Unicode ("Thunderbolt"))

                            Method (_DSM, 4, NotSerialized)

                            {

                                Store (Package (0x03)

                                    {

                                        "power-save",

                                        One,

                                        Buffer (One)

                                        {

                                            0x00

                                        }

                                    }, Local0)

                                DTGP (Arg0, Arg1, Arg2, Arg3, RefOf (Local0))

                                Return (Local0)

                            }

                        }

 

In the Ioreg of a macbook 13,1 I see some additional properties I will try to inject properties more specific to Thunderbolt.

Hi remote.syst3m, 
How is your Thunderbolt progress going ?
I'm quite happy that you and others are still trying to get your thunderbolt cards/ports working as I own the Asus ThunderboltEX 3 expansion card - How different is this one compared to yours ?
Managed to get this card working with both my 2 x MacBooPro's (2015 & 2016 models), using a PC with Windows 10 64bits through an Apple Thunderbolt 2m cable (MD861ZM/A) and my Apple Thunderbolt 3 USB-C to Thunderbolt 2 Adapter (MMEL2ZM/A) - I can at least transfers files at a blazing 20GB/s speed between the 2 x MBPs or 1 x MBP and the PC with the Asus ThunderboltEX 3 installed!
Although my knowledge is limited I want to help as much as possible in any testing that anyone requires here,  ok?
MaLd0n has created my dsdt.aml that shows the following IOReg PCI devices structure:
It is obviously lacking a lot of the full PCI devices discovery & properties as per Mork vom Ork excellent work on his thunderbolt expansion board - that is my aim!!!
 
I'll leave here my current 
EFI folder (w/ dsdt.aml) and some images of my thunderbolt testing to keep this thread alive...
 
Boa sorte,
Paulo

 

post-105782-0-59984500-1518185292_thumb.jpeg

post-105782-0-42327100-1518185874_thumb.png

post-105782-0-95120500-1518185911_thumb.png

post-105782-0-52396100-1518185938_thumb.png

post-105782-0-19123100-1518185958_thumb.png

post-105782-0-58223200-1518185964_thumb.png

post-105782-0-17472400-1518185999_thumb.jpeg

post-105782-0-63611000-1518186030_thumb.jpeg

post-105782-0-94015700-1518186048_thumb.jpeg

post-105782-0-52073100-1518186248_thumb.png

post-105782-0-57654900-1518186259_thumb.jpg

post-105782-0-89129700-1518186374_thumb.jpg

post-105782-0-57587300-1518187622_thumb.jpg

post-105782-0-05016700-1518187629_thumb.jpg

EFI.zip

Link to comment
Share on other sites

Another thing that needs investigation, besides ACPI is UEFI. Use UEFITool to get UEFI from a firmware update. Use Universal-IFR-Extractor to get the list of Thunderbolt variables in the forms packages. Then search the UEFI for code that uses those variables. This probably involves searching UEFI for the GUIDs of the involved protocols.

I took a couple hours to look at using UEFITool (Mac or Windows) and Universal-IFR-Extractor (Windows). It's quite simple to get the IFR information from a bios file. I've tried Asus Z370, X299, and Gigabyte Z170 BIOS files. They all contain firmwares from AMI and therefore have many of the same Thunderbolt related variables stored in the Setup NVRAM variable at various offsets. Many of the variables are not presented to the user in BIOS.

 

Here's the list from ASUS Z370 (more info such as defaults and options are in the IFR):

0448 One Of: Thunderbolt(TM) Support
0449 Checkbox: Wake From Thunderbolt(TM) Devices
044F One Of: Thunderbolt(TM) PCIe Support
0451 One Of: Thunderbolt Usb Support
0452 One Of: Thunderbolt Boot Support
0455 One Of: Thunderbolt(TM) PCIe Cache-line Size
0456 Checkbox: GPIO3 Force Pwr
0457 Numeric: Wait time in ms after applying Force Pwr
0459 One Of: Security Level
045A One Of: Call pre boot Smi handler
0468 Numeric: Reserve mem per phy slot
046A Numeric: Reserve P mem per phy slot
046C Numeric: Reserve IO per phy slot
0470 Checkbox: Native OS Hot Plug
0471 One Of: SW SMI on TBT hot-plug
0472 One Of: GPIO filter
0473 One Of: ACPI Notify on TBT Hot-plug
0474 One Of: MSI enabled in FADT
0475 Numeric: AIC Location
0476 One Of: Enable CLK REQ
0477 One Of: Enable ASPM
0478 One Of: Enable LTR
0479 One Of: TBT Host Router
047A One Of: AIC Location Group
047B One Of: AIC Location
047C One Of: AIC Location
047D Numeric: Extra Bus Reserved
047E Numeric: Reseved Memory
0480 Numeric: Reserved I/O
0481 Numeric: Memory Alignment
0482 Numeric: Reserved PMemory
0484 Numeric: PMemory Alignment
0485 One Of: Skip PCI enumeration
0486 One Of: Skip PCI OptionRom
0487 One Of: Skip PCI Interrupt Assignment
0488 One Of: ACPI Removal Object Suppport
0489 One Of: Alpine Ridge Workaround Select
048A One Of: AR XHCI Host Pre-wake
048B Numeric: AR XHCI Host Active LTR
048F Numeric: AR XHCI Host High LTR
0493 Numeric: AR XHCI Host Medium LTR
0497 Numeric: AR XHCI Host Low LTR
There are almost 3000 other variables in the setup configuration.

 

The next step is to find the code that uses those variables, but I'm not sure how that gets accessed. There are occurrences of "Setup" and "EC87D643-EBA4-4bb5-A1E5-3F3E36B20DA9" (SYSTEM_CONFIGURATION_GUID) in edk2 which may give a clue.

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

I found some relevant code in PlatformInit of the BIOS. There's a function that reads the Setup NVRAM variable to a local stack variable and extracts some of the Thunderbolt settings. Since it's a local variable, the offsets in the assembly are stack relative, not SYSTEM_CONFIGURATION struct relative so you can't search for settings offsets that way which means you have to look at every function manually to see if they use the settings that you're interested in. I suppose it's possible to create a script to find functions that read the Setup NVRAM variable, finds the stack address used for the destination, then scans the entire function for specific offsets that we want. That is nearly impossible because the stack pointer can change often inside a function (arguments that are pushed on the stack for a function call might not be immediately popped).

 

I used Hopper to disassemble the files created by UEFIExtract. Hopper doesn't support TE image files so I wrote a script to convert those to PE (included below).

 

Hopper can keep track of stack pointer changes, so it knows for each instruction what a stack relative address is pointing to. The nearly impossible script is more possible with the disassembly from Hopper.

 

Image PlatformInit is part of stage pei of UEFI. They use a struct EFI_PEI_SERVICES to call useful functions. A pointer to this is stored in field Ps of struct PEI_CORE_INSTANCE. Function SetPeiServicesTablePointer is used to store a pointer to field Ps of struct PEI_CORE_INSTANCE to the 4 bytes immediately preceding the Interrupt Descriptor Table. The sidt instruction is used to get the address of the IDT and the lidt instruction is used to set it. This is all setup by source file PeiMain.c of PeiCore.

 

PlatformInit has many functions that use GetPeiServicesTablePointer to get a pointer to the pointer to EFI_PEI_SERVICES. These are from source file PeiServicesLib.c

 

I think some of it might be setting up some PCD stuff (EDKII Platform Configuration Database Entries) using settings from NVRAM. That might be interesting. Some of the UEFI code affects the ACPI code (for example, when Thunderbolt is enabled, XTBT is renamed _E23 where the Edge-Triggered GPE number (23) is calculated by the code based on one of the settings).

 

I don't see an easy way to import types into Hopper (entering 3000 settings fields in a struct by hand will take forever and have errors that are not easily fixable with the current UI).

 

I've included the scripts I used for searching (produces easier to use results (hierarchical with full path) than UefiTool.app).

 

#=========================================================================================
# Extract some downloaded bios files

cd ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7
~/Downloads/UEFIstuff/UEFITool-master/build-uefiextract-Desktop_Qt_5_10_1_clang_64bit-Debug/UEFIExtract ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7/Z170XG7.22j


#=========================================================================================
# Get a list of type and subtype combinations

cd ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7/Z170XG7.22j.dump

find . -name info.txt -exec printf "sed -nE '1,2 p' '%s' | tr '\\\\n' ' ' ; echo\n" {} \; | sh | sort -u


#=========================================================================================
# Find body.bin files containing the Setup var name and guid

cd ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7/Z170XG7.22j.dump

search() {
	grep -q "$1" /tmp/efihex.txt
}

IFS=$'\n'
guid='EC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9'
guidhex=$(echo -n "${guid:6:2} ${guid:4:2} ${guid:2:2} ${guid:0:2} ${guid:11:2} ${guid:9:2} ${guid:16:2} ${guid:14:2} ${guid:19:2} ${guid:21:2} ${guid:24:2} ${guid:26:2} ${guid:28:2} ${guid:30:2} ${guid:32:2} ${guid:34:2}" | tr '[:upper:]' '[:lower:]')
## 43 d6 87 ec a4 eb b5 4b a1 e5 3f 3e 36 b2 0d a9
setuphex=$(printf "Setup\000" | iconv -f UTF-8 -t UTF-16LE | xxd -ps -c1 | tr '\n' ' ')
# 53 00 65 00 74 00 75 00 70 00 00 00 
pat1='^Type: File .*'
pat2='^Type: Section .*'
for theinfo in $(find . -name info.txt); do
	thetype=$(sed -nE '1,2 p' $theinfo | tr '\n' ' ')
	if [[ $thetype =~ $pat1 || $thetype =~ $pat2 ]]; then
		thebody=${theinfo/info.txt/body.bin}
		if [ -f $thebody ]; then
			xxd -ps -c1 $thebody | tr '\n' ' ' > /tmp/efihex.txt
			if search "$guidhex"; then
			if search "$setuphex"; then
				echo $thetype $theinfo
				#echo "# found"
			fi
			fi
		fi
	fi
done


#=========================================================================================
# Find body.bin files containing the Setup var name and guid and XTBT text (used in ACPI)

cd ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7/Z170XG7.22j.dump

search() {
	grep -q "$1" /tmp/efihex.txt
}

IFS=$'\n'
guid='EC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9'
guidhex=$(echo -n "${guid:6:2} ${guid:4:2} ${guid:2:2} ${guid:0:2} ${guid:11:2} ${guid:9:2} ${guid:16:2} ${guid:14:2} ${guid:19:2} ${guid:21:2} ${guid:24:2} ${guid:26:2} ${guid:28:2} ${guid:30:2} ${guid:32:2} ${guid:34:2}" | tr '[:upper:]' '[:lower:]')
## 43 d6 87 ec a4 eb b5 4b a1 e5 3f 3e 36 b2 0d a9
XTBThex=$(printf "TBT" | xxd -ps -c1 | tr '\n' ' ')
# 53 00 65 00 74 00 75 00 70 00 00 00 
#thunderboltSupportHex="53 04" #0x453
#thunderboltPcieSupportHex="5a 04" #0x45A
#thunderboltUsbSupportHex="5c 04" #0x45C
pat1='^Type: File .*'
pat2='^Type: Section .*'
for theinfo in $(find . -name info.txt); do
	thetype=$(sed -nE '1,2 p' $theinfo | tr '\n' ' ')
	if [[ $thetype =~ $pat1 || $thetype =~ $pat2 ]]; then
		thebody=${theinfo/info.txt/body.bin}
		if [ -f $thebody ]; then
			xxd -ps -c1 $thebody | tr '\n' ' ' > /tmp/efihex.txt
			if search "$guidhex"; then
			if search "$setuphex"; then
			if search "$XTBThex"; then
				echo $thetype $theinfo
				#echo "# found"
			fi
			fi
			fi
		fi
	fi
done


#=========================================================================================
# Convert all TE image files to PE so they can be disassembled by Hopper

cd ~/Downloads/UEFIstuff/UEFIbios/GA-Z170X-Gaming_7/Z170XG7.22j.dump


ConvertTEtoPE() {
	theTEFile="$1"
	thePEFile=${theTEFile/.bin/.pe}
	teHeader=$(dd if="${theTEFile}" bs=40 count=1 2> /dev/null | xxd -ps -c40)
	TEsignature=${teHeader:0:4} # VZ
	TEmachine=${teHeader:4:4}
	TEnumberOfSections=${teHeader:8:2}
	TEsubsystem=${teHeader:10:2} # 11 = EFI driver with boot services.
	TEstrippedSize=$((0x${teHeader:14:2}${teHeader:12:2}))
	TEaddressOfEntryPoint=${teHeader:16:8} # pointer to the entry point function, relative to the image base address
	TEbaseOfCode=${teHeader:24:8}
	TEimageBase=${teHeader:32:16}
	TEreloc=${teHeader:48:16}
	TEdebug=${teHeader:64:16}

	if [[ $TEsignature == 565a ]]; then
	
		TEsections="$(dd if="${theTEFile}" bs=40 skip=1 count=0x$TEnumberOfSections 2> /dev/null | xxd -ps -c40)"
		PEsizeOfCode=0
		PEsizeOfInitializedData=0

		IFS=$'\n'
		for theSection in $TEsections; do
			if [[ $theSection =~ ^(2e7465787400.{68})$ ]]; then
				PEsizeOfCode=$(($PEsizeOfCode + 0x${theSection:38:2}${theSection:36:2}${theSection:34:2}${theSection:32:2}))
			else
				PEsizeOfInitializedData=$(($PEsizeOfInitializedData + 0x${theSection:38:2}${theSection:36:2}${theSection:34:2}${theSection:32:2}))
			fi
		done

		PEsizes=00000000000000000000000000000000

		if [[ $TEmachine == 4c01 ]]; then
			PEoptionalHeaderSize=e0
			PEmagic=0b01
			PEimageBase=00000000${TEimageBase:0:8}
		elif [[ $TEmachine == 6486 ]]; then
			PEoptionalHeaderSize=f0
			PEmagic=0b02
			PEimageBase=$TEimageBase
			PEsizes=$PEsizes$PEsizes
		else
			echo "# bad TE machine: $TEmachine"
			return 1
		fi

		PEdosStub=4d5a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
		PEheader=50450000${TEmachine}${TEnumberOfSections}00000000000000000000000000${PEoptionalHeaderSize}002220

		sizeOfTEFile=$(wc -c < $theTEFile)

		peSizeOfImage=$(($sizeOfTEFile - 40 + $TEstrippedSize))
		peSizeOfHeaders=$(($TEstrippedSize + 40 * 0x$TEnumberOfSections))
		peHeaderOffset=$(($TEstrippedSize - 0x$PEoptionalHeaderSize - ${#PEheader}/2))

		peSizeOfImageHex=$(          printf "%08x" $peSizeOfImage           | sed -E "s/(..)(..)(..)(..)/\4\3\2\1/g")
		peSizeOfHeadersHex=$(        printf "%08x" $peSizeOfHeaders         | sed -E "s/(..)(..)(..)(..)/\4\3\2\1/g")
		peHeaderOffsetHex=$(         printf "%08x" $peHeaderOffset          | sed -E "s/(..)(..)(..)(..)/\4\3\2\1/g")
		PEsizeOfCodeHex=$(           printf "%08x" $PEsizeOfCode            | sed -E "s/(..)(..)(..)(..)/\4\3\2\1/g")
		PEsizeOfInitializedDataHex=$(printf "%08x" $PEsizeOfInitializedData | sed -E "s/(..)(..)(..)(..)/\4\3\2\1/g")

		PEoptionalHeader=${PEmagic}0900${PEsizeOfCodeHex}${PEsizeOfInitializedDataHex}00000000${TEaddressOfEntryPoint}${TEbaseOfCode}${PEimageBase}200000002000000000000000000000000000000000000000${peSizeOfImageHex}${peSizeOfHeadersHex}00000000${TEsubsystem}000000${PEsizes}000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000${TEreloc}${TEdebug}000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

		(
			echo -n ${PEdosStub}${peHeaderOffsetHex}$(seq -f '00' -s '' $(($peHeaderOffset - ${#PEdosStub}/2 - 4 )))${PEheader}${PEoptionalHeader} | xxd -ps -r
			dd if="${theTEFile}" bs=1 skip=40 2> /dev/null
		) > "$thePEFile"
	
	else
		echo "# bad TE signature: $TEsignature"
		return 1
	fi
}


IFS=$'\n'
pat1='^Type: Section Subtype: TE image '
for theinfo in $(find . -name info.txt); do
	thetype=$(sed -nE '1,2 p' $theinfo | tr '\n' ' ')
	if [[ $thetype =~ $pat1 ]]; then
		thebody=${theinfo/info.txt/body.bin}
		if [ -f $thebody ]; then
			echo "#" $thebody
			ConvertTEtoPE $thebody
		fi
	fi
done


open -a /Applications/Hopper\ Disassembler\ v4.app ."/3 BIOS region/4 8C8CE578-8A3D-4F1C-9935-896185C32DD3/0 PeiBoardConfigInit/1 TE image section/body.pe"
open -a /Applications/Hopper\ Disassembler\ v4.app ."/3 BIOS region/5 8C8CE578-8A3D-4F1C-9935-896185C32DD3/1 RomLayoutPei/1 TE image section/body.pe"
open -a /Applications/Hopper\ Disassembler\ v4.app ."/3 BIOS region/5 8C8CE578-8A3D-4F1C-9935-896185C32DD3/2 PeiCore/0 TE image section/body.pe"


#=========================================================================================
# Utility function to convert a physical address to a PCIe bus device function register

PCIFunctionFromAddress() {
	# baseAddress and baseBus come from ACPI data table having signature MCFG
	adr=$1
	baseAddress=0xF0000000
	baseBus=0
	pciAdr=$((adr - baseAddress))
	printf "# %08X = %02X:%02X.%X -> %X\n" $adr $(((pciAdr >> 20 & 0xFF) + baseBus)) $((pciAdr >> 15 &0x1F)) $((pciAdr >> 12 & 7)) $((pciAdr & 0xFFF))
}


PCIFunctionFromAddress 0xF7FFFFFF

# F7FFFFFF = 7F:1F.7 -> FFF


#=========================================================================================

  • Like 4
Link to comment
Share on other sites

This is a mini-guide to get Thunderbolt hotswap working. My SSDT is for an ASRock TB3 (JHL6540) card in my X299 motherboard, but I know this also works with the Gigabyte X99 Designare's built-in TB3 port.

If you need a more basic overview of SSDTs then I suggest Shiloh's SSDT GPU Injection thread at the place that shall not be named.

 

Based on the TheRacerMaster's work, and remote.syst3m's idea to change the value of "PCIHotplugCapable", I have TB3 hotswap working. Thunderbolt does not show as loaded in System Profiler, and this is undoubtedly a bit of a hack, but it seems to work and it is quite easy to implement.

 

TheRacer Master's github work seems to be based on importing MacBookPro14,1 ACPI information. You can find some raw Darwin Dumps here from him that contain DSDTs, SSDTs, and IOreg.

 

Below is the seemingly relevant bit, pulled from TheRacerMaster's github, with only the "PCIHotplugCapable" value changed to enabled and a few values modified to fit my computer.

            Device (DSB0)
            {
                Name (_ADR, Zero)  // _ADR: Address
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    If (LNot (Arg2))
                    {
                        Return (Buffer (One)
                        {
                             0x03                                           
                        })
                    }

                    Return (Package (0x02)
                    {
                        "PCIHotplugCapable", 
                        One
                    })
                }

I implemented this as an SSDT, but perhaps one could simply inject the single property via Clover arbitrary, or just the DSB0 device with that one property.

 

1. What you need:

IOregistryExplorer (or IOJones)

MaciASL (use Rehabman's patchmatic)

Thunderbolt working (just without hotswap)

 

2. Identify the TB device address

2.1 Open IOreg and find your thunderbolt device(s) by typing in "thunderbolt" in the search bar. 

 

2.2. Take note of the address (PCI0.RP05 for me).

 

2.3. Now clear the thunderbolt search and switch to IOACPIPlane view on the top right of IOreg. Find that same address. You should see a few other entires under it, and make note of whatever does not begin with H (for X99), and any values for X299. In this case, mine are PXSX and SLT5. We are going to prevent these from loading by setting their STA value to Zero so that our devices load instead.

 

3. Modify stock SSDT

3.1 Download the attached base SSDT and replace any instances of PCI0.RP05 with your actual address. If you have multiple thunderbolt controllers then copy and modify accordingly.

 

3.2. Replace PXSX and SLT5 with your value(s) from IOACPIPlane view. You might only have one value, in which case you can delete the extra line from the stock SSDT.

 

That should be it! Reboot and open IOreg again. Look to see if you now have PCIHotplugCapable set to "True" on the right-hand side. If so, then it should be working.

 

4. BIOS Settings

4.1. If you have an ASUS X299 board then you should enabled ASPM and GPIO ForcePwr in addition to the normal BIOS settings (Legacy Security, Cache Line-in 128, any slot selection). If you don't do this then you will not see a USB 3.1 bus for the TB3 card unless you keep a USB 3.1 device plugged in to the TB3 port on startup.

 

5. Inject USB ports (not required for hotswap but clears up errors in boot log)

I also hardcoded the two USB 3.1 ports on my card to clear up some complaints during verbose startup. This was pulled from one of PikerAlpha's blog posts. I don't think it matters which device you inject this into (DSB2,3,4), but I chose DSB2 based upon the address on my particular card (0x0002000) locatable in IOreg. If I had had 0x0003000 then I would have done DSB3, etc. 

 

5.1. If you already have an XHC2 device, then name it XHC3, 4, or whatever is appropriate. If you only have one TB3 port, then you only need HS01 and SSP1.

            Device (DSB2)
            {
                Name (_ADR, 0x00020000)  // _ADR: Address
                Device (XHC2)
                {
                    Name (_ADR, Zero)  // _ADR: Address
                    Device (RHUB)
                    {
                        Name (_ADR, Zero)  // _ADR: Address
                        Device (SSP1)
                        {
                            Name (_ADR, One)  // _ADR: Address
                            Name (_UPC, Package (0x04)  // _UPC: USB Port Capabilities
                            {
                                0xFF, 
                                0x09, 
                                Zero, 
                                Zero
                            })
                            Name (_PLD, Package (0x01)  // _PLD: Physical Location of Device
                            {
                                Buffer (0x10)
                                {
                                    /* 0000 */  0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    /* 0008 */  0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
                                }
                            })
                            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                            {
                                If (LEqual (Arg2, Zero))
                                {
                                    Return (Buffer (One)
                                    {
                                         0x03                                           
                                    })
                                }

                                Return (Package (0x02)
                                {
                                    "UsbCPortNumber", 
                                    One
                                })
                            }
                        }

                        Device (SSP2)
                        {
                            Name (_ADR, 0x02)  // _ADR: Address
                            Name (_UPC, Package (0x04)  // _UPC: USB Port Capabilities
                            {
                                0xFF, 
                                0x09, 
                                Zero, 
                                Zero
                            })
                            Name (_PLD, Package (0x01)  // _PLD: Physical Location of Device
                            {
                                Buffer (0x10)
                                {
                                    /* 0000 */  0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    /* 0008 */  0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
                                }
                            })
                            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                            {
                                If (LEqual (Arg2, Zero))
                                {
                                    Return (Buffer (One)
                                    {
                                         0x03                                           
                                    })
                                }

                                Return (Package (0x02)
                                {
                                    "UsbCPortNumber", 
                                    0x02
                                })
                            }
                        }

                        Device (HS01)
                        {
                            Name (_ADR, 0x03)  // _ADR: Address
                            Name (_UPC, Package (0x04)  // _UPC: USB Port Capabilities
                            {
                                0xFF, 
                                0x09, 
                                Zero, 
                                Zero
                            })
                            Name (_PLD, Package (0x01)  // _PLD: Physical Location of Device
                            {
                                Buffer (0x10)
                                {
                                    /* 0000 */  0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    /* 0008 */  0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
                                }
                            })
                        }

                        Device (HS02)
                        {
                            Name (_ADR, 0x04)  // _ADR: Address
                            Name (_UPC, Package (0x04)  // _UPC: USB Port Capabilities
                            {
                                0xFF, 
                                0x09, 
                                Zero, 
                                Zero
                            })
                            Name (_PLD, Package (0x01)  // _PLD: Physical Location of Device
                            {
                                Buffer (0x10)
                                {
                                    /* 0000 */  0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    /* 0008 */  0x31, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
                                }
                            })
                        }
                    }
                }
            }

 

SSDT-TB3.aml.zip

Edited by maleorderbride
  • Like 5
Link to comment
Share on other sites

Good to hear! I only wrote this up though--remote had the idea of changing that flag, and TheRacerMaster did 99% of the SSDT in his github ;)

Hi maleorderbride,

 

Do you know if your code works with the DSL6540 Asus ThunderboltEX 3 model ?

 

When I switch IORegistryExplorer to IOACPIPlane I see a lot of entries starting with H..., see below:

post-105782-0-40677100-1520021965_thumb.jpeg

 

So I should zero my D07C device ?

 

My files are a few posts above and my DSDT.aml was created by MaLd0n.

 

Boa sorte,

Paulo

Link to comment
Share on other sites

Could someone help me to understand how to enable hot swap with an ssdt - Still don't get it...

Attaching my IOReg File...

It should work. But I don't know what other ssdt you have and acpi device rename in clover. 

SSDT-1.aml.zip

 

Add rename to clover acpi patch PC00 to PCI0 -> 50433030 > 50434930 

  • Like 1
Link to comment
Share on other sites

Make sure that you have enabled 4G decoding in bios and replace your dsdt in clover patch folder attachicon.gifDSDT.aml.zip

Thanks.

 

Checked that I have "Above 4G Decoding" in bios and replaced my dsdt.aml with the one that you've sent.

 

I'm attaching the the new ioreg - Is it how you expected it to be?

 

Also, a couple of question just for sanity :wink_anim: :

  • These changes are just for the hot swap of the TB3 controller right ?
  • I'm guessing we are still far way from having a full TB3 implementation as did Mork vom Ork with his Gigabyte Thunderbolt3 AlpineRidge on post #3 of this thread, right ?

 

Boa sorte,

Paulo

paulo’s iMac Pro2.ioreg.zip

Link to comment
Share on other sites

 Share

×
×
  • Create New...