-
-
Notifications
You must be signed in to change notification settings - Fork 13
Legacy BIOS
This sections describes what you find in general on a PC Laptop MXM card and what tools are needed to make the vBIOS iMac compatible. The AMD BIOS contains in general two parts, the first is called legacy BIOS responsible for all functionality containing data and code for a number or modules, like the VRAM_INFO (responsible for VRAM type support). In general one can assume that the BIOS coming with a card already supports all hardware including the VRAM chips. We will focus on this first part here.
Tools to analyze:
- atomdis (prints out data and command tables)
- ATOMTableResize (allow to change complete modules and recalculates the CRC32 checksum)
So very first step will be adjusting the output connector table (OBJ_INFO module) within the legacy BIOS part. This is in general necessary because the PC cards have been used in Laptops with different hardware and different video ports. We need at least one connector of type eDP with correct parameters, and another of type DP to drive the external (miniDP) connected monitor. Only in a single case the BIOS came already correctly configured.
More details to follow ...
The usable storage of the BIOS has a fixed length of 0x20000 bytes (131072 in decimal) regardless which chip size you may find on physical MXM cards. These 0x20000 bytes are divided in 256 blocks of 512 bytes. So all BIOS parts together (legacy and GOP and possible other parts) cannot exceed this 256 blocks. In general both the legacy and GOP part have nearly equal size near 120 blocks, which leaves literally no space for additional parts (aka code).
The internal structure demands to start on block boundaries, this is why you always start replace actions at the very same spot or you have to cross check if the starting address were you insert the new BIOS part is a multiple of 512 (byte).
All BIOS parts have a header starting with 0xAA55
and a PCI data structure, short body, starting with 0x50434952
which is PCIR in ascii and both can be visually spotted using hex editor. One can have more than two those parts chained together in a single BIOS as shown below on the right hand side bar.
You can see the length of legacy BIOS part counted in blocks is mentioned two times within the print out on the right hand side, in the ROM Header 0
it is called Image Size
(79) and within the PCI Data Structure
it is called Image Length
(79, too). In case you manually modify the BIOS PCI Data structure cutting away code/datat you have to manually recalculate the new block size (measured in 512 byte) and change both entries. In the last step use ATOMTableResize to recalculate the checksum.
You may have noticed from the upper picture that there is a Last Image Index
marked. If it has the value 0x80
the computer stops reading/interpreting code after that part. If you add additional parts you have to make sure, the last part has the value 0x80
, all former ones the value 0x00
. It is quite easy. If you want to disable trailing parts from being used just set the Last Image Index
in the last module you want to use to 0x80
and recalculate the checksum. The first part has an index value of 0x00
, the latter GOP part an index value of 0x80
. We will see EFI BIOS versions having four such parts, of course only the last one using the 0x80
.
The checksum does only apply to the first legacy part. Whenever you change data there a recalculation is necessary. Changing the following parts does not change the checksum at all!
In order to understand modifications explained later here a short overview. The legacy BIOS starts with it's ROM Signature:
- PCI Header starting with
AA55
- PCI Data Structure starting with ascii
PCIR
- a few bytes of more data, a final ascii
AMD ATOMBIOS
, some trailing0x00000000
blocks to fill the gap until the VGA parts starts- vga bios itself (starting in the W5170M BIOS at
0x280
)- COMMAND TABLE begins with mit
A6000101
(starting in the W5170M BIOS at0x9D76
)- DATA TABLE begins either with
4A000101
or48000101
(starting in the W5170M BIOS at0x9E1C
)- commands (code of modules, module by module, as described in COMMAND table)
- data (of modules)
You can use the tool atomdis to print and disassemble contents:
Usage: ../../../Tools/ATOMDIS/atomdis [<opts>] <file> <cmd> [<cmd>...]
Opts: -o <vga_offset> Specify offset of VGA bios in <file>
-r <registers.xml> Load registers specification file
-a <addr_format> Format for command addresses. Default: '%04x: '
-A Output addresses instead of offsets
for MM register, FB, and BIOS data accesses
Cmds: i Dump info on AtomBIOS
l Info + Table list
x <start> <len> Hexdump
d <nr> Data table dump
c <nr> Command table disasm
C <start> Table disasm (debug)
T Test (debug)
F Full dump (long output, sanitized)
all values in hex
If you want to list all command and data tables (start addresses and length in hex values):
atomdis W5170M-GOP.rom l
Read 20000 bytes of data from W5170M-GOP.rom
Command Tables:
0000: b5e2 Len 006e (ASIC_Init)
0001: b650 Len 0057 (GetDisplaySurfaceSize)
0002: b6a8 Len 010f (ASIC_RegistersInit)
0003: d414 Len 0118 (VRAM_BlockVenderDetection)
0004: e39e Len 01c8 (SetClocksRatio/DIGxEncoderControl)
0005: b7b8 Len 03c5 (MemoryControllerInit)
0006: - (EnableCRTCMemReq)
0007: d52c Len 000d (MemoryParamAdjust)
0008: - (DVOEncoderControl)
0009: bb7e Len 00ff (GPIOPinControl)
000a: bc7e Len 0141 (SetEngineClock)
000b: bdc0 Len 00fe (SetMemoryClock)
000c: bebe Len 052c (SetPixelClock)
000d: c3ea Len 0140 (DynamicClockGating)
000e: c52a Len 0050 (ResetMemoryDLL)
000f: c57a Len 0062 (ResetMemoryDevice)
0010: df7a Len 016d (MemoryPLLInit)
0011: e0e8 Len 0089 (AdjustDisplayPll)
0012: c7a6 Len 0111 (AdjustMemoryController)
0013: c8b8 Len 005f (EnableASIC_StaticPwrMgt)
0014: c918 Len 0074 (ASIC_StaticPwrMgtStatusChange/SetUniphyInstance)
0015: c98c Len 0076 (DAC_LoadDetection)
0016: - (LVTMAEncoderControl)
0017: - (LCD1OutputControl)
0018: ca02 Len 00b2 (DAC1EncoderControl)
0019: - (DAC2EncoderControl)
001a: - (DVOOutputControl)
001b: - (CV1OutputControl)
001c: ef5a Len 0038 (GetConditionalGoldenSetting/SetCRTC_DPM_State)
001d: - (TVEncoderControl)
001e: ef92 Len 00b8 (TMDSAEncoderControl)
001f: f04a Len 0126 (LVDSEncoderControl)
0020: - (TV1OutputControl)
0021: cab4 Len 007a (EnableScaler)
0022: cb2e Len 004b (BlankCRTC)
0023: cb7a Len 003e (EnableCRTC)
0024: cbb8 Len 01ad (GetPixelClock)
0025: cd66 Len 002c (EnableVGA_Render)
0026: cd92 Len 0022 (EnableVGA_Access/GetSCLKOverMCLKRatio)
0027: - (SetCRTC_Timing)
0028: cdb4 Len 0019 (SetCRTC_OverScan)
0029: - (SetCRTC_Replication)
002a: cdce Len 00af (SelectCRTC_Source)
002b: ce7e Len 01e6 (EnableGraphSurfaces)
002c: d064 Len 0058 (UpdateCRTC_DoubleBufferRegisters)
002d: d0bc Len 00d9 (LUT_AutoFill)
002e: - (EnableHW_IconCursor)
002f: d196 Len 004a (GetMemoryClock)
0030: d1e0 Len 004e (GetEngineClock)
0031: d22e Len 0128 (SetCRTC_UsingDTDTiming)
0032: - (ExternalEncoderControl)
0033: - (LVTMAOutputControl)
0034: d356 Len 00be (VRAM_BlockDetectionByStrap)
0035: d53a Len 00e4 (MemoryCleanUp)
0036: d61e Len 0239 (ReadEDIDFromHWAssistedI2C/ProcessI2cChannelTransaction)
0037: - (WriteOneByteToHWAssistedI2C)
0038: d858 Len 005f (ReadHWAssistedI2CStatus/HPDInterruptService)
0039: d8b8 Len 002d (SpeedFanControl)
003a: d8e6 Len 000a (PowerConnectorDetection)
003b: d8f0 Len 0018 (MC_Synchronization)
003c: d908 Len 0088 (ComputeMemoryEnginePLL)
003d: d990 Len 005f (MemoryRefreshConversion)
003e: e566 Len 0029 (VRAM_GetCurrentInfoBlock)
003f: d9f0 Len 01c0 (DynamicMemorySettings)
0040: dbb0 Len 0355 (MemoryTraining)
0041: df06 Len 0074 (EnableSpreadSpectrumOnPPLL)
0042: - (TMDSAOutputControl)
0043: e172 Len 00c6 (SetVoltage)
0044: - (DAC1OutputControl)
0045: - (DAC2OutputControl)
0046: e2aa Len 00f4 (SetupHWAssistedI2CStatus)
0047: c5dc Len 0110 (ClockSource)
0048: c6ec Len 00ba (MemoryDeviceInit)
0049: - (EnableYUV)
004a: - (DIG1EncoderControl)
004b: - (DIG2EncoderControl)
004c: e590 Len 0746 (DIG1TransmitterControl/UNIPHYTransmitterControl)
004d: - (DIG2TransmitterControl/LVTMATransmitterControl)
004e: ecd6 Len 0227 (ProcessAuxChannelTransaction)
004f: eefe Len 005c (DPEncoderService)
Data Tables:
0000: - (UtilityPipeLine)
0001: - (MultimediaCapabilityInfo)
0002: - (MultimediaConfigInfo)
0003: 9e66 Len 00e4 Rev 01:02 (StandardVESA_Timing) (struct size 01c4)
0004: 9f4a Len 006c Rev 02:02 (FirmwareInfo) (struct size 006c)
0005: 9fb6 Len 0304 Rev 02:01 (DAC_Info) (struct size 0008)
0006: a2ba Len 004e Rev 01:03 (LVDS_Info) (struct size 0034)
0007: b186 Len 045b Rev 03:01 (TMDS_Info) (struct size 001e)
0008: - (AnalogTV_Info)
0009: - (SupportedDevicesInfo)
000a: a308 Len 00dc Rev 01:01 (GPIO_I2C_Info)
000b: a3e4 Len 000c Rev 01:05 (VRAM_UsageByFirmware) (struct size 000c)
000c: a3f0 Len 001c Rev 01:01 (GPIO_Pin_LUT)
000d: a40c Len 00a8 Rev 01:01 (VESA_ToInternalModeLUT)
000e: - (ComponentVideoInfo)
000f: a4b4 Len 0268 Rev 06:01 (PowerPlayInfo)
0010: - (CompassionateData)
0011: b16e Len 0018 Rev 02:01 (SaveRestoreInfo/DispDevicePriorityInfo)
0012: - (PPLL_SS_Info/SS_Info)
0013: - (OemInfo)
0014: - (XTMDS_Info)
0015: - (MclkSS_Info)
0016: a71c Len 011e Rev 01:03 (Object_Info/Object_Header) (struct size 0010)
0017: a83a Len 007d Rev 01:01 (IndirectIOAccess)
0018: - (MC_InitParameter/AdjustARB_SEQ)
0019: - (ASIC_VDDC_Info)
001a: b0c0 Len 0040 Rev 03:01 (ASIC_InternalSS_Info/ASIC_MVDDC_Info) (struct size 0034)
001b: b100 Len 006d Rev 02:03 (TV_VideoMode/DispOutInfo)
001c: a8b8 Len 06c0 Rev 02:01 (VRAM_Info) (struct size 0354)
001d: - (MemoryTrainingInfo/ASIC_MVDDQ_Info)
001e: - (IntegratedSystemInfo)
001f: - (ASIC_ProfilingInfo/ASIC_VDDCI_Info)
0020: af78 Len 0148 Rev 03:01 (VoltageObjectInfo/VRAM_GPIO_DetectionInfo)
0021: - (PowerSourceInfo)
If you want to print/disassemble the Object_Info/Object_Header (short OBJ_INFO) module, it is module number 0x16 within the above printed Data Table. This module contains the connector information per port used to identify the connector types (LVDS, eDP, DP, HDMI, VGA, DVI, etc.) and parameters. So it is key to modify it properly or find an already proper working module from a BIOS of the same AMD GPU family.
atomdis W5170M-GOP.rom d 16
Read 20000 bytes of data from W5170M-GOP.rom
data_table 0000a71c #16 (Object_Info/Object_Header):
Size 011e
Format Rev. 01
Param Rev. 00
Content Rev. 03
00000000: 8a02 3e00 0000 ce00 0000 1200 ..>.........
00000010: 0000 0401 0000 0200 0a00 1431 0011 2121 ...........1..!!
00000020: 0800 0a00 1331 0011 2122 8000 0a00 1332 .....1..!".....2
00000030: 0011 2021 0002 0a00 1333 0011 2022 0400 .. !.....3.. "..
00000040: 0000 1431 6200 6800 0000 1331 7d00 8300 ...1b.h....1}...
00000050: 0000 1332 9800 9e00 0000 1333 b300 b900 ...2.......3....
00000060: 0000 0121 2100 0000 040c 0100 1001 0000 ...!!...........
00000070: 0200 0000 0104 9200 0204 0300 ff01 2122 ..............!"
00000080: 0000 0004 0c01 0010 0200 0008 0000 0001 ................
00000090: 0493 0002 0404 00ff 0120 2100 0000 040c ......... !.....
000000a0: 0100 2002 0000 8000 0000 0104 9000 0204 .. .............
000000b0: 0100 ff01 2022 0000 0004 0c01 0030 0200 .... ".......0..
000000c0: 0000 0200 0001 0491 0002 0402 00ff 0400 ................
000000d0: 0000 2121 f200 f800 0000 2122 fd00 0301 ..!!......!"....
000000e0: 0000 2021 0801 0e01 0000 2022 1301 1901 .. !...... "....
000000f0: 0000 0100 1101 1431 1404 0300 ff01 0011 .......1........
00000100: 0113 3114 0403 00ff 0100 1101 1332 1404 ..1..........2..
00000110: 0300 ff01 0011 0113 3314 0403 00ff ........3.....
NOTE: General revisionless dumper only.
NOTE: Data part see radeonhd
0000: ATOM_COMMON_TABLE_HEADER sHeader :
0000: USHORT usStructureSize = 0x011e (286)
0002: UCHAR ucTableFormatRevision = 0x01 (1)
0003: UCHAR ucTableContentRevision = 0x03 (3)
0004: USHORT usDeviceSupport = 0x028a (650)
0006: USHORT usConnectorObjectTableOffset = 0x003e (62)
0008: USHORT usRouterObjectTableOffset = 0x0000 (0)
000a: USHORT usEncoderObjectTableOffset = 0x00ce (206)
000c: USHORT usProtectionObjectTableOffset = 0x0000 (0)
000e: USHORT usDisplayPathTableOffset = 0x0012 (18)
Total data structure size: 0010
This Java tool offers a GUI to extract and replace modules completely from the BIOS. While replacing it recalculates all absolute new addresses within the data and command tables and fixes the CRC checksum of the legacy part.
You can mix and match modules found within the legacy BIOS of a common AMD GPU family (e.g. Venus) using this software. So if you already have adjusted the OBJ_INFO module responsible for connector settings to drive the iMac internal display you can pull this module out of a working BIOS and transplant it into a currently non working vBIOS of the same family. In fact I used the OBJ_INFO module found in the W5170M BIOS from a blue AMD card later for all other cards to enable the backlight on internal display on iMacs (here a green HP W5170M, a red Dell M5100 and finally a blue MXM-B M6000). This is the most easy way to get this most important part done.
The same applies to adjustment for VRAM support. As you may have noticed there are mostly three suppliers of VRAM, Samsung, Hynix and Micron/Elpida. Not all BIOS versions support all memory types from the start. If you want to add support for a new card of the same family with different VRAM chips just pull the VRAM_INFO module out of the BIOS coming with that new card and replace it in the already working iMac BIOS. It is that easy!
After replacing modules always save the file either by pressing save
or save and fix everything
. This way the address tables are rebuild and the checksum will be updated.
If you cannot find a proper working OBJ_INFO module you have to adjust it manually within the hex editor. This is the dark art ....