[librm] Make rm_sp and rm_ss globals again
[people/dverkamp/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 /* Access to variables in .data16 and .text16 */
19 extern char *data16;
20 extern char *text16;
21
22 #define __data16( variable )                                            \
23         __attribute__ (( section ( ".data16" ) ))                       \
24         _data16_ ## variable __asm__ ( #variable )
25
26 #define __data16_array( variable, array )                               \
27         __attribute__ (( section ( ".data16" ) ))                       \
28         _data16_ ## variable array __asm__ ( #variable )
29
30 #define __bss16( variable )                                             \
31         __attribute__ (( section ( ".bss16" ) ))                        \
32         _data16_ ## variable __asm__ ( #variable )
33
34 #define __bss16_array( variable, array )                                \
35         __attribute__ (( section ( ".bss16" ) ))                        \
36         _data16_ ## variable array __asm__ ( #variable )
37
38 #define __text16( variable )                                            \
39         __attribute__ (( section ( ".text16.data" ) ))                  \
40         _text16_ ## variable __asm__ ( #variable )
41
42 #define __text16_array( variable, array )                               \
43         __attribute__ (( section ( ".text16.data" ) ))                  \
44         _text16_ ## variable array __asm__ ( #variable )
45
46 #define __use_data16( variable )                                        \
47         ( * ( ( typeof ( _data16_ ## variable ) * )                     \
48               & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
49
50 #define __use_text16( variable )                                        \
51         ( * ( ( typeof ( _text16_ ## variable ) * )                     \
52               & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
53
54 #define __from_data16( pointer )                                        \
55         ( ( unsigned int )                                              \
56           ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
57
58 #define __from_text16( pointer )                                        \
59         ( ( unsigned int )                                              \
60           ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
61
62 /* Variables in librm.S, present in the normal data segment */
63 extern uint16_t rm_sp;
64 extern uint16_t rm_ss;
65 extern uint16_t __data16 ( rm_cs );
66 #define rm_cs __use_data16 ( rm_cs )
67 extern uint16_t __text16 ( rm_ds );
68 #define rm_ds __use_text16 ( rm_ds )
69
70 /* Functions that librm expects to be able to link to.  Included here
71  * so that the compiler will catch prototype mismatches.
72  */
73 extern void gateA20_set ( void );
74
75 /*
76  * librm_mgmt: functions for manipulating base memory and executing
77  * real-mode code.
78  *
79  * Full API documentation for these functions is in realmode.h.
80  *
81  */
82
83 /* Macro for obtaining a physical address from a segment:offset pair. */
84 #define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
85
86 /* Copy to/from base memory */
87 static inline __attribute__ (( always_inline )) void
88 copy_to_real_librm ( unsigned int dest_seg, unsigned int dest_off,
89                      void *src, size_t n ) {
90         memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
91 }
92 static inline __attribute__ (( always_inline )) void
93 copy_from_real_librm ( void *dest, unsigned int src_seg,
94                        unsigned int src_off, size_t n ) {
95         memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
96 }
97 #define put_real_librm( var, dest_seg, dest_off )                             \
98         do {                                                                  \
99                 * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
100         } while ( 0 )
101 #define get_real_librm( var, src_seg, src_off )                               \
102         do {                                                                  \
103                 var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
104         } while ( 0 )
105 #define copy_to_real copy_to_real_librm
106 #define copy_from_real copy_from_real_librm
107 #define put_real put_real_librm
108 #define get_real get_real_librm
109
110 /**
111  * A pointer to a user buffer
112  *
113  * Even though we could just use a void *, we use an intptr_t so that
114  * attempts to use normal pointers show up as compiler warnings.  Such
115  * code is actually valid for librm, but not for libkir (i.e. under
116  * KEEP_IT_REAL), so it's good to have the warnings even under librm.
117  */
118 typedef intptr_t userptr_t;
119
120 /**
121  * Add offset to user pointer
122  *
123  * @v ptr               User pointer
124  * @v offset            Offset
125  * @ret new_ptr         New pointer value
126  */
127 static inline __attribute__ (( always_inline )) userptr_t
128 userptr_add ( userptr_t ptr, off_t offset ) {
129         return ( ptr + offset );
130 }
131
132 /**
133  * Copy data to user buffer
134  *
135  * @v buffer            User buffer
136  * @v offset            Offset within user buffer
137  * @v src               Source
138  * @v len               Length
139  */
140 static inline __attribute__ (( always_inline )) void
141 copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
142         memcpy ( ( ( void * ) buffer + offset ), src, len );
143 }
144
145 /**
146  * Copy data from user buffer
147  *
148  * @v dest              Destination
149  * @v buffer            User buffer
150  * @v offset            Offset within user buffer
151  * @v len               Length
152  */
153 static inline __attribute__ (( always_inline )) void
154 copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
155         memcpy ( dest, ( ( void * ) buffer + offset ), len );
156 }
157
158 /**
159  * Copy data between user buffers
160  *
161  * @v dest              Destination user buffer
162  * @v dest_off          Offset within destination buffer
163  * @v src               Source user buffer
164  * @v src_off           Offset within source buffer
165  * @v len               Length
166  */
167 static inline __attribute__ (( always_inline )) void
168 memcpy_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
169               size_t len ) {
170         memcpy ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
171                  len );
172 }
173
174 /**
175  * Copy data between user buffers, allowing for overlap
176  *
177  * @v dest              Destination user buffer
178  * @v dest_off          Offset within destination buffer
179  * @v src               Source user buffer
180  * @v src_off           Offset within source buffer
181  * @v len               Length
182  */
183 static inline __attribute__ (( always_inline )) void
184 memmove_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
185                size_t len ) {
186         memmove ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
187                   len );
188 }
189
190 /**
191  * Fill user buffer with a constant byte
192  *
193  * @v buffer            User buffer
194  * @v offset            Offset within buffer
195  * @v c                 Constant byte with which to fill
196  * @v len               Length
197  */
198 static inline __attribute__ (( always_inline )) void
199 memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
200         memset ( ( ( void * ) buffer + offset ), c, len );
201 }
202
203 /**
204  * Find length of NUL-terminated string in user buffer
205  *
206  * @v buffer            User buffer
207  * @v offset            Offset within buffer
208  * @ret len             Length of string (excluding NUL)
209  */
210 static inline __attribute__ (( always_inline )) size_t
211 strlen_user ( userptr_t buffer, off_t offset ) {
212         return strlen ( ( void * ) buffer + offset );
213 }
214
215 /**
216  * Find character in user buffer
217  *
218  * @v buffer            User buffer
219  * @v offset            Starting offset within buffer
220  * @v c                 Character to search for
221  * @v len               Length of user buffer
222  * @ret offset          Offset of character, or <0 if not found
223  */
224 static inline __attribute__ (( always_inline )) off_t
225 memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
226         void *found;
227
228         found = memchr ( ( ( void * ) buffer + offset ), c, len );
229         return ( found ? ( found - ( void * ) buffer ) : -1 );
230 }
231
232 /**
233  * Convert virtual address to user buffer
234  *
235  * @v virtual           Virtual address
236  * @ret buffer          User buffer
237  *
238  * This constructs a user buffer from an ordinary pointer.  Use it
239  * when you need to pass a pointer to an internal buffer to a function
240  * that expects a @c userptr_t.
241  */
242 static inline __attribute__ (( always_inline )) userptr_t
243 virt_to_user ( void * virtual ) {
244         return ( ( intptr_t ) virtual );
245 }
246
247 /**
248  * Convert segment:offset address to user buffer
249  *
250  * @v segment           Real-mode segment
251  * @v offset            Real-mode offset
252  * @ret buffer          User buffer
253  */
254 static inline __attribute__ (( always_inline )) userptr_t
255 real_to_user ( unsigned int segment, unsigned int offset ) {
256         return virt_to_user ( VIRTUAL ( segment, offset ) );
257 }
258
259 /**
260  * Convert physical address to user buffer
261  *
262  * @v physical          Physical address
263  * @ret buffer          User buffer
264  */
265 static inline __attribute__ (( always_inline )) userptr_t
266 phys_to_user ( physaddr_t physical ) {
267         return virt_to_user ( phys_to_virt ( physical ) );
268 }
269
270 /**
271  * Convert user buffer to physical address
272  *
273  * @v buffer            User buffer
274  * @v offset            Offset within user buffer
275  * @ret physical        Physical address
276  */
277 static inline __attribute__ (( always_inline )) physaddr_t
278 user_to_phys ( userptr_t buffer, off_t offset ) {
279         return virt_to_phys ( ( void * ) buffer + offset );
280 }
281
282 /* TEXT16_CODE: declare a fragment of code that resides in .text16 */
283 #define TEXT16_CODE( asm_code_str )                     \
284         ".section \".text16\", \"ax\", @progbits\n\t"   \
285         ".code16\n\t"                                   \
286         asm_code_str "\n\t"                             \
287         ".code32\n\t"                                   \
288         ".previous\n\t"
289
290 /* REAL_CODE: declare a fragment of code that executes in real mode */
291 #define REAL_CODE( asm_code_str )                       \
292         "pushl $1f\n\t"                                 \
293         "call real_call\n\t"                            \
294         "addl $4, %%esp\n\t"                            \
295         TEXT16_CODE ( "\n1:\n\t"                        \
296                       asm_code_str                      \
297                       "\n\t"                            \
298                       "ret\n\t" )
299
300 /* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
301 #define PHYS_CODE( asm_code_str )                       \
302         "call _virt_to_phys\n\t"                        \
303         asm_code_str                                    \
304         "call _phys_to_virt\n\t"
305
306 #endif /* ASSEMBLY */
307
308 #endif /* LIBRM_H */