Contribute
Register

Thunderbolt 4, modified firmware, Full Thunderbolt Bus tree

Joined
Jan 1, 2020
Messages
615
Motherboard
MSI Z490 MPG Gaming Edge Wifi
CPU
i5-10600K
Graphics
RX 6600 XT
Mac
  1. iMac
  2. MacBook Pro
  3. Mac mini
I have bought an Asrock Thunderbolt 4 AIC (Rev 1) with the following specification here :
Thunderbolt 4 AIC(L2).png

After patching firmware as usual (3 bytes similar to Thunderbolt 3 Titan Ridge)... et voila:

Capture d’écran 2024-03-26 à 20.22.29.png


This AIC board have a TBTForcePower jumper, no external wire jumper needed.

Without a TBTHeader cable and plugged into an Asus B460M that doesn't include Thunderbolt setting (No TBT header and no TBT BIOS capabilities), it works fine (Hot-plug, Sleep/Wake, Alternate mode DisplayPort and 10Gbps USB-C).

Before firmware patching, Hot-plug wasn't working. It seems that macOS can drive Hot-plug capability very well... without AppleHPMIECS driver.

Capture d’écran 2024-03-26 à 20.44.57.png


I also made 2 kernel patches to improve detection of "Complex" thunderbolt devices (that take more virtual memory like eGPU). "Simple" devices like Apple thunderbolt Ethernet (connected on previous screenshot) work without theses kernel patches.
Theses 2 patches consist on changing default IOThunderboltSwitchOS to IOThunderboltSwitchType6 :)

For information, on disassembled code of IOThunderboltFamily, I also seen IOThunderboltSwitchJHL8440 .. I tried it, but I didn't have such as a good result as the SwitchType6

This last screen shot is with an AMD RX5500 XT graphic card embedded on eGPU :
Capture d’écran 2024-03-26 à 21.04.45.png

Port@C and Port@D are USB4 adapters for AppleThunderboltUSBDownAdapter, I have enabled them on DROM (0x28C & 0x28D).. alas this driver plug-in is not available for Intel x86 platform (Apple Silicon only).. We should try an USB4 device that use PCIe bus to see what happen.

I have customised DROM part (at 0x4210 firmware address) before firmware flashing. You should do the same to customise your Thunderbolt UID (explain here). First byte at 0x4211 should remain at 0x00 if you have only one thunderbolt card.

Two lessons learned during reverse code investigations:
  • IOThunderboltSwitchOS & IOThunderboltSwitchType6 doesn't read ThunderboltDROM property unlike done with thunderbolt 3.
  • TBTFlags property is required with minimum value of 0x8 (08 00 00 00) to load previous ThunderboltSwitches.
Thunderbolt/USB4 System informations without plugged device:
Capture d’écran 2024-03-26 à 21.32.08.png


Other cards like ASUS Thunderbolt EX4 and Gigabyte GC-Maple Ridge could be tested like this.

I hope that Thunderbolt 5 (Barlow Ridge), expected in 2024, would be quite similar to Thunderbolt 3 & 4 :rolleyes:

EDIT:
Mistake on my first attached file, not fully patched ! Now it's OK.
 

Attachments

  • ASROCK_Thunderbolt4_AIC_modified_Elias64Fr.zip
    224.7 KB · Views: 42
Last edited:
I'll take another look and will post some close-up photos. If there is a SOIC8 chip, that would be great because I
think the EFI shell command does not accept a modified firmware.
You can try joined TbtNvmDrvShellUpdate.efi application extracted from BIOS 2103 with stock Thunderbolt firmware v31 (renamed as NVM.bin) under OpenShell from OpenCore. Then patch it to see result.
On this application, a verification is done on DROM vendor name (ASUS) with an offset of 0x426C.
A special care should be take if you enable port@C ans port@D, previous offset should be patched (+0x4).
I can do this if we have a success flashing of a patched firmware & without enabling theses two ports.
Shell command: TbtNvmDrvShellUpdate NVM.bin

