@@ -54,6 +54,9 @@ jumpTo32BitAndLandHere:
mov gs, ax
mov ss, ax
+ ; parameter for Flat32SearchForBfvBase
+ xor eax, eax ; Start searching from top of 4GB for BfvBase
+
OneTimeCallRet TransitionFromReal16To32BitFlat
ALIGN 2
new file mode 100644
@@ -0,0 +1,68 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 32 bit flat protected mode into 64 bit flat protected mode
+;
+; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019, Citrix Systems, Inc.
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+;
+; Modified: EAX, EBX, ECX, EDX, ESP
+;
+Transition32FlatTo64Flat:
+
+ OneTimeCall SetCr3ForPageTables64
+
+ mov eax, cr4
+ bts eax, 5 ; enable PAE
+ mov cr4, eax
+
+ mov ecx, 0xc0000080
+ rdmsr
+ bts eax, 8 ; set LME
+ wrmsr
+
+ mov eax, cr0
+ bts eax, 31 ; set PG
+ mov cr0, eax ; enable paging
+
+ ;
+ ; backup ESP
+ ;
+ mov ebx, esp
+
+ ;
+ ; recalculate delta
+ ;
+ mov esp, PVH_SPACE(16)
+ call .delta
+.delta:
+ pop edx
+ sub edx, ADDR_OF(.delta)
+
+ ;
+ ; push return addr and seg to the stack, then return far
+ ;
+ push dword LINEAR_CODE64_SEL
+ mov eax, ADDR_OF(jumpTo64BitAndLandHere)
+ add eax, edx ; add delta
+ push eax
+ retf
+
+BITS 64
+jumpTo64BitAndLandHere:
+
+ ;
+ ; restore ESP
+ ;
+ mov esp, ebx
+
+ debugShowPostCode POSTCODE_64BIT_MODE
+
+ OneTimeCallRet Transition32FlatTo64Flat
+
new file mode 100644
@@ -0,0 +1,87 @@
+;------------------------------------------------------------------------------
+; @file
+; Search for the Boot Firmware Volume (BFV) base address
+;
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019, Citrix Systems, Inc.
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \
+; { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } }
+%define FFS_GUID_DWORD0 0x8c8ce578
+%define FFS_GUID_DWORD1 0x4f1c8a3d
+%define FFS_GUID_DWORD2 0x61893599
+%define FFS_GUID_DWORD3 0xd32dc385
+
+BITS 32
+
+;
+; Modified: EAX, EBX, ECX
+; Preserved: EDI, ESP
+;
+; @param[in] EAX Start search from here
+; @param[out] EBP Address of Boot Firmware Volume (BFV)
+;
+Flat32SearchForBfvBase:
+
+ mov ecx, eax
+searchingForBfvHeaderLoop:
+ ;
+ ; We check for a firmware volume at every 4KB address in the 16MB
+ ; just below where we started, ECX.
+ ;
+ sub eax, 0x1000
+ mov ebx, ecx
+ sub ebx, eax
+ cmp ebx, 0x01000000
+ ; if ECX-EAX > 16MB; jump notfound
+ ja searchedForBfvHeaderButNotFound
+
+ ;
+ ; Check FFS GUID
+ ;
+ cmp dword [eax + 0x10], FFS_GUID_DWORD0
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x14], FFS_GUID_DWORD1
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x18], FFS_GUID_DWORD2
+ jne searchingForBfvHeaderLoop
+ cmp dword [eax + 0x1c], FFS_GUID_DWORD3
+ jne searchingForBfvHeaderLoop
+
+ ;
+ ; Check FV Length
+ ;
+ cmp dword [eax + 0x24], 0
+ jne searchingForBfvHeaderLoop
+ mov ebx, eax
+ add ebx, dword [eax + 0x20]
+ cmp ebx, ecx
+ jnz searchingForBfvHeaderLoop
+
+ jmp searchedForBfvHeaderAndItWasFound
+
+searchedForBfvHeaderButNotFound:
+ ;
+ ; Hang if the SEC entry point was not found
+ ;
+ debugShowPostCode POSTCODE_BFV_NOT_FOUND
+
+ ;
+ ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed
+ ; for debugging purposes.
+ ;
+ mov eax, 0xBFBFBFBF
+ mov ebp, eax
+ jmp $
+
+searchedForBfvHeaderAndItWasFound:
+ mov ebp, eax
+
+ debugShowPostCode POSTCODE_BFV_FOUND
+
+ OneTimeCallRet Flat32SearchForBfvBase
+
@@ -16,25 +16,42 @@ xenPVHMain:
;
mov di, 'BP'
- ;
- ; ESP will be used as initial value of the EAX register
- ; in Main.asm
- ;
- xor esp, esp
-
;
; Store "Start of day" struct pointer for later use
;
mov dword[PVH_SPACE (0)], ebx
mov dword[PVH_SPACE (4)], 'XPVH'
+ ;
+ ; calculate delta between build-addr and run position
+ ;
+ mov esp, PVH_SPACE(16) ; create a temporary stack
+ call .delta
+.delta:
+ pop edx ; get addr of .delta
+ sub edx, ADDR_OF(.delta) ; calculate delta
+
+ ;
+ ; Find address of GDT and gdtr and fix the later
+ ;
mov ebx, ADDR_OF(gdtr)
+ add ebx, edx ; add delta gdtr
+ mov eax, ADDR_OF(GDT_BASE)
+ add eax, edx ; add delta to GDT_BASE
+ mov dword[ebx + 2], eax ; fix GDT_BASE addr in gdtr
lgdt [ebx]
mov eax, SEC_DEFAULT_CR0
mov cr0, eax
- jmp LINEAR_CODE_SEL:ADDR_OF(.jmpToNewCodeSeg)
+ ;
+ ; push return addr to the stack, then return far
+ ;
+ push dword LINEAR_CODE_SEL ; segment to select
+ mov eax, ADDR_OF(.jmpToNewCodeSeg) ; return addr
+ add eax, edx ; add delta to return addr
+ push eax
+ retf
.jmpToNewCodeSeg:
mov eax, SEC_DEFAULT_CR4
@@ -47,6 +64,18 @@ xenPVHMain:
mov gs, ax
mov ss, ax
+ ;
+ ; ESP will be used as initial value of the EAX register
+ ; in Main.asm
+ ;
+ xor esp, esp
+
+ ;
+ ; parameter for Flat32SearchForBfvBase
+ ;
+ mov eax, ADDR_OF(fourGigabytes)
+ add eax, edx ; add delta
+
;
; Jump to the main routine of the pre-SEC code
; skiping the 16-bit part of the routine and