[uaccess] Formalise the uaccess API
authorMichael Brown <mcb30@etherboot.org>
Mon, 13 Oct 2008 02:47:33 +0000 (03:47 +0100)
committerMichael Brown <mcb30@etherboot.org>
Mon, 13 Oct 2008 03:10:34 +0000 (04:10 +0100)
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().

21 files changed:
src/arch/i386/core/gdbidt.S
src/arch/i386/core/gdbmach.c
src/arch/i386/core/pic8259.c
src/arch/i386/core/start32.S [deleted file]
src/arch/i386/core/virtaddr.S
src/arch/i386/core/x86_io.c
src/arch/i386/drivers/net/undinet.c
src/arch/i386/firmware/pcbios/gateA20.c
src/arch/i386/include/bits/uaccess.h
src/arch/i386/include/gpxe/x86_io.h
src/arch/i386/include/int13.h
src/arch/i386/include/librm.h
src/arch/i386/include/pxe_addr.h [deleted file]
src/arch/i386/include/realmode.h
src/arch/i386/include/registers.h
src/arch/i386/include/virtaddr.h [deleted file]
src/arch/i386/transitions/librm_mgmt.c
src/config/defaults/pcbios.h
src/include/gpxe/io.h
src/include/gpxe/uaccess.h
src/include/pxe_types.h

index 860f7b0..64c29e4 100644 (file)
@@ -2,7 +2,7 @@
  * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
  */
 
-#include <virtaddr.h>
+#include <librm.h>
 
 #define SIZEOF_I386_REGS       32
 #define SIZEOF_I386_FLAGS      4
index 5e72e4d..d07663c 100644 (file)
@@ -19,7 +19,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <assert.h>
-#include <virtaddr.h>
+#include <gpxe/uaccess.h>
 #include <gpxe/gdbstub.h>
 #include <gdbmach.h>
 
