summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-09-18 05:37:11 +0200
committerMichael Brown2012-07-09 16:41:22 +0200
commit3befa5cb7d4fd84fa4f339a4743f017d30123a07 (patch)
treedce0c26518332fe5f39059adde9b0d3164742f61
parent[import] Import version 1.20 (diff)
downloadmemtest86-3befa5cb7d4fd84fa4f339a4743f017d30123a07.tar.gz
memtest86-3befa5cb7d4fd84fa4f339a4743f017d30123a07.tar.xz
memtest86-3befa5cb7d4fd84fa4f339a4743f017d30123a07.zip
[import] Import version 1.25
http://www.memtest.org/download/1.25/memtest86+-1.25.tar.gz
-rw-r--r--changelog29
-rw-r--r--controller.c222
-rw-r--r--head.S1
-rw-r--r--init.c52
-rw-r--r--mt86+_loader.asm226
-rw-r--r--mt86+_loader.binbin0 -> 784 bytes
-rwxr-xr-xprecomp.binbin86980 -> 86948 bytes
7 files changed, 419 insertions, 111 deletions
diff --git a/changelog b/changelog
index 8fb6bb4..829b0fa 100644
--- a/changelog
+++ b/changelog
@@ -1,18 +1,11 @@
-- Added advanced support for Intel Grantsdale (i915)
-- Added advanced support for Intel Alderwood (i925)
-- Added advanced support for VIA K8T800 Pro
-- Added support for Prescott core E0
-- Added support for Cyrix III CPU
-- Added support for VIA C3 Samuel2/Ezra/Nehemiah CPU
-- Added detection for VIA CLE266 and PLE133 Chipset
-- Added support for .5 FID for AMD K8
-- Complete rewrite of the Cool 'n Quiet core
-- Fixed a bug with K8 > 2.2 GHz
-- Fixed a bug with test #12 (no kb input check)
-- Removed the KTxxx (K7) advanced detection completely
-- Removed Bit Fade Test from the test batch
- (Can still be run standalone)
-- Fixed a bug with VIA VT82C693A/694X detection
-
-
-
+- Bug Fixes with i915/925X memory ratio
+- Rewrite the buggy E7500/E7501 ECC Polling code (Thanks to Tyan)
+- Added advanced dectection for E7500/E7501
+- Added support for FSB533 LGA775 CPU
+- Added support for DDR2-600 mode on i915/925.
+- Added detection for Xeon DP/MP
+- Added detection for AMD K8 Sempron
+- Added detection for SiS 661
+- Fixed the KT133/266 freeze bug (again)
+- Fixed crash with ATi RS300 & Pentium M
+- Some bugs fixes & code optimization
diff --git a/controller.c b/controller.c
index 923a9e5..67278f9 100644
--- a/controller.c
+++ b/controller.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V1.15 Specific code (GPL V2.0)
+ * MemTest86+ V1.25 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -69,6 +69,44 @@ static struct ecc_info {
.mode = ECC_UNKNOWN,
};
+void print_timings_info(float cas, int rcd, int rp, int ras) {
+
+ /* Now, we could print some additionnals timings infos) */
+ cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
+ col2 += 9;
+
+ // CAS Latency (tCAS)
+ if (cas == 1.5) {
+ cprint(LINE_CPU+5, col2, "1.5"); col2 += 3;
+ } else if (cas == 2.5) {
+ cprint(LINE_CPU+5, col2, "2.5"); col2 += 3;
+ } else {
+ dprint(LINE_CPU+5, col2, cas, 1, 0); col2 += 1;
+ }
+ cprint(LINE_CPU+5, col2, "-"); col2 += 1;
+
+ // RAS-To-CAS (tRCD)
+ dprint(LINE_CPU+5, col2, rcd, 1, 0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ col2 +=2;
+
+ // RAS Precharge (tRP)
+ dprint(LINE_CPU+5, col2, rp, 1, 0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ col2 +=2;
+
+ // RAS Active to precharge (tRAS)
+ if (ras < 9) {
+ dprint(LINE_CPU+5, col2, ras, 1, 0);
+ col2 += 2;
+ } else {
+ dprint(LINE_CPU+5, col2, ras, 2, 0);
+ col2 += 3;
+ }
+
+}
+
+
void print_fsb_info(float val, const char *text_fsb) {
cprint(LINE_CPU+5, col2, "Settings: ");
@@ -313,12 +351,12 @@ static void setup_iE7xxx(void)
unsigned long mchcfgns;
unsigned long drc;
unsigned long device;
+ unsigned long dvnp;
-
/* Read the hardare capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
-
+
/* This is a check for E7205 */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device);
@@ -334,32 +372,40 @@ static void setup_iE7xxx(void)
/* E7205 doesn't support scrubbing */
if (device != 0x255d) {
/* scrub enabled */
- /* For E7501, 10b or 11b (2:1) indicate valid SCRUB operations */
- ctrl.cap = ECC_SCRUB;
- if (mchcfgns & (1 << 2)) {
- ctrl.mode |= __ECC_SCRUB;
- }
+ /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */
+ ctrl.cap = ECC_SCRUB;
+ if (mchcfgns & 1) {
+ ctrl.mode |= __ECC_SCRUB;
+ }
+
+ /* Now, we can active Dev1/Fun1 */
+ /* Thanks to Tyan for providing us the board to solve this */
+ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp);
+ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xE0, 2, (dvnp & 0xFE));
+
}
+
/* Clear any prexisting error reports */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3);
+
+
}
static void poll_iE7xxx(void)
{
unsigned long ferr;
unsigned long nerr;
-
- unsigned char err;
+
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
- err = ferr | nerr;
- if (err & 1) {
+ if (ferr & 1) {
/* Find out about the first correctable error */
unsigned long celog_add;
unsigned long celog_syndrome;
unsigned long page;
+
/* Read the error location */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
/* Read the syndrome */
@@ -370,11 +416,16 @@ static void poll_iE7xxx(void)
/* Report the error */
print_ecc_err(page, 0, 1, celog_syndrome, 0);
+
+ /* Clear Bit */
+ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
- if (err & 2) {
+
+ if (ferr & 2) {
/* Found out about the first uncorrectable error */
unsigned long uccelog_add;
unsigned long page;
+
/* Read the error location */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
@@ -384,10 +435,15 @@ static void poll_iE7xxx(void)
/* Report the error */
print_ecc_err(page, 0, 0, 0, 0);
+ /* Clear Bit */
+ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
- /* Clear the error registers */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
+
+ /* Check if DRAM_NERR contains data */
+ if (nerr & 3) {
+ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
+ }
+
}
static void setup_i440gx(void)
@@ -723,7 +779,7 @@ static void poll_i860(void)
/* --------------------------------------------------------------------- */
-static int amd64cm[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4, 0x6, 0x8, 0xA, 0xC, 0xE, 0x10, 0x12, 0x14, 0x16};
+
static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5};
static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0};
@@ -731,35 +787,29 @@ static void poll_fsb_amd64(void) {
unsigned int mcgsrl;
unsigned int mcgsth;
- unsigned long fid, temp, temp2;
+ unsigned long fid, temp2;
unsigned long dramchr;
double clockratio;
double dramclock;
- int i;
+
float coef;
coef = 10;
/* First, got the FID by MSR */
- /* First look if Cool 'n Quiet is supported to choose the right msr */
+ /* First look if Cool 'n Quiet is supported to choose the best msr */
if (((cpu_id.pwrcap >> 1) & 1) == 1) {
rdmsr(0xc0010042, mcgsrl, mcgsth);
- fid = (mcgsrl& 0x1F);
+ fid = (mcgsrl & 0x3F);
} else {
rdmsr(0xc0010015, mcgsrl, mcgsth);
- fid = ((mcgsrl >> 24)& 0x1F);
+ fid = ((mcgsrl >> 24)& 0x3F);
}
- temp = fid & 0x1E;
-
- for(i = 4; i < sizeof(amd64cm)/sizeof(amd64cm[0]); i++) {
- if (amd64cm[i] == temp) {
- coef = i;
- break;
- }
- }
+ /* Extreme simplification. */
+ coef = ( fid / 2 ) + 4.0;
- /* Support for .5 coef */
- if ((fid & 1) == 1) { coef = coef + 0.5; }
+ /* Support for .5 coef */
+ if ((fid & 1) == 1) { coef = coef + 0.5; }
/* Next, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
@@ -807,14 +857,20 @@ static void poll_fsb_i925(void) {
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- ptr=(long*)(dev0+0x112);
+ ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
- mchcfg = (mchcfg >> 12)&3;
+
+ mchcfg = (mchcfg >> 4)&3;
if (mchcfg == 2) { dramratio = 1; }
- else if (mchcfg == 3) { dramratio = 1.33334; }
else if (mchcfg == 1) { dramratio = 0.66667; }
+ else if (mchcfg == 3) {
+ // If mchcfg[0] = 1 => FSB533 / = 0 => FSB800
+ if ((mchcfg & 1) == 0) { dramratio = 1.33334; }
+ else { dramratio = 1.5; }
+ }
+
// Compute RAM Frequency
fsb = ((extclock /1000) / coef);
@@ -824,7 +880,6 @@ static void poll_fsb_i925(void) {
print_fsb_info(dramclock, "RAM : ");
/* Print FSB (only if ECC is not enabled) */
-
cprint(LINE_CPU+4, col +1, "- FSB : ");
col += 9;
dprint(LINE_CPU+4, col, fsb, 3,0);
@@ -884,28 +939,38 @@ static void poll_fsb_i875(void) {
static void poll_fsb_p4(void) {
- ulong fsb;
+ ulong fsb, idetect;
unsigned int msr_lo, msr_hi;
int coef;
- /* Find multiplier (by MSR) */
+ /* Find multiplier (by MSR) - Added a check for P-M for ATi RSxxx chipsets */
+ if (cpu_id.type == 6) {
+ rdmsr(0x2A, msr_lo, msr_hi);
+ coef = (msr_lo >> 22) & 0x1F;
+ } else {
rdmsr(0x2C, msr_lo, msr_hi);
-
- coef = (msr_lo >> 24) & 0x1F;
+ coef = (msr_lo >> 24) & 0x1F;
+ }
fsb = ((extclock /1000) / coef);
/* Print FSB */
-
cprint(LINE_CPU+4, col +1, "/ FSB : ");
col += 9;
dprint(LINE_CPU+4, col, fsb, 3,0);
col += 3;
cprint(LINE_CPU+4, col +1, "Mhz");
col += 4;
+
+ /* For synchro only chipsets */
+ pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
+ if (idetect == 0x2540 || idetect == 0x254C) {
+ print_fsb_info(fsb, "RAM : ");
+ }
}
+
static void poll_fsb_i855(void) {
@@ -1050,7 +1115,6 @@ static void poll_timings_i925(void) {
ulong dev0, mch, drt, drc, dcc, temp;
long *ptr;
-
//Read Offset 9C
pci_conf_read( 0, 0, 0, 0x9C, 1, &mch);
@@ -1125,13 +1189,14 @@ static void poll_timings_i925(void) {
else if (temp == 2) { cprint(LINE_CPU+5, col2, " Dual Channel (Interleaved)"); }
else { cprint(LINE_CPU+5, col2, " Single Channel (64 bits)"); }
-
}
static void poll_timings_i875(void) {
ulong dev6, dev62;
ulong temp;
+ float cas;
+ int rcd, rp, ras;
long *ptr, *ptr2;
/* Read the MMR Base Address & Define the pointer */
@@ -1147,49 +1212,33 @@ static void poll_timings_i875(void) {
cprint(LINE_CPU+4, col +1, "- PAT : Disabled");
}
- /* Now, we could print some additionnals timings infos) */
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
+ /* Now, we could check some additionnals timings infos) */
ptr=(long*)(dev6+0x60);
// CAS Latency (tCAS)
temp = ((*ptr >> 5)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "2.5-"); col2 +=4; }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "2-"); col2 +=2; }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "3-"); col2 +=2; }
+ if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; }
// RAS-To-CAS (tRCD)
temp = ((*ptr >> 2)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "3-"); }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; }
// RAS Precharge (tRP)
temp = (*ptr&0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "3-"); }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; }
// RAS Active to precharge (tRAS)
temp = ((*ptr >> 7)& 0x7);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "10"); col2 +=2; }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "9"); col2 +=1; }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "8"); col2 +=1; }
- if (temp == 0x3) { cprint(LINE_CPU+5, col2, "7"); col2 +=1; }
- if (temp == 0x4) { cprint(LINE_CPU+5, col2, "6"); col2 +=1; }
- if (temp == 0x5) { cprint(LINE_CPU+5, col2, "5"); col2 +=1; }
+ ras = 10 - temp;
- cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
+ // Print timings
+ print_timings_info(cas, rcd, rp, ras);
// Print 64 or 128 bits mode
if (((*ptr2 >> 21)&1) == 1) {
- cprint(LINE_CPU+5, col2, " Dual Channel (128 bits)");
- col2 +=24;
+ cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
} else {
- cprint(LINE_CPU+5, col2, " Single Channel (64 bits)");
- col2 +=15;
+ cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
}
}
@@ -1229,6 +1278,32 @@ static void poll_timings_i855(void) {
}
+static void poll_timings_E750x(void) {
+
+ ulong drt, drc, temp;
+ float cas;
+ int rcd, rp, ras;
+
+ pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
+ pci_conf_read( 0, 0, 0, 0x7C, 4, &drc);
+
+ if ((drt >> 4) & 1) { cas = 2; } else { cas = 2.5; };
+ if ((drt >> 1) & 1) { rcd = 2; } else { rcd = 3; };
+ if (drt & 1) { rp = 2; } else { rp = 3; };
+
+ temp = ((drt >> 9) & 3);
+ if (temp == 2) { ras = 5; } else if (temp == 1) { ras = 6; } else { ras = 7; }
+
+ print_timings_info(cas, rcd, rp, ras);
+
+ if (((drc >> 22)&1) == 1) {
+ cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
+ } else {
+ cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
+ }
+
+}
+
static void poll_timings_i852(void) {
ulong drt, temp;
@@ -1469,6 +1544,7 @@ static struct pci_memory_controller controllers[] = {
{ 0x1039, 0x0748, "SiS 748", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0655, "SiS 655", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0648, "SiS 648", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0661, "SiS 661", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
/* ALi */
{ 0x10b9, 0x1531, "Aladdin 4", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -1488,7 +1564,7 @@ static struct pci_memory_controller controllers[] = {
{ 0x10de, 0x00E1, "nForce3 250", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
/* VIA */
- { 0x1106, 0x0305, "VIA KT133/KT133A", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0305, "VIA KT133/KT133A", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1106, 0x0391, "vt8371", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1106, 0x0501, "vt8501", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1106, 0x0585, "vt82c585", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -1534,8 +1610,8 @@ static struct pci_memory_controller controllers[] = {
{ 0x8086, 0x71A0, "Intel i440gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
{ 0x8086, 0x71A2, "Intel i440gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
{ 0x8086, 0x84C5, "Intel i450gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x2540, "Intel E7500", 1, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x254C, "Intel E7501", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
+ { 0x8086, 0x2540, "Intel E7500", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
+ { 0x8086, 0x254C, "Intel E7501", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
{ 0x8086, 0x255d, "Intel E7205", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
{ 0x8086, 0x2570, "Intel i848/i865", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing },
{ 0x8086, 0x2578, "Intel i875P", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_i875 },
@@ -1600,8 +1676,8 @@ static void print_memory_controller(void)
if (ctrl.mode & __ECC_SCRUB) {
int on;
on = ctrl.mode & __ECC_SCRUB;
- cprint(LINE_CPU+4, col, "Scrub");
- cprint(LINE_CPU+4, col +5, on?"+ ":"- ");
+ cprint(LINE_CPU+4, col, " Scrub");
+ cprint(LINE_CPU+4, col +6, on?"+ ":"- ");
col += 7;
}
if (ctrl.cap & __ECC_UNEXPECTED) {
diff --git a/head.S b/head.S
index 400f183..28772c3 100644
--- a/head.S
+++ b/head.S
@@ -347,6 +347,7 @@ have_cpuid:
movl X86_VENDOR_ID+8(%esi), %eax
cmpl $0x6c65746e,%eax # Is this an Intel CPU?
jne not_intel
+ movb %bl, X86_PWRCAP(%esi) # Store BrandID in AMD PWRCAP if the CPU is from Intel
movl $2, %eax # Use the CPUID instruction to get cache info
cpuid
movl %eax, X86_CACHE(%esi)
diff --git a/init.c b/init.c
index 90b8dec..e7b2508 100644
--- a/init.c
+++ b/init.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V1.15 Specific code (GPL V2.0)
+ * MemTest86+ V1.25 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -51,7 +51,7 @@ static void display_init(void)
for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) {
*pp = 0x20;
}
- cprint(0, 0, " Memtest86 v1.20 ");
+ cprint(0, 0, " Memtest86 v1.25 ");
for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) {
*pp = 0xA4;
@@ -441,29 +441,23 @@ void cpu_type(void)
break;
case 15:
switch(cpu_id.model) {
- case 4:
- case 7:
- case 8:
- case 11:
- case 12:
- case 15:
default:
cprint(LINE_CPU, 0, "AMD Athlon 64");
off = 13;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
break;
case 5:
cprint(LINE_CPU, 0, "AMD Opteron");
off = 11;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
break;
+ case 12:
+ cprint(LINE_CPU, 0, "AMD Sempron");
+ off = 11;
+ break;
}
+ l1_cache = cpu_id.cache_info[3];
+ l1_cache += cpu_id.cache_info[7];
+ l2_cache = (cpu_id.cache_info[11] << 8);
+ l2_cache += cpu_id.cache_info[10];
break;
}
break;
@@ -654,10 +648,16 @@ void cpu_type(void)
switch(cpu_id.model) {
case 0:
case 1:
- if (l2_cache == 128) {
+ if (l2_cache == 128) {
cprint(LINE_CPU, 0, "Celeron (0.18)");
off = 14;
- } else {
+ } else if (cpu_id.pwrcap == 0x0B) {
+ cprint(LINE_CPU, 0, "Xeon DP (0.18)");
+ off = 14;
+ } else if (cpu_id.pwrcap == 0x0C) {
+ cprint(LINE_CPU, 0, "Xeon MP (0.18)");
+ off = 14;
+ } else {
cprint(LINE_CPU, 0, "Pentium 4 (0.18)");
off = 16;
}
@@ -666,7 +666,13 @@ void cpu_type(void)
if (l2_cache == 128) {
cprint(LINE_CPU, 0, "Celeron (0.13)");
off = 14;
- } else {
+ } else if (cpu_id.pwrcap == 0x0B) {
+ cprint(LINE_CPU, 0, "Xeon DP (0.13)");
+ off = 14;
+ } else if (cpu_id.pwrcap == 0x0C) {
+ cprint(LINE_CPU, 0, "Xeon MP (0.13)");
+ off = 14;
+ } else {
cprint(LINE_CPU, 0, "Pentium 4 (0.13)");
off = 16;
}
@@ -676,7 +682,13 @@ void cpu_type(void)
if (l2_cache == 256) {
cprint(LINE_CPU, 0, "Celeron (0.09)");
off = 14;
- } else {
+ } else if (cpu_id.pwrcap == 0x0B) {
+ cprint(LINE_CPU, 0, "Xeon DP (0.09)");
+ off = 14;
+ } else if (cpu_id.pwrcap == 0x0C) {
+ cprint(LINE_CPU, 0, "Xeon MP (0.09)");
+ off = 14;
+ } else {
cprint(LINE_CPU, 0, "Pentium 4 (0.09)");
off = 16;
}
diff --git a/mt86+_loader.asm b/mt86+_loader.asm
new file mode 100644
index 0000000..38825be
--- /dev/null
+++ b/mt86+_loader.asm
@@ -0,0 +1,226 @@
+; A loader for www.Memtest86.com images, by Eric Auer 2003.
+; This assumes that the image starts with the boot sector,
+; which has the size of setup.S in sectors in a byte at offset
+; 1f1h (497). Further, I assume setup.S directly after the boot
+; sector and the actual memtest head.S after setup.S ...
+
+; This version is derived from memtestL loader, which loads
+; memtest.bin from a separate file. This version is meant to
+; be used like (DOS / Unix variants):
+; copy /b memteste.bin + memtest.bin memtest.exe
+; cat memteste.bin memtest.bin > memtest.exe
+; The good thing is that you get a single file which can be
+; compressed, for example with http://upx.sf.net/ (UPX).
+
+%define fullsize (86948 + buffer - start)
+ ; 84420 is the size of memtest86+ V1.25, adjust as needed!
+
+%define stacksize 2048
+%define stackpara ((stacksize + 15) / 16)
+
+ ; the trick is that NASM believes the header would be part
+ ; of the loaded image, so we "org 20h bytes too early" to fix:
+ org 0e0h ; NASM thinks after header we have 100h
+ ; which is what we want it to think.
+
+exeh: db "MZ"
+ dw fullsize % 512 ; how much to load from
+ dw (fullsize + 511) / 512 ; .exe to RAM
+ dw 0 ; no relocations used
+ dw 2 ; header size is 2 * 16 bytes
+ dw stackpara ; minimum heap is 128 * 16 bytes, for stack
+ dw stackpara ; we do not need more heap either
+ dw (fullsize + 15) / 16 ; SS is after file
+ ; segment offsets are relative to PSPseg+10h
+ ; initial DS and ES point to PSPseg, and file
+ ; except headers is loaded to PSPseg+10h.
+
+ dw stacksize-4 ; initial SP value
+ dw 0 ; no checksum
+ dw 100h ; initial IP
+ dw -10h ; initial CS relative to PSPseg+10h
+ dw 0 ; no relocation table, "offset 0 in file"
+ dw 0 ; this is not an overlay
+ db "MEMT" ; padding to a multiple of 16 bytes
+
+ ; loaded part begins here (set CS so that IP is 100h here)
+
+start: ; entry point ; if you use obj + linker, use "..start:"
+ mov ax,cs ; ***
+ mov ds,ax ; ***
+ mov es,ax ; ***
+
+ ; test if we have 386 or better:
+ pushf ; save flags
+ xor ax,ax
+ push ax
+ popf ; try to clear all bits
+ pushf
+ pop ax
+ and ax,0f000h
+ cmp ax,0f000h
+ jz noinst1 ; 4 msb stuck to 1: 808x or 80186
+ mov ax,0f000h
+ push ax
+ popf ; try to set 4 msb
+ pushf
+ pop ax
+ test ax,0f000h
+ jz noinst1 ; 4 msb stuck to 0: 80286
+ popf ; restore flags
+ jmp short found386
+
+noinst1:
+ popf ; restore flags
+ mov dx,need386
+ jmp generror
+
+
+found386: ; now test if the system is in real mode:
+ smsw ax ; MSW is the low half of CR0
+ ; (smsw is not priv'd, unlike mov eax,cr0)
+ test al,1 ; if the PE (protected mode) flag on?
+%ifndef DEBUG ; ignore findings in debug mode
+ jnz foundprotected
+%endif
+ jmp foundreal
+
+foundprotected:
+ mov dx,noreal
+ jmp generror
+
+; ------------
+
+need386 db "Sorry, you need at least a 386 CPU to use Memtest86+."
+ db 13,10,"$"
+noreal db "You cannot run Memtest86+ if the system already is in"
+ db " protected mode.",13,10,"$"
+
+; ------------
+
+generror: ; generic error exit
+ push cs
+ pop ds
+ push cs
+ pop es
+ mov ah,9
+ int 21h
+ mov ax,4c01h
+ int 21h
+
+; ------------
+
+foundreal:
+ mov cx,buffer+15
+ shr cx,4 ; buffer offset in paragraphs
+ mov ax,cs
+ add ax,cx ; buffer offset in paragraphs
+ ; now AX is the buffer segment
+ mov [cs:bufsetup+2],ax ; far pointer to boot sector now
+ mov cx,20h ; size of boot sector in paragraphs
+ add [cs:bufsetup+2],cx ; far pointer to setup now
+ movzx eax,ax
+ shl eax,4 ; linear buffer offset
+ mov [cs:buflinear],eax
+
+findpoint: ; now patch the loader!
+ mov al,[buffer+1f1h] ; size of setup.S in sectors
+ ; should be 4 ...
+ inc al ; the boot sector itself
+ movzx eax,al
+ shl eax,9 ; log 2 of sector size
+ add [cs:buflinear],eax ; linear address of head.S now
+ mov ax,[buffer+237h] ; should be jmp far dword (ofs, seg)
+ cmp ax,0ea66h
+ jz foundpatch
+patchbug: ; could not patch the jump
+ mov dx,nopatch
+ jmp generror
+
+gdtbug:
+ mov dx,nogdt
+ jmp generror
+
+foundpatch:
+ mov eax,[cs:buflinear]
+ mov [buffer+239h],eax ; patch the protected mode entry jump
+ ; (offset only - segment selector unchanged: flat linear CS)
+
+findgdt:
+ mov eax,[cs:buffer+20ch] ; should be lgdt offset
+ and eax,00ffffffh
+ cmp eax,0016010fh ; lgdt ...
+ jnz gdtbug
+
+ mov ax,[cs:buffer+20fh] ; GDTR contents pointer
+ mov bx,ax
+ mov eax,[cs:buffer+200h+bx+2] ; GDT linear offset
+ and eax,1ffh ; assume GDT in first sector of setup.S
+ ; *** WARNING: this is needed because setup.S contains
+ ; *** HARDCODED offset of setup.S on linear 90200h, which
+ ; *** is 90000h + bootsect.S ... flaw in Memtest86!
+
+ mov cx,[cs:bufsetup+2] ; setup.S segment
+ movzx ecx,cx
+ shl ecx,4 ; linear setup.S address
+ add eax,ecx ; fixed GDT linear offset
+ mov [cs:buffer+200h+bx+2],eax ; patch it
+
+ ;mov dx,trying
+ ;mov ah,9
+ ;int 21h
+
+ ;xor ax,ax
+ ;int 16h ; wait for a keypress from the user
+
+ mov ax,[cs:bufsetup+2] ; setup segment
+ mov ds,ax ; set nice data segments for setup.S ...
+ mov es,ax
+ xor ax,ax
+ mov fs,ax
+ mov gs,ax
+
+ cli
+ lss sp,[cs:newstack] ; stack in first 64k now!
+ movzx esp,sp ; ensure 16bit stack pointer
+ ; Memtest86 head.S assumes that it can just turn SS to
+ ; linear. This would put the stack at 0:200h or so for us
+ ; if we fail to move the stack around ...
+
+%ifdef DEBUG
+ mov ebp,[cs:buflinear] ; will show up in debugging logs
+ mov esi,[cs:bufsetup] ; will show up in debugging logs
+%endif
+
+ jmp far [cs:bufsetup]
+ ; setup.S will enable the A20 (ignoring HIMEM, just using
+ ; the classic 8042 programming trick) and turn on protected
+ ; mode. Then it will jump to head.S, which luckily can run
+ ; from any offset inside the linear 4 GB CS ...
+
+; ------------
+
+buflinear dd 0 ; linear address of head.S entry point
+bufsetup dw 0,0 ; far pointer to setup.S entry point
+
+newstack dw 03fch,0 ; beware, stack will overwrite IDT.
+
+; ------------
+
+nopatch db "jmp far dword not found at setup.S offset 37h,",13,10
+ db "(file offset 237h is not 66h, 0eah)",13,10
+ db "please adjust and recompile memtestl...",13,10,"$"
+
+nogdt db "lgdt [...] not found at setup.S offset 0ch,",13,10
+ db "(file offset 20ch is not 0fh, 01h, 16h)",13,10
+ db "please adjust and recompile memtestl...",13,10,"$"
+
+trying db "Now trying to start Memtest86...",13,10
+ db "You have to reboot to leave Memtest86 again.",13,10
+ db "Press a key to go on.",13,10,"$"
+
+; ------------
+
+ align 16
+buffer: ; a label pointing to where in the file memtest.bin will be.
+
diff --git a/mt86+_loader.bin b/mt86+_loader.bin
new file mode 100644
index 0000000..75eeb7a
--- /dev/null
+++ b/mt86+_loader.bin
Binary files differ
diff --git a/precomp.bin b/precomp.bin
index 2a600d6..f937573 100755
--- a/precomp.bin
+++ b/precomp.bin
Binary files differ