Skip to contentSkip to conversation

drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

PATCH New Oz Tiram 4 participants 25 messages Jun 21 – Jul 8

Subsystems (2)
lore
Share & tools
lore

Oz Tiram

author
#0 lore raw

PATCH 1/1 drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail:

- The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
- No platform BIOS mapping exists.

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted from the running hardware to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +19 -0
index aa039e148a5e..491f88f495a6 100644
@@ -26,6 +26,7 @@
  *          Jerome Glisse
  */
 
+#include <linux/firmware.h>
 #include "amdgpu.h"
 #include "atom.h"
 
@@ -457,6 +458,24 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{
+		const struct firmware *fw;
+		char fw_name[32];
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			adev->bios_size = fw->size;
+			release_firmware(fw);
+			if (adev->bios) {
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
 
Signature · 1 line
2.53.0
#1 lore raw
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [High] The firmware file fallback for APU VBIOS discovery does not validate the loaded firmware with check_atom_bios(), potentially leading to a kernel panic or out-of-bounds reads.

Pre-existing issues:
- [High] Pre-existing off-by-one boundary checks in check_atom_bios() allow out-of-bounds memory reads when evaluating truncated or malformed VBIOS images. --

commit 3e01d007e8160f9d82a04903ddd4a636561ac6f7
Author: Oz Tiram <[email protected]>

drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

This patch adds a fifth fallback path for APU VBIOS discovery using a firmware file loaded via request_firmware(). This allows a VBIOS image extracted from running hardware to be used when other methods like VFCT or ROM BAR fail.

Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5ee..491f88f495a66 100644

[ ... ]

Quoted 5 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +1 -0
@@ -457,6 +458,24 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) · line 471

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +10 -0
+		const struct firmware *fw;
+		char fw_name[32];
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			adev->bios_size = fw->size;
+			release_firmware(fw);
+			if (adev->bios) {

[Severity: High]
Does this new firmware fallback path need to validate the fetched memory using check_atom_bios()?

All other VBIOS discovery paths appear to validate the fetched memory before accepting the BIOS image. If the provided firmware file is empty (size 0), kmemdup() returns ZERO_SIZE_PTR (which evaluates to true). The driver will later dereference this pointer during ATOM BIOS parsing, which could cause a kernel page fault.

Additionally, if the firmware is malformed or undersized, the ATOM BIOS parser could read out-of-bounds.

[Severity: High]
This is a pre-existing issue, but check_atom_bios() appears to have off-by-one boundary checks that can allow out-of-bounds memory reads when evaluating malformed or truncated VBIOS images:

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c:check_atom_bios() {
    ...
	if (!bios || size < 0x49) {
		dev_dbg(adev->dev, "VBIOS mem is null or mem size is wrong\n");
		return false;
	}

	...

	bios_header_start = bios[0x48] | (bios[0x49] << 8);
    ...
}

If size is exactly 0x49 (73 bytes), the check size < 0x49 passes, but the code then accesses bios[0x49], which is the 74th byte, resulting in a 1-byte out-of-bounds read.

There is another similar boundary check later in the same function:

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c:check_atom_bios() {
    ...
	tmp = bios_header_start + 4;
	if (size < tmp) {
		dev_dbg(adev->dev, "VBIOS header is broken\n");
		return false;
	}

	if (!memcmp(bios + tmp, "ATOM", 4) ||
    ...
}

If the buffer size is exactly equal to tmp, size < tmp passes, but the subsequent memcmp() reads 4 bytes starting at tmp, which is completely past the end of the allocated buffer. Can these boundary checks be updated to prevent KASAN out-of-bounds warnings when parsing VBIOS blobs?

Quoted 9 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +7 -0
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
author
#2 lore raw

PATCH 1/1 drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

In reply to Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail:

- The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
- No platform BIOS mapping exists.

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted from the running hardware to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Validate the fetched firmware with check_atom_bios() before accepting
it, consistent with all other VBIOS discovery paths. Save fw->size before release_firmware() so it remains valid for the size check. Release the buffer via amdgpu_bios_release() if validation fails.

 drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +23 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
  *          Jerome Glisse
  */
 
+#include <linux/firmware.h>
 #include "amdgpu.h"
 #include "atom.h"
 
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{
+		const struct firmware *fw;
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
 
Signature · 1 line
2.53.0
#3 lore raw
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Out-of-bounds reads in check_atom_bios when validating VBIOS headers, made directly reachable via the new user-supplied firmware file fallback. --

commit a2fe12b488b874804f022bf152336e0c586847dc
Author: Oz Tiram <[email protected]>

drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

This commit adds a fifth fallback method to discover an APU VBIOS by requesting a firmware file when all other methods fail. The fallback uses request_firmware() and allocates the VBIOS buffer using kmemdup() with the exact firmware size.

Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5ee..86064c753b099 100644

[ ... ]

Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +2 -0
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{
+		const struct firmware *fw;

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) · line 472

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +10 -0
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {

[Severity: High]
This isn't a bug introduced by this patch, but allocating the buffer to the exact firmware size via kmemdup() exposes existing out-of-bounds reads in check_atom_bios().

Looking at check_atom_bios(), the initial size check is:

    if (!bios || size < 0x49) {
        ...
        return false;
    }

But then it reads bios[0x49]:

    bios_header_start = bios[0x48] | (bios[0x49] << 8);

If fw_size is exactly 0x49, bios[0x49] reads 1 byte past the end of the kmemdup() buffer.

Similarly, check_atom_bios() later checks size against tmp before reading 4 bytes for the ATOM signature:

    tmp = bios_header_start + 4;
    if (size < tmp) {
        ...
        return false;
    }

    if (!memcmp(bios + tmp, "ATOM", 4) ||
        !memcmp(bios + tmp, "MOTA", 4)) {

If size is exactly tmp (or up to tmp + 3), memcmp() will read up to 4 bytes past the end of the allocation.

Could a malformed firmware file loaded through this new path trigger KASAN slab-out-of-bounds warnings or page faults due to these bounds checks?

Quoted 13 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +10 -0
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
 
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#4 lore raw
In reply to Oz Tiram
Quoted 10 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail:

That's pretty odd to me. Isn't this a BIOS bug? Can you share more about why all of these are failing?

Does the UEFI GOP driver work?

Quoted 8 lines

- The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
- No platform BIOS mapping exists.

Quoted 8 lines

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted from the running hardware

I thought you just said this didn't work. How did you extract it?

Quoted 57 lines

to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Validate the fetched firmware with check_atom_bios() before accepting
it, consistent with all other VBIOS discovery paths. Save fw->size before release_firmware() so it remains valid for the size check. Release the buffer via amdgpu_bios_release() if validation fails.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++
  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +23 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
   *          Jerome Glisse
   */
 
+#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
 
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
  		goto success;
  	}
 
+	{
+		const struct firmware *fw;
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
  	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
  	return false;
 
#5 lore raw
Quoted 32 lines · Mario Limonciello
Quoted 10 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail:

That's pretty odd to me. Isn't this a BIOS bug? Can you share more about why all of these are failing?

Does the UEFI GOP driver work?

Quoted 12 lines

- The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
- No platform BIOS mapping exists.

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Quoted 6 lines
Quoted 4 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted from the running hardware

I thought you just said this didn't work. How did you extract it?

This is not likely to work which is why we don't generally support this. On APUs, the base vbios image is updated by the sbios at boot depending on the runtime configuration of the specific system (OEM display configuration, etc.). Overriding these values with something else can cause serious problems.

Alex

Quoted 59 lines
Quoted 58 lines

to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Validate the fetched firmware with check_atom_bios() before accepting
it, consistent with all other VBIOS discovery paths. Save fw->size before release_firmware() so it remains valid for the size check. Release the buffer via amdgpu_bios_release() if validation fails.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++
  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +23 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
   *          Jerome Glisse
   */
 
+#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
 
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
              goto success;
      }
 
+     {
+             const struct firmware *fw;
+             char fw_name[32];
+             size_t fw_size;
+
+             snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+                      adev->pdev->vendor, adev->pdev->device);
+             if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+                     adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+                     fw_size = fw->size;
+                     release_firmware(fw);
+                     if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                             amdgpu_bios_release(adev);
+                     } else {
+                             adev->bios_size = fw_size;
+                             dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                                      fw_name);
+                             goto success;
+                     }
+             }
+     }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;
 
author
#6 lore raw
In reply to Mario Limonciello

Hi Mario,

Sorry for the slow response, I'm new to the kernel contribution process. Thanks for the review. v2 addresses your questions: -

The VFCT does contain the iGPU entry, but with a stale PCIBus value from BIOS POST time (0x6A). With pci=realloc,assign-busses the iGPU lands on bus 0x0B at runtime, so amdgpu_acpi_vfct_bios() never matches it

This is clarified in the commit message along with a note that the UEFI GOP driver initializes the iGPU successfully, confirming the hardware is functional.

The VBIOS image data in the VFCT is valid — only the PCIBus metadata is wrong.

The firmware file was extracted directly from the VFCT with dd, skipping past the ACPI header and VFCT_IMAGE_HEADER. The commit message now documents the exact command and byte offsets.

The patch follows.

Oz

Quoted 92 lines · Mario Limonciello
Quoted 10 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail:

That's pretty odd to me.  Isn't this a BIOS bug?  Can you share more about why all of these are failing?

Does the UEFI GOP driver work?

Quoted 8 lines

   - The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
   - No platform BIOS mapping exists.

Quoted 8 lines

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted from the running hardware

I thought you just said this didn't work.  How did you extract it?

Quoted 54 lines

to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Validate the fetched firmware with check_atom_bios() before accepting it, consistent with all other VBIOS discovery paths. Save fw->size before release_firmware() so it remains valid for the size check. Release the buffer via amdgpu_bios_release() if validation fails.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

author
#7 lore raw

PATCH v2 1/1 drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

In reply to Mario Limonciello

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail. The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

- The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A). When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it).
- No platform BIOS mapping exists.

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional. The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong. The firmware file can be extracted directly from the VFCT using dd:

  dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
     of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but
