VirtualBox

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

Last change on this file since 105374 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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