index defe2e7..8a0433d 100644 (file)
@@ -16,6 +16,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <gpxe/io.h>
 #include <pic8259.h>
 
 /** @file
diff --git a/src/arch/i386/core/start32.S b/src/arch/i386/core/start32.S
deleted file mode 100644 (file)
index 37ef5eb..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-#include "virtaddr.h"
-       
-       .equ    MSR_K6_EFER,   0xC0000080
-       .equ    EFER_LME,      0x00000100
-       .equ    X86_CR4_PAE,   0x00000020
-       .equ    CR0_PG,        0x80000000
-
-#ifdef GAS291
-#define DATA32 data32;
-#define ADDR32 addr32;
-#define        LJMPI(x)        ljmp    x
-#else
-#define DATA32 data32
-#define ADDR32 addr32
-/* newer GAS295 require #define        LJMPI(x)        ljmp    *x */
-#define        LJMPI(x)        ljmp    x
-#endif
-
-/*
- * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
- * then you only have to take care of %ebx, %esi, %edi and %ebp.  These
- * registers must not be altered under any circumstance.  All other registers
- * may be clobbered without any negative side effects.  If you don't follow
- * this rule then you'll run into strange effects that only occur on some
- * gcc versions (because the register allocator may use different registers).
- *
- * All the data32 prefixes for the ljmp instructions are necessary, because
- * the assembler emits code with a relocation address of 0.  This means that
- * all destinations are initially negative, which the assembler doesn't grok,
- * because for some reason negative numbers don't fit into 16 bits. The addr32
- * prefixes are there for the same reasons, because otherwise the memory
- * references are only 16 bit wide.  Theoretically they are all superfluous.
- * One last note about prefixes: the data32 prefixes on all call _real_to_prot
- * instructions could be removed if the _real_to_prot function is changed to
- * deal correctly with 16 bit return addresses.  I tried it, but failed.
- */
-
-       .text
-       .arch i386
-       .code32
-
-       /* This is a struct os_entry_regs */
-       .globl os_regs
-os_regs:       .space 56
-               
-/**************************************************************************
-XSTART32 - Transfer control to the kernel just loaded
-**************************************************************************/
-       .globl xstart32
-xstart32:
-       /* Save the callee save registers */
-       movl    %ebp, os_regs + 32
-       movl    %esi, os_regs + 36
-       movl    %edi, os_regs + 40
-       movl    %ebx, os_regs + 44
-
-       /* save the return address */
-       popl    %eax
-       movl    %eax, os_regs + 48
-
-       /* save the stack pointer */
-       movl    %esp, os_regs + 52
-
-       /* Get the new destination address */
-       popl    %ecx
-
-       /* Store the physical address of xend on the stack */
-       movl    $xend32, %ebx
-       addl    virt_offset, %ebx
-       pushl   %ebx
-
-       /* Store the destination address on the stack */
-       pushl   $PHYSICAL_CS
-       pushl   %ecx
-
-       /* Cache virt_offset */
-       movl    virt_offset, %ebp
-       
-       /* Switch to using physical addresses */
-       call    _virt_to_phys
-
-       /* Save the target stack pointer */
-       movl    %esp, os_regs + 12(%ebp)
-       leal    os_regs(%ebp), %esp
-
-       /* Store the pointer to os_regs */
-       movl    %esp, os_regs_ptr(%ebp)
-
-       /* Load my new registers */
-       popal
-       movl    (-32 + 12)(%esp), %esp
-
-       /* Jump to the new kernel
-        * The lret switches to a flat code segment
-        */
-       lret
-
-       .balign 4
-       .globl xend32
-xend32:
-       /* Fixup %eflags */
-       nop
-       cli
-       cld
-       
-       /* Load %esp with &os_regs + virt_offset */
-       .byte   0xbc /* movl $0, %esp */
-os_regs_ptr:
-       .long   0
-
-       /* Save the result registers */
-       addl    $32, %esp
-       pushal
-
-       /* Compute virt_offset */
-       movl    %esp, %ebp
-       subl    $os_regs, %ebp
-       
-       /* Load the stack pointer and convert it to physical address */
-       movl    52(%esp), %esp
-       addl    %ebp, %esp
-
-       /* Enable the virtual addresses */
-       leal    _phys_to_virt(%ebp), %eax
-       call    *%eax
-
-       /* Restore the callee save registers */
-       movl    os_regs + 32, %ebp
-       movl    os_regs + 36, %esi
-       movl    os_regs + 40, %edi
-       movl    os_regs + 44, %ebx
-       movl    os_regs + 48, %edx
-       movl    os_regs + 52, %esp
-
-       /* Get the C return value */
-       movl    os_regs + 28, %eax
-
-       jmpl    *%edx
-
-#ifdef CONFIG_X86_64
-       .arch   sledgehammer
-/**************************************************************************
-XSTART_lm - Transfer control to the kernel just loaded in long mode
-**************************************************************************/
-       .globl xstart_lm
-xstart_lm:
-       /* Save the callee save registers */
-       pushl   %ebp
-       pushl   %esi
-       pushl   %edi
-       pushl   %ebx
-
-       /* Cache virt_offset && (virt_offset & 0xfffff000) */
-       movl    virt_offset, %ebp
-       movl    %ebp, %ebx
-       andl    $0xfffff000, %ebx
-
-       /* Switch to using physical addresses */
-       call    _virt_to_phys
-
-       /* Initialize the page tables */
-       /* Level 4 */
-       leal    0x23 + pgt_level3(%ebx), %eax
-       leal    pgt_level4(%ebx), %edi
-       movl    %eax, (%edi)
-
-       /* Level 3 */
-       leal    0x23 + pgt_level2(%ebx), %eax
-       leal    pgt_level3(%ebx), %edi
-       movl    %eax, 0x00(%edi)
-       addl    $4096, %eax
-       movl    %eax, 0x08(%edi)
-       addl    $4096, %eax
-       movl    %eax, 0x10(%edi)
-       addl    $4096, %eax
-       movl    %eax, 0x18(%edi)
-
-       /* Level 2 */
-       movl    $0xe3, %eax
-       leal    pgt_level2(%ebx), %edi
-       leal    16384(%edi), %esi
-pgt_level2_loop:
-       movl    %eax, (%edi)
-       addl    $8, %edi
-       addl    $0x200000, %eax
-       cmp     %esi, %edi
-       jne     pgt_level2_loop
-
-       /* Point at the x86_64 page tables */
-       leal    pgt_level4(%ebx), %edi
-       movl    %edi, %cr3
-
-
-       /* Setup for the return from 64bit mode */
-       /* 64bit align the stack */
-       movl    %esp, %ebx              /* original stack pointer + 16 */
-       andl    $0xfffffff8, %esp
-
-       /* Save original stack pointer + 16 */
-       pushl   %ebx
-
-       /* Save virt_offset */
-       pushl   %ebp
-
-       /* Setup for the jmp to 64bit long mode */
-       leal    start_lm(%ebp), %eax
-       movl    %eax, 0x00 + start_lm_addr(%ebp)
-       movl    $LM_CODE_SEG, %eax
-       movl    %eax, 0x04 + start_lm_addr(%ebp)
-
-       /* Setup for the jump out of 64bit long mode */
-       leal    end_lm(%ebp), %eax
-       movl    %eax, 0x00 + end_lm_addr(%ebp)
-       movl    $FLAT_CODE_SEG, %eax
-       movl    %eax, 0x04 + end_lm_addr(%ebp)
-
-       /* Enable PAE mode */
-       movl    %cr4, %eax
-       orl     $X86_CR4_PAE, %eax
-       movl    %eax, %cr4
-
-       /* Enable long mode */
-       movl    $MSR_K6_EFER, %ecx
-       rdmsr
-       orl     $EFER_LME, %eax
-       wrmsr
-
-       /* Start paging, entering 32bit compatiblity mode */
-       movl    %cr0, %eax
-       orl     $CR0_PG, %eax
-       movl    %eax, %cr0
-
-       /* Enter 64bit long mode */
-       ljmp    *start_lm_addr(%ebp)
-       .code64
-start_lm:
-       /* Load 64bit data segments */
-       movl    $LM_DATA_SEG, %eax
-       movl    %eax, %ds
-       movl    %eax, %es
-       movl    %eax, %ss
-
-       andq    $0xffffffff, %rbx
-       /* Get the address to jump to */
-       movl    20(%rbx), %edx
-       andq    $0xffffffff, %rdx
-       
-       /* Get the argument pointer */
-       movl    24(%rbx), %ebx
-       andq    $0xffffffff, %rbx
-
-       /* Jump to the 64bit code */
-       call    *%rdx
-
-       /* Preserve the result */
-       movl    %eax, %edx
-
-       /* Fixup %eflags */
-       cli
-       cld
-
-       /* Switch to 32bit compatibility mode */
-       ljmp    *end_lm_addr(%rip)
-
-       .code32
-end_lm:
-       /* Disable paging */
-       movl    %cr0, %eax
-       andl    $~CR0_PG, %eax
-       movl    %eax, %cr0
-
-       /* Disable long mode */
-       movl    $MSR_K6_EFER, %ecx
-       rdmsr
-       andl    $~EFER_LME, %eax
-       wrmsr
-
-       /* Disable PAE */
-       movl    %cr4, %eax
-       andl    $~X86_CR4_PAE, %eax
-       movl    %eax, %cr4
-       
-       /* Compute virt_offset */
-       popl    %ebp
-
-       /* Compute the original stack pointer + 16 */
-       popl    %ebx
-       movl    %ebx, %esp
-
-       /* Enable the virtual addresses */
-       leal    _phys_to_virt(%ebp), %eax
-       call    *%eax
-
-       /* Restore the callee save registers */
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       popl    %ebp
-
-       /* Get the C return value */
-       movl    %edx, %eax
-
-       /* Return */
-       ret
-
-       .arch i386
-#endif /* CONFIG_X86_64 */
-
-#ifdef CONFIG_X86_64
-       .section ".bss"
-       .p2align 12
-       /* Include a dummy space in case we are loaded badly aligned */
-       .space 4096
-       /* Reserve enough space for a page table convering 4GB with 2MB pages */
-pgt_level4:    
-       .space 4096
-pgt_level3:    
-       .space 4096
-pgt_level2:    
-       .space 16384
-start_lm_addr:
-       .space  8
-end_lm_addr:
-       .space  8
-#endif
index 5d76237..cf6da4f 100644 (file)
@@ -4,7 +4,7 @@
  *
  */
 
