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
15FILE_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 */
76static inline __always_inline void *
77real_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 */
89static inline __always_inline void
90copy_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 */
103static inline __always_inline void
104copy_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 */
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" retur dest)
Definition string.h:151
static const void * src
Definition string.h:48
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define __always_inline
Declare a function to be always inline.
Definition compiler.h:611
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
Access to external ("user") memory.
#define copy_to_real
Definition libkir.h:78
#define copy_from_real
Definition libkir.h:79
uint16_t segment
Code segment.
Definition librm.h:3
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
i386 registers.