123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647 |
- ;; @file
- ; Provide FSP API entry points.
- ;
- ; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
- ; SPDX-License-Identifier: BSD-2-Clause-Patent
- ;;
- SECTION .text
- %include "SaveRestoreSseNasm.inc"
- %include "MicrocodeLoadNasm.inc"
- ;
- ; Following are fixed PCDs
- ;
- extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
- extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
- extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
- ;
- ; Following functions will be provided in PlatformSecLib
- ;
- extern ASM_PFX(AsmGetFspBaseAddress)
- extern ASM_PFX(AsmGetFspInfoHeaderNoStack)
- ;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
- extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
- extern ASM_PFX(SecCarInit)
- ;
- ; Define the data length that we saved on the stack top
- ;
- DATA_LEN_OF_PER0 EQU 18h
- DATA_LEN_OF_MCUD EQU 18h
- DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
- ;
- ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
- ; build error. This needs to be fixed later on.
- ;
- struc MicrocodeHdr
- .MicrocodeHdrVersion: resd 1
- .MicrocodeHdrRevision: resd 1
- .MicrocodeHdrDate: resd 1
- .MicrocodeHdrProcessor: resd 1
- .MicrocodeHdrChecksum: resd 1
- .MicrocodeHdrLoader: resd 1
- .MicrocodeHdrFlags: resd 1
- .MicrocodeHdrDataSize: resd 1
- .MicrocodeHdrTotalSize: resd 1
- .MicrocodeHdrRsvd: resd 3
- .size:
- endstruc
- struc ExtSigHdr
- .ExtSigHdrCount: resd 1
- .ExtSigHdrChecksum: resd 1
- .ExtSigHdrRsvd: resd 3
- .size:
- endstruc
- struc ExtSig
- .ExtSigProcessor: resd 1
- .ExtSigFlags: resd 1
- .ExtSigChecksum: resd 1
- .size:
- endstruc
- struc LoadMicrocodeParams
- ; FSP_UPD_HEADER {
- .FspUpdHeader: resd 8
- ; }
- ; FSPT_CORE_UPD {
- .MicrocodeCodeAddr: resd 1
- .MicrocodeCodeSize: resd 1
- .CodeRegionBase: resd 1
- .CodeRegionSize: resd 1
- ; }
- .size:
- endstruc
- struc LoadMicrocodeParamsFsp22
- ; FSP_UPD_HEADER {
- .FspUpdHeaderSignature: resd 2
- .FspUpdHeaderRevision: resb 1
- .FspUpdHeaderReserved: resb 23
- ; }
- ; FSPT_ARCH_UPD {
- .FsptArchRevision: resb 1
- .FsptArchReserved: resb 3
- .FsptArchUpd: resd 7
- ; }
- ; FSPT_CORE_UPD {
- .MicrocodeCodeAddr: resd 1
- .MicrocodeCodeSize: resd 1
- .CodeRegionBase: resd 1
- .CodeRegionSize: resd 1
- ; }
- .size:
- endstruc
- struc LoadMicrocodeParamsFsp24
- ; FSP_UPD_HEADER {
- .FspUpdHeaderSignature: resd 2
- .FspUpdHeaderRevision: resb 1
- .FspUpdHeaderReserved: resb 23
- ; }
- ; FSPT_ARCH2_UPD {
- .FsptArchRevision: resb 1
- .FsptArchReserved: resb 3
- .FsptArchLength: resd 1
- .FspDebugHandler resq 1
- .FsptArchUpd: resd 4
- ; }
- ; FSPT_CORE_UPD {
- .MicrocodeCodeAddr: resq 1
- .MicrocodeCodeSize: resq 1
- .CodeRegionBase: resq 1
- .CodeRegionSize: resq 1
- ; }
- .size:
- endstruc
- ;
- ; Define SSE macros
- ;
- ;
- ;args 1: ReturnAddress 2:MmxRegister
- ;
- %macro LOAD_MMX_EXT 2
- mov esi, %1
- movd %2, esi ; save ReturnAddress into MMX
- %endmacro
- ;
- ;args 1: RoutineLabel 2:MmxRegister
- ;
- %macro CALL_MMX_EXT 2
- mov esi, %%ReturnAddress
- movd %2, esi ; save ReturnAddress into MMX
- jmp %1
- %%ReturnAddress:
- %endmacro
- ;
- ;arg 1:MmxRegister
- ;
- %macro RET_ESI_EXT 1
- movd esi, %1 ; move ReturnAddress from MMX to ESI
- jmp esi
- %endmacro
- ;
- ;arg 1:RoutineLabel
- ;
- %macro CALL_MMX 1
- CALL_MMX_EXT %1, mm7
- %endmacro
- %macro RET_ESI 0
- RET_ESI_EXT mm7
- %endmacro
- %macro CALL_EDI 1
- mov edi, %%ReturnAddress
- jmp %1
- %%ReturnAddress:
- %endmacro
- %macro CALL_EBP 1
- mov ebp, %%ReturnAddress
- jmp %1
- %%ReturnAddress:
- %endmacro
- %macro RET_EBP 0
- jmp ebp ; restore EIP from EBP
- %endmacro
- ;
- ; Load UPD region pointer in ECX
- ;
- global ASM_PFX(LoadUpdPointerToECX)
- ASM_PFX(LoadUpdPointerToECX):
- ;
- ; esp + 4 is input UPD parameter
- ; If esp + 4 is NULL the default UPD should be used
- ; ecx will be the UPD region that should be used
- ;
- mov ecx, dword [esp + 4]
- cmp ecx, 0
- jnz ParamValid
- ;
- ; Fall back to default UPD region
- ;
- CALL_EDI ASM_PFX(AsmGetFspInfoHeaderNoStack)
- mov ecx, DWORD [eax + 01Ch] ; Read FsptImageBaseAddress
- add ecx, DWORD [eax + 024h] ; Get Cfg Region base address = FsptImageBaseAddress + CfgRegionOffset
- ParamValid:
- RET_EBP
- ;
- ; @todo: The strong/weak implementation does not work.
- ; This needs to be reviewed later.
- ;
- ;------------------------------------------------------------------------------
- ;
- ;;global ASM_PFX(SecPlatformInitDefault)
- ;ASM_PFX(SecPlatformInitDefault):
- ; ; Inputs:
- ; ; mm7 -> Return address
- ; ; Outputs:
- ; ; eax -> 0 - Successful, Non-zero - Failed.
- ; ; Register Usage:
- ; ; eax is cleared and ebp is used for return address.
- ; ; All others reserved.
- ;
- ; ; Save return address to EBP
- ; movd ebp, mm7
- ;
- ; xor eax, eax
- ;Exit1:
- ; jmp ebp
- ;------------------------------------------------------------------------------
- global ASM_PFX(LoadMicrocodeDefault)
- ASM_PFX(LoadMicrocodeDefault):
- ; Inputs:
- ; ecx -> UPD region contains LoadMicrocodeParams pointer
- ; Register Usage:
- ; All are destroyed
- ; Assumptions:
- ; No memory available, stack is hard-coded and used for return address
- ; Executed by SBSP and NBSP
- ; Beginning of microcode update region starts on paragraph boundary
- ;
- ; Save return address to EBP
- ;
- movd ebp, mm7
- mov esp, ecx ; ECX has been assigned to UPD region
- cmp esp, 0
- jz ParamError
- ; skip loading Microcode if the MicrocodeCodeSize is zero
- ; and report error if size is less than 2k
- ; first check UPD header revision
- cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
- jb Fsp20UpdHeader
- cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
- je Fsp24UpdHeader
- jmp Fsp22UpdHeader
- Fsp20UpdHeader:
- ; UPD structure is compliant with FSP spec 2.0/2.1
- mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
- cmp eax, 0
- jz Exit2
- cmp eax, 0800h
- jl ParamError
- mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
- cmp esi, 0
- jnz CheckMainHeader
- jmp ParamError
- Fsp22UpdHeader:
- ; UPD structure is compliant with FSP spec 2.2
- mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
- cmp eax, 0
- jz Exit2
- cmp eax, 0800h
- jl ParamError
- mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
- cmp esi, 0
- jnz CheckMainHeader
- jmp ParamError
- Fsp24UpdHeader:
- ; UPD structure is compliant with FSP spec 2.4
- mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
- cmp eax, 0
- jz Exit2
- cmp eax, 0800h
- jl ParamError
- mov esi, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
- cmp esi, 0
- jnz CheckMainHeader
- ParamError:
- mov eax, 080000002h
- jmp Exit2
- CheckMainHeader:
- ; Get processor signature and platform ID from the installed processor
- ; and save into registers for later use
- ; ebx = processor signature
- ; edx = platform ID
- mov eax, 1
- cpuid
- mov ebx, eax
- mov ecx, MSR_IA32_PLATFORM_ID
- rdmsr
- mov ecx, edx
- shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
- and ecx, 7h ; platform id at bit[52..50]
- mov edx, 1
- shl edx, cl
- ; Current register usage
- ; esp -> stack with parameters
- ; esi -> microcode update to check
- ; ebx = processor signature
- ; edx = platform ID
- ; Check for valid microcode header
- ; Minimal test checking for header version and loader version as 1
- mov eax, dword 1
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
- jne AdvanceFixedSize
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
- jne AdvanceFixedSize
- ; Check if signature and plaform ID match
- cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
- jne LoadMicrocodeDefault1
- test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
- jnz LoadCheck ; Jif signature and platform ID match
- LoadMicrocodeDefault1:
- ; Check if extended header exists
- ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
- xor eax, eax
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
- je NextMicrocode
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
- je NextMicrocode
- ; Then verify total size - sizeof header > data size
- mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
- sub ecx, MicrocodeHdr.size
- cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
- jng NextMicrocode ; Jif extended header does not exist
- ; Set edi -> extended header
- mov edi, esi
- add edi, MicrocodeHdr.size
- add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
- ; Get count of extended structures
- mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
- ; Move pointer to first signature structure
- add edi, ExtSigHdr.size
- CheckExtSig:
- ; Check if extended signature and platform ID match
- cmp dword [edi + ExtSig.ExtSigProcessor], ebx
- jne LoadMicrocodeDefault2
- test dword [edi + ExtSig.ExtSigFlags], edx
- jnz LoadCheck ; Jif signature and platform ID match
- LoadMicrocodeDefault2:
- ; Check if any more extended signatures exist
- add edi, ExtSig.size
- loop CheckExtSig
- NextMicrocode:
- ; Advance just after end of this microcode
- xor eax, eax
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
- je LoadMicrocodeDefault3
- add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
- jmp CheckAddress
- LoadMicrocodeDefault3:
- add esi, dword 2048
- jmp CheckAddress
- AdvanceFixedSize:
- ; Advance by 4X dwords
- add esi, dword 1024
- CheckAddress:
- ; Check UPD header revision
- cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
- jb Fsp20UpdHeader1
- cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
- je Fsp24UpdHeader1;
- jmp Fsp22UpdHeader1
- Fsp20UpdHeader1:
- ; UPD structure is compliant with FSP spec 2.0/2.1
- ; Is automatic size detection ?
- mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
- cmp eax, 0ffffffffh
- jz LoadMicrocodeDefault4
- ; Address >= microcode region address + microcode region size?
- add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
- cmp esi, eax
- jae Done ;Jif address is outside of microcode region
- jmp CheckMainHeader
- Fsp22UpdHeader1:
- ; UPD structure is compliant with FSP spec 2.2
- ; Is automatic size detection ?
- mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
- cmp eax, 0ffffffffh
- jz LoadMicrocodeDefault4
- ; Address >= microcode region address + microcode region size?
- add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
- cmp esi, eax
- jae Done ;Jif address is outside of microcode region
- jmp CheckMainHeader
- Fsp24UpdHeader1:
- ; UPD structure is compliant with FSP spec 2.4
- ; Is automatic size detection ?
- mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
- cmp eax, 0ffffffffh
- jz LoadMicrocodeDefault4
- ; Address >= microcode region address + microcode region size?
- add eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
- cmp esi, eax
- jae Done ;Jif address is outside of microcode region
- jmp CheckMainHeader
- LoadMicrocodeDefault4:
- ; Is valid Microcode start point ?
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
- jz Done
- LoadCheck:
- ; Get the revision of the current microcode update loaded
- mov ecx, MSR_IA32_BIOS_SIGN_ID
- xor eax, eax ; Clear EAX
- xor edx, edx ; Clear EDX
- wrmsr ; Load 0 to MSR at 8Bh
- mov eax, 1
- cpuid
- mov ecx, MSR_IA32_BIOS_SIGN_ID
- rdmsr ; Get current microcode signature
- ; Verify this microcode update is not already loaded
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
- je Continue
- LoadMicrocode:
- ; EAX contains the linear address of the start of the Update Data
- ; EDX contains zero
- ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
- ; Start microcode load with wrmsr
- mov eax, esi
- add eax, MicrocodeHdr.size
- xor edx, edx
- mov ecx, MSR_IA32_BIOS_UPDT_TRIG
- wrmsr
- mov eax, 1
- cpuid
- Continue:
- jmp NextMicrocode
- Done:
- mov eax, 1
- cpuid
- mov ecx, MSR_IA32_BIOS_SIGN_ID
- rdmsr ; Get current microcode signature
- xor eax, eax
- cmp edx, 0
- jnz Exit2
- mov eax, 08000000Eh
- Exit2:
- jmp ebp
- ;
- ; EstablishStackFsp: EDI should be preserved cross this function
- ;
- global ASM_PFX(EstablishStackFsp)
- ASM_PFX(EstablishStackFsp):
- ;
- ; Save parameter pointer in edx
- ;
- mov edx, ecx ; ECX has been assigned to UPD region
- ;
- ; Enable FSP STACK
- ;
- mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
- add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
- push DATA_LEN_OF_MCUD ; Size of the data region
- push 4455434Dh ; Signature of the data region 'MCUD'
- ; check UPD structure revision (edx + 8)
- cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
- jb Fsp20UpdHeader2
- cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
- je Fsp24UpdHeader2
- jmp Fsp22UpdHeader2
- Fsp20UpdHeader2:
- ; UPD structure is compliant with FSP spec 2.0/2.1
- push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
- push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
- push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
- push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
- jmp ContinueAfterUpdPush
- Fsp22UpdHeader2:
- ; UPD structure is compliant with FSP spec 2.2
- push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
- push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
- push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
- push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
- jmp ContinueAfterUpdPush
- Fsp24UpdHeader2:
- ; UPD structure is compliant with FSP spec 2.4
- push dword [edx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 24
- push dword [edx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 16
- push dword [edx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8
- push dword [edx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
- ContinueAfterUpdPush:
- ;
- ; Save API entry/exit timestamp into stack
- ;
- push DATA_LEN_OF_PER0 ; Size of the data region
- push 30524550h ; Signature of the data region 'PER0'
- rdtsc
- push edx
- push eax
- LOAD_EDX
- push edx
- LOAD_EAX
- push eax
- ;
- ; Terminator for the data on stack
- ;
- push 0
- ;
- ; Set ECX/EDX to the BootLoader temporary memory range
- ;
- mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
- mov edx, ecx
- add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
- sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
- cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
- jb EstablishStackFspSuccess
- mov eax, 80000003h ;EFI_UNSUPPORTED
- jmp EstablishStackFspExit
- EstablishStackFspSuccess:
- xor eax, eax
- EstablishStackFspExit:
- RET_ESI
- ;----------------------------------------------------------------------------
- ; TempRamInit API
- ;
- ; This FSP API will load the microcode update, enable code caching for the
- ; region specified by the boot loader and also setup a temporary stack to be
- ; used till main memory is initialized.
- ;
- ;----------------------------------------------------------------------------
- global ASM_PFX(TempRamInitApi)
- ASM_PFX(TempRamInitApi):
- ;
- ; Ensure SSE is enabled
- ;
- ENABLE_SSE
- ;
- ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
- ;
- SAVE_REGS
- ;
- ; Save timestamp into XMM6
- ;
- rdtsc
- SAVE_EAX
- SAVE_EDX
- CALL_EBP ASM_PFX(LoadUpdPointerToECX) ; ECX for UPD param
- SAVE_ECX ; save UPD param to slot 3 in xmm6
- ;
- ; Sec Platform Init
- ;
- CALL_MMX ASM_PFX(SecPlatformInit)
- cmp eax, 0
- jnz TempRamInitExit
- ; Load microcode
- LOAD_ESP
- LOAD_ECX
- CALL_MMX ASM_PFX(LoadMicrocodeDefault)
- SAVE_UCODE_STATUS ; Save microcode return status in slot 1 in xmm5.
- ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
- ; Call Sec CAR Init
- LOAD_ESP
- LOAD_ECX
- CALL_MMX ASM_PFX(SecCarInit)
- cmp eax, 0
- jnz TempRamInitExit
- LOAD_ESP
- LOAD_ECX
- mov edi, ecx ; Save UPD param to EDI for later code use
- CALL_MMX ASM_PFX(EstablishStackFsp)
- cmp eax, 0
- jnz TempRamInitExit
- LOAD_UCODE_STATUS ; Restore microcode status if no CAR init error from slot 1 in xmm5.
- TempRamInitExit:
- mov bl, al ; save al data in bl
- mov al, 07Fh ; API exit postcode 7f
- out 080h, al
- mov al, bl ; restore al data from bl
- ;
- ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
- ;
- LOAD_REGS
- ret
- ;----------------------------------------------------------------------------
- ; Module Entrypoint API
- ;----------------------------------------------------------------------------
- global ASM_PFX(_ModuleEntryPoint)
- ASM_PFX(_ModuleEntryPoint):
- jmp $
|