-#include "virtaddr.h"
+#include "librm.h"
                
        .arch i386
        .text
index 1aab6c9..424a96c 100644 (file)
@@ -65,10 +65,8 @@ static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
                               : : "A" ( data ), "r" ( io_addr ) );
 }
 
-PROVIDE_IOAPI_INLINE ( x86, virt_to_phys );
-PROVIDE_IOAPI_INLINE ( x86, phys_to_virt );
-PROVIDE_IOAPI_INLINE ( x86, virt_to_bus );
-PROVIDE_IOAPI_INLINE ( x86, bus_to_virt );
+PROVIDE_IOAPI_INLINE ( x86, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, bus_to_phys );
 PROVIDE_IOAPI_INLINE ( x86, ioremap );
 PROVIDE_IOAPI_INLINE ( x86, iounmap );
 PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
index 12b954c..229fde0 100644 (file)
@@ -23,6 +23,7 @@
 #include <biosint.h>
 #include <pnpbios.h>
 #include <basemem_packet.h>
+#include <gpxe/io.h>
 #include <gpxe/iobuf.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/if_ether.h>
index 9113524..34e3ac5 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <realmode.h>
 #include <bios.h>
+#include <gpxe/io.h>
 #include <gpxe/timer.h>
 
 #define K_RDWR         0x60            /* keyboard data & cmds (read/write) */
index 9c6d0c2..0ecc502 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef _BITS_UACCESS_H
 #define _BITS_UACCESS_H
 
-#include <realmode.h>
+/** @file
+ *
+ * i386-specific user access API implementations
+ *
+ */
+
+#include <librm.h>
 
 #endif /* _BITS_UACCESS_H */
index 8b9942e..0ecedfe 100644 (file)
@@ -15,8 +15,6 @@
  * into a machine with such an old CPU anyway.
  */
 
-#include <virtaddr.h>
-
 #ifdef IOAPI_X86
 #define IOAPI_PREFIX_x86
 #else
  *
  */
 
-static inline __always_inline unsigned long
-IOAPI_INLINE ( x86, virt_to_phys ) ( volatile const void *addr ) {
-       return ( ( ( unsigned long ) addr ) + virt_offset );
-}
-
-static inline __always_inline void *
-IOAPI_INLINE ( x86, phys_to_virt ) ( unsigned long phys_addr ) {
-       return ( ( void * ) ( phys_addr - virt_offset ) );
-}
+/*
+ * Physical<->Bus and Bus<->I/O address mappings
+ *
+ */
 
 static inline __always_inline unsigned long
-IOAPI_INLINE ( x86, virt_to_bus ) ( volatile const void *addr ) {
-       return virt_to_phys ( addr );
+IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
+       return phys_addr;
 }
 
-static inline __always_inline void *
-IOAPI_INLINE ( x86, bus_to_virt ) ( unsigned long bus_addr ) {
-       return phys_to_virt ( bus_addr );
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
+       return bus_addr;
 }
 
 static inline __always_inline void *
index 72ca97d..bf6d031 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <stdint.h>
 #include <gpxe/list.h>
+#include <realmode.h>
 
 struct block_device;
 
index 07a85c5..9eb2767 100755 (executable)
 #ifndef LIBRM_H
 #define LIBRM_H
 
-/* Drag in protected-mode segment selector values */
-#include "virtaddr.h"
-#include "realmode.h"
+/* Segment selectors as used in our protected-mode GDTs.
+ *
+ * Don't change these unless you really know what you're doing.
+ */
+
+#define VIRTUAL_CS 0x08
+#define VIRTUAL_DS 0x10
+#define PHYSICAL_CS 0x18
+#define PHYSICAL_DS 0x20
+#define REAL_CS 0x28
+#define REAL_DS 0x30
+#if 0
+#define LONG_CS 0x38
+#define LONG_DS 0x40
+#endif
 
 #ifndef ASSEMBLY
 
-#include "stddef.h"
-#include "string.h"
+#ifdef UACCESS_LIBRM
+#define UACCESS_PREFIX_librm
+#else
+#define UACCESS_PREFIX_librm __librm_
+#endif
+
+/* Variables in librm.S */
+extern unsigned long virt_offset;
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr                Physical address
+ * @ret userptr                User pointer
+ */
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
+       return ( phys_addr - virt_offset );
+}
 
