7171448ff0547f8ce586644be8eb58073086bc80
[people/xl0/gpxe.git] / src / arch / i386 / include / librm.h
1 #ifndef LIBRM_H
2 #define LIBRM_H
3
4 /* Drag in protected-mode segment selector values */
5 #include "virtaddr.h"
6 #include "realmode.h"
7
8 #ifndef ASSEMBLY
9
10 #include "stddef.h"
11 #include "string.h"
12
13 /*
14  * Data structures and type definitions
15  *
16  */
17
18 /* Variables in librm.S, present in the normal data segment */
19 extern uint16_t rm_sp;
20 extern uint16_t rm_ss;
21 extern uint16_t rm_cs;
22 extern uint32_t pm_esp;
23
24 /* Functions that librm expects to be able to link to.  Included here
25  * so that the compiler will catch prototype mismatches.
26  */
27 extern void gateA20_set ( void );
28
29 /*
30  * librm_mgmt: functions for manipulating base memory and executing
31  * real-mode code.
32  *
33  * Full API documentation for these functions is in realmode.h.
34  *
35  */
36
37 /* Macro for obtaining a physical address from a segment:offset pair. */
38 #define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
39
40 /* Copy to/from base memory */
41 static inline void copy_to_real_librm ( uint16_t dest_seg, uint16_t dest_off,
42                                         void *src, size_t n ) {
43         memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
44 }
45 static inline void copy_from_real_librm ( void *dest,
46                                           uint16_t src_seg, uint16_t src_off,
47                                           size_t n ) {
48         memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
49 }
50 #define put_real_librm( var, dest_seg, dest_off )                             \
51         do {                                                                  \
52                 * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
53         } while ( 0 )
54 #define get_real_librm( var, src_seg, src_off )                               \
55         do {                                                                  \
56                 var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
57         } while ( 0 )
58 #define copy_to_real copy_to_real_librm
59 #define copy_from_real copy_from_real_librm
60 #define put_real put_real_librm
61 #define get_real get_real_librm
62
63 /* Copy to/from real-mode stack */
64 extern uint16_t copy_to_rm_stack ( void *data, size_t size );
65 extern void remove_from_rm_stack ( void *data, size_t size );
66
67 /* Place/remove parameter on real-mode stack in a way that's
68  * compatible with libkir
69  */
70 #define BASEMEM_PARAMETER_INIT_LIBRM( param ) \
71         copy_to_rm_stack ( & ( param ), sizeof ( param ) )
72 #define BASEMEM_PARAMETER_DONE_LIBRM( param ) \
73         remove_from_rm_stack ( & ( param ), sizeof ( param ) )
74 #define BASEMEM_PARAMETER_INIT BASEMEM_PARAMETER_INIT_LIBRM
75 #define BASEMEM_PARAMETER_DONE BASEMEM_PARAMETER_DONE_LIBRM
76
77 /* REAL_FRAGMENT: Declare and define a real-mode code fragment in .text16 */
78 #define REAL_FRAGMENT( name, asm_code_str )                             \
79         extern void name ( void );                                      \
80         extern char name ## _size[];                                    \
81         __asm__ __volatile__ (                                          \
82                 ".section \".text16\"\n\t"                              \
83                 ".code16\n\t"                                           \
84                 ".arch i386\n\t"                                        \
85                 #name ":\n\t"                                           \
86                 asm_code_str "\n\t"                                     \
87                 "ret\n\t"                                               \
88                 #name "_end:\n\t"                                       \
89                 ".equ " #name "_size, " #name "_end - " #name "\n\t"    \
90                 ".code32\n\t"                                           \
91                 ".previous\n\t"                                         \
92                 : :                                                     \
93         )
94 #define FRAGMENT_SIZE( fragment ) ( (size_t) fragment ## _size )
95
96 /* REAL_CALL: call a real-mode routine via librm */
97 #define OUT_CONSTRAINTS(...) __VA_ARGS__
98 #define IN_CONSTRAINTS(...) __VA_ARGS__
99 #define CLOBBER(...) __VA_ARGS__
100 #define REAL_CALL( routine, num_out_constraints, out_constraints,       \
101                    in_constraints, clobber )                            \
102         do {                                                            \
103                 __asm__ __volatile__ (                                  \
104                                       "pushl $" #routine "\n\t"         \
105                                       "call real_call\n\t"              \
106                                       "addl $4, %%esp\n\t"              \
107                                       : out_constraints                 \
108                                       : in_constraints                  \
109                                       : clobber                         \
110                                       );                                \
111         } while ( 0 )
112
113 /* REAL_EXEC: combine RM_FRAGMENT and REAL_CALL into one handy unit */
114 #define PASSTHRU(...) __VA_ARGS__
115 #define REAL_EXEC( name, asm_code_str, num_out_constraints, out_constraints, \
116                    in_constraints, clobber )                                 \
117         do {                                                                 \
118                 REAL_FRAGMENT ( name, asm_code_str );                        \
119                                                                              \
120                 REAL_CALL ( name, num_out_constraints,                       \
121                             PASSTHRU ( out_constraints ),                    \
122                             PASSTHRU ( in_constraints ),                     \
123                             PASSTHRU ( clobber ) );                          \
124         } while ( 0 )
125
126 #endif /* ASSEMBLY */
127
128 #endif /* LIBRM_H */