with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets. Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

 drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +23 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
  *          Jerome Glisse
  */
 
+#include <linux/firmware.h>
 #include "amdgpu.h"
 #include "atom.h"
 
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{
+		const struct firmware *fw;
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
 
Signature · 1 line
2.53.0
#8 lore raw
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Insufficient size bounds checks in check_atom_bios() lead to out-of-bounds memory reads when validating the VBIOS image. --

commit f277c5eb3a5ff47c43a2c9dc08a427a7be71788e
Author: Oz Tiram <[email protected]>

drm/amd/amdgpu: add firmware file fallback for APU VBIOS discovery

This patch adds a fallback method to load the APU VBIOS from a firmware file when all other discovery methods (VFCT, VRAM BAR, ROM BAR, platform BIOS) fail. This allows hybrid graphics systems with incorrect ACPI metadata to initialize successfully by placing an extracted VBIOS in the firmware path.

Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index 3ebdd792feec1..64b226cb17e3a 100644

[ ... ]

Quoted 6 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +2 -0
@@ -463,6 +464,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
 		goto success;
 	}
 
+	{
+		const struct firmware *fw;

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) · line 478

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +10 -0
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {
                                                           ^^^^^^^^^^^^^^^^^^

[Severity: High]
This isn't a bug introduced by this patch, but passing an arbitrary firmware file size to check_atom_bios() can trigger out-of-bounds reads due to insufficient bounds checks in that function.

If the firmware file size is exactly 73 bytes (size == 0x49), the initial check in check_atom_bios() passes:

check_atom_bios() {
	...
	if (!bios || size < 0x49) {
		...
		return false;
	}
	...

However, the subsequent header read accesses bios[0x49], which is 1 byte past the end of a 73-byte buffer:

	...
	bios_header_start = bios[0x48] | (bios[0x49] << 8);
	...

Similarly, if the firmware size is equal to tmp, the length check passes:

	...
	tmp = bios_header_start + 4;
	if (size < tmp) {
		...
		return false;
	}
	...

But the memcmp() that follows will read 4 bytes starting exactly at the end of the allocated buffer:

	...
	if (!memcmp(bios + tmp, "ATOM", 4) ||
	    !memcmp(bios + tmp, "MOTA", 4)) {
	...

Could this lead to memory safety issues if a malformed firmware file is provided? Should the checks in check_atom_bios() be updated to ensure size is strictly greater than 0x49, and that size >= tmp + 4 before the memcmp() evaluation?

Quoted 12 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +10 -0
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
 	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
 	return false;
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#9 lore raw
In reply to Oz Tiram
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail. The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

- The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A). When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it).
- No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional. The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 54 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but
with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets. Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++
  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +23 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
   *          Jerome Glisse
   */
 
+#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
 
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
  		goto success;
  	}
 
