Explorar el Código

[uaccess] Formalise the uaccess API

The userptr_t is now the fundamental type that gets used for conversions.
For example, virt_to_phys() is implemented in terms of virt_to_user() and
user_to_phys().
tags/v0.9.6
Michael Brown hace 15 años
padre
commit
6554b79ff9

+ 1
- 1
src/arch/i386/core/gdbidt.S Ver fichero

@@ -2,7 +2,7 @@
2 2
  * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
3 3
  */
4 4
 
5
-#include <virtaddr.h>
5
+#include <librm.h>
6 6
 
7 7
 #define SIZEOF_I386_REGS	32
8 8
 #define SIZEOF_I386_FLAGS	4

+ 1
- 1
src/arch/i386/core/gdbmach.c Ver fichero

@@ -19,7 +19,7 @@
19 19
 #include <stddef.h>
20 20
 #include <stdio.h>
21 21
 #include <assert.h>
22
-#include <virtaddr.h>
22
+#include <gpxe/uaccess.h>
23 23
 #include <gpxe/gdbstub.h>
24 24
 #include <gdbmach.h>
25 25
 

+ 1
- 0
src/arch/i386/core/pic8259.c Ver fichero

@@ -16,6 +16,7 @@
16 16
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18 18
 
19
+#include <gpxe/io.h>
19 20
 #include <pic8259.h>
20 21
 
