mirror of
https://github.com/ipxe/ipxe
synced 2025-12-31 06:49:20 +03:00
Add the concept of a "user pointer" (similar to the void __user * in
the kernel), which encapsulates the information needed to refer to an external buffer. Under normal operation, this can just be a void * equivalent, but under -DKEEP_IT_REAL it would be a segoff_t equivalent. Use this concept to avoid the need for bounce buffers in int13.c, which reduces memory usage and opens up the possibility of using multi-sector reads. Extend the block-device API and the SCSI block device implementation to support multi-sector reads. Update iscsi.c to use user buffers. Move the obsolete portions of realmode.h to old_realmode.h. MS-DOS now boots an order of magnitude faster over iSCSI (~10 seconds from power-up to C:> prompt in bochs).
This commit is contained in:
6
src/arch/i386/include/bits/uaccess.h
Normal file
6
src/arch/i386/include/bits/uaccess.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _BITS_UACCESS_H
|
||||
#define _BITS_UACCESS_H
|
||||
|
||||
#include <realmode.h>
|
||||
|
||||
#endif /* _BITS_UACCESS_H */
|
||||
@@ -92,6 +92,69 @@ copy_from_real_librm ( void *dest, unsigned int src_seg,
|
||||
#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;
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @v segment Real-mode segment
|
||||
* @v offset Real-mode offset
|
||||
* @ret buffer User buffer
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) userptr_t
|
||||
real_to_user ( unsigned int segment, unsigned int offset ) {
|
||||
return virt_to_user ( VIRTUAL ( segment, offset ) );
|
||||
}
|
||||
|
||||
/* Copy to/from real-mode stack */
|
||||
extern uint16_t copy_to_rm_stack ( void *data, size_t size );
|
||||
extern void remove_from_rm_stack ( void *data, size_t size );
|
||||
|
||||
22
src/arch/i386/include/old_realmode.h
Normal file
22
src/arch/i386/include/old_realmode.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _OLD_REALMODE_H
|
||||
#define _OLD_REALMODE_H
|
||||
|
||||
#include <realmode.h>
|
||||
|
||||
#warning "Anything including this header is obsolete and must be rewritten"
|
||||
|
||||
/* Just for now */
|
||||
#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 )
|
||||
#define OFFSET(x) ( virt_to_phys ( x ) & 0xf )
|
||||
#define SEGOFF(x) { OFFSET(x), SEGMENT(x) }
|
||||
|
||||
/* To make basemem.c compile */
|
||||
extern int lock_real_mode_stack;
|
||||
extern char *real_mode_stack;
|
||||
extern char real_mode_stack_size[];
|
||||
|
||||
#define RM_FRAGMENT(name,asm) \
|
||||
void name ( void ) {} \
|
||||
extern char name ## _size[];
|
||||
|
||||
#endif /* _OLD_REALMODE_H */
|
||||
@@ -149,25 +149,6 @@ typedef struct segoff segoff_t;
|
||||
* "(discard)" in the above code.
|
||||
*/
|
||||
|
||||
#warning "realmode.h contains placeholders for obsolete macros"
|
||||
|
||||
|
||||
/* Just for now */
|
||||
#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 )
|
||||
#define OFFSET(x) ( virt_to_phys ( x ) & 0xf )
|
||||
#define SEGOFF(x) { OFFSET(x), SEGMENT(x) }
|
||||
|
||||
/* To make basemem.c compile */
|
||||
extern int lock_real_mode_stack;
|
||||
extern char *real_mode_stack;
|
||||
extern char real_mode_stack_size[];
|
||||
|
||||
#define RM_FRAGMENT(name,asm) \
|
||||
void name ( void ) {} \
|
||||
extern char name ## _size[];
|
||||
|
||||
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /* REALMODE_H */
|
||||
|
||||
Reference in New Issue
Block a user