00001 #ifndef REALMODE_H 00002 #define REALMODE_H 00003 00004 #include <stdint.h> 00005 #include <registers.h> 00006 #include <gpxe/uaccess.h> 00007 00008 /* 00009 * Data structures and type definitions 00010 * 00011 */ 00012 00013 FILE_LICENCE ( GPL2_OR_LATER ); 00014 00015 /* 00016 * Declaration of variables in .data16 00017 * 00018 * To place a variable in the .data16 segment, declare it using the 00019 * pattern: 00020 * 00021 * int __data16 ( foo ); 00022 * #define foo __use_data16 ( foo ); 00023 * 00024 * extern uint32_t __data16 ( bar ); 00025 * #define bar __use_data16 ( bar ); 00026 * 00027 * static long __data16 ( baz ) = 0xff000000UL; 00028 * #define baz __use_data16 ( baz ); 00029 * 00030 * i.e. take a normal declaration, add __data16() around the variable 00031 * name, and add a line saying "#define <name> __use_data16 ( <name> ) 00032 * 00033 * You can then access them just like any other variable, for example 00034 * 00035 * int x = foo + bar; 00036 * 00037 * This magic is achieved at a cost of only around 7 extra bytes per 00038 * group of accesses to .data16 variables. When using KEEP_IT_REAL, 00039 * there is no extra cost. 00040 * 00041 * You should place variables in .data16 when they need to be accessed 00042 * by real-mode code. Real-mode assembly (e.g. as created by 00043 * REAL_CODE()) can access these variables via the usual data segment. 00044 * You can therefore write something like 00045 * 00046 * static uint16_t __data16 ( foo ); 00047 * #define foo __use_data16 ( foo ) 00048 * 00049 * int bar ( void ) { 00050 * __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t" 00051 * "movw %ax, foo" ) 00052 * : : ); 00053 * return foo; 00054 * } 00055 * 00056 * Variables may also be placed in .text16 using __text16 and 00057 * __use_text16. Some variables (e.g. chained interrupt vectors) fit 00058 * most naturally in .text16; most should be in .data16. 00059 * 00060 * If you have only a pointer to a magic symbol within .data16 or 00061 * .text16, rather than the symbol itself, you can attempt to extract 00062 * the underlying symbol name using __from_data16() or 00063 * __from_text16(). This is not for the faint-hearted; check the 00064 * assembler output to make sure that it's doing the right thing. 00065 */ 00066 00067 /** 00068 * Copy data to base memory 00069 * 00070 * @v dest_seg Destination segment 00071 * @v dest_off Destination offset 00072 * @v src Source 00073 * @v len Length 00074 */ 00075 static inline __always_inline void 00076 copy_to_real ( unsigned int dest_seg, unsigned int dest_off, 00077 void *src, size_t n ) { 00078 copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n ); 00079 } 00080 00081 /** 00082 * Copy data to base memory 00083 * 00084 * @v dest Destination 00085 * @v src_seg Source segment 00086 * @v src_off Source offset 00087 * @v len Length 00088 */ 00089 static inline __always_inline void 00090 copy_from_real ( void *dest, unsigned int src_seg, 00091 unsigned int src_off, size_t n ) { 00092 copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n ); 00093 } 00094 00095 /** 00096 * Write a single variable to base memory 00097 * 00098 * @v var Variable to write 00099 * @v dest_seg Destination segment 00100 * @v dest_off Destination offset 00101 */ 00102 #define put_real( var, dest_seg, dest_off ) \ 00103 copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) ) 00104 00105 /** 00106 * Read a single variable from base memory 00107 * 00108 * @v var Variable to read 00109 * @v src_seg Source segment 00110 * @v src_off Source offset 00111 */ 00112 #define get_real( var, src_seg, src_off ) \ 00113 copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) ) 00114 00115 /* 00116 * REAL_CODE ( asm_code_str ) 00117 * 00118 * This can be used in inline assembly to create a fragment of code 00119 * that will execute in real mode. For example: to write a character 00120 * to the BIOS console using INT 10, you would do something like: 00121 * 00122 * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" ) 00123 * : "=a" ( character ) : "a" ( 0x0000 ) ); 00124 * 00125 */ 00126 00127 #endif /* REALMODE_H */
1.5.7.1