VirtualBox

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

Last change on this file since 53517 was 52776, checked in by vboxsync, 10 years ago

fix OSE

  • 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 52776 2014-09-17 14:51:43Z 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-2014 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%endif
1697
1698%ifdef BS2_INC_BS2EXITMODE_P16
1699;;
1700; Exit 16-bit protected or long mode (cs = CS16, ss = SS16).
1701;
1702; @returns cs,ds,ss,es,gs,fs loaded with the 0 selector.
1703; All other registers are preserved.
1704; @uses nothing
1705;
1706BEGINCODELOW
1707BITS 16
1708BEGINPROC bs2ExitMode_p16
1709 push eax
1710 pushfd
1711 cli
1712
1713 ; Make sure we've got the right SS and CS values (paranoia).
1714 mov ax, BS2_SEL_SS16
1715 mov ss, ax
1716 jmp far BS2_SEL_CS16:.code16_start
1717
1718.code16_start:
1719 ; Turn off paging and protected mode.
1720 mov eax, cr0
1721 and eax, 0ffffffffh - X86_CR0_PE - X86_CR0_PG
1722 mov cr0, eax
1723 jmp far 0000:.real_mode_start
1724
1725.real_mode_start:
1726 ; Load the correct real mode segment registers.
1727 xor ax, ax
1728 mov ss, ax
1729 mov ds, ax
1730 mov es, ax
1731 mov fs, ax
1732 mov gs, ax
1733
1734 ; Load the real mode idtr.
1735 lidt [idtr_real_mode]
1736
1737 ; Cleanup.
1738 mov ax, [esp + 8h]
1739 call ax
1740
1741%ifndef BS2_NOINC_COMMON
1742 ; Set globals.
1743 call SetCpuModeGlobals_rm
1744%endif
1745
1746 popfd
1747 pop eax
1748 add sp, 2h ; cleanup routine address
1749 ret
1750ENDPROC bs2ExitMode_p16
1751%endif ; BS2_INC_CMN_P16
1752
1753
1754%ifdef BS2_INC_CMN_P32
1755;;
1756; Exit 32-bit protected or long mode (cs = CS32, ss = SS32).
1757;
1758; The return address as well as the stack registers must be somewhere within
1759; the first 64KB of the address space.
1760;
1761; @returns cs,ds,ss,es,gs,fs loaded with the 0 selector.
1762; All other registers are preserved.
1763; @uses nothing
1764;
1765BEGINCODELOW
1766BITS 32
1767BEGINPROC bs2ExitMode_p32
1768 push eax
1769 mov eax, [esp + 8h] ; return address
1770 mov [esp + 0ah], ax
1771 mov eax, [esp + 4h] ; cleanup routine address
1772 mov [esp + 08h], ax
1773 pop eax
1774 add esp, 4h
1775
1776 call Bs2Thunk_p32_p16
1777BITS 16
1778 jmp bs2ExitMode_p16
1779ENDPROC bs2ExitMode_p32
1780%endif ; BS2_INC_CMN_P32
1781
1782
1783;;
1784; Dummy cleanup routine.
1785BEGINCODELOW
1786BITS 16
1787BEGINPROC bs2ExitModeCleanupNop_rm
1788 ret
1789ENDPROC bs2ExitModeCleanupNop_rm
1790
1791
1792%ifdef BS2_INC_CMN_PAE
1793;;
1794; Cleans up after leaving PAE mode.
1795; @uses nothing
1796BEGINCODELOW
1797BITS 16
1798BEGINPROC bs2ExitModeCleanupPae_rm
1799 push eax
1800 mov eax, cr4
1801 and eax, ~X86_CR4_PAE
1802 mov cr4, eax
1803 pop eax
1804 ret
1805ENDPROC bs2ExitModeCleanupPae_rm
1806%endif
1807
1808
1809%ifdef BS2_INC_CMN_LM
1810;;
1811; Cleans up after leaving long mode.
1812; @uses nothing
1813BEGINCODELOW
1814BITS 16
1815BEGINPROC bs2ExitModeCleanupLm_rm
1816 push eax
1817 push edx
1818 push ecx
1819
1820 mov ecx, MSR_K6_EFER
1821 rdmsr
1822 and eax, ~MSR_K6_EFER_LME
1823 wrmsr
1824
1825 pop ecx
1826 pop edx
1827 pop eax
1828 ret
1829ENDPROC bs2ExitModeCleanupLm_rm
1830%endif
1831
1832
1833
1834;
1835; Thunking routines for switching between 16/32/64-bit code.
1836;
1837
1838
1839%ifdef BS2_INC_CMN_PM
1840;;
1841; Switches from 32-bit to 16-bit mode ({eip,esp,ebp} < 64KB).
1842;
1843; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1844; All other registers are preserved.
1845; @uses nothing
1846;
1847BEGINCODELOW
1848BITS 32
1849BEGINPROC Bs2Thunk_p32_p16
1850 push eax
1851 pushf
1852 cli
1853 mov ax, BS2_SEL_SS16
1854 jmp far BS2_SEL_CS16:.code16_start
1855BITS 16
1856.code16_start:
1857 mov ss, ax
1858 mov ax, BS2_SEL_DS16
1859 mov ds, ax
1860 mov es, ax
1861 mov fs, ax
1862 mov gs, ax
1863
1864 ; Fix the return address and then return.
1865 mov ax, [esp + 08h]
1866 mov [esp + 0ah], ax
1867 popfd
1868 pop eax
1869 add sp, 2h
1870 ret
1871ENDPROC Bs2Thunk_p32_p16
1872 %define Bs2Thunk_p32_pe16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1873 %define Bs2Thunk_p32_pp16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1874 %define Bs2Thunk_p32_pae16 Bs2Thunk_p32_p16 ; Alternative name for TMPL_NM
1875%endif ; BS2_INC_CMN_PM
1876
1877
1878%ifdef BS2_INC_CMN_PM
1879;;
1880; Switches from 16-bit to 32-bit mode (cs = CS16, ds = DS16).
1881;
1882; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
1883; ebp and esp converted to 32bit.
1884; All other registers are preserved.
1885; @uses nothing
1886;
1887BEGINCODELOW
1888BITS 16
1889BEGINPROC Bs2Thunk_p16_p32
1890 push word 0
1891 push eax
1892 pushfd
1893 cli
1894 jmp far BS2_SEL_CS32:.code32_start
1895BITS 32
1896.code32_start:
1897 mov eax, BS2_SEL_SS32
1898 mov ss, ax
1899 mov ax, BS2_SEL_DS32
1900 mov ds, ax
1901 mov es, ax
1902 mov fs, ax
1903 mov gs, ax
1904 and ebp, 0ffffh
1905 and esp, 0ffffh
1906
1907 ; Fix the return address and then return.
1908 movzx eax, word [esp + 0ah]
1909 mov [esp + 08h], eax
1910 popfd
1911 pop eax
1912 ret
1913ENDPROC Bs2Thunk_p16_p32
1914 %define Bs2Thunk_p16_pe32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1915 %define Bs2Thunk_p16_pp32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1916 %define Bs2Thunk_p16_pae32 Bs2Thunk_p16_p32 ; Alternative name for TMPL_NM
1917%endif ; BS2_INC_CMN_PM
1918
1919
1920%ifdef BS2_INC_CMN_LM
1921;;
1922; Switches from 64-bit to 16-bit mode ({rip,rsp,rbp} < 64KB).
1923;
1924; @returns cs,ds,ss,es,gs,fs loaded with 16-bit selectors.
1925; All other registers are preserved.
1926; @uses nothing
1927;
1928BEGINCODELOW
1929BITS 64
1930BEGINPROC Bs2Thunk_lm64_lm16
1931 push rax
1932 pushf
1933 cli
1934 mov ax, BS2_SEL_SS16
1935 push BS2_SEL_CS16
1936 push .code16_start
1937 retf
1938BITS 16
1939.code16_start:
1940 mov ss, ax
1941 mov ax, BS2_SEL_DS16
1942 mov ds, ax
1943 mov es, ax
1944 mov fs, ax
1945 mov gs, ax
1946
1947 ; Fix the return address and then return.
1948 mov ax, [esp + 10h]
1949 mov [esp + 16h], ax
1950 popfd
1951 add sp, 4h
1952 pop eax
1953 add sp, 4h + 6h
1954 ret
1955ENDPROC Bs2Thunk_lm64_lm16
1956 %define Bs2Thunk_p64_lm16 Bs2Thunk_lm64_lm16 ; Alternative name for TMPL_NM
1957%endif ; BS2_INC_CMN_LM
1958
1959
1960%ifdef BS2_INC_LM16
1961;;
1962; Switches from 16-bit to 64-bit mode (cs = CS16, ss = SS16).
1963;
1964; @returns cs,ds,ss,es,gs,fs loaded with 64-bit selectors.
1965; rbp and rsp converted to 16/32/64-bit.
1966; All other registers are preserved.
1967; @uses nothing
1968;
1969BEGINCODELOW
1970BITS 16
1971BEGINPROC Bs2Thunk_lm16_lm64
1972 push word 0
1973 push dword 0
1974 push dword 0
1975 push eax
1976 push dword 0
1977 pushfd
1978 cli
1979 mov eax, BS2_SEL_SS64
1980 jmp far BS2_SEL_CS64:.code64_start
1981BITS 64
1982.code64_start:
1983 mov ss, ax
1984 mov ax, BS2_SEL_DS64
1985 mov ds, ax
1986 mov es, ax
1987 mov fs, ax
1988 mov gs, ax
1989
1990 and ebp, 0ffffh
1991 and esp, 0ffffh
1992 and edi, 0ffffffffh
1993 and esi, 0ffffffffh
1994 and ebx, 0ffffffffh
1995
1996 ; Fix the return address and then return.
1997 movzx rax, word [rsp + 16h]
1998 mov [rsp + 10h], rax
1999 popf
2000 pop rax
2001 ret
2002ENDPROC Bs2Thunk_lm16_lm64
2003 %define Bs2Thunk_p16_lm64 Bs2Thunk_lm16_lm64 ; Alternative name for TMPL_NM
2004%endif ; BS2_INC_LM16
2005
2006
2007%ifdef BS2_INC_LM32
2008;;
2009; Switches from 64-bit to 32-bit mode ({rip,rsp,rbp} < 4GB).
2010;
2011; @returns cs,ds,ss,es,gs,fs loaded with 32-bit selectors.
2012; All other registers are preserved.
2013; @uses nothing
2014;
2015BEGINCODEHIGH
2016BITS 64
2017BEGINPROC Bs2Thunk_lm64_lm32
2018 push rax
2019 pushf
2020 cli
2021 mov ax, BS2_SEL_SS32
2022 push BS2_SEL_CS32
2023 push .code32_start
2024 retf
2025BITS 32
2026.code32_start:
2027 mov ss, ax
2028 mov ax, BS2_SEL_DS32
2029 mov ds, ax
2030 mov es, ax
2031 mov fs, ax
2032 mov gs, ax
2033
2034 ; Fix the return address and then return.
2035 mov eax, [esp + 10h]
2036 mov [esp + 14h], eax
2037 popfd
2038 mov eax, [esp + 4h]
2039 lea esp, [esp + 10h]
2040 ret
2041ENDPROC Bs2Thunk_lm64_lm32
2042 %define Bs2Thunk_p64_lm32 Bs2Thunk_lm64_lm32 ; Alternative name for TMPL_NM
2043%endif ; BS2_INC_LM32
2044
2045
2046%ifdef BS2_INC_LM32
2047;;
2048; Switches from 32-bit to 64-bit mode (cs = CS32, ss = SS32).
2049;
2050; @returns cs,ds,ss,es,gs,fs loaded with 64-bit selectors.
2051; rbp and rsp converted to 32/64-bit.
2052; All other registers are preserved.
2053; @uses nothing
2054;
2055BEGINCODEHIGH
2056BITS 32
2057BEGINPROC Bs2Thunk_lm32_lm64
2058 push dword 0
2059 push dword 0
2060 push eax
2061 push dword 0
2062 pushfd
2063 cli
2064 mov eax, BS2_SEL_SS64
2065 jmp far BS2_SEL_CS64:.code64_start
2066BITS 64
2067.code64_start:
2068 mov ss, ax
2069 mov ax, BS2_SEL_DS64
2070 mov ds, ax
2071 mov es, ax
2072 mov fs, ax
2073 mov gs, ax
2074
2075 and ebp, 0ffffffffh
2076 and esp, 0ffffffffh
2077 and edi, 0ffffffffh
2078 and esi, 0ffffffffh
2079 and ebx, 0ffffffffh
2080
2081 ; Fix the return address and then return.
2082 mov eax, [rsp + 14h]
2083 mov [rsp + 10h], rax
2084 popf
2085 pop rax
2086 ret
2087ENDPROC Bs2Thunk_lm32_lm64
2088 %define Bs2Thunk_p32_lm64 Bs2Thunk_lm32_lm64 ; Alternative name for TMPL_NM
2089%endif ; BS2_INC_LM32
2090
2091
2092
2093
2094;
2095; Routines for checking if mode is supported or not.
2096;
2097; @returns al=1 & ZF=0 if supported, al=0 & ZF=1 if not.
2098; @uses nothing.
2099;
2100
2101; These are easy.
2102BEGINCODELOW
2103BITS 16
2104BEGINPROC bs2IsModeSupportedYes_rm
2105GLOBALNAME Bs2IsModeSupported_rm_rm
2106GLOBALNAME Bs2IsModeSupported_rm_pe16
2107GLOBALNAME Bs2IsModeSupported_rm_pe32
2108GLOBALNAME Bs2IsModeSupported_rm_pev86
2109GLOBALNAME Bs2IsModeSupported_rm_pp16
2110GLOBALNAME Bs2IsModeSupported_rm_pp32
2111GLOBALNAME Bs2IsModeSupported_rm_ppv86
2112 mov al, 1
2113 test al, al
2114 ret
2115ENDPROC bs2IsModeSupportedYes_rm
2116
2117
2118%ifdef BS2_INC_CMN_PAE
2119BEGINCODELOW
2120BITS 16
2121BEGINPROC Bs2IsPaeSupported_16
2122GLOBALNAME Bs2IsModeSupported_rm_pae16
2123GLOBALNAME Bs2IsModeSupported_rm_pae32
2124GLOBALNAME Bs2IsModeSupported_rm_paev86
2125 push eax
2126 push ebx
2127 push ecx
2128 push edx
2129
2130 mov eax, 0
2131 cpuid
2132 cmp eax, 1
2133 jb .no
2134 cmp eax, 1000h
2135 ja .no
2136
2137 mov eax, 1
2138 cpuid
2139 test edx, X86_CPUID_FEATURE_EDX_PAE
2140
2141 pop edx
2142 pop ecx
2143 pop ebx
2144 pop eax
2145
2146 mov al, 0
2147 jz .no
2148 mov al, 1
2149.no:
2150 ret
2151ENDPROC Bs2IsPaeSupported_16
2152%endif ; BS2_INC_CMN_PAE
2153
2154
2155%ifdef BS2_INC_CMN_LM
2156BEGINCODELOW
2157BITS 16
2158BEGINPROC Bs2IsLongModeSupported_16
2159GLOBALNAME Bs2IsModeSupported_rm_lm16
2160GLOBALNAME Bs2IsModeSupported_rm_lm32
2161GLOBALNAME Bs2IsModeSupported_rm_lm64
2162 push eax
2163 push ebx
2164 push ecx
2165 push edx
2166
2167 mov eax, 080000000h
2168 cpuid
2169 cmp eax, 080000001h
2170 jb .no
2171 cmp eax, 080001000h
2172 ja .no
2173
2174 mov eax, 080000001h
2175 cpuid
2176 test edx, X86_CPUID_EXT_FEATURE_EDX_LONG_MODE
2177
2178 pop edx
2179 pop ecx
2180 pop ebx
2181 pop eax
2182
2183 mov al, 0
2184 jz .no
2185 mov al, 1
2186.no:
2187 ret
2188ENDPROC Bs2IsLongModeSupported_16
2189%endif ; BS2_INC_CMN_LM
2190
2191
2192;
2193; Include addition init/base code.
2194;
2195%ifdef BS2_WITH_TRAPS
2196 %include "bootsector2-common-init-traps.mac"
2197%endif
2198
2199
2200;
2201; Include common code.
2202;
2203%ifndef BS2_NOINC_COMMON
2204 %include "bootsector2-common-routines.mac"
2205%endif
2206
2207;
2208; Include trap records if requested.
2209;
2210%ifdef BS2_WITH_TRAPRECS
2211 %include "bootsector2-common-traprec.mac"
2212%endif
2213
2214;
2215; Map stuff for the initial environment.
2216;
2217%ifdef BS2_INIT_RM
2218 %define TMPL_RM
2219%endif
2220%ifdef BS2_INIT_PE32
2221 %define TMPL_PE32
2222%endif
2223%ifdef BS2_INIT_PP32
2224 %define TMPL_PP32
2225%endif
2226%ifdef BS2_INIT_PAE32
2227 %define TMPL_PAE32
2228%endif
2229%ifdef BS2_INIT_LM64
2230 %define TMPL_LM64
2231%endif
2232%include "bootsector2-template-header.mac"
2233
2234
2235;
2236; Where we jump after initialization.
2237;
2238TMPL_BEGINCODE
2239BITS TMPL_BITS
2240bs2DoneInit:
2241%ifdef BS2_INIT_SAVE_REGS
2242 mov eax, cr2
2243 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr2], eax
2244 mov eax, cr3
2245 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr3], eax
2246 mov eax, cr4
2247 mov [BS2_REG_SAVE_ADDR + BS2REGS.cr4], eax
2248 mov byte [BS2_REG_SAVE_ADDR + BS2REGS.cBits], 16
2249 xor eax, eax
2250 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.cs], ax
2251 mov ax, start
2252 mov [cs:BS2_REG_SAVE_ADDR + BS2REGS.rip], eax
2253%endif
2254
2255%ifdef BS2_WITH_TRAPRECS
2256 ;
2257 ; Install the trap records.
2258 ;
2259 BS2_TRAP_RECS_INSTALL
2260%endif
2261
2262 ;
2263 ; Detect the CPU.
2264 ;
2265 xor eax, eax
2266 mov [g_fCpuIntel], al
2267 mov [g_fCpuAmd], al
2268 cpuid
2269 cmp ecx, 0x444d4163
2270 jne .not_amd
2271 cmp edx, 0x69746e65
2272 jne .not_amd
2273 cmp ebx, 0x68747541
2274 jne .not_amd
2275 mov byte [g_fCpuAmd], 1
2276 jmp .not_intel
2277
2278.not_amd:
2279 cmp ecx, 0x6c65746e
2280 jne .not_intel
2281 cmp edx, 0x49656e69
2282 jne .not_intel
2283 cmp ebx, 0x756e6547
2284 jne .not_intel
2285 mov byte [g_fCpuIntel], 1
2286.not_intel:
2287
2288 ;
2289 ; Call the user 'main' procedure (shouldn't return).
2290 ;
2291 call main
2292.panic_again
2293 call Bs2Panic
2294 jmp .panic_again
2295
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