+	{
+		const struct firmware *fw;
+		char fw_name[32];
+		size_t fw_size;
+
+		snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+			 adev->pdev->vendor, adev->pdev->device);
+		if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+			adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			fw_size = fw->size;
+			release_firmware(fw);
+			if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+				amdgpu_bios_release(adev);
+			} else {
+				adev->bios_size = fw_size;
+				dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+					 fw_name);
+				goto success;
+			}
+		}
+	}
+
  	dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
  	return false;
 
author
#10 lore raw

Hi Mario,

  To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

  I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

  Oz

Quoted 109 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 51 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses.  Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#11 lore raw
Quoted 6 lines · Oz Tiram

Hi Mario,

  To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now. You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

  I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it. But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 113 lines

  Oz

Quoted 109 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 51 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses.  Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

From 42ac2fe3085cc3593523ac3e514bc36616078b4f Mon Sep 17 00:00:00 2001
From: Mario Limonciello <[email protected]>
Date: Sun, 5 Jul 2026 15:48:05 -0500
Subject: [PATCH] drm/amdgpu/radeon: Fix VFCT bus number matching with soft
filter

On systems where PCI bus renumbering occurs (e.g. pci=realloc, resource conflicts), the runtime bus number may differ from the BIOS POST bus number recorded in the VFCT table. This causes amdgpu_acpi_vfct_bios() to fail finding the VBIOS even though the correct device entry exists.

Introduce amdgpu_acpi_vfct_match() which treats the bus number as a soft filter: vendor/device/function identity is the hard requirement, while exact bus match is the preferred path. When bus numbers disagree but device identity matches, accept the VFCT entry and log a dev_notice for diagnostics.

Apply the same fix to radeon_acpi_vfct_bios().

While updating radeon, also modernize the error handling:
- Replace DRM_ERROR with dev_info/dev_notice
- Remove legacy goto out + acpi_put_table pattern (acpi_put_table was removed from the kernel)
- Use early return instead of goto for cleaner control flow

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 48 +++++++++++++--
 drivers/gpu/drm/radeon/radeon_bios.c     | 78 +++++++++++++++++-------
 2 files changed, 99 insertions(+), 27 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +42 -6
index 35d04e69aec0..fa730af5e979 100644
@@ -370,6 +370,46 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
 		false : amdgpu_asic_read_disabled_bios(adev);
 }
 
+/**
+ * amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
+ * @adev: AMDGPU device
+ * @vhdr: VFCT image header to check
+ *
+ * VFCT entries contain the PCI bus number as recorded during BIOS POST.
+ * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
+ * resource conflicts), the runtime bus number may differ from the POST
+ * value.  Match by device identity (vendor + device + function) and use
+ * the bus number as a preference: exact bus match is preferred, but when
+ * the bus numbers disagree we accept the entry if the device identity
+ * matches.
+ *
+ * Returns: 0 on match, -ENODEV on no match
+ */
+static int amdgpu_acpi_vfct_match(struct amdgpu_device *adev,
+				  VFCT_IMAGE_HEADER *vhdr)
+{
+	/* Vendor and device IDs must always match */
+	if (vhdr->VendorID != adev->pdev->vendor ||
+	    vhdr->DeviceID != adev->pdev->device)
+		return -ENODEV;
+
+	if (vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
+	    vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn))
+		return -ENODEV;
+
+	/* Exact bus number match - preferred */
+	if (vhdr->PCIBus == adev->pdev->bus->number)
+		return 0;
+
+	/* Bus mismatch but device identity matches (PCI renumbering case) */
+	dev_notice(adev->dev,
+		   "VFCT bus number mismatch: table %u != runtime %u, "
+		   "matching by device identity (vendor 0x%04x device 0x%04x)\\n",
+		   vhdr->PCIBus, adev->pdev->bus->number,
+		   adev->pdev->vendor, adev->pdev->device);
+	return 0;
+}
+
 #ifdef CONFIG_ACPI
 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 {
@@ -406,11 +446,7 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 		}
 
 		if (vhdr->ImageLength &&
-		    vhdr->PCIBus == adev->pdev->bus->number &&
-		    vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
-		    vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
-		    vhdr->VendorID == adev->pdev->vendor &&
-		    vhdr->DeviceID == adev->pdev->device) {
+		    !amdgpu_acpi_vfct_match(adev, vhdr)) {
 			adev->bios = kmemdup(&vbios->VbiosContent,
 					     vhdr->ImageLength,
 					     GFP_KERNEL);
@@ -424,7 +460,7 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 		}
 	}
 
-	dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
+	dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\\n");
 	return false;
 }
 #else
drivers/gpu/drm/radeon/radeon_bios.c +57 -21

115 lines not on this page · raw message

Signature · 1 line
2.53.0
author Tested-by
#12 lore raw

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

  amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 != runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Quoted 136 lines · Mario Limonciello
Quoted 6 lines · Oz Tiram

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here
- if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 114 lines

   Oz

Quoted 110 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 52 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses.  Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23
+++++++++++++++++++++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#13 lore raw

Hi Oz,

Quoted 12 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

  amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 !=
runtime 11,
      matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming. Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 137 lines · Mario Limonciello
Quoted 136 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here
- if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 114 lines

   Oz

Quoted 110 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 52 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses.  Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++
++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

author
#14 lore raw

Hi Mario,

Quoted 1 line

If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

  amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Thank you,

Oz

