mirror of
https://github.com/ipxe/ipxe
synced 2025-12-29 11:03:15 +03:00
Merged mcb30-realmode-redesign back to HEAD
This commit is contained in:
@@ -1,124 +1,124 @@
|
||||
/* Real-mode interface
|
||||
*/
|
||||
#ifndef REALMODE_H
|
||||
#define REALMODE_H
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include "etherboot.h"
|
||||
#include "segoff.h"
|
||||
#include "stdint.h"
|
||||
#include "compiler.h"
|
||||
#include "registers.h"
|
||||
#include "io.h"
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
union {
|
||||
uint8_t l;
|
||||
uint8_t byte;
|
||||
};
|
||||
uint8_t h;
|
||||
} PACKED;
|
||||
uint16_t word;
|
||||
} PACKED reg16_t;
|
||||
|
||||
typedef union {
|
||||
reg16_t w;
|
||||
uint32_t dword;
|
||||
} PACKED reg32_t;
|
||||
|
||||
/* Macros to help with defining inline real-mode trampoline fragments.
|
||||
/*
|
||||
* Data structures and type definitions
|
||||
*
|
||||
*/
|
||||
#define RM_XSTR(x) #x /* Macro hackery needed to stringify */
|
||||
|
||||
/* All i386 registers, as passed in by prot_call or kir_call */
|
||||
struct real_mode_regs {
|
||||
struct i386_all_regs;
|
||||
} PACKED;
|
||||
|
||||
/* Segment:offset structure. Note that the order within the structure
|
||||
* is offset:segment.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t offset;
|
||||
uint16_t segment;
|
||||
} segoff_t PACKED;
|
||||
|
||||
/* Macro hackery needed to stringify bits of inline assembly */
|
||||
#define RM_XSTR(x) #x
|
||||
#define RM_STR(x) RM_XSTR(x)
|
||||
#define RM_FRAGMENT(name, asm_code_str) \
|
||||
extern void name ( void ); \
|
||||
extern void name ## _end (void); \
|
||||
__asm__( \
|
||||
".section \".text16\"\n\t" \
|
||||
".code16\n\t" \
|
||||
".arch i386\n\t" \
|
||||
".globl " #name " \n\t" \
|
||||
#name ":\n\t" \
|
||||
asm_code_str "\n\t" \
|
||||
".globl " #name "_end\n\t" \
|
||||
#name "_end:\n\t" \
|
||||
".code32\n\t" \
|
||||
".previous\n\t" \
|
||||
)
|
||||
|
||||
#define FRAGMENT_SIZE(fragment) ( (size_t) ( ( (void*) fragment ## _end )\
|
||||
- ( (void*) (fragment) ) ) )
|
||||
|
||||
/* Data structures in _prot_to_real and _real_to_prot. These
|
||||
* structures are accessed by assembly code as well as C code.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t esp;
|
||||
uint16_t cs;
|
||||
uint16_t ss;
|
||||
uint32_t r2p_params;
|
||||
} PACKED prot_to_real_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t ret_addr;
|
||||
uint32_t esp;
|
||||
uint32_t ebx;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t ebp;
|
||||
uint32_t out_stack;
|
||||
uint32_t out_stack_len;
|
||||
} PACKED real_to_prot_params_t;
|
||||
|
||||
/* Function prototypes: realmode.c
|
||||
*/
|
||||
#define real_call( fragment, in_stack, out_stack ) \
|
||||
_real_call ( fragment, FRAGMENT_SIZE(fragment), \
|
||||
(void*)(in_stack), \
|
||||
( (in_stack) == NULL ? 0 : sizeof(*(in_stack)) ), \
|
||||
(void*)(out_stack), \
|
||||
( (out_stack) == NULL ? 0 : sizeof(*(out_stack)) ) )
|
||||
extern uint16_t _real_call ( void *fragment, int fragment_len,
|
||||
void *in_stack, int in_stack_len,
|
||||
void *out_stack, int out_stack_len );
|
||||
/* Function prototypes: realmode_asm.S
|
||||
*/
|
||||
extern void rm_callback_interface;
|
||||
extern uint16_t rm_callback_interface_size;
|
||||
extern uint32_t rm_etherboot_location;
|
||||
extern void _rm_in_call ( void );
|
||||
extern void _rm_in_call_far ( void );
|
||||
|
||||
extern void _prot_to_real_prefix ( void );
|
||||
extern void _prot_to_real_prefix_end ( void );
|
||||
extern uint16_t prot_to_real_prefix_size;
|
||||
|
||||
extern void _real_to_prot_suffix ( void );
|
||||
extern void _real_to_prot_suffix_end ( void );
|
||||
extern uint16_t real_to_prot_suffix_size;
|
||||
|
||||
/* PXE assembler bits */
|
||||
extern void pxe_callback_interface;
|
||||
extern uint16_t pxe_callback_interface_size;
|
||||
extern void _pxe_in_call_far ( void );
|
||||
extern void _pxenv_in_call_far ( void );
|
||||
extern void _pxe_intercept_int1a ( void );
|
||||
extern segoff_t _pxe_intercepted_int1a;
|
||||
extern segoff_t _pxe_pxenv_location;
|
||||
|
||||
/* Global variables
|
||||
*/
|
||||
extern uint32_t real_mode_stack;
|
||||
extern size_t real_mode_stack_size;
|
||||
extern int lock_real_mode_stack;
|
||||
|
||||
|
||||
/* Function prototypes from basemem.c
|
||||
*/
|
||||
#ifdef LINUXBIOS
|
||||
/* A silly hard code that let's the code compile and work.
|
||||
* When this becomes a problem feel free to implement
|
||||
* something better.
|
||||
*/
|
||||
static inline void allot_real_mode_stack(void) { real_mode_stack = 0x7c00; }
|
||||
/* Drag in the selected real-mode transition library header */
|
||||
#ifdef KEEP_IT_REAL
|
||||
#include "libkir.h"
|
||||
#else
|
||||
void allot_real_mode_stack(void);
|
||||
#include "librm.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The API to some functions is identical between librm and libkir, so
|
||||
* they are documented here, even though the prototypes are in librm.h
|
||||
* and libkir.h.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
|
||||
* void *src, size_t n )
|
||||
* void copy_from_real ( void *dest, uint16_t src_seg, uint16_t src_off,
|
||||
* size_t n )
|
||||
*
|
||||
* These functions can be used to copy data to and from arbitrary
|
||||
* locations in base memory.
|
||||
*/
|
||||
|
||||
/*
|
||||
* put_real ( variable, uint16_t dest_seg, uint16_t dest_off )
|
||||
* get_real ( variable, uint16_t src_seg, uint16_t src_off )
|
||||
*
|
||||
* These macros can be used to read or write single variables to and
|
||||
* from arbitrary locations in base memory. "variable" must be a
|
||||
* variable of either 1, 2 or 4 bytes in length.
|
||||
*/
|
||||
|
||||
/*
|
||||
* REAL_CALL ( routine, num_out_constraints, out_constraints,
|
||||
* in_constraints, clobber )
|
||||
* REAL_EXEC ( name, asm_code_str, num_out_constraints, out_constraints,
|
||||
* in_constraints, clobber )
|
||||
*
|
||||
* If you have a pre-existing real-mode routine that you want to make
|
||||
* a far call to, use REAL_CALL. If you have a code fragment that you
|
||||
* want to copy down to base memory, execute, and then remove, use
|
||||
* REAL_EXEC.
|
||||
*
|
||||
* out_constraints must be of the form OUT_CONSTRAINTS(constraints),
|
||||
* and in_constraints must be of the form IN_CONSTRAINTS(constraints),
|
||||
* where "constraints" is a constraints list as would be used in an
|
||||
* inline __asm__()
|
||||
*
|
||||
* clobber must be of the form CLOBBER ( clobber_list ), where
|
||||
* "clobber_list" is a clobber list as would be used in an inline
|
||||
* __asm__().
|
||||
*
|
||||
* These are best illustrated by example. To write a character to the
|
||||
* console using INT 10, you would do something like:
|
||||
*
|
||||
* REAL_EXEC ( rm_test_librm,
|
||||
* "int $0x10",
|
||||
* 1,
|
||||
* OUT_CONSTRAINTS ( "=a" ( discard ) ),
|
||||
* IN_CONSTRAINTS ( "a" ( 0x0e00 + character ),
|
||||
* "b" ( 1 ) ),
|
||||
* CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
|
||||
*
|
||||
* IMPORTANT: gcc does not automatically assume that input operands
|
||||
* get clobbered. The only way to specify that an input operand may
|
||||
* be modified is to also specify it as an output operand; hence the
|
||||
* "(discard)" in the above code.
|
||||
*/
|
||||
|
||||
#warning "realmode.h contains placeholders for obsolete macros"
|
||||
|
||||
|
||||
/* Just for now */
|
||||
#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 )
|
||||
#define OFFSET(x) ( virt_to_phys ( x ) & 0xf )
|
||||
#define SEGOFF(x) { OFFSET(x), SEGMENT(x) }
|
||||
|
||||
/* To make basemem.c compile */
|
||||
extern int lock_real_mode_stack;
|
||||
extern char *real_mode_stack;
|
||||
extern char real_mode_stack_size[];
|
||||
|
||||
#define RM_FRAGMENT(name,asm) \
|
||||
void name ( void ) {} \
|
||||
extern char name ## _size[];
|
||||
|
||||
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /* REALMODE_H */
|
||||
|
||||
Reference in New Issue
Block a user