-/*
- * Data structures and type definitions
+/**
+ * Convert user buffer to physical address
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset from user pointer
+ * @ret phys_addr      Physical address
+ */
+static inline __always_inline unsigned long
+UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
+       return ( userptr + offset + virt_offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
+       return trivial_virt_to_user ( addr );
+}
+
+static inline __always_inline void *
+UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
+       return trivial_user_to_virt ( userptr, offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
+       return trivial_userptr_add ( userptr, offset );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
+                                       userptr_t src, off_t src_off,
+                                       size_t len ) {
+       trivial_memcpy_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
+                                        userptr_t src, off_t src_off,
+                                        size_t len ) {
+       trivial_memmove_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
+                                       int c, size_t len ) {
+       trivial_memset_user ( buffer, offset, c, len );
+}
+
+static inline __always_inline size_t
+UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
+       return trivial_strlen_user ( buffer, offset );
+}
+
+static inline __always_inline off_t
+UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
+                                       int c, size_t len ) {
+       return trivial_memchr_user ( buffer, offset, c, len );
+}
+
+
+/******************************************************************************
+ *
+ * Access to variables in .data16 and .text16
  *
  */
 
-/* Access to variables in .data16 and .text16 */
 extern char *data16;
 extern char *text16;
 
@@ -72,178 +160,6 @@ extern uint16_t __text16 ( rm_ds );
  */
 extern void gateA20_set ( void );
 
-/*
- * librm_mgmt: functions for manipulating base memory and executing
- * real-mode code.
- *
- * Full API documentation for these functions is in realmode.h.
- *
- */
-
-/* Macro for obtaining a physical address from a segment:offset pair. */
-#define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
-
-/* Copy to/from base memory */
-static inline __attribute__ (( always_inline )) void
-copy_to_real_librm ( unsigned int dest_seg, unsigned int dest_off,
-                    void *src, size_t n ) {
-       memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
-}
-static inline __attribute__ (( always_inline )) void
-copy_from_real_librm ( void *dest, unsigned int src_seg,
-                      unsigned int src_off, size_t n ) {
-       memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
-}
-#define put_real_librm( var, dest_seg, dest_off )                            \
-       do {                                                                  \
-               * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
-       } while ( 0 )
-#define get_real_librm( var, src_seg, src_off )                                      \
-       do {                                                                  \
-               var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
-       } while ( 0 )
-#define copy_to_real copy_to_real_librm
-#define copy_from_real copy_from_real_librm
-#define put_real put_real_librm
-#define get_real get_real_librm
-
-/**
- * A pointer to a user buffer
- *
- * Even though we could just use a void *, we use an intptr_t so that
- * attempts to use normal pointers show up as compiler warnings.  Such
- * code is actually valid for librm, but not for libkir (i.e. under
- * KEEP_IT_REAL), so it's good to have the warnings even under librm.
- */
-typedef intptr_t userptr_t;
-
-/**
- * Add offset to user pointer
- *
- * @v ptr              User pointer
- * @v offset           Offset
- * @ret new_ptr                New pointer value
- */
-static inline __attribute__ (( always_inline )) userptr_t
-userptr_add ( userptr_t ptr, off_t offset ) {
-       return ( ptr + offset );
-}
-
-/**
- * Copy data to user buffer
- *
- * @v buffer           User buffer
- * @v offset           Offset within user buffer
- * @v src              Source
- * @v len              Length
- */
-static inline __attribute__ (( always_inline )) void
-copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
-       memcpy ( ( ( void * ) buffer + offset ), src, len );
-}
-
-/**
- * Copy data from user buffer
- *
- * @v dest             Destination
- * @v buffer           User buffer
- * @v offset           Offset within user buffer
- * @v len              Length
- */
-static inline __attribute__ (( always_inline )) void
-copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
-       memcpy ( dest, ( ( void * ) buffer + offset ), len );
-}
-
-/**
- * Copy data between user buffers
- *
- * @v dest             Destination user buffer
- * @v dest_off         Offset within destination buffer
- * @v src              Source user buffer
- * @v src_off          Offset within source buffer
- * @v len              Length
- */
-static inline __attribute__ (( always_inline )) void
-memcpy_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
-             size_t len ) {
-       memcpy ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
-                len );
-}
-
-/**
- * Copy data between user buffers, allowing for overlap
- *
- * @v dest             Destination user buffer
- * @v dest_off         Offset within destination buffer
- * @v src              Source user buffer
- * @v src_off          Offset within source buffer
- * @v len              Length
- */
-static inline __attribute__ (( always_inline )) void
-memmove_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
-              size_t len ) {
-       memmove ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
-                 len );
-}
-
-/**
- * Fill user buffer with a constant byte
- *
- * @v buffer           User buffer
- * @v offset           Offset within buffer
- * @v c                        Constant byte with which to fill
- * @v len              Length
- */
-static inline __attribute__ (( always_inline )) void
-memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
-       memset ( ( ( void * ) buffer + offset ), c, len );
-}
-
-/**
- * Find length of NUL-terminated string in user buffer
- *
- * @v buffer           User buffer
- * @v offset           Offset within buffer
- * @ret len            Length of string (excluding NUL)
- */
-static inline __attribute__ (( always_inline )) size_t
-strlen_user ( userptr_t buffer, off_t offset ) {
-       return strlen ( ( void * ) buffer + offset );
-}
-
-/**
- * Find character in user buffer
- *
- * @v buffer           User buffer
- * @v offset           Starting offset within buffer
- * @v c                        Character to search for
- * @v len              Length of user buffer
- * @ret offset         Offset of character, or <0 if not found
- */
-static inline __attribute__ (( always_inline )) off_t
-memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
-       void *found;
-
-       found = memchr ( ( ( void * ) buffer + offset ), c, len );
-       return ( found ? ( found - ( void * ) buffer ) : -1 );
-}
-
-/**
- * Convert virtual address to user buffer
- *
- * @v virtual          Virtual address
- * @ret buffer         User buffer
- *
- * This constructs a user buffer from an ordinary pointer.  Use it
- * when you need to pass a pointer to an internal buffer to a function
- * that expects a @c userptr_t.
- */
-static inline __attribute__ (( always_inline )) userptr_t
-virt_to_user ( void * virtual ) {
-       return ( ( intptr_t ) virtual );
-}
-
 /**
  * Convert segment:offset address to user buffer
  *
@@ -251,32 +167,9 @@ virt_to_user ( void * virtual ) {
  * @v offset           Real-mode offset
  * @ret buffer         User buffer
  */
