VirtualBox

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

Last change on this file since 60778 was 58574, checked in by vboxsync, 9 years ago

bootsector2: map files with all available information.

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