21 22
 /** @file

+ 0
- 325
src/arch/i386/core/start32.S Ver fichero

@@ -1,325 +0,0 @@
1
-#include "virtaddr.h"
2
-	
3
-	.equ	MSR_K6_EFER,   0xC0000080
4
-	.equ	EFER_LME,      0x00000100
5
-	.equ	X86_CR4_PAE,   0x00000020
6
-	.equ	CR0_PG,        0x80000000
7
-
8
-#ifdef	GAS291
9
-#define DATA32 data32;
10
-#define ADDR32 addr32;
11
-#define	LJMPI(x)	ljmp	x
12
-#else
13
-#define DATA32 data32
14
-#define ADDR32 addr32
15
-/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */
16
-#define	LJMPI(x)	ljmp	x
17
-#endif
18
-
19
-/*
20
- * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
21
- * then you only have to take care of %ebx, %esi, %edi and %ebp.  These
22
- * registers must not be altered under any circumstance.  All other registers
23
- * may be clobbered without any negative side effects.  If you don't follow
24
- * this rule then you'll run into strange effects that only occur on some
25
- * gcc versions (because the register allocator may use different registers).
26
- *
27
- * All the data32 prefixes for the ljmp instructions are necessary, because
28
- * the assembler emits code with a relocation address of 0.  This means that
29
- * all destinations are initially negative, which the assembler doesn't grok,
30
- * because for some reason negative numbers don't fit into 16 bits. The addr32
31
- * prefixes are there for the same reasons, because otherwise the memory
32
- * references are only 16 bit wide.  Theoretically they are all superfluous.
33
- * One last note about prefixes: the data32 prefixes on all call _real_to_prot
34
- * instructions could be removed if the _real_to_prot function is changed to
35
- * deal correctly with 16 bit return addresses.  I tried it, but failed.
36
- */
37
-
38
-	.text
39
-	.arch i386
40
-	.code32
41
-
42
-	/* This is a struct os_entry_regs */
43
-	.globl os_regs
44
-os_regs:	.space 56
45
-		
46
-/**************************************************************************
47
-XSTART32 - Transfer control to the kernel just loaded
48
-**************************************************************************/
49
-	.globl xstart32
50
-xstart32:
51
-	/* Save the callee save registers */
52
-	movl	%ebp, os_regs + 32
53
-	movl	%esi, os_regs + 36
54
-	movl	%edi, os_regs + 40
55
-	movl	%ebx, os_regs + 44
56
-
57
-	/* save the return address */
58
-	popl	%eax
59
-	movl	%eax, os_regs + 48
60
-
61
-	/* save the stack pointer */
62
-	movl	%esp, os_regs + 52
63
-
64
-	/* Get the new destination address */
65
-	popl	%ecx
66
-
67
-	/* Store the physical address of xend on the stack */
68
-	movl	$xend32, %ebx
69
-	addl	virt_offset, %ebx
70
-	pushl	%ebx
71
-
72
-	/* Store the destination address on the stack */
73
-	pushl	$PHYSICAL_CS
74
-	pushl	%ecx
75
-
76
-	/* Cache virt_offset */
77
-	movl	virt_offset, %ebp
78
-	
79
-	/* Switch to using physical addresses */
80
-	call	_virt_to_phys
81
-
82
-	/* Save the target stack pointer */
83
-	movl	%esp, os_regs + 12(%ebp)
84
-	leal	os_regs(%ebp), %esp
85
-
86
-	/* Store the pointer to os_regs */
87
-	movl	%esp, os_regs_ptr(%ebp)
88
-
89
-	/* Load my new registers */
90
-	popal
91
-	movl	(-32 + 12)(%esp), %esp
92
-
93
-	/* Jump to the new kernel
94
-	 * The lret switches to a flat code segment
95
-	 */
96
-	lret
97
-
98
-	.balign 4
99
-	.globl xend32
100
-xend32:
101
-	/* Fixup %eflags */
102
-	nop
103
-	cli
104
-	cld
105
-	
106
-	/* Load %esp with &os_regs + virt_offset */
107
-	.byte	0xbc /* movl $0, %esp */
108
-os_regs_ptr:
109
-	.long	0
110
-
111
-	/* Save the result registers */
112
-	addl	$32, %esp
113
-	pushal
114
-
115
-	/* Compute virt_offset */
116
-	movl	%esp, %ebp
117
-	subl	$os_regs, %ebp
118
-	
119
-	/* Load the stack pointer and convert it to physical address */
120
-	movl	52(%esp), %esp
121
-	addl	%ebp, %esp
122
-
123
-	/* Enable the virtual addresses */
124
-	leal	_phys_to_virt(%ebp), %eax
125
-	call	*%eax
126
-
127
-	/* Restore the callee save registers */
128
-	movl	os_regs + 32, %ebp
129
-	movl	os_regs + 36, %esi
130
-	movl	os_regs + 40, %edi
131
-	movl	os_regs + 44, %ebx
132
-	movl	os_regs + 48, %edx
133
-	movl	os_regs + 52, %esp
134
-
135
-	/* Get the C return value */
136
-	movl	os_regs + 28, %eax
137
-
138
-	jmpl	*%edx
139
-
140
-#ifdef CONFIG_X86_64
141
-	.arch	sledgehammer
142
-/**************************************************************************
143
-XSTART_lm - Transfer control to the kernel just loaded in long mode
144
-**************************************************************************/
145
-	.globl xstart_lm
146
-xstart_lm:
147
-	/* Save the callee save registers */
148
-	pushl	%ebp
149
-	pushl	%esi
150
-	pushl	%edi
151
-	pushl	%ebx
152
-
153
-	/* Cache virt_offset && (virt_offset & 0xfffff000) */
154
-	movl	virt_offset, %ebp
155
-	movl	%ebp, %ebx
156
-	andl	$0xfffff000, %ebx
157
-
158
-	/* Switch to using physical addresses */
159
-	call	_virt_to_phys
160
-
161
-	/* Initialize the page tables */
162
-	/* Level 4 */
163
-	leal	0x23 + pgt_level3(%ebx), %eax
164
-	leal	pgt_level4(%ebx), %edi
165
-	movl	%eax, (%edi)
166
-
167
-	/* Level 3 */
168
-	leal	0x23 + pgt_level2(%ebx), %eax
169
-	leal	pgt_level3(%ebx), %edi
170
-	movl	%eax, 0x00(%edi)
171
-	addl	$4096, %eax
172
-	movl	%eax, 0x08(%edi)
173
-	addl	$4096, %eax
174
-	movl	%eax, 0x10(%edi)
175
-	addl	$4096, %eax
176
-	movl	%eax, 0x18(%edi)
177
-
178
-	/* Level 2 */
179
-	movl	$0xe3, %eax
180
-	leal	pgt_level2(%ebx), %edi
181
-	leal	16384(%edi), %esi
182
-pgt_level2_loop:
183
-	movl	%eax, (%edi)
184
-	addl	$8, %edi
185
-	addl	$0x200000, %eax
186
-	cmp	%esi, %edi
187
-	jne	pgt_level2_loop
188
-
189
-	/* Point at the x86_64 page tables */
190
-	leal	pgt_level4(%ebx), %edi
191
-	movl	%edi, %cr3
192
-
193
-
194
-	/* Setup for the return from 64bit mode */
195
-	/* 64bit align the stack */
196
-	movl	%esp, %ebx		/* original stack pointer + 16 */
197
-	andl	$0xfffffff8, %esp
198
-
199
-	/* Save original stack pointer + 16 */
200
-	pushl	%ebx
201
-
202
-	/* Save virt_offset */
203
-	pushl	%ebp
204
-
205
-	/* Setup for the jmp to 64bit long mode */
206
-	leal	start_lm(%ebp), %eax
207
-	movl	%eax, 0x00 + start_lm_addr(%ebp)
208
-	movl	$LM_CODE_SEG, %eax
209
-	movl	%eax, 0x04 + start_lm_addr(%ebp)
210
-
211
-	/* Setup for the jump out of 64bit long mode */
212
-	leal	end_lm(%ebp), %eax
213
-	movl	%eax, 0x00 + end_lm_addr(%ebp)
214
-	movl	$FLAT_CODE_SEG, %eax
215
-	movl	%eax, 0x04 + end_lm_addr(%ebp)
216
-
217
-	/* Enable PAE mode */
218
-	movl	%cr4, %eax
219
-	orl	$X86_CR4_PAE, %eax
220
-	movl	%eax, %cr4
221
-
222
-	/* Enable long mode */
223
-	movl	$MSR_K6_EFER, %ecx
224
-	rdmsr
225
-	orl	$EFER_LME, %eax
226
-	wrmsr
227
-
228
-	/* Start paging, entering 32bit compatiblity mode */
229
-	movl	%cr0, %eax
230
-	orl	$CR0_PG, %eax
231
-	movl	%eax, %cr0
232
-
233
-	/* Enter 64bit long mode */
234
-	ljmp	*start_lm_addr(%ebp)
235
-	.code64
236
-start_lm:
237
-	/* Load 64bit data segments */
238
-	movl	$LM_DATA_SEG, %eax
239
-	movl	%eax, %ds
240
-	movl	%eax, %es
241
-	movl	%eax, %ss
242
-
243
-	andq	$0xffffffff, %rbx
244
-	/* Get the address to jump to */
245
-	movl	20(%rbx), %edx
246
-	andq	$0xffffffff, %rdx
247
-	
248
-	/* Get the argument pointer */
249
-	movl	24(%rbx), %ebx
250
-	andq	$0xffffffff, %rbx
251
-
252
-	/* Jump to the 64bit code */
253
-	call	*%rdx
254
-
255
-	/* Preserve the result */
256
-	movl	%eax, %edx
257
-
258
-	/* Fixup %eflags */
259
-	cli
260
-	cld
261
-
262
-	/* Switch to 32bit compatibility mode */
263
-	ljmp	*end_lm_addr(%rip)
264
-
265
-	.code32
266
-end_lm:
267
-	/* Disable paging */
268
-	movl	%cr0, %eax
269
-	andl	$~CR0_PG, %eax
270
-	movl	%eax, %cr0
271
-
272
-	/* Disable long mode */
273
-	movl	$MSR_K6_EFER, %ecx
274
-	rdmsr
275
-	andl	$~EFER_LME, %eax
276
-	wrmsr
277
-
278
-	/* Disable PAE */
279
-	movl	%cr4, %eax
280
-	andl	$~X86_CR4_PAE, %eax
281
-	movl	%eax, %cr4
282
-	
283
-	/* Compute virt_offset */
284
-	popl	%ebp
285
-
286
-	/* Compute the original stack pointer + 16 */
287
-	popl	%ebx
288
-	movl	%ebx, %esp
289
-
290
-	/* Enable the virtual addresses */
291
-	leal	_phys_to_virt(%ebp), %eax
292
-	call	*%eax
293
-
294
-	/* Restore the callee save registers */
295
-	popl	%ebx
296
-	popl	%esi
297
-	popl	%edi
298
-	popl	%ebp
299
-
300
-	/* Get the C return value */
301
-	movl	%edx, %eax
302
-
303
-	/* Return */
304
-	ret
305
-
306
-	.arch i386
307
-#endif /* CONFIG_X86_64 */
308
-
309
-#ifdef CONFIG_X86_64
310
-	.section ".bss"
311
-	.p2align 12
312
-	/* Include a dummy space in case we are loaded badly aligned */
313
-	.space 4096
314
-	/* Reserve enough space for a page table convering 4GB with 2MB pages */
315
-pgt_level4:	
316
-	.space 4096
317
-pgt_level3:	
318
-	.space 4096
319
-pgt_level2:	
320
-	.space 16384
321
-start_lm_addr:
322
-	.space	8
323
-end_lm_addr:
324
-	.space	8
325
-#endif

