summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2012-07-10 20:26:41 +0200
committerMichael Brown2015-04-21 01:39:17 +0200
commitbe35022f55e5cf8f864d7aac079f9a8a433d84f9 (patch)
treef0906b02eaab6a44c9b84ed11701064c85c53179
parent[pxe] Add memtest.0 target which can be loaded as a PXE NBP (diff)
downloadmemtest86-be35022f55e5cf8f864d7aac079f9a8a433d84f9.tar.gz
memtest86-be35022f55e5cf8f864d7aac079f9a8a433d84f9.tar.xz
memtest86-be35022f55e5cf8f864d7aac079f9a8a433d84f9.zip
[pxe] Switch back to real mode on exit
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--Makefile5
-rw-r--r--exit.S81
-rw-r--r--lib.c8
-rw-r--r--main.c30
-rw-r--r--test.h8
5 files changed, 126 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index baf60e1..eb5fedb 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ CC=gcc
CFLAGS= -Wall -march=i486 -m32 -O1 -fomit-frame-pointer -fno-builtin \
-ffreestanding -fPIC $(SMP_FL) -fno-stack-protector
-OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \
+OBJS= head.o exit.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \
config.o cpuid.o linuxbios.o pci.o memsize.o spd.o error.o dmi.o controller.o \
smp.o vmem.o random.o
@@ -48,6 +48,9 @@ setup.s: setup.S config.h defs.h
pxe.s: pxe.S config.h defs.h
$(CC) -E -traditional $< -o $@
+exit.s: exit.S config.h defs.h
+ $(CC) -E -traditional $< -o $@
+
memtest.bin: memtest_shared.bin bootsect.o setup.o memtest.bin.lds
$(LD) -T memtest.bin.lds bootsect.o setup.o -b binary \
memtest_shared.bin -o memtest.bin
diff --git a/exit.S b/exit.S
new file mode 100644
index 0000000..23858da
--- /dev/null
+++ b/exit.S
@@ -0,0 +1,81 @@
+/*
+ * exit.S Copyright (C) 2012 Michael Brown <mcb30@ipxe.org>
+ *
+ */
+
+#include "defs.h"
+
+.text
+.code32
+.globl exit
+exit:
+ /* Exit status to %eax */
+ movl 4(%esp), %eax
+
+ /* Load IDT and GDT and switch to 16-bit code segment */
+ cli
+ lidt idt_descr
+ lgdt gdt_descr
+ ljmp $REAL_CS, $(1f - LOW_TEST_ADR)
+1:
+ .code16
+ /* Load 16-bit limits for other segment registers */
+ movw $REAL_DS, %bx
+ movw %bx, %ds
+ movw %bx, %es
+ movw %bx, %fs
+ movw %bx, %gs
+ movw %bx, %ss
+ movl $LOW_TEST_ADR, %esp
+
+ /* Switch to real mode */
+ movl %cr0, %ebx
+ andb $~0x01, %bl
+ movl %ebx, %cr0
+ ljmp $(LOW_TEST_ADR >> 4), $1f
+1:
+ /* Load real-mode segment registers */
+ xorw %bx, %bx
+ movw %bx, %ds
+ movw %bx, %es
+ movw %bx, %fs
+ movw %bx, %gs
+ movw %bx, %ss
+
+ /* Reenable interrupts */
+ sti
+
+ /* Perform a warm reset */
+ movw $0x1234, %ax
+ movw %ax, 0x472
+ movb $0xfe, %al
+ outb %al, $0x64
+
+ /* If reset failed, halt the CPU */
+ cli
+ hlt
+
+.align 16
+gdt:
+ /* Dummy */
+ .word 0,0,0,0
+ /* Unused */
+ .word 0,0,0,0
+ /* Unused */
+ .word 0,0,0,0
+ /* Unused */
+ .word 0,0,0,0
+ /* 16 bit real mode code segment */
+ .word 0xffff, ( LOW_TEST_ADR & 0xffff )
+ .word ( 0x9b00 | ( LOW_TEST_ADR >> 16 ) ), 0
+ /* 16 bit real mode data segment */
+ .word 0xffff, 0, 0x9300, 0
+gdt_end:
+gdt_descr:
+ .word gdt_end - gdt - 1
+ .long gdt
+
+.align 16
+idt_descr:
+ .word 0xffff
+ .long 0
diff --git a/lib.c b/lib.c
index a2b829d..299a2d7 100644
--- a/lib.c
+++ b/lib.c
@@ -28,6 +28,9 @@ int serial_baud_rate = SERIAL_BAUD_RATE;
unsigned char serial_parity = 0;
unsigned char serial_bits = 8;
+extern volatile int mstr_cpu;
+extern volatile int bail;
+
struct ascii_map_str {
int ascii;
int keycode;
@@ -632,7 +635,8 @@ void check_input(void)
case 1:
/* "ESC" key was pressed, bail out. */
cprint(LINE_RANGE, COL_MID+23, "Halting... ");
- reboot();
+ v->exit++;
+ bail++;
break;
case 46:
/* c - Configure */
@@ -1196,4 +1200,4 @@ void get_list(int x, int y, int len, char *buf)
return;
}
}
-} \ No newline at end of file
+}
diff --git a/main.c b/main.c
index 144fb1b..bf456ef 100644
--- a/main.c
+++ b/main.c
@@ -203,7 +203,7 @@ void btrace(int me, int line, char *msg, int wait, long v1, long v2)
}
/* Relocate the test to a new address. Be careful to not overlap! */
-static void run_at(unsigned long addr, int cpu)
+void run_at(unsigned long addr, int cpu)
{
ulong *ja = (ulong *)(addr + startup_32 - _start);
@@ -526,6 +526,25 @@ void test_start(void)
btrace(my_cpu_num, __LINE__, "Start Done", 1, 0, 0);
start_seq = 2;
+ /* Exit if testing has finished */
+ if (v->exit) {
+ paging_off();
+ set_cache(1);
+ barrier();
+ if (my_cpu_num == 0) {
+ if (v->ecount) {
+ exit(EXIT_FAILURE);
+ } else if (v->pass) {
+ exit(EXIT_SUCCESS);
+ } else {
+ exit(EXIT_INCOMPLETE);
+ }
+ } else {
+ /* Halt APs */
+ __asm__ __volatile__ ( "cli ; hlt" );
+ }
+ }
+
/* Loop through all tests */
while (1) {
/* If the restart flag is set all initial params */
@@ -550,6 +569,11 @@ void test_start(void)
btrace(my_cpu_num, __LINE__, "Sched_Barr", 1,window,win_next);
barrier();
+ /* Exit if testing has finished */
+ if (v->exit) {
+ run_at(LOW_TEST_ADR, my_cpu_num);
+ }
+
/* Don't go over the 8TB PAE limit */
if (win_next > MAX_MEM) {
break;
@@ -759,8 +783,8 @@ void test_start(void)
if (v->ecount == 0)
{
/* If onepass is enabled and we did not get any errors
- * reboot to exit the test */
- if (onepass) { reboot(); }
+ * exit the test */
+ if (onepass) { v->exit++; }
if (!btflag) cprint(LINE_MSG, COL_MSG-8, "** Pass complete, no errors, press Esc to exit **");
if(BEEP_END_NO_ERROR)
{
diff --git a/test.h b/test.h
index 862da15..4a7e375 100644
--- a/test.h
+++ b/test.h
@@ -173,6 +173,7 @@ int get_key(void);
int ascii_to_keycode(int in);
void wait_keyup(void);
void print_hdr(void);
+void run_at(unsigned long addr, int cpu);
void restart(void);
void parity_err(ulong edi, ulong esi);
void start_config(void);
@@ -190,6 +191,7 @@ void bit_fade_fill(unsigned long n, int cpu);
void bit_fade_chk(unsigned long n, int cpu);
void find_ticks_for_pass(void);
void beep(unsigned int frequency);
+void exit(int status);
#define PRINTMODE_SUMMARY 0
#define PRINTMODE_ADDRESSES 1
@@ -302,6 +304,7 @@ struct vars {
int fail_safe;
int each_sec;
int beepmode;
+ int exit;
};
#define FIRMWARE_UNKNOWN 0
@@ -314,5 +317,10 @@ extern unsigned char _size, _pages;
extern struct mem_info_t mem_info;
+/* Exit codes */
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_INCOMPLETE 2
+
#endif /* __ASSEMBLY__ */
#endif /* _TEST_H_ */