iPXE
realmode.h
Go to the documentation of this file.
1 #ifndef REALMODE_H
2 #define REALMODE_H
3 
4 #include <stdint.h>
5 #include <string.h>
6 #include <registers.h>
7 #include <librm.h>
8 #include <ipxe/uaccess.h>
9 
10 /*
11  * Data structures and type definitions
12  *
13  */
14 
15 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
16 
17 /*
18  * Declaration of variables in .data16
19  *
20  * To place a variable in the .data16 segment, declare it using the
21  * pattern:
22  *
23  * int __data16 ( foo );
24  * #define foo __use_data16 ( foo );
25  *
26  * extern uint32_t __data16 ( bar );
27  * #define bar __use_data16 ( bar );
28  *
29  * static long __data16 ( baz ) = 0xff000000UL;
30  * #define baz __use_data16 ( baz );
31  *
32  * i.e. take a normal declaration, add __data16() around the variable
33  * name, and add a line saying "#define <name> __use_data16 ( <name> )
34  *
35  * You can then access them just like any other variable, for example
36  *
37  * int x = foo + bar;
38  *
39  * This magic is achieved at a cost of only around 7 extra bytes per
40  * group of accesses to .data16 variables. When using KEEP_IT_REAL,
41  * there is no extra cost.
42  *
43  * You should place variables in .data16 when they need to be accessed
44  * by real-mode code. Real-mode assembly (e.g. as created by
45  * REAL_CODE()) can access these variables via the usual data segment.
46  * You can therefore write something like
47  *
48  * static uint16_t __data16 ( foo );
49  * #define foo __use_data16 ( foo )
50  *
51  * int bar ( void ) {
52  * __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t"
53  * "movw %ax, foo" )
54  * : : );
55  * return foo;
56  * }
57  *
58  * Variables may also be placed in .text16 using __text16 and
59  * __use_text16. Some variables (e.g. chained interrupt vectors) fit
60  * most naturally in .text16; most should be in .data16.
61  *
62  * If you have only a pointer to a magic symbol within .data16 or
63  * .text16, rather than the symbol itself, you can attempt to extract
64  * the underlying symbol name using __from_data16() or
65  * __from_text16(). This is not for the faint-hearted; check the
66  * assembler output to make sure that it's doing the right thing.
67  */
68 
69 /**
70  * Convert segment:offset address to virtual address
71  *
72  * @v segment Real-mode segment
73  * @v offset Real-mode offset
74  * @ret virt Virtual address
75  */
76 static inline __always_inline void *
77 real_to_virt ( unsigned int segment, unsigned int offset ) {
78  return ( phys_to_virt ( ( segment << 4 ) + offset ) );
79 }
80 
81 /**
82  * Copy data to base memory
83  *
84  * @v dest_seg Destination segment
85  * @v dest_off Destination offset
86  * @v src Source
87  * @v len Length
88  */
89 static inline __always_inline void
90 copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
91  void *src, size_t n ) {
92  memcpy ( real_to_virt ( dest_seg, dest_off ), src, n );
93 }
94 
95 /**
96  * Copy data to base memory
97  *
98  * @v dest Destination
99  * @v src_seg Source segment
100  * @v src_off Source offset
101  * @v len Length
102  */
103 static inline __always_inline void
104 copy_from_real ( void *dest, unsigned int src_seg,
105  unsigned int src_off, size_t n ) {
106  memcpy ( dest, real_to_virt ( src_seg, src_off ), n );
107 }
108 
109 /**
110  * Write a single variable to base memory
111  *
112  * @v var Variable to write
113  * @v dest_seg Destination segment
114  * @v dest_off Destination offset
115  */
116 #define put_real( var, dest_seg, dest_off ) \
117  copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
118 
119 /**
120  * Read a single variable from base memory
121  *
122  * @v var Variable to read
123  * @v src_seg Source segment
124  * @v src_off Source offset
125  */
126 #define get_real( var, src_seg, src_off ) \
127  copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
128 
129 /*
130  * REAL_CODE ( asm_code_str )
131  *
132  * This can be used in inline assembly to create a fragment of code
133  * that will execute in real mode. For example: to write a character
134  * to the BIOS console using INT 10, you would do something like:
135  *
136  * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
137  * : "=a" ( character ) : "a" ( 0x0000 ) );
138  *
139  */
140 
141 #endif /* REALMODE_H */
uint16_t segment
Code segment.
Definition: librm.h:138
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
i386 registers.
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition: realmode.h:77
void * memcpy(void *dest, const void *src, size_t len) __nonnull
Access to external ("user") memory.
static const void * src
Definition: string.h:47
static __always_inline void copy_to_real(unsigned int dest_seg, unsigned int dest_off, void *src, size_t n)
Copy data to base memory.
Definition: realmode.h:90
#define __always_inline
Declare a function to be always inline.
Definition: compiler.h:611
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
String functions.
static __always_inline void copy_from_real(void *dest, unsigned int src_seg, unsigned int src_off, size_t n)
Copy data to base memory.
Definition: realmode.h:104