Browse Source

[comboot] Restore the real-mode stack pointer on exit from a COMBOOT image

COMBOOT images use INTs to issue API calls; these end up making calls
into gPXE from real mode, and so temporarily change the real-mode
stack pointer.  When our COMBOOT code uses a longjmp() to implement
the various "exit COMBOOT image" API calls, this leaves the real-mode
stack pointer stuck with its temporary value, which causes problems if
we eventually try to exit out of gPXE back to the BIOS.

Fix by adding rmsetjmp() and rmlongjmp() calls (analogous to
sigsetjmp()/siglongjmp()); these save and restore the additional state
needed for real-mode calls to function correctly.
tags/v0.9.7
Michael Brown 16 years ago
parent
commit
5026a35fef

+ 1
- 1
src/arch/i386/image/com32.c View File

52
 	int state;
52
 	int state;
53
 	uint32_t avail_mem_top;
53
 	uint32_t avail_mem_top;
54
 
54
 
55
-	state = setjmp ( comboot_return );
55
+	state = rmsetjmp ( comboot_return );
56
 
56
 
57
 	switch ( state ) {
57
 	switch ( state ) {
58
 	case 0: /* First time through; invoke COM32 program */
58
 	case 0: /* First time through; invoke COM32 program */

+ 1
- 1
src/arch/i386/image/comboot.c View File

133
 	userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
133
 	userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
134
 	int state;
134
 	int state;
135
 
135
 
136
-	state = setjmp ( comboot_return );
136
+	state = rmsetjmp ( comboot_return );
137
 
137
 
138
 	switch ( state ) {
138
 	switch ( state ) {
139
 	case 0: /* First time through; invoke COMBOOT program */
139
 	case 0: /* First time through; invoke COMBOOT program */

+ 1
- 1
src/arch/i386/include/comboot.h View File

78
 extern int comboot_resolv ( const char *name, struct in_addr *address );
78
 extern int comboot_resolv ( const char *name, struct in_addr *address );
79
 
79
 
80
 /* setjmp/longjmp context buffer used to return after loading an image */
80
 /* setjmp/longjmp context buffer used to return after loading an image */
81
-extern jmp_buf comboot_return;
81
+extern rmjmp_buf comboot_return;
82
 
82
 
83
 /* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
83
 /* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
84
 extern struct image *comboot_replacement_image;
84
 extern struct image *comboot_replacement_image;

+ 31
- 5
src/arch/i386/include/setjmp.h View File

1
 #ifndef ETHERBOOT_SETJMP_H
1
 #ifndef ETHERBOOT_SETJMP_H
2
 #define ETHERBOOT_SETJMP_H
2
 #define ETHERBOOT_SETJMP_H
3
 
3
 
4
+#include <stdint.h>
5
+#include <realmode.h>
4
 
6
 
5
-/* Define a type for use by setjmp and longjmp */
6
-#define JBLEN 6
7
-typedef unsigned long jmp_buf[JBLEN];
7
+/** A jump buffer */
8
+typedef struct {
9
+	uint32_t retaddr;
10
+	uint32_t ebx;
11
+	uint32_t esp;
12
+	uint32_t ebp;
13
+	uint32_t esi;
14
+	uint32_t edi;
15
+} jmp_buf[1];
8
 
16
 
9
-extern int __asmcall setjmp (jmp_buf env);
10
-extern void __asmcall longjmp (jmp_buf env, int val);
17
+/** A real-mode-extended jump buffer */
18
+typedef struct {
19
+	jmp_buf env;
20
+	uint16_t rm_ss;
21
+	uint16_t rm_sp;
22
+} rmjmp_buf[1];
23
+
24
+extern int __asmcall setjmp ( jmp_buf env );
25
+extern void __asmcall longjmp ( jmp_buf env, int val );
26
+
27
+#define rmsetjmp( _env ) ( {			\
28
+	(_env)->rm_ss = rm_ss;			\
29
+	(_env)->rm_sp = rm_sp;			\
30
+	setjmp ( (_env)->env ); } )		\
31
+
32
+#define rmlongjmp( _env, _val ) do {		\
33
+	rm_ss = (_env)->rm_ss;			\
34
+	rm_sp = (_env)->rm_sp;			\
35
+	longjmp ( (_env)->env, (_val) );	\
36
+	} while ( 0 )
11
 
37
 
12
 #endif /* ETHERBOOT_SETJMP_H */
38
 #endif /* ETHERBOOT_SETJMP_H */

+ 6
- 6
src/arch/i386/interface/syslinux/comboot_call.c View File

67
 extern void int22_wrapper ( void );
67
 extern void int22_wrapper ( void );
68
 
68
 
69
 /* setjmp/longjmp context buffer used to return after loading an image */
69
 /* setjmp/longjmp context buffer used to return after loading an image */
70
-jmp_buf comboot_return;
70
+rmjmp_buf comboot_return;
71
 
71
 
72
 /* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
72
 /* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
73
 struct image *comboot_replacement_image;
73
 struct image *comboot_replacement_image;
235
  * Terminate program interrupt handler
235
  * Terminate program interrupt handler
236
  */
236
  */
237
 static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
237
 static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
238
-	longjmp ( comboot_return, COMBOOT_EXIT );
238
+	rmlongjmp ( comboot_return, COMBOOT_EXIT );
239
 }
239
 }
240
 
240
 
241
 
241
 
248
 	switch ( ix86->regs.ah ) {
248
 	switch ( ix86->regs.ah ) {
249
 	case 0x00:
249
 	case 0x00:
250
 	case 0x4C: /* Terminate program */
250
 	case 0x4C: /* Terminate program */
251
-		longjmp ( comboot_return, COMBOOT_EXIT );
251
+		rmlongjmp ( comboot_return, COMBOOT_EXIT );
252
 		break;
252
 		break;
253
 
253
 
254
 	case 0x01: /* Get Key with Echo */
254
 	case 0x01: /* Get Key with Echo */
347
 			DBG ( "COMBOOT: executing command '%s'\n", cmd );
347
 			DBG ( "COMBOOT: executing command '%s'\n", cmd );
348
 			system ( cmd );
348
 			system ( cmd );
349
 			DBG ( "COMBOOT: exiting after executing command...\n" );
349
 			DBG ( "COMBOOT: exiting after executing command...\n" );
350
-			longjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
350
+			rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
351
 		}
351
 		}
352
 		break;
352
 		break;
353
 
353
 
354
 	case 0x0004: /* Run default command */
354
 	case 0x0004: /* Run default command */
355
 		/* FIXME: just exit for now */
355
 		/* FIXME: just exit for now */
356
-		longjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
356
+		rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
357
 		break;
357
 		break;
358
 
358
 
359
 	case 0x0005: /* Force text mode */
359
 	case 0x0005: /* Force text mode */
552
 			 * part of the COMBOOT program's memory space.
552
 			 * part of the COMBOOT program's memory space.
553
 			 */
553
 			 */
554
 			DBG ( "COMBOOT: exiting to run kernel...\n" );
554
 			DBG ( "COMBOOT: exiting to run kernel...\n" );
555
-			longjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
555
+			rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
556
 		}
556
 		}
557
 		break;
557
 		break;
558
 
558
 

Loading…
Cancel
Save