+ 1
- 1
src/arch/i386/core/virtaddr.S Ver fichero

@@ -4,7 +4,7 @@
4 4
  *
5 5
  */
6 6
 
7
-#include "virtaddr.h"
7
+#include "librm.h"
8 8
 		
9 9
 	.arch i386
10 10
 	.text

+ 2
- 4
src/arch/i386/core/x86_io.c Ver fichero

@@ -65,10 +65,8 @@ static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
65 65
 			       : : "A" ( data ), "r" ( io_addr ) );
66 66
 }
67 67
 
68
-PROVIDE_IOAPI_INLINE ( x86, virt_to_phys );
69
-PROVIDE_IOAPI_INLINE ( x86, phys_to_virt );
70
-PROVIDE_IOAPI_INLINE ( x86, virt_to_bus );
71
-PROVIDE_IOAPI_INLINE ( x86, bus_to_virt );
68
+PROVIDE_IOAPI_INLINE ( x86, phys_to_bus );
69
+PROVIDE_IOAPI_INLINE ( x86, bus_to_phys );
72 70
 PROVIDE_IOAPI_INLINE ( x86, ioremap );
73 71
 PROVIDE_IOAPI_INLINE ( x86, iounmap );
74 72
 PROVIDE_IOAPI_INLINE ( x86, io_to_bus );

+ 1
- 0
src/arch/i386/drivers/net/undinet.c Ver fichero

@@ -23,6 +23,7 @@
23 23
 #include <biosint.h>
24 24
 #include <pnpbios.h>
25 25
 #include <basemem_packet.h>
26
+#include <gpxe/io.h>
26 27
 #include <gpxe/iobuf.h>
27 28
 #include <gpxe/netdevice.h>
28 29
 #include <gpxe/if_ether.h>

+ 1
- 0
src/arch/i386/firmware/pcbios/gateA20.c Ver fichero

@@ -1,6 +1,7 @@
1 1
 #include <stdio.h>
2 2
 #include <realmode.h>
3 3
 #include <bios.h>
4
+#include <gpxe/io.h>
4 5
 #include <gpxe/timer.h>
5 6
 
6 7
 #define K_RDWR		0x60		/* keyboard data & cmds (read/write) */

+ 7
- 1
src/arch/i386/include/bits/uaccess.h Ver fichero

@@ -1,6 +1,12 @@
1 1
 #ifndef _BITS_UACCESS_H
2 2
 #define _BITS_UACCESS_H
3 3
 
4
-#include <realmode.h>
4
+/** @file
5
+ *
6
+ * i386-specific user access API implementations
7
+ *
8
+ */
9
+
10
+#include <librm.h>
5 11
 
6 12
 #endif /* _BITS_UACCESS_H */

+ 9
- 16
src/arch/i386/include/gpxe/x86_io.h Ver fichero

@@ -15,8 +15,6 @@
15 15
  * into a machine with such an old CPU anyway.
16 16
  */
17 17
 
18
-#include <virtaddr.h>
19
-
20 18
 #ifdef IOAPI_X86
21 19
 #define IOAPI_PREFIX_x86
22 20
 #else
@@ -28,24 +26,19 @@
28 26
  *
29 27
  */
30 28
 
31
-static inline __always_inline unsigned long
32
-IOAPI_INLINE ( x86, virt_to_phys ) ( volatile const void *addr ) {
33
-	return ( ( ( unsigned long ) addr ) + virt_offset );
34
-}
35
-
36
-static inline __always_inline void *
37
-IOAPI_INLINE ( x86, phys_to_virt ) ( unsigned long phys_addr ) {
38
-	return ( ( void * ) ( phys_addr - virt_offset ) );
39
-}
29
+/*
30
+ * Physical<->Bus and Bus<->I/O address mappings
31
+ *
32
+ */
40 33
 
41 34
 static inline __always_inline unsigned long
42
-IOAPI_INLINE ( x86, virt_to_bus ) ( volatile const void *addr ) {
43
-	return virt_to_phys ( addr );
35
+IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
36
+	return phys_addr;
44 37
 }
45 38
 
46
-static inline __always_inline void *
47
-IOAPI_INLINE ( x86, bus_to_virt ) ( unsigned long bus_addr ) {
48
-	return phys_to_virt ( bus_addr );
39
+static inline __always_inline unsigned long
40
+IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
41
+	return bus_addr;
49 42
 }
50 43
 
51 44
 static inline __always_inline void *

+ 1
- 0
src/arch/i386/include/int13.h Ver fichero

@@ -9,6 +9,7 @@
9 9
 
10 10
 #include <stdint.h>
11 11
 #include <gpxe/list.h>
12
+#include <realmode.h>
12 13
 
13 14
 struct block_device;
14 15
 

+ 98
- 205
src/arch/i386/include/librm.h Ver fichero

@@ -1,21 +1,109 @@
1 1
 #ifndef LIBRM_H
2 2
 #define LIBRM_H
3 3
 