-static inline __attribute__ (( always_inline )) userptr_t
+static inline __always_inline userptr_t
 real_to_user ( unsigned int segment, unsigned int offset ) {
-       return virt_to_user ( VIRTUAL ( segment, offset ) );
-}
-
-/**
- * Convert physical address to user buffer
- *
- * @v physical         Physical address
- * @ret buffer         User buffer
- */
-static inline __attribute__ (( always_inline )) userptr_t
-phys_to_user ( physaddr_t physical ) {
-       return virt_to_user ( phys_to_virt ( physical ) );
-}
-
-/**
- * Convert user buffer to physical address
- *
- * @v buffer           User buffer
- * @v offset           Offset within user buffer
- * @ret physical       Physical address
- */
-static inline __attribute__ (( always_inline )) physaddr_t
-user_to_phys ( userptr_t buffer, off_t offset ) {
-       return virt_to_phys ( ( void * ) buffer + offset );
+       return ( phys_to_user ( ( segment << 4 ) + offset ) );
 }
 
 extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
diff --git a/src/arch/i386/include/pxe_addr.h b/src/arch/i386/include/pxe_addr.h
deleted file mode 100644 (file)
index 954551e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Architecture-specific portion of pxe.h for Etherboot
- *
- * This file has to define the types SEGOFF16_t, SEGDESC_t and
- * SEGSEL_t for use in other PXE structures.  See pxe.h for details.
- */
-
-#ifndef PXE_ADDR_H
-#define PXE_ADDR_H
-
-#define IS_NULL_SEGOFF16(x) ( ( (x).segment == 0 ) && ( (x).offset == 0 ) )
-#define SEGOFF16_TO_PTR(x) ( VIRTUAL( (x).segment, (x).offset ) )
-#define PTR_TO_SEGOFF16(ptr,segoff16) \
-       (segoff16).segment = SEGMENT(ptr); \
-       (segoff16).offset  = OFFSET(ptr);
-
-#endif /* PXE_ADDR_H */
index ea4192e..26e6dd7 100644 (file)
@@ -1,45 +1,15 @@
 #ifndef REALMODE_H
 #define REALMODE_H
 
-#ifndef ASSEMBLY
-
-#include "stdint.h"
-#include "registers.h"
-#include <gpxe/io.h>
+#include <stdint.h>
+#include <registers.h>
+#include <gpxe/uaccess.h>
 
 /*
  * Data structures and type definitions
  *
  */
 
-/* Segment:offset structure.  Note that the order within the structure
- * is offset:segment.
- */
-struct segoff {
-       uint16_t offset;
-       uint16_t segment;
-} __attribute__ (( packed ));
-
-typedef struct segoff segoff_t;
-
-/* Macro hackery needed to stringify bits of inline assembly */
-#define RM_XSTR(x) #x
-#define RM_STR(x) RM_XSTR(x)
-
-/* Drag in the selected real-mode transition library header */
-#ifdef KEEP_IT_REAL
-#include "libkir.h"
-#else
-#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.
- *
- */
-
 /*
  * Declaration of variables in .data16
  *
@@ -92,24 +62,53 @@ typedef struct segoff segoff_t;
  * assembler output to make sure that it's doing the right thing.
  */
 
-/*
- * 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 )
+/**
+ * Copy data to base memory
  *
- * These functions can be used to copy data to and from arbitrary
- * locations in base memory.
+ * @v dest_seg         Destination segment
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v len              Length
  */
+static inline __always_inline void
+copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
+              void *src, size_t n ) {
+       copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
+}
 
-/*
- * put_real ( variable, uint16_t dest_seg, uint16_t dest_off )
- * get_real ( variable, uint16_t src_seg, uint16_t src_off )
+/**
+ * Copy data to base memory
+ *
+ * @v dest             Destination
+ * @v src_seg          Source segment
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+static inline __always_inline void
+copy_from_real ( void *dest, unsigned int src_seg,
+                unsigned int src_off, size_t n ) {
+       copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
+}
+
+/**
+ * Write a single variable to base memory
  *
- * 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.
+ * @v var              Variable to write
+ * @v dest_seg         Destination segment
+ * @v dest_off         Destination offset
  */
+#define put_real( var, dest_seg, dest_off ) \
+       copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
+
+/**
+ * Read a single variable from base memory
+ *
+ * @v var              Variable to read
+ * @v src_seg          Source segment
+ * @v src_off          Source offset
+ */
+#define get_real( var, src_seg, src_off ) \
+       copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
 
 /*
  * REAL_CODE ( asm_code_str )
@@ -123,6 +122,4 @@ typedef struct segoff segoff_t;
  *
  */
 
-#endif /* ASSEMBLY */
-
 #endif /* REALMODE_H */
index 2b9b2b4..e68fa85 100644 (file)
@@ -10,8 +10,7 @@
  *
  */
 
