xref: /aosp_15_r20/external/coreboot/src/vendorcode/amd/pi/Lib/amdlib.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Library
6  *
7  * Contains interface to the AMD AGESA library
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  Lib
12  * @e \$Revision: 48409 $   @e \$Date: 2011-03-08 11:19:40 -0600 (Tue, 08 Mar 2011) $
13  *
14  */
15 /*
16  ******************************************************************************
17  *
18  * Copyright (c) 2008 - 2011, Advanced Micro Devices, Inc.
19  *               2013 - 2014, Sage Electronic Engineering, LLC
20  * All rights reserved.
21  *
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.
32  *
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  ******************************************************************************
44  */
45 
46 #include <AGESA.h>
47 #include <cpuRegisters.h>
48 #include <cpu/x86/mp.h>
49 #include <cpu/x86/cache.h>
50 #include <Filecode.h>
51 #include <Ids.h>
52 #include <Porting.h>
53 #include "amdlib.h"
54 CODE_GROUP (G1_PEICC)
55 RDATA_GROUP (G1_PEICC)
56 
57 #if !defined(AMDLIB_OPTIMIZE)
58 	#define AMDLIB_OPTIMIZE
59 #endif
60 
61 #define FILECODE LIB_AMDLIB_FILECODE
62 
63 STATIC
64 BOOLEAN
65 GetPciMmioAddress (
66      OUT   UINT64            *MmioAddress,
67      OUT   UINT32            *MmioSize,
68   IN       AMD_CONFIG_PARAMS *StdHeader
69   );
70 
71 STATIC
72 VOID
73 LibAmdGetDataFromPtr (
74   IN       ACCESS_WIDTH AccessWidth,
75   IN       CONST VOID   *Data,
76   IN       CONST VOID   *DataMask,
77      OUT   UINT32       *TemData,
78      OUT   UINT32       *TempDataMask
79   );
80 VOID
81 IdsOutPort (
82   IN       UINT32 Addr,
83   IN       UINT32 Value,
84   IN       UINT32 Flag
85   );
86 
87 VOID
88 CpuidRead (
89   IN        UINT32      CpuidFcnAddress,
90   OUT       CPUID_DATA  *Value
91   );
92 
93 UINT8
94 ReadNumberOfCpuCores(
95   void
96   );
97 
98 AMDLIB_OPTIMIZE
99 UINT8
ReadIo8(IN UINT16 Address)100 ReadIo8 (
101   IN       UINT16 Address
102   )
103 {
104   return __inbyte (Address);
105 }
106 
107 AMDLIB_OPTIMIZE
108 UINT16
ReadIo16(IN UINT16 Address)109 ReadIo16 (
110   IN       UINT16 Address
111   )
112 {
113   return __inword (Address);
114 }
115 
116 AMDLIB_OPTIMIZE
117 UINT32
ReadIo32(IN UINT16 Address)118 ReadIo32 (
119   IN       UINT16 Address
120   )
121 {
122   return __indword (Address);
123 }
124 
125 AMDLIB_OPTIMIZE
126 VOID
WriteIo8(IN UINT16 Address,IN UINT8 Data)127 WriteIo8 (
128   IN       UINT16 Address,
129   IN       UINT8 Data
130   )
131 {
132   __outbyte (Address, Data);
133 }
134 
135 AMDLIB_OPTIMIZE
136 VOID
WriteIo16(IN UINT16 Address,IN UINT16 Data)137 WriteIo16 (
138   IN       UINT16 Address,
139   IN       UINT16 Data
140   )
141 {
142   __outword (Address, Data);
143 }
144 
145 AMDLIB_OPTIMIZE
146 VOID
WriteIo32(IN UINT16 Address,IN UINT32 Data)147 WriteIo32 (
148   IN       UINT16 Address,
149   IN       UINT32 Data
150   )
151 {
152    __outdword (Address, Data);
153 }
154 
155 STATIC
156 AMDLIB_OPTIMIZE
SetFsBase(UINT64 address)157 UINT64 SetFsBase (
158   UINT64 address
159   )
160 {
161   UINT64 hwcr;
162   hwcr = __readmsr (0xC0010015);
163   __writemsr (0xC0010015, hwcr | 1 << 17);
164   __writemsr (0xC0000100, address);
165   return hwcr;
166 }
167 
168 STATIC
169 AMDLIB_OPTIMIZE
170 VOID
RestoreHwcr(UINT64 value)171 RestoreHwcr (
172   UINT64
173   value
174   )
175 {
176   __writemsr (0xC0010015, value);
177 }
178 
179 AMDLIB_OPTIMIZE
180 UINT8
Read64Mem8(IN UINT64 Address)181 Read64Mem8 (
182   IN       UINT64 Address
183   )
184 {
185   UINT8 dataRead;
186   UINT64 hwcrSave;
187   if ((Address >> 32) == 0) {
188     return *(volatile UINT8 *) (UINTN) Address;
189   }
190   hwcrSave = SetFsBase (Address);
191   dataRead = __readfsbyte (0);
192   RestoreHwcr (hwcrSave);
193   return dataRead;
194 }
195 
196 AMDLIB_OPTIMIZE
197 UINT16
Read64Mem16(IN UINT64 Address)198 Read64Mem16 (
199   IN       UINT64 Address
200   )
201 {
202   UINT16 dataRead;
203   UINT64 hwcrSave;
204   if ((Address >> 32) == 0) {
205     return *(volatile UINT16 *) (UINTN) Address;
206   }
207   hwcrSave = SetFsBase (Address);
208   dataRead = __readfsword (0);
209   RestoreHwcr (hwcrSave);
210   return dataRead;
211 }
212 
213 AMDLIB_OPTIMIZE
214 UINT32
Read64Mem32(IN UINT64 Address)215 Read64Mem32 (
216   IN       UINT64 Address
217   )
218 {
219   UINT32 dataRead;
220   UINT64 hwcrSave;
221   if ((Address >> 32) == 0) {
222     return *(volatile UINT32 *) (UINTN) Address;
223   }
224   hwcrSave = SetFsBase (Address);
225   dataRead = __readfsdword (0);
226   RestoreHwcr (hwcrSave);
227   return dataRead;
228   }
229 
230 AMDLIB_OPTIMIZE
231 VOID
Write64Mem8(IN UINT64 Address,IN UINT8 Data)232 Write64Mem8 (
233   IN       UINT64 Address,
234   IN       UINT8 Data
235   )
236 {
237   if ((Address >> 32) == 0){
238     *(volatile UINT8 *) (UINTN) Address = Data;
239   }
240   else {
241     UINT64 hwcrSave;
242     hwcrSave = SetFsBase (Address);
243     __writefsbyte (0, Data);
244     RestoreHwcr (hwcrSave);
245   }
246 }
247 
248 AMDLIB_OPTIMIZE
249 VOID
Write64Mem16(IN UINT64 Address,IN UINT16 Data)250 Write64Mem16 (
251   IN       UINT64 Address,
252   IN       UINT16 Data
253   )
254 {
255  if ((Address >> 32) == 0){
256    *(volatile UINT16 *) (UINTN) Address = Data;
257  }
258  else {
259    UINT64 hwcrSave;
260    hwcrSave = SetFsBase (Address);
261    __writefsword (0, Data);
262    RestoreHwcr (hwcrSave);
263  }
264 }
265 
266 AMDLIB_OPTIMIZE
267 VOID
Write64Mem32(IN UINT64 Address,IN UINT32 Data)268 Write64Mem32 (
269   IN       UINT64 Address,
270   IN       UINT32 Data
271   )
272 {
273   if ((Address >> 32) == 0){
274     *(volatile UINT32 *) (UINTN) Address = Data;
275   }
276   else {
277     UINT64 hwcrSave;
278     hwcrSave = SetFsBase (Address);
279     __writefsdword (0, Data);
280     RestoreHwcr (hwcrSave);
281   }
282 }
283 
284 AMDLIB_OPTIMIZE
285 VOID
LibAmdReadCpuReg(IN UINT8 RegNum,OUT UINT32 * Value)286 LibAmdReadCpuReg (
287   IN       UINT8 RegNum,
288      OUT   UINT32 *Value
289   )
290 {
291     *Value = 0;
292     switch (RegNum){
293     case CR4_REG:
294       *Value = __readcr4 ();
295       break;
296     case DR0_REG:
297       *Value = __readdr (0);
298       break;
299     case DR1_REG:
300       *Value = __readdr (1);
301       break;
302     case DR2_REG:
303       *Value = __readdr (2);
304       break;
305     case DR3_REG:
306       *Value = __readdr (3);
307       break;
308     case DR7_REG:
309       *Value = __readdr (7);
310       break;
311     default:
312       *Value = -1;
313       break;
314   }
315 }
316 
317 AMDLIB_OPTIMIZE
318 VOID
LibAmdWriteCpuReg(IN UINT8 RegNum,IN UINT32 Value)319 LibAmdWriteCpuReg (
320   IN       UINT8 RegNum,
321   IN       UINT32 Value
322   )
323 {
324    switch (RegNum){
325     case CR4_REG:
326       __writecr4 (Value);
327       break;
328     case DR0_REG:
329       __writedr (0, Value);
330       break;
331     case DR1_REG:
332       __writedr (1, Value);
333       break;
334     case DR2_REG:
335       __writedr (2, Value);
336       break;
337     case DR3_REG:
338       __writedr (3, Value);
339       break;
340     case DR7_REG:
341       __writedr (7, Value);
342       break;
343     default:
344       break;
345   }
346 }
347 
348 AMDLIB_OPTIMIZE
349 VOID
LibAmdWriteBackInvalidateCache(void)350 LibAmdWriteBackInvalidateCache (
351   void
352   )
353 {
354   __wbinvd ();
355 }
356 
357 AMDLIB_OPTIMIZE
358 VOID
LibAmdHDTBreakPoint(void)359 LibAmdHDTBreakPoint (
360   void
361   )
362 {
363   __writemsr (0xC001100A, __readmsr (0xC001100A) | 1);
364   __debugbreak (); // do you really need icebp? If so, go back to asm code
365 }
366 
367 AMDLIB_OPTIMIZE
368 UINT8
LibAmdBitScanForward(IN UINT32 value)369 LibAmdBitScanForward (
370   IN       UINT32 value
371   )
372 {
373   UINTN Index;
374   for (Index = 0; Index < 32; Index++){
375     if (value & (1 << Index)) break;
376   }
377   return (UINT8) Index;
378 }
379 
380 AMDLIB_OPTIMIZE
381 UINT8
LibAmdBitScanReverse(IN UINT32 value)382 LibAmdBitScanReverse (
383   IN       UINT32 value
384 )
385 {
386   uint8_t bit = 31;
387   do {
388     if (value & (1 << 31))
389       return bit;
390 
391     value <<= 1;
392     bit--;
393 
394   } while (value != 0);
395 
396   return 0xFF; /* Error code indicating no bit found */
397 }
398 
399 AMDLIB_OPTIMIZE
400 VOID
LibAmdMsrRead(IN UINT32 MsrAddress,OUT UINT64 * Value,IN OUT AMD_CONFIG_PARAMS * ConfigPtr)401 LibAmdMsrRead (
402   IN       UINT32 MsrAddress,
403      OUT   UINT64 *Value,
404   IN OUT   AMD_CONFIG_PARAMS *ConfigPtr
405   )
406 {
407   if ((MsrAddress == 0xFFFFFFFF) || (MsrAddress == 0x00000000)) {
408 	  IdsErrorStop(MsrAddress);
409   }
410   *Value = __readmsr (MsrAddress);
411 }
412 
413 AMDLIB_OPTIMIZE
414 VOID
LibAmdMsrWrite(IN UINT32 MsrAddress,IN UINT64 * Value,IN OUT AMD_CONFIG_PARAMS * ConfigPtr)415 LibAmdMsrWrite (
416   IN       UINT32 MsrAddress,
417   IN       UINT64 *Value,
418   IN OUT   AMD_CONFIG_PARAMS *ConfigPtr
419   )
420 {
421   __writemsr (MsrAddress, *Value);
422 }
423 
424 AMDLIB_OPTIMIZE
LibAmdCpuidRead(IN UINT32 CpuidFcnAddress,OUT CPUID_DATA * Value,IN OUT AMD_CONFIG_PARAMS * ConfigPtr)425 void LibAmdCpuidRead (
426   IN       UINT32 CpuidFcnAddress,
427      OUT   CPUID_DATA* Value,
428   IN OUT   AMD_CONFIG_PARAMS *ConfigPtr
429   )
430 {
431   __cpuid ((int *)Value, CpuidFcnAddress);
432 }
433 
434 AMDLIB_OPTIMIZE
435 UINT64
ReadTSC(void)436 ReadTSC (
437   void
438   )
439 {
440   return __rdtsc ();
441 }
442 
443 AMDLIB_OPTIMIZE
444 VOID
LibAmdSimNowEnterDebugger(void)445 LibAmdSimNowEnterDebugger (
446   void
447   )
448 {
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
452                                    0x0F, 0xA2,                       // cpuid
453                                    0x61,                             // popad
454                                    0xC3                              // ret
455                                  };
456   ((VOID (*)(VOID)) (size_t) opcode) (); // call the function
457 }
458 
459 AMDLIB_OPTIMIZE
460 VOID
IdsOutPort(IN UINT32 Addr,IN UINT32 Value,IN UINT32 Flag)461 IdsOutPort (
462   IN       UINT32 Addr,
463   IN       UINT32 Value,
464   IN       UINT32 Flag
465   )
466 {
467   __outdword ((UINT16) Addr, Value);
468 }
469 
470 AMDLIB_OPTIMIZE
471 VOID
StopHere(void)472 StopHere (
473   void
474   )
475 {
476   VOLATILE UINTN x = 1;
477   while (x);
478 }
479 
480 AMDLIB_OPTIMIZE
481 VOID
LibAmdCLFlush(IN UINT64 Address,IN UINT8 Count)482 LibAmdCLFlush (
483   IN       UINT64 Address,
484   IN       UINT8  Count
485   )
486 {
487   UINT64 hwcrSave;
488   UINT8  *address32;
489   UINTN  Index;
490   address32 = 0;
491   hwcrSave = SetFsBase (Address);
492   for (Index = 0; Index < Count; Index++){
493     mfence();
494     clflush(&address32 [Index * 64]);
495   }
496   RestoreHwcr (hwcrSave);
497 }
498 
499 
500 AMDLIB_OPTIMIZE
501 VOID
LibAmdFinit(void)502 LibAmdFinit(
503   void
504   )
505 {
506 	/* TODO: finit */
507 	__asm__ volatile ("finit");
508 }
509 /*---------------------------------------------------------------------------------------*/
510 /**
511  * Read IO port
512  *
513  *
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
518  *
519  */
520 VOID
LibAmdIoRead(IN ACCESS_WIDTH AccessWidth,IN UINT16 IoAddress,OUT VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)521 LibAmdIoRead (
522   IN       ACCESS_WIDTH AccessWidth,
523   IN       UINT16 IoAddress,
524      OUT   VOID *Value,
525   IN OUT   AMD_CONFIG_PARAMS *StdHeader
526   )
527 {
528   switch (AccessWidth) {
529   case AccessWidth8:
530   case AccessS3SaveWidth8:
531     *(UINT8 *) Value = ReadIo8 (IoAddress);
532     break;
533   case AccessWidth16:
534   case AccessS3SaveWidth16:
535     *(UINT16 *) Value = ReadIo16 (IoAddress);
536     break;
537   case AccessWidth32:
538   case AccessS3SaveWidth32:
539     *(UINT32 *) Value = ReadIo32 (IoAddress);
540     break;
541   default:
542     ASSERT (FALSE);
543     break;
544   }
545 }
546 
547 /*---------------------------------------------------------------------------------------*/
548 /**
549  * Write IO port
550  *
551  *
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
556  *
557  */
558 VOID
LibAmdIoWrite(IN ACCESS_WIDTH AccessWidth,IN UINT16 IoAddress,IN CONST VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)559 LibAmdIoWrite (
560   IN       ACCESS_WIDTH AccessWidth,
561   IN       UINT16 IoAddress,
562   IN       CONST VOID *Value,
563   IN OUT   AMD_CONFIG_PARAMS *StdHeader
564   )
565 {
566   switch (AccessWidth) {
567   case AccessWidth8:
568   case AccessS3SaveWidth8:
569     WriteIo8 (IoAddress, *(UINT8 *) Value);
570     break;
571   case AccessWidth16:
572   case AccessS3SaveWidth16:
573     WriteIo16 (IoAddress, *(UINT16 *) Value);
574     break;
575   case AccessWidth32:
576   case AccessS3SaveWidth32:
577     WriteIo32 (IoAddress, *(UINT32 *) Value);
578     break;
579   default:
580     ASSERT (FALSE);
581     break;
582   }
583 }
584 
585 /*---------------------------------------------------------------------------------------*/
586 /**
587  * IO read modify write
588  *
589  *
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
595  *
596  */
597 VOID
LibAmdIoRMW(IN ACCESS_WIDTH AccessWidth,IN UINT16 IoAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN OUT AMD_CONFIG_PARAMS * StdHeader)598 LibAmdIoRMW (
599   IN       ACCESS_WIDTH AccessWidth,
600   IN       UINT16 IoAddress,
601   IN       CONST VOID *Data,
602   IN       CONST VOID *DataMask,
603   IN OUT   AMD_CONFIG_PARAMS *StdHeader
604   )
605 {
606   UINT32  TempData;
607   UINT32  TempMask;
608   UINT32  Value;
609   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
610   LibAmdIoRead (AccessWidth, IoAddress, &Value, NULL);
611   Value = (Value & (~TempMask)) | TempData;
612   LibAmdIoWrite (AccessWidth, IoAddress, &Value, NULL);
613 }
614 
615 /*---------------------------------------------------------------------------------------*/
616 /**
617  * Poll IO register
618  *
619  *  Poll register until (RegisterValue & DataMask) ==  Data
620  *
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
627  *
628  */
629 VOID
LibAmdIoPoll(IN ACCESS_WIDTH AccessWidth,IN UINT16 IoAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN UINT64 Delay,IN OUT AMD_CONFIG_PARAMS * StdHeader)630 LibAmdIoPoll (
631   IN       ACCESS_WIDTH AccessWidth,
632   IN       UINT16 IoAddress,
633   IN       CONST VOID *Data,
634   IN       CONST VOID *DataMask,
635   IN       UINT64 Delay,
636   IN OUT   AMD_CONFIG_PARAMS *StdHeader
637   )
638 {
639   UINT32  TempData;
640   UINT32  TempMask;
641   UINT32  Value;
642   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
643   do {
644     LibAmdIoRead (AccessWidth, IoAddress, &Value, NULL);
645   } while (TempData != (Value & TempMask));
646 }
647 
648 /*---------------------------------------------------------------------------------------*/
649 /**
650  * Read memory/MMIO
651  *
652  *
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
657  *
658  */
659 VOID
LibAmdMemRead(IN ACCESS_WIDTH AccessWidth,IN UINT64 MemAddress,OUT VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)660 LibAmdMemRead (
661   IN       ACCESS_WIDTH AccessWidth,
662   IN       UINT64 MemAddress,
663      OUT   VOID *Value,
664   IN OUT   AMD_CONFIG_PARAMS *StdHeader
665   )
666 {
667   switch (AccessWidth) {
668   case AccessWidth8:
669   case AccessS3SaveWidth8:
670     *(UINT8 *) Value = Read64Mem8 (MemAddress);
671     break;
672   case AccessWidth16:
673   case AccessS3SaveWidth16:
674     *(UINT16 *) Value = Read64Mem16 (MemAddress);
675     break;
676   case AccessWidth32:
677   case AccessS3SaveWidth32:
678     *(UINT32 *) Value = Read64Mem32 (MemAddress);
679     break;
680   default:
681     ASSERT (FALSE);
682     break;
683   }
684 }
685 
686 /*---------------------------------------------------------------------------------------*/
687 /**
688  * Write memory/MMIO
689  *
690  *
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
695  *
696  */
697 VOID
LibAmdMemWrite(IN ACCESS_WIDTH AccessWidth,IN UINT64 MemAddress,IN CONST VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)698 LibAmdMemWrite (
699   IN       ACCESS_WIDTH AccessWidth,
700   IN       UINT64 MemAddress,
701   IN       CONST VOID *Value,
702   IN OUT   AMD_CONFIG_PARAMS *StdHeader
703   )
704 {
705 
706   switch (AccessWidth) {
707   case AccessWidth8:
708   case AccessS3SaveWidth8:
709     Write64Mem8 (MemAddress, *((UINT8 *) Value));
710     break;
711   case AccessWidth16:
712   case AccessS3SaveWidth16:
713     Write64Mem16 (MemAddress, *((UINT16 *) Value));
714     break;
715   case AccessWidth32:
716   case AccessS3SaveWidth32:
717     Write64Mem32 (MemAddress, *((UINT32 *) Value));
718     break;
719   default:
720     ASSERT (FALSE);
721     break;
722   }
723 }
724 /*---------------------------------------------------------------------------------------*/
725 /**
726  * Memory/MMIO read modify write
727  *
728  *
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
734  *
735  */
736 VOID
LibAmdMemRMW(IN ACCESS_WIDTH AccessWidth,IN UINT64 MemAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN OUT AMD_CONFIG_PARAMS * StdHeader)737 LibAmdMemRMW (
738   IN       ACCESS_WIDTH AccessWidth,
739   IN       UINT64 MemAddress,
740   IN       CONST VOID *Data,
741   IN       CONST VOID *DataMask,
742   IN OUT   AMD_CONFIG_PARAMS *StdHeader
743   )
744 {
745   UINT32  TempData;
746   UINT32  TempMask;
747   UINT32  Value;
748   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
749   LibAmdMemRead (AccessWidth, MemAddress, &Value, NULL);
750   Value = (Value & (~TempMask)) | TempData;
751   LibAmdMemWrite (AccessWidth, MemAddress, &Value, NULL);
752 }
753 
754 /*---------------------------------------------------------------------------------------*/
755 /**
756  * Poll Mmio
757  *
758  *  Poll register until (RegisterValue & DataMask) ==  Data
759  *
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
766  *
767  */
768 VOID
LibAmdMemPoll(IN ACCESS_WIDTH AccessWidth,IN UINT64 MemAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN UINT64 Delay,IN OUT AMD_CONFIG_PARAMS * StdHeader)769 LibAmdMemPoll (
770   IN       ACCESS_WIDTH AccessWidth,
771   IN       UINT64 MemAddress,
772   IN       CONST VOID *Data,
773   IN       CONST VOID *DataMask,
774   IN       UINT64 Delay,
775   IN OUT   AMD_CONFIG_PARAMS *StdHeader
776   )
777 {
778   UINT32  TempData = 0;
779   UINT32  TempMask = 0;
780   UINT32  Value;
781   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
782   do {
783     LibAmdMemRead (AccessWidth, MemAddress, &Value, NULL);
784   } while (TempData != (Value & TempMask));
785 }
786 
787 /*---------------------------------------------------------------------------------------*/
788 /**
789  * Read PCI config space
790  *
791  *
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
796  *
797  */
798 VOID
LibAmdPciRead(IN ACCESS_WIDTH AccessWidth,IN PCI_ADDR PciAddress,OUT VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)799 LibAmdPciRead (
800   IN       ACCESS_WIDTH AccessWidth,
801   IN       PCI_ADDR PciAddress,
802      OUT   VOID *Value,
803   IN OUT   AMD_CONFIG_PARAMS *StdHeader
804   )
805 {
806   UINT32 LegacyPciAccess;
807   UINT32 MMIOSize;
808   UINT64 RMWrite;
809   UINT64 RMWritePrevious;
810   UINT64 MMIOAddress;
811 
812 
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);
820     } else {
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);
827     }
828     //IDS_HDT_CONSOLE (LIB_PCI_RD, "~PCI RD %08x = %08x\n", LegacyPciAccess, *(UINT32 *)Value);
829   } else {
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);
835   }
836 }
837 
838 /*---------------------------------------------------------------------------------------*/
839 /**
840  * Write PCI config space
841  *
842  *
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
847  *
848  */
849 VOID
LibAmdPciWrite(IN ACCESS_WIDTH AccessWidth,IN PCI_ADDR PciAddress,IN CONST VOID * Value,IN OUT AMD_CONFIG_PARAMS * StdHeader)850 LibAmdPciWrite (
851   IN       ACCESS_WIDTH AccessWidth,
852   IN       PCI_ADDR PciAddress,
853   IN       CONST VOID *Value,
854   IN OUT   AMD_CONFIG_PARAMS *StdHeader
855   )
856 {
857   UINT32 LegacyPciAccess;
858   UINT32 MMIOSize;
859   UINT64 RMWrite;
860   UINT64 RMWritePrevious;
861   UINT64 MMIOAddress;
862 
863 
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);
871     } else {
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);
878     }
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");
882   } else {
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");
890   }
891 }
892 
893 /*---------------------------------------------------------------------------------------*/
894 /**
895  * PCI read modify write
896  *
897  *
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
903  *
904  */
905 VOID
LibAmdPciRMW(IN ACCESS_WIDTH AccessWidth,IN PCI_ADDR PciAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN OUT AMD_CONFIG_PARAMS * StdHeader)906 LibAmdPciRMW (
907   IN       ACCESS_WIDTH AccessWidth,
908   IN       PCI_ADDR PciAddress,
909   IN       CONST VOID *Data,
910   IN       CONST VOID *DataMask,
911   IN OUT   AMD_CONFIG_PARAMS *StdHeader
912   )
913 {
914   UINT32  TempData = 0;
915   UINT32  TempMask = 0;
916   UINT32  Value;
917   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
918   LibAmdPciRead (AccessWidth, PciAddress, &Value, NULL);
919   Value = (Value & (~TempMask)) | TempData;
920   LibAmdPciWrite (AccessWidth, PciAddress, &Value, NULL);
921 }
922 
923 /*---------------------------------------------------------------------------------------*/
924 /**
925  * Poll PCI config space register
926  *
927  *  Poll register until (RegisterValue & DataMask) ==  Data
928  *
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
935  *
936  */
937 VOID
LibAmdPciPoll(IN ACCESS_WIDTH AccessWidth,IN PCI_ADDR PciAddress,IN CONST VOID * Data,IN CONST VOID * DataMask,IN UINT64 Delay,IN OUT AMD_CONFIG_PARAMS * StdHeader)938 LibAmdPciPoll (
939   IN       ACCESS_WIDTH AccessWidth,
940   IN       PCI_ADDR PciAddress,
941   IN       CONST VOID *Data,
942   IN       CONST VOID *DataMask,
943   IN       UINT64 Delay,
944   IN OUT   AMD_CONFIG_PARAMS *StdHeader
945   )
946 {
947   UINT32  TempData = 0;
948   UINT32  TempMask = 0;
949   UINT32  Value;
950   LibAmdGetDataFromPtr (AccessWidth, Data,  DataMask, &TempData, &TempMask);
951   do {
952     LibAmdPciRead (AccessWidth, PciAddress, &Value, NULL);
953   } while (TempData != (Value & TempMask));
954 }
955 
956 /*---------------------------------------------------------------------------------------*/
957 /**
958  * Get MMIO base address for PCI accesses
959  *
960  * @param[out] MmioAddress   PCI MMIO base address
961  * @param[out] MmioSize      Size of region in bytes
962  * @param[in]  StdHeader     Standard configuration header
963  *
964  * @retval    TRUE          MmioAddress/MmioSize are valid
965  */
966 STATIC
967 BOOLEAN
GetPciMmioAddress(OUT UINT64 * MmioAddress,OUT UINT32 * MmioSize,IN AMD_CONFIG_PARAMS * StdHeader)968 GetPciMmioAddress (
969      OUT   UINT64            *MmioAddress,
970      OUT   UINT32            *MmioSize,
971   IN       AMD_CONFIG_PARAMS *StdHeader
972   )
973 {
974   BOOLEAN MmioIsEnabled;
975   UINT32  EncodedSize;
976   UINT64  LocalMsrRegister;
977 
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;
985   }
986   return MmioIsEnabled;
987 }
988 
989 /*---------------------------------------------------------------------------------------*/
990 /**
991  * Read field of PCI config register.
992  *
993  *
994  *
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
1000  */
1001 VOID
LibAmdPciReadBits(IN PCI_ADDR Address,IN UINT8 Highbit,IN UINT8 Lowbit,OUT UINT32 * Value,IN AMD_CONFIG_PARAMS * StdHeader)1002 LibAmdPciReadBits (
1003   IN       PCI_ADDR Address,
1004   IN       UINT8 Highbit,
1005   IN       UINT8 Lowbit,
1006      OUT   UINT32 *Value,
1007   IN       AMD_CONFIG_PARAMS *StdHeader
1008   )
1009 {
1010   ASSERT (Highbit < 32 && Lowbit < 32 && Highbit >= Lowbit && (Address.AddressValue & 3) == 0);
1011 
1012   LibAmdPciRead (AccessWidth32, Address, Value, NULL);
1013   *Value >>= Lowbit;  // Shift
1014 
1015   // A 1 << 32 == 1 << 0 due to x86 SHL instruction, so skip if that is the case
1016 
1017   if ((Highbit - Lowbit) != 31) {
1018     *Value &= (((UINT32) 1 << (Highbit - Lowbit + 1)) - 1);
1019   }
1020 }
1021 
1022 /*---------------------------------------------------------------------------------------*/
1023 /**
1024  * Write field of PCI config register.
1025  *
1026  *
1027  *
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
1033  */
1034 VOID
LibAmdPciWriteBits(IN PCI_ADDR Address,IN UINT8 Highbit,IN UINT8 Lowbit,IN CONST UINT32 * Value,IN AMD_CONFIG_PARAMS * StdHeader)1035 LibAmdPciWriteBits (
1036   IN       PCI_ADDR Address,
1037   IN       UINT8 Highbit,
1038   IN       UINT8 Lowbit,
1039   IN       CONST UINT32 *Value,
1040   IN       AMD_CONFIG_PARAMS *StdHeader
1041   )
1042 {
1043   UINT32 Temp;
1044   UINT32 Mask;
1045 
1046   ASSERT (Highbit < 32 && Lowbit < 32 && Highbit >= Lowbit && (Address.AddressValue & 3) == 0);
1047 
1048   // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
1049 
1050   if ((Highbit - Lowbit) != 31) {
1051     Mask = (((UINT32) 1 << (Highbit - Lowbit + 1)) - 1);
1052   } else {
1053     Mask = (UINT32) 0xFFFFFFFF;
1054   }
1055 
1056   LibAmdPciRead (AccessWidth32, Address, &Temp, NULL);
1057   Temp &= ~(Mask << Lowbit);
1058   Temp |= (*Value & Mask) << Lowbit;
1059   LibAmdPciWrite (AccessWidth32, Address, &Temp, NULL);
1060 }
1061 
1062 /*---------------------------------------------------------------------------------------*/
1063 /**
1064  * Locate next capability pointer
1065  *
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
1068  *  returned.
1069  *  To start a new search from the head of the list, specify a SBDFO with an offset of zero.
1070  *
1071  * @param[in,out] Address       Pci address
1072  * @param[in]     StdHeader     Standard configuration header
1073  */
1074 
1075 VOID
LibAmdPciFindNextCap(IN OUT PCI_ADDR * Address,IN AMD_CONFIG_PARAMS * StdHeader)1076 LibAmdPciFindNextCap (
1077   IN OUT   PCI_ADDR *Address,
1078   IN       AMD_CONFIG_PARAMS *StdHeader
1079   )
1080 {
1081   PCI_ADDR Base;
1082   UINT32 Offset;
1083   UINT32 Temp;
1084   PCI_ADDR TempAddress;
1085 
1086   ASSERT (Address != NULL);
1087   ASSERT (*(UINT32 *) Address != ILLEGAL_SBDFO);
1088 
1089   Base.AddressValue = Address->AddressValue;
1090   Offset = Base.Address.Register;
1091   Base.Address.Register = 0;
1092 
1093   Address->AddressValue = (UINT32) ILLEGAL_SBDFO;
1094 
1095   // Verify that the SBDFO points to a valid PCI device SANITY CHECK
1096   LibAmdPciRead (AccessWidth32, Base, &Temp, NULL);
1097   if (Temp == 0xFFFFFFFF) {
1098     ASSERT (FALSE);
1099     return; // There is no device at this address
1100   }
1101 
1102   // Verify that the device supports a capability list
1103   TempAddress.AddressValue = Base.AddressValue + 0x04;
1104   LibAmdPciReadBits (TempAddress, 20, 20, &Temp, NULL);
1105   if (Temp == 0) {
1106     return; // This PCI device does not support capability lists
1107   }
1108 
1109   if (Offset != 0) {
1110     // If we are continuing on an existing list
1111     TempAddress.AddressValue = Base.AddressValue + Offset;
1112     LibAmdPciReadBits (TempAddress, 15, 8, &Temp, NULL);
1113   } else {
1114     // We are starting on a new list
1115     TempAddress.AddressValue = Base.AddressValue + 0x34;
1116     LibAmdPciReadBits (TempAddress, 7, 0, &Temp, NULL);
1117   }
1118 
1119   if (Temp == 0) {
1120     return; // We have reached the end of the capabilities list
1121   }
1122 
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)) {
1128     ASSERT (FALSE);
1129     return;
1130   }
1131 
1132   Address->AddressValue = Base.AddressValue + Temp;
1133   return;
1134 }
1135 
1136 /*---------------------------------------------------------------------------------------*/
1137 /**
1138  * Set memory with value
1139  *
1140  *
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)
1145  */
1146 VOID
LibAmdMemFill(IN VOID * Destination,IN UINT8 Value,IN UINTN FillLength,IN OUT AMD_CONFIG_PARAMS * StdHeader)1147 LibAmdMemFill (
1148   IN       VOID *Destination,
1149   IN       UINT8 Value,
1150   IN       UINTN FillLength,
1151   IN OUT   AMD_CONFIG_PARAMS *StdHeader
1152   )
1153 {
1154   UINT8 *Dest;
1155   Dest = Destination;
1156   while ((FillLength--) != 0) {
1157     *Dest++ = Value;
1158   }
1159 }
1160 
1161 /*---------------------------------------------------------------------------------------*/
1162 /**
1163  * Copy memory
1164  *
1165  *
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)
1170  */
1171 VOID
LibAmdMemCopy(IN VOID * Destination,IN CONST VOID * Source,IN UINTN CopyLength,IN OUT AMD_CONFIG_PARAMS * StdHeader)1172 LibAmdMemCopy (
1173   IN       VOID *Destination,
1174   IN       CONST VOID *Source,
1175   IN       UINTN CopyLength,
1176   IN OUT   AMD_CONFIG_PARAMS *StdHeader
1177   )
1178 {
1179   UINT8 *Dest;
1180   CONST UINT8 *SourcePtr;
1181   Dest = Destination;
1182   SourcePtr = Source;
1183   while ((CopyLength--) != 0) {
1184     *Dest++ = *SourcePtr++;
1185   }
1186 }
1187 
1188 /*---------------------------------------------------------------------------------------*/
1189 /**
1190  * Verify checksum of binary image (B1/B2/B3)
1191  *
1192  *
1193  * @param[in]   ImagePtr      Pointer to image  start
1194  * @retval      TRUE          Checksum valid
1195  * @retval      FALSE         Checksum invalid
1196  */
1197 BOOLEAN
LibAmdVerifyImageChecksum(IN CONST VOID * ImagePtr)1198 LibAmdVerifyImageChecksum (
1199   IN       CONST VOID *ImagePtr
1200   )
1201 {
1202   // Assume ImagePtr points to the binary start ($AMD)
1203   // Checksum is on an even boundary in AMD_IMAGE_HEADER
1204 
1205   UINT16 Sum;
1206   UINT32 i;
1207 
1208   Sum = 0;
1209 
1210   i = ((AMD_IMAGE_HEADER*) ImagePtr)->ImageSize;
1211 
1212   while (i > 1) {
1213     Sum = Sum + *((UINT16 *)ImagePtr);
1214     ImagePtr = (VOID *) ((UINT8 *)ImagePtr + 2);
1215     i = i - 2;
1216   }
1217   if (i > 0) {
1218     Sum = Sum + *((UINT8 *) ImagePtr);
1219   }
1220 
1221   return (Sum == 0)?TRUE:FALSE;
1222 }
1223 
1224 /*---------------------------------------------------------------------------------------*/
1225 /**
1226  * Locate AMD binary image that contain specific module
1227  *
1228  *
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
1235  */
1236 CONST VOID *
LibAmdLocateImage(IN CONST VOID * StartAddress,IN CONST VOID * EndAddress,IN UINT32 Alignment,IN CONST CHAR8 ModuleSignature[8])1237 LibAmdLocateImage (
1238   IN       CONST VOID *StartAddress,
1239   IN       CONST VOID *EndAddress,
1240   IN       UINT32 Alignment,
1241   IN       CONST CHAR8 ModuleSignature[8]
1242   )
1243 
1244 {
1245   CONST UINT8 *CurrentPtr = StartAddress;
1246   AMD_MODULE_HEADER *ModuleHeaderPtr;
1247   CONST UINT64 SearchStr = *((UINT64*)ModuleSignature);
1248 
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))) {
1260             return  CurrentPtr;
1261           }
1262           ModuleHeaderPtr = (AMD_MODULE_HEADER *)ModuleHeaderPtr->NextBlock;
1263         }
1264 //      }
1265     }
1266     CurrentPtr += Alignment;
1267   }
1268   return NULL;
1269 }
1270 
1271 /*---------------------------------------------------------------------------------------*/
1272 /**
1273  * Returns the package type mask for the processor
1274  *
1275  *
1276  * @param[in]     StdHeader     Standard configuration header (Optional)
1277  */
1278 
1279 //  Returns the package type mask for the processor
1280 UINT32
LibAmdGetPackageType(IN AMD_CONFIG_PARAMS * StdHeader)1281 LibAmdGetPackageType (
1282   IN       AMD_CONFIG_PARAMS *StdHeader
1283   )
1284 {
1285   UINT32      ProcessorPackageType;
1286   CPUID_DATA  CpuId;
1287 
1288   LibAmdCpuidRead (0x80000001, &CpuId, NULL);
1289   ProcessorPackageType = (UINT32) (CpuId.EBX_Reg >> 28) & 0xF; // bit 31:28
1290   return (UINT32) (1 << ProcessorPackageType);
1291 }
1292 
1293 /*---------------------------------------------------------------------------------------*/
1294 /**
1295  * Returns the package type mask for the processor
1296  *
1297  *
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
1303  */
1304 
1305 STATIC
1306 VOID
LibAmdGetDataFromPtr(IN ACCESS_WIDTH AccessWidth,IN CONST VOID * Data,IN CONST VOID * DataMask,OUT UINT32 * TemData,OUT UINT32 * TempDataMask)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
1313   )
1314 {
1315   switch (AccessWidth) {
1316   case AccessWidth8:
1317   case AccessS3SaveWidth8:
1318     *TemData = (UINT32)*(UINT8 *) Data;
1319     *TempDataMask = (UINT32)*(UINT8 *) DataMask;
1320     break;
1321   case AccessWidth16:
1322   case AccessS3SaveWidth16:
1323     *TemData = (UINT32)*(UINT16 *) Data;
1324     *TempDataMask = (UINT32)*(UINT16 *) DataMask;
1325     break;
1326   case AccessWidth32:
1327   case AccessS3SaveWidth32:
1328     *TemData = *(UINT32 *) Data;
1329     *TempDataMask = *(UINT32 *) DataMask;
1330     break;
1331   default:
1332     IDS_ERROR_TRAP;
1333     break;
1334   }
1335 }
1336 
1337 /*---------------------------------------------------------------------------------------*/
1338 /**
1339  * Returns the package type mask for the processor
1340  *
1341  *
1342  * @param[in]     AccessWidth     Access width
1343  * @retval        Width in number of bytes
1344  */
1345 
1346 UINT8
LibAmdAccessWidth(IN ACCESS_WIDTH AccessWidth)1347 LibAmdAccessWidth (
1348   IN       ACCESS_WIDTH AccessWidth
1349   )
1350 {
1351   UINT8 Width;
1352 
1353   switch (AccessWidth) {
1354   case AccessWidth8:
1355   case AccessS3SaveWidth8:
1356     Width = 1;
1357     break;
1358   case AccessWidth16:
1359   case AccessS3SaveWidth16:
1360     Width = 2;
1361     break;
1362   case AccessWidth32:
1363   case AccessS3SaveWidth32:
1364     Width = 4;
1365     break;
1366   case AccessWidth64:
1367   case AccessS3SaveWidth64:
1368     Width = 8;
1369     break;
1370   default:
1371     Width = 0;
1372     IDS_ERROR_TRAP;
1373     break;
1374   }
1375   return Width;
1376 }
1377 
1378 AMDLIB_OPTIMIZE
1379 VOID
CpuidRead(IN UINT32 CpuidFcnAddress,OUT CPUID_DATA * Value)1380 CpuidRead (
1381   IN        UINT32      CpuidFcnAddress,
1382   OUT       CPUID_DATA  *Value
1383   )
1384 {
1385   __cpuid ((int *)Value, CpuidFcnAddress);
1386 }
1387 
1388 AMDLIB_OPTIMIZE
1389 UINT8
ReadNumberOfCpuCores(void)1390 ReadNumberOfCpuCores(
1391   void
1392   )
1393 {
1394   CPUID_DATA  Value;
1395   CpuidRead (0x80000008, &Value);
1396   return   Value.ECX_Reg & 0xff;
1397 }
1398 
1399 BOOLEAN
IdsErrorStop(IN UINT32 FileCode)1400 IdsErrorStop (
1401   IN      UINT32 FileCode
1402   )
1403 {
1404 	struct POST {
1405 		UINT16 deadlo;
1406 		UINT32 messagelo;
1407 		UINT16 deadhi;
1408 		UINT32 messagehi;
1409 	} post = {0xDEAD, FileCode, 0xDEAD, FileCode};
1410 	UINT16 offset = 0;
1411 	UINT16 j;
1412 
1413 	while(1) {
1414 		offset %= sizeof(struct POST) / 2;
1415 		WriteIo16(80, *((UINT16 *)&post)+offset);
1416 		++offset;
1417 		for (j=0; j<250; ++j) {
1418 			ReadIo8(80);
1419 		}
1420 	}
1421 }
1422