VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Thunk/EfiThunk.asm@ 32130

Last change on this file since 32130 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1; $Id: EfiThunk.asm 28800 2010-04-27 08:22:32Z vboxsync $
2;; @file
3; 16-bit EFI Thunk - 16-bit code executed immediately after CPU startup/reset,
4; performs minimal setup, switches CPU to 32-bit mode
5; and passes control to the 32-bit firmware entry point
6;
7;; @todo yasm 0.8.0 got binary sections which could simplify things in this file,
8; see: http://www.tortall.net/projects/yasm/manual/html/manual.html#objfmt-bin-section
9
10;
11; Copyright (C) 2009 Oracle Corporation
12;
13; This file is part of VirtualBox Open Source Edition (OSE), as
14; available from http://www.virtualbox.org. This file is free software;
15; you can redistribute it and/or modify it under the terms of the GNU
16; General Public License (GPL) as published by the Free Software
17; Foundation, in version 2 as it comes in the "COPYING" file of the
18; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20;
21
22;*******************************************************************************
23;* Defined Constants And Macros *
24;*******************************************************************************
25;; we'll use no more than 128 vectors atm
26%define IDT_VECTORS 128
27;; keep in sync with actual GDT size
28%define GDT_SELECTORS 10
29
30
31;*******************************************************************************
32;* Header Files *
33;*******************************************************************************
34%include "VBox/asmdefs.mac"
35%include "VBox/x86.mac"
36%include "DevEFI.mac"
37
38;
39; 0xfffff000/0xf000 - Where we start.
40;
41 ORG 0xf000
42
43;
44; 0xfffff000/0xf000 - Parameters passed by DevEFI, DEVEFIINFO.
45;
46DevEfiParameters:
47 times DEVEFIINFO_size db 0
48
49;
50; The IDT.
51; The first 16 vectors have dedicated handlers to ease debugging.
52; The remaining uses a common handler.
53;
54align 16
55efi_thunk_IDT:
56%assign i 0
57%rep 16
58 dw Trap_ %+ i, 0x10, 0x8e00, 0xffff
59 %assign i i+1
60%endrep
61 times IDT_VECTORS-16 dw DefaultTrap, 0x10, 0x8e00, 0xffff
62
63
64;
65; The GDT.
66; Note! Keep this in sync with GDT_SELECTORS.
67;
68align 16
69efi_thunk_GDT:
70 dw 0, 0, 0, 0 ; null selector
71 dw 0, 0, 0, 0 ; ditto
72 dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10)
73 dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
74 dw 0xffff, 0, 0x9b00, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff - FIXME: the base is 0, not f0000 here.
75 dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff - FIXME: ditto.
76 dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat stack segment (0x30)
77 dw 0xffff, 0, 0x9a00, 0x00af ; 64 bit flat code segment (0x38)
78 dw 0, 0, 0, 0 ; ditto
79 dw 0, 0, 0, 0 ; ditto
80
81;; For lidt
82efi_thunk_idtr:
83 dw 8*IDT_VECTORS-1 ; limit 15:00
84 dw efi_thunk_IDT ; base 15:00
85 db 0x0f ; base 23:16
86 db 0x00 ; unused
87
88;; For lgdt
89efi_thunk_gdtr:
90 dw 8*GDT_SELECTORS-1 ; limit 15:00
91 dw efi_thunk_GDT ; base 15:00
92 db 0x0f ; base 23:16
93 db 0x00 ; unused
94
95BITS 32
96
97;;
98; The default trap/interrupt handler.
99;
100DefaultTrap:
101 push ebp
102 mov ebp, esp
103 mov eax, EFI_PANIC_CMD_THUNK_TRAP
104 mov edx, EFI_PANIC_PORT
105 out dx, al
106 jmp HaltForEver
107
108;;
109; Generate 16 Trap_N handlers that pushes trap number on the stack.
110%assign i 0
111%rep 16
112Trap_ %+ i:
113 push ebp ; Create a valid stackframe for the debugger. (not
114 push byte i ; quite true if there is an error value pushed)
115 jmp CommonTrap
116 %assign i i+1
117%endrep
118
119;;
120; Common trap handler for the 16 dedicated ones.
121;
122CommonTrap:
123 lea ebp, [esp + 4] ; stack frame part 2.
124 push edx
125 push eax
126 mov edx, EFI_PANIC_PORT
127 mov eax, EFI_PANIC_CMD_THUNK_TRAP
128 out dx, al
129
130HaltForEver:
131 cli
132 hlt
133 jmp short HaltForEver ; In case of NMI.
134
135BITS 16
136;;
137; This i the place where we jump immediately after boot and
138; switch the CPU into protected mode.
139;
140genesis:
141%ifdef DISABLED_CODE
142 ; Say 'Hi' to the granny!
143 mov al, 0x41
144 mov dx, EFI_DEBUG_PORT
145 out dx, al
146%endif
147 cli ; paranoia
148
149
150 ; enable a20
151 in al, 0x92
152 or al, 0x02
153 out 0x92, al
154
155 ; check that we loaded in the right place
156 cmp word [cs:efi_thunk_gdtr], 8*GDT_SELECTORS-1
157 je load_ok
158 ; panic if our offset is wrong, which most likely means invalid ORG
159 mov ax, EFI_PANIC_CMD_BAD_ORG
160 mov dx, EFI_PANIC_PORT
161 out dx, al
162load_ok:
163
164 ; load IDTR and GDTR.
165 cs lidt [efi_thunk_idtr]
166 cs lgdt [efi_thunk_gdtr]
167
168 ; set PE bit in CR0, not paged
169 mov eax, cr0
170 or al, X86_CR0_PE
171 mov cr0, eax
172
173 ; start protected mode code: ljmpl 0x10:code_32
174 db 0x66, 0xea
175 dw code_32 ; low offset word
176 dw 0xffff ; high offset word
177 dw 0x0010 ; protected mode CS selector
178
179 ;
180 ; At this point we're in 32-bit protected mode
181 ;
182BITS 32
183code_32:
184 ; load some segments
185 mov ax, 0x18 ; Flat 32-bit data segment
186 mov ds, ax
187 mov es, ax
188 mov ax, 0x30 ; Flat 32-bit stack segment
189 mov ss, ax
190 ; load the null selector into FS/GS (catches unwanted accesses)
191 xor ax, ax
192 mov gs, ax
193 mov fs, ax
194
195 ;
196 ; Switch stack, have it start at the last page before 2M
197 ;
198 mov esp, 0xfffff000;
199
200 ;
201 ; Jump to 32-bit entry point of the firmware, interrupts still disabled.
202 ;
203 ; It's up to the firmware init code to setup a working IDT (and optionally
204 ; GDT and TSS) before enabling interrupts. It may also switch the stack
205 ; around all it wants for all we care.
206 ;
207 mov eax,[0xfffff000 + DEVEFIINFO.fFlags]
208 and eax, DEVEFI_INFO_FLAGS_AMD64
209 jnz trampoline_64
210 mov ebp, [0xfffff000 + DEVEFIINFO.PhysFwVol]
211 mov esi, [0xfffff000 + DEVEFIINFO.pfnFirmwareEP]
212 mov edi, [0xfffff000 + DEVEFIINFO.pfnPeiEP]
213 jmp [0xfffff000 + DEVEFIINFO.pfnFirmwareEP]
214 jmp HaltForEver
215trampoline_64:
216%macro fill_pkt 1
217%%loop:
218 mov [ebx],eax
219 xor edx,edx
220 mov [ebx + 4], edx
221 add ebx, 8
222 add eax, %1
223 loop %%loop
224%endmacro
225
226%define base 0x800000;0xfffff000
227 mov ecx, 0x800 ; pde size
228 mov ebx, base - (6 << X86_PAGE_4K_SHIFT)
229 xor eax, eax
230 ;; or flags to eax
231 or eax, (X86_PDE_P|X86_PDE_A|X86_PDE_PS|X86_PDE_PCD|X86_PDE_RW|RT_BIT(6))
232 fill_pkt (1 << X86_PAGE_2M_SHIFT)
233
234 ;; pdpt (1st 4 entries describe 4Gb)
235 mov ebx, base - (2 << X86_PAGE_4K_SHIFT)
236 mov eax, base - (6 << X86_PAGE_4K_SHIFT) ;;
237 or eax, (X86_PDPE_P|X86_PDPE_RW|X86_PDPE_A|X86_PDPE_PCD)
238 mov [ebx],eax
239 xor edx,edx
240 mov [ebx + 4], edx
241 add ebx, 8
242
243 mov eax, base - 5 * (1 << X86_PAGE_4K_SHIFT) ;;
244 or eax, (X86_PDPE_P|X86_PDPE_RW|X86_PDPE_A|X86_PDPE_PCD)
245 mov [ebx],eax
246 xor edx,edx
247 mov [ebx + 4], edx
248 add ebx, 8
249
250 mov eax, base - 4 * (1 << X86_PAGE_4K_SHIFT) ;;
251 or eax, (X86_PDPE_P|X86_PDPE_RW|X86_PDPE_A|X86_PDPE_PCD)
252 mov [ebx],eax
253 xor edx,edx
254 mov [ebx + 4], edx
255 add ebx, 8
256
257 mov eax, base - 3 * (1 << X86_PAGE_4K_SHIFT) ;;
258 or eax, (X86_PDPE_P|X86_PDPE_RW|X86_PDPE_A|X86_PDPE_PCD)
259 mov [ebx],eax
260 xor edx,edx
261 mov [ebx + 4], edx
262 add ebx, 8
263
264 mov ecx, 0x1f7 ; pdte size
265 mov ebx, base - 2 * (1 << X86_PAGE_4K_SHIFT) + 4 * 8
266 mov eax, base - 6 * (1 << X86_PAGE_4K_SHIFT);;
267 or eax, (X86_PDPE_P|X86_PDPE_RW|X86_PDPE_A|X86_PDPE_PCD)
268 ;; or flags to eax
269 fill_pkt 3 * (1 << X86_PAGE_4K_SHIFT)
270
271 mov ecx, 0x200 ; pml4 size
272 mov ebx, base - (1 << X86_PAGE_4K_SHIFT)
273 mov eax, base - 2 * (1 << X86_PAGE_4K_SHIFT) ;;
274 or eax, (X86_PML4E_P|X86_PML4E_PCD|X86_PML4E_A|X86_PML4E_RW)
275 ;; or flags to eax
276 fill_pkt 0
277
278 mov eax, base - (1 << X86_PAGE_4K_SHIFT)
279 mov cr3, eax
280
281
282 mov eax,cr4
283 or eax, X86_CR4_PAE|X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT
284 mov cr4,eax
285
286 mov ecx, MSR_K6_EFER
287 rdmsr
288 or eax, MSR_K6_EFER_LME
289 wrmsr
290
291 mov eax, cr0
292 or eax, X86_CR0_PG
293 mov cr0, eax
294 jmp compat
295compat:
296 jmp 0x38:0xffff0000 + efi_64
297BITS 64
298efi_64:
299 mov ebp, [0xff009] ; DEVEFIINFO.PhysFwVol
300 mov esi, [0xff000]; + DEVEFIINFO.pfnFirmwareEP]
301 mov edi, [0xff000 + 0x28]; + DEVEFIINFO.pfnPeiEP]
302 jmp [0xff000]; + DEVEFIINFO.pfnFirmwareEP]
303 jmp HaltForEver
304
305 ;
306 ; 0xfffffff0/0xfff0 - This is where the CPU starts executing.
307 ;
308 ;; @todo yasm 0.8.0: SECTION .text start=0fff0h vstart=0fff0h ?
309 times 0xff0-$+DevEfiParameters db 0cch ; Note! $ isn't moved by ORG (yasm v0.6.2).
310cpu_start:
311 BITS 16
312 jmp genesis
313 dw 0xdead
314 dw 0xbeaf
315 times (16 - 7) db 0cch
316end:
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette