mirror of
https://github.com/xcat2/xNBA.git
synced 2025-08-22 03:00:30 +00:00
Access to the gpxe.org and etherboot.org domains and associated resources has been revoked by the registrant of the domain. Work around this problem by renaming project from gPXE to iPXE, and updating URLs to match. Also update README, LOG and COPYRIGHTS to remove obsolete information. Signed-off-by: Michael Brown <mcb30@ipxe.org>
128 lines
3.5 KiB
C
128 lines
3.5 KiB
C
#ifndef REALMODE_H
|
|
#define REALMODE_H
|
|
|
|
#include <stdint.h>
|
|
#include <registers.h>
|
|
#include <ipxe/uaccess.h>
|
|
|
|
/*
|
|
* Data structures and type definitions
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER );
|
|
|
|
/*
|
|
* Declaration of variables in .data16
|
|
*
|
|
* To place a variable in the .data16 segment, declare it using the
|
|
* pattern:
|
|
*
|
|
* int __data16 ( foo );
|
|
* #define foo __use_data16 ( foo );
|
|
*
|
|
* extern uint32_t __data16 ( bar );
|
|
* #define bar __use_data16 ( bar );
|
|
*
|
|
* static long __data16 ( baz ) = 0xff000000UL;
|
|
* #define baz __use_data16 ( baz );
|
|
*
|
|
* i.e. take a normal declaration, add __data16() around the variable
|
|
* name, and add a line saying "#define <name> __use_data16 ( <name> )
|
|
*
|
|
* You can then access them just like any other variable, for example
|
|
*
|
|
* int x = foo + bar;
|
|
*
|
|
* This magic is achieved at a cost of only around 7 extra bytes per
|
|
* group of accesses to .data16 variables. When using KEEP_IT_REAL,
|
|
* there is no extra cost.
|
|
*
|
|
* You should place variables in .data16 when they need to be accessed
|
|
* by real-mode code. Real-mode assembly (e.g. as created by
|
|
* REAL_CODE()) can access these variables via the usual data segment.
|
|
* You can therefore write something like
|
|
*
|
|
* static uint16_t __data16 ( foo );
|
|
* #define foo __use_data16 ( foo )
|
|
*
|
|
* int bar ( void ) {
|
|
* __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t"
|
|
* "movw %ax, foo" )
|
|
* : : );
|
|
* return foo;
|
|
* }
|
|
*
|
|
* Variables may also be placed in .text16 using __text16 and
|
|
* __use_text16. Some variables (e.g. chained interrupt vectors) fit
|
|
* most naturally in .text16; most should be in .data16.
|
|
*
|
|
* If you have only a pointer to a magic symbol within .data16 or
|
|
* .text16, rather than the symbol itself, you can attempt to extract
|
|
* the underlying symbol name using __from_data16() or
|
|
* __from_text16(). This is not for the faint-hearted; check the
|
|
* assembler output to make sure that it's doing the right thing.
|
|
*/
|
|
|
|
/**
|
|
* Copy data to 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 );
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*
|
|
* @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 )
|
|
*
|
|
* This can be used in inline assembly to create a fragment of code
|
|
* that will execute in real mode. For example: to write a character
|
|
* to the BIOS console using INT 10, you would do something like:
|
|
*
|
|
* __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
|
|
* : "=a" ( character ) : "a" ( 0x0000 ) );
|
|
*
|
|
*/
|
|
|
|
#endif /* REALMODE_H */
|