4
-/* Drag in protected-mode segment selector values */
5
-#include "virtaddr.h"
6
-#include "realmode.h"
4
+/* Segment selectors as used in our protected-mode GDTs.
5
+ *
6
+ * Don't change these unless you really know what you're doing.
7
+ */
8
+
9
+#define VIRTUAL_CS 0x08
10
+#define VIRTUAL_DS 0x10
11
+#define PHYSICAL_CS 0x18
12
+#define PHYSICAL_DS 0x20
13
+#define REAL_CS 0x28
14
+#define REAL_DS 0x30
15
+#if 0
16
+#define LONG_CS 0x38
17
+#define LONG_DS 0x40
18
+#endif
7 19
 
8 20
 #ifndef ASSEMBLY
9 21
 
10
-#include "stddef.h"
11
-#include "string.h"
22
+#ifdef UACCESS_LIBRM
23
+#define UACCESS_PREFIX_librm
24
+#else
25
+#define UACCESS_PREFIX_librm __librm_
26
+#endif
27
+
28
+/* Variables in librm.S */
29
+extern unsigned long virt_offset;
30
+
31
+/**
32
+ * Convert physical address to user pointer
33
+ *
34
+ * @v phys_addr		Physical address
35
+ * @ret userptr		User pointer
36
+ */
37
+static inline __always_inline userptr_t
38
+UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
39
+	return ( phys_addr - virt_offset );
40
+}
12 41
 
13
-/*
14
- * Data structures and type definitions
42
+/**
43
+ * Convert user buffer to physical address
44
+ *
45
+ * @v userptr		User pointer
46
+ * @v offset		Offset from user pointer
47
+ * @ret phys_addr	Physical address
48
+ */
49
+static inline __always_inline unsigned long
50
+UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
51
+	return ( userptr + offset + virt_offset );
52
+}
53
+
54
+static inline __always_inline userptr_t
55
+UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
56
+	return trivial_virt_to_user ( addr );
57
+}
58
+
59
+static inline __always_inline void *
60
+UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
61
+	return trivial_user_to_virt ( userptr, offset );
62
+}
63
+
64
+static inline __always_inline userptr_t
65
+UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
66
+	return trivial_userptr_add ( userptr, offset );
67
+}
68
+
69
+static inline __always_inline void
70
+UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
71
+					userptr_t src, off_t src_off,
72
+					size_t len ) {
73
+	trivial_memcpy_user ( dest, dest_off, src, src_off, len );
74
+}
75
+
76
+static inline __always_inline void
77
+UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
78
+					 userptr_t src, off_t src_off,
79
+					 size_t len ) {
80
+	trivial_memmove_user ( dest, dest_off, src, src_off, len );
81
+}
82
+
83
+static inline __always_inline void
84
+UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
85
+					int c, size_t len ) {
86
+	trivial_memset_user ( buffer, offset, c, len );
87
+}
88
+
89
+static inline __always_inline size_t
90
+UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
91
+	return trivial_strlen_user ( buffer, offset );
92
+}
93
+
94
+static inline __always_inline off_t
95
+UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
96
+					int c, size_t len ) {
97
+	return trivial_memchr_user ( buffer, offset, c, len );
98
+}
99
+
100
+
101
+/******************************************************************************
102
+ *
103
+ * Access to variables in .data16 and .text16
15 104
  *
16 105
  */
17 106
 
18
-/* Access to variables in .data16 and .text16 */
19 107
 extern char *data16;
20 108
 extern char *text16;
21 109
 
@@ -72,178 +160,6 @@ extern uint16_t __text16 ( rm_ds );
72 160
  */
73 161
 extern void gateA20_set ( void );
74 162
 
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 163
 /**
248 164
  * Convert segment:offset address to user buffer
249 165
  *
@@ -251,32 +167,9 @@ virt_to_user ( void * virtual ) {
251 167
  * @v offset		Real-mode offset
252 168
  * @ret buffer		User buffer
253 169
  */
254
-static inline __attribute__ (( always_inline )) userptr_t
170
+static inline __always_inline userptr_t
255 171
 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 );
172
+	return ( phys_to_user ( ( segment << 4 ) + offset ) );
280 173
 }
281 174
 
282 175
 extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );

+ 0
- 17
src/arch/i386/include/pxe_addr.h Ver fichero

@@ -1,17 +0,0 @@
1
-/*
2
- * Architecture-specific portion of pxe.h for Etherboot
3
- *
4
- * This file has to define the types SEGOFF16_t, SEGDESC_t and
5
- * SEGSEL_t for use in other PXE structures.  See pxe.h for details.
6
- */
7
-
8
-#ifndef PXE_ADDR_H
9
-#define PXE_ADDR_H
10
-
11
-#define IS_NULL_SEGOFF16(x) ( ( (x).segment == 0 ) && ( (x).offset == 0 ) )
12
-#define SEGOFF16_TO_PTR(x) ( VIRTUAL( (x).segment, (x).offset ) )
13
-#define PTR_TO_SEGOFF16(ptr,segoff16) \
14
-	(segoff16).segment = SEGMENT(ptr); \
15
-	(segoff16).offset  = OFFSET(ptr);
16
-
17
-#endif /* PXE_ADDR_H */

+ 45
- 48
src/arch/i386/include/realmode.h Ver fichero

@@ -1,45 +1,15 @@
1 1
 #ifndef REALMODE_H
2 2
 #define REALMODE_H
3 3
 
4
-#ifndef ASSEMBLY
5
-
6
-#include "stdint.h"
7
-#include "registers.h"
8
-#include <gpxe/io.h>
4
+#include <stdint.h>
5
+#include <registers.h>
6
+#include <gpxe/uaccess.h>
9 7
 
10 8
 /*
11 9
  * Data structures and type definitions
12 10
  *
13 11
  */
14 12
 