Quoted 166 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 != runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 135 lines · Mario Limonciello
Quoted 134 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 114 lines

   Oz

Quoted 110 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 52 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23
+++++++++++++++++++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#15 lore raw
Quoted 9 lines · Oz Tiram

Hi Mario,

Quoted 1 line

If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

  amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying. I would like to dig a little bit futher into that though. What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 174 lines

Thank you,

Oz

Quoted 166 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 135 lines · Mario Limonciello
Quoted 134 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 114 lines

   Oz

Quoted 110 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 52 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

author
#16 lore raw

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Oz

Quoted 202 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

 > If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

   amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying.  I would like to dig a little bit futher into that though.  What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 175 lines

Thank you,

Oz

Quoted 167 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 136 lines · Mario Limonciello
Quoted 135 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 115 lines

   Oz

Quoted 111 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 53 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23
+++++++++++++++++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name),
"amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#17 lore raw
Quoted 8 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 206 lines

Oz

Quoted 202 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

 > If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

   amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying.  I would like to dig a little bit futher into that though.  What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 175 lines

Thank you,

Oz

Quoted 167 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 136 lines · Mario Limonciello
Quoted 135 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 115 lines

   Oz

Quoted 111 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 53 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++ ++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

author
#18 lore raw

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

  amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

  amdgpu 0000:03:00.0: Fatal error during GPU init
  amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

Oz

Quoted 223 lines · Mario Limonciello
Quoted 8 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 208 lines

Oz

Quoted 204 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

 > If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

   amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying.  I would like to dig a little bit futher into that though.  What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 177 lines

Thank you,

Oz

Quoted 169 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 138 lines · Mario Limonciello
Quoted 137 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 117 lines

   Oz

Quoted 113 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 55 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23
+++++++++++++++ ++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size,
GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev,
fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#19 lore raw
Quoted 18 lines · Oz Tiram

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

  amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

  amdgpu 0000:03:00.0: Fatal error during GPU init
  amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Quoted 8 lines

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

OK, in that case I will clean up and post the patches shortly. You'll be able to use them for a workaround if everyone else is aligned. The part I'm worried about with these is how they would interplay with a system with multiple of the same GPU. But I don't believe we would be fetching VBIOS from VFCT in that case most likely? Not sure.

We really shouldn't have to set pci=realloc,assign-busses on a design with all internal PCIe devices. We should adjust resource allocation code for this case.

So please start another another thread with the linux-pci mailing list on this issue, include a full dmesg showing what happens when you don't add the parameters and then what happens when you do (feel free to include/reference this patch in that thread too).

If you want to use one, this is the kind of thing an LLM with access to a kernel checkout and both those dmesgs might be good at helping to propose a draft for a solution to the resource allocation code too.

You can CC me on that linux-pci mailing list submission, and we'll see if we can come up with a better solution for you.

Quoted 228 lines

Oz

Quoted 223 lines · Mario Limonciello
Quoted 8 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 208 lines

Oz

Quoted 204 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

 > If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

   amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying.  I would like to dig a little bit futher into that though.  What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 177 lines

Thank you,

Oz

Quoted 169 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign- busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 138 lines · Mario Limonciello
Quoted 137 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 117 lines

   Oz

Quoted 113 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 55 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++ ++ ++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size,
GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev,
fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

#20 lore raw
Quoted 31 lines · Mario Limonciello
Quoted 18 lines · Oz Tiram

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11,

       matching by device identity (vendor 0x1002 device 0x1900)

amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

amdgpu 0000:03:00.0: Fatal error during GPU init
amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Quoted 8 lines

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

Quoted 5 lines

OK, in that case I will clean up and post the patches shortly. You'll be able to use them for a workaround if everyone else is aligned. The part I'm worried about with these is how they would interplay with a system with multiple of the same GPU. But I don't believe we would be fetching VBIOS from VFCT in that case most likely? Not sure.

It's allowed by the spec. A number of apple systems use VFCT for multu-GPU systems with the same GPU.

Alex

Quoted 300 lines

We really shouldn't have to set pci=realloc,assign-busses on a design with all internal PCIe devices. We should adjust resource allocation code for this case.

So please start another another thread with the linux-pci mailing list on this issue, include a full dmesg showing what happens when you don't add the parameters and then what happens when you do (feel free to include/reference this patch in that thread too).

If you want to use one, this is the kind of thing an LLM with access to a kernel checkout and both those dmesgs might be good at helping to propose a draft for a solution to the resource allocation code too.

You can CC me on that linux-pci mailing list submission, and we'll see if we can come up with a better solution for you.

Quoted 282 lines

Oz

Quoted 277 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 261 lines

Oz

Quoted 257 lines · Mario Limonciello
Quoted 12 lines · Oz Tiram

Hi Mario,

Quoted 1 line

If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 7 lines

amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns
the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying. I would like to dig a little bit futher into that though. What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 221 lines

Thank you,

Oz

Quoted 213 lines · Mario Limonciello

Hi Oz,

Quoted 24 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the
runtime bus is 11 (0x0B). Your patch fires exactly as expected:

amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table
106 ! = runtime 11,

       matching by device identity (vendor 0x1002 device 0x1900)

amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather
than \n. The resulting kernel message has a literal "\n" at the end. Same issue
exists in the nearby "too short #2" dev_info -- not introduced by your patch, but
might be worth cleaning up.

Quoted 2 lines

Thanks for confirming. Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign- busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 173 lines · Mario Limonciello
Quoted 172 lines · Oz Tiram
Quoted 8 lines

Hi Mario,

To make sure I understand correctly: are you suggesting that
the bus
number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime,
causing the
mismatch?

That's what it sounds like right now. You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 4 lines

I'm not familiar enough with the PCI subsystem to know the
right way to
implement that — could you point me in the right direction?

Well there's a variety of ways to do it. But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 146 lines

Oz

Quoted 142 lines · Mario Limonciello
Quoted 26 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts four paths
before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail. The specific case motivating this patch
is a hybrid graphics machine (dGPU + APU) where:

- The VFCT table contains the iGPU entry but with a stale
PCIBus value
from BIOS POST time (0x6A). When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are
reassigned dynamically

     and the iGPU lands on bus 0x0B at runtime.

