VirtualBox

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

Last change on this file since 76690 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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