15
-/* Segment:offset structure.  Note that the order within the structure
16
- * is offset:segment.
17
- */
18
-struct segoff {
19
-	uint16_t offset;
20
-	uint16_t segment;
21
-} __attribute__ (( packed ));
22
-
23
-typedef struct segoff segoff_t;
24
-
25
-/* Macro hackery needed to stringify bits of inline assembly */
26
-#define RM_XSTR(x) #x
27
-#define RM_STR(x) RM_XSTR(x)
28
-
29
-/* Drag in the selected real-mode transition library header */
30
-#ifdef KEEP_IT_REAL
31
-#include "libkir.h"
32
-#else
33
-#include "librm.h"
34
-#endif
35
-
36
-/*
37
- * The API to some functions is identical between librm and libkir, so
38
- * they are documented here, even though the prototypes are in librm.h
39
- * and libkir.h.
40
- *
41
- */
42
-
43 13
 /*
44 14
  * Declaration of variables in .data16
45 15
  *
@@ -92,24 +62,53 @@ typedef struct segoff segoff_t;
92 62
  * assembler output to make sure that it's doing the right thing.
93 63
  */
94 64
 
95
-/*
96
- * void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
97
- *		       void *src, size_t n )
98
- * void copy_from_real ( void *dest, uint16_t src_seg, uint16_t src_off,
99
- *			 size_t n )
65
+/**
66
+ * Copy data to base memory
100 67
  *
101
- * These functions can be used to copy data to and from arbitrary
102
- * locations in base memory.
68
+ * @v dest_seg		Destination segment
69
+ * @v dest_off		Destination offset
70
+ * @v src		Source
71
+ * @v len		Length
103 72
  */
73
+static inline __always_inline void
74
+copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
75
+	       void *src, size_t n ) {
76
+	copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
77
+}
104 78
 
105
-/*
106
- * put_real ( variable, uint16_t dest_seg, uint16_t dest_off )
107
- * get_real ( variable, uint16_t src_seg, uint16_t src_off )
79
+/**
80
+ * Copy data to base memory
81
+ *
82
+ * @v dest		Destination
83
+ * @v src_seg		Source segment
84
+ * @v src_off		Source offset
85
+ * @v len		Length
86
+ */
87
+static inline __always_inline void
88
+copy_from_real ( void *dest, unsigned int src_seg,
89
+		 unsigned int src_off, size_t n ) {
90
+	copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
91
+}
92
+
93
+/**
94
+ * Write a single variable to base memory
108 95
  *
109
- * These macros can be used to read or write single variables to and
110
- * from arbitrary locations in base memory.  "variable" must be a
111
- * variable of either 1, 2 or 4 bytes in length.
96
+ * @v var		Variable to write
97
+ * @v dest_seg		Destination segment
98
+ * @v dest_off		Destination offset
112 99
  */
100
+#define put_real( var, dest_seg, dest_off ) \
101
+	copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
102
+
103
+/**
104
+ * Read a single variable from base memory
105
+ *
106
+ * @v var		Variable to read
107
+ * @v src_seg		Source segment
108
+ * @v src_off		Source offset
109
+ */
110
+#define get_real( var, src_seg, src_off ) \
111
+	copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
113 112
 
114 113
 /*
115 114
  * REAL_CODE ( asm_code_str )
@@ -123,6 +122,4 @@ typedef struct segoff segoff_t;
123 122
  *
124 123
  */
125 124
 
126
-#endif /* ASSEMBLY */
127
-
128 125
 #endif /* REALMODE_H */

+ 11
- 2
src/arch/i386/include/registers.h Ver fichero

@@ -10,8 +10,7 @@
10 10
  *
11 11
  */
12 12
 
13
-#include "compiler.h" /* for doxygen */
14
-#include "stdint.h"
13
+#include <stdint.h>
15 14
 
16 15
 /**
17 16
  * A 16-bit general register.
@@ -184,4 +183,14 @@ struct i386_all_regs {
184 183
 #define SF ( 1 <<  7 )
185 184
 #define OF ( 1 << 11 )
186 185
 
186
+/* Segment:offset structure.  Note that the order within the structure
187
+ * is offset:segment.
188
+ */
189
+struct segoff {
190
+	uint16_t offset;
191
+	uint16_t segment;
192
+} PACKED;
193
+
194
+typedef struct segoff segoff_t;
195
+
187 196
 #endif /* REGISTERS_H */

+ 0
- 74
src/arch/i386/include/virtaddr.h Ver fichero

@@ -1,74 +0,0 @@
1
-#ifndef VIRTADDR_H
2
-#define VIRTADDR_H
3
-
4
-/* Segment selectors as used in our protected-mode GDTs.
5
- *
6
- * Don't change these unless you really know what you're doing.
7
- */
8
-
9
-#define VIRTUAL_CS 0x08
10
-#define VIRTUAL_DS 0x10
11
-#define PHYSICAL_CS 0x18
12
-#define PHYSICAL_DS 0x20
13
-#define REAL_CS 0x28
14
-#define REAL_DS 0x30
15
-#if 0
16
-#define LONG_CS 0x38
17
-#define LONG_DS 0x40
18
-#endif
19
-
20
-#ifndef ASSEMBLY
21
-
22
-#ifndef KEEP_IT_REAL
23
-
24
-/*
25
- * Without -DKEEP_IT_REAL, we are in 32-bit protected mode with a
26
- * fixed link address but an unknown physical start address.  Our GDT
27
- * sets up code and data segments with an offset of virt_offset, so
28
- * that link-time addresses can still work.
29
- *
30
- */
31
-
32
-/* Variables in virtaddr.S */
33
-extern unsigned long virt_offset;
34
-
35
-#else /* KEEP_IT_REAL */
36
-
37
-#include <stdint.h>
38
-
39
-/*
40
- * With -DKEEP_IT_REAL, we are in 16-bit real mode with fixed link
41
- * addresses and a segmented memory model.  We have separate code and
42
- * data segments.
43
- *
44
- * Because we may be called in 16-bit protected mode (damn PXE spec),
45
- * we cannot simply assume that physical = segment * 16 + offset.
46
- * Instead, we have to look up the physical start address of the
47
- * segment in the !PXE structure.  We have to assume that
48
- * virt_to_phys() is called only on pointers within the data segment,
49
- * because nothing passes segment information to us.
50
- *
51
- * We don't implement phys_to_virt at all, because there will be many
52
- * addresses that simply cannot be reached via a virtual address when
53
- * the virtual address space is limited to 64kB!
54
- */
55
-
56
-static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
57
-	/* Cheat: just for now, do the segment*16+offset calculation */
58
-	uint16_t ds;
59
-
60
-	__asm__ ( "movw %%ds, %%ax" : "=a" ( ds ) : );
61
-	return ( 16 * ds + ( ( unsigned long ) virt_addr ) );
62
-}
63
-
64
-/* Define it as a deprecated function so that we get compile-time
65
- * warnings, rather than just the link-time errors.
66
- */
67
-extern void * phys_to_virt ( unsigned long phys_addr )
68
-     __attribute__ ((deprecated));
69
-
70
-#endif /* KEEP_IT_REAL */
71
-
72
-#endif /* ASSEMBLY */
73
-
74
-#endif /* VIRTADDR_H */

