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