Fix boot script thunk issue that we need dispatch in PEI mode for Framework dispatch function, not in DXE mode.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11189 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
#
|
||||
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# AsmDispatchExecute.asm
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
|
||||
# transit back to long mode.
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Procedure: AsmExecute32BitCode
|
||||
#
|
||||
# Input: None
|
||||
#
|
||||
# Output: None
|
||||
#
|
||||
# Prototype: EFI_STATUS
|
||||
# AsmExecute32BitCode (
|
||||
# IN UINT64 Function,
|
||||
# IN UINT64 Param1,
|
||||
# IN UINT64 Param2,
|
||||
# IN IA32_DESCRIPTOR *InternalGdtr
|
||||
# );
|
||||
#
|
||||
#
|
||||
# Description: A thunk function to execute 32-bit code in long mode.
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmExecute32BitCode)
|
||||
ASM_PFX(AsmExecute32BitCode):
|
||||
#
|
||||
# save orignal GDTR and CS
|
||||
#
|
||||
movq %ds, %rax
|
||||
push %rax
|
||||
movq %cs, %rax
|
||||
push %rax
|
||||
subq $0x10, %rsp
|
||||
sgdt (%rsp)
|
||||
#
|
||||
# load internal GDT
|
||||
#
|
||||
lgdt (%r9)
|
||||
#
|
||||
# Save general purpose register and rflag register
|
||||
#
|
||||
pushfq
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %rbp
|
||||
push %rbx
|
||||
|
||||
#
|
||||
# save CR3
|
||||
#
|
||||
movq %cr3, %rax
|
||||
movq %rax, %rbp
|
||||
|
||||
#
|
||||
# Prepare the CS and return address for the transition from 32-bit to 64-bit mode
|
||||
#
|
||||
movq $0x10, %rax # load long mode selector
|
||||
shl $32, %rax
|
||||
lea ReloadCS(%rip), %r9 #Assume the ReloadCS is under 4G
|
||||
orq %r9, %rax
|
||||
push %rax
|
||||
#
|
||||
# Save parameters for 32-bit function call
|
||||
#
|
||||
movq %r8, %rax
|
||||
shl $32, %rax
|
||||
orq %rdx, %rax
|
||||
push %rax
|
||||
#
|
||||
# save the 32-bit function entry and the return address into stack which will be
|
||||
# retrieve in compatibility mode.
|
||||
#
|
||||
lea ReturnBack(%rip), %rax #Assume the ReloadCS is under 4G
|
||||
shl $32, %rax
|
||||
orq %rcx, %rax
|
||||
push %rax
|
||||
|
||||
#
|
||||
# let rax save DS
|
||||
#
|
||||
movq $0x18, %rax
|
||||
|
||||
#
|
||||
# Change to Compatible Segment
|
||||
#
|
||||
movq $8, %rcx # load compatible mode selector
|
||||
shl $32, %rcx
|
||||
lea Compatible(%rip), %rdx # assume address < 4G
|
||||
orq %rdx, %rcx
|
||||
push %rcx
|
||||
retf
|
||||
|
||||
Compatible:
|
||||
# reload DS/ES/SS to make sure they are correct referred to current GDT
|
||||
movs %ax, %ds
|
||||
movs %ax, %es
|
||||
movs %ax, %ss
|
||||
|
||||
#
|
||||
# Disable paging
|
||||
#
|
||||
movq %cr0, %rcx
|
||||
btc $31, %ecx
|
||||
movq %rcx, %cr0
|
||||
#
|
||||
# Clear EFER.LME
|
||||
#
|
||||
movl $0xC0000080, %ecx
|
||||
rdmsr
|
||||
btc $8, %eax
|
||||
wrmsr
|
||||
|
||||
# Now we are in protected mode
|
||||
#
|
||||
# Call 32-bit function. Assume the function entry address and parameter value is less than 4G
|
||||
#
|
||||
pop %rax # Here is the function entry
|
||||
#
|
||||
# Now the parameter is at the bottom of the stack, then call in to IA32 function.
|
||||
#
|
||||
jmp *%rax
|
||||
ReturnBack:
|
||||
pop %rcx # drop param1
|
||||
pop %rcx # drop param2
|
||||
|
||||
#
|
||||
# restore CR4
|
||||
#
|
||||
movq %cr4, %rax
|
||||
bts $5, %eax
|
||||
movq %rax, %cr4
|
||||
|
||||
#
|
||||
# restore CR3
|
||||
#
|
||||
movl %ebp, %eax
|
||||
movq %rax, %cr3
|
||||
|
||||
#
|
||||
# Set EFER.LME to re-enable ia32-e
|
||||
#
|
||||
movl $0xC0000080, %ecx
|
||||
rdmsr
|
||||
bts $8, %eax
|
||||
wrmsr
|
||||
#
|
||||
# Enable paging
|
||||
#
|
||||
movq %cr0, %rax
|
||||
bts $31, %eax
|
||||
mov %rax, %cr0
|
||||
# Now we are in compatible mode
|
||||
|
||||
#
|
||||
# Reload cs register
|
||||
#
|
||||
retf
|
||||
ReloadCS:
|
||||
#
|
||||
# Now we're in Long Mode
|
||||
#
|
||||
#
|
||||
# Restore C register and eax hold the return status from 32-bit function.
|
||||
# Note: Do not touch rax from now which hold the return value from IA32 function
|
||||
#
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
popfq
|
||||
#
|
||||
# Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
|
||||
#
|
||||
lgdt (%rsp)
|
||||
#
|
||||
# drop GDT descriptor in stack
|
||||
#
|
||||
addq $0x10, %rsp
|
||||
#
|
||||
# switch to orignal CS and GDTR
|
||||
#
|
||||
pop %r9 # get CS
|
||||
shl $32, %r9 # rcx[32..47] <- Cs
|
||||
lea @F(%rip), %rcx
|
||||
orq %r9, %rcx
|
||||
push %rcx
|
||||
retf
|
||||
@@:
|
||||
#
|
||||
# Reload original DS/ES/SS
|
||||
#
|
||||
pop %rcx
|
||||
movq %rcx, %ds
|
||||
movq %rcx, %es
|
||||
movq %rcx, %ss
|
||||
ret
|
||||
|
@@ -0,0 +1,216 @@
|
||||
;
|
||||
; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
; 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.
|
||||
;
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; AsmDispatchExecute.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
|
||||
; transit back to long mode.
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
.code
|
||||
;----------------------------------------------------------------------------
|
||||
; Procedure: AsmExecute32BitCode
|
||||
;
|
||||
; Input: None
|
||||
;
|
||||
; Output: None
|
||||
;
|
||||
; Prototype: EFI_STATUS
|
||||
; AsmExecute32BitCode (
|
||||
; IN UINT64 Function,
|
||||
; IN UINT64 Param1,
|
||||
; IN UINT64 Param2,
|
||||
; IN IA32_DESCRIPTOR *InternalGdtr
|
||||
; );
|
||||
;
|
||||
;
|
||||
; Description: A thunk function to execute 32-bit code in long mode.
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
AsmExecute32BitCode PROC
|
||||
;
|
||||
; save orignal GDTR and CS
|
||||
;
|
||||
mov rax, ds
|
||||
push rax
|
||||
mov rax, cs
|
||||
push rax
|
||||
sub rsp, 10h
|
||||
sgdt fword ptr [rsp]
|
||||
;
|
||||
; load internal GDT
|
||||
;
|
||||
lgdt fword ptr [r9]
|
||||
;
|
||||
; Save general purpose register and rflag register
|
||||
;
|
||||
pushfq
|
||||
push rdi
|
||||
push rsi
|
||||
push rbp
|
||||
push rbx
|
||||
|
||||
;
|
||||
; save CR3
|
||||
;
|
||||
mov rax, cr3
|
||||
mov rbp, rax
|
||||
|
||||
;
|
||||
; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
|
||||
;
|
||||
mov rax, 10h ; load long mode selector
|
||||
shl rax, 32
|
||||
mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G
|
||||
or rax, r9
|
||||
push rax
|
||||
;
|
||||
; Save parameters for 32-bit function call
|
||||
;
|
||||
mov rax, r8
|
||||
shl rax, 32
|
||||
or rax, rdx
|
||||
push rax
|
||||
;
|
||||
; save the 32-bit function entry and the return address into stack which will be
|
||||
; retrieve in compatibility mode.
|
||||
;
|
||||
mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G
|
||||
shl rax, 32
|
||||
or rax, rcx
|
||||
push rax
|
||||
|
||||
;
|
||||
; let rax save DS
|
||||
;
|
||||
mov rax, 018h
|
||||
|
||||
;
|
||||
; Change to Compatible Segment
|
||||
;
|
||||
mov rcx, 08h ; load compatible mode selector
|
||||
shl rcx, 32
|
||||
mov rdx, OFFSET Compatible ; assume address < 4G
|
||||
or rcx, rdx
|
||||
push rcx
|
||||
retf
|
||||
|
||||
Compatible:
|
||||
; reload DS/ES/SS to make sure they are correct referred to current GDT
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
|
||||
;
|
||||
; Disable paging
|
||||
;
|
||||
mov rcx, cr0
|
||||
btc ecx, 31
|
||||
mov cr0, rcx
|
||||
;
|
||||
; Clear EFER.LME
|
||||
;
|
||||
mov ecx, 0C0000080h
|
||||
rdmsr
|
||||
btc eax, 8
|
||||
wrmsr
|
||||
|
||||
; Now we are in protected mode
|
||||
;
|
||||
; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
|
||||
;
|
||||
pop rax ; Here is the function entry
|
||||
;
|
||||
; Now the parameter is at the bottom of the stack, then call in to IA32 function.
|
||||
;
|
||||
jmp rax
|
||||
ReturnBack:
|
||||
pop rcx ; drop param1
|
||||
pop rcx ; drop param2
|
||||
|
||||
;
|
||||
; restore CR4
|
||||
;
|
||||
mov rax, cr4
|
||||
bts eax, 5
|
||||
mov cr4, rax
|
||||
|
||||
;
|
||||
; restore CR3
|
||||
;
|
||||
mov eax, ebp
|
||||
mov cr3, rax
|
||||
|
||||
;
|
||||
; Set EFER.LME to re-enable ia32-e
|
||||
;
|
||||
mov ecx, 0C0000080h
|
||||
rdmsr
|
||||
bts eax, 8
|
||||
wrmsr
|
||||
;
|
||||
; Enable paging
|
||||
;
|
||||
mov rax, cr0
|
||||
bts eax, 31
|
||||
mov cr0, rax
|
||||
; Now we are in compatible mode
|
||||
|
||||
;
|
||||
; Reload cs register
|
||||
;
|
||||
retf
|
||||
ReloadCS:
|
||||
;
|
||||
; Now we're in Long Mode
|
||||
;
|
||||
;
|
||||
; Restore C register and eax hold the return status from 32-bit function.
|
||||
; Note: Do not touch rax from now which hold the return value from IA32 function
|
||||
;
|
||||
pop rbx
|
||||
pop rbp
|
||||
pop rsi
|
||||
pop rdi
|
||||
popfq
|
||||
;
|
||||
; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
|
||||
;
|
||||
lgdt fword ptr[rsp]
|
||||
;
|
||||
; drop GDT descriptor in stack
|
||||
;
|
||||
add rsp, 10h
|
||||
;
|
||||
; switch to orignal CS and GDTR
|
||||
;
|
||||
pop r9 ; get CS
|
||||
shl r9, 32 ; rcx[32..47] <- Cs
|
||||
mov rcx, OFFSET @F
|
||||
or rcx, r9
|
||||
push rcx
|
||||
retf
|
||||
@@:
|
||||
;
|
||||
; Reload original DS/ES/SS
|
||||
;
|
||||
pop rcx
|
||||
mov ds, rcx
|
||||
mov es, rcx
|
||||
mov ss, rcx
|
||||
ret
|
||||
AsmExecute32BitCode ENDP
|
||||
|
||||
END
|
@@ -0,0 +1,106 @@
|
||||
/** @file
|
||||
Execute 32-bit code in Long Mode
|
||||
Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit
|
||||
back to long mode.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
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.
|
||||
|
||||
**/
|
||||
#include "ScriptSave.h"
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 LimitLow : 16;
|
||||
UINT32 BaseLow : 16;
|
||||
UINT32 BaseMid : 8;
|
||||
UINT32 Type : 4;
|
||||
UINT32 System : 1;
|
||||
UINT32 Dpl : 2;
|
||||
UINT32 Present : 1;
|
||||
UINT32 LimitHigh : 4;
|
||||
UINT32 Software : 1;
|
||||
UINT32 Reserved : 1;
|
||||
UINT32 DefaultSize : 1;
|
||||
UINT32 Granularity : 1;
|
||||
UINT32 BaseHigh : 8;
|
||||
} Bits;
|
||||
UINT64 Uint64;
|
||||
} IA32_GDT;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Global Descriptor Table (GDT)
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
|
||||
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */
|
||||
{{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */
|
||||
{{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */
|
||||
{{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */
|
||||
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */
|
||||
};
|
||||
|
||||
//
|
||||
// IA32 Gdt register
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
|
||||
sizeof (mGdtEntries) - 1,
|
||||
(UINTN) mGdtEntries
|
||||
};
|
||||
/**
|
||||
Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
|
||||
long mode.
|
||||
@param Function The 32bit code entry to be executed.
|
||||
@param Param1 The first parameter to pass to 32bit code
|
||||
@param Param2 The second parameter to pass to 32bit code
|
||||
@param InternalGdtr The GDT and GDT descriptor used by this library
|
||||
|
||||
@retval EFI_SUCCESS Execute 32bit code successfully.
|
||||
@retval other Something wrong when execute the 32bit code
|
||||
**/
|
||||
EFI_STATUS
|
||||
AsmExecute32BitCode (
|
||||
IN UINT64 Function,
|
||||
IN UINT64 Param1,
|
||||
IN UINT64 Param2,
|
||||
IN IA32_DESCRIPTOR *InternalGdtr
|
||||
);
|
||||
|
||||
/**
|
||||
Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
|
||||
long mode.
|
||||
|
||||
@param Function The 32bit code entry to be executed.
|
||||
@param Param1 The first parameter to pass to 32bit code
|
||||
@param Param2 The second parameter to pass to 32bit code
|
||||
@retval EFI_SUCCESS Execute 32bit code successfully.
|
||||
@retval other Something wrong when execute the 32bit code
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Execute32BitCode (
|
||||
IN UINT64 Function,
|
||||
IN UINT64 Param1,
|
||||
IN UINT64 Param2
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (Function != 0);
|
||||
|
||||
Status = AsmExecute32BitCode (
|
||||
Function,
|
||||
Param1,
|
||||
Param2,
|
||||
&mGdt
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
Reference in New Issue
Block a user