7 * Contains interface to the AMD AGESA library
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 48409 $ @e \$Date: 2011-03-08 11:19:40 -0600 (Tue, 08 Mar 2011) $
16 ******************************************************************************
18 * Copyright (c) 2008 - 2011, Advanced Micro Devices, Inc.
19 * 2013 - 2014, Sage Electronic Engineering, LLC
20 * All rights reserved.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are met:
24 * * Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * * Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
30 * its contributors may be used to endorse or promote products derived
31 * from this software without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
37 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 ******************************************************************************
47 #include <cpuRegisters.h>
48 #include <cpu/x86/mp.h>
49 #include <cpu/x86/cache.h>
55 RDATA_GROUP (G1_PEICC
)
57 #if !defined(AMDLIB_OPTIMIZE)
58 #define AMDLIB_OPTIMIZE
61 #define FILECODE LIB_AMDLIB_FILECODE
66 OUT UINT64
*MmioAddress
,
68 IN AMD_CONFIG_PARAMS
*StdHeader
73 LibAmdGetDataFromPtr (
74 IN ACCESS_WIDTH AccessWidth
,
76 IN CONST VOID
*DataMask
,
78 OUT UINT32
*TempDataMask
89 IN UINT32 CpuidFcnAddress
,
104 return __inbyte (Address
);
113 return __inword (Address
);
122 return __indword (Address
);
132 __outbyte (Address
, Data
);
142 __outword (Address
, Data
);
152 __outdword (Address
, Data
);
162 hwcr
= __readmsr (0xC0010015);
163 __writemsr (0xC0010015, hwcr
| 1 << 17);
164 __writemsr (0xC0000100, address
);
176 __writemsr (0xC0010015, value
);
187 if ((Address
>> 32) == 0) {
188 return *(volatile UINT8
*) (UINTN
) Address
;
190 hwcrSave
= SetFsBase (Address
);
191 dataRead
= __readfsbyte (0);
192 RestoreHwcr (hwcrSave
);
204 if ((Address
>> 32) == 0) {
205 return *(volatile UINT16
*) (UINTN
) Address
;
207 hwcrSave
= SetFsBase (Address
);
208 dataRead
= __readfsword (0);
209 RestoreHwcr (hwcrSave
);
221 if ((Address
>> 32) == 0) {
222 return *(volatile UINT32
*) (UINTN
) Address
;
224 hwcrSave
= SetFsBase (Address
);
225 dataRead
= __readfsdword (0);
226 RestoreHwcr (hwcrSave
);
237 if ((Address
>> 32) == 0){
238 *(volatile UINT8
*) (UINTN
) Address
= Data
;
242 hwcrSave
= SetFsBase (Address
);
243 __writefsbyte (0, Data
);
244 RestoreHwcr (hwcrSave
);
255 if ((Address
>> 32) == 0){
256 *(volatile UINT16
*) (UINTN
) Address
= Data
;
260 hwcrSave
= SetFsBase (Address
);
261 __writefsword (0, Data
);
262 RestoreHwcr (hwcrSave
);
273 if ((Address
>> 32) == 0){
274 *(volatile UINT32
*) (UINTN
) Address
= Data
;
278 hwcrSave
= SetFsBase (Address
);
279 __writefsdword (0, Data
);
280 RestoreHwcr (hwcrSave
);
294 *Value
= __readcr4 ();
297 *Value
= __readdr (0);
300 *Value
= __readdr (1);
303 *Value
= __readdr (2);
306 *Value
= __readdr (3);
309 *Value
= __readdr (7);
329 __writedr (0, Value
);
332 __writedr (1, Value
);
335 __writedr (2, Value
);
338 __writedr (3, Value
);
341 __writedr (7, Value
);
350 LibAmdWriteBackInvalidateCache (
359 LibAmdHDTBreakPoint (
363 __writemsr (0xC001100A, __readmsr (0xC001100A) | 1);
364 __debugbreak (); // do you really need icebp? If so, go back to asm code
369 LibAmdBitScanForward (
374 for (Index
= 0; Index
< 32; Index
++){
375 if (value
& (1 << Index
)) break;
377 return (UINT8
) Index
;
382 LibAmdBitScanReverse (
388 if (value
& (1 << 31))
394 } while (value
!= 0);
396 return 0xFF; /* Error code indicating no bit found */
402 IN UINT32 MsrAddress
,
404 IN OUT AMD_CONFIG_PARAMS
*ConfigPtr
407 if ((MsrAddress
== 0xFFFFFFFF) || (MsrAddress
== 0x00000000)) {
408 IdsErrorStop(MsrAddress
);
410 *Value
= __readmsr (MsrAddress
);
416 IN UINT32 MsrAddress
,
418 IN OUT AMD_CONFIG_PARAMS
*ConfigPtr
421 __writemsr (MsrAddress
, *Value
);
425 void LibAmdCpuidRead (
426 IN UINT32 CpuidFcnAddress
,
427 OUT CPUID_DATA
* Value
,
428 IN OUT AMD_CONFIG_PARAMS
*ConfigPtr
431 __cpuid ((int *)Value
, CpuidFcnAddress
);
445 LibAmdSimNowEnterDebugger (
449 STATIC CONST UINT8 opcode
[] = {0x60, // pushad
450 0xBB, 0x02, 0x00, 0x00, 0x00, // mov ebx, 2
451 0xB8, 0x0B, 0xD0, 0xCC, 0xBA, // mov eax, 0xBACCD00B
456 ((VOID (*)(VOID
)) (size_t) opcode
) (); // call the function
467 __outdword ((UINT16
) Addr
, Value
);
476 VOLATILE UINTN x
= 1;
491 hwcrSave
= SetFsBase (Address
);
492 for (Index
= 0; Index
< Count
; Index
++){
494 clflush(&address32
[Index
* 64]);
496 RestoreHwcr (hwcrSave
);
507 __asm__
volatile ("finit");
509 /*---------------------------------------------------------------------------------------*/
514 * @param[in] AccessWidth Access width
515 * @param[in] IoAddress IO port address
516 * @param[in] Value Pointer to save data
517 * @param[in] StdHeader Standard configuration header
522 IN ACCESS_WIDTH AccessWidth
,
525 IN OUT AMD_CONFIG_PARAMS
*StdHeader
528 switch (AccessWidth
) {
530 case AccessS3SaveWidth8
:
531 *(UINT8
*) Value
= ReadIo8 (IoAddress
);
534 case AccessS3SaveWidth16
:
535 *(UINT16
*) Value
= ReadIo16 (IoAddress
);
538 case AccessS3SaveWidth32
:
539 *(UINT32
*) Value
= ReadIo32 (IoAddress
);
547 /*---------------------------------------------------------------------------------------*/
552 * @param[in] AccessWidth Access width
553 * @param[in] IoAddress IO port address
554 * @param[in] Value Pointer to data
555 * @param[in] StdHeader Standard configuration header
560 IN ACCESS_WIDTH AccessWidth
,
562 IN CONST VOID
*Value
,
563 IN OUT AMD_CONFIG_PARAMS
*StdHeader
566 switch (AccessWidth
) {
568 case AccessS3SaveWidth8
:
569 WriteIo8 (IoAddress
, *(UINT8
*) Value
);
572 case AccessS3SaveWidth16
:
573 WriteIo16 (IoAddress
, *(UINT16
*) Value
);
576 case AccessS3SaveWidth32
:
577 WriteIo32 (IoAddress
, *(UINT32
*) Value
);
585 /*---------------------------------------------------------------------------------------*/
587 * IO read modify write
590 * @param[in] AccessWidth Access width
591 * @param[in] IoAddress IO address
592 * @param[in] Data OR data
593 * @param[in] DataMask Mask to be used before data write back to register.
594 * @param[in] StdHeader Standard configuration header
599 IN ACCESS_WIDTH AccessWidth
,
602 IN CONST VOID
*DataMask
,
603 IN OUT AMD_CONFIG_PARAMS
*StdHeader
609 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
610 LibAmdIoRead (AccessWidth
, IoAddress
, &Value
, NULL
);
611 Value
= (Value
& (~TempMask
)) | TempData
;
612 LibAmdIoWrite (AccessWidth
, IoAddress
, &Value
, NULL
);
615 /*---------------------------------------------------------------------------------------*/
619 * Poll register until (RegisterValue & DataMask) == Data
621 * @param[in] AccessWidth Access width
622 * @param[in] IoAddress IO address
623 * @param[in] Data Data to compare
624 * @param[in] DataMask And mask
625 * @param[in] Delay Poll for time in 100ns (not supported)
626 * @param[in] StdHeader Standard configuration header
631 IN ACCESS_WIDTH AccessWidth
,
634 IN CONST VOID
*DataMask
,
636 IN OUT AMD_CONFIG_PARAMS
*StdHeader
642 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
644 LibAmdIoRead (AccessWidth
, IoAddress
, &Value
, NULL
);
645 } while (TempData
!= (Value
& TempMask
));
648 /*---------------------------------------------------------------------------------------*/
653 * @param[in] AccessWidth Access width
654 * @param[in] MemAddress Memory address
655 * @param[in] Value Pointer to data
656 * @param[in] StdHeader Standard configuration header
661 IN ACCESS_WIDTH AccessWidth
,
662 IN UINT64 MemAddress
,
664 IN OUT AMD_CONFIG_PARAMS
*StdHeader
667 switch (AccessWidth
) {
669 case AccessS3SaveWidth8
:
670 *(UINT8
*) Value
= Read64Mem8 (MemAddress
);
673 case AccessS3SaveWidth16
:
674 *(UINT16
*) Value
= Read64Mem16 (MemAddress
);
677 case AccessS3SaveWidth32
:
678 *(UINT32
*) Value
= Read64Mem32 (MemAddress
);
686 /*---------------------------------------------------------------------------------------*/
691 * @param[in] AccessWidth Access width
692 * @param[in] MemAddress Memory address
693 * @param[in] Value Pointer to data
694 * @param[in] StdHeader Standard configuration header
699 IN ACCESS_WIDTH AccessWidth
,
700 IN UINT64 MemAddress
,
701 IN CONST VOID
*Value
,
702 IN OUT AMD_CONFIG_PARAMS
*StdHeader
706 switch (AccessWidth
) {
708 case AccessS3SaveWidth8
:
709 Write64Mem8 (MemAddress
, *((UINT8
*) Value
));
712 case AccessS3SaveWidth16
:
713 Write64Mem16 (MemAddress
, *((UINT16
*) Value
));
716 case AccessS3SaveWidth32
:
717 Write64Mem32 (MemAddress
, *((UINT32
*) Value
));
724 /*---------------------------------------------------------------------------------------*/
726 * Memory/MMIO read modify write
729 * @param[in] AccessWidth Access width
730 * @param[in] MemAddress Memory address
731 * @param[in] Data OR data
732 * @param[in] DataMask Mask to be used before data write back to register.
733 * @param[in] StdHeader Standard configuration header
738 IN ACCESS_WIDTH AccessWidth
,
739 IN UINT64 MemAddress
,
741 IN CONST VOID
*DataMask
,
742 IN OUT AMD_CONFIG_PARAMS
*StdHeader
748 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
749 LibAmdMemRead (AccessWidth
, MemAddress
, &Value
, NULL
);
750 Value
= (Value
& (~TempMask
)) | TempData
;
751 LibAmdMemWrite (AccessWidth
, MemAddress
, &Value
, NULL
);
754 /*---------------------------------------------------------------------------------------*/
758 * Poll register until (RegisterValue & DataMask) == Data
760 * @param[in] AccessWidth Access width
761 * @param[in] MemAddress Memory address
762 * @param[in] Data Data to compare
763 * @param[in] DataMask AND mask
764 * @param[in] Delay Poll for time in 100ns (not supported)
765 * @param[in] StdHeader Standard configuration header
770 IN ACCESS_WIDTH AccessWidth
,
771 IN UINT64 MemAddress
,
773 IN CONST VOID
*DataMask
,
775 IN OUT AMD_CONFIG_PARAMS
*StdHeader
781 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
783 LibAmdMemRead (AccessWidth
, MemAddress
, &Value
, NULL
);
784 } while (TempData
!= (Value
& TempMask
));
787 /*---------------------------------------------------------------------------------------*/
789 * Read PCI config space
792 * @param[in] AccessWidth Access width
793 * @param[in] PciAddress Pci address
794 * @param[in] Value Pointer to data
795 * @param[in] StdHeader Standard configuration header
800 IN ACCESS_WIDTH AccessWidth
,
801 IN PCI_ADDR PciAddress
,
803 IN OUT AMD_CONFIG_PARAMS
*StdHeader
806 UINT32 LegacyPciAccess
;
809 UINT64 RMWritePrevious
;
813 ASSERT (PciAddress
.AddressValue
!= ILLEGAL_SBDFO
);
814 if (!GetPciMmioAddress (&MMIOAddress
, &MMIOSize
, NULL
)) {
815 // We need to convert our "portable" PCI address into a "real" PCI access
816 LegacyPciAccess
= ((1 << 31) + (PciAddress
.Address
.Register
& 0xFC) + (PciAddress
.Address
.Function
<< 8) + (PciAddress
.Address
.Device
<< 11) + (PciAddress
.Address
.Bus
<< 16) + ((PciAddress
.Address
.Register
& 0xF00) << (24 - 8)));
817 if (PciAddress
.Address
.Register
<= 0xFF) {
818 LibAmdIoWrite (AccessWidth32
, IOCF8
, &LegacyPciAccess
, NULL
);
819 LibAmdIoRead (AccessWidth
, IOCFC
+ (UINT16
) (PciAddress
.Address
.Register
& 0x3), Value
, NULL
);
821 LibAmdMsrRead (NB_CFG
, &RMWritePrevious
, NULL
);
822 RMWrite
= RMWritePrevious
| 0x0000400000000000;
823 LibAmdMsrWrite (NB_CFG
, &RMWrite
, NULL
);
824 LibAmdIoWrite (AccessWidth32
, IOCF8
, &LegacyPciAccess
, NULL
);
825 LibAmdIoRead (AccessWidth
, IOCFC
+ (UINT16
) (PciAddress
.Address
.Register
& 0x3), Value
, NULL
);
826 LibAmdMsrWrite (NB_CFG
, &RMWritePrevious
, NULL
);
828 //IDS_HDT_CONSOLE (LIB_PCI_RD, "~PCI RD %08x = %08x\n", LegacyPciAccess, *(UINT32 *)Value);
830 // Setup the MMIO address
831 ASSERT ((MMIOAddress
+ MMIOSize
) > (MMIOAddress
+ (PciAddress
.AddressValue
& 0x0FFFFFFF)));
832 MMIOAddress
+= (PciAddress
.AddressValue
& 0x0FFFFFFF);
833 LibAmdMemRead (AccessWidth
, MMIOAddress
, Value
, NULL
);
834 //IDS_HDT_CONSOLE (LIB_PCI_RD, "~MMIO RD %08x = %08x\n", (UINT32) MMIOAddress, *(UINT32 *)Value);
838 /*---------------------------------------------------------------------------------------*/
840 * Write PCI config space
843 * @param[in] AccessWidth Access width
844 * @param[in] PciAddress Pci address
845 * @param[in] Value Pointer to data
846 * @param[in] StdHeader Standard configuration header
851 IN ACCESS_WIDTH AccessWidth
,
852 IN PCI_ADDR PciAddress
,
853 IN CONST VOID
*Value
,
854 IN OUT AMD_CONFIG_PARAMS
*StdHeader
857 UINT32 LegacyPciAccess
;
860 UINT64 RMWritePrevious
;
864 ASSERT (PciAddress
.AddressValue
!= ILLEGAL_SBDFO
);
865 if (!GetPciMmioAddress (&MMIOAddress
, &MMIOSize
, NULL
)) {
866 // We need to convert our "portable" PCI address into a "real" PCI access
867 LegacyPciAccess
= ((1 << 31) + (PciAddress
.Address
.Register
& 0xFC) + (PciAddress
.Address
.Function
<< 8) + (PciAddress
.Address
.Device
<< 11) + (PciAddress
.Address
.Bus
<< 16) + ((PciAddress
.Address
.Register
& 0xF00) << (24 - 8)));
868 if (PciAddress
.Address
.Register
<= 0xFF) {
869 LibAmdIoWrite (AccessWidth32
, IOCF8
, &LegacyPciAccess
, NULL
);
870 LibAmdIoWrite (AccessWidth
, IOCFC
+ (UINT16
) (PciAddress
.Address
.Register
& 0x3), Value
, NULL
);
872 LibAmdMsrRead (NB_CFG
, &RMWritePrevious
, NULL
);
873 RMWrite
= RMWritePrevious
| 0x0000400000000000;
874 LibAmdMsrWrite (NB_CFG
, &RMWrite
, NULL
);
875 LibAmdIoWrite (AccessWidth32
, IOCF8
, &LegacyPciAccess
, NULL
);
876 LibAmdIoWrite (AccessWidth
, IOCFC
+ (UINT16
) (PciAddress
.Address
.Register
& 0x3), Value
, NULL
);
877 LibAmdMsrWrite (NB_CFG
, &RMWritePrevious
, NULL
);
879 //IDS_HDT_CONSOLE (LIB_PCI_WR, "~PCI WR %08x = %08x\n", LegacyPciAccess, *(UINT32 *)Value);
880 //printk(BIOS_DEBUG, "~PCI WR %08x = %08x\n", LegacyPciAccess, *(UINT32 *)Value);
881 //printk(BIOS_DEBUG, "LibAmdPciWrite\n");
883 // Setup the MMIO address
884 ASSERT ((MMIOAddress
+ MMIOSize
) > (MMIOAddress
+ (PciAddress
.AddressValue
& 0x0FFFFFFF)));
885 MMIOAddress
+= (PciAddress
.AddressValue
& 0x0FFFFFFF);
886 LibAmdMemWrite (AccessWidth
, MMIOAddress
, Value
, NULL
);
887 //IDS_HDT_CONSOLE (LIB_PCI_WR, "~MMIO WR %08x = %08x\n", (UINT32) MMIOAddress, *(UINT32 *)Value);
888 //printk(BIOS_DEBUG, "~MMIO WR %08x = %08x\n", (UINT32) MMIOAddress, *(UINT32 *)Value);
889 //printk(BIOS_DEBUG, "LibAmdPciWrite mmio\n");
893 /*---------------------------------------------------------------------------------------*/
895 * PCI read modify write
898 * @param[in] AccessWidth Access width
899 * @param[in] PciAddress Pci address
900 * @param[in] Data OR Data
901 * @param[in] DataMask Mask to be used before data write back to register.
902 * @param[in] StdHeader Standard configuration header
907 IN ACCESS_WIDTH AccessWidth
,
908 IN PCI_ADDR PciAddress
,
910 IN CONST VOID
*DataMask
,
911 IN OUT AMD_CONFIG_PARAMS
*StdHeader
917 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
918 LibAmdPciRead (AccessWidth
, PciAddress
, &Value
, NULL
);
919 Value
= (Value
& (~TempMask
)) | TempData
;
920 LibAmdPciWrite (AccessWidth
, PciAddress
, &Value
, NULL
);
923 /*---------------------------------------------------------------------------------------*/
925 * Poll PCI config space register
927 * Poll register until (RegisterValue & DataMask) == Data
929 * @param[in] AccessWidth Access width
930 * @param[in] PciAddress Pci address
931 * @param[in] Data Data to compare
932 * @param[in] DataMask AND mask
933 * @param[in] Delay Poll for time in 100ns (not supported)
934 * @param[in] StdHeader Standard configuration header
939 IN ACCESS_WIDTH AccessWidth
,
940 IN PCI_ADDR PciAddress
,
942 IN CONST VOID
*DataMask
,
944 IN OUT AMD_CONFIG_PARAMS
*StdHeader
950 LibAmdGetDataFromPtr (AccessWidth
, Data
, DataMask
, &TempData
, &TempMask
);
952 LibAmdPciRead (AccessWidth
, PciAddress
, &Value
, NULL
);
953 } while (TempData
!= (Value
& TempMask
));
956 /*---------------------------------------------------------------------------------------*/
958 * Get MMIO base address for PCI accesses
960 * @param[out] MmioAddress PCI MMIO base address
961 * @param[out] MmioSize Size of region in bytes
962 * @param[in] StdHeader Standard configuration header
964 * @retval TRUE MmioAddress/MmioSize are valid
969 OUT UINT64
*MmioAddress
,
970 OUT UINT32
*MmioSize
,
971 IN AMD_CONFIG_PARAMS
*StdHeader
974 BOOLEAN MmioIsEnabled
;
976 UINT64 LocalMsrRegister
;
978 MmioIsEnabled
= FALSE
;
979 LibAmdMsrRead (MSR_MMIO_Cfg_Base
, &LocalMsrRegister
, NULL
);
980 if ((LocalMsrRegister
& BIT0
) != 0) {
981 *MmioAddress
= LocalMsrRegister
& 0xFFFFFFFFFFF00000;
982 EncodedSize
= (UINT32
) ((LocalMsrRegister
& 0x3C) >> 2);
983 *MmioSize
= ((1 << EncodedSize
) * 0x100000);
984 MmioIsEnabled
= TRUE
;
986 return MmioIsEnabled
;
989 /*---------------------------------------------------------------------------------------*/
991 * Read field of PCI config register.
995 * @param[in] Address Pci address (register must be DWORD aligned)
996 * @param[in] Highbit High bit position of the field in DWORD
997 * @param[in] Lowbit Low bit position of the field in DWORD
998 * @param[out] Value Pointer to data
999 * @param[in] StdHeader Standard configuration header
1003 IN PCI_ADDR Address
,
1007 IN AMD_CONFIG_PARAMS
*StdHeader
1010 ASSERT (Highbit
< 32 && Lowbit
< 32 && Highbit
>= Lowbit
&& (Address
.AddressValue
& 3) == 0);
1012 LibAmdPciRead (AccessWidth32
, Address
, Value
, NULL
);
1013 *Value
>>= Lowbit
; // Shift
1015 // A 1 << 32 == 1 << 0 due to x86 SHL instruction, so skip if that is the case
1017 if ((Highbit
- Lowbit
) != 31) {
1018 *Value
&= (((UINT32
) 1 << (Highbit
- Lowbit
+ 1)) - 1);
1022 /*---------------------------------------------------------------------------------------*/
1024 * Write field of PCI config register.
1028 * @param[in] Address Pci address (register must be DWORD aligned)
1029 * @param[in] Highbit High bit position of the field in DWORD
1030 * @param[in] Lowbit Low bit position of the field in DWORD
1031 * @param[in] Value Pointer to data
1032 * @param[in] StdHeader Standard configuration header
1035 LibAmdPciWriteBits (
1036 IN PCI_ADDR Address
,
1039 IN CONST UINT32
*Value
,
1040 IN AMD_CONFIG_PARAMS
*StdHeader
1046 ASSERT (Highbit
< 32 && Lowbit
< 32 && Highbit
>= Lowbit
&& (Address
.AddressValue
& 3) == 0);
1048 // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
1050 if ((Highbit
- Lowbit
) != 31) {
1051 Mask
= (((UINT32
) 1 << (Highbit
- Lowbit
+ 1)) - 1);
1053 Mask
= (UINT32
) 0xFFFFFFFF;
1056 LibAmdPciRead (AccessWidth32
, Address
, &Temp
, NULL
);
1057 Temp
&= ~(Mask
<< Lowbit
);
1058 Temp
|= (*Value
& Mask
) << Lowbit
;
1059 LibAmdPciWrite (AccessWidth32
, Address
, &Temp
, NULL
);
1062 /*---------------------------------------------------------------------------------------*/
1064 * Locate next capability pointer
1066 * Given a SBDFO this routine will find the next PCI capabilities list entry.
1067 * if the end of the list is reached, or if a problem is detected, then ILLEGAL_SBDFO is
1069 * To start a new search from the head of the list, specify a SBDFO with an offset of zero.
1071 * @param[in,out] Address Pci address
1072 * @param[in] StdHeader Standard configuration header
1076 LibAmdPciFindNextCap (
1077 IN OUT PCI_ADDR
*Address
,
1078 IN AMD_CONFIG_PARAMS
*StdHeader
1084 PCI_ADDR TempAddress
;
1086 ASSERT (Address
!= NULL
);
1087 ASSERT (*(UINT32
*) Address
!= ILLEGAL_SBDFO
);
1089 Base
.AddressValue
= Address
->AddressValue
;
1090 Offset
= Base
.Address
.Register
;
1091 Base
.Address
.Register
= 0;
1093 Address
->AddressValue
= (UINT32
) ILLEGAL_SBDFO
;
1095 // Verify that the SBDFO points to a valid PCI device SANITY CHECK
1096 LibAmdPciRead (AccessWidth32
, Base
, &Temp
, NULL
);
1097 if (Temp
== 0xFFFFFFFF) {
1099 return; // There is no device at this address
1102 // Verify that the device supports a capability list
1103 TempAddress
.AddressValue
= Base
.AddressValue
+ 0x04;
1104 LibAmdPciReadBits (TempAddress
, 20, 20, &Temp
, NULL
);
1106 return; // This PCI device does not support capability lists
1110 // If we are continuing on an existing list
1111 TempAddress
.AddressValue
= Base
.AddressValue
+ Offset
;
1112 LibAmdPciReadBits (TempAddress
, 15, 8, &Temp
, NULL
);
1114 // We are starting on a new list
1115 TempAddress
.AddressValue
= Base
.AddressValue
+ 0x34;
1116 LibAmdPciReadBits (TempAddress
, 7, 0, &Temp
, NULL
);
1120 return; // We have reached the end of the capabilities list
1123 // Error detection and recovery- The statement below protects against
1124 // PCI devices with broken PCI capabilities lists. Detect a pointer
1125 // that is not uint32 aligned, points into the first 64 reserved DWORDs
1126 // or points back to itself.
1127 if (((Temp
& 3) != 0) || (Temp
== Offset
) || (Temp
< 0x40)) {
1132 Address
->AddressValue
= Base
.AddressValue
+ Temp
;
1136 /*---------------------------------------------------------------------------------------*/
1138 * Set memory with value
1141 * @param[in,out] Destination Pointer to memory range
1142 * @param[in] Value Value to set memory with
1143 * @param[in] FillLength Size of the memory range
1144 * @param[in] StdHeader Standard configuration header (Optional)
1148 IN VOID
*Destination
,
1150 IN UINTN FillLength
,
1151 IN OUT AMD_CONFIG_PARAMS
*StdHeader
1156 while ((FillLength
--) != 0) {
1161 /*---------------------------------------------------------------------------------------*/
1166 * @param[in,out] Destination Pointer to destination buffer
1167 * @param[in] Source Pointer to source buffer
1168 * @param[in] CopyLength buffer length
1169 * @param[in] StdHeader Standard configuration header (Optional)
1173 IN VOID
*Destination
,
1174 IN CONST VOID
*Source
,
1175 IN UINTN CopyLength
,
1176 IN OUT AMD_CONFIG_PARAMS
*StdHeader
1180 CONST UINT8
*SourcePtr
;
1183 while ((CopyLength
--) != 0) {
1184 *Dest
++ = *SourcePtr
++;
1188 /*---------------------------------------------------------------------------------------*/
1190 * Verify checksum of binary image (B1/B2/B3)
1193 * @param[in] ImagePtr Pointer to image start
1194 * @retval TRUE Checksum valid
1195 * @retval FALSE Checksum invalid
1198 LibAmdVerifyImageChecksum (
1199 IN CONST VOID
*ImagePtr
1202 // Assume ImagePtr points to the binary start ($AMD)
1203 // Checksum is on an even boundary in AMD_IMAGE_HEADER
1210 i
= ((AMD_IMAGE_HEADER
*) ImagePtr
)->ImageSize
;
1213 Sum
= Sum
+ *((UINT16
*)ImagePtr
);
1214 ImagePtr
= (VOID
*) ((UINT8
*)ImagePtr
+ 2);
1218 Sum
= Sum
+ *((UINT8
*) ImagePtr
);
1221 return (Sum
== 0)?TRUE
:FALSE
;
1224 /*---------------------------------------------------------------------------------------*/
1226 * Locate AMD binary image that contain specific module
1229 * @param[in] StartAddress Pointer to start range
1230 * @param[in] EndAddress Pointer to end range
1231 * @param[in] Alignment Image address alignment
1232 * @param[in] ModuleSignature Module signature.
1233 * @retval NULL if image not found
1234 * @retval pointer to image header
1238 IN CONST VOID
*StartAddress
,
1239 IN CONST VOID
*EndAddress
,
1240 IN UINT32 Alignment
,
1241 IN CONST CHAR8 ModuleSignature
[8]
1245 CONST UINT8
*CurrentPtr
= StartAddress
;
1246 AMD_MODULE_HEADER
*ModuleHeaderPtr
;
1247 CONST UINT64 SearchStr
= *((UINT64
*)ModuleSignature
);
1249 // Search from start to end incrementing by alignment
1250 while ((CurrentPtr
>= (UINT8
*) StartAddress
) && (CurrentPtr
< (UINT8
*) EndAddress
)) {
1251 // First find a binary image
1252 if (IMAGE_SIGNATURE
== *((UINT32
*) CurrentPtr
)) {
1253 // TODO Figure out a way to fix the AGESA binary checksum
1254 // if (LibAmdVerifyImageChecksum (CurrentPtr)) {
1255 // If we have a valid image, search module linked list for a match
1256 ModuleHeaderPtr
= (AMD_MODULE_HEADER
*)(((AMD_IMAGE_HEADER
*) CurrentPtr
)->ModuleInfoOffset
);
1257 while ((ModuleHeaderPtr
!= NULL
) &&
1258 (MODULE_SIGNATURE
== *((UINT32
*)&(ModuleHeaderPtr
->ModuleHeaderSignature
)))) {
1259 if (SearchStr
== *((UINT64
*)&(ModuleHeaderPtr
->ModuleIdentifier
))) {
1262 ModuleHeaderPtr
= (AMD_MODULE_HEADER
*)ModuleHeaderPtr
->NextBlock
;
1266 CurrentPtr
+= Alignment
;
1271 /*---------------------------------------------------------------------------------------*/
1273 * Returns the package type mask for the processor
1276 * @param[in] StdHeader Standard configuration header (Optional)
1279 // Returns the package type mask for the processor
1281 LibAmdGetPackageType (
1282 IN AMD_CONFIG_PARAMS
*StdHeader
1285 UINT32 ProcessorPackageType
;
1288 LibAmdCpuidRead (0x80000001, &CpuId
, NULL
);
1289 ProcessorPackageType
= (UINT32
) (CpuId
.EBX_Reg
>> 28) & 0xF; // bit 31:28
1290 return (UINT32
) (1 << ProcessorPackageType
);
1293 /*---------------------------------------------------------------------------------------*/
1295 * Returns the package type mask for the processor
1298 * @param[in] AccessWidth Access width
1299 * @param[in] Data data
1300 * @param[in] DataMask data
1301 * @param[out] TemData typecast data
1302 * @param[out] TempDataMask typecast data
1307 LibAmdGetDataFromPtr (
1308 IN ACCESS_WIDTH AccessWidth
,
1309 IN CONST VOID
*Data
,
1310 IN CONST VOID
*DataMask
,
1311 OUT UINT32
*TemData
,
1312 OUT UINT32
*TempDataMask
1315 switch (AccessWidth
) {
1317 case AccessS3SaveWidth8
:
1318 *TemData
= (UINT32
)*(UINT8
*) Data
;
1319 *TempDataMask
= (UINT32
)*(UINT8
*) DataMask
;
1322 case AccessS3SaveWidth16
:
1323 *TemData
= (UINT32
)*(UINT16
*) Data
;
1324 *TempDataMask
= (UINT32
)*(UINT16
*) DataMask
;
1327 case AccessS3SaveWidth32
:
1328 *TemData
= *(UINT32
*) Data
;
1329 *TempDataMask
= *(UINT32
*) DataMask
;
1337 /*---------------------------------------------------------------------------------------*/
1339 * Returns the package type mask for the processor
1342 * @param[in] AccessWidth Access width
1343 * @retval Width in number of bytes
1348 IN ACCESS_WIDTH AccessWidth
1353 switch (AccessWidth
) {
1355 case AccessS3SaveWidth8
:
1359 case AccessS3SaveWidth16
:
1363 case AccessS3SaveWidth32
:
1367 case AccessS3SaveWidth64
:
1381 IN UINT32 CpuidFcnAddress
,
1382 OUT CPUID_DATA
*Value
1385 __cpuid ((int *)Value
, CpuidFcnAddress
);
1390 ReadNumberOfCpuCores(
1395 CpuidRead (0x80000008, &Value
);
1396 return Value
.ECX_Reg
& 0xff;
1409 } post
= {0xDEAD, FileCode
, 0xDEAD, FileCode
};
1414 offset
%= sizeof(struct POST
) / 2;
1415 WriteIo16(80, *((UINT16
*)&post
)+offset
);
1417 for (j
=0; j
<250; ++j
) {