diff options
-rw-r--r-- | nvbiosemu.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/nvbiosemu.c b/nvbiosemu.c index cbcc727..4ca4148 100644 --- a/nvbiosemu.c +++ b/nvbiosemu.c @@ -25,6 +25,7 @@ static uint32_t *PMC; static uint32_t *PRAMIN; static uint8_t *PROM; +static uint32_t *PNV50; static void *map_dev_mem (int fd, unsigned long Base, unsigned long Size) { @@ -98,16 +99,42 @@ static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, uint8_t *data) PMC[0x1850 / 4] = 0x1; } -static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data) +static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, uint32_t *data) +{ + const uint32_t *pramin = PRAMIN; + int arch = PMC[0] >> 20 & 0x1ff; + uint32_t old_bar0_pramin = 0; + + printf("Attempting to locate BIOS image in PRAMIN"); + + if (arch > 0x50) { + uint32_t vbios_vram; + + vbios_vram = (PNV50[0x9f04/4] & ~0xff) << 8; + if (!vbios_vram) { + vbios_vram = PMC[0x1700/4] << 16; + vbios_vram += 0xf0000; + } + + old_bar0_pramin = PMC[0x1700/4]; + PMC[0x1700/4] = vbios_vram >> 16; + } + + memcpy(data, pramin, NV_PROM_SIZE); + + if (arch > 0x50) + PMC[0x1700/4] = old_bar0_pramin; +} + +static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint32_t *data) { NVShadowVBIOS_PROM(pScrn, (uint8_t *)data); if (NVValidVBIOS(pScrn, (uint8_t *)data)) return TRUE; -/* NVShadowVBIOS_PRAMIN(pScrn, data); + NVShadowVBIOS_PRAMIN(pScrn, data); if (NVValidVBIOS(pScrn, (uint8_t *)data)) return TRUE; -*/ return FALSE; } @@ -149,11 +176,12 @@ int reload_nv_bios(uintptr_t pcimemaddr) printf("Using card memory region at 0x%x\n", pcimemaddr); - PMC = map_dev_mem(fd, pcimemaddr + 0x000000, NV_PROM_SIZE); + PMC = map_dev_mem(fd, pcimemaddr + 0x000000, 0xffff); PRAMIN = map_dev_mem(fd, pcimemaddr + 0x700000, NV_PROM_SIZE); PROM = map_dev_mem(fd, pcimemaddr + 0x300000, NV_PROM_SIZE); + PNV50 = map_dev_mem(fd, pcimemaddr + 0x610000, 0xffff); - if (NVShadowVBIOS(NULL, bios)) { + if (NVShadowVBIOS(NULL, (uint32_t *)bios)) { if (fake_bios(fd, bios)) return 1; } else @@ -164,6 +192,7 @@ int reload_nv_bios(uintptr_t pcimemaddr) unmap_dev_mem((unsigned long)PMC, NV_PROM_SIZE); unmap_dev_mem((unsigned long)PRAMIN, NV_PROM_SIZE); unmap_dev_mem((unsigned long)PROM, NV_PROM_SIZE); + unmap_dev_mem((unsigned long)PNV50, 0xffff); return 0; } |