diff options
Diffstat (limited to 'ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64')
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc | 494 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm | 364 | ||||
-rw-r--r-- | ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm | 712 |
3 files changed, 1570 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc new file mode 100644 index 0000000..027e32e --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc @@ -0,0 +1,494 @@ +;@file +; This file contains macros supporting 64 bit assembly +; +;@copyright +; Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; This file contains an 'Intel Peripheral Driver' and uniquely +; identified as "Intel Reference Module" and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +; + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: _movq +; +; Input: rxx - general perpose 64 bit register +; mmx - MMX register +; +; Output: None +; +; Registers: +; +; Description: Performs "movq rxx, mmx" and "movq mmx, rxx" operations +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +_movq MACRO toReg:REQ, frReg:REQ + LOCAL gReg, mReg, op + db 48h ; ; REX.W prefix +IFIDNI <toReg>, <rax> + gReg = 00h + op = 7Eh +ELSEIFIDNI <toReg>, <rcx> + gReg = 01h + op = 7Eh +ELSEIFIDNI <toReg>, <rdx> + gReg = 02h + op = 7Eh +ELSEIFIDNI <toReg>, <rbx> + gReg = 03h + op = 7Eh +ELSEIFIDNI <toReg>, <rsp> + gReg = 04h + op = 7Eh +ELSEIFIDNI <toReg>, <rbp> + gReg = 05h + op = 7Eh +ELSEIFIDNI <toReg>, <rsi> + gReg = 06h + op = 7Eh +ELSEIFIDNI <toReg>, <rdi> + gReg = 07h + op = 7Eh +ELSEIFIDNI <toReg>, <mm0> + mReg = 0C0h + 0 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm1> + mReg = 0C0h + 1 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm2> + mReg = 0C0h + 2 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm3> + mReg = 0C0h + 3 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm4> + mReg = 0C0h + 4 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm5> + mReg = 0C0h + 5 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm6> + mReg = 0C0h + 6 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm7> + mReg = 0C0h + 7 * 08h + op = 6Eh +ENDIF + +;; If op = 7E format movq rxx, mmx + +IFIDNI <frReg>, <rax> + gReg = 00h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rcx> + gReg = 01h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rdx> + gReg = 02h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rbx> + gReg = 03h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rsp> + gReg = 04h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rbp> + gReg = 05h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rsi> + gReg = 06h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <rdi> + gReg = 07h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm0> + mReg = 0C0h + 0 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm1> + mReg = 0C0h + 1 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm2> + mReg = 0C0h + 2 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm3> + mReg = 0C0h + 3 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm4> + mReg = 0C0h + 4 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm5> + mReg = 0C0h + 5 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm6> + mReg = 0C0h + 6 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm7> + mReg = 0C0h + 7 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ENDIF + db 0Fh, op, gReg + mReg +ENDM + + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: _movd +; +; Input: exx - general perpose 32 bit register +; mmx - MMX register +; +; Output: None +; +; Registers: +; +; Description: Performs "movd exx, mmx" and "movd mmx, exx" operations +; coded to perform in compatibility or protected mode but +; assembled by ml64 +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + + +_movd MACRO toReg:REQ, frReg:REQ + LOCAL gReg, mReg, op +IFIDNI <toReg>, <eax> + gReg = 00h + op = 7Eh +ELSEIFIDNI <toReg>, <ecx> + gReg = 01h + op = 7Eh +ELSEIFIDNI <toReg>, <edx> + gReg = 02h + op = 7Eh +ELSEIFIDNI <toReg>, <ebx> + gReg = 03h + op = 7Eh +ELSEIFIDNI <toReg>, <esp> + gReg = 04h + op = 7Eh +ELSEIFIDNI <toReg>, <ebp> + gReg = 05h + op = 7Eh +ELSEIFIDNI <toReg>, <esi> + gReg = 06h + op = 7Eh +ELSEIFIDNI <toReg>, <edi> + gReg = 07h + op = 7Eh +ELSEIFIDNI <toReg>, <mm0> + mReg = 0C0h + 0 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm1> + mReg = 0C0h + 1 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm2> + mReg = 0C0h + 2 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm3> + mReg = 0C0h + 3 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm4> + mReg = 0C0h + 4 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm5> + mReg = 0C0h + 5 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm6> + mReg = 0C0h + 6 * 08h + op = 6Eh +ELSEIFIDNI <toReg>, <mm7> + mReg = 0C0h + 7 * 08h + op = 6Eh +ENDIF + +;; If op = 7E format movq exx, mmx + +IFIDNI <frReg>, <eax> + gReg = 00h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ecx> + gReg = 01h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <edx> + gReg = 02h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ebx> + gReg = 03h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <esp> + gReg = 04h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <ebp> + gReg = 05h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <esi> + gReg = 06h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <edi> + gReg = 07h + IF op EQ 7Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm0> + mReg = 0C0h + 0 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm1> + mReg = 0C0h + 1 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm2> + mReg = 0C0h + 2 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm3> + mReg = 0C0h + 3 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm4> + mReg = 0C0h + 4 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm5> + mReg = 0C0h + 5 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm6> + mReg = 0C0h + 6 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ELSEIFIDNI <frReg>, <mm7> + mReg = 0C0h + 7 * 08h + IF op EQ 6Eh + .ERR + ENDIF +ENDIF + db 0Fh, op, gReg + mReg +ENDM + +;----------------------------------------------------------------------------- +; 64 bit macros +; + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: PUSHA_64 +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Saves all registers on stack +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +PUSHA_64 MACRO + push rsp + push rbp + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: POPA_64 +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Restores all registers from stack +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +POPA_64 MACRO + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + pop rbp + pop rsp +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: START_FRAME +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Starts frame declaration. Creates variable to hold total +; size of all local vars. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +START_FRAME MACRO + SZ = 0 +ENDM + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: MAKE_LOCAL +; +; Input: ARG - var definition in form Label[Count]:QuolifiedType +; +; Output: None +; +; Registers: +; +; Description: Defines local procedure variable. Adds size of created variable +; to total size of locals. +; size of all local vars. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +MAKE_LOCAL MACRO ARG:REQ + LOCAL brk, rbrk, clm, lbl, cnt, qtp + brk INSTR <ARG>, <[> + rbrk INSTR <ARG>, <]> + clm INSTR <ARG>, <:> + IF brk GT 0 + lbl SUBSTR <ARG>, 1, brk-1 + cnt SUBSTR <ARG>, brk+1, rbrk-brk-1 + qtp SUBSTR <ARG>, clm+1 + LOCAL lbl[cnt]:qtp + ELSE + lbl SUBSTR <ARG>, 1, clm-1 + qtp SUBSTR <ARG>, clm+1 + LOCAL lbl:qtp + ENDIF + + SZ = SZ + sizeof lbl +ENDM + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Macro: END_FRAME +; +; Input: None +; +; Output: None +; +; Registers: +; +; Description: Ends frame declaration. Creates stack sufficient to hold +; all declared variables. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +END_FRAME MACRO + SZ = SZ + 10h ; Margin + enter SZ, 0 ; With spare room on stack + .allocstack SZ + .endprolog +ENDM + + + +SAVED_GDT TEXTEQU <mm0> +SAVED_SS TEXTEQU <mm1> +SAVED_ESP TEXTEQU <mm2> +SAVED_EBP TEXTEQU <mm3> +
\ No newline at end of file diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm new file mode 100644 index 0000000..f1c44b9 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm @@ -0,0 +1,364 @@ +;/*++ +; This file contains an 'Intel Peripheral Driver' and uniquely +; identified as "Intel Reference Module" and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; +; Module Name: +; +; TxtDxeAp.asm +; +; Abstract: +; +; This file contains DXE AP initialization code. +; +;--*/ + + .xlist + include txt.inc + include mmx64.inc + .list + + + _TEXT SEGMENT + + +EXTERN mAcmBase:QWORD +EXTERN mMcuAddr:QWORD +EXTERN mApMtrrTab:QWORD +EXTERN mApIdt:QWORD +EXTERN mApCr4:QWORD +EXTERN mApSavedIa32ThermInterruptMSR:QWORD +EXTERN mApSavedApicThermalValue:DWORD + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: DoApInit +; +; Input: AcmBase - Base address of LT BIOS ACM +; McuAddr - Address of MCU patch in flash +; +; Output: None +; +; Registers: All are preserved +; +; Description: Initiatialize AP before GETSEC as per TXT BWG +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +DoApInit PROC FRAME + + START_FRAME + MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD + MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD + MAKE_LOCAL NEXT_MTRR_INDEX:QWORD + MAKE_LOCAL NEXT_MTRR_SIZE:QWORD + ; jmp $ + END_FRAME + + pushf + cli + PUSHA_64 + ; + ; Check uCode was loaded or not + ; + mov rcx, MCU_REV_MSR + xor rax, rax + xor rdx, rdx + wrmsr + mov rax, 1 + cpuid + mov rcx, MCU_REV_MSR + rdmsr + or rdx, rdx + jnz uCode_loaded + + ; + ; Load uCode update + ; + mov rax, 1 + cpuid + + mov rax, mMcuAddr + lea rax, [rax + SIZEOF MCU] ; RAX -> MCU data (after header) + xor rdx, rdx + mov rcx, MCU_LOAD_MSR ; Trigger to load MCU + + wrmsr ; Load MCU + + mov rax, 1 + cpuid +uCode_loaded: +;----------------------------------------------------------------------------- +; +; Section: Initial RLPs cache requirements +; +; Description: Ensure CR0.CD and CR0.NW are cleared +; +;----------------------------------------------------------------------------- + ; + ; Clear CR0.CD and CR0.NW + ; + mov rax, cr0 + and rax, NOT (CR0_CD_MASK + CR0_NW_MASK) + mov cr0, rax + +;----------------------------------------------------------------------------- +; +; Section: Clean all MCi_STATUS MSR registers +; +; Description: MCA registers are cleaned +; +;----------------------------------------------------------------------------- + + mov rcx, MCG_CAP + rdmsr + movzx rbx, al ; ebx = MCR bank count + xor rax, rax ; Write 0 into all MCi_STATUS registers + xor rdx, rdx + mov rcx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec rbx + jz @F + add rcx, 4 ; ecx = number of MSRs per bank + jmp McaErrorCleanLoopStart + +@@: + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + rdmsr + and eax, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR) + or eax, (B_INTERRUPT_MASK + V_MODE_SMI) + wrmsr + jmp @f +x2ApicDisabled: + ; mask thermal LVT + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + mov edx, [rax+LOCAL_APIC_THERMAL_DEF] + and edx, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR) + or edx, (B_INTERRUPT_MASK + V_MODE_SMI) + mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ;disable DTS SMIs +@@: + POPA_64 + popf + + leave + ret 0 +DoApInit ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: ApSaveConfig +; +; Input: None +; +; Output: None +; +; Registers: All are preserved +; +; Description: Saves AP configuration +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +ApSaveConfig PROC FRAME + START_FRAME + END_FRAME + + pushf + cli + PUSHA_64 + + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov rcx, rax + + lea rbx, mApMtrrTab + +SaveNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + rdmsr + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop SaveNextMtrr + + mov rcx, IA32_MTRR_DEF_TYPE + rdmsr + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + + lea rbx, mApIdt + sidt [rbx] + lea rbx, mApCr4 + mov rax, cr4 + mov QWORD PTR [rbx], rax + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + rdmsr + lea rbx, mApSavedApicThermalValue + mov DWORD PTR [rbx], eax ; read and save thermal LVT + jmp @f +x2ApicDisabled: + + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + lea rbx, mApSavedApicThermalValue + mov edx, DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF] + mov DWORD PTR [rbx], edx ; read and save thermal LVT +@@: + mov rcx, EFI_MSR_IA32_THERM_INTERRUPT + rdmsr ; + lea rbx, mApSavedIa32ThermInterruptMSR + mov QWORD PTR [rbx+0], rax + mov QWORD PTR [rbx+8], rdx + ;disable THERMAL INT + and rax, NOT (BIT0+BIT1+BIT2+BIT4+BIT15+BIT23) + wrmsr + + wbinvd + + POPA_64 + popf + + leave + ret 0 +ApSaveConfig ENDP + + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: ApRestoreConfig +; +; Input: None +; +; Output: None +; +; Registers: All are preserved +; +; Description: Saves AP configuration +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +ApRestoreConfig PROC FRAME + START_FRAME + END_FRAME + + pushf + cli + PUSHA_64 + + ; + ; Disable cache + ; + mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or rax, CR0_CD_MASK OR CR0_NE_MASK + and rax, NOT CR0_NW_MASK + mov cr0, rax + wbinvd + + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov rcx, rax + + lea rbx, mApMtrrTab + +RestoreNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + wrmsr + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop RestoreNextMtrr + + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + mov rcx, IA32_MTRR_DEF_TYPE + wrmsr + + lea rbx, mApIdt + lidt FWORD PTR [rbx] + lea rbx, mApCr4 + mov rax, QWORD PTR [rbx] + mov cr4, rax + + mov rcx, EFI_MSR_IA32_THERM_INTERRUPT + lea rbx, mApSavedIa32ThermInterruptMSR + mov rax, QWORD PTR [rbx+0] + mov rdx, QWORD PTR [rbx+8] + wrmsr + + mov rcx,IA32_APIC_BASE + rdmsr + and rax,BIT11+BIT10 + cmp rax,BIT11+BIT10 + jne x2ApicDisabled + mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM + lea rbx, mApSavedApicThermalValue + mov eax,DWORD PTR [rbx] ;restore thermal LVT + xor rdx,rdx + wrmsr + jmp @f +x2ApicDisabled: + + mov rcx, IA32_APIC_BASE + rdmsr ; Get APIC Base + and rax, BASE_ADDR_MASK ; Just need the address + lea rbx, mApSavedApicThermalValue + mov edx, DWORD PTR [rbx] + mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ; restore thermal LVT +@@: + ; + ; Enable cache + ; + mov rax, cr0 + and rax, NOT CR0_CD_MASK + mov cr0, rax + + POPA_64 + popf + + leave + ret 0 +ApRestoreConfig ENDP + +_TEXT ENDS + + END diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm new file mode 100644 index 0000000..00f9c87 --- /dev/null +++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm @@ -0,0 +1,712 @@ +;/*++ +; This file contains an 'Intel Peripheral Driver' and uniquely +; identified as "Intel Reference Module" and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +;--*/ +; +;/*++ +; +; Copyright (c) 1999 - 2011 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; +; Module Name: +; +; TxtDxeBsp.asm +; +; Abstract: +; +; This file contains code to launch BIOS ACM functions in DXE phase +; +;--*/ + .xlist + include txt.inc + include mmx64.inc + .list + + + _TEXT SEGMENT + +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +; Procedure: LaunchBiosAcm +; +; Input: AcmBase - Base address of LT BIOS ACM +; Function - function number to execute +; +; Output: None +; +; Registers: None are preserved +; +; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and +; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point. +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- + +LaunchBiosAcm PROC FRAME + + START_FRAME + MAKE_LOCAL AcmBase:QWORD + MAKE_LOCAL Funct:QWORD + MAKE_LOCAL BIOS_GDT[2]:QWORD + MAKE_LOCAL CompModeSel:QWORD + MAKE_LOCAL CompModeOff:QWORD + MAKE_LOCAL LongModeSel:QWORD + MAKE_LOCAL LongModeOff:QWORD + MAKE_LOCAL SavedCR3:QWORD + MAKE_LOCAL SavedCR4:QWORD + MAKE_LOCAL SavedDS:QWORD + MAKE_LOCAL SavedES:QWORD + MAKE_LOCAL SavedGS:QWORD + MAKE_LOCAL SavedFS:QWORD + MAKE_LOCAL SavedMiscEnablesRax:QWORD + MAKE_LOCAL SavedMiscEnablesRdx:QWORD + MAKE_LOCAL MtrrTab[2*(IA32_MTRR_PHYSMASK9 - IA32_MTRR_PHYSBASE0 + 1)]:QWORD + MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD + MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD + MAKE_LOCAL NEXT_MTRR_INDEX:QWORD + MAKE_LOCAL NEXT_MTRR_SIZE:QWORD + MAKE_LOCAL MTRR_COUNT:QWORD + MAKE_LOCAL MtrrTypeRax:QWORD + MAKE_LOCAL MtrrTypeRdx:QWORD + END_FRAME + + ; + ; Save input parameters + ; + mov AcmBase, rcx + + mov Funct, rdx + + sgdt BIOS_GDT ; save gdtr + + ; + ; Save the general purpose register state + ; + pushf + cli + + PUSHA_64 + ; + ; Tell where we are + ; + in ax, 80h + mov ah, BYTE PTR Funct + or ah, PORT80_CODE_PREFIX + out 80h, ax + ; + ; Save segment registers. + ; + mov ax, ds + mov SavedDS, rax + mov ax, es + mov SavedES, rax + mov ax, gs + mov SavedGS, rax + mov ax, fs + mov SavedFS, rax + + ; Save cr4 + ; + mov rax, cr4 + mov SavedCR4, rax + + ; + ; Save IA32_MISC_ENABLES MSR + ; + mov rcx, IA32_MISC_ENABLE_MSR + rdmsr + mov SavedMiscEnablesRax, rax + mov SavedMiscEnablesRdx, rdx + +;----------------------------------------------------------------------------- +; +; Section: Save variable MTRRs +; +; Description: All variable MTRRs are saved in local variables. +; They will be restored after runnong of BIOS ACM +; +;----------------------------------------------------------------------------- + mov rcx, IA32_MTRR_CAP + rdmsr + and rax, 0FFh + shl rax, 1 + mov MTRR_COUNT, rax + mov rcx, rax + lea rbx, MtrrTab + +SaveNextMtrr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + rdmsr + mov [rbx+0], rax + mov [rbx+8], rdx + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + add rbx, 10h + loop SaveNextMtrr + + ; + ; Save IA32_MTRR_DEF_TYPE MSR + ; + mov rcx, IA32_MTRR_DEF_TYPE + rdmsr + mov MtrrTypeRax, rax + mov MtrrTypeRdx, rdx + +;----------------------------------------------------------------------------- +; +; Section: Program MTRRs +; +; Description: Variable MTRRs are programmed to cache ACM as WB +; +;----------------------------------------------------------------------------- + ; + ; Enable SMXE, SSE and debug extensions + ; + mov rax, cr4 + or rax, CR4_OSFXSR + CR4_DE + CR4_SMXE + mov cr4, rax + + ; + ; Disable cache + ; + mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW + or rax, CR0_CD_MASK OR CR0_NE_MASK + and rax, NOT CR0_NW_MASK + mov cr0, rax + wbinvd + ; + ; Disable MTRRs, set Default Type to UC + ; + mov rcx, IA32_MTRR_DEF_TYPE + xor rax, rax + xor rdx, rdx + wrmsr + + ; + ; Clear all of the Variable MTRRs + ; + mov rcx, MTRR_COUNT + +ClearNextMttr: + add rcx, IA32_MTRR_PHYSBASE0 - 1 + wrmsr + sub rcx, IA32_MTRR_PHYSBASE0 - 1 + loop ClearNextMttr + + ; + ; Determine size of AC module + ; + mov rsi, AcmBase + xor rax, rax + mov eax, DWORD PTR [rsi+ACM_HEADER.AcmSize] + shl rax, 2 ; ...in bytes (ACM header has size in dwords) + ; + ; Round up to page size + ; + add rax, 0FFFh ; + and rax, 0FFFFF000h ; Aligned to a page (4KB) + + ; + ; Program MTRRs to cover BIOS ACM + ; + sub rcx, rcx + mov NEXT_MTRR_INDEX, rcx ; Start from MTRR0 + + ; + ; Save remaining size to cache + ; + mov ACM_SIZE_TO_CACHE, rax ; Size of ACM that must be cached + mov ACM_BASE_TO_CACHE, rsi ; Base ACM address + +nextMtrr: + ; + ; Get remaining size to cache + ; + mov rax, ACM_SIZE_TO_CACHE + and rax, rax + jz done ; If no left size - we are done + ; + ; Determine next size to cache. + ; We start from bottom up. Use the following algorythm: + ; 1. Get our own alignment. Max size we can cache equals to our alignment + ; 2. Determine what is bigger - alignment or remaining size to cache. + ; If aligment is bigger - cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; If remaining size to cache is bigger + ; Determine the biggest 2^N part of it and cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; 3. End when there is no left size to cache or no left MTRRs + ; + mov rsi, ACM_BASE_TO_CACHE + bsf rcx, rsi ; Get index of lowest bit set in base address + ; + ; Convert index into size to be cached by next MTRR + ; + mov rdx, 1h + shl rdx, cl ; Alignment is in rdx + cmp rdx, rax ; What is bigger, alignment or remaining size? + jbe gotSize ; JIf aligment is less + ; + ; Remaining size is bigger. Get the biggest part of it, 2^N in size + ; + bsr rcx, rax ; Get index of highest set bit + ; + ; Convert index into size to be cached by next MTRR + ; + mov rdx, 1 + shl rdx, cl ; Size to cache + +gotSize: + mov rax, rdx + mov NEXT_MTRR_SIZE, rax ; Save + + ; + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; + dec rax ; eax - size to cache less one byte + not rax ; eax contains low 32 bits of mask + or rax, MTRR_VALID ; Set valid bit + ; + ; Program mask register + ; + mov rcx, IA32_MTRR_PHYSMASK0 ; setup variable mtrr + mov rbx, NEXT_MTRR_INDEX + add rcx, rbx + + mov rdx, 0Fh + wrmsr + ; + ; Program base register + ; + sub rdx, rdx + mov rcx, IA32_MTRR_PHYSBASE0 ; setup variable mtrr + add rcx, rbx ; ebx is still NEXT_MTRR_INDEX + + mov rax, ACM_BASE_TO_CACHE + or rax, WB ; set type to write back + wrmsr + ; + ; Advance and loop + ; Reduce remaining size to cache + ; + mov rbx, ACM_SIZE_TO_CACHE + mov rax, NEXT_MTRR_SIZE + sub rbx, rax + mov ACM_SIZE_TO_CACHE, rbx + + ; + ; Increment MTRR index + ; + mov rbx, NEXT_MTRR_INDEX + add rbx, 2 + mov NEXT_MTRR_INDEX, rbx + ; + ; Increment base address to cache + ; + mov rbx, ACM_BASE_TO_CACHE + mov rax, NEXT_MTRR_SIZE + add rbx, rax + mov ACM_BASE_TO_CACHE, rbx + + jmp nextMtrr + +done: + ; + ; Enable Variable MTRRs + ; + xor rdx, rdx + mov rax, MTRR_ENABLE + mov rcx, IA32_MTRR_DEF_TYPE + wrmsr + ; + ; Enable cache + ; + mov rax, cr0 + and rax, NOT CR0_CD_MASK + mov cr0, rax + + ; + ; Clean all MCi_STATUS MSR registers + ; SCLEAN will generate GPF otherwise + ; + mov rcx, MCG_CAP + rdmsr + movzx rbx, al ; ebx = MCR bank count + xor rax, rax ; Write 0 into all MCi_STATUS registers + xor rdx, rdx + mov rcx, MC0_STATUS + +McaErrorCleanLoopStart: + wrmsr + dec rbx + jz @F + add rcx, 4 ; ecx = number of MSRs per bank + jmp McaErrorCleanLoopStart + +@@: +;----------------------------------------------------------------------------- +; +; Section: Find Compatible Segment Descriptor in GDT +; +; Description: GDT is scanned until code descriptor with L bit = 0 is found +; +;----------------------------------------------------------------------------- + + lea rax, BIOS_GDT + add rax, 2 ; Point to base + mov rax, [rax] ; Get base of GDT + mov rbx, rax ; Save GDT base + + mov cx, WORD PTR BIOS_GDT + movzx rcx, cx + inc rcx ; rcx - total size of GDT in bytes + add rcx, rax ; rcx - end of GDT + +loopStart: + cmp QWORD PTR [rax], 0 ; Reserved? + je ApplicationDescriptor + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T + jz nextDescriptor ; JIf system descriptor + ; + ; Application descriptor found + ; + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, 8 ; Bit 3 of sType - code segment if set + jz nextDescriptor ; JIf data descriptor + ; + ; Code descriptor is found + ; + test byte ptr [rax].SEG_DESCRIPTOR.LAR16_23, MASK L + jnz nextDescriptor + ; + ; Compatibility mode code descriptor is found + ; + sub rax, rbx ; rax is compatibility segment selector + jmp CompatibilityModeJump + +nextDescriptor: + cmp rax, rcx + jb @F + jmp $ ; Nothing found - impossible situation + +@@: + test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T + jz @F + +ApplicationDescriptor: + ; + ; Application descriptor - 8 bytes + ; + add rax, 8 + jmp loopStart + +@@: + add rax, 16 + jmp loopStart + +;----------------------------------------------------------------------------- +; +; Section: Jump to compatibility mode +; +; Description: Found selector and known label offset +; are used to transfer control to compatibility mode. +; +; NOTE! +; Code programmed from this point on till the return to long mode +; looks differently than code actually executed by CPU +; This is because assembler is in x64 mode whereas CPU is not. +; Whereever differences are present between written and executed code, +; actual instructions are shown in comments. +; +; Example1: Programmed: mov rax, cr4 +; Executed: mov eax, cr4 +; Assembler fails to assemble "mov eax, cr4" since CR4 is +; 64 bits wide in x64 mode. Generated opcodes are nevertheless +; correct. +; +; Example2: Programmed: mov eax, DWORD PTR [rbx+0] +; Executed: mov eax, DWORD PTR [ebx+0] +; Default addressing in x64 mode is 64 bit. If ebx were coded +; in this example, assembler would generate unneeded REX prefix. +; By programming rbx this prefix is not generated and +; opcode corresponds to ebx addressing in compatibility mode +; +;----------------------------------------------------------------------------- + +CompatibilityModeJump: + ; + ; Save Long mode and Compatibility mode selectors and offsets before transition + ; + mov CompModeSel, rax ; Save Compatibility Mode selector + mov rcx, OFFSET ProtectedMode2 + mov CompModeOff, rcx + mov cx, cs + movzx rcx, cx + mov LongModeSel, rcx + mov rcx, OFFSET LongMode2 + mov LongModeOff, rcx + + shl rax, 32 + mov rcx, OFFSET CompatibilityMode + or rax, rcx + push rax + retf + +CompatibilityMode: +;----------------------------------------------------------------------------- +; +; Section: Jump to protected mode +; +; Description: Compatibility mode is disabled since BIOS ACM must run +; in protected 32 bit mode. +; +;----------------------------------------------------------------------------- + + ; + ; Disable paging + ; + mov rcx, cr0 + and ecx, DWORD PTR (NOT BIT31) + mov cr0, rcx + ; + ; Clear EFER.LME + ; + mov ecx, IA32_EFER_MSR + rdmsr + and eax, NOT LME + wrmsr + jmp ProtectedMode + +ProtectedMode: + +;----------------------------------------------------------------------------- +; +; Section: Launch BIOS ACM +; +; Description: Prepare and execute GETSEC[ENTERACCS] +; +;----------------------------------------------------------------------------- + + ; + ; Save return values in MMX registers + ; + + mov ax, ss + movzx eax,ax +% _movd SAVED_SS, eax +% _movd SAVED_EBP, ebp +% _movd SAVED_ESP, esp + lea eax, BIOS_GDT +% _movd SAVED_GDT, eax + mov rax, cr3 ; mov eax, cr3 - in 32 bit mode + mov DWORD PTR SavedCR3, eax + ; + ; Call GETSEC[ENTERACCS] + ; + mov esi, DWORD PTR Funct ; esi = ACM function + mov eax, DWORD PTR AcmBase + mov ebx, eax ; ebx = AcmBase + mov ecx, DWORD PTR [rbx+ACM_HEADER.AcmSize] ; mov DWORD PTR [ebx+ACM_HEADER.AcmSize] - in 32 bit mode + ; ecx = size of ACM in dwords + shl ecx, 2 ; ecx = size of ACM in bytes + xor edx, edx + xor edi, edi + mov eax, ENTERACCS ; eax = ENTERACCS + + _GETSEC + +;for debugging only +; mov ax, 055AAh +; out 80h, ax +;; jmp $ +;----------------------------------------------------------------------------- +; +; Section: Restore protected mode environment +; +; Description: Since BIOS ACM changes GDT, +; BIOS GDT, stack and and CS selector are restored. +; +; +;----------------------------------------------------------------------------- + + ; + ; Reload the GDTR. Upon return CPU is loaded with selector from ACM GDT + ; The following instruction works simply because whatever CS selector is + ; currently, it is flat selector. + ; +% _movd eax, SAVED_GDT + lgdt FWORD ptr [rax] ; lgdt FWORD ptr [eax] - in 32 bit mode + + ; + ; Restore the stack + ; +% _movd eax, SAVED_EBP + mov ebp, eax ; restore ebp +% _movd eax, SAVED_ESP + mov esp, eax ; restore esp +% _movd eax, SAVED_SS + mov ss, ax ; restore ss + + ; + ; Reload cs register + ; + mov eax, DWORD PTR CompModeSel + push rax ; push eax - in 32 bit mode + + mov eax, DWORD PTR CompModeOff + push rax ; push eax - in 32 bit mode + retf ; will jump to Protected label below + +ProtectedMode2: + +;----------------------------------------------------------------------------- +; +; Section: Restore MTRRs +; +; Description: BIOS MTRR values are restored. +; +;----------------------------------------------------------------------------- + ; + ; Disable paging + ; + mov rax, cr0 + and eax, DWORD PTR (NOT CR0_PG_MASK) + mov cr0, rax + + mov rcx, MTRR_COUNT + lea ebx, MtrrTab + +RestoreNextMtrr: + add ecx, IA32_MTRR_PHYSBASE0 - 1 + mov eax, DWORD PTR [rbx+0] ; mov eax, DWORD PTR [ebx+0] - in 32 bit mode + mov edx, DWORD PTR [rbx+8] ; mov eax, DWORD PTR [ebx+8] - in 32 bit mode + wrmsr + sub ecx, IA32_MTRR_PHYSBASE0 - 1 + add ebx, 10h + loop RestoreNextMtrr + + mov rcx, IA32_MTRR_DEF_TYPE + mov rdx, MtrrTypeRdx + mov rax, MtrrTypeRax + wrmsr +;----------------------------------------------------------------------------- +; +; Section: Switch to compatibility mode +; +; Description: Compatibility mode i srestored by enabling of paging - +; this is done by restoring CR4 contenxt, and setting of LME bit. +; +;----------------------------------------------------------------------------- + + ; + ; Enable PAE in CR4 + ; + mov eax, DWORD PTR SavedCR4 + or eax, CR4_PAE + mov cr4, rax + + ; + ; Reload CR3 + ; + mov eax, DWORD PTR SavedCR3 + mov cr3, rax + + ; + ; Set EFER.LME to re-enable ia32-e + ; + mov ecx, IA32_EFER_MSR + rdmsr + or eax, LME + wrmsr + ; + ; Enable paging + ; + mov rax, cr0 + or eax, CR0_PG_MASK + mov cr0, rax + + jmp CompatibilityMode2 + +CompatibilityMode2: + wbinvd ; Flush and invalidate the cache + ; + ; Now we're in Compatibility mode - restore segment registers. + ; + mov rax, SavedDS + mov ds, ax + mov rax, SavedES + mov es, ax + mov rax, SavedGS + mov gs, ax + mov rax, SavedFS + mov fs, ax + ; + ; Reastore IA32_MISC_ENABLES MSR + ; + mov rcx, IA32_MISC_ENABLE_MSR + mov rdx, SavedMiscEnablesRdx + mov rax, SavedMiscEnablesRax + wrmsr + + +;----------------------------------------------------------------------------- +; +; Section: Switch to long mode +; +; Description: Previously saved selector and offset are used to return +; CPU to long mode. +; +;----------------------------------------------------------------------------- + ; + ; Reload cs register + ; + mov eax, DWORD PTR LongModeSel + push rax ; push eax - in 32 bit mode + + mov eax, DWORD PTR LongModeOff + push rax ; push eax - in 32 bit mode + retf + +LongMode2: +;----------------------------------------------------------------------------- +; +; Section: Resore registers, stack and exit. +; +; Description: Previously saved registers are restored. Stack is restored +; by execution leave instruction and control is returned to +; caller. +; +; NOTE! +; This section ends differences between programmed and +; executed code. +; +;----------------------------------------------------------------------------- + ; + ; Now we're in Long Mode + ; Restore control registers + ; + mov rax, SavedCR4 + mov cr4, rax + + POPA_64 + popf + + leave + ret 0 + +LaunchBiosAcm ENDP + +_TEXT ENDS + + END |