Flat32.S 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. #------------------------------------------------------------------------------
  2. #
  3. # Copyright (c) 2013 - 2016 Intel Corporation.
  4. #
  5. # SPDX-License-Identifier: BSD-2-Clause-Patent
  6. #
  7. # Module Name:
  8. #
  9. # Flat32.S
  10. #
  11. # Abstract:
  12. #
  13. # This is the code that goes from real-mode to protected mode.
  14. # It consumes the reset vector, configures the stack.
  15. #
  16. #
  17. #------------------------------------------------------------------------------
  18. .macro RET32
  19. jmp *%esp
  20. .endm
  21. #
  22. # ROM/SPI/MEMORY Definitions
  23. #
  24. .equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) # Memory Base Address = 0
  25. .equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) # DDR3 Memory Size = 2GB
  26. .equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) # eSRAM Memory Size = 512K
  27. .equ QUARK_STACK_SIZE_BYTES, (0x008000) # Quark stack size = 32K
  28. #
  29. # RTC/CMOS definitions
  30. #
  31. .equ RTC_INDEX, (0x70)
  32. .equ NMI_DISABLE, (0x80) # Bit7=1 disables NMI
  33. .equ NMI_ENABLE, (0x00) # Bit7=0 disables NMI
  34. .equ RTC_DATA, (0x71)
  35. #
  36. # PCI Configuration definitions
  37. #
  38. .equ PCI_CFG, (0x80000000) # PCI configuration access mechanism
  39. .equ PCI_ADDRESS_PORT, (0xCF8)
  40. .equ PCI_DATA_PORT, (0xCFC)
  41. #
  42. # Quark PCI devices
  43. #
  44. .equ HOST_BRIDGE_PFA, (0x0000) # B0:D0:F0 (Host Bridge)
  45. .equ ILB_PFA, (0x00F8) # B0:D31:F0 (Legacy Block)
  46. #
  47. # ILB PCI Config Registers
  48. #
  49. .equ BDE, (0x0D4) # BIOS Decode Enable register
  50. .equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) # Decode all BIOS decode ranges
  51. #
  52. # iLB Reset Register
  53. #
  54. .equ ILB_RESET_REG, (0x0CF9)
  55. .equ CF9_WARM_RESET, (0x02)
  56. .equ CF9_COLD_RESET, (0x08)
  57. #
  58. # Host Bridge PCI Config Registers
  59. #
  60. .equ MESSAGE_BUS_CONTROL_REG, (0xD0) # Message Bus Control Register
  61. .equ SB_OPCODE_FIELD, (0x18) # Bit location of Opcode field
  62. .equ OPCODE_SIDEBAND_REG_READ, (0x10) # Read opcode
  63. .equ OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
  64. .equ OPCODE_SIDEBAND_ALT_REG_READ, (0x06) # Alternate Read opcode
  65. .equ OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
  66. .equ OPCODE_WARM_RESET_REQUEST, (0xF4) # Reset Warm
  67. .equ OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
  68. .equ SB_PORT_FIELD, (0x10) # Bit location of Port ID field
  69. .equ MEMORY_ARBITER_PORT_ID, (0x00)
  70. .equ HOST_BRIDGE_PORT_ID, (0x03)
  71. .equ RMU_PORT_ID, (0x04)
  72. .equ MEMORY_MANAGER_PORT_ID, (0x05)
  73. .equ SOC_UNIT_PORT_ID, (0x31)
  74. .equ SB_ADDR_FIELD, (0x08) # Bit location of Register field
  75. .equ SB_BE_FIELD, (0x04) # Bit location of Byte Enables field
  76. .equ ALL_BYTE_EN, (0x0F) # All Byte Enables
  77. .equ MESSAGE_DATA_REG, (0xD4) # Message Data Register
  78. #
  79. # Memory Arbiter Config Registers
  80. #
  81. .equ AEC_CTRL_OFFSET, (0x00)
  82. #
  83. # Host Bridge Config Registers
  84. #
  85. .equ HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
  86. .equ OR_PM_FIELD, (0x10)
  87. .equ SMI_EN, (0x00080000)
  88. .equ HMBOUND_OFFSET, (0x08)
  89. .equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
  90. .equ HMBOUND_LOCK, (0x01)
  91. .equ HECREG_OFFSET, (0x09)
  92. .equ EC_BASE, (0xE0000000)
  93. .equ EC_ENABLE, (0x01)
  94. .equ HLEGACY_OFFSET, (0x0A)
  95. .equ NMI, (0x00004000)
  96. .equ SMI, (0x00001000)
  97. .equ INTR, (0x00000400)
  98. #
  99. # Memory Manager Config Registers
  100. #
  101. .equ ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
  102. .equ BLOCK_ENABLE_PG, (0x10000000)
  103. .equ BIMRVCTL_OFFSET, (0x19)
  104. .equ ENABLE_IMR_INTERRUPT, (0x80000000)
  105. #
  106. # SOC UNIT Debug Registers
  107. #
  108. .equ CFGSTICKY_W1_OFFSET, (0x50)
  109. .equ FORCE_COLD_RESET, (0x00000001)
  110. .equ CFGSTICKY_RW_OFFSET, (0x51)
  111. .equ RESET_FOR_ESRAM_LOCK, (0x00000020)
  112. .equ RESET_FOR_HMBOUND_LOCK, (0x00000040)
  113. .equ CFGNONSTICKY_W1_OFFSET, (0x52)
  114. .equ FORCE_WARM_RESET, (0x00000001)
  115. #
  116. # CR0 cache control bit definition
  117. #
  118. .equ CR0_CACHE_DISABLE, 0x040000000
  119. .equ CR0_NO_WRITE, 0x020000000
  120. ASM_GLOBAL ASM_PFX(PcdGet32(PcdEsramStage1Base))
  121. #
  122. # Contrary to the name, this file contains 16 bit code as well.
  123. #
  124. .text
  125. #----------------------------------------------------------------------------
  126. #
  127. # Procedure: _ModuleEntryPoint
  128. #
  129. # Input: None
  130. #
  131. # Output: None
  132. #
  133. # Destroys: Assume all registers
  134. #
  135. # Description:
  136. #
  137. # Transition to non-paged flat-model protected mode from a
  138. # hard-coded GDT that provides exactly two descriptors.
  139. # This is a bare bones transition to protected mode only
  140. # used for a while in PEI and possibly DXE.
  141. #
  142. # After enabling protected mode, a far jump is executed to
  143. # transfer to PEI using the newly loaded GDT.
  144. #
  145. # Return: None
  146. #
  147. #----------------------------------------------------------------------------
  148. ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
  149. ASM_PFX(_ModuleEntryPoint):
  150. #
  151. # Warm Reset (INIT#) check.
  152. #
  153. .byte 0xbe,0x00,0xf0 #movw $0xF000, %si
  154. .byte 0x8e,0xde #movw %si, %ds
  155. .byte 0xbe,0xf0,0xff #movw $0xFFF0, %si
  156. .byte 0x80,0x3c,0xea #cmpb $0xEA, (%si) # Is it warm reset ?
  157. jne NotWarmReset # Jump if not.
  158. .byte 0xb0,0x08 #movb $0x08, %al
  159. .byte 0xba,0xf9,0x0c #movw $0xcf9, %dx
  160. .byte 0xee #outb %al, %dx
  161. .byte 0xb0,0x55 #movb $0x55, %al
  162. .byte 0xe6,0x80 #outb %al, $0x80
  163. jmp .
  164. NotWarmReset:
  165. .byte 0x66,0x8b,0xe8 #movl %eax, %ebp
  166. #
  167. # Load the GDT table in GdtDesc
  168. #
  169. .byte 0x66,0xbe #movl $GdtDesc, %esi
  170. .long GdtDesc
  171. .byte 0x66,0x2e,0x0f,0x01,0x14 #lgdt %cs:(%si)
  172. #
  173. # Transition to 16 bit protected mode
  174. #
  175. .byte 0x0f,0x20,0xc0 #movl %cr0, %eax # Get control register 0
  176. .byte 0x66,0x83,0xc8,0x03 #orl $0x0000003, %eax # Set PE bit (bit #0) & MP bit (bit #1)
  177. .byte 0x0f,0x22,0xc0 #movl %eax, %cr0 # Activate protected mode
  178. #
  179. # Now we're in 16 bit protected mode
  180. # Set up the selectors for 32 bit protected mode entry
  181. #
  182. .byte 0xb8 #movw SYS_DATA_SEL, %ax
  183. .word SYS_DATA_SEL
  184. .byte 0x8e,0xd8 #movw %ax, %ds
  185. .byte 0x8e,0xc0 #movw %ax, %es
  186. .byte 0x8e,0xe0 #movw %ax, %fs
  187. .byte 0x8e,0xe8 #movw %ax, %gs
  188. .byte 0x8e,0xd0 #movw %ax, %ss
  189. #
  190. # Transition to Flat 32 bit protected mode
  191. # The jump to a far pointer causes the transition to 32 bit mode
  192. #
  193. .byte 0x66,0xbe #movl ProtectedModeEntryLinearAddress, %esi
  194. .long ProtectedModeEntryLinearAddress
  195. .byte 0x66,0x2e,0xff,0x2c #jmp %cs:(%esi)
  196. #
  197. # Protected mode portion initializes stack, configures cache, and calls C entry point
  198. #
  199. #----------------------------------------------------------------------------
  200. #
  201. # Procedure: ProtectedModeEntryPoint
  202. #
  203. # Input: Executing in 32 Bit Protected (flat) mode
  204. # cs: 0-4GB
  205. # ds: 0-4GB
  206. # es: 0-4GB
  207. # fs: 0-4GB
  208. # gs: 0-4GB
  209. # ss: 0-4GB
  210. #
  211. # Output: This function never returns
  212. #
  213. # Destroys:
  214. # ecx
  215. # edi
  216. # esi
  217. # esp
  218. #
  219. # Description:
  220. # Perform any essential early platform initilaisation
  221. # Setup a stack
  222. # Transfer control to EDKII code in eSRAM
  223. #
  224. #----------------------------------------------------------------------------
  225. ProtectedModeEntryPoint:
  226. leal L0, %esp
  227. jmp stackless_EarlyPlatformInit
  228. L0:
  229. #
  230. # Set up stack pointer
  231. #
  232. movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp
  233. movl $QUARK_ESRAM_MEM_SIZE_BYTES, %esi
  234. addl %esi, %esp # ESP = top of stack (stack grows downwards).
  235. #
  236. # Store the the BIST value in EBP
  237. #
  238. movl $0, %ebp # No processor BIST on Quark
  239. #
  240. # Push processor count to stack first, then BIST status (AP then BSP)
  241. #
  242. movl $1, %eax
  243. cpuid
  244. shrl $16, %ebx
  245. andl $0x000000FF, %ebx
  246. cmpb $1, %bl
  247. jae PushProcessorCount
  248. #
  249. # Some processors report 0 logical processors. Effectively 0 = 1.
  250. # So we fix up the processor count
  251. #
  252. incl %ebx
  253. PushProcessorCount:
  254. pushl %ebx
  255. #
  256. # We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
  257. # for all processor threads
  258. #
  259. xorl %ecx, %ecx
  260. movb %bl, %cl
  261. PushBist:
  262. pushl %ebp
  263. loop PushBist
  264. #
  265. # Pass Control into the PEI Core
  266. #
  267. call PlatformSecLibStartup
  268. #
  269. # PEI Core should never return to here, this is just to capture an invalid return.
  270. #
  271. jmp .
  272. #----------------------------------------------------------------------------
  273. #
  274. # Procedure: stackless_EarlyPlatformInit
  275. #
  276. # Input: esp - Return address
  277. #
  278. # Output: None
  279. #
  280. # Destroys: Assume all registers
  281. #
  282. # Description:
  283. # Any early platform initialisation required
  284. #
  285. # Return:
  286. # None
  287. #
  288. #----------------------------------------------------------------------------
  289. stackless_EarlyPlatformInit:
  290. #
  291. # Save return address
  292. #
  293. movl %esp, %ebp
  294. #
  295. # Ensure cache is disabled.
  296. #
  297. movl %cr0, %eax
  298. orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
  299. invd
  300. movl %eax, %cr0
  301. #
  302. # Disable NMI operation
  303. # Good convention suggests you should read back RTC data port after
  304. # accessing the RTC index port.
  305. #
  306. movb $(NMI_DISABLE), %al
  307. movw $(RTC_INDEX), %dx
  308. outb %al, %dx
  309. movw $(RTC_DATA), %dx
  310. inb %dx, %al
  311. #
  312. # Disable SMI (Disables SMI wire, not SMI messages)
  313. #
  314. movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
  315. leal L1, %esp
  316. jmp stackless_SideBand_Read
  317. L1:
  318. andl $(~SMI_EN), %eax
  319. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
  320. leal L2, %esp
  321. jmp stackless_SideBand_Write
  322. L2:
  323. #
  324. # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
  325. #
  326. movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
  327. leal L3, %esp
  328. jmp stackless_SideBand_Read
  329. L3:
  330. andl $(FORCE_WARM_RESET), %eax
  331. jz TestForceColdReset # Zero means bit clear, we're not requested to warm reset so continue as normal
  332. jmp IssueWarmReset
  333. TestForceColdReset:
  334. movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
  335. leal L4, %esp
  336. jmp stackless_SideBand_Read
  337. L4:
  338. andl $(FORCE_COLD_RESET), %eax
  339. jz TestHmboundLock # Zero means bit clear, we're not requested to cold reset so continue as normal
  340. jmp IssueColdReset
  341. #
  342. # Before setting HMBOUND, check it's not locked
  343. #
  344. TestHmboundLock:
  345. movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
  346. leal L5, %esp
  347. jmp stackless_SideBand_Read
  348. L5:
  349. andl $(HMBOUND_LOCK), %eax
  350. jz ConfigHmbound # Zero means bit clear, we have the config we want so continue as normal
  351. #
  352. # Failed to config - store sticky bit debug
  353. #
  354. movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
  355. leal L6, %esp
  356. jmp stackless_SideBand_Read
  357. L6:
  358. orl $(RESET_FOR_HMBOUND_LOCK), %eax
  359. movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
  360. leal L7, %esp
  361. jmp stackless_SideBand_Write
  362. L7:
  363. jmp IssueWarmReset
  364. #
  365. # Set up the HMBOUND register
  366. #
  367. ConfigHmbound:
  368. movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
  369. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
  370. leal L8, %esp
  371. jmp stackless_SideBand_Write
  372. L8:
  373. #
  374. # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
  375. #
  376. movl $(ENABLE_IMR_INTERRUPT), %eax # Data (Set interrupt enable mask)
  377. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
  378. leal L9, %esp
  379. jmp stackless_SideBand_Write
  380. L9:
  381. #
  382. # Set eSRAM address
  383. #
  384. movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax # Data (Set eSRAM location)
  385. shr $(0x18), %eax
  386. addl $(BLOCK_ENABLE_PG), %eax
  387. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
  388. leal L10, %esp
  389. jmp stackless_SideBand_Write
  390. L10:
  391. #
  392. # Check that we're not blocked from setting the config that we want.
  393. #
  394. movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
  395. leal L11, %esp
  396. jmp stackless_SideBand_Read
  397. L11:
  398. andl $(BLOCK_ENABLE_PG), %eax
  399. jnz ConfigPci # Non-zero means bit set, we have the config we want so continue as normal
  400. #
  401. # Failed to config - store sticky bit debug
  402. #
  403. movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
  404. leal L12, %esp
  405. jmp stackless_SideBand_Read
  406. L12:
  407. orl $(RESET_FOR_ESRAM_LOCK), %eax # Set the bit we're interested in
  408. movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
  409. leal L13, %esp
  410. jmp stackless_SideBand_Write
  411. L13:
  412. jmp IssueWarmReset
  413. #
  414. # Enable PCIEXBAR
  415. #
  416. ConfigPci:
  417. movl $(EC_BASE + EC_ENABLE), %eax # Data
  418. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
  419. leal L14, %esp
  420. jmp stackless_SideBand_Write
  421. L14:
  422. movl $(EC_BASE + EC_ENABLE), %eax # Data
  423. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
  424. leal L15, %esp
  425. jmp stackless_SideBand_Write
  426. L15:
  427. #
  428. # Open up full 8MB SPI decode
  429. #
  430. movl $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx # PCI Configuration address
  431. movl $(DECODE_ALL_REGIONS_ENABLE), %eax
  432. leal L16, %esp
  433. jmp stackless_PCIConfig_Write
  434. L16:
  435. #
  436. # Enable NMI operation
  437. # Good convention suggests you should read back RTC data port after
  438. # accessing the RTC index port.
  439. #
  440. movb $(NMI_ENABLE), %al
  441. movw $(RTC_INDEX), %dx
  442. outb %al, %dx
  443. movw $(RTC_DATA), %dx
  444. inb %dx, %al
  445. #
  446. # Clear Host Bridge SMI, NMI, INTR fields
  447. #
  448. movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
  449. leal L21, %esp
  450. jmp stackless_SideBand_Read
  451. L21:
  452. andl $~(NMI + SMI + INTR), %eax # Clear NMI, SMI, INTR fields
  453. movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
  454. leal L22, %esp
  455. jmp stackless_SideBand_Write
  456. L22:
  457. #
  458. # Restore return address
  459. #
  460. movl %ebp, %esp
  461. RET32
  462. IssueWarmReset:
  463. #
  464. # Issue Warm Reset request to Remote Management Unit via iLB
  465. #
  466. movw $(CF9_WARM_RESET), %ax
  467. movw $(ILB_RESET_REG), %dx
  468. outw %ax, %dx
  469. jmp . # Stay here until we are reset.
  470. IssueColdReset:
  471. #
  472. # Issue Cold Reset request to Remote Management Unit via iLB
  473. #
  474. movw $(CF9_COLD_RESET), %ax
  475. movw $(ILB_RESET_REG), %dx
  476. outw %ax, %dx
  477. jmp . # Stay here until we are reset.
  478. #----------------------------------------------------------------------------
  479. #
  480. # Procedure: stackless_SideBand_Read
  481. #
  482. # Input: esp - return address
  483. # ecx[15:8] - Register offset
  484. # ecx[23:16] - Port ID
  485. # ecx[31:24] - Opcode
  486. #
  487. # Output: eax - Data read
  488. #
  489. # Destroys:
  490. # eax
  491. # ebx
  492. # cl
  493. # esi
  494. #
  495. # Description:
  496. # Perform requested sideband read
  497. #
  498. #----------------------------------------------------------------------------
  499. stackless_SideBand_Read:
  500. movl %esp, %esi # Save the return address
  501. #
  502. # Load the SideBand Packet Register to generate the transaction
  503. #
  504. movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
  505. movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
  506. xchgl %ecx, %eax
  507. leal L17, %esp
  508. jmp stackless_PCIConfig_Write
  509. L17:
  510. xchgl %ecx, %eax
  511. #
  512. # Read the SideBand Data Register
  513. #
  514. movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
  515. leal L18, %esp
  516. jmp stackless_PCIConfig_Read
  517. L18:
  518. movl %esi, %esp # Restore the return address
  519. RET32
  520. #----------------------------------------------------------------------------
  521. #
  522. # Procedure: stackless_SideBand_Write
  523. #
  524. # Input: esp - return address
  525. # eax - Data
  526. # ecx[15:8] - Register offset
  527. # ecx[23:16] - Port ID
  528. # ecx[31:24] - Opcode
  529. #
  530. # Output: None
  531. #
  532. # Destroys:
  533. # ebx
  534. # cl
  535. # esi
  536. #
  537. # Description:
  538. # Perform requested sideband write
  539. #
  540. #
  541. #----------------------------------------------------------------------------
  542. stackless_SideBand_Write:
  543. movl %esp, %esi # Save the return address
  544. #
  545. # Load the SideBand Data Register with the data
  546. #
  547. movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
  548. leal L19, %esp
  549. jmp stackless_PCIConfig_Write
  550. L19:
  551. #
  552. # Load the SideBand Packet Register to generate the transaction
  553. #
  554. movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
  555. movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
  556. xchgl %ecx, %eax
  557. leal L20, %esp
  558. jmp stackless_PCIConfig_Write
  559. L20:
  560. xchgl %ecx, %eax
  561. movl %esi, %esp # Restore the return address
  562. RET32
  563. #----------------------------------------------------------------------------
  564. #
  565. # Procedure: stackless_PCIConfig_Write
  566. #
  567. # Input: esp - return address
  568. # eax - Data to write
  569. # ebx - PCI Config Address
  570. #
  571. # Output: None
  572. #
  573. # Destroys:
  574. # dx
  575. #
  576. # Description:
  577. # Perform a DWORD PCI Configuration write
  578. #
  579. #----------------------------------------------------------------------------
  580. stackless_PCIConfig_Write:
  581. #
  582. # Write the PCI Config Address to the address port
  583. #
  584. xchgl %ebx, %eax
  585. movw $(PCI_ADDRESS_PORT), %dx
  586. outl %eax, %dx
  587. xchgl %ebx, %eax
  588. #
  589. # Write the PCI DWORD Data to the data port
  590. #
  591. movw $(PCI_DATA_PORT), %dx
  592. outl %eax, %dx
  593. RET32
  594. #----------------------------------------------------------------------------
  595. #
  596. # Procedure: stackless_PCIConfig_Read
  597. #
  598. # Input: esp - return address
  599. # ebx - PCI Config Address
  600. #
  601. # Output: eax - Data read
  602. #
  603. # Destroys:
  604. # eax
  605. # dx
  606. #
  607. # Description:
  608. # Perform a DWORD PCI Configuration read
  609. #
  610. #----------------------------------------------------------------------------
  611. stackless_PCIConfig_Read:
  612. #
  613. # Write the PCI Config Address to the address port
  614. #
  615. xchgl %ebx, %eax
  616. movw $(PCI_ADDRESS_PORT), %dx
  617. outl %eax, %dx
  618. xchgl %ebx, %eax
  619. #
  620. # Read the PCI DWORD Data from the data port
  621. #
  622. movw $(PCI_DATA_PORT), %dx
  623. inl %dx, %eax
  624. RET32
  625. #
  626. # ROM-based Global-Descriptor Table for the Tiano PEI Phase
  627. #
  628. .align 16
  629. #
  630. # GDT[0]: 000h: Null entry, never used.
  631. #
  632. GDT_BASE:
  633. BootGdtTable:
  634. # null descriptor
  635. .equ NULL_SEL, . - GDT_BASE # Selector [0]
  636. .word 0 # limit 15:0
  637. .word 0 # base 15:0
  638. .byte 0 # base 23:16
  639. .byte 0 # type
  640. .byte 0 # limit 19:16, flags
  641. .byte 0 # base 31:24
  642. # linear data segment descriptor
  643. .equ LINEAR_SEL, . - GDT_BASE # Selector [0x8]
  644. .word 0xFFFF # limit 0xFFFFF
  645. .word 0 # base 0
  646. .byte 0
  647. .byte 0x92 # present, ring 0, data, expand-up, writable
  648. .byte 0xCF # page-granular, 32-bit
  649. .byte 0
  650. # linear code segment descriptor
  651. .equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
  652. .word 0xFFFF # limit 0xFFFFF
  653. .word 0 # base 0
  654. .byte 0
  655. .byte 0x9A # present, ring 0, data, expand-up, writable
  656. .byte 0xCF # page-granular, 32-bit
  657. .byte 0
  658. # system data segment descriptor
  659. .equ SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
  660. .word 0xFFFF # limit 0xFFFFF
  661. .word 0 # base 0
  662. .byte 0
  663. .byte 0x92 # present, ring 0, data, expand-up, writable
  664. .byte 0xCF # page-granular, 32-bit
  665. .byte 0
  666. # system code segment descriptor
  667. .equ SYS_CODE_SEL, . - GDT_BASE
  668. .word 0xFFFF # limit 0xFFFFF
  669. .word 0 # base 0
  670. .byte 0
  671. .byte 0x9A # present, ring 0, data, expand-up, writable
  672. .byte 0xCF # page-granular, 32-bit
  673. .byte 0
  674. # spare segment descriptor
  675. .equ SYS16_CODE_SEL, . - GDT_BASE
  676. .word 0xffff # limit 0xFFFFF
  677. .word 0 # base 0
  678. .byte 0x0f
  679. .byte 0x9b # present, ring 0, data, expand-up, writable
  680. .byte 0 # page-granular, 32-bit
  681. .byte 0
  682. # spare segment descriptor
  683. .equ SYS16_DATA_SEL, . - GDT_BASE
  684. .word 0xffff # limit 0xFFFFF
  685. .word 0 # base 0
  686. .byte 0
  687. .byte 0x93 # present, ring 0, data, expand-up, not-writable
  688. .byte 0 # page-granular, 32-bit
  689. .byte 0
  690. # spare segment descriptor
  691. .equ SPARE5_SEL, . - GDT_BASE
  692. .word 0 # limit 0xFFFFF
  693. .word 0 # base 0
  694. .byte 0
  695. .byte 0 # present, ring 0, data, expand-up, writable
  696. .byte 0 # page-granular, 32-bit
  697. .byte 0
  698. .equ GDT_SIZE, . - GDT_BASE
  699. #
  700. # GDT Descriptor
  701. #
  702. GdtDesc: # GDT descriptor
  703. .word GDT_SIZE - 1
  704. .long BootGdtTable
  705. ProtectedModeEntryLinearAddress:
  706. ProtectedModeEntryLinearOffset:
  707. .long ProtectedModeEntryPoint
  708. .word LINEAR_CODE_SEL