+ 56
- 45
src/arch/i386/transitions/librm_mgmt.c Ver fichero

@@ -1,45 +1,56 @@
1
-/*
2
- * librm: a library for interfacing to real-mode code
3
- *
4
- * Michael Brown <mbrown@fensystems.co.uk>
5
- *
6
- */
7
-
8
-#include <stdint.h>
9
-#include <librm.h>
10
-
11
-/*
12
- * This file provides functions for managing librm.
13
- *
14
- */
15
-
16
-/**
17
- * Allocate space on the real-mode stack and copy data there from a
18
- * user buffer
19
- *
20
- * @v data			User buffer
21
- * @v size			Size of stack data
22
- * @ret sp			New value of real-mode stack pointer
23
- */
24
-uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
25
-	userptr_t rm_stack;
26
-	rm_sp -= size;
27
-	rm_stack = real_to_user ( rm_ss, rm_sp );
28
-	memcpy_user ( rm_stack, 0, data, 0, size );
29
-	return rm_sp;
30
-};
31
-
32
-/**
33
- * Deallocate space on the real-mode stack, optionally copying back
34
- * data to a user buffer.
35
- *
36
- * @v data			User buffer
37
- * @v size			Size of stack data
38
- */
39
-void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
40
-	if ( data ) {
41
-		userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
42
-		memcpy_user ( rm_stack, 0, data, 0, size );
43
-	}
44
-	rm_sp += size;
45
-};
1
+/*
2
+ * librm: a library for interfacing to real-mode code
3
+ *
4
+ * Michael Brown <mbrown@fensystems.co.uk>
5
+ *
6
+ */
7
+
8
+#include <stdint.h>
9
+#include <realmode.h>
10
+
11
+/*
12
+ * This file provides functions for managing librm.
13
+ *
14
+ */
15
+
16
+/**
17
+ * Allocate space on the real-mode stack and copy data there from a
18
+ * user buffer
19
+ *
20
+ * @v data			User buffer
21
+ * @v size			Size of stack data
22
+ * @ret sp			New value of real-mode stack pointer
23
+ */
24
+uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
25
+	userptr_t rm_stack;
26
+	rm_sp -= size;
27
+	rm_stack = real_to_user ( rm_ss, rm_sp );
28
+	memcpy_user ( rm_stack, 0, data, 0, size );
29
+	return rm_sp;
30
+};
31
+
32
+/**
33
+ * Deallocate space on the real-mode stack, optionally copying back
34
+ * data to a user buffer.
35
+ *
36
+ * @v data			User buffer
37
+ * @v size			Size of stack data
38
+ */
39
+void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
40
+	if ( data ) {
41
+		userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
42
+		memcpy_user ( rm_stack, 0, data, 0, size );
43
+	}
44
+	rm_sp += size;
45
+};
46
+
47
+PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
48
+PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
49
+PROVIDE_UACCESS_INLINE ( librm, virt_to_user );
50
+PROVIDE_UACCESS_INLINE ( librm, user_to_virt );
51
+PROVIDE_UACCESS_INLINE ( librm, userptr_add );
52
+PROVIDE_UACCESS_INLINE ( librm, memcpy_user );
53
+PROVIDE_UACCESS_INLINE ( librm, memmove_user );
54
+PROVIDE_UACCESS_INLINE ( librm, memset_user );
55
+PROVIDE_UACCESS_INLINE ( librm, strlen_user );
56
+PROVIDE_UACCESS_INLINE ( librm, memchr_user );

+ 1
- 0
src/config/defaults/pcbios.h Ver fichero

@@ -7,6 +7,7 @@
7 7
  *
8 8
  */
9 9
 
10
+#define UACCESS_LIBRM
10 11
 #define IOAPI_X86
11 12
 #define PCIAPI_PCBIOS
12 13
 #define TIMER_PCBIOS

+ 16
- 16
src/include/gpxe/io.h Ver fichero

@@ -19,6 +19,7 @@
19 19
 #include <stdint.h>
20 20
 #include <gpxe/api.h>
21 21
 #include <config/ioapi.h>
22
+#include <gpxe/uaccess.h>
22 23
 
23 24
 /**
24 25
  * Calculate static inline I/O API function name
@@ -149,24 +150,20 @@
149 150
 	} while ( 0 )
150 151
 
151 152
 /**
152
- * Convert virtual address to a physical address
153
+ * Convert physical address to a bus address
153 154
  *
154
- * @v addr		Virtual address
155
- * @ret phys_addr	Physical address
155
+ * @v phys_addr		Physical address
156
+ * @ret bus_addr	Bus address
156 157
  */
157
-unsigned long virt_to_phys ( volatile const void *addr );
158
+unsigned long phys_to_bus ( unsigned long phys_addr );
158 159
 
159 160
 /**
160
- * Convert physical address to a virtual address
161
+ * Convert bus address to a physical address
161 162
  *
162
- * @v addr		Virtual address
163
+ * @v bus_addr		Bus address
163 164
  * @ret phys_addr	Physical address
164
- *
165
- * This operation isn't actually valid within our memory model, and is
166
- * impossible to achieve under -DKEEP_IT_REAL.  Some drivers haven't
167
- * been updated to avoid it yet, though.
168 165
  */
169
-void * phys_to_virt ( unsigned long phys_addr );
166
+unsigned long bus_to_phys ( unsigned long bus_addr );
170 167
 
