FspApiEntry.s 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. #------------------------------------------------------------------------------
  2. #
  3. # Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
  4. # SPDX-License-Identifier: BSD-2-Clause-Patent
  5. #
  6. # Abstract:
  7. #
  8. # Provide FSP API entry points.
  9. #
  10. #------------------------------------------------------------------------------
  11. .equ MSR_IA32_PLATFORM_ID, 0x00000017
  12. .equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079
  13. .equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b
  14. MicrocodeHdr:
  15. .equ MicrocodeHdrVersion, 0x0000
  16. .equ MicrocodeHdrRevision, 0x0004
  17. .equ MicrocodeHdrDate, 0x0008
  18. .equ MicrocodeHdrProcessor, 0x000c
  19. .equ MicrocodeHdrChecksum, 0x0010
  20. .equ MicrocodeHdrLoader, 0x0014
  21. .equ MicrocodeHdrFlags, 0x0018
  22. .equ MicrocodeHdrDataSize, 0x001C
  23. .equ MicrocodeHdrTotalSize, 0x0020
  24. .equ MicrocodeHdrRsvd, 0x0024
  25. MicrocodeHdrEnd:
  26. .equ MicrocodeHdrLength, 0x0030 # MicrocodeHdrLength = MicrocodeHdrEnd - MicrocodeHdr
  27. ExtSigHdr:
  28. .equ ExtSigHdrCount, 0x0000
  29. .equ ExtSigHdrChecksum, 0x0004
  30. .equ ExtSigHdrRsvd, 0x0008
  31. ExtSigHdrEnd:
  32. .equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr
  33. ExtSig:
  34. .equ ExtSigProcessor, 0x0000
  35. .equ ExtSigFlags, 0x0004
  36. .equ ExtSigChecksum, 0x0008
  37. ExtSigEnd:
  38. .equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig
  39. LoadMicrocodeParams:
  40. .equ MicrocodeCodeAddr, 0x0000
  41. .equ MicrocodeCodeSize, 0x0004
  42. LoadMicrocodeParamsEnd:
  43. .macro SAVE_REGS
  44. pinsrw $0x00, %ebp, %xmm7
  45. ror $0x10, %ebp
  46. pinsrw $0x01, %ebp, %xmm7
  47. ror $0x10, %ebp
  48. #
  49. pinsrw $0x02, %ebx, %xmm7
  50. ror $0x10, %ebx
  51. pinsrw $0x03, %ebx, %xmm7
  52. ror $0x10, %ebx
  53. #
  54. pinsrw $0x04, %esi, %xmm7
  55. ror $0x10, %esi
  56. pinsrw $0x05, %esi, %xmm7
  57. ror $0x10, %esi
  58. #
  59. pinsrw $0x06, %edi, %xmm7
  60. ror $0x10, %edi
  61. pinsrw $0x07, %edi, %xmm7
  62. ror $0x10, %edi
  63. #
  64. pinsrw $0x00, %esp, %xmm6
  65. ror $0x10, %esp
  66. pinsrw $0x01, %esp, %xmm6
  67. ror $0x10, %esp
  68. .endm
  69. .macro LOAD_REGS
  70. pshufd $0xe4, %xmm7, %xmm7
  71. movd %xmm7, %ebp
  72. pshufd $0xe4, %xmm7, %xmm7
  73. #
  74. pshufd $0x39, %xmm7, %xmm7
  75. movd %xmm7, %ebx
  76. pshufd $0x93, %xmm7, %xmm7
  77. #
  78. pshufd $0x4e, %xmm7, %xmm7
  79. movd %xmm7, %esi
  80. pshufd $0x4e, %xmm7, %xmm7
  81. #
  82. pshufd $0x93, %xmm7, %xmm7
  83. movd %xmm7, %edi
  84. pshufd $0x39, %xmm7, %xmm7
  85. #
  86. movd %xmm6, %esp
  87. .endm
  88. .macro LOAD_EAX
  89. pshufd $0x39, %xmm6, %xmm6
  90. movd %xmm6, %eax
  91. pshufd $0x93, %xmm6, %xmm6
  92. .endm
  93. .macro LOAD_EDX
  94. pshufd $0xe4, %xmm6, %xmm6
  95. movd %xmm6, %edx
  96. pshufd $0xe4, %xmm6, %xmm6
  97. .endm
  98. .macro SAVE_EAX
  99. pinsrw $0x02, %eax, %xmm6
  100. ror $0x10, %eax
  101. pinsrw $0x03, %eax, %xmm6
  102. ror $0x10, %eax
  103. .endm
  104. .macro SAVE_EDX
  105. pinsrw $0x04, %edx, %xmm6
  106. ror $0x10, %edx
  107. pinsrw $0x05, %edx, %xmm6
  108. ror $0x10, %edx
  109. .endm
  110. .macro LOAD_ESP
  111. movd %xmm6, %esp
  112. .endm
  113. .macro ENABLE_SSE
  114. jmp NextAddress
  115. .align 4
  116. #
  117. # Float control word initial value:
  118. # all exceptions masked, double-precision, round-to-nearest
  119. #
  120. ASM_PFX(mFpuControlWord): .word 0x027F
  121. #
  122. # Multimedia-extensions control word:
  123. # all exceptions masked, round-to-nearest, flush to zero for masked underflow
  124. #
  125. ASM_PFX(mMmxControlWord): .long 0x01F80
  126. SseError:
  127. #
  128. # Processor has to support SSE
  129. #
  130. jmp SseError
  131. NextAddress:
  132. #
  133. # Initialize floating point units
  134. #
  135. finit
  136. fldcw ASM_PFX(mFpuControlWord)
  137. #
  138. # Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
  139. # whether the processor supports SSE instruction.
  140. #
  141. movl $1, %eax
  142. cpuid
  143. btl $25, %edx
  144. jnc SseError
  145. #
  146. # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
  147. #
  148. movl %cr4, %eax
  149. orl $BIT9, %eax
  150. movl %eax, %cr4
  151. #
  152. # The processor should support SSE instruction and we can use
  153. # ldmxcsr instruction
  154. #
  155. ldmxcsr ASM_PFX(mMmxControlWord)
  156. .endm
  157. #Save in ECX-SLOT 3 in xmm6.
  158. .macro SAVE_EAX_MICROCODE_RET_STATUS
  159. pinsrw $0x6, %eax, %xmm6
  160. ror $0x10, %eax
  161. pinsrw $0x7, %eax, %xmm6
  162. rol $0x10, %eax
  163. .endm
  164. #Restore from ECX-SLOT 3 in xmm6.
  165. .macro LOAD_EAX_MICROCODE_RET_STATUS
  166. pshufd $0x93, %xmm6, %xmm6
  167. movd %xmm6, %eax
  168. pshufd $0x39, %xmm6, %xmm6
  169. .endm
  170. #
  171. # Following are fixed PCDs
  172. #
  173. ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
  174. ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
  175. ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
  176. #
  177. # Following functions will be provided in C
  178. #
  179. ASM_GLOBAL ASM_PFX(SecStartup)
  180. ASM_GLOBAL ASM_PFX(FspApiCallingCheck)
  181. #
  182. # Following functions will be provided in PlatformSecLib
  183. #
  184. ASM_GLOBAL ASM_PFX(AsmGetFspBaseAddress)
  185. ASM_GLOBAL ASM_PFX(AsmGetFspInfoHeader)
  186. ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
  187. ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)
  188. #
  189. # Define the data length that we saved on the stack top
  190. #
  191. .equ DATA_LEN_OF_PER0, 0x018
  192. .equ DATA_LEN_OF_MCUD, 0x018
  193. .equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
  194. #------------------------------------------------------------------------------
  195. # SecPlatformInitDefault
  196. # Inputs:
  197. # mm7 -> Return address
  198. # Outputs:
  199. # eax -> 0 - Successful, Non-zero - Failed.
  200. # Register Usage:
  201. # eax is cleared and ebp is used for return address.
  202. # All others reserved.
  203. #------------------------------------------------------------------------------
  204. ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)
  205. ASM_PFX(SecPlatformInitDefault):
  206. #
  207. # Save return address to EBP
  208. #
  209. movd %mm7, %ebp
  210. xorl %eax, %eax
  211. SecPlatformInitDefaultExit:
  212. jmp *%ebp
  213. #------------------------------------------------------------------------------
  214. # LoadMicrocodeDefault
  215. #
  216. # Inputs:
  217. # esp -> LoadMicrocodeParams pointer
  218. # Register Usage:
  219. # esp Preserved
  220. # All others destroyed
  221. # Assumptions:
  222. # No memory available, stack is hard-coded and used for return address
  223. # Executed by SBSP and NBSP
  224. # Beginning of microcode update region starts on paragraph boundary
  225. #------------------------------------------------------------------------------
  226. ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)
  227. ASM_PFX(LoadMicrocodeDefault):
  228. #
  229. # Save return address to EBP
  230. #
  231. movd %mm7, %ebp
  232. cmpl $0x00, %esp
  233. jz ParamError
  234. movl 4(%esp), %eax #dword ptr [] Parameter pointer
  235. cmpl $0x00, %eax
  236. jz ParamError
  237. movl %eax, %esp
  238. movl MicrocodeCodeAddr(%esp), %esi
  239. cmpl $0x00, %esi
  240. jnz CheckMainHeader
  241. ParamError:
  242. movl $0x080000002, %eax
  243. jmp LoadMicrocodeExit
  244. CheckMainHeader:
  245. #
  246. # Get processor signature and platform ID from the installed processor
  247. # and save into registers for later use
  248. # ebx = processor signature
  249. # edx = platform ID
  250. #
  251. movl $0x01, %eax
  252. cpuid
  253. movl %eax, %ebx
  254. movl $MSR_IA32_PLATFORM_ID, %ecx
  255. rdmsr
  256. movl %edx, %ecx
  257. shrl $0x12, %ecx # shift (50d-32d=18d=0x12) bits
  258. andl $0x07, %ecx # platform id at bit[52..50]
  259. movl $0x01, %edx
  260. shll %cl,%edx
  261. #
  262. # Current register usage
  263. # esp -> stack with paramters
  264. # esi -> microcode update to check
  265. # ebx = processor signature
  266. # edx = platform ID
  267. #
  268. #
  269. # Check for valid microcode header
  270. # Minimal test checking for header version and loader version as 1
  271. #
  272. movl $0x01, %eax
  273. cmpl %eax, MicrocodeHdrVersion(%esi)
  274. jne AdvanceFixedSize
  275. cmpl %eax, MicrocodeHdrLoader(%esi)
  276. jne AdvanceFixedSize
  277. #
  278. # Check if signature and plaform ID match
  279. #
  280. cmpl MicrocodeHdrProcessor(%esi), %ebx
  281. jne LoadMicrocodeL0
  282. testl MicrocodeHdrFlags(%esi), %edx
  283. jnz LoadCheck #Jif signature and platform ID match
  284. LoadMicrocodeL0:
  285. #
  286. # Check if extended header exists
  287. # First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
  288. #
  289. xorl %eax, %eax
  290. cmpl %eax, MicrocodeHdrTotalSize(%esi)
  291. je NextMicrocode
  292. cmpl %eax, MicrocodeHdrDataSize(%esi)
  293. je NextMicrocode
  294. #
  295. # Then verify total size - sizeof header > data size
  296. #
  297. movl MicrocodeHdrTotalSize(%esi), %ecx
  298. subl $MicrocodeHdrLength, %ecx
  299. cmpl MicrocodeHdrDataSize(%esi), %ecx
  300. jle NextMicrocode
  301. #
  302. # Set edi -> extended header
  303. #
  304. movl %esi, %edi
  305. addl $MicrocodeHdrLength, %edi
  306. addl MicrocodeHdrDataSize(%esi), %edi
  307. #
  308. # Get count of extended structures
  309. #
  310. movl ExtSigHdrCount(%edi), %ecx
  311. #
  312. # Move pointer to first signature structure
  313. #
  314. addl ExtSigHdrLength, %edi
  315. CheckExtSig:
  316. #
  317. # Check if extended signature and platform ID match
  318. #
  319. cmpl %ebx, ExtSigProcessor(%edi)
  320. jne LoadMicrocodeL1
  321. test %edx, ExtSigFlags(%edi)
  322. jnz LoadCheck # Jif signature and platform ID match
  323. LoadMicrocodeL1:
  324. #
  325. # Check if any more extended signatures exist
  326. #
  327. addl $ExtSigLength, %edi
  328. loop CheckExtSig
  329. NextMicrocode:
  330. #
  331. # Advance just after end of this microcode
  332. #
  333. xorl %eax, %eax
  334. cmpl %eax, MicrocodeHdrTotalSize(%esi)
  335. je LoadMicrocodeL2
  336. addl MicrocodeHdrTotalSize(%esi), %esi
  337. jmp CheckAddress
  338. LoadMicrocodeL2:
  339. addl $0x800, %esi #add esi, dword ptr 2048
  340. jmp CheckAddress
  341. AdvanceFixedSize:
  342. #
  343. # Advance by 4X dwords
  344. #
  345. addl $0x400, %esi #add esi, dword ptr 1024
  346. CheckAddress:
  347. #
  348. # Is valid Microcode start point ?
  349. #
  350. cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)
  351. #
  352. # Is automatic size detection ?
  353. #
  354. movl MicrocodeCodeSize(%esp), %eax
  355. cmpl $0x0ffffffff, %eax
  356. jz LoadMicrocodeL3
  357. #
  358. # Address >= microcode region address + microcode region size?
  359. #
  360. addl MicrocodeCodeAddr(%esp), %eax
  361. cmpl %eax, %esi
  362. jae Done #Jif address is outside of microcode region
  363. jmp CheckMainHeader
  364. LoadMicrocodeL3:
  365. LoadCheck:
  366. #
  367. # Get the revision of the current microcode update loaded
  368. #
  369. movl $MSR_IA32_BIOS_SIGN_ID, %ecx
  370. xorl %eax, %eax # Clear EAX
  371. xorl %edx, %edx # Clear EDX
  372. wrmsr # Load 0 to MSR at 8Bh
  373. movl $0x01, %eax
  374. cpuid
  375. movl $MSR_IA32_BIOS_SIGN_ID, %ecx
  376. rdmsr # Get current microcode signature
  377. #
  378. # Verify this microcode update is not already loaded
  379. #
  380. cmpl %edx, MicrocodeHdrRevision(%esi)
  381. je Continue
  382. LoadMicrocode0:
  383. #
  384. # EAX contains the linear address of the start of the Update Data
  385. # EDX contains zero
  386. # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
  387. # Start microcode load with wrmsr
  388. #
  389. movl %esi, %eax
  390. addl $MicrocodeHdrLength, %eax
  391. xorl %edx, %edx
  392. movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
  393. wrmsr
  394. movl $0x01, %eax
  395. cpuid
  396. Continue:
  397. jmp NextMicrocode
  398. Done:
  399. movl $0x01, %eax
  400. cpuid
  401. movl $MSR_IA32_BIOS_SIGN_ID, %ecx
  402. rdmsr # Get current microcode signature
  403. xorl %eax, %eax
  404. cmpl $0x00, %edx
  405. jnz LoadMicrocodeExit
  406. movl $0x08000000E, %eax
  407. LoadMicrocodeExit:
  408. jmp *%ebp
  409. #----------------------------------------------------------------------------
  410. # EstablishStackFsp
  411. #
  412. #----------------------------------------------------------------------------
  413. ASM_GLOBAL ASM_PFX(EstablishStackFsp)
  414. ASM_PFX(EstablishStackFsp):
  415. #
  416. # Save parameter pointer in edx
  417. #
  418. movl 4(%esp), %edx
  419. #
  420. # Enable FSP STACK
  421. #
  422. movl PcdGet32(PcdTemporaryRamBase), %esp
  423. addl PcdGet32(PcdTemporaryRamSize), %esp
  424. pushl $DATA_LEN_OF_MCUD # Size of the data region
  425. pushl $0x4455434D # Signature of the data region 'MCUD'
  426. pushl 12(%edx) # Code size
  427. pushl 8(%edx) # Code base
  428. pushl 4(%edx) # Microcode size
  429. pushl (%edx) # Microcode base
  430. #
  431. # Save API entry/exit timestamp into stack
  432. #
  433. pushl $DATA_LEN_OF_PER0 # Size of the data region
  434. pushl $0x30524550 # Signature of the data region 'PER0'
  435. LOAD_EDX
  436. pushl %edx
  437. LOAD_EAX
  438. pushl %eax
  439. rdtsc
  440. pushl %edx
  441. pushl %eax
  442. #
  443. # Terminator for the data on stack
  444. #
  445. push $0x00
  446. #
  447. # Set ECX/EDX to the BootLoader temporary memory range
  448. #
  449. movl PcdGet32 (PcdTemporaryRamBase), %ecx
  450. movl %ecx, %edx
  451. addl PcdGet32 (PcdTemporaryRamSize), %edx
  452. subl PcdGet32 (PcdFspTemporaryRamSize), %edx
  453. xorl %eax, %eax
  454. movd %mm7, %esi #RET_ESI
  455. jmp *%esi
  456. #----------------------------------------------------------------------------
  457. # TempRamInit API
  458. #
  459. # This FSP API will load the microcode update, enable code caching for the
  460. # region specified by the boot loader and also setup a temporary stack to be
  461. # used till main memory is initialized.
  462. #
  463. #----------------------------------------------------------------------------
  464. ASM_GLOBAL ASM_PFX(TempRamInitApi)
  465. ASM_PFX(TempRamInitApi):
  466. #
  467. # Ensure SSE is enabled
  468. #
  469. ENABLE_SSE
  470. #
  471. # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
  472. #
  473. SAVE_REGS
  474. #
  475. # Save timestamp into XMM6
  476. #
  477. rdtsc
  478. SAVE_EAX
  479. SAVE_EDX
  480. #
  481. # Check Parameter
  482. #
  483. movl 4(%esp), %eax
  484. cmpl $0x00, %eax
  485. movl $0x80000002, %eax
  486. jz NemInitExit
  487. #
  488. # Sec Platform Init
  489. #
  490. movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit
  491. movd %esi, %mm7
  492. .weak ASM_PFX(SecPlatformInit)
  493. .set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)
  494. jmp ASM_PFX(SecPlatformInit)
  495. TempRamInitApiL1:
  496. cmpl $0x00, %eax
  497. jnz NemInitExit
  498. #
  499. # Load microcode
  500. #
  501. LOAD_ESP
  502. movl $TempRamInitApiL2, %esi #CALL_MMX LoadMicrocode
  503. movd %esi, %mm7
  504. .weak ASM_PFX(LoadMicrocode)
  505. .set ASM_PFX(LoadMicrocode), ASM_PFX(LoadMicrocodeDefault)
  506. jmp ASM_PFX(LoadMicrocode)
  507. TempRamInitApiL2:
  508. SAVE_EAX_MICROCODE_RET_STATUS #Save microcode return status in ECX-SLOT 3 in xmm6.
  509. #@note If return value eax is not 0, microcode did not load, but continue and attempt to boot from ECX-SLOT 3 in xmm6.
  510. #
  511. # Call Sec CAR Init
  512. #
  513. LOAD_ESP
  514. movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit
  515. movd %esi, %mm7
  516. jmp ASM_PFX(SecCarInit)
  517. TempRamInitApiL3:
  518. cmpl $0x00, %eax
  519. jnz NemInitExit
  520. #
  521. # EstablishStackFsp
  522. #
  523. LOAD_ESP
  524. movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp
  525. movd %esi, %mm7
  526. jmp ASM_PFX(EstablishStackFsp)
  527. TempRamInitApiL4:
  528. LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.
  529. NemInitExit:
  530. #
  531. # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
  532. #
  533. LOAD_REGS
  534. ret
  535. #----------------------------------------------------------------------------
  536. # FspInit API
  537. #
  538. # This FSP API will perform the processor and chipset initialization.
  539. # This API will not return. Instead, it transfers the control to the
  540. # ContinuationFunc provided in the parameter.
  541. #
  542. #----------------------------------------------------------------------------
  543. ASM_GLOBAL ASM_PFX(FspInitApi)
  544. ASM_PFX(FspInitApi):
  545. movl $0x01, %eax
  546. jmp FspApiCommon
  547. #----------------------------------------------------------------------------
  548. # NotifyPhase API
  549. #
  550. # This FSP API will notify the FSP about the different phases in the boot
  551. # process
  552. #
  553. #----------------------------------------------------------------------------
  554. ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
  555. ASM_PFX(NotifyPhaseApi):
  556. movl $0x02, %eax
  557. jmp FspApiCommon
  558. #----------------------------------------------------------------------------
  559. # FspMemoryInit API
  560. #
  561. # This FSP API is called after TempRamInit and initializes the memory.
  562. #
  563. #----------------------------------------------------------------------------
  564. ASM_GLOBAL ASM_PFX(FspMemoryInitApi)
  565. ASM_PFX(FspMemoryInitApi):
  566. movl $0x03, %eax
  567. jmp FspApiCommon
  568. #----------------------------------------------------------------------------
  569. # TempRamExitApi API
  570. #
  571. # This API tears down temporary RAM
  572. #
  573. #----------------------------------------------------------------------------
  574. ASM_GLOBAL ASM_PFX(TempRamExitApi)
  575. ASM_PFX(TempRamExitApi):
  576. movl $0x04, %eax
  577. jmp FspApiCommon
  578. #----------------------------------------------------------------------------
  579. # FspSiliconInit API
  580. #
  581. # This FSP API initializes the CPU and the chipset including the IO
  582. # controllers in the chipset to enable normal operation of these devices.
  583. #
  584. #----------------------------------------------------------------------------
  585. ASM_GLOBAL ASM_PFX(FspSiliconInitApi)
  586. ASM_PFX(FspSiliconInitApi):
  587. movl $0x05, %eax
  588. jmp FspApiCommon
  589. #----------------------------------------------------------------------------
  590. # FspApiCommon API
  591. #
  592. # This is the FSP API common entry point to resume the FSP execution
  593. #
  594. #----------------------------------------------------------------------------
  595. ASM_GLOBAL ASM_PFX(FspApiCommon)
  596. ASM_PFX(FspApiCommon):
  597. #
  598. # EAX holds the API index
  599. #
  600. #
  601. # Stack must be ready
  602. #
  603. pushl %eax
  604. addl $0x04, %esp
  605. cmpl -4(%esp), %eax
  606. jz FspApiCommonL0
  607. movl $0x080000003, %eax
  608. jmp FspApiCommonExit
  609. FspApiCommonL0:
  610. #
  611. # Verify the calling condition
  612. #
  613. pushal
  614. pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4]
  615. pushl %eax #push ApiIdx
  616. call ASM_PFX(FspApiCallingCheck)
  617. addl $0x08, %esp
  618. cmpl $0x00, %eax
  619. jz FspApiCommonL1
  620. movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax
  621. popal
  622. ret
  623. FspApiCommonL1:
  624. popal
  625. cmpl $0x01, %eax # FspInit API
  626. jz FspApiCommonL2
  627. cmpl $0x03, %eax # FspMemoryInit API
  628. jz FspApiCommonL2
  629. call ASM_PFX(AsmGetFspInfoHeader)
  630. jmp Loader2PeiSwitchStack
  631. FspApiCommonL2:
  632. #
  633. # FspInit and FspMemoryInit APIs, setup the initial stack frame
  634. #
  635. #
  636. # Place holder to store the FspInfoHeader pointer
  637. #
  638. pushl %eax
  639. #
  640. # Update the FspInfoHeader pointer
  641. #
  642. pushl %eax
  643. call ASM_PFX(AsmGetFspInfoHeader)
  644. movl %eax, 4(%esp)
  645. popl %eax
  646. #
  647. # Create a Task Frame in the stack for the Boot Loader
  648. #
  649. pushfl # 2 pushf for 4 byte alignment
  650. cli
  651. pushal
  652. #
  653. # Reserve 8 bytes for IDT save/restore
  654. #
  655. subl $0x08, %esp
  656. sidt (%esp)
  657. #
  658. # Setup new FSP stack
  659. #
  660. movl %esp, %edi
  661. movl PcdGet32(PcdTemporaryRamBase), %esp
  662. addl PcdGet32(PcdTemporaryRamSize), %esp
  663. subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
  664. #
  665. # Pass the API Idx to SecStartup
  666. #
  667. pushl %eax
  668. #
  669. # Pass the BootLoader stack to SecStartup
  670. #
  671. pushl %edi
  672. #
  673. # Pass entry point of the PEI core
  674. #
  675. call ASM_PFX(AsmGetFspBaseAddress)
  676. movl %eax, %edi
  677. addl PcdGet32(PcdFspAreaSize), %edi
  678. subl $0x20, %edi
  679. addl %ds:(%edi), %eax
  680. pushl %eax
  681. #
  682. # Pass BFV into the PEI Core
  683. # It uses relative address to calucate the actual boot FV base
  684. # For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
  685. # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
  686. # they are different. The code below can handle both cases.
  687. #
  688. call ASM_PFX(AsmGetFspBaseAddress)
  689. movl %eax, %edi
  690. call ASM_PFX(GetBootFirmwareVolumeOffset)
  691. addl %edi, %eax
  692. pushl %eax
  693. #
  694. # Pass stack base and size into the PEI Core
  695. #
  696. movl PcdGet32(PcdTemporaryRamBase), %eax
  697. addl PcdGet32(PcdTemporaryRamSize), %eax
  698. subl PcdGet32(PcdFspTemporaryRamSize), %eax
  699. pushl %eax
  700. pushl PcdGet32(PcdFspTemporaryRamSize)
  701. #
  702. # Pass Control into the PEI Core
  703. #
  704. call ASM_PFX(SecStartup)
  705. addl $4, %esp
  706. FspApiCommonExit:
  707. ret