amdgpu_acpi_vfct_bios()
matches entries by bus number, so the entry is never found.
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it).
- No platform BIOS mapping exists.

Quoted 5 lines

The UEFI GOP driver initialises the iGPU successfully for early display,
confirming the hardware is functional. The VBIOS image data embedded in
the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 25 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68))
count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header
and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength
field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to
bind, leaving the APU completely unusable under Linux.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware(). This allows a VBIOS image extracted as above to be
placed in /lib/firmware/ and makes the binding succeed without patching
ACPI tables or BIOS.

Quoted 4 lines

The fallback is only reached if all existing paths have already failed,
so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 62 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but
with a stale PCIBus from BIOS POST that mismatches the
runtime bus
number assigned by pci=realloc,assign-busses. Explain
that the VBIOS
image data is valid and document the dd extraction
command and byte
offsets. Note that the UEFI GOP driver initialises the
iGPU
successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++
++ ++ ++ ++++
  1 file changed, 23 insertions(+)
(quoted diff) renamed from drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0

drivers/ gpu/ drm/amd/amdgpu/amdgpu_bios.c
index aa039e148a5e..86064c753b09 100644

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
@@ -26,6 +26,7 @@
   *          Jerome Glisse
   */
  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct

amdgpu_device *adev)

          goto success;
      }

+ {

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +5 -0
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/

%04x_%04x.bin",

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +3 -0
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size,

GFP_KERNEL);

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +3 -0
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev,

fw_size)) {

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +4 -0
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from

firmware file %s\n",

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +6 -0
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;
#21 lore raw
Quoted 33 lines · Alex Deucher
Quoted 31 lines · Mario Limonciello
Quoted 26 lines · Oz Tiram

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

    amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11,
        matching by device identity (vendor 0x1002 device 0x1900)
    amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

amdgpu 0000:03:00.0: Fatal error during GPU init
amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

Quoted 8 lines
Quoted 5 lines

OK, in that case I will clean up and post the patches shortly. You'll be able to use them for a workaround if everyone else is aligned. The part I'm worried about with these is how they would interplay with a system with multiple of the same GPU. But I don't believe we would be fetching VBIOS from VFCT in that case most likely? Not sure.

It's allowed by the spec. A number of apple systems use VFCT for multu-GPU systems with the same GPU.

But then what happens with the bus numbers? They all need to be on the same bus?

Quoted 303 lines

Alex

Quoted 300 lines

We really shouldn't have to set pci=realloc,assign-busses on a design with all internal PCIe devices. We should adjust resource allocation code for this case.

So please start another another thread with the linux-pci mailing list on this issue, include a full dmesg showing what happens when you don't add the parameters and then what happens when you do (feel free to include/reference this patch in that thread too).

If you want to use one, this is the kind of thing an LLM with access to a kernel checkout and both those dmesgs might be good at helping to propose a draft for a solution to the resource allocation code too.

You can CC me on that linux-pci mailing list submission, and we'll see if we can come up with a better solution for you.

Quoted 282 lines

Oz

Quoted 277 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 261 lines

Oz

Quoted 257 lines · Mario Limonciello
Quoted 12 lines · Oz Tiram

Hi Mario,

Quoted 1 line

If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 7 lines

amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns
the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying. I would like to dig a little bit futher into that though. What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 221 lines

Thank you,

Oz

Quoted 213 lines · Mario Limonciello

Hi Oz,

Quoted 24 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the
runtime bus is 11 (0x0B). Your patch fires exactly as expected:

amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table
106 ! = runtime 11,
matching by device identity (vendor 0x1002 device 0x1900)
amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather
than \n. The resulting kernel message has a literal "\n" at the end. Same issue
exists in the nearby "too short #2" dev_info -- not introduced by your patch, but
might be worth cleaning up.

Quoted 2 lines

Thanks for confirming. Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign- busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 173 lines · Mario Limonciello
Quoted 172 lines · Oz Tiram
Quoted 8 lines

Hi Mario,

To make sure I understand correctly: are you suggesting that
the bus
number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime,
causing the
mismatch?

That's what it sounds like right now. You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 4 lines

I'm not familiar enough with the PCI subsystem to know the
right way to
implement that — could you point me in the right direction?

Well there's a variety of ways to do it. But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 146 lines

Oz

Quoted 142 lines · Mario Limonciello
Quoted 31 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no
dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts
four paths
before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail. The specific case motivating
this patch
is a hybrid graphics machine (dGPU + APU) where:

- The VFCT table contains the iGPU entry but with a stale
PCIBus value
from BIOS POST time (0x6A). When the kernel boots with
pci=realloc,assign-busses, PCI bus numbers are
reassigned dynamically
and the iGPU lands on bus 0x0B at runtime.
amdgpu_acpi_vfct_bios()
matches entries by bus number, so the entry is never found.
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it).
- No platform BIOS mapping exists.

The UEFI GOP driver initialises the iGPU successfully for
early display,
confirming the hardware is functional. The VBIOS image data
embedded in
the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 29 lines

The firmware
file can be extracted directly from the VFCT using dd:

dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68))
count=16896 \
of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI
table header
and VFCT_IMAGE_HEADER; the image length 16896 comes from the
ImageLength
field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and
refuses to
bind, leaving the APU completely unusable under Linux.

Add a fifth fallback: request a firmware file named
"amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via
request_firmware(). This allows a VBIOS image extracted as
above to be
placed in /lib/firmware/ and makes the binding succeed
without patching
ACPI tables or BIOS.

The fallback is only reached if all existing paths have
already failed,
so there is no regression risk for boards where VFCT or ROM
BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 62 lines

