intel_extreme: find VBT in OpRegion version 2.0 and from 2.1
we check the OpRegion version and use the rvda pointer when available. from 2.1 the pointer is relative. Change-Id: I64d8aea65368aa3c5597f63a2b96b6a430e04315 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5109 Reviewed-by: Jérôme Duval <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -159,86 +159,167 @@ dumprom(void *rom, uint32 size, intel_info &info)
|
|||||||
PROM-programmed timings info when compensation mode is off on your machine.
|
PROM-programmed timings info when compensation mode is off on your machine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// outdated: https://01.org/sites/default/files/documentation/skl_opregion_rev0p5.pdf
|
||||||
|
|
||||||
#define ASLS 0xfc // ASL Storage.
|
#define ASLS 0xfc // ASL Storage.
|
||||||
#define OPREGION_SIGNATURE "IntelGraphicsMem"
|
#define OPREGION_SIGNATURE "IntelGraphicsMem"
|
||||||
|
#define OPREGION_ASLE_OFFSET 0x300
|
||||||
|
#define OPREGION_VBT_OFFSET 0x400
|
||||||
|
#define MBOX_ACPI (1 << 0)
|
||||||
|
#define MBOX_SWSCI (1 << 1)
|
||||||
|
#define MBOX_ASLE (1 << 2)
|
||||||
|
#define MBOX_ASLE_EXT (1 << 3)
|
||||||
|
|
||||||
|
|
||||||
|
struct opregion_header {
|
||||||
|
uint8 signature[16];
|
||||||
|
uint32 size;
|
||||||
|
uint8 reserved;
|
||||||
|
uint8 revision_version;
|
||||||
|
uint8 minor_version;
|
||||||
|
uint8 major_version;
|
||||||
|
uint8 sver[32];
|
||||||
|
uint8 vver[16];
|
||||||
|
uint8 gver[16];
|
||||||
|
uint32 mboxes;
|
||||||
|
uint32 driver_model;
|
||||||
|
uint32 platform_configuration;
|
||||||
|
uint8 gop_version[32];
|
||||||
|
uint8 rsvd[124];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
struct opregion_asle {
|
||||||
|
uint32 ardy;
|
||||||
|
uint32 aslc;
|
||||||
|
uint32 tche;
|
||||||
|
uint32 alsi;
|
||||||
|
uint32 bclp;
|
||||||
|
uint32 pfit;
|
||||||
|
uint32 cblv;
|
||||||
|
uint16 bclm[20];
|
||||||
|
uint32 cpfm;
|
||||||
|
uint32 epfm;
|
||||||
|
uint8 plut[74];
|
||||||
|
uint32 pfmb;
|
||||||
|
uint32 cddv;
|
||||||
|
uint32 pcft;
|
||||||
|
uint32 srot;
|
||||||
|
uint32 iuer;
|
||||||
|
uint64 fdss;
|
||||||
|
uint32 fdsp;
|
||||||
|
uint32 stat;
|
||||||
|
uint64 rvda;
|
||||||
|
uint32 rvds;
|
||||||
|
uint8 rsvd[58];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
get_bios(int* vbtOffset)
|
get_bios(int* vbtOffset)
|
||||||
{
|
{
|
||||||
|
STATIC_ASSERT(sizeof(opregion_header) == 0x100);
|
||||||
|
STATIC_ASSERT(sizeof(opregion_asle) == 0x100);
|
||||||
|
|
||||||
intel_info &info = *gDeviceInfo[0];
|
intel_info &info = *gDeviceInfo[0];
|
||||||
// first try to fetch Intel OpRegion which should be polulated by the BIOS at start
|
// first try to fetch Intel OpRegion which should be populated by the BIOS at start
|
||||||
uint64_t kVBIOSAddress = 0;
|
uint32 kVBIOSSize;
|
||||||
uint32 kVBIOSSize = 8 * 1024;
|
|
||||||
|
|
||||||
// get OpRegion - see Intel ACPI IGD info in acpi_igd_opregion_spec_0.pdf
|
for (uint32 romMethod = 0; romMethod < 2; romMethod++) {
|
||||||
kVBIOSAddress = get_pci_config(info.pci, ASLS, 4);
|
switch(romMethod) {
|
||||||
if (!kVBIOSAddress) {
|
case 0:
|
||||||
TRACE((DEVICE_NAME ": ACPI OpRegion not supported!\n"));
|
{
|
||||||
} else {
|
// get OpRegion - see Intel ACPI IGD info in acpi_igd_opregion_spec_0.pdf
|
||||||
TRACE((DEVICE_NAME ": Graphic OpRegion physical addr: 0x%" B_PRIx64
|
uint64 kVBIOSAddress = get_pci_config(info.pci, ASLS, 4);
|
||||||
"; size: 0x%" B_PRIx32 "\n", kVBIOSAddress, kVBIOSSize));
|
if (kVBIOSAddress == 0) {
|
||||||
vbios.area = map_physical_memory("ASLS mapping", kVBIOSAddress,
|
TRACE((DEVICE_NAME ": ACPI OpRegion not supported!\n"));
|
||||||
kVBIOSSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&vbios.memory);
|
continue;
|
||||||
|
}
|
||||||
if (vbios.area >= 0) {
|
kVBIOSSize = 8 * 1024;
|
||||||
TRACE((DEVICE_NAME ": mapping ASLS: 0x%" B_PRIx64 " -> %p\n",
|
TRACE((DEVICE_NAME ": Graphic OpRegion physical addr: 0x%" B_PRIx64
|
||||||
kVBIOSAddress, vbios.memory));
|
"; size: 0x%" B_PRIx32 "\n", kVBIOSAddress, kVBIOSSize));
|
||||||
// check if we got the ASLS and signature
|
vbios.area = map_physical_memory("ASLS mapping", kVBIOSAddress,
|
||||||
if (memcmp(vbios.memory, OPREGION_SIGNATURE, 16)) {
|
kVBIOSSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&vbios.memory);
|
||||||
TRACE((DEVICE_NAME ": OpRegion signature mismatch\n"));
|
if (vbios.area < 0)
|
||||||
|
continue;
|
||||||
|
TRACE((DEVICE_NAME ": mapping OpRegion: 0x%" B_PRIx64 " -> %p\n",
|
||||||
|
kVBIOSAddress, vbios.memory));
|
||||||
|
// check if we got the OpRegion and signature
|
||||||
|
if (memcmp(vbios.memory, OPREGION_SIGNATURE, 16) != 0) {
|
||||||
|
TRACE((DEVICE_NAME ": OpRegion signature mismatch\n"));
|
||||||
|
delete_area(vbios.area);
|
||||||
|
vbios.area = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
opregion_header* header = (opregion_header*)vbios.memory;
|
||||||
|
opregion_asle* asle = (opregion_asle*)(vbios.memory + OPREGION_ASLE_OFFSET);
|
||||||
|
if (header->major_version < 2 || (header->mboxes & MBOX_ASLE) == 0
|
||||||
|
|| asle->rvda == 0 || asle->rvds == 0) {
|
||||||
|
vbios.memory += OPREGION_VBT_OFFSET;
|
||||||
|
kVBIOSSize -= OPREGION_VBT_OFFSET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint64 rvda = asle->rvda;
|
||||||
|
kVBIOSSize = asle->rvds;
|
||||||
|
if (header->major_version > 3 || header->minor_version >= 1) {
|
||||||
|
rvda += kVBIOSAddress;
|
||||||
|
}
|
||||||
|
TRACE((DEVICE_NAME ": RVDA physical addr: 0x%" B_PRIx64
|
||||||
|
"; size: 0x%" B_PRIx32 "\n", rvda, kVBIOSSize));
|
||||||
delete_area(vbios.area);
|
delete_area(vbios.area);
|
||||||
vbios.area = -1;
|
vbios.area = map_physical_memory("RVDA mapping", rvda,
|
||||||
// force using ISA legacy map as fall-back
|
kVBIOSSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void **)&vbios.memory);
|
||||||
kVBIOSAddress = 0;
|
if (vbios.area < 0)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
uint64 kVBIOSAddress = 0xc0000;
|
||||||
|
kVBIOSSize = 64 * 1024;
|
||||||
|
/* !!!DANGER!!!: mapping of BIOS using legacy location as a fallback,
|
||||||
|
hence, if panel mode will be set using info from VBT this way, it will
|
||||||
|
be taken from primary card's VBIOS */
|
||||||
|
vbios.area = map_physical_memory("VBIOS mapping", kVBIOSAddress,
|
||||||
|
kVBIOSSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void**)&vbios.memory);
|
||||||
|
if (vbios.area < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TRACE((DEVICE_NAME ": mapping VBIOS: 0x%" B_PRIx64 " -> %p\n",
|
||||||
|
kVBIOSAddress, vbios.memory));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// mapping failed: force using ISA legacy map as fall-back
|
|
||||||
kVBIOSAddress = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!kVBIOSAddress) {
|
// dump ROM to file if selected in settings file
|
||||||
kVBIOSAddress = 0xc0000;
|
if (read_settings_dumpRom())
|
||||||
kVBIOSSize = 64 * 1024;
|
dumprom(vbios.memory, kVBIOSSize, info);
|
||||||
/* !!!DANGER!!!: mapping of BIOS using legacy location as a fallback,
|
|
||||||
hence, if panel mode will be set using info from VBT this way, it will
|
|
||||||
be taken from primary card's VBIOS */
|
|
||||||
vbios.area = map_physical_memory("VBIOS mapping", kVBIOSAddress,
|
|
||||||
kVBIOSSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, (void**)&vbios.memory);
|
|
||||||
|
|
||||||
if (vbios.area < 0)
|
// scan BIOS for VBT signature
|
||||||
return false;
|
*vbtOffset = kVBIOSSize;
|
||||||
|
for (uint32 i = 0; i + 4 < kVBIOSSize; i += 4) {
|
||||||
|
if (memcmp(vbios.memory + i, "$VBT", 4) == 0) {
|
||||||
|
*vbtOffset = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TRACE((DEVICE_NAME ": mapping VBIOS: 0x%" B_PRIx64 " -> %p\n",
|
if ((*vbtOffset + (uint32)sizeof(vbt_header)) >= kVBIOSSize) {
|
||||||
kVBIOSAddress, vbios.memory));
|
TRACE((DEVICE_NAME": bad VBT offset : 0x%x\n", *vbtOffset));
|
||||||
}
|
delete_area(vbios.area);
|
||||||
|
|
||||||
// dump ROM to file if selected in settings file
|
|
||||||
if (read_settings_dumpRom())
|
|
||||||
dumprom(vbios.memory, kVBIOSSize, info);
|
|
||||||
|
|
||||||
// scan BIOS for VBT signature
|
|
||||||
*vbtOffset = kVBIOSSize;
|
|
||||||
for (uint32 i = 0; i + 4 < kVBIOSSize; i += 4) {
|
|
||||||
if (memcmp(vbios.memory + i, "$VBT", 4) == 0) {
|
|
||||||
*vbtOffset = i;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + *vbtOffset);
|
||||||
|
if (memcmp(vbt->signature, "$VBT", 4) != 0) {
|
||||||
|
TRACE((DEVICE_NAME": bad VBT signature: %20s\n", vbt->signature));
|
||||||
|
delete_area(vbios.area);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*vbtOffset + (uint32)sizeof(vbt_header)) >= kVBIOSSize) {
|
return false;
|
||||||
TRACE((DEVICE_NAME": bad VBT offset : 0x%x\n", *vbtOffset));
|
|
||||||
delete_area(vbios.area);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + *vbtOffset);
|
|
||||||
if (memcmp(vbt->signature, "$VBT", 4) != 0) {
|
|
||||||
TRACE((DEVICE_NAME": bad VBT signature: %20s\n", vbt->signature));
|
|
||||||
delete_area(vbios.area);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user