FspApiEntry.asm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. ;; @file
  2. ; Provide FSP API entry points.
  3. ;
  4. ; Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
  5. ; SPDX-License-Identifier: BSD-2-Clause-Patent
  6. ;;
  7. .586p
  8. .model flat,C
  9. .code
  10. .xmm
  11. INCLUDE SaveRestoreSse.inc
  12. INCLUDE MicrocodeLoad.inc
  13. ;
  14. ; Following are fixed PCDs
  15. ;
  16. EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
  17. EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
  18. EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
  19. EXTERN PcdGet32(PcdFspAreaSize):DWORD
  20. ;
  21. ; Following functions will be provided in C
  22. ;
  23. EXTERN SecStartup:PROC
  24. EXTERN FspApiCallingCheck:PROC
  25. ;
  26. ; Following functions will be provided in PlatformSecLib
  27. ;
  28. EXTERN AsmGetFspBaseAddress:PROC
  29. EXTERN AsmGetFspInfoHeader:PROC
  30. EXTERN GetBootFirmwareVolumeOffset:PROC
  31. EXTERN Loader2PeiSwitchStack:PROC
  32. EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
  33. EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
  34. EXTERN SecCarInit:PROC
  35. ;
  36. ; Define the data length that we saved on the stack top
  37. ;
  38. DATA_LEN_OF_PER0 EQU 18h
  39. DATA_LEN_OF_MCUD EQU 18h
  40. DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
  41. ;
  42. ; Define SSE macros
  43. ;
  44. LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
  45. mov esi, ReturnAddress
  46. movd MmxRegister, esi ; save ReturnAddress into MMX
  47. ENDM
  48. CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
  49. local ReturnAddress
  50. mov esi, offset ReturnAddress
  51. movd MmxRegister, esi ; save ReturnAddress into MMX
  52. jmp RoutineLabel
  53. ReturnAddress:
  54. ENDM
  55. RET_ESI_EXT MACRO MmxRegister
  56. movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
  57. jmp esi
  58. ENDM
  59. CALL_MMX MACRO RoutineLabel
  60. CALL_MMX_EXT RoutineLabel, mm7
  61. ENDM
  62. RET_ESI MACRO
  63. RET_ESI_EXT mm7
  64. ENDM
  65. ;------------------------------------------------------------------------------
  66. SecPlatformInitDefault PROC NEAR PUBLIC
  67. ; Inputs:
  68. ; mm7 -> Return address
  69. ; Outputs:
  70. ; eax -> 0 - Successful, Non-zero - Failed.
  71. ; Register Usage:
  72. ; eax is cleared and ebp is used for return address.
  73. ; All others reserved.
  74. ; Save return address to EBP
  75. movd ebp, mm7
  76. xor eax, eax
  77. exit:
  78. jmp ebp
  79. SecPlatformInitDefault ENDP
  80. ;------------------------------------------------------------------------------
  81. LoadMicrocodeDefault PROC NEAR PUBLIC
  82. ; Inputs:
  83. ; esp -> LoadMicrocodeParams pointer
  84. ; Register Usage:
  85. ; esp Preserved
  86. ; All others destroyed
  87. ; Assumptions:
  88. ; No memory available, stack is hard-coded and used for return address
  89. ; Executed by SBSP and NBSP
  90. ; Beginning of microcode update region starts on paragraph boundary
  91. ;
  92. ;
  93. ; Save return address to EBP
  94. movd ebp, mm7
  95. cmp esp, 0
  96. jz paramerror
  97. mov eax, dword ptr [esp + 4] ; Parameter pointer
  98. cmp eax, 0
  99. jz paramerror
  100. mov esp, eax
  101. mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
  102. cmp esi, 0
  103. jnz check_main_header
  104. paramerror:
  105. mov eax, 080000002h
  106. jmp exit
  107. mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
  108. check_main_header:
  109. ; Get processor signature and platform ID from the installed processor
  110. ; and save into registers for later use
  111. ; ebx = processor signature
  112. ; edx = platform ID
  113. mov eax, 1
  114. cpuid
  115. mov ebx, eax
  116. mov ecx, MSR_IA32_PLATFORM_ID
  117. rdmsr
  118. mov ecx, edx
  119. shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
  120. and ecx, 7h ; platform id at bit[52..50]
  121. mov edx, 1
  122. shl edx, cl
  123. ; Current register usage
  124. ; esp -> stack with paramters
  125. ; esi -> microcode update to check
  126. ; ebx = processor signature
  127. ; edx = platform ID
  128. ; Check for valid microcode header
  129. ; Minimal test checking for header version and loader version as 1
  130. mov eax, dword ptr 1
  131. cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
  132. jne advance_fixed_size
  133. cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
  134. jne advance_fixed_size
  135. ; Check if signature and plaform ID match
  136. cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
  137. jne @f
  138. test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
  139. jnz load_check ; Jif signature and platform ID match
  140. @@:
  141. ; Check if extended header exists
  142. ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
  143. xor eax, eax
  144. cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
  145. je next_microcode
  146. cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
  147. je next_microcode
  148. ; Then verify total size - sizeof header > data size
  149. mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
  150. sub ecx, sizeof MicrocodeHdr
  151. cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
  152. jng next_microcode ; Jif extended header does not exist
  153. ; Set edi -> extended header
  154. mov edi, esi
  155. add edi, sizeof MicrocodeHdr
  156. add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
  157. ; Get count of extended structures
  158. mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
  159. ; Move pointer to first signature structure
  160. add edi, sizeof ExtSigHdr
  161. check_ext_sig:
  162. ; Check if extended signature and platform ID match
  163. cmp [edi].ExtSig.ExtSigProcessor, ebx
  164. jne @f
  165. test [edi].ExtSig.ExtSigFlags, edx
  166. jnz load_check ; Jif signature and platform ID match
  167. @@:
  168. ; Check if any more extended signatures exist
  169. add edi, sizeof ExtSig
  170. loop check_ext_sig
  171. next_microcode:
  172. ; Advance just after end of this microcode
  173. xor eax, eax
  174. cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
  175. je @f
  176. add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
  177. jmp check_address
  178. @@:
  179. add esi, dword ptr 2048
  180. jmp check_address
  181. advance_fixed_size:
  182. ; Advance by 4X dwords
  183. add esi, dword ptr 1024
  184. check_address:
  185. ; Is valid Microcode start point ?
  186. cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
  187. jz done
  188. ; Is automatic size detection ?
  189. mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
  190. cmp eax, 0ffffffffh
  191. jz @f
  192. ; Address >= microcode region address + microcode region size?
  193. add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
  194. cmp esi, eax
  195. jae done ;Jif address is outside of microcode region
  196. jmp check_main_header
  197. @@:
  198. load_check:
  199. ; Get the revision of the current microcode update loaded
  200. mov ecx, MSR_IA32_BIOS_SIGN_ID
  201. xor eax, eax ; Clear EAX
  202. xor edx, edx ; Clear EDX
  203. wrmsr ; Load 0 to MSR at 8Bh
  204. mov eax, 1
  205. cpuid
  206. mov ecx, MSR_IA32_BIOS_SIGN_ID
  207. rdmsr ; Get current microcode signature
  208. ; Verify this microcode update is not already loaded
  209. cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
  210. je continue
  211. load_microcode:
  212. ; EAX contains the linear address of the start of the Update Data
  213. ; EDX contains zero
  214. ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
  215. ; Start microcode load with wrmsr
  216. mov eax, esi
  217. add eax, sizeof MicrocodeHdr
  218. xor edx, edx
  219. mov ecx, MSR_IA32_BIOS_UPDT_TRIG
  220. wrmsr
  221. mov eax, 1
  222. cpuid
  223. continue:
  224. jmp next_microcode
  225. done:
  226. mov eax, 1
  227. cpuid
  228. mov ecx, MSR_IA32_BIOS_SIGN_ID
  229. rdmsr ; Get current microcode signature
  230. xor eax, eax
  231. cmp edx, 0
  232. jnz exit
  233. mov eax, 08000000Eh
  234. exit:
  235. jmp ebp
  236. LoadMicrocodeDefault ENDP
  237. EstablishStackFsp PROC NEAR PRIVATE
  238. ;
  239. ; Save parameter pointer in edx
  240. ;
  241. mov edx, dword ptr [esp + 4]
  242. ;
  243. ; Enable FSP STACK
  244. ;
  245. mov esp, PcdGet32 (PcdTemporaryRamBase)
  246. add esp, PcdGet32 (PcdTemporaryRamSize)
  247. push DATA_LEN_OF_MCUD ; Size of the data region
  248. push 4455434Dh ; Signature of the data region 'MCUD'
  249. push dword ptr [edx + 12] ; Code size
  250. push dword ptr [edx + 8] ; Code base
  251. push dword ptr [edx + 4] ; Microcode size
  252. push dword ptr [edx] ; Microcode base
  253. ;
  254. ; Save API entry/exit timestamp into stack
  255. ;
  256. push DATA_LEN_OF_PER0 ; Size of the data region
  257. push 30524550h ; Signature of the data region 'PER0'
  258. LOAD_EDX
  259. push edx
  260. LOAD_EAX
  261. push eax
  262. rdtsc
  263. push edx
  264. push eax
  265. ;
  266. ; Terminator for the data on stack
  267. ;
  268. push 0
  269. ;
  270. ; Set ECX/EDX to the BootLoader temporary memory range
  271. ;
  272. mov ecx, PcdGet32 (PcdTemporaryRamBase)
  273. mov edx, ecx
  274. add edx, PcdGet32 (PcdTemporaryRamSize)
  275. sub edx, PcdGet32 (PcdFspTemporaryRamSize)
  276. xor eax, eax
  277. RET_ESI
  278. EstablishStackFsp ENDP
  279. ;----------------------------------------------------------------------------
  280. ; TempRamInit API
  281. ;
  282. ; This FSP API will load the microcode update, enable code caching for the
  283. ; region specified by the boot loader and also setup a temporary stack to be
  284. ; used till main memory is initialized.
  285. ;
  286. ;----------------------------------------------------------------------------
  287. TempRamInitApi PROC NEAR PUBLIC
  288. ;
  289. ; Ensure SSE is enabled
  290. ;
  291. ENABLE_SSE
  292. ;
  293. ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
  294. ;
  295. SAVE_REGS
  296. ;
  297. ; Save timestamp into XMM6
  298. ;
  299. rdtsc
  300. SAVE_EAX
  301. SAVE_EDX
  302. ;
  303. ; Check Parameter
  304. ;
  305. mov eax, dword ptr [esp + 4]
  306. cmp eax, 0
  307. mov eax, 80000002h
  308. jz TempRamInitExit
  309. ;
  310. ; Sec Platform Init
  311. ;
  312. CALL_MMX SecPlatformInit
  313. cmp eax, 0
  314. jnz TempRamInitExit
  315. ; Load microcode
  316. LOAD_ESP
  317. CALL_MMX LoadMicrocode
  318. SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
  319. ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
  320. ; Call Sec CAR Init
  321. LOAD_ESP
  322. CALL_MMX SecCarInit
  323. cmp eax, 0
  324. jnz TempRamInitExit
  325. LOAD_ESP
  326. CALL_MMX EstablishStackFsp
  327. LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
  328. TempRamInitExit:
  329. ;
  330. ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
  331. ;
  332. LOAD_REGS
  333. ret
  334. TempRamInitApi ENDP
  335. ;----------------------------------------------------------------------------
  336. ; FspInit API
  337. ;
  338. ; This FSP API will perform the processor and chipset initialization.
  339. ; This API will not return. Instead, it transfers the control to the
  340. ; ContinuationFunc provided in the parameter.
  341. ;
  342. ;----------------------------------------------------------------------------
  343. FspInitApi PROC NEAR PUBLIC
  344. mov eax, 1
  345. jmp FspApiCommon
  346. FspInitApi ENDP
  347. ;----------------------------------------------------------------------------
  348. ; NotifyPhase API
  349. ;
  350. ; This FSP API will notify the FSP about the different phases in the boot
  351. ; process
  352. ;
  353. ;----------------------------------------------------------------------------
  354. NotifyPhaseApi PROC C PUBLIC
  355. mov eax, 2
  356. jmp FspApiCommon
  357. NotifyPhaseApi ENDP
  358. ;----------------------------------------------------------------------------
  359. ; FspMemoryInit API
  360. ;
  361. ; This FSP API is called after TempRamInit and initializes the memory.
  362. ;
  363. ;----------------------------------------------------------------------------
  364. FspMemoryInitApi PROC NEAR PUBLIC
  365. mov eax, 3
  366. jmp FspApiCommon
  367. FspMemoryInitApi ENDP
  368. ;----------------------------------------------------------------------------
  369. ; TempRamExitApi API
  370. ;
  371. ; This API tears down temporary RAM
  372. ;
  373. ;----------------------------------------------------------------------------
  374. TempRamExitApi PROC C PUBLIC
  375. mov eax, 4
  376. jmp FspApiCommon
  377. TempRamExitApi ENDP
  378. ;----------------------------------------------------------------------------
  379. ; FspSiliconInit API
  380. ;
  381. ; This FSP API initializes the CPU and the chipset including the IO
  382. ; controllers in the chipset to enable normal operation of these devices.
  383. ;
  384. ;----------------------------------------------------------------------------
  385. FspSiliconInitApi PROC C PUBLIC
  386. mov eax, 5
  387. jmp FspApiCommon
  388. FspSiliconInitApi ENDP
  389. ;----------------------------------------------------------------------------
  390. ; FspApiCommon API
  391. ;
  392. ; This is the FSP API common entry point to resume the FSP execution
  393. ;
  394. ;----------------------------------------------------------------------------
  395. FspApiCommon PROC C PUBLIC
  396. ;
  397. ; EAX holds the API index
  398. ;
  399. ;
  400. ; Stack must be ready
  401. ;
  402. push eax
  403. add esp, 4
  404. cmp eax, dword ptr [esp - 4]
  405. jz @F
  406. mov eax, 080000003h
  407. jmp exit
  408. @@:
  409. ;
  410. ; Verify the calling condition
  411. ;
  412. pushad
  413. push [esp + 4 * 8 + 4] ; push ApiParam
  414. push eax ; push ApiIdx
  415. call FspApiCallingCheck
  416. add esp, 8
  417. cmp eax, 0
  418. jz @F
  419. mov dword ptr [esp + 4 * 7], eax
  420. popad
  421. ret
  422. @@:
  423. popad
  424. cmp eax, 1 ; FspInit API
  425. jz @F
  426. cmp eax, 3 ; FspMemoryInit API
  427. jz @F
  428. call AsmGetFspInfoHeader
  429. jmp Loader2PeiSwitchStack
  430. @@:
  431. ;
  432. ; FspInit and FspMemoryInit APIs, setup the initial stack frame
  433. ;
  434. ;
  435. ; Place holder to store the FspInfoHeader pointer
  436. ;
  437. push eax
  438. ;
  439. ; Update the FspInfoHeader pointer
  440. ;
  441. push eax
  442. call AsmGetFspInfoHeader
  443. mov [esp + 4], eax
  444. pop eax
  445. ;
  446. ; Create a Task Frame in the stack for the Boot Loader
  447. ;
  448. pushfd ; 2 pushf for 4 byte alignment
  449. cli
  450. pushad
  451. ; Reserve 8 bytes for IDT save/restore
  452. sub esp, 8
  453. sidt fword ptr [esp]
  454. ;
  455. ; Setup new FSP stack
  456. ;
  457. mov edi, esp
  458. mov esp, PcdGet32(PcdTemporaryRamBase)
  459. add esp, PcdGet32(PcdTemporaryRamSize)
  460. sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
  461. ;
  462. ; Pass the API Idx to SecStartup
  463. ;
  464. push eax
  465. ;
  466. ; Pass the BootLoader stack to SecStartup
  467. ;
  468. push edi
  469. ;
  470. ; Pass entry point of the PEI core
  471. ;
  472. call AsmGetFspBaseAddress
  473. mov edi, eax
  474. add edi, PcdGet32 (PcdFspAreaSize)
  475. sub edi, 20h
  476. add eax, DWORD PTR ds:[edi]
  477. push eax
  478. ;
  479. ; Pass BFV into the PEI Core
  480. ; It uses relative address to calucate the actual boot FV base
  481. ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
  482. ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
  483. ; they are different. The code below can handle both cases.
  484. ;
  485. call AsmGetFspBaseAddress
  486. mov edi, eax
  487. call GetBootFirmwareVolumeOffset
  488. add eax, edi
  489. push eax
  490. ;
  491. ; Pass stack base and size into the PEI Core
  492. ;
  493. mov eax, PcdGet32(PcdTemporaryRamBase)
  494. add eax, PcdGet32(PcdTemporaryRamSize)
  495. sub eax, PcdGet32(PcdFspTemporaryRamSize)
  496. push eax
  497. push PcdGet32(PcdFspTemporaryRamSize)
  498. ;
  499. ; Pass Control into the PEI Core
  500. ;
  501. call SecStartup
  502. add esp, 4
  503. exit:
  504. ret
  505. FspApiCommon ENDP
  506. END