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