-#include "compiler.h" /* for doxygen */
-#include "stdint.h"
+#include <stdint.h>
 
 /**
  * A 16-bit general register.
@@ -184,4 +183,14 @@ struct i386_all_regs {
 #define SF ( 1 <<  7 )
 #define OF ( 1 << 11 )
 
+/* Segment:offset structure.  Note that the order within the structure
+ * is offset:segment.
+ */
+struct segoff {
+       uint16_t offset;
+       uint16_t segment;
+} PACKED;
+
+typedef struct segoff segoff_t;
+
 #endif /* REGISTERS_H */
diff --git a/src/arch/i386/include/virtaddr.h b/src/arch/i386/include/virtaddr.h
deleted file mode 100644 (file)
index e7bb2cc..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef VIRTADDR_H
-#define VIRTADDR_H
-
-/* Segment selectors as used in our protected-mode GDTs.
- *
- * Don't change these unless you really know what you're doing.
- */
-
-#define VIRTUAL_CS 0x08
-#define VIRTUAL_DS 0x10
-#define PHYSICAL_CS 0x18
-#define PHYSICAL_DS 0x20
-#define REAL_CS 0x28
-#define REAL_DS 0x30
-#if 0
-#define LONG_CS 0x38
-#define LONG_DS 0x40
-#endif
-
-#ifndef ASSEMBLY
-
-#ifndef KEEP_IT_REAL
-
-/*
- * Without -DKEEP_IT_REAL, we are in 32-bit protected mode with a
- * fixed link address but an unknown physical start address.  Our GDT
- * sets up code and data segments with an offset of virt_offset, so
- * that link-time addresses can still work.
- *
- */
-
-/* Variables in virtaddr.S */
-extern unsigned long virt_offset;
-
-#else /* KEEP_IT_REAL */
-
-#include <stdint.h>
-
-/*
- * With -DKEEP_IT_REAL, we are in 16-bit real mode with fixed link
- * addresses and a segmented memory model.  We have separate code and
- * data segments.
- *
- * Because we may be called in 16-bit protected mode (damn PXE spec),
- * we cannot simply assume that physical = segment * 16 + offset.
- * Instead, we have to look up the physical start address of the
- * segment in the !PXE structure.  We have to assume that
- * virt_to_phys() is called only on pointers within the data segment,
- * because nothing passes segment information to us.
- *
- * We don't implement phys_to_virt at all, because there will be many
- * addresses that simply cannot be reached via a virtual address when
- * the virtual address space is limited to 64kB!
- */
-
-static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
-       /* Cheat: just for now, do the segment*16+offset calculation */
-       uint16_t ds;
-
-       __asm__ ( "movw %%ds, %%ax" : "=a" ( ds ) : );
-       return ( 16 * ds + ( ( unsigned long ) virt_addr ) );
-}
-
-/* Define it as a deprecated function so that we get compile-time
- * warnings, rather than just the link-time errors.
- */
-extern void * phys_to_virt ( unsigned long phys_addr )
-     __attribute__ ((deprecated));
-
-#endif /* KEEP_IT_REAL */
-
-#endif /* ASSEMBLY */
-
-#endif /* VIRTADDR_H */
index 59b2eab..50569f8 100755 (executable)
@@ -1,45 +1,56 @@
-/*\r
- * librm: a library for interfacing to real-mode code\r
- *\r
- * Michael Brown <mbrown@fensystems.co.uk>\r
- *\r
- */\r
-\r
-#include <stdint.h>\r
-#include <librm.h>\r
-\r
-/*\r
- * This file provides functions for managing librm.\r
- *\r
- */\r
-\r
-/**\r
- * Allocate space on the real-mode stack and copy data there from a\r
- * user buffer\r
- *\r
- * @v data                     User buffer\r
- * @v size                     Size of stack data\r
- * @ret sp                     New value of real-mode stack pointer\r
- */\r
-uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {\r
-       userptr_t rm_stack;\r
-       rm_sp -= size;\r
-       rm_stack = real_to_user ( rm_ss, rm_sp );\r
-       memcpy_user ( rm_stack, 0, data, 0, size );\r
-       return rm_sp;\r
-};\r
-\r
-/**\r
- * Deallocate space on the real-mode stack, optionally copying back\r
- * data to a user buffer.\r
- *\r
- * @v data                     User buffer\r
- * @v size                     Size of stack data\r
- */\r
-void remove_user_from_rm_stack ( userptr_t data, size_t size ) {\r
-       if ( data ) {\r
-               userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );\r
-               memcpy_user ( rm_stack, 0, data, 0, size );\r
-       }\r
-       rm_sp += size;\r
-};\r
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+#include <stdint.h>
+#include <realmode.h>
+
+/*
+ * This file provides functions for managing librm.
+ *
+ */
+
+/**
+ * Allocate space on the real-mode stack and copy data there from a
+ * user buffer
+ *
+ * @v data                     User buffer
+ * @v size                     Size of stack data
+ * @ret sp                     New value of real-mode stack pointer
+ */
+uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
+       userptr_t rm_stack;
+       rm_sp -= size;
+       rm_stack = real_to_user ( rm_ss, rm_sp );
+       memcpy_user ( rm_stack, 0, data, 0, size );
+       return rm_sp;
+};
+
+/**
+ * Deallocate space on the real-mode stack, optionally copying back
+ * data to a user buffer.
+ *
+ * @v data                     User buffer
+ * @v size                     Size of stack data
+ */
+void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
+       if ( data ) {
+               userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
+               memcpy_user ( rm_stack, 0, data, 0, size );
+       }
+       rm_sp += size;
+};
+
+PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
+PROVIDE_UACCESS_INLINE ( librm, virt_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_virt );
+PROVIDE_UACCESS_INLINE ( librm, userptr_add );
+PROVIDE_UACCESS_INLINE ( librm, memcpy_user );
+PROVIDE_UACCESS_INLINE ( librm, memmove_user );
+PROVIDE_UACCESS_INLINE ( librm, memset_user );
+PROVIDE_UACCESS_INLINE ( librm, strlen_user );
+PROVIDE_UACCESS_INLINE ( librm, memchr_user );
index a670e7a..211f28c 100644 (file)
@@ -7,6 +7,7 @@
  *
  */
 
