iPXE
librm.h
Go to the documentation of this file.
1#ifndef LIBRM_H
2#define LIBRM_H
4FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
6/* Segment selectors as used in our protected-mode GDTs.
7 *
8 * Don't change these unless you really know what you're doing.
9 */
10#define VIRTUAL_CS 0x08
11#define VIRTUAL_DS 0x10
12#define PHYSICAL_CS 0x18
13#define PHYSICAL_DS 0x20
14#define REAL_CS 0x28
15#define REAL_DS 0x30
16#define P2R_DS 0x38
17#define LONG_CS 0x40
19/* Calculate symbol address within VIRTUAL_CS or VIRTUAL_DS
20 *
21 * In a 64-bit build, we set the bases of VIRTUAL_CS and VIRTUAL_DS
22 * such that truncating a .textdata symbol value to 32 bits gives a
23 * valid 32-bit virtual address.
24 *
25 * The C code is compiled with -mcmodel=kernel and so we must place
26 * all .textdata symbols within the negative 2GB of the 64-bit address
27 * space. Consequently, all .textdata symbols will have the MSB set
28 * after truncation to 32 bits. This means that a straightforward
29 * R_X86_64_32 relocation record for the symbol will fail, since the
30 * truncated symbol value will not correctly zero-extend to the
31 * original 64-bit value.
32 *
33 * Using an R_X86_64_32S relocation record would work, but there is no
34 * (sensible) way to generate these relocation records within 32-bit
35 * or 16-bit code.
36 *
37 * The simplest solution is to generate an R_X86_64_32 relocation
38 * record with an addend of (-0xffffffff00000000). Since all
39 * .textdata symbols are within the negative 2GB of the 64-bit address
40 * space, this addend acts to effectively truncate the symbol to 32
41 * bits, thereby matching the semantics of the R_X86_64_32 relocation
42 * records generated for 32-bit and 16-bit code.
43 *
44 * In a 32-bit build, this problem does not exist, and we can just use
45 * the .textdata symbol values directly.
46 */
47#ifdef __x86_64__
48#define VIRTUAL(address) ( (address) - 0xffffffff00000000 )
49#else
50#define VIRTUAL(address) (address)
51#endif
52
53#ifdef ASSEMBLY
54
55/**
56 * Call C function from real-mode code
57 *
58 * @v function C function
59 */
60.macro virtcall function
61 pushl $VIRTUAL(\function)
62 call virt_call
63.endm
64
65#else /* ASSEMBLY */
66
67/**
68 * Call C function from real-mode code
69 *
70 * @v function C function
71 */
72#define VIRT_CALL( function ) \
73 "pushl $( " _S2 ( VIRTUAL ( function ) ) " )\n\t" \
74 "call virt_call\n\t"
75
76/******************************************************************************
77 *
78 * Access to variables in .data16 and .text16
79 *
80 */
81
82extern char * const data16;
83extern char * const text16;
84
85#define __data16( variable ) \
86 __attribute__ (( section ( ".data16" ) )) \
87 _data16_ ## variable __asm__ ( #variable )
88
89#define __data16_array( variable, array ) \
90 __attribute__ (( section ( ".data16" ) )) \
91 _data16_ ## variable array __asm__ ( #variable )
92
93#define __bss16( variable ) \
94 __attribute__ (( section ( ".bss16" ) )) \
95 _data16_ ## variable __asm__ ( #variable )
96
97#define __bss16_array( variable, array ) \
98 __attribute__ (( section ( ".bss16" ) )) \
99 _data16_ ## variable array __asm__ ( #variable )
100
101#define __text16( variable ) \
102 __attribute__ (( section ( ".text16.data" ) )) \
103 _text16_ ## variable __asm__ ( #variable )
104
105#define __text16_array( variable, array ) \
106 __attribute__ (( section ( ".text16.data" ) )) \
107 _text16_ ## variable array __asm__ ( #variable )
108
109#define __use_data16( variable ) \
110 ( * ( ( typeof ( _data16_ ## variable ) * ) \
111 & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
112
113#define __use_text16( variable ) \
114 ( * ( ( typeof ( _text16_ ## variable ) * ) \
115 & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
116
117#define __from_data16( pointer ) \
118 ( ( unsigned int ) \
119 ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
120
121#define __from_text16( pointer ) \
122 ( ( unsigned int ) \
123 ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
124
125/* Variables in librm.S, present in the normal data segment */
126extern uint16_t rm_sp;
127extern uint16_t rm_ss;
128extern const uint16_t __text16 ( rm_cs );
129#define rm_cs __use_text16 ( rm_cs )
130extern const uint16_t __text16 ( rm_ds );
131#define rm_ds __use_text16 ( rm_ds )
132
133extern uint16_t copy_to_rm_stack ( const void *data, size_t size );
134extern void remove_from_rm_stack ( void *data, size_t size );
135
136/* CODE_DEFAULT: restore default .code32/.code64 directive */
137#ifdef __x86_64__
138#define CODE_DEFAULT ".code64"
139#define STACK_DEFAULT "q"
140#else
141#define CODE_DEFAULT ".code32"
142#define STACK_DEFAULT "l"
143#endif
144
145/* LINE_SYMBOL: declare a symbol for the current source code line */
146#define LINE_SYMBOL _S2 ( OBJECT ) "__line_" _S2 ( __LINE__ ) "__%=:"
147
148/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
149#define TEXT16_CODE( asm_code_str ) \
150 ".section \".text16\", \"ax\", @progbits\n\t" \
151 "\n" LINE_SYMBOL "\n\t" \
152 ".code16\n\t" \
153 asm_code_str "\n\t" \
154 CODE_DEFAULT "\n\t" \
155 ".previous\n\t"
156
157/* REAL_CODE: declare a fragment of code that executes in real mode */
158#define REAL_CODE( asm_code_str ) \
159 "push" STACK_DEFAULT " $1f\n\t" \
160 "call real_call\n\t" \
161 TEXT16_CODE ( "\n1:\n\t" \
162 asm_code_str \
163 "\n\t" \
164 "ret\n\t" )
165
166/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
167#define PHYS_CODE( asm_code_str ) \
168 "push" STACK_DEFAULT " $1f\n\t" \
169 "call phys_call\n\t" \
170 ".section \".text.phys\", \"ax\", @progbits\n\t"\
171 "\n" LINE_SYMBOL "\n\t" \
172 ".code32\n\t" \
173 "\n1:\n\t" \
174 asm_code_str \
175 "\n\t" \
176 "ret\n\t" \
177 CODE_DEFAULT "\n\t" \
178 ".previous\n\t"
179
180/** Number of interrupts */
181#define NUM_INT 256
182
183/** A 32-bit interrupt descriptor table register */
184struct idtr32 {
185 /** Limit */
187 /** Base */
189} __attribute__ (( packed ));
190
191/** A 64-bit interrupt descriptor table register */
192struct idtr64 {
193 /** Limit */
195 /** Base */
197} __attribute__ (( packed ));
198
199/** A 32-bit interrupt descriptor table entry */
201 /** Low 16 bits of address */
203 /** Code segment */
205 /** Unused */
207 /** Type and attributes */
209 /** High 16 bits of address */
211} __attribute__ (( packed ));
212
213/** A 64-bit interrupt descriptor table entry */
215 /** Low 16 bits of address */
217 /** Code segment */
219 /** Unused */
221 /** Type and attributes */
223 /** Middle 16 bits of address */
225 /** High 32 bits of address */
227 /** Reserved */
229} __attribute__ (( packed ));
230
231/** Interrupt descriptor is present */
232#define IDTE_PRESENT 0x80
233
234/** Interrupt descriptor 32-bit interrupt gate type */
235#define IDTE_TYPE_IRQ32 0x0e
236
237/** Interrupt descriptor 64-bit interrupt gate type */
238#define IDTE_TYPE_IRQ64 0x0e
239
240/** An interrupt vector
241 *
242 * Each interrupt vector comprises an eight-byte fragment of code:
243 *
244 * 50 pushl %eax (or pushq %rax in long mode)
245 * b0 xx movb $INT, %al
246 * e9 xx xx xx xx jmp interrupt_wrapper
247 */
249 /** "push" instruction */
251 /** "movb" instruction */
253 /** Interrupt number */
255 /** "jmp" instruction */
257 /** Interrupt wrapper address offset */
259 /** Next instruction after jump */
261} __attribute__ (( packed ));
262
263/** "push %eax" instruction */
264#define PUSH_INSN 0x50
265
266/** "movb" instruction */
267#define MOVB_INSN 0xb0
268
269/** "jmp" instruction */
270#define JMP_INSN 0xe9
271
272/** 32-bit interrupt wrapper stack frame */
291
292/** 64-bit interrupt wrapper stack frame */
315
316extern void set_interrupt_vector ( unsigned int intr, void *vector );
317
318/** A page table */
320 /** Page address and flags */
323
324/** Page flags */
326 /** Page is present */
327 PAGE_P = 0x01,
328 /** Page is writable */
329 PAGE_RW = 0x02,
330 /** Page is accessible by user code */
331 PAGE_US = 0x04,
332 /** Page-level write-through */
333 PAGE_PWT = 0x08,
334 /** Page-level cache disable */
335 PAGE_PCD = 0x10,
336 /** Page is a large page */
337 PAGE_PS = 0x80,
338 /** Page is the last page in an allocation
339 *
340 * This bit is ignored by the hardware. We use it to track
341 * the size of allocations made by ioremap().
342 */
343 PAGE_LAST = 0x800,
344};
345
346/** The I/O space page table */
347extern struct page_table io_pages;
348
349/** Maximum number of I/O pages */
350#define IO_PAGE_COUNT \
351 ( sizeof ( io_pages.page ) / sizeof ( io_pages.page[0] ) )
352
353/** I/O page size
354 *
355 * We choose to use 2MB pages for I/O space, to minimise the number of
356 * page table entries required.
357 */
358#define IO_PAGE_SIZE 0x200000UL
359
360/** I/O page base address
361 *
362 * We choose to place I/O space immediately above the identity-mapped
363 * 32-bit address space.
364 */
365#define IO_BASE ( ( void * ) 0x100000000ULL )
366
367/** Startup IPI real-mode handler */
368extern char __text16_array ( sipi, [] );
369#define sipi __use_text16 ( sipi )
370
371/** Length of startup IPI real-mode handler */
372extern size_t ABS_SYMBOL ( sipi_len );
373#define sipi_len ABS_VALUE ( sipi_len )
374
375/** Startup IPI real-mode handler copy of real-mode data segment */
377#define sipi_ds __use_text16 ( sipi_ds )
378
379/** Startup IPI protected-mode handler (physical address) */
381
382/** Startup IPI register state */
383extern struct i386_regs sipi_regs;
384
385extern void setup_sipi ( unsigned int vector, uint32_t handler,
386 struct i386_regs *regs );
387
388#endif /* ASSEMBLY */
389
390#endif /* LIBRM_H */
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
uint8_t function
Function.
Definition edd.h:5
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint32_t vector
MSI-X vector.
Definition ena.h:9
uint8_t intr
Interrupts enabled.
Definition ena.h:3
#define ABS_SYMBOL(name)
Declare an absolute symbol (e.g.
Definition compiler.h:655
uint16_t size
Buffer size.
Definition dwmac.h:3
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
struct page_table __attribute__
#define rm_ds
Definition libkir.h:39
#define rm_cs
Definition libkir.h:38
uint16_t copy_to_rm_stack(const void *data, size_t size)
Allocate space on the real-mode stack and copy data there.
Definition librm_mgmt.c:67
uint16_t rm_ss
void set_interrupt_vector(unsigned int intr, void *vector)
Set interrupt vector.
Definition librm_mgmt.c:98
char *const text16
uint32_t sipi_handler
Startup IPI protected-mode handler (physical address)
#define sipi_ds
Definition librm.h:377
void remove_from_rm_stack(void *data, size_t size)
Deallocate space on the real-mode stack, optionally copying back data.
Definition librm_mgmt.c:82
#define __text16_array(variable, array)
Definition librm.h:105
page_flags
Page flags.
Definition librm.h:325
@ PAGE_RW
Page is writable.
Definition librm.h:329
@ PAGE_PWT
Page-level write-through.
Definition librm.h:333
@ PAGE_US
Page is accessible by user code.
Definition librm.h:331
@ PAGE_LAST
Page is the last page in an allocation.
Definition librm.h:343
@ PAGE_P
Page is present.
Definition librm.h:327
@ PAGE_PCD
Page-level cache disable.
Definition librm.h:335
@ PAGE_PS
Page is a large page.
Definition librm.h:337
#define __text16(variable)
Definition librm.h:101
#define sipi_len
Definition librm.h:373
struct page_table io_pages
The I/O space page table.
uint16_t rm_sp
void setup_sipi(unsigned int vector, uint32_t handler, struct i386_regs *regs)
Set up startup IPI handler.
Definition librm_mgmt.c:417
#define sipi
Definition librm.h:369
char *const data16
Definition ib_mad.h:8
struct i386_regs sipi_regs
Startup IPI register state.
Definition librm_mgmt.c:49
struct i386_regs regs
Definition registers.h:1
A 32-bit general register dump.
Definition registers.h:62
A 32-bit interrupt descriptor table register.
Definition librm.h:184
uint32_t base
Base.
Definition librm.h:188
uint16_t limit
Limit.
Definition librm.h:186
A 64-bit interrupt descriptor table register.
Definition librm.h:192
uint16_t limit
Limit.
Definition librm.h:194
uint64_t base
Base.
Definition librm.h:196
A 32-bit interrupt descriptor table entry.
Definition librm.h:200
uint16_t low
Low 16 bits of address.
Definition librm.h:202
uint16_t segment
Code segment.
Definition librm.h:204
uint8_t attr
Type and attributes.
Definition librm.h:208
uint16_t high
High 16 bits of address.
Definition librm.h:210
uint8_t unused
Unused.
Definition librm.h:206
A 64-bit interrupt descriptor table entry.
Definition librm.h:214
uint8_t attr
Type and attributes.
Definition librm.h:222
uint16_t segment
Code segment.
Definition librm.h:218
uint32_t reserved
Reserved.
Definition librm.h:228
uint32_t high
High 32 bits of address.
Definition librm.h:226
uint16_t mid
Middle 16 bits of address.
Definition librm.h:224
uint8_t unused
Unused.
Definition librm.h:220
uint16_t low
Low 16 bits of address.
Definition librm.h:216
32-bit interrupt wrapper stack frame
Definition librm.h:273
uint32_t edi
Definition librm.h:281
uint32_t esi
Definition librm.h:282
uint32_t cs
Definition librm.h:288
uint32_t ss
Definition librm.h:275
uint32_t ecx
Definition librm.h:284
uint32_t fs
Definition librm.h:277
uint32_t gs
Definition librm.h:276
uint32_t edx
Definition librm.h:283
uint32_t ebx
Definition librm.h:285
uint32_t esp
Definition librm.h:274
uint32_t eflags
Definition librm.h:289
uint32_t eax
Definition librm.h:286
uint32_t es
Definition librm.h:278
uint32_t ds
Definition librm.h:279
uint32_t ebp
Definition librm.h:280
uint32_t eip
Definition librm.h:287
64-bit interrupt wrapper stack frame
Definition librm.h:293
uint64_t rdi
Definition librm.h:303
uint64_t r14
Definition librm.h:295
uint64_t r12
Definition librm.h:297
uint64_t rsi
Definition librm.h:304
uint64_t r11
Definition librm.h:298
uint64_t rip
Definition librm.h:309
uint64_t rdx
Definition librm.h:305
uint64_t rbp
Definition librm.h:302
uint64_t r9
Definition librm.h:300
uint64_t rsp
Definition librm.h:312
uint64_t cs
Definition librm.h:310
uint64_t rflags
Definition librm.h:311
uint64_t ss
Definition librm.h:313
uint64_t rbx
Definition librm.h:307
uint64_t r13
Definition librm.h:296
uint64_t r8
Definition librm.h:301
uint64_t r15
Definition librm.h:294
uint64_t rcx
Definition librm.h:306
uint64_t r10
Definition librm.h:299
uint64_t rax
Definition librm.h:308
An interrupt vector.
Definition librm.h:248
uint8_t push
"push" instruction
Definition librm.h:250
uint32_t offset
Interrupt wrapper address offset.
Definition librm.h:258
uint8_t jmp
"jmp" instruction
Definition librm.h:256
uint8_t movb
"movb" instruction
Definition librm.h:252
uint8_t intr
Interrupt number.
Definition librm.h:254
uint8_t next[0]
Next instruction after jump.
Definition librm.h:260
A page table.
Definition librm.h:319
uint64_t page[512]
Page address and flags.
Definition librm.h:321