diff options
author | Michael Brown | 2009-09-18 05:37:11 +0200 |
---|---|---|
committer | Michael Brown | 2012-07-09 16:41:22 +0200 |
commit | 3befa5cb7d4fd84fa4f339a4743f017d30123a07 (patch) | |
tree | dce0c26518332fe5f39059adde9b0d3164742f61 | |
parent | [import] Import version 1.20 (diff) | |
download | memtest86-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-- | changelog | 29 | ||||
-rw-r--r-- | controller.c | 222 | ||||
-rw-r--r-- | head.S | 1 | ||||
-rw-r--r-- | init.c | 52 | ||||
-rw-r--r-- | mt86+_loader.asm | 226 | ||||
-rw-r--r-- | mt86+_loader.bin | bin | 0 -> 784 bytes | |||
-rwxr-xr-x | precomp.bin | bin | 86980 -> 86948 bytes |
7 files changed, 419 insertions, 111 deletions
@@ -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) { @@ -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) @@ -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 Binary files differnew file mode 100644 index 0000000..75eeb7a --- /dev/null +++ b/mt86+_loader.bin diff --git a/precomp.bin b/precomp.bin Binary files differindex 2a600d6..f937573 100755 --- a/precomp.bin +++ b/precomp.bin |