171 168
 /**
172 169
  * Convert virtual address to a bus address
@@ -174,7 +171,10 @@ void * phys_to_virt ( unsigned long phys_addr );
174 171
  * @v addr		Virtual address
175 172
  * @ret bus_addr	Bus address
176 173
  */
177
-unsigned long virt_to_bus ( volatile const void *addr );
174
+static inline __always_inline unsigned long
175
+virt_to_bus ( volatile const void *addr ) {
176
+	return phys_to_bus ( virt_to_phys ( addr ) );
177
+}
178 178
 
179 179
 /**
180 180
  * Convert bus address to a virtual address
@@ -182,11 +182,11 @@ unsigned long virt_to_bus ( volatile const void *addr );
182 182
  * @v bus_addr		Bus address
183 183
  * @ret addr		Virtual address
184 184
  *
185
- * This operation isn't actually valid within our memory model, and is
186
- * impossible to achieve under -DKEEP_IT_REAL.  Some drivers haven't
187
- * been updated to avoid it yet, though.
185
+ * This operation is not available under all memory models.
188 186
  */
189
-void * bus_to_virt ( unsigned long bus_addr );
187
+static inline __always_inline void * bus_to_virt ( unsigned long bus_addr ) {
188
+	return phys_to_virt ( bus_to_phys ( bus_addr ) );
189
+}
190 190
 
191 191
 /**
192 192
  * Map bus address as an I/O address

+ 315
- 1
src/include/gpxe/uaccess.h Ver fichero

@@ -19,9 +19,323 @@
19 19
  *
20 20
  */
21 21
 
22
-#include <bits/uaccess.h>
22
+#include <stdint.h>
23
+#include <string.h>
24
+#include <gpxe/api.h>
25
+#include <config/ioapi.h>
26
+
27
+/**
28
+ * A pointer to a user buffer
29
+ *
30
+ */
31
+typedef unsigned long userptr_t;
23 32
 
24 33
 /** Equivalent of NULL for user pointers */
25 34
 #define UNULL ( ( userptr_t ) 0 )
26 35
 
