AArch64 option ROMs for AMD GPUs

Usually, on AArch64 systems with proprietary UEFI firmware, a HDMI/DP display does not light up until the point where the OS driver takes control. This makes it tedious to access the UEFI configuration menus or the GRUB bootloader menu, since it either requires connecting a VGA monitor to the BMC, or finding it on the network and connecting to it.

Also, OS drivers for GPUs are all developed and tested under the assumption that the option ROM driver has executed when the OS takes over. This means any errata handling or OEM tweaks may not take effect as they would otherwise.

For AMD cards, it is possible to address this problem by replacing the x86 EFI driver on the card with an AArch64 one (or adding one if only a legacy x86 driver was there in the first place)

  1. Build flashrom from the ati branch at https://github.com/ardbiesheuvel/flashrom
  2. Check out edk2 (https://github.com/tianocore/edk2) and build the base tools (make -C BaseTools/)
  3. Dump the option ROM (as root)

    # ./flashrom -p ati_spi -r vbios.rom

    (Note that the ati_spi driver is currently hardcoded to support PCI domain/segment #0 only. )

  4. List the table of contents
    $ edk2/BaseTools/Source/C/bin/EfiRom -d vbios.rom 
    Image 1 -- Offset 0x0
      ROM header contents
        Signature              0xAA55
        PCIR offset            0x0244
        Signature               PCIR
        Vendor ID               0x1002
        Device ID               0x67DF
        Length                  0x0018
        Revision                0x0000
        DeviceListOffset        0x00
        Class Code              0x030000
        Image size              0xEA00
        Code revision:          0x0F32
        MaxRuntimeImageLength   0x00
        ConfigUtilityCodeHeaderOffset 0x4D41
        DMTFCLPEntryPointOffset 0x2044
        Indicator               0x00
        Code type               0x00
    Image 2 -- Offset 0xEA00
      ROM header contents
        Signature              0xAA55
        PCIR offset            0x001C
        Signature               PCIR
        Vendor ID               0x1002
        Device ID               0x67DF
        Length                  0x0018
        Revision                0x0000
        DeviceListOffset        0x00
        Class Code              0x030000
        Image size              0xE600
        Code revision:          0x0000
        MaxRuntimeImageLength   0x00
        ConfigUtilityCodeHeaderOffset 0x4F47
        DMTFCLPEntryPointOffset 0x2050
        Indicator               0x80   (last image)
        Code type               0x03   (EFI image)
      EFI ROM header contents
        EFI Signature          0x0EF1
        Compression Type       0x0001 (compressed)
        Machine type           0x8664 (X64)
        Subsystem              0x000B (EFI boot service driver)
        EFI image offset       0x0058 (@0xEA58)
    
    

    The first image contains the ATOM BIOS code, and should be kept – it is loaded by the OS driver when it probes the card. The second image is the existing x86 EFI driver.

  5. Create a compressed option ROM image from the AMD GOP driver for arm64 (https://www.amd.com/en/support/kb/release-notes/rn-aar), using the vendor and device IDs taken from the output above.
    $ edk2/BaseTools/Source/C/bin/EfiRom -f 0x1002 -i 0x67DF -l 0x030000 -ec Arm64Gop_1_68.efi

    This will create a file called Arm64Gop_1_68.rom in the current directory.

  6. Copy the ROM image to a new file, and store the old one for safe keeping.

  7. If the ROM image has sufficient space for an additional driver and you want to keep the x86 EFI driver, or if it does not have a EFI driver in the first place, you will need to use a hex editor to find the 0x80 ‘indicator’ byte at offset 22 of the last header that starts with PCIR, and change it to 0x0.

  8. Insert the AMD GOP option ROM image into the copy of the option ROM

    $ dd if=Arm64Gop_1_68.rom of=vbios_new.rom conv=notrunc seek=<byte offset>

    where byte offset equals offset + size of the preceding image. Note that this must be a multiple of 512. For the image above, this would be 0xea00 + 0xe600, assuming we are keeping the x86 driver (or 0xea00 if not).

  9. Dump the new image contents to double check that everything looks as expected.
    $ edk2/BaseTools/Source/C/bin/EfiRom -d vbios_new.rom 
    Image 1 -- Offset 0x0
      ROM header contents
        Signature              0xAA55
        PCIR offset            0x0244
        Signature               PCIR
        Vendor ID               0x1002
        Device ID               0x67DF
        Length                  0x0018
        Revision                0x0000
        DeviceListOffset        0x00
        Class Code              0x030000
        Image size              0xEA00
        Code revision:          0x0F32
        MaxRuntimeImageLength   0x00
        ConfigUtilityCodeHeaderOffset 0x4D41
        DMTFCLPEntryPointOffset 0x2044
        Indicator               0x00
        Code type               0x00
    Image 2 -- Offset 0xEA00
      ROM header contents
        Signature              0xAA55
        PCIR offset            0x001C
        Signature               PCIR
        Vendor ID               0x1002
        Device ID               0x67DF
        Length                  0x0018
        Revision                0x0000
        DeviceListOffset        0x00
        Class Code              0x030000
        Image size              0xE600
        Code revision:          0x0000
        MaxRuntimeImageLength   0x00
        ConfigUtilityCodeHeaderOffset 0x4F47
        DMTFCLPEntryPointOffset 0x2050
        Indicator               0x00
        Code type               0x03   (EFI image)
      EFI ROM header contents
        EFI Signature          0x0EF1
        Compression Type       0x0001 (compressed)
        Machine type           0x8664 (X64)
        Subsystem              0x000B (EFI boot service driver)
        EFI image offset       0x0058 (@0xEA58)
    Image 3 -- Offset 0x1D000
      ROM header contents
        Signature              0xAA55
        PCIR offset            0x001C
        Signature               PCIR
        Vendor ID               0x1002
        Device ID               0x67DF
        Length                  0x001C
        Revision                0x0003
        DeviceListOffset        0x00
        Class Code              0x030000
        Image size              0xFA00
        Code revision:          0x0000
        MaxRuntimeImageLength   0x00
        ConfigUtilityCodeHeaderOffset 0x00
        DMTFCLPEntryPointOffset 0x00
        Indicator               0x80   (last image)
        Code type               0x03   (EFI image)
      EFI ROM header contents
        EFI Signature          0x0EF1
        Compression Type       0x0001 (compressed)
        Machine type           0xAA64 (AA64)
        Subsystem              0x000B (EFI boot service driver)
        EFI image offset       0x0038 (@0x1D038)
    
    

  10. Use flashrom with the -w switch to write the new image back to the device.
  11. In the UEFI shell, the ‘drivers’ command will list all the UEFI drivers that have been loaded. E.g.,

    D1 00014400 D - -  1  - AMD GOP ARM64 Release Driver, Rev. Offset(0x1D000,...

    where the ‘D’ in the third column signifies that it has attached to the device.