Could you post the details of these 3 kext patches?
patch 1:
  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch SwitchOS to SwitchType6 (Ventura)
  • find: 4C89F7E8 46300500
  • replace by: 4C89F7E8 843E0800
  • max kernel: 22.9.9
patch 2:
  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch SwitchOS to SwitchType6 (Sonoma)
  • find: 4889DFE8 F55F0500
  • replace by: 4889DFE8 BB850800
  • min kernel: 23.0.0
patch 3:
  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch port number limitation (Common)
  • find: B8FFF03F FF234304
  • replace by: E90B0000 00234304

This one (@0x4081) is new --maybe this is the key! We did not make this particular change on Titan Ridge.
No... on Titan ridge @0x4081, we have changed 0xA0 to 0x20 (we have cleared bit 8) , on Maple ridge @0x4081, we change 0x85 to 0x05 (we also clear bit 8)

1. Flash my GC-Maple Ridge add-in-card with @Elias64Fr's 3-byte change
Not only, you also have to enable port@7 as usual on firmware DROM
 

Attachments

  • NVM.zip
    222.7 KB · Views: 30
  • TbtNvmDrvShellUpdate.efi
    9.7 KB · Views: 19
Last edited:
@Elias64Fr,

Are you able to compute the correct CRC32 checksum for the firmware file in Post 1 above?

If we use the settings that we discovered several years ago for Titan Ridge, we get this:

Screenshot 2024-04-03 at 4.07.27 PM.png


These are the DROM bytes for this checksum:

Code:
01 79 00 01 00 0D 00 01 00 08 81 80 02 00 00 00 00 08 82 90 01 00 00 00 00 08 83 80 04 00 00 00 00 08 84 90 03 00 00 00 00 05 85 00 00 00 05 86 50 00 00 02 87 0B 88 20 01 00 64 00 00 00 00 00 03 89 80 05 8A 50 00 00 05 8B 50 00 00 02 8C 02 8D 0D 01 41 70 70 6C 65 20 49 6E 63 2E 00 0C 02 4D 61 63 69 6E 74 6F 73 68 00 0F 09 10 04 87 80 09 00 01 28 00 00 00 00 01 FF

In the screenshot below, we see that the original firmware file shows CRC32 = 8C 4E 09 4E. But in the screenshot above we get E6 FD FB 30 (in reverse).

Screenshot 2024-04-03 at 4.10.23 PM.png
 
@Elias64Fr,

Are you able to compute the correct CRC32 checksum for the firmware file in Post 1 above?

If we use the settings that we discovered several years ago for Titan Ridge, we get this:

View attachment 581007

These are the DROM bytes for this checksum:

Code:
01 79 00 01 00 0D 00 01 00 08 81 80 02 00 00 00 00 08 82 90 01 00 00 00 00 08 83 80 04 00 00 00 00 08 84 90 03 00 00 00 00 05 85 00 00 00 05 86 50 00 00 02 87 0B 88 20 01 00 64 00 00 00 00 00 03 89 80 05 8A 50 00 00 05 8B 50 00 00 02 8C 02 8D 0D 01 41 70 70 6C 65 20 49 6E 63 2E 00 0C 02 4D 61 63 69 6E 74 6F 73 68 00 0F 09 10 04 87 80 09 00 01 28 00 00 00 00 01 FF

In the screenshot below, we see that the original firmware file shows CRC32 = 8C 4E 09 4E. But in the screenshot above we get E6 FD FB 30 (in reverse).

View attachment 581006
You've got one too many bytes for the checksum. Remove the trailing FF.

I've updated my ThunderboltUtil.sh script.
Code:
ignoreuid=0
dodump=0
cd /Volumes/Work/Programming/ThunderboltProjects/ThunderboltDROM
source Scripts/ThunderboltUtil.sh
loadfwfile .."/Notes/from Elias64Fr/ASROCK_Thunderbolt4_AIC_modified_Elias64Fr.bin"

