Status: ✅ RESOLVED AND PERMANENT. On normal boot amdgpu loads from
initramfs, the internal panel (eDP-1) lights up at 1920×1080 native.
| Item | Value |
|---|---|
| Machine | HP ProBook 445 G7 |
| GPU | AMD Renoir iGPU (1002:1636, subsystem HP 103C:8730), PCI 0000:05:00.0 |
| OS | Ubuntu 26.04, kernel 7.0.0-27-generic |
| Symptom | 100% black screen with amdgpu; amdgpu_get_bios() / display stage failed |
| Root cause | The VBIOS image in the HP flash is a generic template with no eDP object; the real VBIOS (with the panel) only exists in the ROM BAR, populated by the SBIOS during POST |
| Fix | (a) amdgpu recompiled with file-load of VBIOS + HPD underflow fix; (b) vbios.bin = dump of the real ROM BAR; (c) early load via dracut |
| Result | card1 → amdgpu, eDP-1 = 1920×1080/1680×1050/…; no Failed to create link encoder, no wait timed out |
On all tested kernels (6.8, 6.17, 7.0) amdgpu failed to probe with
-22 (EINVAL), leaving the display on simple-framebuffer (simpledrm) — or,
with the patched module probing deeper, in a black screen with no fallback.
amdgpu_get_bios() tries to obtain the VBIOS in this order: ATRM → VFCT →
VRAM BAR → ROM BAR → platform. On this machine, in normal boot state:
- ATRM: no ACPI method → absent.
- VFCT: no VFCT ACPI table in this ACPI.
- VRAM shadow: absent.
- ROM BAR: returned
I/O errorwhen the GPU had not been POSTed. - platform: picked up the copy the SBIOS shadows at
0xC0000— the generic VBIOS.
Even when a VBIOS was obtained, the display (DC) stage failed:
create_links: BIOS object table - number of connectors: 5
... link_id: 21, is_internal_display: 0, hpd_int_gpio_uid id: 0
*ERROR* Failed to create link encoder!
construct_phy failed.
link_factory.c→construct_phy: without HPD in the VBIOS, executeslink->hpd_src = hpd_info.hpd_int_gpio_uid - 1. Withuid = 0(generic VBIOS) →hpd_src = -1(unsigned underflow → huge value).dcn21_link_encoder_create(dcn21_resource.c):if (... || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) return NULL;link_enc_hpd_regs[]has 5 entries; hugehpd_source→NULL→ "Failed to create link encoder" for all links → no CRTC → black screen.
Comparing the VBIOS extracted from the HP firmware with the dump of the ROM BAR
(read with the GPU already POSTed for simpledrm), the images differ in ~351 bytes,
all in the 0xCC00–0xD300 region (LCD_Info @0xCCD8 + Display Object Table @0xD248):
| Region | HP flash (renoir_vbios_113-RENOIR-037.rom) |
Real ROM BAR (vbios_rombar.bin) |
|---|---|---|
LCD_Info @0xCCD8 |
zeroed (no panel timing) | real timing 1920×1080 (0x780×0x438) |
Connector table @0xD250 |
5× 0x15 (MXM) — generic placeholder |
0x14 (eDP, internal panel) + 0x0C (HDMI) + 2× 0x13 (DP), with valid HPD/GPIO |
| Strings | "Renoir Generic VBIOS" | real OEM mapping |
Conclusion: the eDP/panel mapping is not in the flash; it is assembled by the SBIOS during iGPU POST. The correct VBIOS always existed — in the ROM BAR.
Source downloaded from apt pool linux_7.0.0-27.27 and extracted with dpkg-source.
Patch 1 — VBIOS file-load (drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c):
- New
amdgpu_read_bios_from_file()that callsrequest_firmware("amdgpu/vbios.bin")and validates withcheck_atom_bios. - Called first in
amdgpu_get_bios_apu(). MODULE_FIRMWARE("amdgpu/vbios.bin")→ ensuresvbios.binis pulled into initramfs.
Patch 2 — HPD underflow fix (drivers/gpu/drm/amd/display/dc/link/link_factory.c):
/* before */ link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
/* after */ link->hpd_src = hpd_info.hpd_int_gpio_uid ? hpd_info.hpd_int_gpio_uid - 1 : 0;With the real VBIOS this fix is a no-op (VBIOS already provides valid HPD), but it protects against regression.
- Source:
/sys/bus/pci/devices/0000:05:00.0/rom(readable with GPU already POSTed). - 54784 bytes, mod256 checksum = 0 (valid),
113-RENOIR-037,ATOMBIOSBK-AMD VER017.010.000.031. - sha256:
e40fd9a8f8a244d3dbea3c7e9834032740a2c0d71000aa1d81d61989cf95425a - Install to
/lib/firmware/amdgpu/vbios.bin.
Ubuntu 26.04 uses dracut, not mkinitramfs.
/etc/dracut.conf.d/amdgpu.conf→add_drivers+=" amdgpu "update-initramfs -u -k 7.0.0-27-genericembedsamdgpu.ko.zst+vbios.binin the initramfs.
- Symptom:
amdgpu: disagrees about version of symbol module_layout. - Cause: single-module in-tree build (
make drivers/.../amdgpu.ko) withoutvmlinux.ogenerates CRCs from source headers, not the binary kernel. - Fix: EXTMOD build (
make -C $SRC M=drivers/gpu/drm/amd/amdgpu modules) withModule.symversfrom the binary kernel (/lib/modules/.../build/Module.symvers,module_layout=0xb0c84d61) copied into the source tree.
- Symptom:
x86/modules: Invalid relocation target, existing value is nonzero ...(fatal,-ENOEXEC) → module aborts before probe. - Cause: kernel has
CONFIG_DEBUG_INFO_BTF_MODULES=y, which adds 24 bytes tostruct module(fieldsbtf_*) before theexitfield. Our.confighad the option disabled →cleanup_modulelanded at the wrong offset (0x490vs0x4a8). - Fix: rebuild with
KCFLAGS="-DCONFIG_DEBUG_INFO_BTF_MODULES=1"(no need for pahole/vmlinux).cleanup_modulemoved to0x4a8. ✅ - Lesson: when copying
Module.symversfrom the kernel to match CRCs, you must also match every.configoption that changes the layout of an exported struct — otherwise CRC passes but the binary/relocation diverges.
- vermagic
7.0.0-27-generic SMP preempt mod_unload modversions✅ module_layout = 0xb0c84d61(== kernel), 0/1130 divergent symbols ✅firmware: amdgpu/vbios.binpresent ✅- Build env: gcc 15.2.0 (identical to kernel build), Secure Boot OFF,
MODULE_SIG_FORCEoff, lockdown[none]. - Required packages:
flex bison libelf-dev.
Precondition: boot with the GPU already POSTed and the amdgpu module not
driving the display (the broken state qualifies: simpledrm active, or recovery /
nomodeset boot). The ROM BAR is only readable after POST.
sudo apt install dkms patch flex bison libelf-dev linux-headers-$(uname -r)
git clone https://github.com/Jeanmarcus93/hp-probook-445g7-amdgpu-fix.git
cd hp-probook-445g7-amdgpu-fix
sudo bash install.sh
# reboot via the normal GRUB entryinstall.sh runs the four steps in order:
scripts/dump_vbios_rom.sh— auto-detects the AMD GPU on the PCI bus, enables the ROM BAR, dumps the real VBIOS and validates it (0x55AA signature, mod-256 checksum,ATOMBIOSBKmarker, object table v1.4 content).scripts/install_vbios.sh— installs the dump as/lib/firmware/amdgpu/vbios.bin(with backup of any previous file).scripts/build_dkms.sh— downloads the matchinglinux-sourcepackage, extracts onlydrivers/gpu/drm/amd/(the subtree is self-contained:FULL_AMD_PATH=$(src)/..), applies the patches frompatches/, installs the tree in/usr/src/amdgpu-rombar-<version>/and runsdkms add/build/install.scripts/make_amdgpu_permanent.sh— dracut early-load conf (add_drivers+=" amdgpu ") + initramfs regeneration + sanity checks.
Each script can also be run individually; all take optional arguments (PCI BDF, dump path, kernel version) and default to auto-detection.
Optional no-reboot test with auto-recovery: sudo bash scripts/test_amdgpu_real.sh
loads the module manually and, if the panel doesn't light up in 90 s, reboots
back to simpledrm on its own.
The module is packaged as amdgpu-rombar with AUTOINSTALL="yes": every new
kernel installed via apt triggers an automatic rebuild against that kernel's
headers — no apt-mark hold needed, no manual rebuild.
The build is EXTMOD against the headers package of the target kernel, so
modversions CRCs, autoconf (CONFIG_DEBUG_INFO_BTF_MODULES) and the
struct module layout come out right automatically (see
Build notes for why that matters).
Secure Boot: Ubuntu's dkms signs modules automatically with the MOK key in
/var/lib/shim-signed/mok/if one is enrolled. With Secure Boot enabled and no enrolled MOK, the module will not load — enroll one first (sudo update-secureboot-policy --new-key+mokutil --import).
The patches/ directory contains unified diffs against the vanilla
linux_7.0.0-27.27 source:
0001-amdgpu-bios-add-file-load-vbios.patch— VBIOS file-load inamdgpu_bios.c0002-link-factory-fix-hpd-underflow.patch— HPD underflow fix inlink_factory.c0003-amdgpu-trace-fix-out-of-tree-include-path.patch—TRACE_INCLUDE_PATH .inamdgpu_trace.h. Only needed for the out-of-tree/DKMS build (the in-tree relative path../../drivers/gpu/drm/amd/amdgpudoesn't exist when building as an external module). Skip it if you're patching a full kernel tree.
Apply to a full kernel tree with patch -p1, or to the extracted amd/
subtree with patch -p4 (which is what build_dkms.sh does).
The reconstructed tree (vanilla source + these patches) was verified byte-identical to the DKMS tree running on the reference machine.
uname -r
# 7.0.0-27-generic
readlink -f /sys/class/drm/card1/device/driver
# .../bus/pci/drivers/amdgpu
dmesg | grep -iE 'Fetched VBIOS|Display Core|eDP-1'
# amdgpu 0000:05:00.0: Fetched VBIOS from file (amdgpu/vbios.bin)
# [drm] Display Core v3.2.369 initialized on DCN 2.1
# [drm] Using ACPI provided EDID for eDP-1
cat /sys/class/drm/card1-eDP-1/modes | head
# 1920x1080
# 1680x1050
sha256sum /lib/firmware/amdgpu/vbios.bin
# e40fd9a8f8a244d3dbea3c7e9834032740a2c0d71000aa1d81d61989cf95425aThe Fetched VBIOS from file timestamp at ~8.5 s confirms the load happens
on boot (via initramfs/dracut), not via manual modprobe.
If the screen goes black:
-
In GRUB (hold Shift/Esc), choose Advanced options → recovery (
nomodeset):amdgpuwon't probe and simpledrm restores video. -
Remove the DKMS module (the stock module in
/lib/modules/.../kernel/...takes over again):sudo dkms remove amdgpu-rombar/$(uname -r | cut -d- -f1) --all sudo rm -f /etc/dracut.conf.d/amdgpu.conf sudo depmod -a sudo update-initramfs -u -k "$(uname -r)"
-
Reboot.
- GPU: AMD Renoir iGPU, PCI
0000:05:00.0(bus 5, slot 0, func 0) 1002:1636, subsystem HP103C:8730- HP BIOS S79 (password-locked: F10 setup and flashrom inaccessible → flash immutable)
- Generic VBIOS from HP flash:
113-RENOIR-037, sha256fb51268390b6ee18a20a2f5d6840f72844ddc88715dd91f6cce9c686182445a7 - Real VBIOS (ROM BAR): same string, sha256
e40fd9a8f8a244d3dbea3c7e9834032740a2c0d71000aa1d81d61989cf95425a
Este repositório contém a solução completa para o bug de tela preta que afeta o HP ProBook 445 G7 com processador AMD Ryzen 5 4500U (GPU Renoir integrada) no Ubuntu 26.04 / kernel 7.0.0-27.
Problema: A HP armazenou um VBIOS genérico (template sem painel eDP) na
flash do firmware. O VBIOS real — com os timings do painel 1920×1080 e os
conectores eDP/HDMI/DisplayPort corretos — só existe na ROM BAR da GPU e é
preenchido pelo SBIOS durante o POST. O driver amdgpu do kernel carrega o
VBIOS do lugar errado (platform/0xC0000) e recebe o template genérico, causando
um underflow no HPD que derruba o display completamente.
Solução (3 partes):
- Módulo
amdgpupatcheado — dois patches no kernel 7.0.0-27:amdgpu_bios.c: nova função que carrega o VBIOS de/lib/firmware/amdgpu/vbios.binlink_factory.c: corrige underflow dohpd_src(proteção contra regressão)
vbios.binreal — dump da ROM BAR com a GPU já POSTada (contém eDP 0x14, HDMI 0x0C, 2× DP 0x13, LCD_Info 1920×1080)- Carga antecipada via dracut —
add_drivers+=" amdgpu "no initramfs
Instalação (comando único):
git clone https://github.com/Jeanmarcus93/hp-probook-445g7-amdgpu-fix.git
cd hp-probook-445g7-amdgpu-fix
sudo bash install.sh
# reinicie pela entrada normal do GRUBPré-requisito: boot com a GPU já POSTada (recovery, nomodeset ou simpledrm ativo). A ROM BAR só é legível após o POST da iGPU.
Modelo exato testado: HP ProBook 445 G7, BIOS HP S79 (protegida por senha),
AMD Ryzen 5 4500U com Radeon Graphics, PCI 0000:05:00.0, 1002:1636 subsystem 103C:8730.
Rollback: boot via recovery do GRUB (nomodeset), remova o módulo DKMS
(dkms remove amdgpu-rombar/7.0.0 --all), apague o conf do dracut e regenere o initramfs.
⚠️ Nota para outros modelos: Este fix é específico para o HP ProBook 445 G7. O scriptvalidate_vbios.py --require-edpverifica se o dump contém painel eDP/LVDS. Em outros laptops com o mesmo problema (VBIOS genérico na flash), a abordagem é a mesma mas os patches podem precisar de ajustes para kernels diferentes.