VirtualBox

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

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

bootsector2-common-init-*: fixes.

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