With the UEFI Bus Support you can find the framebuffer via the BAR (Base Address Register).
This code works for me in Qemu when the AddressSpaceGranularity is 32 bit.
EFI_ADDRESS_SPACE_DESCRIPTOR *asd = NULL;
Status = SystemTable->BootServices->AllocatePool(EfiBootServicesData, sizeof(EFI_ADDRESS_SPACE_DESCRIPTOR), (VOID**)&asd);
if (EFI_ERROR(Status)) {
Print(L"Failed to allocate memory for the asp: %d\r\n", Status);
return Status;
}
UINT64 count = 0;
UINT8 BAR = 0;
Status = PciIo->GetBarAttributes(PciIo, BAR, NULL, (VOID**)&asd);
if (EFI_ERROR(Status)) {
Print(L"BAR attributes err: %d ", Status);
} else {
if (PciConfig.ClassCode == 3) {
UINT8 *vram = (UINT8*)asd->AddressMin;
UINT64 value = (UINT64)vram[0];
UINT8 data = 0;
for (int i = 0; i < 30000; i++) {
data = vram[i]; // Example usage: reading byte-by-byte from VRAM
if (data == 0) {
vram[i] = 100;
}
if (data == value) {
count++;
} else {
Print(u"%dx %d, ", count, value);
count = 1;
value = data;
}
}
Print(u"%dx %d, ", count, data);
Print(u"\r\n");
}
}
SystemTable->BootServices->FreePool(asd);
With the structure:
typedef struct {
uint8_t QWORD_ASD;
uint16_t Length;
uint8_t ResourceType;
uint8_t GeneralFlags;
uint8_t TypeSpecificFlags;
uint64_t AddressSpaceGranularity;
uint64_t AddressMin;
uint64_t AddressMax;
uint64_t AddressTransOffset;
uint64_t AddressLength;
uint8_t EndTag;
uint8_t Checksum;
} EFI_ADDRESS_SPACE_DESCRIPTOR;
AddressMin is the starting address of the bar. And the ResourceType should be 0. https://uefi.org/specs/UEFI/2.11/14_Protocols_PCI_Bus_Support.html#qword-address-space-descriptor-2
I am currently trying to make this work too but my system is also 64 bit so this doesnt work for me except for Qemu tests.