+#define UACCESS_LIBRM
 #define IOAPI_X86
 #define PCIAPI_PCBIOS
 #define TIMER_PCBIOS
index 24cc180..0fc7c74 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdint.h>
 #include <gpxe/api.h>
 #include <config/ioapi.h>
+#include <gpxe/uaccess.h>
 
 /**
  * Calculate static inline I/O API function name
        } while ( 0 )
 
 /**
- * Convert virtual address to a physical address
+ * Convert physical address to a bus address
  *
- * @v addr             Virtual address
- * @ret phys_addr      Physical address
+ * @v phys_addr                Physical address
+ * @ret bus_addr       Bus address
  */
-unsigned long virt_to_phys ( volatile const void *addr );
+unsigned long phys_to_bus ( unsigned long phys_addr );
 
 /**
- * Convert physical address to a virtual address
+ * Convert bus address to a physical address
  *
- * @v addr             Virtual address
+ * @v bus_addr         Bus address
  * @ret phys_addr      Physical address
- *
- * This operation isn't actually valid within our memory model, and is
- * impossible to achieve under -DKEEP_IT_REAL.  Some drivers haven't
- * been updated to avoid it yet, though.
  */
-void * phys_to_virt ( unsigned long phys_addr );
+unsigned long bus_to_phys ( unsigned long bus_addr );
 
 /**
  * Convert virtual address to a bus address
@@ -174,7 +171,10 @@ void * phys_to_virt ( unsigned long phys_addr );
  * @v addr             Virtual address
  * @ret bus_addr       Bus address
  */
-unsigned long virt_to_bus ( volatile const void *addr );
+static inline __always_inline unsigned long
+virt_to_bus ( volatile const void *addr ) {
+       return phys_to_bus ( virt_to_phys ( addr ) );
+}
 
 /**
  * Convert bus address to a virtual address
@@ -182,11 +182,11 @@ unsigned long virt_to_bus ( volatile const void *addr );
  * @v bus_addr         Bus address
  * @ret addr           Virtual address
  *
- * This operation isn't actually valid within our memory model, and is
- * impossible to achieve under -DKEEP_IT_REAL.  Some drivers haven't
- * been updated to avoid it yet, though.
+ * This operation is not available under all memory models.
  */
-void * bus_to_virt ( unsigned long bus_addr );
+static inline __always_inline void * bus_to_virt ( unsigned long bus_addr ) {
+       return phys_to_virt ( bus_to_phys ( bus_addr ) );
+}
 
 /**
  * Map bus address as an I/O address
index 05f89e0..f677b7f 100644 (file)
  *
  */
 
-#include <bits/uaccess.h>
+#include <stdint.h>
+#include <string.h>
+#include <gpxe/api.h>
+#include <config/ioapi.h>
+
+/**
+ * A pointer to a user buffer
+ *
+ */
+typedef unsigned long userptr_t;
 
 /** Equivalent of NULL for user pointers */
 #define UNULL ( ( userptr_t ) 0 )
 
