VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bootsector2-common-init-code.mac@ 66145

Last change on this file since 66145 was 66145, checked in by vboxsync, 8 years ago

bootsectors: Relocated shutdown port.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.4 KB
Line 
1; $Id: bootsector2-common-init-code.mac 66145 2017-03-16 20:10:59Z vboxsync $
2;; @file
3; Common bootsector code init.
4;
5; In addition to initialize the stack at %7bf0 it loads the first 512KB of the
6; floppy image at %7c00. The control is handed over with interrupts disabled
7; to a 'main' function defined by the includer.
8;
9; The following defines controls the mode we call main in:
10; - BS2_INIT_RM (default)
11; - BS2_INIT_PE32
12; - BS2_INIT_PP32
13; - BS2_INIT_PAE32
14; - BS2_INIT_LM64
15;
16; The following defines controls code inclusion:
17; - BS2_INC_RM
18; - BS2_INC_PE
19; - BS2_INC_PE16
20; - BS2_INC_PE32
21; - BS2_INC_PEV86
22; - BS2_INC_PP
23; - BS2_INC_PP16
24; - BS2_INC_PP32
25; - BS2_INC_PPV86
26; - BS2_INC_PAE
27; - BS2_INC_PAE16
28; - BS2_INC_PAE32
29; - BS2_INC_PAEV86
30; - BS2_INC_LM
31; - BS2_INC_LM16
32; - BS2_INC_LM32
33; - BS2_INC_LM64
34; - BS2_INC_CMN_R86
35; - BS2_INC_CMN_V86
36; - BS2_INC_CMN_P16
37; - BS2_INC_CMN_P32
38; - BS2_INC_CMN_P64
39; - BS2_WITH_TRAPS
40;
41
42;
43; Copyright (C) 2007-2016 Oracle Corporation
44;
45; This file is part of VirtualBox Open Source Edition (OSE), as
46; available from http://www.virtualbox.org. This file is free software;
47; you can redistribute it and/or modify it under the terms of the GNU
48; General Public License (GPL) as published by the Free Software
49; Foundation, in version 2 as it comes in the "COPYING" file of the
50; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
51; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
52;
53; The contents of this file may alternatively be used under the terms
54; of the Common Development and Distribution License Version 1.0
55; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
56; VirtualBox OSE distribution, in which case the provisions of the
57; CDDL are applicable instead of those of the GPL.
58;
59; You may elect to license modified versions of this file under the
60; terms and conditions of either the GPL or the CDDL or both.
61;
62
63
64; map files should include symbols and everything.
65[map all]
66
67;*******************************************************************************
68;* Header Files *
69;*******************************************************************************
70%include "bootsector2-structures.mac"
71%include "bootsector2-common-macros-1.mac"
72
73
74;*******************************************************************************
75;* Defined Constants And Macros *
76;*******************************************************************************
77
78;; The magic shutdown I/O port
79%define SHUTDOWN_PORT 0x040f
80
81;; @name Static Memory Allocation
82; @{
83;; The boot sector load address.
84%define BS2_ADDR 07c00h
85;; The stack is located before the code (and will overflow into the interrupt
86; table and other essential system data).
87%define STACK_ADDR (BS2_ADDR - 256)
88
89%ifdef BS2_WITH_TRAPS
90;; The address of the ring-0 stack in bs2Tss32BitDf.
91%define BS2_DF_R0_STACK_ADDR 06800h
92;; The address of the ring-0 stack in TSSxx.
93%define BS2_R0_STACK_ADDR 06000h
94;; The address of the ring-1 stack in TSSxx.
95%define BS2_R1_STACK_ADDR 05000h
96;; The address of the ring-2 stack in TSSxx.
97%define BS2_R2_STACK_ADDR 04800h
98%endif ; BS2_WITH_TRAPS
99
100;;
101; Where we save the boot registers during init.
102%define BS2_REG_SAVE_ADDR 06000h
103
104;; The start of the memory area used for paging, stacks and so forth.
105%define BS2_PXX_BASE 080000h
106
107;; The page map level 4 address (all entries point to BS2_LM_PDP_ADDR).
108%define BS2_LM_PML4_ADDR 080000h
109;; The long mode page directory pointer table address.
110%define BS2_LM_PDP_ADDR 081000h
111;; The PAE page directory pointer table address.
112%define BS2_PAE_PDP_ADDR 082000h
113;; The address of the 4 PAE page directories. Also used by long mode.
114%define BS2_PAE_PD_ADDR 083000h
115;; The address of the 32-bit page directory.
116%define BS2_32B_PD_ADDR 087000h
117;; User page table #0.
118%define BS2_USER_PX_0_ADDR 088000h
119;; User page table #1.
120%define BS2_USER_PX_1_ADDR 089000h
121;; User page table #2.
122%define BS2_USER_PX_2_ADDR 08a000h
123;; User page table #3.
124%define BS2_USER_PX_3_ADDR 08b000h
125;; User page table #4.
126%define BS2_USER_PX_4_ADDR 08c000h
127;; User page table #5.
128%define BS2_USER_PX_5_ADDR 08d000h
129;; User page table #6.
130%define BS2_USER_PX_6_ADDR 08e000h
131;; User page table #7.
132%define BS2_USER_PX_7_ADDR 08f000h
133;; The selector to use when accessing the PDP and PD from real mode.
134%define BS2_PXX_SEL 08000h
135;; Converts a BS2_P*_ADDR into a BS2_PXX_SEL selector offset.
136%define BS2_PXX_OFF(Addr) ( (Addr) - (BS2_PXX_SEL * 16) )
137
138;; The base address in the default address spaces of the range where we are
139; free to muck about as much as we like. (This is a virtual address.)
140%define BS2_MUCK_ABOUT_BASE 000400000h
141
142; We have some free space here 090000h...09a000h (stacks moved)
143
144;; The address of the LDT.
145%define BS2_LDT_BASE 09b000h
146;; The size of the LDT in bytes.
147%define BS2_LDT_SIZE 001fffh
148
149;; The start of the memory area used for paging, stacks and so forth.
150%define BS2_PXX_LAST 09ffffh
151;; @}
152
153
154;;
155; @name Group of 32-bit, 16-bit and 64-bit selectors for one ring.
156; @{
157%define BS2_SEL_GRP_CS32 00h
158%define BS2_SEL_GRP_DS32 08h
159%define BS2_SEL_GRP_SS32 10h
160%define BS2_SEL_GRP_CS16 18h
161%define BS2_SEL_GRP_DS16 20h
162%define BS2_SEL_GRP_SS16 28h
163%define BS2_SEL_GRP_CS64 30h
164%define BS2_SEL_GRP_DS64 38h
165%define BS2_SEL_GRP_SS64 38h
166%define BS2_SEL_GRP_SIZE 40h
167;; @}
168
169
170;; Move to program.
171%ifndef BS2_WITHOUT_RAW_MODE
172 %define BS2_WITH_RAW_MODE
173%endif
174
175; Implicit code inclusion based on the init mode.
176%ifdef BS2_INIT_PE32
177 %define BS2_INC_PE32
178%elifdef BS2_INIT_PP32
179 %define BS2_INC_PP32
180%elifdef BS2_INIT_PAE32
181 %define BS2_INC_PAE32
182%elifdef BS2_INIT_LM64
183 %define BS2_INC_LM64
184%else
185 %define BS2_INIT_RM ; the default
186 %define BS2_INC_RM
187%endif
188
189; Aliases.
190%ifdef BS2_INC_PE
191 %define BS2_INC_PE16
192 %define BS2_INC_PE32
193 %define BS2_INC_PEV86
194%endif
195%ifdef BS2_INC_PP
196 %define BS2_INC_PP16
197 %define BS2_INC_PP32
198 %define BS2_INC_PPV86
199%endif
200%ifdef BS2_INC_PAE
201 %define BS2_INC_PAE16
202 %define BS2_INC_PAE32
203 %define BS2_INC_PAEV86
204%endif
205%ifdef BS2_INC_LM
206 %define BS2_INC_LM16
207 %define BS2_INC_LM32
208 %define BS2_INC_LM64
209%endif
210
211; Common code.
212%ifdef BS2_INC_RM
213 %define BS2_INC_CMN_R86
214%endif
215%ifdef BS2_INC_PE16
216 %define BS2_INC_CMN_P16
217 %define BS2_INC_CMN_PE
218 %define BS2_INC_CMN_PM
219%endif
220%ifdef BS2_INC_PE32
221 %define BS2_INC_CMN_P32
222 %define BS2_INC_CMN_PE
223 %define BS2_INC_CMN_PM
224%endif
225%ifdef BS2_INC_PEV86
226 %define BS2_INC_CMN_R86
227 %define BS2_INC_CMN_V86
228 %define BS2_INC_CMN_PE
229 %define BS2_INC_CMN_PM
230%endif
231%ifdef BS2_INC_PP16
232 %define BS2_INC_CMN_P16
233 %define BS2_INC_CMN_PP
234 %define BS2_INC_CMN_PM
235%endif
236%ifdef BS2_INC_PP32
237 %define BS2_INC_CMN_P32
238 %define BS2_INC_CMN_PP
239 %define BS2_INC_CMN_PM
240%endif
241%ifdef BS2_INC_PPV86
242 %define BS2_INC_CMN_R86
243 %define BS2_INC_CMN_V86
244 %define BS2_INC_CMN_PP
245 %define BS2_INC_CMN_PM
246%endif
247%ifdef BS2_INC_PAE16
248 %define BS2_INC_CMN_P16
249 %define BS2_INC_CMN_PAE
250 %define BS2_INC_CMN_PM
251 %define BS2_INC_CMN_PAE_LM
252%endif
253%ifdef BS2_INC_PAE32
254 %define BS2_INC_CMN_P32
255 %define BS2_INC_CMN_PAE
256 %define BS2_INC_CMN_PM
257 %define BS2_INC_CMN_PAE_LM
258%endif
259%ifdef BS2_INC_PAEV86
260 %define BS2_INC_CMN_R86
261 %define BS2_INC_CMN_V86
262 %define BS2_INC_CMN_PAE
263 %define BS2_INC_CMN_PM
264 %define BS2_INC_CMN_PAE_LM
265%endif
266%ifdef BS2_INC_LM16
267 %define BS2_INC_CMN_P16
268 %define BS2_INC_CMN_LM
269 %define BS2_INC_CMN_PAE_LM
270%endif
271%ifdef BS2_INC_LM32
272 %define BS2_INC_CMN_P32
273 %define BS2_INC_CMN_LM
274 %define BS2_INC_CMN_PAE_LM
275%endif
276%ifdef BS2_INC_LM64
277 %define BS2_INC_CMN_LM64
278 %define BS2_INC_CMN_LM
279 %define BS2_INC_CMN_PAE_LM
280%endif
281
282
283;
284; Misc defines.
285;
286;; The offset of the TSS32.CR3 field.
287%define BS2_TSS32_CR3_OFF 01ch
288
289
290;*******************************************************************************
291;* Structures and Typedefs *
292;*******************************************************************************
293
294
295;
296; Start with a jump just to follow the convention.
297; Also declare all segments/sections to establish them and their order.
298;
299 ORG BS2_ADDR
300
301section .text valign=16 align=16 progbits
302section .data vfollows=.text follows=.text valign=16 align=16 progbits
303section .texthigh vfollows=.data follows=.data valign=16 align=16 progbits
304section .traprecs vfollows=.texthigh follows=.texthigh valign=8 align=8 progbits
305section .end vfollows=.traprecs follows=.traprecs valign=512 align=512 progbits
306
307%define BEGINCODELOW section .text ;;< For 16-bit code.
308%define BEGINCODEHIGH section .texthigh ;;< For 32-bit and 64-bit code.
309%define BEGINEND section .end ;;< For aligning image to 512 bytes.
310
311BEGINCODELOW
312BITS 16
313start:
314 jmp short bs2InitCode
315 nop
316 nop ; alignment
317
318;
319; Abuse the bios parameter block area for data storage.
320;
321gdtr:
322 dw bs2GdtEnd - bs2Gdt - 1 ; limit 15:00
323 dw bs2Gdt ; base 15:00
324 db 0 ; base 23:16
325 db 0 ; unused
326
327idtr_null:
328 dw 0 ; limit 15:00
329 dw bs2Gdt ; base 15:00
330 db 0 ; base 23:16
331 db 0 ; unused
332
333%ifdef BS2_WITH_TRAPS
334 %ifdef BS2_INC_CMN_PM
335idtr_32bit:
336 dw bs2Idt32bitEnd - bs2Idt32bit -1 ; limit 15:00
337 dw bs2Idt32bit ; base 15:00
338 db 0 ; base 23:16
339 db 0 ; unused
340 %endif
341
342 %ifdef BS2_INC_CMN_LM
343idtr_64bit:
344 dw bs2Idt64bitEnd - bs2Idt64bit -1 ; limit 15:00
345 dw bs2Idt64bit ; base 15:00
346 db 0 ; base 23:16
347 db 0 ; unused
348 %endif
349
350%elifdef BS2_WITH_RAW_MODE
351idtr_dummy_32bit:
352 dw bs2DummyIdt32bitEnd - bs2DummyIdt32bit -1 ; limit 15:00
353 dw bs2DummyIdt32bit ; base 15:00
354 db 0 ; base 23:16
355 db 0 ; unused
356%endif
357
358idtr_real_mode:
359 dw 01ffh ; limit 15:00
360 dw 0 ; base 15:00
361 db 0 ; base 23:16
362 db 0 ; unused
363
364g_achHex:
365 db '0123456789abcdef', 0
366
367g_bBootDrv:
368 db 80h ; Not in the official BPB location, but whatever.
369g_fCpuIntel:
370 db 0
371g_fCpuAmd:
372 db 0
373
374bs2BpbPadding:
375 times 3dh - (bs2BpbPadding - start) db 0
376
377
378;
379; Where to real init code starts.
380;
381bs2InitCode:
382 cli
383
384%ifdef BS2_INIT_SAVE_REGS
385 ; save the registers if we've been asked to do so.
386 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.rax], eax
387 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.rsp], esp
388 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.rbp], ebp
389 mov ax, ss
390 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.ss], ax
391 mov ax, ds
392 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.ds], ax
393 mov ax, es
394 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.es], ax
395 mov ax, fs
396 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.fs], ax
397 mov ax, gs
398%endif
399
400 ; set up the segment reisters and stack.
401 xor eax, eax
402 mov ds, ax
403 mov es, ax
404 mov fs, ax
405 mov gs, ax
406 mov ss, ax
407 mov esp, STACK_ADDR
408 mov [esp], eax ; clear the first 16 bytes
409 mov [esp + 04h], eax
410 mov [esp + 08h], eax ; fake rbp.
411 mov [esp + 0ch], eax ; fake ebp and bp
412 mov ebp, esp
413
414%ifdef BS2_INIT_SAVE_REGS
415 ; Save more registers now that ds is known and the stack is usable.
416 pushfd
417 pop eax
418 mov [BS2_REG_SAVE_ADDR + BS2REGS.rflags], eax
419 mov [BS2_REG_SAVE_ADDR + BS2REGS.rbx], ebx
420 mov [BS2_REG_SAVE_ADDR + BS2REGS.rcx], ecx
421 mov [BS2_REG_SAVE_ADDR + BS2REGS.rdx], edx
422 mov [BS2_REG_SAVE_ADDR + BS2REGS.rsi], esi
423 mov [BS2_REG_SAVE_ADDR + BS2REGS.rdi], edi
424%endif
425
426 ; Make sure caching is enabled and alignment is off.
427 mov eax, cr0
428%ifdef BS2_INIT_SAVE_REGS
429 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr0], eax
430%endif
431 and eax, ~(X86_CR0_NW | X86_CR0_CD | X86_CR0_AM)
432 mov cr0, eax
433
434 ; Load all the code.
435 call bs2InitLoadImage
436 mov [g_bBootDrv], dl
437
438 ; Initialize the data structures for the included modes requiring this.
439%ifdef BS2_INC_CMN_PP
440 call bs2InitPagedProtMode
441%endif
442%ifdef BS2_INC_CMN_PAE
443 call bs2InitPaeProtMode
444%endif
445%ifdef BS2_INC_CMN_LM
446 call bs2InitLongMode
447%endif
448
449 ; Entered the desired mode.
450%ifdef BS2_INIT_PE32
451 call Bs2EnterMode_rm_pe32
452BITS 32
453%endif
454%ifdef BS2_INIT_PP32
455 call Bs2EnterMode_rm_pp32
456BITS 32
457%endif
458%ifdef BS2_INIT_PAE32
459 call Bs2EnterMode_rm_pae32
460BITS 32
461%endif
462%ifdef BS2_INIT_LM64
463 call Bs2EnterMode_rm_lm64
464BITS 64
465%endif
466%ifdef BS2_INIT_RM
467 call SetCpuModeGlobals_rm
468%endif
469
470%ifdef BS2_WITH_RAW_MODE
471 ;
472 ; Mask interrupts and then set IF.
473 ;
474 mov al, 0ffh
475 out 021h, al
476 out 0a1h, al
477 sti
478%endif
479
480 jmp bs2DoneInit
481
482
483;;
484; Loads the image off the floppy.
485;
486; This uses the the_end label to figure out the length. For this to work
487; cleanly the label must be aligned on a sector boundrary. Use BS2_PAD_IMAGE
488; to make sure this is the case.
489;
490; Clobbers everything except ebp and esp. Panics on failure.
491;
492; @param dl The boot drive number (from BIOS).
493; @uses ax, cx, bx, esi, di
494;
495BEGINCODELOW
496BITS 16
497BEGINPROC bs2InitLoadImage
498 push bp
499 mov bp, sp
500 push es
501%define bSavedDiskNo byte [bp - 04h]
502 push dx
503%define bMaxSector byte [bp - 06h]
504 push 0
505%define bMaxHead byte [bp - 08h]
506 push 0
507%define bMaxCylinder byte [bp - 0ah]
508 push 0
509
510 ;
511 ; Try figure the geometry.
512 ;
513 mov ah, 08h
514 int 13h
515 jc .failure
516 mov bMaxSector, cl
517 mov bMaxHead, dh
518 mov bMaxCylinder, ch
519 mov dl, bSavedDiskNo
520
521 ;
522 ; Reload all the sectors one at a time (avoids problems).
523 ;
524 lea esi, [dword the_end]
525 sub esi, start
526 shr esi, 9 ; si = number of sectors to load.
527 mov di, BS2_ADDR / 16 ; The current load segment.
528 mov cx, 0001h ; ch/cylinder=0 (0-based); cl/sector=1 (1-based)
529 xor dh, dh ; dh/head=0
530.the_load_loop:
531 xor bx, bx
532 mov es, di ; es:bx -> buffer
533 mov ax, 0201h ; al=1 sector; ah=read function
534 int 13h
535 jc .failure
536
537 ; advance to the next sector/head/cylinder.
538 inc cl
539 cmp cl, bMaxSector
540 jbe .adv_addr
541
542 mov cl, 1
543 inc dh
544 cmp dh, bMaxHead
545 jbe .adv_addr
546
547 mov dh, 0
548 inc ch
549
550.adv_addr:
551 add di, 512 / 16
552 dec si
553 jnz .the_load_loop
554
555 add sp, 3*2
556 pop dx
557 pop es
558 leave
559 ret
560
561 ;
562 ; Something went wrong, display a message.
563 ;
564.failure:
565 pusha
566
567 ; print message
568 mov si, .s_szErrMsg
569 mov ah, 0eh
570 xor bx, bx
571.failure_next_char:
572 lodsb
573 int 10h
574 cmp si, .s_szErrMsgEnd
575 jb .failure_next_char
576
577 ; format the error number.
578 movzx bx, byte [bp - 2 - 1] ; read the ah of the pusha frame
579 shr bl, 4
580 mov al, [bx + g_achHex]
581 int 10h
582
583 movzx bx, byte [bp - 2 - 1] ; read the ah of the pusha frame
584 and bl, 0fh
585 mov al, [bx + g_achHex]
586 int 10h
587
588 ; panic
589 popa
590 call Bs2Panic
591.s_szErrMsg:
592 db 13, 10, 'read error: '
593.s_szErrMsgEnd:
594ENDPROC bs2InitLoadImage
595
596;; Pads the image so bs2InitLoadImage can load it without trouble.
597%macro BS2_PAD_IMAGE 0
598bs2PadImageLabel:
599; times ( (512*18*2) - ( (bs2PadImageLabel - start) % (512*18*2) ) ) db 0 ; track aligned size.
600 times ( 512 - ( (bs2PadImageLabel - start) % 512 ) ) db 0 ; sector aligned size.
601; times ( 10000h - BS2_ADDR - (bs2PadImageLabel - start) ) db 0 ; full segment 0 size.
602%endmacro
603
604
605;;
606; Shutdown routine that will work in real and protected mode, providing
607; that SS is valid that we can load it into DS.
608;
609; Does not return.
610;
611BEGINCODELOW
612BITS 16
613BEGINPROC Bs2Shutdown
614 cli
615 mov bl, 64
616 mov dx, SHUTDOWN_PORT
617 mov ax, ss
618 mov ds, ax
619.retry:
620 mov ecx, 8
621 mov esi, .s_szShutdown
622 rep outsb
623 dec bl
624 jnz .retry
625 ; Shutdown failed!
626 jmp Bs2Panic
627.s_szShutdown:
628 db 'Shutdown', 0
629ENDPROC Bs2Shutdown
630
631
632;;
633; Panic routine for real mode.
634;
635; Does not return.
636;
637BEGINCODELOW
638BITS 16
639BEGINPROC Bs2Panic
640 cli
641.hlt_again:
642 hlt
643 jmp .hlt_again
644ENDPROC Bs2Panic
645
646
647;
648; Padd the remainder of the sector with zeros and
649; end it with the dos signature.
650;
651bs2Padding:
652 times 510 - (bs2Padding - start) db 0
653 db 055h, 0aah
654
655
656;
657; The GDT (X86DESCGENERIC).
658;
659align 8, db 0
660bs2Gdt:
661 dw 00000h, 00000h, 00000h, 00000h ; null selector
662%define BS2_SEL_R0_BASE 08h
663%define BS2_SEL_CS32 08h
664 dw 0ffffh, 00000h, 09b00h, 000cfh ; 32-bit flat code segment.
665%define BS2_SEL_DS32 10h
666 dw 0ffffh, 00000h, 09300h, 000cfh ; 32-bit flat data segment.
667%define BS2_SEL_SS32 18h
668 dw 0ffffh, 00000h, 09300h, 000cfh ; 32-bit flat stack segment.
669%define BS2_SEL_CS16 20h
670 dw 0ffffh, 00000h, 09b00h, 00000h ; 16-bit code segment with base 0.
671%define BS2_SEL_DS16 28h
672 dw 0ffffh, 00000h, 09300h, 00000h ; 16-bit data segment with base 0.
673%define BS2_SEL_SS16 30h
674 dw 0ffffh, 00000h, 09300h, 00000h ; 16-bit stack segment with base 0.
675%define BS2_SEL_CS64 38h
676 dw 0ffffh, 00000h, 09a00h, 000afh ; 64-bit code segment.
677%define BS2_SEL_DS64 40h
678%define BS2_SEL_SS64 40h
679 dw 0ffffh, 00000h, 09300h, 000afh ; 64-bit stack and data segment.
680 dw 00000h, 00000h, 00000h, 00000h ; Unused
681%define BS2_SEL_MMIO16 50h
682%define BS2_SEL_MMIO16_BASE 0100000h
683 dw 0ffffh, 00000h, 09310h, 00000h ; 16-bit VMMDev MMIO segment with base 0100000h.
684 dw 00000h, 00000h, 00000h, 00000h ; Unused
685%define BS2_SEL_LDT 60h ; LDT usage requires manual LLDT and setting up.
686 dw BS2_LDT_SIZE, BS2_LDT_BASE & 0xffff, 08200h | ((BS2_LDT_BASE >> 16) & 0xff), 00000h
687 dw 00000h, 00000h, 00000h, 00000h ; zero for 64-bit mode.
688%define BS2_SEL_CS16_EO 70h
689 dw 0fffeh, 00000h, 09800h, 00000h ; 16-bit code segment with base 0, not accessed, execute only, short limit.
690 dw 00000h, 00000h, 00000h, 00000h ; unused.
691%ifdef BS2_WITH_TRAPS
692 %ifdef BS2_INC_CMN_PM
693 %define BS2_SEL_TSS32 80h
694 dw (bs2Tss32BitEnd - bs2Tss32Bit) - 1 ; 32-bit TSS.
695 dw bs2Tss32Bit
696 db 0
697 db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80
698 dw 0
699 %define BS2_SEL_TSS32_DF 88h
700 dw (bs2Tss32BitDfEnd - bs2Tss32BitDf) - 1; 32-bit TSS, double fault.
701 dw bs2Tss32BitDf
702 db 0
703 db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80
704 dw 0
705 %else
706 dw 00000h, 00000h, 00000h, 00000h
707 dw 00000h, 00000h, 00000h, 00000h
708 %endif
709 %ifdef BS2_INC_CMN_LM
710 %define BS2_SEL_TSS64 90h
711 dw (bs2Tss64BitEnd - bs2Tss64Bit) - 1 ; 32-bit TSS.
712 dw bs2Tss64Bit
713 db 0
714 db AMD64_SEL_TYPE_SYS_TSS_AVAIL | 0x80
715 dw 0
716 dw 00000h, 00000h, 00000h, 00000h ; 2nd half of the 64-bit selector (not necessary).
717 %else
718 dw 00000h, 00000h, 00000h, 00000h
719 dw 00000h, 00000h, 00000h, 00000h
720 %endif
721%endif
722 ; Ring-1 selectors.
723%define BS2_SEL_R1_BASE 0a0h
724%define BS2_SEL_R1_CS32 0a0h
725 dw 0ffffh, 00000h, 0bb00h, 000cfh ; Ring-1 32-bit flat code segment.
726%define BS2_SEL_R1_DS32 0a8h
727 dw 0ffffh, 00000h, 0b300h, 000cfh ; Ring-1 32-bit flat data segment.
728%define BS2_SEL_R1_SS32 0b0h
729 dw 0ffffh, 00000h, 0b300h, 000cfh ; Ring-1 32-bit flat stack segment.
730%define BS2_SEL_R1_CS16 0b8h
731 dw 0ffffh, 00000h, 0bb00h, 00000h ; Ring-1 16-bit code segment with base 0.
732%define BS2_SEL_R1_DS16 0c0h
733 dw 0ffffh, 00000h, 0b300h, 00000h ; Ring-1 16-bit data segment with base 0.
734%define BS2_SEL_R1_SS16 0c8h
735 dw 0ffffh, 00000h, 0b300h, 00000h ; Ring-1 16-bit stack segment with base 0.
736%define BS2_SEL_R1_CS64 0d0h
737 dw 0ffffh, 00000h, 0ba00h, 000afh ; Ring-1 64-bit code segment.
738%define BS2_SEL_R1_DS64 0d8h
739%define BS2_SEL_R1_SS64 0d8h
740 dw 0ffffh, 00000h, 0b300h, 000afh ; Ring-1 64-bit stack and data segment.
741
742 ; Ring-2 selectors.
743%define BS2_SEL_R2_BASE 0e0h
744%define BS2_SEL_R2_CS32 0e0h
745 dw 0ffffh, 00000h, 0db00h, 000cfh ; Ring-2 32-bit flat code segment.
746%define BS2_SEL_R2_DS32 0e8h
747 dw 0ffffh, 00000h, 0d300h, 000cfh ; Ring-2 32-bit flat data segment.
748%define BS2_SEL_R2_SS32 0f0h
749 dw 0ffffh, 00000h, 0d300h, 000cfh ; Ring-2 32-bit flat stack segment.
750%define BS2_SEL_R2_CS16 0f8h
751 dw 0ffffh, 00000h, 0db00h, 00000h ; Ring-2 16-bit code segment with base 0.
752%define BS2_SEL_R2_DS16 0f0h
753 dw 0ffffh, 00000h, 0d300h, 00000h ; Ring-2 16-bit data segment with base 0.
754%define BS2_SEL_R2_SS16 108h
755 dw 0ffffh, 00000h, 0d300h, 00000h ; Ring-2 16-bit stack segment with base 0.
756%define BS2_SEL_R2_CS64 110h
757 dw 0ffffh, 00000h, 0da00h, 000afh ; Ring-2 64-bit code segment.
758%define BS2_SEL_R2_DS64 118h
759%define BS2_SEL_R2_SS64 118h
760 dw 0ffffh, 00000h, 0d300h, 000afh ; Ring-2 64-bit stack and data segment.
761
762 ; Ring-3 selectors.
763%define BS2_SEL_R3_BASE 120h
764%define BS2_SEL_R3_CS32 120h
765 dw 0ffffh, 00000h, 0fb00h, 000cfh ; Ring-3 32-bit flat code segment.
766%define BS2_SEL_R3_DS32 128h
767 dw 0ffffh, 00000h, 0f300h, 000cfh ; Ring-3 32-bit flat data segment.
768%define BS2_SEL_R3_SS32 130h
769 dw 0ffffh, 00000h, 0f300h, 000cfh ; Ring-3 32-bit flat stack segment.
770%define BS2_SEL_R3_CS16 138h
771 dw 0ffffh, 00000h, 0fb00h, 00000h ; Ring-3 16-bit code segment with base 0.
772%define BS2_SEL_R3_DS16 140h
773 dw 0ffffh, 00000h, 0f300h, 00000h ; Ring-3 16-bit data segment with base 0.
774%define BS2_SEL_R3_SS16 148h
775 dw 0ffffh, 00000h, 0f300h, 00000h ; Ring-3 16-bit stack segment with base 0.
776%define BS2_SEL_R3_CS64 150h
777 dw 0ffffh, 00000h, 0fa00h, 000afh ; Ring-1 64-bit code segment.
778%define BS2_SEL_R3_DS64 158h
779%define BS2_SEL_R3_SS64 158h
780 dw 0ffffh, 00000h, 0f300h, 000afh ; Ring-1 64-bit stack and data segment.
781
782 ; Here follows a bunch of spare GDT entries for (ab)use in testing.
783%define BS2_SEL_SPARE0 160h
784bs2GdtSpare0:
785 dq 0
786%define BS2_SEL_SPARE1 (BS2_SEL_SPARE0 + 08h)
787bs2GdtSpare1:
788 dq 0
789%define BS2_SEL_SPARE2 (BS2_SEL_SPARE0 + 10h)
790bs2GdtSpare2:
791 dq 0
792%define BS2_SEL_SPARE3 (BS2_SEL_SPARE0 + 18h)
793bs2GdtSpare3:
794 dq 0
795bs2GdtEnd:
796
797
798%ifndef BS2_WITH_TRAPS
799 %ifdef BS2_WITH_RAW_MODE
800;
801; Dummy 32-bit IDT for making CSAM happy.
802;
803align 16, db 0
804bs2DummyIdt32bit:
805 dw 0, 0, 0, 0
806 dw 0, 0, 0, 0
807 dw 0, 0, 0, 0
808 dw 0, 0, 0, 0
809bs2DummyIdt32bitEnd
810 %endif
811%endif
812
813
814;
815; Mode initialization routines.
816;
817
818%ifdef BS2_INC_CMN_PP
819;;
820; Initializes the paged protected mode structures during init.
821;
822; @uses ebx, esi
823;
824BEGINCODELOW
825BITS 16
826BEGINPROC bs2InitPagedProtMode
827 push ds
828
829 ;
830 ; Create a paging hierarchy
831 ;
832 mov bx, BS2_PXX_SEL
833 mov ds, bx
834 mov ebx, BS2_PXX_OFF(BS2_32B_PD_ADDR)
835 xor esi, esi ; physical address
836
837 ; The page directory.
838.pd_loop:
839 mov dword [bx], esi
840 or word [bx], X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_PS | X86_PDE4M_US
841 add esi, _4M
842 add bx, 4
843 test bx, 0fffh
844 jnz .pd_loop
845
846%ifdef BS2_WITH_RAW_MODE
847 ;
848 ; Make sure there is some free space for the hypervisor near the top
849 ; of the address space (last 4MB is mapped).
850 ;
851 and byte [bx - 08h], 0feh
852 and byte [bx - 0ch], 0feh
853 and byte [bx - 10h], 0feh
854 and byte [bx - 14h], 0feh
855%endif
856
857 pop ds
858 ret
859ENDPROC bs2InitPagedProtMode
860%endif ; BS2_INC_CMN_PP
861
862
863%ifdef BS2_INC_CMN_PAE_LM
864;;
865; Initializes the PAE page directories.
866;
867; Assumes ds is set to BS2_PXX_SEL already and that edx is zero.
868;
869; @uses ebx, esi
870; @internal
871;
872BEGINPROC bs2InitPaePageDirs
873 mov esi, X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_PS | X86_PDE4M_US
874 mov ebx, BS2_PXX_OFF(BS2_PAE_PD_ADDR)
875.pd_loop:
876 mov [bx], esi
877 mov [bx + 4], edx
878 add esi, _2M
879 add bx, 8
880 test bx, 0fffh
881 jnz .pd_loop
882 cmp bx, BS2_PXX_OFF(BS2_PAE_PD_ADDR + 4*_4K)
883 jne .pd_loop
884
885%ifdef BS2_WITH_RAW_MODE
886 ;
887 ; Make sure there is some free space for the hypervisor near the top
888 ; of the address space (last 4MB is mapped).
889 ;
890 and byte [bx - 10h], 0feh
891 and byte [bx - 18h], 0feh
892 and byte [bx - 20h], 0feh
893 and byte [bx - 28h], 0feh
894%endif
895
896 ret
897ENDPROC bs2InitPaePageDirs
898%endif ; BS2_INC_CMN_PAE_LM
899
900
901%ifdef BS2_INC_CMN_PAE
902;;
903; Initializes the PAE protected mode structures during init.
904;
905; @uses edx, ebx, esi.
906;
907BEGINCODELOW
908BITS 16
909BEGINPROC bs2InitPaeProtMode
910 push ds
911
912 mov dx, BS2_PXX_SEL
913 mov ds, dx
914 xor edx, edx
915
916 ;
917 ; Join paths with long mode.
918 ;
919 call bs2InitPaePageDirs
920
921 ;
922 ; Create the page directory pointer table.
923 ;
924 mov ebx, BS2_PXX_OFF(BS2_PAE_PDP_ADDR)
925 mov dword [bx], (BS2_PAE_PD_ADDR ) | X86_PDPE_P
926 mov dword [bx + 04h], edx
927 mov dword [bx + 08h], (BS2_PAE_PD_ADDR + 1000h) | X86_PDPE_P
928 mov dword [bx + 0ch], edx
929 mov dword [bx + 10h], (BS2_PAE_PD_ADDR + 2000h) | X86_PDPE_P
930 mov dword [bx + 14h], edx
931 mov dword [bx + 18h], (BS2_PAE_PD_ADDR + 3000h) | X86_PDPE_P
932 mov dword [bx + 1ch], edx
933
934 pop ds
935 ret
936ENDPROC bs2InitPaeProtMode
937%endif ; BS2_INC_CMN_PAE
938
939
940%ifdef BS2_INC_CMN_LM
941;;
942; Initializes the long mode structures during init.
943;
944; @uses edx, ebx, esi
945;
946BEGINCODELOW
947BITS 16
948BEGINPROC bs2InitLongMode
949 push ds
950
951 mov dx, BS2_PXX_SEL
952 mov ds, dx
953 xor edx, edx
954
955 ;
956 ; Join paths with the PAE code.
957 ;
958 call bs2InitPaePageDirs
959
960 ;
961 ; Create the long mode page directory pointer table.
962 ;
963 mov ebx, BS2_PXX_OFF(BS2_LM_PDP_ADDR)
964.pdptr_loop:
965 mov dword [bx], (BS2_PAE_PD_ADDR ) | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US
966 mov dword [bx + 04h], edx
967 mov dword [bx + 08h], (BS2_PAE_PD_ADDR + 1000h) | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US
968 mov dword [bx + 0ch], edx
969 mov dword [bx + 10h], (BS2_PAE_PD_ADDR + 2000h) | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US
970 mov dword [bx + 14h], edx
971 mov dword [bx + 18h], (BS2_PAE_PD_ADDR + 3000h) | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US
972 mov dword [bx + 1ch], edx
973 add bx, 20h
974 test bx, 0fffh
975 jnz .pdptr_loop
976
977 ;
978 ; Set up the page map level 4 table, all entries mapping the same PDPTR.
979 ;
980 mov ebx, BS2_PXX_OFF(BS2_LM_PML4_ADDR)
981.pml4_loop:
982 mov dword [bx], BS2_LM_PDP_ADDR | X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US
983 mov dword [bx + 4], edx
984 add bx, 8
985 test bx, 0fffh
986 jnz .pml4_loop
987
988 pop ds
989 ret
990ENDPROC bs2InitLongMode
991%endif ; BS2_INC_CMN_LM
992
993
994
995;
996; Routines for entering the different modes.
997;
998
999%ifdef BS2_INC_RM
1000;;
1001; Dummy.
1002BEGINCODELOW
1003BITS 16
1004BEGINPROC Bs2EnterMode_rm_rm
1005 ret
1006ENDPROC Bs2EnterMode_rm_rm
1007%endif ; BS2_INC_RM
1008
1009
1010%ifdef BS2_INC_PE16
1011;;
1012; Enters unpaged protected mode from real mode (cs = 0).
1013;
1014; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1015; ebp and esp converted to 32/16-bit.
1016; All other registers are preserved.
1017; @uses nothing
1018;
1019BEGINCODELOW
1020BITS 16
1021BEGINPROC Bs2EnterMode_rm_pe16
1022 push eax
1023 pushfd
1024 cli
1025%ifndef BS2_NOINC_COMMON
1026 push word SetCpuModeGlobals_pe16
1027%endif
1028
1029 ;
1030 ; Switch to protected mode.
1031 ;
1032 xor ax, ax
1033 mov ds, ax
1034 lgdt [gdtr]
1035%ifdef BS2_WITH_TRAPS
1036 lidt [idtr_32bit]
1037%elifdef BS2_WITH_RAW_MODE
1038 lidt [idtr_dummy_32bit]
1039%else
1040 lidt [idtr_null]
1041%endif
1042
1043 mov eax, cr0
1044 or eax, X86_CR0_PE
1045 and eax, 0ffffffffh - X86_CR0_PG
1046 mov cr0, eax
1047 jmp far BS2_SEL_CS16:bs2ProtModeCode16Start_p16
1048ENDPROC Bs2EnterMode_rm_pe16
1049%endif ; BS2_INC_PE16
1050
1051
1052%ifdef BS2_INC_PE32
1053;;
1054; Enters unpaged protected mode from real mode (cs = 0).
1055;
1056; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1057; ebp and esp converted to 32-bit.
1058; All other registers are preserved.
1059; @uses nothing
1060;
1061BEGINCODELOW
1062BITS 16
1063BEGINPROC Bs2EnterMode_rm_pe32
1064 push word 0
1065 push eax
1066 pushfd
1067 cli
1068%ifndef BS2_NOINC_COMMON
1069 push dword SetCpuModeGlobals_pe32
1070%endif
1071
1072 ; Do the mode switch.
1073 xor ax, ax
1074 mov ds, ax
1075 lgdt [gdtr]
1076%ifdef BS2_WITH_TRAPS
1077 lidt [idtr_32bit]
1078%elifdef BS2_WITH_RAW_MODE
1079 lidt [idtr_dummy_32bit]
1080%else
1081 lidt [idtr_null]
1082%endif
1083
1084 mov eax, cr0
1085 or eax, X86_CR0_PE
1086 and eax, 0ffffffffh - X86_CR0_PG
1087 mov cr0, eax
1088 jmp far BS2_SEL_CS32:bs2ProtModeCode32Start_p32
1089ENDPROC Bs2EnterMode_rm_pe32
1090%endif ; BS2_INC_PE32
1091
1092
1093;; @todo BS2_INC_PEV86
1094
1095
1096%ifdef BS2_INC_PP16
1097;;
1098; Enters paged protected mode from real mode (cs = 0).
1099;
1100; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1101; ebp and esp converted to 16/32-bit.
1102; All other registers are preserved.
1103; @uses nothing
1104;
1105BEGINCODELOW
1106BITS 16
1107BEGINPROC Bs2EnterMode_rm_pp16
1108 push eax
1109 pushfd
1110 cli
1111%ifndef BS2_NOINC_COMMON
1112 push word SetCpuModeGlobals_pp16
1113%endif
1114
1115 ; Do the mode switch.
1116 xor ax, ax
1117 mov ds, ax
1118 lgdt [gdtr]
1119%ifdef BS2_WITH_TRAPS
1120 lidt [idtr_32bit]
1121%elifdef BS2_WITH_RAW_MODE
1122 lidt [idtr_dummy_32bit]
1123%else
1124 lidt [idtr_null]
1125%endif
1126
1127 mov eax, BS2_32B_PD_ADDR
1128 mov cr3, eax
1129%ifdef BS2_WITH_TRAPS
1130 mov [bs2Tss32BitDf + BS2_TSS32_CR3_OFF], eax
1131%endif
1132
1133 mov eax, cr4
1134 or eax, X86_CR4_PSE
1135 and eax, ~X86_CR4_PAE
1136 mov cr4, eax
1137
1138 mov eax, cr0
1139 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_WP
1140 mov cr0, eax
1141 jmp far BS2_SEL_CS16:bs2ProtModeCode16Start_p16
1142ENDPROC Bs2EnterMode_rm_pp16
1143%endif ; BS2_INC_PP16
1144
1145
1146%ifdef BS2_INC_PP32
1147;;
1148; Enters paged protected mode from real mode (cs = 0).
1149;
1150; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1151; ebp and esp converted to 32-bit.
1152; All other registers are preserved.
1153; @uses nothing
1154;
1155BEGINCODELOW
1156BITS 16
1157BEGINPROC Bs2EnterMode_rm_pp32
1158 push word 0
1159 push eax
1160 pushfd
1161 cli
1162%ifndef BS2_NOINC_COMMON
1163 push dword SetCpuModeGlobals_pp32
1164%endif
1165
1166 ; Do the mode switch.
1167 xor ax, ax
1168 mov ds, ax
1169 lgdt [gdtr]
1170%ifdef BS2_WITH_TRAPS
1171 lidt [idtr_32bit]
1172%elifdef BS2_WITH_RAW_MODE
1173 lidt [idtr_dummy_32bit]
1174%else
1175 lidt [idtr_null]
1176%endif
1177
1178 mov eax, BS2_32B_PD_ADDR
1179 mov cr3, eax
1180%ifdef BS2_WITH_TRAPS
1181 mov [bs2Tss32BitDf + BS2_TSS32_CR3_OFF], eax
1182%endif
1183
1184 mov eax, cr4
1185 or eax, X86_CR4_PSE
1186 and eax, ~X86_CR4_PAE
1187 mov cr4, eax
1188
1189 mov eax, cr0
1190 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_WP
1191 mov cr0, eax
1192 jmp far BS2_SEL_CS32:bs2ProtModeCode32Start_p32
1193ENDPROC Bs2EnterMode_rm_pp32
1194%endif ; BS2_INC_PP16
1195
1196
1197;; @todo BS2_INC_PPV86
1198
1199
1200%ifdef BS2_INC_PAE16
1201;;
1202; Enters PAE protected mode from real mode (cs = 0).
1203;
1204; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1205; ebp and esp converted to 16/32-bit.
1206; All other registers are preserved.
1207; @uses nothing
1208;
1209BEGINCODELOW
1210BITS 16
1211BEGINPROC Bs2EnterMode_rm_pae16
1212 push eax
1213 pushfd
1214 cli
1215%ifndef BS2_NOINC_COMMON
1216 push word SetCpuModeGlobals_pae16
1217%endif
1218
1219 ; Do the mode switch.
1220 xor ax, ax
1221 mov ds, ax
1222 lgdt [gdtr]
1223%ifdef BS2_WITH_TRAPS
1224 lidt [idtr_32bit]
1225%elifdef BS2_WITH_RAW_MODE
1226 lidt [idtr_dummy_32bit]
1227%else
1228 lidt [idtr_null]
1229%endif
1230
1231 mov eax, BS2_PAE_PDP_ADDR
1232 mov cr3, eax
1233%ifdef BS2_WITH_TRAPS
1234 mov [bs2Tss32BitDf + BS2_TSS32_CR3_OFF], eax
1235%endif
1236
1237 mov eax, cr4
1238 or eax, X86_CR4_PAE | X86_CR4_PSE
1239 mov cr4, eax
1240
1241 mov eax, cr0
1242 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_WP
1243 mov cr0, eax
1244 jmp far BS2_SEL_CS16:bs2ProtModeCode16Start_p16
1245ENDPROC Bs2EnterMode_rm_pae16
1246%endif ; BS2_INC_PAE16
1247
1248
1249%ifdef BS2_INC_PAE32
1250;;
1251; Enters PAE protected mode from real mode (cs = 0).
1252;
1253; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1254; ebp and esp converted to 32-bit.
1255; All other registers are preserved.
1256; @uses nothing
1257;
1258BEGINCODELOW
1259BITS 16
1260BEGINPROC Bs2EnterMode_rm_pae32
1261 push word 0
1262 push eax
1263 pushfd
1264 cli
1265%ifndef BS2_NOINC_COMMON
1266 push dword SetCpuModeGlobals_pae32
1267%endif
1268
1269 ; Do the mode switch.
1270 xor ax, ax
1271 mov ds, ax
1272 lgdt [gdtr]
1273%ifdef BS2_WITH_TRAPS
1274 lidt [idtr_32bit]
1275%elifdef BS2_WITH_RAW_MODE
1276 lidt [idtr_dummy_32bit]
1277%else
1278 lidt [idtr_null]
1279%endif
1280
1281 mov eax, BS2_PAE_PDP_ADDR
1282 mov cr3, eax
1283%ifdef BS2_WITH_TRAPS
1284 mov [bs2Tss32BitDf + BS2_TSS32_CR3_OFF], eax
1285%endif
1286
1287 mov eax, cr4
1288 or eax, X86_CR4_PAE | X86_CR4_PSE
1289 mov cr4, eax
1290
1291 mov eax, cr0
1292 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_WP
1293 mov cr0, eax
1294 jmp far BS2_SEL_CS32:bs2ProtModeCode32Start_p32
1295ENDPROC Bs2EnterMode_rm_pae32
1296%endif ; BS2_INC_PAE32
1297
1298
1299;; @todo BS2_INC_PAEV86
1300
1301
1302%ifdef BS2_INC_LM16
1303;;
1304; Enters long mode from real mode (cs = 0).
1305;
1306; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1307; rbp and rsp converted to 16/32/64-bit.
1308; All other registers are preserved.
1309; @uses nothing
1310;
1311BEGINCODELOW
1312BITS 16
1313BEGINPROC Bs2EnterMode_rm_lm16
1314 call Bs2EnterMode_rm_lm64
1315BITS 64
1316 call Bs2Thunk_lm64_lm16
1317BITS 16
1318 ret
1319ENDPROC Bs2EnterMode_rm_lm16
1320%endif ; BS2_INC_LM16
1321
1322
1323%ifdef BS2_INC_LM32
1324;;
1325; Enters long mode from real mode (cs = 0).
1326;
1327; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1328; rbp and rsp converted to 16/32/64-bit.
1329; All other registers are preserved.
1330; @uses nothing
1331;
1332BEGINCODELOW
1333BITS 16
1334BEGINPROC Bs2EnterMode_rm_lm32
1335 ; Change the return address into a 32-bit one.
1336 push word 0 ; Reserved 2 extra bytes for 32-bit return address.
1337 push eax ; Save eax.
1338 movzx eax, word [esp + 6h] ; Read narrow return address.
1339 mov [esp + 4h], eax ; Store wide return address.
1340 pop eax ; Restore eax.
1341
1342 ; Do the mode switch and thunking.
1343 call Bs2EnterMode_rm_lm64
1344BITS 64
1345 call Bs2Thunk_lm64_lm32
1346BITS 32
1347 ret
1348ENDPROC Bs2EnterMode_rm_lm32
1349%endif ; BS2_INC_LM32
1350
1351
1352%ifdef BS2_INC_LM64
1353;;
1354; Enters long mode from real mode (cs = 0).
1355;
1356; @returns cs,ds,ss,es,gs,fs loaded with 64-bit selectors.
1357; rbp and rsp converted to 64-bit.
1358; All other registers are preserved.
1359; @uses nothing
1360;
1361BEGINCODELOW
1362BITS 16
1363BEGINPROC Bs2EnterMode_rm_lm64
1364 push word 0 ; reserve bytes for 64-bit return address.
1365 push dword 0
1366 push dword 0 ; rax
1367 push eax
1368 push dword 0 ; rcx
1369 push ecx
1370 push dword 0 ; rdx
1371 push edx
1372 push dword 0 ; rflags
1373 pushfd
1374 cli
1375
1376 ; Fix the return address.
1377 mov ax, [esp + 20h + 6h]
1378 mov word [esp + 20h + 6h], 0
1379 mov [esp + 20h], ax
1380
1381 ;
1382 ; Switch to long mode.
1383 ;
1384 xor ax, ax
1385 mov ds, ax
1386 lgdt [gdtr]
1387%ifdef BS2_WITH_TRAPS
1388 lidt [idtr_64bit]
1389%else
1390 lidt [idtr_null]
1391%endif
1392
1393 mov eax, BS2_LM_PML4_ADDR
1394 mov cr3, eax
1395
1396 mov eax, cr4
1397 or eax, X86_CR4_PAE | X86_CR4_PSE
1398 mov cr4, eax
1399
1400 mov ecx, MSR_K6_EFER
1401 rdmsr
1402 or eax, MSR_K6_EFER_LME
1403 wrmsr
1404
1405 mov eax, cr0
1406 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_WP
1407 mov cr0, eax
1408 jmp far BS2_SEL_CS64:.code64_start
1409
1410BITS 64
1411.code64_start:
1412 mov eax, BS2_SEL_DS64
1413 mov ds, ax
1414 mov es, ax
1415 mov fs, ax
1416 mov gs, ax
1417 mov ax, BS2_SEL_SS64
1418 mov ss, ax
1419%ifdef BS2_WITH_TRAPS
1420 btr dword [bs2Gdt + BS2_SEL_TSS64 + 32/8], 1+8 ; busy -> avail
1421 %ifndef BS2_WITH_MANUAL_LTR
1422 mov ax, BS2_SEL_TSS64
1423 ltr ax
1424 %endif
1425%endif
1426
1427 and ebp, 0ffffh
1428 and esp, 0ffffh
1429 and edi, 0ffffffffh
1430 and esi, 0ffffffffh
1431 and ebx, 0ffffffffh
1432
1433%ifndef BS2_NOINC_COMMON
1434 call SetCpuModeGlobals_lm64
1435%endif
1436
1437 popf
1438 pop rdx
1439 pop rcx
1440 pop rax
1441 ret
1442ENDPROC Bs2EnterMode_rm_lm64
1443%endif ; BS2_INC_PAE32
1444
1445
1446
1447%ifdef BS2_INC_CMN_P16
1448;;
1449; Code shared by the three 16-bit protected mode switchers.
1450;
1451; @internal
1452;
1453BEGINCODELOW
1454BITS 16
1455BEGINPROC bs2ProtModeCode16Start_p16
1456 ; Initialize the registers.
1457 mov ax, BS2_SEL_DS16
1458 mov ds, ax
1459 mov es, ax
1460 mov fs, ax
1461 mov gs, ax
1462 mov ax, BS2_SEL_SS16
1463 mov ss, ax
1464 and esp, 0ffffh
1465 and ebp, 0ffffh
1466%ifdef BS2_WITH_TRAPS
1467 btr word [bs2Gdt + BS2_SEL_TSS32 + 32/8], 1+8 ; busy -> avail
1468 btr word [bs2Gdt + BS2_SEL_TSS32_DF + 32/8], 1+8 ; busy -> avail
1469 %ifndef BS2_WITH_MANUAL_LTR
1470 mov ax, BS2_SEL_TSS32
1471 ltr ax
1472 %endif
1473%endif
1474
1475%ifndef BS2_NOINC_COMMON
1476 ; Set up mode specific global variables.
1477 pop ax
1478 call ax
1479%endif
1480
1481 popfd
1482 pop eax
1483 ret
1484ENDPROC bs2ProtModeCode16Start_p16
1485%endif ; BS2_INC_CMN_P16
1486
1487
1488%ifdef BS2_INC_CMN_P32
1489;;
1490; Code shared by the three 32-bit protected mode switchers.
1491;
1492; @internal
1493;
1494BEGINCODELOW
1495BITS 32
1496BEGINPROC bs2ProtModeCode32Start_p32
1497 ; Initialize the registers.
1498 mov ax, BS2_SEL_DS32
1499 mov ds, ax
1500 mov es, ax
1501 mov fs, ax
1502 mov gs, ax
1503 mov ax, BS2_SEL_SS32
1504 mov ss, ax
1505 and esp, 0ffffh
1506 and ebp, 0ffffh
1507%ifdef BS2_WITH_TRAPS
1508 btr dword [bs2Gdt + BS2_SEL_TSS32 + 32/8], 1+8 ; busy -> avail
1509 btr dword [bs2Gdt + BS2_SEL_TSS32_DF + 32/8], 1+8 ; busy -> avail
1510 %ifndef BS2_WITH_MANUAL_LTR
1511 mov ax, BS2_SEL_TSS32
1512 ltr ax
1513 %endif
1514%endif
1515
1516%ifndef BS2_NOINC_COMMON
1517 ; Set up mode specific global variables.
1518 pop eax
1519 call eax
1520%endif
1521
1522 ; Make the return address 32-bit and then return.
1523 movzx eax, word [esp + 0ah]
1524 mov [esp + 8h], eax
1525 popfd
1526 pop eax
1527 ret
1528ENDPROC bs2ProtModeCode32Start_p32
1529%endif ; BS2_INC_CMN_P32
1530
1531
1532
1533;
1534; Routines for exitting the different modes.
1535;
1536
1537
1538%ifdef BS2_INC_RM
1539;;
1540; Dummy.
1541BEGINCODELOW
1542BITS 16
1543BEGINPROC Bs2ExitMode_rm
1544 ret
1545ENDPROC Bs2ExitMode_rm
1546%endif ; BS2_INC_RM
1547
1548
1549%ifdef BS2_INC_PE16
1550;;
1551; See bs2ExitMode_p16.
1552BEGINCODELOW
1553BITS 16
1554BEGINPROC Bs2ExitMode_pe16
1555 push bs2ExitModeCleanupNop_rm
1556 jmp bs2ExitMode_p16
1557ENDPROC Bs2ExitMode_pe16
1558%endif ; BS2_INC_PE16
1559
1560
1561%ifdef BS2_INC_PE32
1562;;
1563; See bs2ExitMode_p32.
1564BEGINCODEHIGH
1565BITS 32
1566BEGINPROC Bs2ExitMode_pe32
1567 push bs2ExitModeCleanupNop_rm
1568 jmp bs2ExitMode_p32
1569ENDPROC Bs2ExitMode_pe32
1570%endif ; BS2_INC_PE32
1571
1572
1573%ifdef BS2_INC_PEV86
1574;;
1575; See Bs2ExitMode_v86.
1576BEGINCODELOW
1577BITS 16
1578BEGINPROC Bs2ExitMode_pev86
1579 push bs2ExitModeCleanupNop_rm
1580 jmp Bs2ExitMode_pv86
1581ENDPROC Bs2ExitMode_pev86
1582%endif ; BS2_INC_PEV86
1583
1584
1585%ifdef BS2_INC_PP16
1586;;
1587; See bs2ExitMode_p16.
1588BEGINCODELOW
1589BITS 16
1590BEGINPROC Bs2ExitMode_pp16
1591 push bs2ExitModeCleanupNop_rm
1592 jmp bs2ExitMode_p16
1593ENDPROC Bs2ExitMode_pp16
1594%endif ; BS2_INC_PP16
1595
1596
1597%ifdef BS2_INC_PP32
1598;;
1599; See bs2ExitMode_p32.
1600BEGINCODEHIGH
1601BITS 32
1602BEGINPROC Bs2ExitMode_pp32
1603 push bs2ExitModeCleanupNop_rm
1604 jmp bs2ExitMode_p32
1605ENDPROC Bs2ExitMode_pp32
1606%endif ; BS2_INC_PP32
1607
1608
1609%ifdef BS2_INC_PPV86
1610;;
1611; See Bs2ExitMode_v86.
1612BEGINCODELOW
1613BITS 16
1614BEGINPROC Bs2ExitMode_ppv86
1615 push bs2ExitModeCleanupNop_rm
1616 jmp Bs2ExitMode_pv86
1617ENDPROC Bs2ExitMode_ppv86
1618%endif ; BS2_INC_PPV86
1619
1620
1621
1622%ifdef BS2_INC_PAE16
1623;;
1624; See bs2ExitMode_p16.
1625BEGINCODELOW
1626BITS 16
1627BEGINPROC Bs2ExitMode_pae16
1628 push bs2ExitModeCleanupPae_rm
1629 jmp bs2ExitMode_p16
1630ENDPROC Bs2ExitMode_pae16
1631%endif ; BS2_INC_pae16
1632
1633
1634%ifdef BS2_INC_PAE32
1635;;
1636; See bs2ExitMode_p32.
1637BEGINCODEHIGH
1638BITS 32
1639BEGINPROC Bs2ExitMode_pae32
1640 push bs2ExitModeCleanupPae_rm
1641 jmp bs2ExitMode_p32
1642ENDPROC Bs2ExitMode_pae32
1643%endif ; BS2_INC_PAE32
1644
1645
1646%ifdef BS2_INC_PAEV86
1647;;
1648; See Bs2ExitMode_v86.
1649BEGINCODELOW
1650BITS 16
1651BEGINPROC Bs2ExitMode_paev86
1652 push bs2ExitModeCleanupPae_rm
1653 jmp Bs2ExitMode_pv86
1654ENDPROC Bs2ExitMode_paev86
1655%endif ; BS2_INC_PAEV86
1656
1657
1658%ifdef BS2_INC_LM16
1659;;
1660; See bs2ExitMode_p16.
1661BEGINCODELOW
1662BITS 16
1663BEGINPROC Bs2ExitMode_lm16
1664 push bs2ExitModeCleanupLm_rm
1665 jmp bs2ExitMode_p16
1666ENDPROC Bs2ExitMode_lm16
1667%endif ; BS2_INC_lm16
1668
1669
1670%ifdef BS2_INC_LM32
1671;;
1672; See bs2ExitMode_p32.
1673BEGINCODEHIGH
1674BITS 32
1675BEGINPROC Bs2ExitMode_lm32
1676 push bs2ExitModeCleanupLm_rm
1677 jmp bs2ExitMode_p32
1678ENDPROC Bs2ExitMode_lm32
1679%endif ; BS2_INC_LM32
1680
1681
1682%ifdef BS2_INC_LM64
1683;;
1684; See Bs2ExitMode_v86.
1685BEGINCODELOW
1686BITS 64
1687BEGINPROC Bs2ExitMode_lm64
1688 call Bs2Thunk_lm64_lm16
1689BITS 16
1690 pop dword [esp]
1691 pop word [esp]
1692 push bs2ExitModeCleanupLm_rm
1693 jmp bs2ExitMode_p16
1694ENDPROC Bs2ExitMode_lm64
1695%endif ; BS2_INC_LM64
1696
1697
1698; Isn't there a better way to do this in yasm?
1699%ifdef BS2_INC_CMN_P16
1700 %define BS2_INC_BS2EXITMODE_P16
1701%elifdef BS2_INC_CMN_LM
1702 %define BS2_INC_BS2EXITMODE_P16
1703%elifdef BS2_INC_CMN_P32
1704 %define BS2_INC_BS2EXITMODE_P16
1705%endif
1706
1707%ifdef BS2_INC_BS2EXITMODE_P16
1708;;
1709; Exit 16-bit protected or long mode (cs = CS16, ss = SS16).
1710;
1711; @returns cs,ds,ss,es,gs,fs loaded with the 0 selector.
1712; All other registers are preserved.
1713; @uses nothing
1714;
1715BEGINCODELOW
1716BITS 16
1717BEGINPROC bs2ExitMode_p16
1718 push eax
1719 pushfd
1720 cli
1721
1722 ; Make sure we've got the right SS and CS values (paranoia).
1723 mov ax, BS2_SEL_SS16
1724 mov ss, ax
1725 jmp far BS2_SEL_CS16:.code16_start
1726
1727.code16_start:
1728 ; Turn off paging and protected mode.
1729 mov eax, cr0
1730 and eax, 0ffffffffh - X86_CR0_PE - X86_CR0_PG
1731 mov cr0, eax
1732 jmp far 0000:.real_mode_start
1733
1734.real_mode_start:
1735 ; Load the correct real mode segment registers.
1736 xor ax, ax
1737 mov ss, ax
1738 mov ds, ax
1739 mov es, ax
1740 mov fs, ax
1741 mov gs, ax
1742
1743 ; Load the real mode idtr.
1744 lidt [idtr_real_mode]
1745
1746 ; Cleanup.
1747 mov ax, [esp + 8h]
1748 call ax
1749
1750%ifndef BS2_NOINC_COMMON
1751 ; Set globals.
1752 call SetCpuModeGlobals_rm
1753%endif
1754
1755 popfd
1756 pop eax
1757 add sp, 2h ; cleanup routine address
1758 ret
1759ENDPROC bs2ExitMode_p16
1760%endif ; BS2_INC_CMN_P16
1761
1762
1763%ifdef BS2_INC_CMN_P32
1764;;
1765; Exit 32-bit protected or long mode (cs = CS32, ss = SS32).
1766;
1767; The return address as well as the stack registers must be somewhere within
1768; the first 64KB of the address space.
1769;
1770; @returns cs,ds,ss,es,gs,fs loaded with the 0 selector.
1771; All other registers are preserved.
1772; @uses nothing
1773;
1774BEGINCODELOW
1775BITS 32
1776BEGINPROC bs2ExitMode_p32
1777 push eax
1778 mov eax, [esp + 8h] ; return address
1779 mov [esp + 0ah], ax
1780 mov eax, [esp + 4h] ; cleanup routine address
1781 mov [esp + 08h], ax
1782 pop eax
1783 add esp, 4h
1784
1785 call Bs2Thunk_p32_p16
1786BITS 16
1787 jmp bs2ExitMode_p16
1788ENDPROC bs2ExitMode_p32
1789%endif ; BS2_INC_CMN_P32
1790
1791
1792;;
1793; Dummy cleanup routine.
1794BEGINCODELOW
1795BITS 16
1796BEGINPROC bs2ExitModeCleanupNop_rm
1797 ret
1798ENDPROC bs2ExitModeCleanupNop_rm
1799
1800
1801%ifdef BS2_INC_CMN_PAE
1802;;
1803; Cleans up after leaving PAE mode.
1804; @uses nothing
1805BEGINCODELOW
1806BITS 16
1807BEGINPROC bs2ExitModeCleanupPae_rm
1808 push eax
1809 mov eax, cr4
1810 and eax, ~X86_CR4_PAE
1811 mov cr4, eax
1812 pop eax
1813 ret
1814ENDPROC bs2ExitModeCleanupPae_rm
1815%endif
1816
1817
1818%ifdef BS2_INC_CMN_LM
1819;;
1820; Cleans up after leaving long mode.
1821; @uses nothing
1822BEGINCODELOW
1823BITS 16
1824BEGINPROC bs2ExitModeCleanupLm_rm
1825 push eax
1826 push edx
1827 push ecx
1828
1829 mov ecx, MSR_K6_EFER
1830 rdmsr
1831 and eax, ~MSR_K6_EFER_LME
1832 wrmsr
1833
1834 pop ecx
1835 pop edx
1836 pop eax
1837 ret
1838ENDPROC bs2ExitModeCleanupLm_rm
1839%endif
1840
1841
1842
1843;
1844; Thunking routines for switching between 16/32/64-bit code.
1845;
1846
1847
1848%ifdef BS2_INC_CMN_PM
1849;;
1850; Switches from 32-bit to 16-bit mode ({eip,esp,ebp} < 64KB).
1851;
1852; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1853; All other registers are preserved.
1854; @uses nothing
1855;
1856BEGINCODELOW
1857BITS 32
1858BEGINPROC Bs2Thunk_p32_p16
1859 push eax
1860 pushf
1861 cli
1862 mov ax, BS2_SEL_SS16
1863 jmp far BS2_SEL_CS16:.code16_start
1864BITS 16
1865.code16_start:
1866 mov ss, ax
1867 mov ax, BS2_SEL_DS16
1868 mov ds, ax
1869 mov es, ax
1870 mov fs, ax
1871 mov gs, ax
1872
1873 ; Fix the return address and then return.
1874 mov ax, [esp + 08h]
1875 mov [esp + 0ah], ax
1876 popfd
1877 pop eax
1878 add sp, 2h
1879 ret
1880ENDPROC Bs2Thunk_p32_p16
1881 %define Bs2Thunk_p32_pe16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1882 %define Bs2Thunk_p32_pp16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1883 %define Bs2Thunk_p32_pae16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1884%endif ; BS2_INC_CMN_PM
1885
1886
1887%ifdef BS2_INC_CMN_PM
1888;;
1889; Switches from 16-bit to 32-bit mode (cs = CS16, ds = DS16).
1890;
1891; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1892; ebp and esp converted to 32bit.
1893; All other registers are preserved.
1894; @uses nothing
1895;
1896BEGINCODELOW
1897BITS 16
1898BEGINPROC Bs2Thunk_p16_p32
1899 push word 0
1900 push eax
1901 pushfd
1902 cli
1903 jmp far BS2_SEL_CS32:.code32_start
1904BITS 32
1905.code32_start:
1906 mov eax, BS2_SEL_SS32
1907 mov ss, ax
1908 mov ax, BS2_SEL_DS32
1909 mov ds, ax
1910 mov es, ax
1911 mov fs, ax
1912 mov gs, ax
1913 and ebp, 0ffffh
1914 and esp, 0ffffh
1915
1916 ; Fix the return address and then return.
1917 movzx eax, word [esp + 0ah]
1918 mov [esp + 08h], eax
1919 popfd
1920 pop eax
1921 ret
1922ENDPROC Bs2Thunk_p16_p32
1923 %define Bs2Thunk_p16_pe32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1924 %define Bs2Thunk_p16_pp32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1925 %define Bs2Thunk_p16_pae32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1926%endif ; BS2_INC_CMN_PM
1927
1928
1929%ifdef BS2_INC_CMN_LM
1930;;
1931; Switches from 64-bit to 16-bit mode ({rip,rsp,rbp} < 64KB).
1932;
1933; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1934; All other registers are preserved.
1935; @uses nothing
1936;
1937BEGINCODELOW
1938BITS 64
1939BEGINPROC Bs2Thunk_lm64_lm16
1940 push rax
1941 pushf
1942 cli
1943 mov ax, BS2_SEL_SS16
1944 push BS2_SEL_CS16
1945 push .code16_start
1946 retf
1947BITS 16
1948.code16_start:
1949 mov ss, ax
1950 mov ax, BS2_SEL_DS16
1951 mov ds, ax
1952 mov es, ax
1953 mov fs, ax
1954 mov gs, ax
1955
1956 ; Fix the return address and then return.
1957 mov ax, [esp + 10h]
1958 mov [esp + 16h], ax
1959 popfd
1960 add sp, 4h
1961 pop eax
1962 add sp, 4h + 6h
1963 ret
1964ENDPROC Bs2Thunk_lm64_lm16
1965 %define Bs2Thunk_p64_lm16 Bs2Thunk_lm64_lm16 ; Alternative name for TMPL_NM
1966%endif ; BS2_INC_CMN_LM
1967
1968
1969%ifdef BS2_INC_LM16
1970;;
1971; Switches from 16-bit to 64-bit mode (cs = CS16, ss = SS16).
1972;
1973; @returns cs,ds,ss,es,gs,fs loaded with 64-bit selectors.
1974; rbp and rsp converted to 16/32/64-bit.
1975; All other registers are preserved.
1976; @uses nothing
1977;
1978BEGINCODELOW
1979BITS 16
1980BEGINPROC Bs2Thunk_lm16_lm64
1981 push word 0
1982 push dword 0
1983 push dword 0
1984 push eax
1985 push dword 0
1986 pushfd
1987 cli
1988 mov eax, BS2_SEL_SS64
1989 jmp far BS2_SEL_CS64:.code64_start
1990BITS 64
1991.code64_start:
1992 mov ss, ax
1993 mov ax, BS2_SEL_DS64
1994 mov ds, ax
1995 mov es, ax
1996 mov fs, ax
1997 mov gs, ax
1998
1999 and ebp, 0ffffh
2000 and esp, 0ffffh
2001 and edi, 0ffffffffh
2002 and esi, 0ffffffffh
2003 and ebx, 0ffffffffh
2004
2005 ; Fix the return address and then return.
2006 movzx rax, word [rsp + 16h]
2007 mov [rsp + 10h], rax
2008 popf
2009 pop rax
2010 ret
2011ENDPROC Bs2Thunk_lm16_lm64
2012 %define Bs2Thunk_p16_lm64 Bs2Thunk_lm16_lm64 ; Alternative name for TMPL_NM
2013%endif ; BS2_INC_LM16
2014
2015
2016%ifdef BS2_INC_LM32
2017;;
2018; Switches from 64-bit to 32-bit mode ({rip,rsp,rbp} < 4GB).
2019;
2020; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
2021; All other registers are preserved.
2022; @uses nothing
2023;
2024BEGINCODEHIGH
2025BITS 64
2026BEGINPROC Bs2Thunk_lm64_lm32
2027 push rax
2028 pushf
2029 cli
2030 mov ax, BS2_SEL_SS32
2031 push BS2_SEL_CS32
2032 push .code32_start
2033 retf
2034BITS 32
2035.code32_start:
2036 mov ss, ax
2037 mov ax, BS2_SEL_DS32
2038 mov ds, ax
2039 mov es, ax
2040 mov fs, ax
2041 mov gs, ax
2042
2043 ; Fix the return address and then return.
2044 mov eax, [esp + 10h]
2045 mov [esp + 14h], eax
2046 popfd
2047 mov eax, [esp + 4h]
2048 lea esp, [esp + 10h]
2049 ret
2050ENDPROC Bs2Thunk_lm64_lm32
2051 %define Bs2Thunk_p64_lm32 Bs2Thunk_lm64_lm32 ; Alternative name for TMPL_NM
2052%endif ; BS2_INC_LM32
2053
2054
2055%ifdef BS2_INC_LM32
2056;;
2057; Switches from 32-bit to 64-bit mode (cs = CS32, ss = SS32).
2058;
2059; @returns cs,ds,ss,es,gs,fs loaded with 64-bit selectors.
2060; rbp and rsp converted to 32/64-bit.
2061; All other registers are preserved.
2062; @uses nothing
2063;
2064BEGINCODEHIGH
2065BITS 32
2066BEGINPROC Bs2Thunk_lm32_lm64
2067 push dword 0
2068 push dword 0
2069 push eax
2070 push dword 0
2071 pushfd
2072 cli
2073 mov eax, BS2_SEL_SS64
2074 jmp far BS2_SEL_CS64:.code64_start
2075BITS 64
2076.code64_start:
2077 mov ss, ax
2078 mov ax, BS2_SEL_DS64
2079 mov ds, ax
2080 mov es, ax
2081 mov fs, ax
2082 mov gs, ax
2083
2084 and ebp, 0ffffffffh
2085 and esp, 0ffffffffh
2086 and edi, 0ffffffffh
2087 and esi, 0ffffffffh
2088 and ebx, 0ffffffffh
2089
2090 ; Fix the return address and then return.
2091 mov eax, [rsp + 14h]
2092 mov [rsp + 10h], rax
2093 popf
2094 pop rax
2095 ret
2096ENDPROC Bs2Thunk_lm32_lm64
2097 %define Bs2Thunk_p32_lm64 Bs2Thunk_lm32_lm64 ; Alternative name for TMPL_NM
2098%endif ; BS2_INC_LM32
2099
2100
2101
2102
2103;
2104; Routines for checking if mode is supported or not.
2105;
2106; @returns al=1 & ZF=0 if supported, al=0 & ZF=1 if not.
2107; @uses nothing.
2108;
2109
2110; These are easy.
2111BEGINCODELOW
2112BITS 16
2113BEGINPROC bs2IsModeSupportedYes_rm
2114GLOBALNAME Bs2IsModeSupported_rm_rm
2115GLOBALNAME Bs2IsModeSupported_rm_pe16
2116GLOBALNAME Bs2IsModeSupported_rm_pe32
2117GLOBALNAME Bs2IsModeSupported_rm_pev86
2118GLOBALNAME Bs2IsModeSupported_rm_pp16
2119GLOBALNAME Bs2IsModeSupported_rm_pp32
2120GLOBALNAME Bs2IsModeSupported_rm_ppv86
2121 mov al, 1
2122 test al, al
2123 ret
2124ENDPROC bs2IsModeSupportedYes_rm
2125
2126
2127%ifdef BS2_INC_CMN_PAE
2128BEGINCODELOW
2129BITS 16
2130BEGINPROC Bs2IsPaeSupported_16
2131GLOBALNAME Bs2IsModeSupported_rm_pae16
2132GLOBALNAME Bs2IsModeSupported_rm_pae32
2133GLOBALNAME Bs2IsModeSupported_rm_paev86
2134 push eax
2135 push ebx
2136 push ecx
2137 push edx
2138
2139 mov eax, 0
2140 cpuid
2141 cmp eax, 1
2142 jb .no
2143 cmp eax, 1000h
2144 ja .no
2145
2146 mov eax, 1
2147 cpuid
2148 test edx, X86_CPUID_FEATURE_EDX_PAE
2149
2150 pop edx
2151 pop ecx
2152 pop ebx
2153 pop eax
2154
2155 mov al, 0
2156 jz .no
2157 mov al, 1
2158.no:
2159 ret
2160ENDPROC Bs2IsPaeSupported_16
2161%endif ; BS2_INC_CMN_PAE
2162
2163
2164%ifdef BS2_INC_CMN_LM
2165BEGINCODELOW
2166BITS 16
2167BEGINPROC Bs2IsLongModeSupported_16
2168GLOBALNAME Bs2IsModeSupported_rm_lm16
2169GLOBALNAME Bs2IsModeSupported_rm_lm32
2170GLOBALNAME Bs2IsModeSupported_rm_lm64
2171 push eax
2172 push ebx
2173 push ecx
2174 push edx
2175
2176 mov eax, 080000000h
2177 cpuid
2178 cmp eax, 080000001h
2179 jb .no
2180 cmp eax, 080001000h
2181 ja .no
2182
2183 mov eax, 080000001h
2184 cpuid
2185 test edx, X86_CPUID_EXT_FEATURE_EDX_LONG_MODE
2186
2187 pop edx
2188 pop ecx
2189 pop ebx
2190 pop eax
2191
2192 mov al, 0
2193 jz .no
2194 mov al, 1
2195.no:
2196 ret
2197ENDPROC Bs2IsLongModeSupported_16
2198%endif ; BS2_INC_CMN_LM
2199
2200
2201;
2202; Include addition init/base code.
2203;
2204%ifdef BS2_WITH_TRAPS
2205 %include "bootsector2-common-init-traps.mac"
2206%endif
2207
2208
2209;
2210; Include common code.
2211;
2212%ifndef BS2_NOINC_COMMON
2213 %include "bootsector2-common-routines.mac"
2214%endif
2215
2216;
2217; Include trap records if requested.
2218;
2219%ifdef BS2_WITH_TRAPRECS
2220 %include "bootsector2-common-traprec.mac"
2221%endif
2222
2223;
2224; Map stuff for the initial environment.
2225;
2226%ifdef BS2_INIT_RM
2227 %define TMPL_RM
2228%endif
2229%ifdef BS2_INIT_PE32
2230 %define TMPL_PE32
2231%endif
2232%ifdef BS2_INIT_PP32
2233 %define TMPL_PP32
2234%endif
2235%ifdef BS2_INIT_PAE32
2236 %define TMPL_PAE32
2237%endif
2238%ifdef BS2_INIT_LM64
2239 %define TMPL_LM64
2240%endif
2241%include "bootsector2-template-header.mac"
2242
2243
2244;
2245; Where we jump after initialization.
2246;
2247TMPL_BEGINCODE
2248BITS TMPL_BITS
2249bs2DoneInit:
2250%ifdef BS2_INIT_SAVE_REGS
2251 mov eax, cr2
2252 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr2], eax
2253 mov eax, cr3
2254 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr3], eax
2255 mov eax, cr4
2256 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr4], eax
2257 mov byte [BS2_REG_SAVE_ADDR + BS2REGS.cBits], 16
2258 xor eax, eax
2259 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.cs], ax
2260 mov ax, start
2261 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.rip], eax
2262%endif
2263
2264%ifdef BS2_WITH_TRAPRECS
2265 ;
2266 ; Install the trap records.
2267 ;
2268 BS2_TRAP_RECS_INSTALL
2269%endif
2270
2271 ;
2272 ; Detect the CPU.
2273 ;
2274 xor eax, eax
2275 mov [g_fCpuIntel], al
2276 mov [g_fCpuAmd], al
2277 cpuid
2278 cmp ecx, 0x444d4163
2279 jne .not_amd
2280 cmp edx, 0x69746e65
2281 jne .not_amd
2282 cmp ebx, 0x68747541
2283 jne .not_amd
2284 mov byte [g_fCpuAmd], 1
2285 jmp .not_intel
2286
2287.not_amd:
2288 cmp ecx, 0x6c65746e
2289 jne .not_intel
2290 cmp edx, 0x49656e69
2291 jne .not_intel
2292 cmp ebx, 0x756e6547
2293 jne .not_intel
2294 mov byte [g_fCpuIntel], 1
2295.not_intel:
2296
2297 ;
2298 ; Call the user 'main' procedure (shouldn't return).
2299 ;
2300 call main
2301.panic_again
2302 call Bs2Panic
2303 jmp .panic_again
2304
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