summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S')
-rw-r--r--EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S296
1 files changed, 296 insertions, 0 deletions
diff --git a/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S
new file mode 100644
index 0000000000..273b3d5bc2
--- /dev/null
+++ b/EdkModulePkg/Core/DxeIplPeim/Ia32/LongMode.S
@@ -0,0 +1,296 @@
+#------------------------------------------------------------------------------
+#*
+#* Copyright (c) 2006, Intel Corporation
+#* All rights reserved. This program and the accompanying materials
+#* are licensed and made available under the terms and conditions of the BSD License
+#* which accompanies this distribution. The full text of the license may be found at
+#* http://opensource.org/licenses/bsd-license.php
+#*
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#*
+#* LongMode.S
+#*
+#* Abstract:
+#*
+#* Transition from 32-bit protected mode EFI environment into x64
+#* 64-bit bit long mode.
+#*
+#* This file is not fully ported or operational.
+#*
+#------------------------------------------------------------------------------
+
+.686p:
+#.MODEL flat
+
+#
+# Create the exception handler code in IA32 C code
+#
+
+.code:
+.stack:
+.MMX:
+.XMM:
+
+.global _LoadGo64Gdt;
+_LoadGo64Gdt:
+ pushl %ebp # C prolog
+ pushl %edi
+ movl %esp, %ebp
+ #
+ # Disable interrupts
+ #
+ cli
+ #
+ # Reload the selectors
+ # Note:
+ # Make the Selectors 64-bit ready
+ #
+ movl gdtr, %edi # Load GDT register
+ movw %cs, %ax # Get the selector data from our code image
+ mov %ax, %es
+# FIXME MISMATCH: " lgdt FWORD PTR es:[edi] "
+
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+# FIXME MISMATCH: " dd OFFSET DataSelectorRld"
+# FIXME MISMATCH: " dw LINEAR_CODE_SEL "
+DataSelectorRld:
+ movw SYS_DATA_SEL, %ax # Update the Base for the new selectors, too
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ popl %edi
+ popl %ebp
+ ret
+#_LoadGo64Gdt ENDP
+
+
+# VOID
+# ActivateLongMode (
+# IN EFI_PHYSICAL_ADDRESS PageTables,
+# IN EFI_PHYSICAL_ADDRESS HobStart,
+# IN EFI_PHYSICAL_ADDRESS Stack,
+# IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint,
+# IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
+# )
+#
+# Input: [ebp][0h] = Original ebp
+# [ebp][4h] = Return address
+# [ebp][8h] = PageTables
+# [ebp][10h] = HobStart
+# [ebp][18h] = Stack
+# [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
+# [ebp][28h] = CodeEntryPoint2 <--- Call this second
+#
+#
+.global _ActivateLongMode;
+_ActivateLongMode:
+ pushl %ebp # C prolog
+ movl %esp, %ebp
+
+ #
+ # Use CPUID to determine if the processor supports long mode.
+ #
+ movl $0x80000000, %eax # Extended-function code 8000000h.
+ cpuid # Is largest extended function
+ cmpl $0x80000000, %eax # any function > 80000000h?
+ jbe no_long_mode # If not, no long mode.
+ movl $0x80000001, %eax # Extended-function code 8000001h.
+ cpuid # Now EDX = extended-features flags.
+ btl $29, %edx # Test if long mode is supported.
+ jnc no_long_mode # Exit if not supported.
+
+ #
+ # Enable the 64-bit page-translation-table entries by
+ # setting CR4.PAE=1 (this is _required_ before activating
+ # long mode). Paging is not enabled until after long mode
+ # is enabled.
+ #
+ movl %cr4, %eax
+ btsl $5, %eax
+ movl %eax, %cr4
+
+ #
+ # Get the long-mode page tables, and initialize the
+ # 64-bit CR3 (page-table base address) to point to the base
+ # of the PML4 page table. The PML4 page table must be located
+ # below 4 Gbytes because only 32 bits of CR3 are loaded when
+ # the processor is not in 64-bit mode.
+ #
+ movl 0x8(%ebp), %eax # Get Page Tables
+ movl %eax, %cr3 # Initialize CR3 with PML4 base.
+
+ #
+ # Enable long mode (set EFER.LME=1).
+ #
+ movl $0xc0000080, %ecx # EFER MSR number.
+ rdmsr # Read EFER.
+ btsl $8, %eax # Set LME=1.
+ wrmsr # Write EFER.
+
+ #
+ # Enable paging to activate long mode (set CR0.PG=1)
+ #
+
+
+ movl %cr0, %eax # Read CR0.
+ btsl $31, %eax # Set PG=1.
+ movl %eax, %cr0 # Write CR0.
+ jmp go_to_long_mode
+go_to_long_mode:
+
+ #
+ # This is the next instruction after enabling paging. Jump to long mode
+ #
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+#FIXME MISMATCH: " dd OFFSET in_long_mode"
+#FIXME MISMATCH: " dw SYS_CODE64_SEL "
+in_long_mode:
+ movw SYS_DATA64_SEL, %ax
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %ds
+ jmp .
+
+
+ #
+ # We're in long mode, so marshall the arguments to call the
+ # passed in function pointers
+ # Recall
+ # [ebp][10h] = HobStart
+ # [ebp][18h] = Stack
+ # [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ # [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ #
+ .byte 0x48
+ movl 0x18(%ebp), %ebx # Setup the stack
+ .byte 0x48
+ movl %ebx, %esp # On a new stack now
+
+
+## 00000905 FF D0 call rax
+
+ .byte 0x48
+ movl 0x10(%ebp), %ecx # Pass Hob Start in RCX
+ .byte 0x48
+ movl 0x28(%ebp), %eax # Get the function pointer for
+ # DxeCoreEntryPoint into EAX
+
+## 00000905 FF D0 call rax
+ .byte 0xff
+ .byte 0xd0
+
+ #
+ # WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ #
+no_long_mode:
+ jmp no_long_mode
+#_ActivateLongMode ENDP
+
+ .align 16
+
+gdtr: #FIXME MISMATCH: "gdtr dw _GDT_END - _GDT_BASE - 1 "
+#FIXME MISMATCH: " dd OFFSET _GDT_BASE "
+
+#-----------------------------------------------------------------------------;
+# global descriptor table (GDT)
+#-----------------------------------------------------------------------------;
+
+ .align 16
+
+.global _GDT_BASE
+_GDT_BASE:
+# null descriptor
+.equ NULL_SEL, .-_GDT_BASE # Selector [0]
+ .word 0 # limit 15:0
+ .word 0 # base 15:0
+ .byte 0 # base 23:16
+ .byte 0 # type
+ .byte 0 # limit 19:16, flags
+ .byte 0 # base 31:24
+
+# linear data segment descriptor
+.equ LINEAR_SEL, .-_GDT_BASE # Selector [0x8]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# linear code segment descriptor
+.equ LINEAR_CODE_SEL, .-_GDT_BASE # Selector [0x10]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9F # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system data segment descriptor
+.equ SYS_DATA_SEL, .-_GDT_BASE # Selector [0x18]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x93 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system code segment descriptor
+.equ SYS_CODE_SEL, .-_GDT_BASE # Selector [0x20]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+.equ SPARE3_SEL, .-_GDT_BASE # Selector [0x28]
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+#
+# system data segment descriptor
+#
+.equ SYS_DATA64_SEL, .-_GDT_BASE # Selector [0x30]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A
+ .byte 0xCF # G | D | L | AVL | Segment [19..16]
+ .byte 0
+
+#
+# system code segment descriptor
+#
+.equ SYS_CODE64_SEL, .-_GDT_BASE # Selector [0x38]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A
+ .byte 0xAF # G | D | L | AVL | Segment [19..16]
+ .byte 0
+
+# spare segment descriptor
+.equ SPARE4_SEL, .-_GDT_BASE # Selector [0x40]
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+_GDT_END:
+
+
+