From 7949c8cbe436b8c054d9b9e9d13dc58bb777253e Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 4 Aug 2011 15:28:50 +0000 Subject: [PATCH] * move create_area for kernel AtomBIOS into radeon_hd_getbios * only create_area if we found a valid AtomBIOS * lock down write access to kernel AtomBIOS area after populating * remove locking on kernel AtomBIOS area as it's not needed git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42573 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/graphics/radeon_hd/radeon_hd.cpp | 110 ++++++++++-------- 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp b/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp index 0999126cf7..fec20e3ec7 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp +++ b/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp @@ -66,8 +66,18 @@ radeon_hd_getbios(radeon_info &info) if (flags & PCI_rom_enable) TRACE("%s: PCI ROM decode enabled successfully\n", __func__); - uint32 rom_base = info.shared_info->rom_phys; - uint32 rom_size = info.shared_info->rom_size; + uint32 rom_base = info.pci->u.h0.rom_base; + uint32 rom_size = info.pci->u.h0.rom_size; + + if (rom_base == 0) { + TRACE("%s: no PCI rom, trying shadow rom\n", __func__); + // ROM has been copied by BIOS + rom_base = 0xC0000; + if (rom_size == 0) { + rom_size = 0x7FFF; + // A guess at maximum shadow bios size + } + } TRACE("%s: seeking rom at 0x%" B_PRIX32 " [size: 0x%" B_PRIX32 "]\n", __func__, rom_base, rom_size); @@ -75,6 +85,7 @@ radeon_hd_getbios(radeon_info &info) uint8* bios; status_t result = B_ERROR; if (rom_base == 0 || rom_size == 0) { + // FAIL: we never found a base to work off of. TRACE("%s: no VGA rom located, disabling AtomBIOS\n", __func__); result = B_ERROR; } else { @@ -83,26 +94,51 @@ radeon_hd_getbios(radeon_info &info) (void **)&bios); if (info.rom_area < B_OK) { + // FAIL : rom area wasn't mapped for access dprintf(DEVICE_NAME ": failed to map rom\n"); result = B_ERROR; } else { if (bios[0] != 0x55 || bios[1] != 0xAA) { + // FAIL : not a PCI rom uint16 id = bios[0] + (bios[1] << 8); TRACE("%s: this isn't a PCI rom (%X)\n", __func__, id); result = B_ERROR; - } else { - memcpy(info.atom_buffer, (void *)bios, rom_size); - if (isAtomBIOS(info.atom_buffer)) { - dprintf(DEVICE_NAME ": %s: AtomBIOS found and mapped!\n", - __func__); - result = B_OK; - } else { - dprintf(DEVICE_NAME ": %s: AtomBIOS not mapped!\n", - __func__); + } else if (isAtomBIOS(bios)) { + info.rom_area = create_area("radeon hd AtomBIOS", + (void **)&info.atom_buffer, B_ANY_KERNEL_ADDRESS, + rom_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + + if (info.rom_area < 0) { + // FAIL : couldn't create kernel AtomBIOS area + dprintf(DEVICE_NAME ": %s: Error creating kernel" + " AtomBIOS area!\n", __func__); result = B_ERROR; + } else { + memset((void*)info.atom_buffer, 0, rom_size); + // Prevent unknown code execution by AtomBIOS parser + memcpy(info.atom_buffer, (void *)bios, rom_size); + // Copy AtomBIOS to kernel area + + if (isAtomBIOS(info.atom_buffer)) { + // SUCCESS : bios copied and verified + dprintf(DEVICE_NAME ": %s: AtomBIOS mapped!\n", + __func__); + set_area_protection(info.rom_area, B_READ_AREA); + // Lock it down + result = B_OK; + } else { + // FAIL : bios didn't copy properly for some reason + dprintf(DEVICE_NAME ": %s: AtomBIOS not mapped!\n", + __func__); + result = B_ERROR; + } } + } else { + dprintf(DEVICE_NAME ": %s: PCI rom found wasn't identified" + " as AtomBIOS!\n", __func__); + result = B_ERROR; } - delete_area(rom_area); + delete_area(rom_area); } } @@ -110,6 +146,11 @@ radeon_hd_getbios(radeon_info &info) rom_config &= ~PCI_rom_enable; set_pci_config(info.pci, PCI_rom_base, 4, rom_config); + if (result == B_OK) { + info.shared_info->rom_phys = rom_base; + info.shared_info->rom_size = rom_size; + } + return result; } @@ -258,43 +299,20 @@ radeon_hd_init(radeon_info &info) = read32(info.registers + R6XX_CONFIG_FB_BASE); // *** AtomBIOS mapping - uint32 rom_base = info.pci->u.h0.rom_base; - uint32 rom_size = info.pci->u.h0.rom_size; - if (rom_base == 0) { - TRACE("%s: no PCI rom, trying shadow rom\n", __func__); - // ROM has been copied by BIOS - rom_base = 0xC0000; - if (rom_size == 0) { - rom_size = 0x7FFF; - // A guess at maximum shadow bios size - } - } - info.shared_info->rom_phys = rom_base; - info.shared_info->rom_size = rom_size; - info.rom_area = create_area("radeon hd AtomBIOS", - (void **)&info.atom_buffer, B_ANY_KERNEL_ADDRESS, - info.shared_info->rom_size, B_FULL_LOCK, - B_READ_AREA | B_WRITE_AREA); - - status_t biosStatus = B_ERROR; - if (info.rom_area < 0) { - dprintf("%s: failed to create kernel AtomBIOS area!\n", __func__); - dprintf(DEVICE_NAME ": card(%ld): couldn't map kernel AtomBIOS area!\n", - info.id); - biosStatus = B_ERROR; - } else { - memset((void*)info.atom_buffer, 0, info.shared_info->rom_size); - // First we try an active bios read - biosStatus = radeon_hd_getbios(info); - if (biosStatus != B_OK) { - // If the active read fails, we do a disabled read - if (info.device_chipset > RADEON_R600) - biosStatus = radeon_hd_getbios_r600(info); - } + // First we try an active bios read + status_t biosStatus = radeon_hd_getbios(info); + if (biosStatus != B_OK) { + // If the active read fails, we do a disabled read + if (info.device_chipset > RADEON_R600) + biosStatus = radeon_hd_getbios_r600(info); } + + // TODO : may want to just return B_ERROR if AtomBIOS isn't + // found as we will require it in the future + info.shared_info->has_rom = (biosStatus == B_OK) ? true : false; - info.shared_info->rom_area = info.rom_area; + info.shared_info->rom_area = (biosStatus == B_OK) ? info.rom_area : -1; // *** Pull active monitor VESA EDID from boot loader edid1_info* edidInfo