summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2009-06-16 10:28:00 +1000
committerBen Skeggs <bskeggs@redhat.com>2009-06-16 13:53:46 +1000
commite66867e4cf9f0bc8a1971664ccc3d5c56b08b2fb (patch)
tree51a814c47d930e9ea36726f6b6f6b42de660a54d
parent42c5730a4f6c243b75fbd40f1dc26e8433191c7b (diff)
bios: use image from PRAMIN in preference to PROM on NV50
There's at least one known case (rh#492658) where the DCB table present in the VBIOS image from PROM is not suitable for use. It contained all 16 entries filled, each entry valid in itself, but contradicting other entries. The VBIOS image in PRAMIN however, still has all 16 entries filled, but the first few entries now match what is present on the hardware, and the rest are set as type 0xf, which we ignore.
-rw-r--r--src/nv_bios.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/src/nv_bios.c b/src/nv_bios.c
index 865b22d..b307fc6 100644
--- a/src/nv_bios.c
+++ b/src/nv_bios.c
@@ -187,42 +187,62 @@ static void load_vbios_pci(NVPtr pNv, uint8_t *data)
#endif
}
+struct methods {
+ const char desc[8];
+ void (*loadbios)(NVPtr, uint8_t *);
+ const bool rw;
+ int score;
+};
+
+static struct methods nv04_methods[] = {
+ { "PROM", load_vbios_prom, false },
+ { "PRAMIN", load_vbios_pramin, true },
+ { "PCI ROM", load_vbios_pci, true }
+};
+
+static struct methods nv50_methods[] = {
+ { "PRAMIN", load_vbios_pramin, true },
+ { "PROM", load_vbios_prom, false },
+ { "PCI ROM", load_vbios_pci, true }
+};
+
static bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data)
{
NVPtr pNv = NVPTR(pScrn);
- struct methods {
- const char desc[8];
- void (*loadbios)(NVPtr, uint8_t *);
- const bool rw;
- int score;
- } method[] = {
- { "PROM", load_vbios_prom, false },
- { "PRAMIN", load_vbios_pramin, true },
- { "PCI ROM", load_vbios_pci, true }
- };
- int i, testscore = 3;
-
- for (i = 0; i < sizeof(method) / sizeof(struct methods); i++) {
+ struct methods *methods, *method;
+ int testscore = 3;
+
+ if (pNv->Architecture < NV_ARCH_50)
+ methods = nv04_methods;
+ else
+ methods = nv50_methods;
+
+ method = methods;
+ while (method->loadbios) {
NV_TRACE(pScrn, "Attempting to load BIOS image from %s\n",
- method[i].desc);
+ method->desc);
data[0] = data[1] = 0; /* avoid reuse of previous image */
- method[i].loadbios(pNv, data);
- method[i].score = score_vbios(pScrn, data, method[i].rw);
- if (method[i].score == testscore)
+ method->loadbios(pNv, data);
+ method->score = score_vbios(pScrn, data, method->rw);
+ if (method->score == testscore)
return true;
+ method++;
}
- while (--testscore > 0)
- for (i = 0; i < sizeof(method) / sizeof(struct methods); i++)
- if (method[i].score == testscore) {
+ while (--testscore > 0) {
+ method = methods;
+ while (method->loadbios) {
+ if (method->score == testscore) {
NV_TRACE(pScrn, "Using BIOS image from %s\n",
- method[i].desc);
- method[i].loadbios(pNv, data);
+ method->desc);
+ method->loadbios(pNv, data);
return true;
}
+ method++;
+ }
+ }
NV_ERROR(pScrn, "No valid BIOS image found\n");
-
return false;
}