listdroms
1)
thedrom=ec00060504030201008c4e094e01790001000d00010008818002000000000882900100000000088380040000000008849003000000000585000000058650000002870b88200100640000000000038980058a500000058b500000028c028d0d014170706c6520496e632e000c024d6163696e746f7368000f0910048780090001280000000001
sources:
../Notes/from Elias64Fr/ASROCK_Thunderbolt4_AIC_modified_Elias64Fr.bin:active:v26:nvm_v0.0:0x4200

dumpdromall
=======================================
1)
0x01) UID: 0x0001020304050600 // Vendor ID (USB-IF):0x0001 Component ID:0x02030405060 Router ID:0x0
0x0d) Version: 1 // TBT3
0x10) TBT3-Vendor ID: 0x1
0x12) TBT3-Device ID: 0xD
0x14) TBT3-Model Revision: 0x1
0x15) TBT3-NVM Revision: 0
0x16)   1: 800200000000 // TBT3-Lane Adapter  { Lane:0, Dual-Lane Link Capable:Yes, 2nd Adapter Num:2 }
0x1e)   2: 900100000000 // TBT3-Lane Adapter  { Lane:1, Dual-Lane Link Capable:Yes, 2nd Adapter Num:1 }
0x26)   3: 800400000000 // TBT3-Lane Adapter  { Lane:0, Dual-Lane Link Capable:Yes, 2nd Adapter Num:4 }
0x2e)   4: 900300000000 // TBT3-Lane Adapter  { Lane:1, Dual-Lane Link Capable:Yes, 2nd Adapter Num:3 }
0x36)   5: 000000 // DP  { Preferred Lane Adapter:0, Preference Valid:0 }
0x3b)   6: 500000 // DP  { Unknown:0x5000, Preferred Lane Adapter:0, Preference Valid:0 }
0x40)   7:
0x42)   8: 200100640000000000 // TBT3-PCIe Upstream Adapter  { xx:01.0, Unknown:0x0100640000000000 }
0x4d)   9: 80 // TBT3-PCIe Downstream Adapter  { xx:04.0 }
0x50)   A: 500000 // DP  { Unknown:0x5000, Preferred Lane Adapter:0, Preference Valid:0 }
0x55)   B: 500000 // DP  { Unknown:0x5000, Preferred Lane Adapter:0, Preference Valid:0 }
0x5a)   C:
0x5c)   D:
0x5e)   1: "Apple Inc." // ASCII Vendor Name
0x6b)   2: "Macintosh" // ASCII Model Name
0x77)   9: 10048780090001280000000001 // Product Descriptor  { USB Spec:4.1.0, Vendor ID:0x8087, Product ID:0x0009, Product FW Revision:28.0.1, TID:0x00000000, Product HW Revision:1 }
0x86) End