Signed-off-by: Oz Tiram <[email protected]>
---
v2: Fix commit message: clarify that VFCT contains the iGPU
entry but
with a stale PCIBus from BIOS POST that mismatches the
runtime bus
number assigned by pci=realloc,assign-busses. Explain
that the VBIOS
image data is valid and document the dd extraction
command and byte
offsets. Note that the UEFI GOP driver initialises the
iGPU
successfully, confirming the hardware is functional.

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++
++ ++ ++ ++++
1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/
drivers/ gpu/ drm/amd/amdgpu/amdgpu_bios.c
index aa039e148a5e..86064c753b09 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -26,6 +26,7 @@
* Jerome Glisse
*/
+#include <linux/firmware.h>
#include "amdgpu.h"
#include "atom.h"
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct
amdgpu_device *adev)
goto success;
}
+ {
+ const struct firmware *fw;
+ char fw_name[32];
+ size_t fw_size;
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+ adev->pdev->vendor, adev->pdev->device);
+ if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+ adev->bios = kmemdup(fw->data, fw->size,
GFP_KERNEL);
+ fw_size = fw->size;
+ release_firmware(fw);
+ if (!adev->bios || !check_atom_bios(adev,
fw_size)) {
+ amdgpu_bios_release(adev);
+ } else {
+ adev->bios_size = fw_size;
+ dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+ fw_name);
+ goto success;
+ }
+ }
+ }
+
dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
return false;

#22 lore raw
Quoted 43 lines · Mario Limonciello
Quoted 39 lines · Alex Deucher
Quoted 36 lines · Mario Limonciello
Quoted 18 lines · Oz Tiram

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

    amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11,
        matching by device identity (vendor 0x1002 device 0x1900)
    amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

amdgpu 0000:03:00.0: Fatal error during GPU init
amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Quoted 8 lines

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

OK, in that case I will clean up and post the patches shortly. You'll be able to use them for a workaround if everyone else is aligned. The part I'm worried about with these is how they would interplay with a system with multiple of the same GPU. But I don't believe we would be fetching VBIOS from VFCT in that case most likely? Not sure.

Quoted 5 lines
Quoted 2 lines

It's allowed by the spec. A number of apple systems use VFCT for multu-GPU systems with the same GPU.

But then what happens with the bus numbers? They all need to be on the same bus?

I'm not sure. As far as I know, the VFCT is populated by the sbios based on the locations at boot time. We can ask the vbios team for more details.

Alex

Quoted 305 lines
Quoted 304 lines

Alex

Quoted 300 lines

We really shouldn't have to set pci=realloc,assign-busses on a design with all internal PCIe devices. We should adjust resource allocation code for this case.

So please start another another thread with the linux-pci mailing list on this issue, include a full dmesg showing what happens when you don't add the parameters and then what happens when you do (feel free to include/reference this patch in that thread too).

If you want to use one, this is the kind of thing an LLM with access to a kernel checkout and both those dmesgs might be good at helping to propose a draft for a solution to the resource allocation code too.

You can CC me on that linux-pci mailing list submission, and we'll see if we can come up with a better solution for you.

Quoted 282 lines

Oz

Quoted 277 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 261 lines

Oz

Quoted 257 lines · Mario Limonciello
Quoted 12 lines · Oz Tiram

Hi Mario,

Quoted 1 line

If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 7 lines

amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns
the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying. I would like to dig a little bit futher into that though. What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 221 lines

Thank you,

Oz

Quoted 213 lines · Mario Limonciello

Hi Oz,

Quoted 24 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the
runtime bus is 11 (0x0B). Your patch fires exactly as expected:

amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table
106 ! = runtime 11,
matching by device identity (vendor 0x1002 device 0x1900)
amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather
than \n. The resulting kernel message has a literal "\n" at the end. Same issue
exists in the nearby "too short #2" dev_info -- not introduced by your patch, but
might be worth cleaning up.

Quoted 2 lines

Thanks for confirming. Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign- busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 173 lines · Mario Limonciello
Quoted 172 lines · Oz Tiram
Quoted 8 lines

Hi Mario,

To make sure I understand correctly: are you suggesting that
the bus
number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime,
causing the
mismatch?

That's what it sounds like right now. You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 4 lines

I'm not familiar enough with the PCI subsystem to know the
right way to
implement that — could you point me in the right direction?

Well there's a variety of ways to do it. But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 146 lines

Oz

Quoted 142 lines · Mario Limonciello

On 7/5/26 05:04, Oz Tiram wrote:
APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no
dedicated VBIOS ROM chip. amdgpu_get_bios_apu() attempts
four paths
before giving up:

1. ACPI VFCT table
2. VRAM BAR read
3. ROM BAR read
4. platform BIOS

On some systems all four fail. The specific case motivating
this patch
is a hybrid graphics machine (dGPU + APU) where:

- The VFCT table contains the iGPU entry but with a stale
PCIBus value
from BIOS POST time (0x6A). When the kernel boots with
pci=realloc,assign-busses, PCI bus numbers are
reassigned dynamically
and the iGPU lands on bus 0x0B at runtime.
amdgpu_acpi_vfct_bios()
matches entries by bus number, so the entry is never found.
- The VRAM BAR is unmapped at probe time.
- The ROM BAR is zero (PCI firmware did not assign it).
- No platform BIOS mapping exists.

The UEFI GOP driver initialises the iGPU successfully for
early display,
confirming the hardware is functional. The VBIOS image data
embedded in
the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's
just when the kernel is booted to reassign busses there is a
problem?

In that case; why not detect the kernel was booted this way
and keep track of the original bus number when reassigned to
avoid the issue?

The firmware
file can be extracted directly from the VFCT using dd:

dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68))
count=16896 \
of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI
table header
and VFCT_IMAGE_HEADER; the image length 16896 comes from the
ImageLength
field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and
refuses to
bind, leaving the APU completely unusable under Linux.

Add a fifth fallback: request a firmware file named
"amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via
request_firmware(). This allows a VBIOS image extracted as
above to be
placed in /lib/firmware/ and makes the binding succeed
without patching
ACPI tables or BIOS.

The fallback is only reached if all existing paths have
already failed,
so there is no regression risk for boards where VFCT or ROM
BAR work.

What happens if the VBIOS changes in another way one boot to
another? You might have some other stateful information that
isn't updated.

The whole thing to me feels like a hack for a behavior we can
control in the kernel when doing reassignments.

