FspApiEntryT.nasm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. ;; @file
  2. ; Provide FSP API entry points.
  3. ;
  4. ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
  5. ; SPDX-License-Identifier: BSD-2-Clause-Patent
  6. ;;
  7. SECTION .text
  8. %include "SaveRestoreSseAvxNasm.inc"
  9. %include "MicrocodeLoadNasm.inc"
  10. ;
  11. ; Following are fixed PCDs
  12. ;
  13. extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
  14. extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
  15. extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
  16. ;
  17. ; Following functions will be provided in PlatformSecLib
  18. ;
  19. extern ASM_PFX(AsmGetFspBaseAddress)
  20. extern ASM_PFX(AsmGetFspInfoHeaderNoStack)
  21. ;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
  22. extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
  23. extern ASM_PFX(SecCarInit)
  24. ;
  25. ; Define the data length that we saved on the stack top
  26. ;
  27. DATA_LEN_OF_PER0 EQU 18h
  28. DATA_LEN_OF_MCUD EQU 18h
  29. DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
  30. ;
  31. ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
  32. ; build error. This needs to be fixed later on.
  33. ;
  34. struc MicrocodeHdr
  35. .MicrocodeHdrVersion: resd 1
  36. .MicrocodeHdrRevision: resd 1
  37. .MicrocodeHdrDate: resd 1
  38. .MicrocodeHdrProcessor: resd 1
  39. .MicrocodeHdrChecksum: resd 1
  40. .MicrocodeHdrLoader: resd 1
  41. .MicrocodeHdrFlags: resd 1
  42. .MicrocodeHdrDataSize: resd 1
  43. .MicrocodeHdrTotalSize: resd 1
  44. .MicrocodeHdrRsvd: resd 3
  45. .size:
  46. endstruc
  47. struc ExtSigHdr
  48. .ExtSigHdrCount: resd 1
  49. .ExtSigHdrChecksum: resd 1
  50. .ExtSigHdrRsvd: resd 3
  51. .size:
  52. endstruc
  53. struc ExtSig
  54. .ExtSigProcessor: resd 1
  55. .ExtSigFlags: resd 1
  56. .ExtSigChecksum: resd 1
  57. .size:
  58. endstruc
  59. struc LoadMicrocodeParamsFsp24
  60. ; FSP_UPD_HEADER {
  61. .FspUpdHeaderSignature: resd 2
  62. .FspUpdHeaderRevision: resb 1
  63. .FspUpdHeaderReserved: resb 23
  64. ; }
  65. ; FSPT_ARCH2_UPD {
  66. .FsptArchRevision: resb 1
  67. .FsptArchReserved: resb 3
  68. .FsptArchLength: resd 1
  69. .FspDebugHandler resq 1
  70. .FsptArchUpd: resd 4
  71. ; }
  72. ; FSPT_CORE_UPD {
  73. .MicrocodeCodeAddr: resq 1
  74. .MicrocodeCodeSize: resq 1
  75. .CodeRegionBase: resq 1
  76. .CodeRegionSize: resq 1
  77. ; }
  78. .size:
  79. endstruc
  80. %macro CALL_RDI 1
  81. mov rdi, %%ReturnAddress
  82. jmp %1
  83. %%ReturnAddress:
  84. %endmacro
  85. ;
  86. ; @todo: The strong/weak implementation does not work.
  87. ; This needs to be reviewed later.
  88. ;
  89. ;------------------------------------------------------------------------------
  90. ;
  91. ;;global ASM_PFX(SecPlatformInitDefault)
  92. ;ASM_PFX(SecPlatformInitDefault):
  93. ; ; Inputs:
  94. ; ; ymm7 -> Return address
  95. ; ; Outputs:
  96. ; ; rax -> 0 - Successful, Non-zero - Failed.
  97. ; ; Register Usage:
  98. ; ; rax is cleared and rbp is used for return address.
  99. ; ; All others reserved.
  100. ;
  101. ; ; Save return address to RBP
  102. ; LOAD_RBP
  103. ;
  104. ; xor rax, rax
  105. ;Exit1:
  106. ; jmp rbp
  107. ;------------------------------------------------------------------------------
  108. global ASM_PFX(LoadMicrocodeDefault)
  109. ASM_PFX(LoadMicrocodeDefault):
  110. ; Inputs:
  111. ; rcx -> LoadMicrocodeParams pointer
  112. ; Register Usage:
  113. ; All are destroyed
  114. ; Assumptions:
  115. ; No memory available, stack is hard-coded and used for return address
  116. ; Executed by SBSP and NBSP
  117. ; Beginning of microcode update region starts on paragraph boundary
  118. ;
  119. ; Save return address to RBP
  120. ;
  121. LOAD_RBP
  122. test rsp, rsp
  123. jz ParamError
  124. test rcx, rcx
  125. jz ParamError
  126. mov rsp, rcx
  127. ;
  128. ; If microcode already loaded before this function, exit this function with SUCCESS.
  129. ;
  130. mov ecx, MSR_IA32_BIOS_SIGN_ID
  131. xor eax, eax ; Clear EAX
  132. xor edx, edx ; Clear EDX
  133. wrmsr ; Load 0 to MSR at 8Bh
  134. mov eax, 1
  135. cpuid
  136. mov ecx, MSR_IA32_BIOS_SIGN_ID
  137. rdmsr ; Get current microcode signature
  138. xor rax, rax
  139. test edx, edx
  140. jnz Exit2
  141. ; skip loading Microcode if the MicrocodeCodeSize is zero
  142. ; and report error if size is less than 2k
  143. ; first check UPD header revision
  144. cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
  145. jb ParamError
  146. cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
  147. jne ParamError
  148. ; UPD structure is compliant with FSP spec 2.4
  149. mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
  150. test rax, rax
  151. jz Exit2
  152. cmp rax, 0800h
  153. jl ParamError
  154. mov rsi, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
  155. test rsi, rsi
  156. jnz CheckMainHeader
  157. ParamError:
  158. mov rax, 08000000000000002h
  159. jmp Exit2
  160. CheckMainHeader:
  161. ; Get processor signature and platform ID from the installed processor
  162. ; and save into registers for later use
  163. ; ebx = processor signature
  164. ; edx = platform ID
  165. mov eax, 1
  166. cpuid
  167. mov ebx, eax
  168. mov ecx, MSR_IA32_PLATFORM_ID
  169. rdmsr
  170. mov ecx, edx
  171. shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
  172. and ecx, 7h ; platform id at bit[52..50]
  173. mov edx, 1
  174. shl edx, cl
  175. ; Current register usage
  176. ; esp -> stack with parameters
  177. ; esi -> microcode update to check
  178. ; ebx = processor signature
  179. ; edx = platform ID
  180. ; Check for valid microcode header
  181. ; Minimal test checking for header version and loader version as 1
  182. mov eax, dword 1
  183. cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
  184. jne AdvanceFixedSize
  185. cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
  186. jne AdvanceFixedSize
  187. ; Check if signature and plaform ID match
  188. cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
  189. jne LoadMicrocodeDefault1
  190. test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
  191. jnz LoadMicrocode ; Jif signature and platform ID match
  192. LoadMicrocodeDefault1:
  193. ; Check if extended header exists
  194. ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
  195. xor rax, rax
  196. cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
  197. je NextMicrocode
  198. cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
  199. je NextMicrocode
  200. ; Then verify total size - sizeof header > data size
  201. mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
  202. sub ecx, MicrocodeHdr.size
  203. cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
  204. jng NextMicrocode ; Jif extended header does not exist
  205. ; Set edi -> extended header
  206. mov edi, esi
  207. add edi, MicrocodeHdr.size
  208. add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
  209. ; Get count of extended structures
  210. mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
  211. ; Move pointer to first signature structure
  212. add edi, ExtSigHdr.size
  213. CheckExtSig:
  214. ; Check if extended signature and platform ID match
  215. cmp dword [edi + ExtSig.ExtSigProcessor], ebx
  216. jne LoadMicrocodeDefault2
  217. test dword [edi + ExtSig.ExtSigFlags], edx
  218. jnz LoadMicrocode ; Jif signature and platform ID match
  219. LoadMicrocodeDefault2:
  220. ; Check if any more extended signatures exist
  221. add edi, ExtSig.size
  222. loop CheckExtSig
  223. NextMicrocode:
  224. ; Advance just after end of this microcode
  225. xor rax, rax
  226. cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
  227. je LoadMicrocodeDefault3
  228. add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
  229. jmp CheckAddress
  230. LoadMicrocodeDefault3:
  231. add esi, dword 2048
  232. jmp CheckAddress
  233. AdvanceFixedSize:
  234. ; Advance by 4X dwords
  235. add esi, dword 1024
  236. CheckAddress:
  237. ; Check UPD header revision
  238. cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
  239. jb ParamError
  240. cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
  241. jne ParamError
  242. ; UPD structure is compliant with FSP spec 2.4
  243. ; Is automatic size detection ?
  244. mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
  245. mov rcx, 0ffffffffffffffffh
  246. cmp rax, rcx
  247. jz LoadMicrocodeDefault4
  248. ; Address >= microcode region address + microcode region size?
  249. add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
  250. cmp rsi, rax
  251. jae Done ;Jif address is outside of microcode region
  252. jmp CheckMainHeader
  253. LoadMicrocodeDefault4:
  254. ; Is valid Microcode start point ?
  255. cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
  256. jz Done
  257. jmp CheckMainHeader
  258. LoadMicrocode:
  259. ; EAX contains the linear address of the start of the Update Data
  260. ; EDX contains zero
  261. ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
  262. ; Start microcode load with wrmsr
  263. mov eax, esi
  264. add eax, MicrocodeHdr.size
  265. xor edx, edx
  266. mov ecx, MSR_IA32_BIOS_UPDT_TRIG
  267. wrmsr
  268. mov eax, 1
  269. cpuid
  270. Done:
  271. mov ecx, MSR_IA32_BIOS_SIGN_ID
  272. xor eax, eax ; Clear EAX
  273. xor edx, edx ; Clear EDX
  274. wrmsr ; Load 0 to MSR at 8Bh
  275. mov eax, 1
  276. cpuid
  277. mov ecx, MSR_IA32_BIOS_SIGN_ID
  278. rdmsr ; Get current microcode signature
  279. xor eax, eax
  280. test edx, edx
  281. jnz Exit2
  282. mov rax, 0800000000000000Eh
  283. Exit2:
  284. jmp rbp
  285. global ASM_PFX(EstablishStackFsp)
  286. ASM_PFX(EstablishStackFsp):
  287. ;
  288. ; Save parameter pointer in rdx
  289. ;
  290. mov rdx, rcx
  291. ;
  292. ; Enable FSP STACK
  293. ;
  294. mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
  295. mov esp, DWORD[rax]
  296. mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
  297. add esp, DWORD[rax]
  298. sub esp, 4
  299. mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
  300. sub esp, 4
  301. mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
  302. ; check UPD structure revision (rdx + 8)
  303. cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
  304. jb ParamError1
  305. cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
  306. je Fsp24UpdHeader
  307. ParamError1:
  308. mov rax, 08000000000000002h
  309. jmp EstablishStackFspExit
  310. Fsp24UpdHeader:
  311. ; UPD structure is compliant with FSP spec 2.4
  312. xor rax, rax
  313. mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
  314. sub rsp, 8
  315. mov qword[rsp], rax
  316. mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
  317. sub rsp, 8
  318. mov qword[rsp], rax
  319. mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
  320. sub rsp, 8
  321. mov qword[rsp], rax
  322. mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
  323. sub rsp, 8
  324. mov qword[rsp], rax
  325. ContinueAfterUpdPush:
  326. ;
  327. ; Save API entry/exit timestamp into stack
  328. ;
  329. sub esp, 4
  330. mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
  331. sub esp, 4
  332. mov dword[esp], 30524550h ; Signature of the data region 'PER0'
  333. rdtsc
  334. sub esp, 4
  335. mov dword[esp], edx
  336. sub esp, 4
  337. mov dword[esp], eax
  338. LOAD_TS rax
  339. push rax
  340. ;
  341. ; Terminator for the data on stack
  342. ;
  343. push 0
  344. ;
  345. ; Set ECX/EDX to the BootLoader temporary memory range
  346. ;
  347. mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
  348. mov edx, [ecx]
  349. mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
  350. add edx, [ecx]
  351. mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
  352. sub edx, [ecx]
  353. mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
  354. mov ecx, [ecx]
  355. cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
  356. jb EstablishStackFspSuccess
  357. mov rax, 08000000000000003h ; EFI_UNSUPPORTED
  358. jmp EstablishStackFspExit
  359. EstablishStackFspSuccess:
  360. xor rax, rax
  361. EstablishStackFspExit:
  362. RET_YMM
  363. ;----------------------------------------------------------------------------
  364. ; TempRamInit API
  365. ;
  366. ; This FSP API will load the microcode update, enable code caching for the
  367. ; region specified by the boot loader and also setup a temporary stack to be
  368. ; used till main memory is initialized.
  369. ;
  370. ;----------------------------------------------------------------------------
  371. global ASM_PFX(TempRamInitApi)
  372. ASM_PFX(TempRamInitApi):
  373. ;
  374. ; Ensure both SSE and AVX are enabled
  375. ;
  376. ENABLE_SSE
  377. ENABLE_AVX
  378. ;
  379. ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
  380. ;
  381. SAVE_REGS
  382. ;
  383. ; Save BFV address in YMM9
  384. ;
  385. SAVE_BFV rbp
  386. ;
  387. ; Save Input Parameter in YMM10
  388. ;
  389. cmp rcx, 0
  390. jnz ParamValid
  391. ;
  392. ; Fall back to default UPD
  393. ;
  394. CALL_RDI ASM_PFX(AsmGetFspInfoHeaderNoStack)
  395. xor rcx, rcx
  396. mov ecx, DWORD [rax + 01Ch] ; Read FsptImageBaseAddress
  397. add ecx, DWORD [rax + 024h] ; Get Cfg Region base address = FsptImageBaseAddress + CfgRegionOffset
  398. ParamValid:
  399. SAVE_RCX
  400. ;
  401. ; Save timestamp into YMM6
  402. ;
  403. rdtsc
  404. shl rdx, 32
  405. or rax, rdx
  406. SAVE_TS rax
  407. ;
  408. ; Sec Platform Init
  409. ;
  410. CALL_YMM ASM_PFX(SecPlatformInit)
  411. test rax, rax
  412. jnz TempRamInitExit
  413. ; Load microcode
  414. LOAD_RCX
  415. CALL_YMM ASM_PFX(LoadMicrocodeDefault)
  416. SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
  417. ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
  418. ; Call Sec CAR Init
  419. LOAD_RCX
  420. CALL_YMM ASM_PFX(SecCarInit)
  421. test rax, rax
  422. jnz TempRamInitExit
  423. LOAD_RCX
  424. CALL_YMM ASM_PFX(EstablishStackFsp)
  425. test rax, rax
  426. jnz TempRamInitExit
  427. LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
  428. TempRamInitExit:
  429. mov bl, al ; save al data in bl
  430. mov al, 07Fh ; API exit postcode 7f
  431. out 080h, al
  432. mov al, bl ; restore al data from bl
  433. ;
  434. ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
  435. ;
  436. LOAD_REGS
  437. LOAD_BFV rbp
  438. ret
  439. ;----------------------------------------------------------------------------
  440. ; Module Entrypoint API
  441. ;----------------------------------------------------------------------------
  442. global ASM_PFX(_ModuleEntryPoint)
  443. ASM_PFX(_ModuleEntryPoint):
  444. jmp $