diff options
author | Michael Brown | 2008-10-13 04:47:33 +0200 |
---|---|---|
committer | Michael Brown | 2008-10-13 05:10:34 +0200 |
commit | 6554b79ff9eb8992f8cdbc6e13c7b5e346accf16 (patch) | |
tree | fd537d32f263feeaffade7e7fd809b2341431624 /src/include | |
parent | [timer] Remove now-obsolete references to TIMER_BIOS and TIMER_RDTSC (diff) | |
download | ipxe-6554b79ff9eb8992f8cdbc6e13c7b5e346accf16.tar.gz ipxe-6554b79ff9eb8992f8cdbc6e13c7b5e346accf16.tar.xz ipxe-6554b79ff9eb8992f8cdbc6e13c7b5e346accf16.zip |
[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().
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/gpxe/io.h | 32 | ||||
-rw-r--r-- | src/include/gpxe/uaccess.h | 316 | ||||
-rw-r--r-- | src/include/pxe_types.h | 5 |
3 files changed, 333 insertions, 20 deletions
diff --git a/src/include/gpxe/io.h b/src/include/gpxe/io.h index 24cc180f..0fc7c74e 100644 --- a/src/include/gpxe/io.h +++ b/src/include/gpxe/io.h @@ -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 @@ -149,24 +150,20 @@ } 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 diff --git a/src/include/gpxe/uaccess.h b/src/include/gpxe/uaccess.h index 05f89e03..f677b7fd 100644 --- a/src/include/gpxe/uaccess.h +++ b/src/include/gpxe/uaccess.h @@ -19,9 +19,323 @@ * */ -#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 */ diff --git a/src/include/pxe_types.h b/src/include/pxe_types.h index e31af062..dd9092ef 100644 --- a/src/include/pxe_types.h +++ b/src/include/pxe_types.h @@ -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 * @{ |