1 ; ****************************************************************************
5 ; * Agesa structures and definitions
7 ; * Contains AMD AGESA core interface
9 ; * @xrefitem bom "File Content Label" "Release Content"
11 ; * @e sub-project: Include
12 ; * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 02:16:51 -0700 (Wed, 22 Dec 2010) $
14 ; ****************************************************************************
16 ; Copyright (C) 2012 Advanced Micro Devices, Inc.
17 ; All rights reserved.
19 ; Redistribution and use in source and binary forms, with or without
20 ; modification, are permitted provided that the following conditions are met:
21 ; * Redistributions of source code must retain the above copyright
22 ; notice, this list of conditions and the following disclaimer.
23 ; * Redistributions in binary form must reproduce the above copyright
24 ; notice, this list of conditions and the following disclaimer in the
25 ; documentation and/or other materials provided with the distribution.
26 ; * Neither the name of Advanced Micro Devices, Inc. nor the names of
27 ; its contributors may be used to endorse or promote products derived
28 ; from this software without specific prior written permission.
30 ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
31 ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33 ; DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
34 ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
37 ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 ;*****************************************************************************
43 PARAM1 textequ <[bp+8]>
44 PARAM2 textequ <[bp+12]>
45 PARAM3 textequ <[bp+16]>
46 RETAddress textequ <[bp+4]>
48 AMD_PRIVATE_PARAMS STRUCT
49 Gate16_CS DW ? ; Segment of AMD_BRIDGE_32 and AMD_CALLOUT_16
50 Gate16_SS DW ? ; RM stack segment
51 Router_Seg DW ? ; Segment of oem router
52 Router_Off DW ? ; Offset of oem router
53 AMD_PRIVATE_PARAMS ENDS
55 ; OEM may pre-define the GDT and selector offsets. If they do not, use our defaults.
56 IFNDEF AGESA_SELECTOR_GDT
57 AGESA_SELECTOR_GDT EQU 00h
59 IFNDEF AGESA_SELECTOR_CODE16
60 AGESA_SELECTOR_CODE16 EQU 08h
62 IFNDEF AGESA_SELECTOR_DATA16
63 AGESA_SELECTOR_DATA16 EQU 10h
65 IFNDEF AGESA_SELECTOR_CODE32
66 AGESA_SELECTOR_CODE32 EQU 18h
68 IFNDEF AGESA_SELECTOR_DATA32
69 AGESA_SELECTOR_DATA32 EQU 20h
73 AMD_BRIDGE_32_GDT MACRO GDT_Name:REQ
76 DD 000000000h, 000000000h ; NULL descriptor
77 DD 00000ffffh, 000009b00h ; 16-bit code, fixed up
78 DD 00000ffffh, 000009300h ; 16-bit data, fixed up
79 DD 00000ffffh, 000CF9B00h ; 32-bit protected mode code
80 DD 00000ffffh, 000CF9300h ; 32-bit protected mode data
81 GDT_Length EQU ($-GDT_Name)
85 ;+-------------------------------------------------------------------------
87 ; AMD_BRIDGE_32 - Execute Agesa through Pushhigh interface
90 ; The following steps are taken:
91 ; 1) Enter 32bit Protected Mode (PM32)
93 ; 3) Restore Real Mode (RM)
96 ; [big real mode] : ds, es set to base 0 limit 4G segment
97 ; EDX - if not 0, provides a FAR PTR to oem router (Seg | Offset)
98 ; ESI - configuration block pointer
102 ; ESI - configuration block pointer
103 ; ds, es, fs, gs - Set to 4GB segment limit for Big Real Mode
109 AMD_BRIDGE_32 MACRO GDT_Name
113 local agesaReturnAddress
126 ; Do not use any locals here, BP will be changed frequently during RM->PM32->RM
129 cli ; Disable interrupts during AGESA
130 cld ; Need known direction flag during AGESA
133 ; Save the FAR PTR input parameter
139 ; Determine where our binary file is and get entry point
141 mov edx, (AMD_CONFIG_PARAMS PTR [esi]).ImageBasePtr
142 add edx, (AMD_IMAGE_HEADER PTR [edx]).EntryPointAddress
144 ; Figure out the return address we will use after calling AGESA
145 ; and store it in ebx until we have our stack set up properly
149 add ebx, OFFSET agesaReturnAddress
151 ; Save our current RM stack AND entry EBP
158 ; BEGIN --- STACK MUST BE BALANCED AT THIS POINT --- BEGIN
160 ; Copy the GDT onto the stack for modification
173 ; Patch 16-bit code and data descriptors on stack. We will
174 ; fix up CS and SS for PM16 during the callout if applicable.
180 mov [bp+AGESA_SELECTOR_CODE16+2], ax
182 mov [bp+AGESA_SELECTOR_CODE16+4], al
186 mov [bp+AGESA_SELECTOR_DATA16+2], ax
188 mov [bp+AGESA_SELECTOR_DATA16+4], al
190 ; Need to place Length and Address on GDT
196 push WORD PTR (GDT_Length-1)
205 ; Place PRIVATE DATA on stack DIRECTLY following GDT
206 ; During this routine, stack data is critical. If
207 ; order is changed or additional added, bad things
210 ; HIGHEST PHYSICAL ADDRESS
213 ; ------------------------
216 ; ------------------------ sp + SIZEOF AMD_PRIVATE_PARAMS + (SIZEOF GDT_LENGTH + 6 {size, address})
220 ; | GDT Addr, Length |
221 ; ------------------------ sp + SIZEOF AMD_PRIVATE_PARAMS
224 ; ------------------------ sp
225 ; ------ THEN PUSH -------
226 ; | Return to 16-bit CS |
227 ; | Return to 16-bit Off |
230 ; LOWEST PHYSICAL ADDRESS
233 sub edi, SIZEOF AMD_PRIVATE_PARAMS
235 mov (AMD_PRIVATE_PARAMS PTR ss:[edi]).Gate16_CS, ax
237 mov (AMD_PRIVATE_PARAMS PTR ss:[edi]).Gate16_SS, ax
238 mov (AMD_PRIVATE_PARAMS PTR ss:[edi]).Router_Off, gs
239 mov (AMD_PRIVATE_PARAMS PTR ss:[edi]).Router_Seg, fs
243 ; Save an address for returning to 16 bit real mode on stack,
244 ; we'll use it in a far ret after turning off CR0.PE so that
245 ; we can take our address off and force a far jump. Be sure
246 ; no unexpected data is on the stack after this!
253 ; Convert ss:esp to "flat"
261 mov esp, eax ; Load the zero based ESP
266 mov eax, CR0 ; Get CPU control word 0
267 or al, 01 ; Enable CPU protected mode
268 mov CR0, eax ; Write back to CPU control word 0
273 ; 16-bit protected mode
275 mov ax, AGESA_SELECTOR_DATA32
282 ; Push our parameters RIGHT TO LEFT, and then return address
284 push esi ; AGESA configuration block pointer (data)
285 push ebx ; after AGESA return offset (32PM flat) - consumed by dispatcher ret
286 pushd AGESA_SELECTOR_CODE32 ; AGESA entry selector (32PM flat)
287 push edx ; AGESA entry point (32PM flat)
290 retf ; <><><> Enter AGESA 32-bit code!!! <><><>
294 ; Returns from the Agesa 32-bit code still PM32
297 DD OFFSET leave32bitPM
298 DW AGESA_SELECTOR_CODE16
304 add esp, 4 ; +4 to remove our config block pointer
306 ; Eax reserve AGESA_STATUS return code, save it
310 ; Turn off CR0.PE, restore 64K stack limit
314 mov ax, AGESA_SELECTOR_DATA16
318 and al, NOT 1 ; Disable protected mode
319 mov CR0, eax ; Write back CR0.PE
321 ; Jump far to enter RM, we saved this address on the stack
322 ; already. Hopefully stack is balanced through AGESA
323 ; nor were any params added by pushing them on the stack and
324 ; not removing them between BEGIN-END comments.
330 ; Set segments registers for big real mode before returning
338 ; Discard GDT, +6 for GDT pointer/size, privates
340 add esp, GDT_Length + 6 + SIZEOF AMD_PRIVATE_PARAMS
342 ; Restore real mode stack and entry EBP
349 ; Restore AGESA_STATUS return code to eax
353 ; END --- STACK MUST BE BALANCED TO THIS POINT --- END
366 ;+-------------------------------------------------------------------------
368 ; AMD_CALLOUT_16 - Execute Callback from Pushhigh interface
371 ; The following steps are taken:
373 ; 2) Setup stack, get private params
376 ; 5) Call oemCallout OR oem router
378 ; 7) Return to Agesa PH
381 ; [32-bit protected mode]
384 ; [esp+16] Configuration Block
385 ; [esp+4] return address to Agesa
388 ; [32-bit protected mode]
393 AMD_CALLOUT_16 MACRO LocalOemCalloutRouter
395 ; Note that we are still PM32, so MASM may work strangely
398 push bp ; Save our original SP to access params
409 DW AGESA_SELECTOR_CODE16
413 ; PM16 CS, but still PM32 SS, as we need to access our private params
414 ; before we enter RM.
416 ; Note: we are working below the stack temporarily, and and it will
417 ; not affect our ability to get entry params
422 ; SGDT will give us the original location of the GDT on our CAS stack.
423 ; We need this value because our private parameters are located just
427 sub edi, GDT_Length + 6
428 sgdt FWORD PTR [edi] ; [edi] = word size, dword address
429 mov edi, DWORD PTR [edi+2] ; Get the PM32 address only
430 sub edi, SIZEOF AMD_PRIVATE_PARAMS + 6
432 ; cx = code segment of this code in RM
433 ; dx = stack segment of CAS in RM
434 ; fs = code segment of oem router (save for later)
435 ; gs = offset of oem router (save for later)
436 ; fs and gs are loaded after switch to real mode because we can't
437 ; use them as scratch pad registers in protected mode
439 mov cx, (AMD_PRIVATE_PARAMS PTR ss:[edi]).Gate16_CS
440 mov dx, (AMD_PRIVATE_PARAMS PTR ss:[edi]).Gate16_SS
442 mov eax, edi ; Save edi in eax for after RM switch
443 mov edi, esp ; Save our current ESP for RM
450 ; We had been accessing the stack in PM32, we will now change to PM16 so we
451 ; will make the stack segment 64KB limit so SP needs to be fixed made PM16
454 mov bx, AGESA_SELECTOR_DATA16
458 ; Save the RM segment and RM offset of the jump we will need to make in
459 ; order to enter RM so that code in this segment is relocatable.
461 ; BEGIN --- Don't unbalance the stack --- BEGIN
468 mov CR0, ebx ; CR0.PE cleared
470 ; Far jump to clear segment descriptor cache and enter RM
476 ; We are in RM, setup RM stack
478 movzx ebx, dx ; Get RM SS in ebx
479 shl ebx, 4 ; Get our stack top on entry in EBP to
480 sub ebp, ebx ; access our entry parameters
481 sub eax, ebx ; save copy of parameters address
482 mov ss, dx ; Set stack segment
484 ; We are going to figure out the address to use when we return
485 ; and have to go back into PM32 while we have access to it
487 movzx ebx, cx ; Get original CS in ebx
489 add ebx, OFFSET PM32Entry
491 ; Now we put our data, func, block params into calling convention
496 ; ESI = config pointer
498 mov ecx, PARAM1 ; Func
499 mov edx, PARAM2 ; Data
500 mov esi, PARAM3 ; pointer
502 push ebx ; Save PM32 mode switch address
503 push edi ; Save PM32 stack pointer
506 ; Get Router Function Address
509 mov ax, (AMD_PRIVATE_PARAMS PTR ss:[edi]).Router_Seg
511 mov ax, (AMD_PRIVATE_PARAMS PTR ss:[edi]).Router_Off
514 mov eax, AGESA_UNSUPPORTED ; Default return value
516 ; If AMD_BRIDGE_32 EDX == 0 call oemCallout
517 ; otherwise call FAR PTR EDX
520 ; sp+2 - EDI aka PM32 stack address
521 ; sp+4 - address of PM32Entry in PM32
528 call LocalOemCalloutRouter
531 ; Make far call to Router function
534 push offset CalloutReturn
540 ; Restore PM32 esp from RM stack
543 pop edi ; Our PM32 stack pointer
544 pop edx ; Our PM32 mode switch address
547 or bl, 1 ; CR0.PE set
550 mov ebx, AGESA_SELECTOR_DATA32
551 pushd AGESA_SELECTOR_CODE32 ; PM32 selector
552 push edx ; PM32 entry point
555 retf ; Far jump to enter PM32
559 ; END --- Don't unbalance the stack --- END
560 ; We are now PM32, so remember MASM is assembling in 16-bit again
576 ; EXIT AMD_CALLOUT_16