mirror of
https://github.com/ipxe/ipxe
synced 2025-12-23 05:21:49 +03:00
[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().
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
* @{
|
||||
|
||||
Reference in New Issue
Block a user