Author: kallisti5 Date: 2011-08-04 17:28:50 +0200 (Thu, 04 Aug 2011) New Revision: 42573 Changeset: https://dev.haiku-os.org/changeset/42573 Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp Log: * 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 Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp 2011-08-04 14:57:34 UTC (rev 42572) +++ haiku/trunk/src/add-ons/kernel/drivers/graphics/radeon_hd/radeon_hd.cpp 2011-08-04 15:28:50 UTC (rev 42573) @@ -66,15 +66,26 @@ 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); 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 @@ (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 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 { - dprintf(DEVICE_NAME ": %s: AtomBIOS not mapped!\n", - __func__); - result = B_ERROR; + 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 @@ 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 @@ = 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 - } + + // 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); } - 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); + // TODO : may want to just return B_ERROR if AtomBIOS isn't + // found as we will require it in the future - 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); - } - } 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