Signed-off-by: Oz Tiram <[email protected]>
---
v2: Fix commit message: clarify that VFCT contains the iGPU
entry but
with a stale PCIBus from BIOS POST that mismatches the
runtime bus
number assigned by pci=realloc,assign-busses. Explain
that the VBIOS
image data is valid and document the dd extraction
command and byte
offsets. Note that the UEFI GOP driver initialises the
iGPU
successfully, confirming the hardware is functional.

drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++
++ ++ ++ ++++
1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/
drivers/ gpu/ drm/amd/amdgpu/amdgpu_bios.c
index aa039e148a5e..86064c753b09 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -26,6 +26,7 @@
* Jerome Glisse
*/
+#include <linux/firmware.h>
#include "amdgpu.h"
#include "atom.h"
@@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct
amdgpu_device *adev)
goto success;
}
+ {
+ const struct firmware *fw;
+ char fw_name[32];
+ size_t fw_size;
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+ adev->pdev->vendor, adev->pdev->device);
+ if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+ adev->bios = kmemdup(fw->data, fw->size,
GFP_KERNEL);
+ fw_size = fw->size;
+ release_firmware(fw);
+ if (!adev->bios || !check_atom_bios(adev,
fw_size)) {
+ amdgpu_bios_release(adev);
+ } else {
+ adev->bios_size = fw_size;
+ dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+ fw_name);
+ goto success;
+ }
+ }
+ }
+
dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
return false;

author
#23 lore raw
In reply to Mario Limonciello

Hi Mario,

Tested on 7.2-rc2 with your patch applied. The mismatch condition is unchanged from 6.18.35:

  amdgpu 0000:0b:00.0: VFCT bus number mismatch: table 106 != runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: Fetched VBIOS from VFCT

Both GPUs initialise fully with your patch.

I also tested 7.2-rc2 without pci=realloc,assign-busses to check whether the pci/realloc changes fixed the dGPU probe failure. They did not -- the dGPU still fails on 7.2-rc2:

  amdgpu 0000:03:00.0: Fatal error during GPU init
  amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

Without the kernel argument the iGPU sits at its POST bus (0x6A), VFCT matches directly, and it works fine -- but the dGPU is unusable. pci=realloc,assign-busses remains necessary for this machine on 7.2-rc2, which means the VFCT mismatch persists and your patch is still needed.

Thank you for not giving up on me so quickly! This is my first time working on such issue. It feels daunting to modify kernel code.

Oz

Quoted 223 lines · Mario Limonciello
Quoted 8 lines · Oz Tiram

Hi Mario,

The GPU is internal. It's an AMD RADEON PRO W7800 48GB. The kernel is built from gentoo-sources-6.18.35.

I will test the latest sys-kernel/vanilla-sources (7.1.3) and let you know.

Best regards,

Thanks. Can you please test 7.2-rc2?

I'll clean up the workaround and propose it for review in parallel.

Quoted 208 lines

Oz

Quoted 204 lines · Mario Limonciello
Quoted 9 lines · Oz Tiram

Hi Mario,

 > If you drop that - does this notice still come up?

No, the notice does not appear without pci=realloc,assign-busses. The iGPU  stays at its POST bus (0x6A = 106), VFCT matches directly, and it fetches the VBIOS without any mismatch.

However, dropping the kernel argument is not an option on this machine:
without it the discrete GPU (0x7449) fails to probe entirely:

Quoted 6 lines

   amdgpu 0000:03:00.0: amdgpu: Fatal error during GPU init amdgpu 0000:03:00.0: probe with driver amdgpu failed with error -12

The firmware BARs cannot be mapped without resource reallocation, so pci=realloc,assign-busses is required for the dGPU, which in turn reassigns the iGPU to bus 0x0B and triggers the mismatch your patch resolves.

Got it; thanks for clarifying.  I would like to dig a little bit futher into that though.  What kernel are you finding this behavior and can it still reproduce with 7.2-rc2 if it's older? There was a bunch of pci/realloc changes that happened in the last cycle that might have helped this.

Also; is it an eGPU (external) or dGPU (internal)?

If it's an dGPU IMO this is arguably a BIOS issue that not enough resources were applied in the first place.

Thanks,

Quoted 177 lines

Thank you,

Oz

Quoted 169 lines · Mario Limonciello

Hi Oz,

Quoted 11 lines · Oz Tiram

Hi Mario,

Tested on a Morefine MNAS X1 AI Workstation (AMD Ryzen 7 Pro 8845HS / Radeon 780M iGPU) with pci=realloc,assign-busses.

The VFCT entry for the iGPU has PCIBus=106 (0x6A, recorded at POST) while the runtime bus is 11 (0x0B). Your patch fires exactly as expected:

   amdgpu 0000:0b:00.0: amdgpu: VFCT bus number mismatch: table 106 ! = runtime 11, matching by device identity (vendor 0x1002 device 0x1900) amdgpu 0000:0b:00.0: amdgpu: Fetched VBIOS from VFCT

Quoted 9 lines

The iGPU initialises fully and drives the framebuffer.

One minor nit: the dev_notice format string ends with \\n (two characters) rather than \n. The resulting kernel message has a literal "\n" at the end. Same issue exists in the nearby "too short #2" dev_info -- not introduced by your patch, but might be worth cleaning up.

Thanks for confirming.  Before I split up this patch and post it in smaller logical pieces can you confirm my proposed root cause is right that this issue happens because "pci=realloc,assign-busses" was on your kernel command line?

If you drop that - does this notice still come up?

Thanks,

Quoted 138 lines · Mario Limonciello
Quoted 137 lines · Oz Tiram
Quoted 6 lines

Hi Mario,

   To make sure I understand correctly: are you suggesting that the bus number in the VFCT was legitimate at BIOS POST time, and that pci=realloc,assign-busses is what changes it at runtime, causing the mismatch?

That's what it sounds like right now.  You can easily drop all the superfluous kernel command line optiosn and see.

Quoted 3 lines

   I'm not familiar enough with the PCI subsystem to know the right way to implement that — could you point me in the right direction?

Well there's a variety of ways to do it.  But how about we start here - if we make that specific busnr match optional and instead make a VID/DID match.

See if the attached patch helps.

Quoted 117 lines

   Oz