+/**
+ * @defgroup uaccess_trivial Trivial user access API implementations
+ *
+ * User access API implementations that can be used by environments in
+ * which virtual addresses allow access to all of memory.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr             Virtual address
+ * @ret userptr                User pointer
+ */
+static inline __always_inline userptr_t
+trivial_virt_to_user ( volatile const void *addr ) {
+       return ( ( userptr_t ) addr );
+}
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset from user pointer
+ * @ret addr           Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void *
+trivial_user_to_virt ( userptr_t userptr, off_t offset ) {
+       return ( ( void * ) userptr + offset );
+}
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset
+ * @ret userptr                New pointer value
+ */
+static inline __always_inline userptr_t
+trivial_userptr_add ( userptr_t userptr, off_t offset ) {
+       return ( userptr + offset );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest             Destination
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+static inline __always_inline void
+trivial_memcpy_user ( userptr_t dest, off_t dest_off,
+                     userptr_t src, off_t src_off, size_t len ) {
+       memcpy ( ( ( void * ) dest + dest_off ),
+                ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest             Destination
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+static inline __always_inline void
+trivial_memmove_user ( userptr_t dest, off_t dest_off,
+                      userptr_t src, off_t src_off, size_t len ) {
+       memmove ( ( ( void * ) dest + dest_off ),
+                 ( ( void * ) src + src_off ), len );
+}
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v buffer           User buffer
+ * @v offset           Offset within buffer
+ * @v c                        Constant byte with which to fill
+ * @v len              Length
+ */
+static inline __always_inline void
+trivial_memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+       memset ( ( ( void * ) buffer + offset ), c, len );
+}
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v buffer           User buffer
+ * @v offset           Offset within buffer
+ * @ret len            Length of string (excluding NUL)
+ */
+static inline __always_inline size_t
+trivial_strlen_user ( userptr_t buffer, off_t offset ) {
+       return strlen ( ( void * ) buffer + offset );
+}
+
+/**
+ * Find character in user buffer
+ *
+ * @v buffer           User buffer
+ * @v offset           Starting offset within buffer
+ * @v c                        Character to search for
+ * @v len              Length of user buffer
+ * @ret offset         Offset of character, or <0 if not found
+ */
+static inline __always_inline off_t
+trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+       void *found;
+
+       found = memchr ( ( ( void * ) buffer + offset ), c, len );
+       return ( found ? ( found - ( void * ) buffer ) : -1 );
+}
+
+/** @} */
+
+/**
+ * Calculate static inline user access API function name
+ *
+ * @v _prefix          Subsystem prefix
+ * @v _api_func                API function
+ * @ret _subsys_func   Subsystem API function
+ */
+#define UACCESS_INLINE( _subsys, _api_func ) \
+       SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/**
+ * Provide an user access API implementation
+ *
+ * @v _prefix          Subsystem prefix
+ * @v _api_func                API function
+ * @v _func            Implementing function
+ */
+#define PROVIDE_UACCESS( _subsys, _api_func, _func ) \
+       PROVIDE_SINGLE_API ( UACCESS_PREFIX_ ## _subsys, _api_func, _func )
+
+/**
+ * Provide a static inline user access API implementation
+ *
+ * @v _prefix          Subsystem prefix
+ * @v _api_func                API function
+ */
+#define PROVIDE_UACCESS_INLINE( _subsys, _api_func ) \
+       PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
+
+/* Include all architecture-independent user access API headers */
+
+/* Include all architecture-dependent user access API headers */
+#include <bits/uaccess.h>
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr                Physical address
+ * @ret userptr                User pointer
+ */
+userptr_t phys_to_user ( unsigned long phys_addr );
+
+/**
+ * Convert user pointer to physical address
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset from user pointer
+ * @ret phys_addr      Physical address
+ */
+unsigned long user_to_phys ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to user pointer
+ *
+ * @v addr             Virtual address
+ * @ret userptr                User pointer
+ */
+userptr_t virt_to_user ( volatile const void *addr );
+
+/**
+ * Convert user pointer to virtual address
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset from user pointer
+ * @ret addr           Virtual address
+ *
+ * This operation is not available under all memory models.
+ */
+void * user_to_virt ( userptr_t userptr, off_t offset );
+
+/**
+ * Add offset to user pointer
+ *
+ * @v userptr          User pointer
+ * @v offset           Offset
+ * @ret userptr                New pointer value
+ */
+userptr_t userptr_add ( userptr_t userptr, off_t offset );
+
+/**
+ * Convert virtual address to a physical address
+ *
+ * @v addr             Virtual address
+ * @ret phys_addr      Physical address
+ */
+static inline __always_inline unsigned long
+virt_to_phys ( volatile const void *addr ) {
+       return user_to_phys ( virt_to_user ( addr ), 0 );
+}
+
+/**
+ * Convert physical address to a virtual address
+ *
+ * @v addr             Virtual address
+ * @ret phys_addr      Physical address
+ *
+ * This operation is not available under all memory models.
+ */
+static inline __always_inline void * phys_to_virt ( unsigned long phys_addr ) {
+       return user_to_virt ( phys_to_user ( phys_addr ), 0 );
+}
+
+/**
+ * Copy data between user buffers
+ *
+ * @v dest             Destination
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+void memcpy_user ( userptr_t dest, off_t dest_off,
+                  userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Copy data to user buffer
+ *
+ * @v dest             Destination
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v len              Length
+ */
+static inline __always_inline void
+copy_to_user ( userptr_t dest, off_t dest_off, const void *src, size_t len ) {
+       memcpy_user ( dest, dest_off, virt_to_user ( src ), 0, len );
+}
+
+/**
+ * Copy data from user buffer
+ *
+ * @v dest             Destination
+ * @v src              Source
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+static inline __always_inline void
+copy_from_user ( void *dest, userptr_t src, off_t src_off, size_t len ) {
+       memcpy_user ( virt_to_user ( dest ), 0, src, src_off, len );
+}
+
+/**
+ * Copy data between user buffers, allowing for overlap
+ *
+ * @v dest             Destination
+ * @v dest_off         Destination offset
+ * @v src              Source
+ * @v src_off          Source offset
+ * @v len              Length
+ */
+void memmove_user ( userptr_t dest, off_t dest_off,
+                   userptr_t src, off_t src_off, size_t len );
+
+/**
+ * Fill user buffer with a constant byte
+ *
+ * @v userptr          User buffer
+ * @v offset           Offset within buffer
+ * @v c                        Constant byte with which to fill
+ * @v len              Length
+ */
+void memset_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
+/**
+ * Find length of NUL-terminated string in user buffer
+ *
+ * @v userptr          User buffer
+ * @v offset           Offset within buffer
+ * @ret len            Length of string (excluding NUL)
+ */
+size_t strlen_user ( userptr_t userptr, off_t offset );
+
+/**
+ * Find character in user buffer
+ *
+ * @v userptr          User buffer
+ * @v offset           Starting offset within buffer
+ * @v c                        Character to search for
+ * @v len              Length of user buffer
+ * @ret offset         Offset of character, or <0 if not found
+ */
+off_t memchr_user ( userptr_t userptr, off_t offset, int c, size_t len );
+
 #endif /* _GPXE_UACCESS_H */
index e31af06..dd9092e 100644 (file)
@@ -7,9 +7,8 @@
  *
  */
 
-#include "stdint.h"
-#include "pxe_addr.h" /* Architecture-specific PXE definitions */
-#include "errno.h" /* PXE status codes */
+#include <stdint.h>
+#include <errno.h> /* PXE status codes */
 
 /** @addtogroup pxe Preboot eXecution Environment (PXE) API
  *  @{