xxd -p -r <<< "$thedrom" | xxd
00000000: ec00 0605 0403 0201 008c 4e09 4e01 7900  ..........N.N.y.
00000010: 0100 0d00 0100 0881 8002 0000 0000 0882  ................
00000020: 9001 0000 0000 0883 8004 0000 0000 0884  ................
00000030: 9003 0000 0000 0585 0000 0005 8650 0000  .............P..
00000040: 0287 0b88 2001 0064 0000 0000 0003 8980  .... ..d........
00000050: 058a 5000 0005 8b50 0000 028c 028d 0d01  ..P....P........
00000060: 4170 706c 6520 496e 632e 000c 024d 6163  Apple Inc....Mac
00000070: 696e 746f 7368 000f 0910 0487 8009 0001  intosh..........
00000080: 2800 0000 0001                           (.....

printf "${thedrom:26:$thedatalen*2}"
01790001000d00010008818002000000000882900100000000088380040000000008849003000000000585000000058650000002870b88200100640000000000038980058a500000058b500000028c028d0d014170706c6520496e632e000c024d6163696e746f7368000f0910048780090001280000000001

printf "%08x %08x" $theexpectedcrc32 $thecrc32
4e094e8c 4e094e8c
 
You've got one too many bytes for the checksum. Remove the trailing FF.
Yes, I forgot that length X means addresses 0 to X-1.

I've updated my ThunderboltUtil.sh script.
Nice!

Usage instructions:
 
Last edited:
If this method does not check for a valid digital signature then it could flash modified firmware...

My understanding is that the signature check is done by the active firmware (the Linux documentation and osy's blog/tutorial seem to support this).

However, the firmware does allow downgrading. NVM firmware update support for Maple Ridge was missing in Linux but it can be enabled with a one-line patch (/sys/bus/thunderbolt/devices/0-0/nvm_non_active0/nvmem is missing without it). I was able to flash NVM 31 on my Z790-CREATOR which was previously running NVM 38. I haven't checked this, but I suspect ASUS added their own downgrade check in the driver that performs the firmware update (CCF23F50-F7C1-4F00-8E70-13643C37E8B0) and simply removed that check in BIOS 9901 for the Z690-CREATOR.
 
Awesome — you have reprogrammed my weekend plans! :)
That's a first step towards reprogramming Thunderbolt controllers, I suppose…

For the convenience of keeping records in one place in this thread, details of the kernel patches are in this post:
patch 1:

  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch SwitchOS to SwitchType6 (Ventura)
  • find: 4C89F7E8 46300500
  • replace by: 4C89F7E8 843E0800
  • max kernel: 22.9.9
patch 2:

  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch SwitchOS to SwitchType6 (Sonoma)
  • find: 4889DFE8 F55F0500
  • replace by: 4889DFE8 BB850800
  • min kernel: 23.0.0
patch 3:

  • identifiers: com.apple.iokit.IOThunderboltFamily
  • comment: IOThunderboltFamily patch port number limitation (Common)
  • find: B8FFF03F FF234304
  • replace by: E90B0000 00234304
 
My plan is roughly as follows:
  • Flash GC-Maple Ridge with (a) modified 3 bytes and (b) modified DROM (with correct CRC)
  • Modify SSDT with TBTFlags set to 0x08 and no DROM property injection
  • See what happens in macOS 14.4.x
    • Check hot plug and various types of devices
  • Then apply kernel patches
  • See what happens
If Thunderbolt bus activates and works well — including hot plug on both ports — then move to next stage below.
  • Check Asus Z690 ProArt for SOIC8 flash ROM
  • Read and save contents of this chip via CH341a, if found
  • Modify firmware via CH341a, modify SSDT, apply kernel patches and check Thunderbolt bus, hot plug, and reliability of both ports
  • Then use EFI shell app to flash original NVM31
  • If successful, use same EFI shell app to flash modified firmware
    • If disaster strikes, use CH341a to restore original firmware
 
I decided to get a head start on the test plan. I've completed the first 3 bullets, namely:
  • Saved original GC-Maple Ridge firmware with CH431a
  • Modified the firmware:
    • 2121 --> 3131
    • 85 --> 05
    • Updated DROM by enabling Port 7 and recomputing CRC
  • Flashed modified firmware to GC-Maple Ridge
  • Modified SSDT as follows:
    • Removed ThunderboltDROM property insertion
    • Changed DSB4 at ADR 0x04 to DSB3 at ADR 0x03
    • Tested with and without ThunderboltConfig property insertion
      • Elias' screenshot shows no ThunderboltConfig property
    • Added TBTFlags
    • Tested with original NHI0 device-id and NHI0 device-id spoofed to 0x15EB
      • Elias' screenshot shows NHI0 device-id spoofed to 0x15EB
  • Bridged the top and middle pins of vertical J1 header to force power on
  • No kext patches applied
Result:
  • Thunderbolt Bus is not activated
Attached are all of the relevant files: (a) SSDT and (b) Modified GC-Maple Ridge Firmware.
Screenshot 2024-04-04 at 2.49.09 PM.png

Screenshot 2024-04-04 at 3.01.52 PM.png
 

Attachments

  • SSDT-TB3-PEG1-PEGP.aml
    2 KB · Views: 21
  • gc-maple-1-modified.bin.zip
    224.8 KB · Views: 17
Last edited:
Back
Top