1#ifndef LIBRM_H
2#define LIBRM_H
3
4FILE_LICENCE ( GPL2_OR_LATER );
5
6/* Segment selectors as used in our protected-mode GDTs.
7 *
8 * Don't change these unless you really know what you're doing.
9 */
10
11#define VIRTUAL_CS 0x08
12#define VIRTUAL_DS 0x10
13#define PHYSICAL_CS 0x18
14#define PHYSICAL_DS 0x20
15#define REAL_CS 0x28
16#define REAL_DS 0x30
17#if 0
18#define LONG_CS 0x38
19#define LONG_DS 0x40
20#endif
21
22#ifndef ASSEMBLY
23
24#ifdef UACCESS_LIBRM
25#define UACCESS_PREFIX_librm
26#else
27#define UACCESS_PREFIX_librm __librm_
28#endif
29
30/* Variables in librm.S */
31extern unsigned long virt_offset;
32
33/**
34 * Convert physical address to user pointer
35 *
36 * @v phys_addr		Physical address
37 * @ret userptr		User pointer
38 */
39static inline __always_inline userptr_t
40UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
41	return ( phys_addr - virt_offset );
42}
43
44/**
45 * Convert user buffer to physical address
46 *
47 * @v userptr		User pointer
48 * @v offset		Offset from user pointer
49 * @ret phys_addr	Physical address
50 */
51static inline __always_inline unsigned long
52UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
53	return ( userptr + offset + virt_offset );
54}
55
56static inline __always_inline userptr_t
57UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
58	return trivial_virt_to_user ( addr );
59}
60
61static inline __always_inline void *
62UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
63	return trivial_user_to_virt ( userptr, offset );
64}
65
66static inline __always_inline userptr_t
67UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
68	return trivial_userptr_add ( userptr, offset );
69}
70
71static inline __always_inline void
72UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
73					userptr_t src, off_t src_off,
74					size_t len ) {
75	trivial_memcpy_user ( dest, dest_off, src, src_off, len );
76}
77
78static inline __always_inline void
79UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
80					 userptr_t src, off_t src_off,
81					 size_t len ) {
82	trivial_memmove_user ( dest, dest_off, src, src_off, len );
83}
84
85static inline __always_inline void
86UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
87					int c, size_t len ) {
88	trivial_memset_user ( buffer, offset, c, len );
89}
90
91static inline __always_inline size_t
92UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
93	return trivial_strlen_user ( buffer, offset );
94}
95
96static inline __always_inline off_t
97UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
98					int c, size_t len ) {
99	return trivial_memchr_user ( buffer, offset, c, len );
100}
101
102
103/******************************************************************************
104 *
105 * Access to variables in .data16 and .text16
106 *
107 */
108
109extern char *data16;
110extern char *text16;
111
112#define __data16( variable )						\
113	__attribute__ (( section ( ".data16" ) ))			\
114	_data16_ ## variable __asm__ ( #variable )
115
116#define __data16_array( variable, array )				\
117	__attribute__ (( section ( ".data16" ) ))			\
118	_data16_ ## variable array __asm__ ( #variable )
119
120#define __bss16( variable )						\
121	__attribute__ (( section ( ".bss16" ) ))			\
122	_data16_ ## variable __asm__ ( #variable )
123
124#define __bss16_array( variable, array )				\
125	__attribute__ (( section ( ".bss16" ) ))			\
126	_data16_ ## variable array __asm__ ( #variable )
127
128#define __text16( variable )						\
129	__attribute__ (( section ( ".text16.data" ) ))			\
130	_text16_ ## variable __asm__ ( #variable )
131
132#define __text16_array( variable, array )				\
133	__attribute__ (( section ( ".text16.data" ) ))			\
134	_text16_ ## variable array __asm__ ( #variable )
135
136#define __use_data16( variable )					\
137	( * ( ( typeof ( _data16_ ## variable ) * )			\
138	      & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
139
140#define __use_text16( variable )					\
141	( * ( ( typeof ( _text16_ ## variable ) * )			\
142	      & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
143
144#define __from_data16( pointer )					\
145	( ( unsigned int )						\
146	  ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
147
148#define __from_text16( pointer )					\
149	( ( unsigned int )						\
150	  ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
151
152/* Variables in librm.S, present in the normal data segment */
153extern uint16_t rm_sp;
154extern uint16_t rm_ss;
155extern uint16_t __data16 ( rm_cs );
156#define rm_cs __use_data16 ( rm_cs )
157extern uint16_t __text16 ( rm_ds );
158#define rm_ds __use_text16 ( rm_ds )
159
160/* Functions that librm expects to be able to link to.  Included here
161 * so that the compiler will catch prototype mismatches.
162 */
163extern void gateA20_set ( void );
164
165/**
166 * Convert segment:offset address to user buffer
167 *
168 * @v segment		Real-mode segment
169 * @v offset		Real-mode offset
170 * @ret buffer		User buffer
171 */
172static inline __always_inline userptr_t
173real_to_user ( unsigned int segment, unsigned int offset ) {
174	return ( phys_to_user ( ( segment << 4 ) + offset ) );
175}
176
177extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
178extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
179
180/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
181#define TEXT16_CODE( asm_code_str )			\
182	".section \".text16\", \"ax\", @progbits\n\t"	\
183	".code16\n\t"					\
184	asm_code_str "\n\t"				\
185	".code32\n\t"					\
186	".previous\n\t"
187
188/* REAL_CODE: declare a fragment of code that executes in real mode */
189#define REAL_CODE( asm_code_str )			\
190	"pushl $1f\n\t"					\
191	"call real_call\n\t"				\
192	"addl $4, %%esp\n\t"				\
193	TEXT16_CODE ( "\n1:\n\t"			\
194		      asm_code_str			\
195		      "\n\t"				\
196		      "ret\n\t" )
197
198/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
199#define PHYS_CODE( asm_code_str )			\
200	"call _virt_to_phys\n\t"			\
201	asm_code_str					\
202	"call _phys_to_virt\n\t"
203
204#endif /* ASSEMBLY */
205
206#endif /* LIBRM_H */
207