Quoted 113 lines · Mario Limonciello
Quoted 21 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail.  The specific case motivating this patch is a hybrid graphics machine (dGPU + APU) where:

   - The VFCT table contains the iGPU entry but with a stale PCIBus value from BIOS POST time (0x6A).  When the kernel boots with pci=realloc,assign-busses, PCI bus numbers are reassigned dynamically and the iGPU lands on bus 0x0B at runtime. amdgpu_acpi_vfct_bios() matches entries by bus number, so the entry is never found.
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it).
   - No platform BIOS mapping exists.

Quoted 3 lines

The UEFI GOP driver initialises the iGPU successfully for early display, confirming the hardware is functional.  The VBIOS image data embedded in the VFCT is also valid; only the PCIBus metadata is wrong.

So the BIOS on this machine is actually totally fine; it's just when the kernel is booted to reassign busses there is a problem?

In that case; why not detect the kernel was booted this way and keep track of the original bus number when reassigned to avoid the issue?

Quoted 13 lines

The firmware
file can be extracted directly from the VFCT using dd:

   dd if=/sys/firmware/acpi/tables/VFCT bs=1 skip=$((0x68)) count=16896 \
      of=/lib/firmware/amdgpu/1002_1900.bin

(0x68 is the byte offset of the VBIOS image after the ACPI table header and VFCT_IMAGE_HEADER; the image length 16896 comes from the ImageLength field in VFCT_IMAGE_HEADER.)

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux.

Quoted 8 lines

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted as above to be placed in /lib/firmware/ and makes the binding succeed without patching ACPI tables or BIOS.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

What happens if the VBIOS changes in another way one boot to another? You might have some other stateful information that isn't updated.

The whole thing to me feels like a hack for a behavior we can control in the kernel when doing reassignments.

Quoted 55 lines

---
v2: Fix commit message: clarify that VFCT contains the iGPU entry but with a stale PCIBus from BIOS POST that mismatches the runtime bus number assigned by pci=realloc,assign-busses. Explain that the VBIOS image data is valid and document the dd extraction command and byte offsets.  Note that the UEFI GOP driver initialises the iGPU successfully, confirming the hardware is functional.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23
+++++++++++++++ ++ ++ ++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/
%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size,
GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev,
fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from
firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;

author
#24 lore raw
In reply to Mario Limonciello

Hi Mario,

Sorry for the slow response, I'm new to the kernel contribution process. Thanks for the review. v2 addresses your questions: -

The VFCT does contain the iGPU entry, but with a stale PCIBus value from BIOS POST time (0x6A). With pci=realloc,assign-busses the iGPU lands on bus 0x0B at runtime, so amdgpu_acpi_vfct_bios() never matches it

This is clarified in the commit message along with a note that the UEFI GOP driver initializes the iGPU successfully, confirming the hardware is functional.

The VBIOS image data in the VFCT is valid — only the PCIBus metadata is wrong.

The firmware file was extracted directly from the VFCT with dd, skipping past the ACPI header and VFCT_IMAGE_HEADER. The commit message now documents the exact command and byte offsets.

The patch follows.

Oz

Quoted 92 lines · Mario Limonciello
Quoted 10 lines · Oz Tiram

APUs (e.g. AMD Radeon 780M / HawkPoint, PCI 1002:1900) have no dedicated VBIOS ROM chip.  amdgpu_get_bios_apu() attempts four paths before giving up:

   1. ACPI VFCT table
   2. VRAM BAR read
   3. ROM BAR read
   4. platform BIOS

On some systems all four fail:

That's pretty odd to me.  Isn't this a BIOS bug?  Can you share more about why all of these are failing?

Does the UEFI GOP driver work?

Quoted 8 lines

   - The VFCT table is absent or contains only the discrete GPU entry (e.g. when a custom ACPI override is present for the dGPU only).
   - The VRAM BAR is unmapped at probe time.
   - The ROM BAR is zero (PCI firmware did not assign it; observed even with pci=realloc,assign-busses).
   - No platform BIOS mapping exists.

Quoted 8 lines

The driver then prints "Unable to locate a BIOS ROM" and refuses to bind, leaving the APU completely unusable under Linux even though the hardware is functional.

Add a fifth fallback: request a firmware file named "amdgpu/<vendor>_<device>.bin" (e.g. "amdgpu/1002_1900.bin") via request_firmware().  This allows a VBIOS image extracted from the running hardware

I thought you just said this didn't work.  How did you extract it?

Quoted 54 lines

to be shipped as a firmware blob in /lib/firmware/ and makes the binding succeed without any change to the ACPI tables.

The fallback is only reached if all existing paths have already failed, so there is no regression risk for boards where VFCT or ROM BAR work.

---
v2: Validate the fetched firmware with check_atom_bios() before accepting it, consistent with all other VBIOS discovery paths. Save fw->size before release_firmware() so it remains valid for the size check. Release the buffer via amdgpu_bios_release() if validation fails.

  drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 23 +++++++++++++++++++++++

  1 file changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +0 -0
index aa039e148a5e..86064c753b09 100644
@@ -26,6 +26,7 @@
    *          Jerome Glisse
    */

  +#include <linux/firmware.h>
  #include "amdgpu.h"
  #include "atom.h"
  @@ -457,6 +458,28 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) goto success;
      }
  +    {
+        const struct firmware *fw;
+        char fw_name[32];
+        size_t fw_size;
+
+        snprintf(fw_name, sizeof(fw_name), "amdgpu/%04x_%04x.bin",
+             adev->pdev->vendor, adev->pdev->device);
+        if (request_firmware(&fw, fw_name, adev->dev) == 0) {
+            adev->bios = kmemdup(fw->data, fw->size, GFP_KERNEL);
+            fw_size = fw->size;
+            release_firmware(fw);
+            if (!adev->bios || !check_atom_bios(adev, fw_size)) {
+                amdgpu_bios_release(adev);
+            } else {
+                adev->bios_size = fw_size;
+                dev_info(adev->dev, "Fetched VBIOS from firmware file %s\n",
+                     fw_name);
+                goto success;
+            }
+        }
+    }
+
      dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
      return false;