summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Bennett <sb476@cam.ac.uk>2007-11-23 18:23:57 +0000
committerStuart Bennett <sb476@cam.ac.uk>2007-11-23 18:48:29 +0000
commit323be42d5916c70c8430bf456b91fdd4385300e3 (patch)
tree512c4766c06d9f676563654399b0012cb1ae6e28
parent99beb25093d751e8fcecb2851dc29a31fe46784d (diff)
Support PRAMIN bios reading
-rw-r--r--nvbiosemu.c39
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;
}