36
+/**
37
+ * @defgroup uaccess_trivial Trivial user access API implementations
38
+ *
39
+ * User access API implementations that can be used by environments in
40
+ * which virtual addresses allow access to all of memory.
41
+ *
42
+ * @{
43
+ *
44
+ */
45
+
46
+/**
47
+ * Convert virtual address to user pointer
48
+ *
49
+ * @v addr		Virtual address
50
+ * @ret userptr		User pointer
51
+ */
52
+static inline __always_inline userptr_t
53
+trivial_virt_to_user ( volatile const void *addr ) {
54
+	return ( ( userptr_t ) addr );
55
+}
56
+
57
+/**
58
+ * Convert user pointer to virtual address
59
+ *
60
+ * @v userptr		User pointer
61
+ * @v offset		Offset from user pointer
62
+ * @ret addr		Virtual address
63
+ *
64
+ * This operation is not available under all memory models.
65
+ */
66
+static inline __always_inline void *
67
+trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
68
+	return ( ( void * ) userptr + offset );
69
+}
70
+
71
+/**
72
+ * Add offset to user pointer
73
+ *
74
+ * @v userptr		User pointer
75
+ * @v offset		Offset
76
+ * @ret userptr		New pointer value
77
+ */
78
+static inline __always_inline userptr_t
79
+trivial_userptr_add ( userptr_t userptr, off_t offset ) {
80
+	return ( userptr + offset );
81
+}
82
+
83
+/**
84
+ * Copy data between user buffers
85
+ *
86
+ * @v dest		Destination
87
+ * @v dest_off		Destination offset
88
+ * @v src		Source
89
+ * @v src_off		Source offset
90
+ * @v len		Length
91
+ */
92
+static inline __always_inline void
93
+trivial_memcpy_user ( userptr_t dest, off_t dest_off,
94
+		      userptr_t src, off_t src_off, size_t len ) {
95
+	memcpy ( ( ( void * ) dest + dest_off ),
96
+		 ( ( void * ) src + src_off ), len );
97
+}
98
+
99
+/**
100
+ * Copy data between user buffers, allowing for overlap
101
+ *
102
+ * @v dest		Destination
103
+ * @v dest_off		Destination offset
104
+ * @v src		Source
105
+ * @v src_off		Source offset
106
+ * @v len		Length
107
+ */
108
+static inline __always_inline void
109
+trivial_memmove_user ( userptr_t dest, off_t dest_off,
110
+		       userptr_t src, off_t src_off, size_t len ) {
111
+	memmove ( ( ( void * ) dest + dest_off ),
112
+		  ( ( void * ) src + src_off ), len );
113
+}
114
+
115
+/**
116
+ * Fill user buffer with a constant byte
117
+ *
118
+ * @v buffer		User buffer
119
+ * @v offset		Offset within buffer
120
+ * @v c			Constant byte with which to fill
121
+ * @v len		Length
122
+ */
123
+static inline __always_inline void
124
+trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
125
+	memset ( ( ( void * ) buffer + offset ), c, len );
126
+}
127
+
128
+/**
129
+ * Find length of NUL-terminated string in user buffer
130
+ *
131
+ * @v buffer		User buffer
132
+ * @v offset		Offset within buffer
133
+ * @ret len		Length of string (excluding NUL)
134
+ */
135
+static inline __always_inline size_t
136
+trivial_strlen_user ( userptr_t buffer, off_t offset ) {
137
+	return strlen ( ( void * ) buffer + offset );
138
+}
139
+
140
+/**
141
+ * Find character in user buffer
142
+ *
143
+ * @v buffer		User buffer
144
+ * @v offset		Starting offset within buffer
145
+ * @v c			Character to search for
146
+ * @v len		Length of user buffer
147
+ * @ret offset		Offset of character, or <0 if not found
148
+ */
149
+static inline __always_inline off_t
150
+trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
151
+	void *found;
152
+
153
+	found = memchr ( ( ( void * ) buffer + offset ), c, len );
154
+	return ( found ? ( found - ( void * ) buffer ) : -1 );
155
+}
156
+
157
+/** @} */
158
+
159
+/**
160
+ * Calculate static inline user access API function name
161
+ *
162
+ * @v _prefix		Subsystem prefix
163
+ * @v _api_func		API function
164
+ * @ret _subsys_func	Subsystem API function
165
+ */
166
+#define UACCESS_INLINE( _subsys, _api_func ) \
167
+	SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
168
+
169
+/**
170
+ * Provide an user access API implementation
171
+ *
172
+ * @v _prefix		Subsystem prefix
173
+ * @v _api_func		API function
174
+ * @v _func		Implementing function
175
+ */
176
+#define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
177
+	PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
178
+
179
+/**
180
+ * Provide a static inline user access API implementation
181
+ *
182
+ * @v _prefix		Subsystem prefix
183
+ * @v _api_func		API function
184
+ */
185
+#define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
186
+	PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
187
+
188
+/* Include all architecture-independent user access API headers */
189
+
190
+/* Include all architecture-dependent user access API headers */
191
+#include <bits/uaccess.h>
192
+
193
+/**
194
+ * Convert physical address to user pointer
195
+ *
196
+ * @v phys_addr		Physical address
197
+ * @ret userptr		User pointer
198
+ */
199
+userptr_t phys_to_user ( unsigned long phys_addr );
200
+
201
+/**
202
+ * Convert user pointer to physical address
203
+ *
204
+ * @v userptr		User pointer
205
+ * @v offset		Offset from user pointer
206
+ * @ret phys_addr	Physical address
207
+ */
208
+unsigned long user_to_phys ( userptr_t userptr, off_t offset );
209
+
210
+/**
211
+ * Convert virtual address to user pointer
212
+ *
213
+ * @v addr		Virtual address
214
+ * @ret userptr		User pointer
215
+ */
216
+userptr_t virt_to_user ( volatile const void *addr );
217
+
218
+/**
219
+ * Convert user pointer to virtual address
220
+ *
221
+ * @v userptr		User pointer
222
+ * @v offset		Offset from user pointer
223
+ * @ret addr		Virtual address
224
+ *
225
+ * This operation is not available under all memory models.
226
+ */
227
+void * user_to_virt ( userptr_t userptr, off_t offset );
228
+
229
+/**
230
+ * Add offset to user pointer
231
+ *
232
+ * @v userptr		User pointer
233
+ * @v offset		Offset
234
+ * @ret userptr		New pointer value
235
+ */
236
+userptr_t userptr_add ( userptr_t userptr, off_t offset );
237
+
238
+/**
239
+ * Convert virtual address to a physical address
240
+ *
241
+ * @v addr		Virtual address
242
+ * @ret phys_addr	Physical address
243
+ */
244
+static inline __always_inline unsigned long
245
+virt_to_phys ( volatile const void *addr ) {
246
+	return user_to_phys ( virt_to_user ( addr ), 0 );
247
+}
248
+
249
+/**
250
+ * Convert physical address to a virtual address
251
+ *
252
+ * @v addr		Virtual address
253
+ * @ret phys_addr	Physical address
254
+ *
255
+ * This operation is not available under all memory models.
256
+ */
257
+static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
258
+	return user_to_virt ( phys_to_user ( phys_addr ), 0 );
259
+}
260
+
261
+/**
262
+ * Copy data between user buffers
263
+ *
264
+ * @v dest		Destination
265
+ * @v dest_off		Destination offset
266
+ * @v src		Source
267
+ * @v src_off		Source offset
268
+ * @v len		Length
269
+ */
270
+void memcpy_user ( userptr_t dest, off_t dest_off,
271
+		   userptr_t src, off_t src_off, size_t len );
272
+
273
+/**
274
+ * Copy data to user buffer
275
+ *
276
+ * @v dest		Destination
277
+ * @v dest_off		Destination offset
278
+ * @v src		Source
279
+ * @v len		Length
280
+ */
281
+static inline __always_inline void
282
+copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
283
+	memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
284
+}
285
+
286
+/**
287
+ * Copy data from user buffer
288
+ *
289
+ * @v dest		Destination
290
+ * @v src		Source
291
+ * @v src_off		Source offset
292
+ * @v len		Length
293
+ */
294
+static inline __always_inline void
295
+copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
296
+	memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
297
+}
298
+
299
+/**
300
+ * Copy data between user buffers, allowing for overlap
301
+ *
302
+ * @v dest		Destination
303
+ * @v dest_off		Destination offset
304
+ * @v src		Source
305
+ * @v src_off		Source offset
306
+ * @v len		Length
307
+ */
308
+void memmove_user ( userptr_t dest, off_t dest_off,
309
+		    userptr_t src, off_t src_off, size_t len );
310
+
311
+/**
312
+ * Fill user buffer with a constant byte
313
+ *
314
+ * @v userptr		User buffer
315
+ * @v offset		Offset within buffer
316
+ * @v c			Constant byte with which to fill
317
+ * @v len		Length
318
+ */
319
+void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
320
+
321
+/**
322
+ * Find length of NUL-terminated string in user buffer
323
+ *
324
+ * @v userptr		User buffer
325
+ * @v offset		Offset within buffer
326
+ * @ret len		Length of string (excluding NUL)
327
+ */
328
+size_t strlen_user ( userptr_t userptr, off_t offset );
329
+
330
+/**
331
+ * Find character in user buffer
332
+ *
333
+ * @v userptr		User buffer
334
+ * @v offset		Starting offset within buffer
335
+ * @v c			Character to search for
336
+ * @v len		Length of user buffer
337
+ * @ret offset		Offset of character, or <0 if not found
338
+ */
339
+off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
340
+
27 341
 #endif /* _GPXE_UACCESS_H */

+ 2
- 3
src/include/pxe_types.h Ver fichero

@@ -7,9 +7,8 @@
7 7
  *
8 8
  */
9 9
 
10
-#include "stdint.h"
11
-#include "pxe_addr.h" /* Architecture-specific PXE definitions */
12
-#include "errno.h" /* PXE status codes */
10
+#include <stdint.h>
11
+#include <errno.h> /* PXE status codes */
13 12
 
14 13
 /** @addtogroup pxe Preboot eXecution Environment (PXE) API
15 14
  *  @{

Loading…
Cancelar
Guardar