mirror of
https://github.com/ipxe/ipxe
synced 2025-12-29 02:52:36 +03:00
[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.
This commit is contained in:
@@ -78,7 +78,7 @@ extern void com32_cfarcall_wrapper ( );
|
||||
extern int comboot_resolv ( const char *name, struct in_addr *address );
|
||||
|
||||
/* setjmp/longjmp context buffer used to return after loading an image */
|
||||
extern jmp_buf comboot_return;
|
||||
extern rmjmp_buf comboot_return;
|
||||
|
||||
/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
|
||||
extern struct image *comboot_replacement_image;
|
||||
|
||||
@@ -1,12 +1,38 @@
|
||||
#ifndef ETHERBOOT_SETJMP_H
|
||||
#define ETHERBOOT_SETJMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <realmode.h>
|
||||
|
||||
/* Define a type for use by setjmp and longjmp */
|
||||
#define JBLEN 6
|
||||
typedef unsigned long jmp_buf[JBLEN];
|
||||
/** A jump buffer */
|
||||
typedef struct {
|
||||
uint32_t retaddr;
|
||||
uint32_t ebx;
|
||||
uint32_t esp;
|
||||
uint32_t ebp;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
} jmp_buf[1];
|
||||
|
||||
extern int __asmcall setjmp (jmp_buf env);
|
||||
extern void __asmcall longjmp (jmp_buf env, int val);
|
||||
/** A real-mode-extended jump buffer */
|
||||
typedef struct {
|
||||
jmp_buf env;
|
||||
uint16_t rm_ss;
|
||||
uint16_t rm_sp;
|
||||
} rmjmp_buf[1];
|
||||
|
||||
extern int __asmcall setjmp ( jmp_buf env );
|
||||
extern void __asmcall longjmp ( jmp_buf env, int val );
|
||||
|
||||
#define rmsetjmp( _env ) ( { \
|
||||
(_env)->rm_ss = rm_ss; \
|
||||
(_env)->rm_sp = rm_sp; \
|
||||
setjmp ( (_env)->env ); } ) \
|
||||
|
||||
#define rmlongjmp( _env, _val ) do { \
|
||||
rm_ss = (_env)->rm_ss; \
|
||||
rm_sp = (_env)->rm_sp; \
|
||||
longjmp ( (_env)->env, (_val) ); \
|
||||
} while ( 0 )
|
||||
|
||||
#endif /* ETHERBOOT_SETJMP_H */
|
||||
|
||||
Reference in New Issue
Block a user