-
-
Notifications
You must be signed in to change notification settings - Fork 13
ObjectInfoNavi
Using the atomdis tool we can extract the ObjInfo data table from the RX5500XT original video BIOS. It prints the contents and even the information about the most important variables we want to examine and modify. Keep in mind we have to reverse byte order when fetching data from the vBIOS file directly, see Endianness.
atomdis RX5500XT.rom d 16
Read 100000 bytes of data from RX5500XT-ORIG.rom
data_table 0000c530 #16 (Object_Info/Object_Header):
Size 00a8
Format Rev. 01
Param Rev. 00
Content Rev. 04
00000000: 880e 0500 1331 5800 2122 0000 .....1X.!"..
00000010: 8500 0000 0800 0000 1332 6100 1e21 0000 .........2a..!..
00000020: 8c00 0000 8000 0000 1333 6a00 1e22 0000 .........3j.."..
00000030: 9300 0000 0002 0000 1334 7300 2021 0000 .........4s. !..
00000040: 9a00 0000 0004 0000 1335 7c00 2121 0000 .........5|.!!..
00000050: a100 0000 0008 0000 0104 9100 0204 0200 ................
00000060: ff01 0492 0002 0403 00ff 0104 9300 0204 ................
00000070: 0400 ff01 0494 0002 0405 00ff 0104 9000 ................
00000080: 0204 0100 ff14 060f 0000 00ff 1406 0f00 ................
00000090: 0000 ff14 060f 0000 00ff 1406 0f00 0000 ................
000000a0: ff14 060f 0000 00ff ........
NOTE: General revisionless dumper only.
NOTE: Data part see radeonhd
0000: ATOM_COMMON_TABLE_HEADER sHeader :
0000: USHORT usStructureSize = 0x00a8 (168)
0002: UCHAR ucTableFormatRevision = 0x01 (1)
0003: UCHAR ucTableContentRevision = 0x04 (4)
0004: USHORT usDeviceSupport = 0x0e88 (3720)
0006: USHORT usConnectorObjectTableOffset = 0x0005 (5)
0008: USHORT usRouterObjectTableOffset = 0x3113 (12563)
000a: USHORT usEncoderObjectTableOffset = 0x0058 (88)
000c: USHORT usProtectionObjectTableOffset = 0x2221 (8737)
000e: USHORT usDisplayPathTableOffset = 0x0000 (0)
Total data structure size: 0010
This complete structure has been defined in the Linux header files. Whenever necessary I have added links to the very same header file using particular line numbers were crucial information can be found.
The 4 byte header decode length of the table in bytes (A800
becomes (endian) to 0x00A8
= 168d
bytes) next bytes 0104
is the ucTableFormatRevision and 0x01
the ucTableContentRevision 0x04
.
The next two byte are 880e
and encode the device support 880e
-> 0x0e88
of all connectors defines later, it is a bitfield, the bits are described in this list. We needed to change this value to 0x0e8a
-> 8a0e
- it sets basically bit #1 to 1 (LCD1 support).
Next two bytes decode the number of connectors in the vBIOS, here 0500
-> 0x0005
= 5d
. This info will remain unchanged.
Now follow 5 (# of connectors) chunks of 16 bytes describing each of the five connectors, in particular
13315800212200008500000008000000
Using the C struct atom_display_object_path_v2 or the upper printout from atomdis
we can easily decode these 16 Byte into
1331 uint16_t display_objid; //Connector Object ID or Misc Object ID
5800 uint16_t disp_recordoffset;
2122 uint16_t encoderobjid; //first encoder closer to the connector, could be either an external or intenal encoder
0000 uint16_t extencoderobjid; //2nd encoder after the first encoder, from the connector point of view;
8500 uint16_t encoder_recordoffset;
0000 uint16_t extencoder_recordoffset;
0800 uint16_t device_tag; //a supported device vector, each display path starts with this.the paths are enumerated in the way of priority, a path appears first
The device_tag contain two bye called
uint8_t priority_id;
uint8_t reserved;
All entries including recordoffset in it's name are literally only offsets in bytes (absolute numbers counting from the start of the data table. These records can contain one or more encoded structures, in particular here again at position 0x58 you find two such structures followed by a FF stop byte:
0104910002040200FF
The first structure is 01049100
and decodes to
01049100
- 01
struture type, 04
structure length in byte, content 9100
(this is 0x0091
the I2C ID of the first connector)
(Typ 01 = ATOM_I2C_RECORD_TYPE)
The second structure is 02040200
and decodes to
02040200
- 02
struture type, 04
structure length in byte, content 0200
(this is 0x0020
the pin ID and plugin state of the first connector)
(Typ 02 = ATOM_HPD_INT_RECORD_TYPE)
at position 0x85
you will find another list of such structures, in this particular case it is only a single one
14060F000000FF
- 14
struture type, 06
structure length in byte, content 0F00 0000
(this is 0x0000000F, a bit mask)
(Typ 14 = ATOM_ENCODER_CAP_RECORD_TYP)
0xF
covers the first five entries of this enumeration, 0x1FF
would cover them all.
The device_tag describes the connector type, all five connectors described uses a display port type. So we need to change this entry to eDP 0x002
or 0200
and at the same time we know from analyzing all the former AMD vBIOS versions that the display_objid like 1331
has to begin with 14, like 1431
.
In my case the successful change was using the second connector changing the display_objid
1332
-> 1432
and the device_tag from
8000
-> 0200
If you take the complete 16 byte description of the second connector you get this:
1332 6100 1E21 0000 8C00 0000 8000 0000
(original DP)
1432 6100 1E21 0000 8C00 0000 0200 0000
(modified to eDP)
This was in addition to the usDeviceSupport value adjustment all we needed to change at the very end!
So the process in general would be quite easy: You prepare five simple modified OBJ_INFO data tables using ATOMTableResize to fetch the original table from the BIOS, using Hex Fiend to do this simple modification and change on by one the both device_tag and display_objid. These modified tables will be imported back into the original BIOS creating five versions. It is important to use the tool ATOMTableResize because it will fix the checksum of the legacy BIOS header. A wrong checksum makes macOS ignoring the injected BIOS!
Unfortunately the RX5500XT in particular does not run when flashed with a modified BIOS. So the only workaround would be to inject the first 64K bytes of the five versions via OpenCore DeviceProperties of the GPU into the macOS.
The DevicePath of this GPU looks unusual PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)
and using the ATY,bin _image
with type Data
you can copy and paste from Hex Fiend into Xcode editing the config.plist the first 64k. Change the view in Hex Fiend (byte grouping to None) to avoid getting white spaces copied over).
<key>PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)</key>
<dict>
<key>enable-gva-support</key>
<integer>1</integer>
<key>shikigva</key>
<integer>128</integer>
<key>unfairgva</key>
<integer>1</integer>
<key>ATY,bin_image</key>
<data>Vapw6T ...... 64K bytes</data>
</dict>
You will also need two more entries applbkl=3
and agdpmod=pikera
to the boot-args of OpenCore in the config.plist. The former will enable the brightness control keys and after a system sleep also brightness control while the latter is key to avoid macOS shutting down the internal LCD on the login screen. This agdpmod=pikera
is needed for all RDNA1.0 AMD dGPU when used in Macs and Hacks. So no exception here.
Before using the simple mode described above we also added in one big operation more modifications to the table changing the size by adding more structures.
The second structure is 02040200
and decodes to
03040200
- 03
struture type, 04
structure length in byte, content 0200
(this is 0x0020
the I2C ID of the first connector)
(Typ 03 = ATOM_CONNECTOR_CAP_RECORD_TYPE)
and
2306020000
- 23
struture type, 06
structure length in byte, content 020000
(this is 0x000020
the I2C ID of the first connector)
(Typ 23 = ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
The result will be like this, you have to adjust size and record address entries as described above:
DA0001048A0E05001331580021220000
B70000000800000014326B001E210000
BE0000000200000013337E001E220000
C5000000000200001334910020210000
CC000000000400001335A40021210000
D3000000000800000104910002040200
03040200230602000000FF0104920002
04030003040200230602000000FF0104
93000204040003040200230602000000
FF010494000204050003040200230602
000000FF010490000204010003040200
230602000000FF14060F000000FF1406
0F000000FF14060F000000FF14060F00
0000FF14060F000000FF
finally we thought we would have to add the PWM frequency of 13.000 Hz used by the iMac in an another data table named LCD_INFO. The process to fetch, alter and reinsert is always the same and needs ATOMTableResize to fix the checksum after each change.
The PWM frequency would be located at absolute position 36d, and coded to C832
= 0x32C8
= 13000d
Hz - the number has to be used in Hertz.
The absolute position of 36d depends on table analysis, again. The table header is always 4 bytes encoding length and revision numbers. It is followed by an structure containing another struct atom_dtd_format of 28 bytes size and atom_common_table_header of four bytes size, makes 4+28+4 = 36 (all decimal).
4 Byte LCD_INFO HEADER 28 Byte struct atom_dtd_format 4 Byte struct atom_common_table_header
-> 2 Byte uint16_t backlight_pwm at position 36d
5C00 0201 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0600 0000
0000 C832 0000 3421 0000 B80B 0000 0000
7D00 0001 0000 0000 00FF FF00 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000
Final reminder:
After making changes to your vBIOS use ATOMTableResize to included the modified tables and fix the checksum. Thereafter you can get the first 64k using Hex Fiend, again. Do not just alter the vBIOS using the editor. Your iMac will ignore the injected vBIOS!