blob: d05164d00b7e78a6e78b87c12a9d595a9da6b23c [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/**
2 * @file
3 *
4 * AMD Integrated Debug Debug_library Routines
5 *
6 * Contains all functions related to HDTOUT
7 *
8 * @xrefitem bom "File Content Label" "Release Content"
9 * @e project: AGESA
10 * @e sub-project: IDS
11 * @e \$Revision: 63688 $ @e \$Date: 2012-01-03 21:18:53 -0600 (Tue, 03 Jan 2012) $
12 */
13/*****************************************************************************
Siyuan Wang641f00c2013-06-08 11:50:55 +080014 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
15 * All rights reserved.
zbao7d94cf92012-07-02 14:19:14 +080016 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080017 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
zbao7d94cf92012-07-02 14:19:14 +080027 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zbao7d94cf92012-07-02 14:19:14 +080038 ******************************************************************************
39 */
40
41 /*----------------------------------------------------------------------------------------
42 * M O D U L E S U S E D
43 *----------------------------------------------------------------------------------------
44 */
45#include "AGESA.h"
46#include "Ids.h"
47#include "IdsLib.h"
48#include "amdlib.h"
49#include "AMD.h"
50#include "heapManager.h"
51#include "cpuRegisters.h"
52#include "cpuServices.h"
53#include "GeneralServices.h"
54#include "IdsDebugPrint.h"
55#include "IdsDpHdtout.h"
56#include "Filecode.h"
57CODE_GROUP (G1_PEICC)
58RDATA_GROUP (G1_PEICC)
59
60#define FILECODE PROC_IDS_DEBUG_IDSDPHDTOUT_FILECODE
61
62/**
63 * Check if String contain the substring
64 *
65 * @param[in] String Pointer of string.
66 * @param[in] Substr Pointer of sub string.
67 *
68 * @retval TRUE S2 is substring of S1
69 * @retval FALSE S2 isn't substring of S1
70 *
71**/
72BOOLEAN
73AmdIdsSubStr (
74 IN CHAR8 *String,
75 IN CHAR8 *Substr
76 )
77{
78 UINT16 i;
79 UINT16 j;
80
81 for (i = 0; String[i] != 0 ; i++) {
82 for (j = 0; (Substr[j] != 0) && (Substr[j] == String[i + j]); j++) {
83 }
84 if (Substr[j] == 0) {
85 return TRUE;
86 }
87 }
88
89 return FALSE;
90}
91
92/**
93 * Determine whether IDS console is enabled.
94 *
95 * @param[in,out] pHdtoutHeader Address of hdtout header pointer
96 * @param[in,out] StdHeader The Pointer of AGESA Header
97 *
98 * @retval TRUE pHdtoutHeader Non zero
99 * @retval FALSE pHdtoutHeader is NULL
100 *
101 **/
102BOOLEAN
103AmdIdsHdtoutGetHeader (
104 IN OUT HDTOUT_HEADER **pHdtoutHeaderPtr,
105 IN OUT AMD_CONFIG_PARAMS *StdHeader
106 )
107{
108 UINT32 Dr3Reg;
109 HDTOUT_HEADER *HdtoutHeaderPtr;
110 LibAmdReadCpuReg (DR3_REG, &Dr3Reg);
111 HdtoutHeaderPtr = (HDTOUT_HEADER *) (UINTN) Dr3Reg;
112 if ((HdtoutHeaderPtr != NULL) && (HdtoutHeaderPtr->Signature == HDTOUT_HEADER_SIGNATURE)) {
113 *pHdtoutHeaderPtr = HdtoutHeaderPtr;
114 return TRUE;
115 } else {
116 return FALSE;
117 }
118}
119/**
120 * Determine whether IDS console is enabled.
121 *
122 * @param[in,out] IdsConsole The Pointer of Ids console data
123 *
124 * @retval TRUE Ids console is enabled.
125 * @retval FALSE Ids console is disabled.
126 *
127 **/
128BOOLEAN
129AmdIdsHdtOutSupport (
130 VOID
131 )
132{
133 BOOLEAN Result;
134 UINT32 DR2reg;
135
136 Result = FALSE;
137
138 LibAmdReadCpuReg (DR2_REG, &DR2reg);
139 if (DR2reg == 0x99CC) {
140 Result = TRUE;
141 }
142
143 return Result;
144}
145
146/**
147 * Get HDTOUT customize Filter
148 *
149 * @param[in,out] Filter Filter do be filled
150 *
151 * @retval TRUE Alway return true, for HDTOUT has its own filter mechanism
152 *
153 **/
154BOOLEAN
155AmdIdsHdtOutGetFilter (
156 IN OUT UINT64 *Filter
157 )
158{
159 HDTOUT_HEADER *HdtoutHeaderPtr;
160
161 if (AmdIdsHdtoutGetHeader (&HdtoutHeaderPtr, NULL) == TRUE) {
162 *Filter = HdtoutHeaderPtr->ConsoleFilter;
163 }
164 return TRUE;
165}
166
167/**
168 *
169 * Initial register setting used for HDT out Function.
170 *
171 *
172 * @param[in,out] StdHeader The Pointer of AGESA Header
173 *
174 **/
175VOID
176AmdIdsHdtOutRegisterRestore (
177 IN OUT AMD_CONFIG_PARAMS *StdHeader
178 )
179{
180 UINT32 CR4reg;
181 UINT64 SMsr;
182
183 SMsr &= ~BIT0;
184
185 LibAmdWriteCpuReg (DR2_REG, 0);
186 LibAmdWriteCpuReg (DR3_REG, 0);
187 LibAmdWriteCpuReg (DR7_REG, 0);
188
189 LibAmdReadCpuReg (CR4_REG, &CR4reg);
190 LibAmdWriteCpuReg (CR4_REG, CR4reg & (~BIT3));
191
192}
193
194/**
195 *
196 * Restore register setting used for HDT out Function.
197 *
198 *
199 * @param[in,out] StdHeader The Pointer of AGESA Header
200 *
201 **/
202VOID
203AmdIdsHdtOutRegisterInit (
204 IN OUT AMD_CONFIG_PARAMS *StdHeader
205 )
206{
207 UINT32 CR4reg;
208 UINT64 SMsr;
209
210 SMsr |= 1;
211
212 LibAmdWriteCpuReg (DR2_REG, 0x99CC);
213
214 LibAmdWriteCpuReg (DR7_REG, 0x02000420);
215
216 LibAmdReadCpuReg (CR4_REG, &CR4reg);
217 LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3));
218}
219
220/**
221 *
222 * Initial function for HDT out Function.
223 *
224 * Init required Debug register & heap, and will also fire a HDTOUT
225 * Command to let hdtout script do corresponding things.
226 *
227 * @param[in,out] StdHeader The Pointer of AGESA Header
228 *
229 **/
230VOID
231AmdIdsHdtOutInit (
232 IN OUT AMD_CONFIG_PARAMS *StdHeader
233 )
234{
235 ALLOCATE_HEAP_PARAMS AllocHeapParams;
236 HDTOUT_HEADER HdtoutHeader;
237 UINT8 Persist;
238 AGESA_STATUS IgnoreSts;
239 HDTOUT_HEADER *pHdtoutHeader;
240
241 IDS_FUNCLIST_EXTERN ();
242 if (AmdIdsHdtOutSupport ()) {
243 AmdIdsHdtOutRegisterInit (StdHeader);
244 // Initialize HDTOUT Header
245 HdtoutHeader.Signature = HDTOUT_HEADER_SIGNATURE;
246 HdtoutHeader.Version = HDTOUT_VERSION;
247 HdtoutHeader.BufferSize = HDTOUT_DEFAULT_BUFFER_SIZE;
248 HdtoutHeader.DataIndex = 0;
249 HdtoutHeader.PrintCtrl = HDTOUT_PRINTCTRL_ON;
250 HdtoutHeader.NumBreakpointUnit = 0;
251 HdtoutHeader.FuncListAddr = (UINT32) (UINT64) IDS_FUNCLIST_ADDR;
252 HdtoutHeader.StatusStr[0] = 0;
253 HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON;
254 HdtoutHeader.EnableMask = 0;
255 HdtoutHeader.ConsoleFilter = IDS_DEBUG_PRINT_MASK;
256
257 // Trigger HDTOUT breakpoint to get inputs from script
258 IdsOutPort (HDTOUT_INIT, (UINT32) (UINT64) &HdtoutHeader, 0);
259 // Disable AP HDTOUT if set BspOnlyFlag
260 if (HdtoutHeader.BspOnlyFlag == HDTOUT_BSP_ONLY) {
261 if (!IsBsp (StdHeader, &IgnoreSts)) {
262 AmdIdsHdtOutRegisterRestore (StdHeader);
263 return;
264 }
265 }
266 // Convert legacy EnableMask to new ConsoleFilter
267 HdtoutHeader.ConsoleFilter |= HdtoutHeader.EnableMask;
268
269 // Disable the buffer if the size is not large enough
270 if (HdtoutHeader.BufferSize < 128) {
271 HdtoutHeader.BufferSize = 0;
272 HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_OFF;
273 } else {
274 HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON;
275 }
276
277 // Check if Hdtout header have been initialed, if so it must 2nd time come here
278 if (AmdIdsHdtoutGetHeader (&pHdtoutHeader, StdHeader)) {
279 Persist = HEAP_SYSTEM_MEM;
280 } else {
281 Persist = HEAP_LOCAL_CACHE;
282 }
283
284 // Allocate heap
285 do {
286 AllocHeapParams.RequestedBufferSize = HdtoutHeader.BufferSize + sizeof (HdtoutHeader) - 2;
287 AllocHeapParams.BufferHandle = IDS_HDT_OUT_BUFFER_HANDLE;
288 AllocHeapParams.Persist = Persist;
289 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
290 break;
291 } else {
292 IdsOutPort (HDTOUT_ERROR, HDTOUT_ERROR_HEAP_ALLOCATION, AllocHeapParams.RequestedBufferSize);
293 HdtoutHeader.BufferSize -= 256;
294 }
295 } while ((HdtoutHeader.BufferSize & 0x8000) == 0);
296 // If the buffer have been successfully allocated?
297 if ((HdtoutHeader.BufferSize & 0x8000) == 0) {
298 LibAmdWriteCpuReg (DR3_REG, (UINT32) (UINT64) AllocHeapParams.BufferPtr);
299 LibAmdMemCopy (AllocHeapParams.BufferPtr, &HdtoutHeader, sizeof (HdtoutHeader) - 2, StdHeader);
300 } else {
301 /// Clear DR3_REG
302 IdsOutPort (HDTOUT_ERROR, HDTOUT_ERROR_HEAP_AllOCATE_FAIL, IDS_DEBUG_PRINT_MASK);
303 LibAmdWriteCpuReg (DR3_REG, 0);
304 }
305 }
306}
307
308/**
309 *
310 * Flush all HDTOUT buffer data before HOB transfer
311 *
312 * @param[in,out] StdHeader The Pointer of AGESA Header
313 *
314 **/
315VOID
316AmdIdsHdtOutBufferFlush (
317 IN OUT AMD_CONFIG_PARAMS *StdHeader
318 )
319{
320 HDTOUT_HEADER *HdtoutHeaderPtr ;
321
322 if (AmdIdsHdtOutSupport ()) {
323 if (AmdIdsHdtoutGetHeader (&HdtoutHeaderPtr, StdHeader)) {
324 if ((HdtoutHeaderPtr->PrintCtrl == HDTOUT_PRINTCTRL_ON) &&
325 (HdtoutHeaderPtr->OutBufferMode == HDTOUT_BUFFER_MODE_ON)) {
326 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINT64) HdtoutHeaderPtr->Data, HdtoutHeaderPtr->DataIndex);
327 HdtoutHeaderPtr->DataIndex = 0;
328 }
329 }
330 }
331}
332
333/**
334 * Exit function for HDT out Function for each cores
335 *
336 * @param[in] Ignored no used
337 * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS.
338 *
339 * @retval AGESA_SUCCESS Success
340 * @retval AGESA_ERROR meet some error
341 *
342 **/
343AGESA_STATUS
344AmdIdsHdtOutExitCoreTask (
345 IN VOID *Ignored,
346 IN OUT AMD_CONFIG_PARAMS *StdHeader
347 )
348{
349 HDTOUT_HEADER *HdtoutHeaderPtr;
350
351 if (AmdIdsHdtoutGetHeader (&HdtoutHeaderPtr, StdHeader)) {
352 if ((HdtoutHeaderPtr->PrintCtrl == HDTOUT_PRINTCTRL_ON) &&
353 (HdtoutHeaderPtr->OutBufferMode == HDTOUT_BUFFER_MODE_ON)) {
354 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINT64) HdtoutHeaderPtr->Data, HdtoutHeaderPtr->DataIndex);
355 }
356 }
357 IdsOutPort (HDTOUT_EXIT, (UINT32) (UINT64) HdtoutHeaderPtr, 0);
358
359 AmdIdsHdtOutRegisterRestore (StdHeader);
360
361 return AGESA_SUCCESS;
362}
363/**
364 *
365 * Exit function for HDT out Function.
366 *
367 * Restore debug register and Deallocate heap, and will also fire a HDTOUT
368 * Command to let hdtout script do corresponding things.
369 *
370 * @param[in,out] StdHeader The Pointer of AGESA Header
371 *
372 **/
373VOID
374AmdIdsHdtOutExit (
375 IN OUT AMD_CONFIG_PARAMS *StdHeader
376 )
377{
378 IDSAPLATETASK IdsApLateTask;
379 if (AmdIdsHdtOutSupport ()) {
380 IdsApLateTask.ApTask = (PF_IDS_AP_TASK) AmdIdsHdtOutExitCoreTask;
381 IdsApLateTask.ApTaskPara = NULL;
382 IdsAgesaRunFcnOnAllCoresLate (&IdsApLateTask, StdHeader);
383 HeapDeallocateBuffer (IDS_HDT_OUT_BUFFER_HANDLE, StdHeader);
384 }
385}
386
387/**
388 *
389 * Exit function for HDT out Function of S3 Resume
390 *
391 * Restore debug register and Deallocate heap, and will also fire a HDTOUT
392 * Command to let hdtout script do corresponding things.
393 *
394 * @param[in,out] StdHeader The Pointer of AGESA Header
395 *
396 **/
397VOID
398AmdIdsHdtOutS3Exit (
399 IN OUT AMD_CONFIG_PARAMS *StdHeader
400 )
401{
402 AGESA_STATUS AgesaStatus;
403
404 if (AmdIdsHdtOutSupport ()) {
405 //Ap debug print exit have been done at the end of AmdInitResume, so we only BSP at here
406 AmdIdsHdtOutExitCoreTask (NULL, StdHeader);
407 if (IsBsp (StdHeader, &AgesaStatus)) {
408 HeapDeallocateBuffer (IDS_HDT_OUT_BUFFER_HANDLE, StdHeader);
409 }
410 }
411}
412/**
413 *
414 * Exit function for HDT out Function of S3 Resume
415 *
416 * Restore debug register and Deallocate heap, and will also fire a HDTOUT
417 * Command to let hdtout script do corresponding things.
418 *
419 * @param[in,out] StdHeader The Pointer of AGESA Header
420 *
421 **/
422VOID
423AmdIdsHdtOutS3ApExit (
424 IN OUT AMD_CONFIG_PARAMS *StdHeader
425 )
426{
427 AP_TASK TaskPtr;
428 UINT32 Ignored;
429 UINT32 BscSocket;
430 UINT32 BscCoreNum;
431 UINT32 Core;
432 UINT32 Socket;
433 UINT32 NumberOfSockets;
434 UINT32 NumberOfCores;
435 AGESA_STATUS IgnoredSts;
436
437 if (AmdIdsHdtOutSupport ()) {
438 // run code on all APs except BSP
439 TaskPtr.FuncAddress.PfApTaskI = (PF_AP_TASK_I)AmdIdsHdtOutExitCoreTask;
440 TaskPtr.DataTransfer.DataSizeInDwords = 0;
441 TaskPtr.DataTransfer.DataPtr = NULL;
442 TaskPtr.DataTransfer.DataTransferFlags = 0;
443 TaskPtr.ExeFlags = WAIT_FOR_CORE;
444
445 NumberOfSockets = GetPlatformNumberOfSockets ();
446 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
447
448 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
449 if (IsProcessorPresent (Socket, StdHeader)) {
450 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
451 for (Core = 0; Core < NumberOfCores; Core++) {
452 if ((Socket != BscSocket) || (Core != BscCoreNum)) {
453 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
454 }
455 }
456 }
457 }
458 }
459 }
460}
461
462/**
463 * Print formated string with accerate buffer
464 * Flow out only when buffer will full
465 *
466 * @param[in] Buffer - Point to input buffer
467 * @param[in] BufferSize - Buffer size
468 * @param[in] HdtoutHeaderPtr - Point to Hdtout Header
469 *
470**/
471VOID
472AmdIdsHdtOutPrintWithBuffer (
473 IN CHAR8 *Buffer,
474 IN UINTN BufferSize,
475 IN HDTOUT_HEADER *HdtoutHeaderPtr
476 )
477{
478 if ((HdtoutHeaderPtr == NULL) || (Buffer == NULL)) {
479 ASSERT (FALSE);
480 return;
481 }
482
483 while (BufferSize--) {
484 if (HdtoutHeaderPtr->DataIndex >= HdtoutHeaderPtr->BufferSize) {
485 //Flow out current buffer, and clear the index
486 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINTN) &HdtoutHeaderPtr->Data[0], HdtoutHeaderPtr->BufferSize);
487 HdtoutHeaderPtr->DataIndex = 0;
488 }
489 HdtoutHeaderPtr->Data[HdtoutHeaderPtr->DataIndex++] = *(Buffer++);
490 }
491}
492/**
493 * Save HDTOUT context, use for break point function
494 *
495 * @param[in] Buffer - Point to input buffer
496 * @param[in] BufferSize - Buffer size
497 * @param[in] HdtoutHeaderPtr - Point to Hdtout Header
498 *
499**/
500VOID
501AmdIdsHdtOutSaveContext (
502 IN CHAR8 *Buffer,
503 IN UINTN BufferSize,
504 IN HDTOUT_HEADER *HdtoutHeaderPtr
505 )
506{
507 UINTN i;
508 UINTN j;
509 UINTN ArrayIndex;
510 UINTN unusedPrefix;
511 UINTN ArrayLength;
512 BOOLEAN SaveStatus;
513
514 ArrayLength = 0;
515
516 // Look for the start of the first ASCII
517 for (i = 0; i < BufferSize - 1; i++) {
518 if ((Buffer[i] > 32) && (Buffer[i] < 127)) {
519 break;
520 }
521 }
522
523 unusedPrefix = i;
524 //ASSERT if no "\n" in status string
525 ASSERT (AmdIdsSubStr (&Buffer[i], "\n"));
526
527 if (i < (BufferSize - 1)) {
528 // Match the first word in StatusStr
529 SaveStatus = FALSE;
530 for (j = 0; !SaveStatus && (HdtoutHeaderPtr->StatusStr[j] != 0); j++) {
531 for (; (Buffer[i] == HdtoutHeaderPtr->StatusStr[j]) && (i < BufferSize); i++, j++) {
532 ArrayLength++;
533 if (Buffer[i] == ' ') {
534 ArrayIndex = j;
535 for (; HdtoutHeaderPtr->StatusStr[j] != '\n'; j++) {
536 ArrayLength++;
537 }
538 // Remove old entry if it's size does not fit
539 if (ArrayLength != ((UINT32) BufferSize - unusedPrefix)) {
540 for (++j; HdtoutHeaderPtr->StatusStr[j] != 0; j++) {
541 HdtoutHeaderPtr->StatusStr[j - ArrayLength] = HdtoutHeaderPtr->StatusStr[j];
542 }
543 j = j - ArrayLength - 1;
544 i = unusedPrefix;
545 // Mark the end of string
546 HdtoutHeaderPtr->StatusStr[j + BufferSize - unusedPrefix + 1] = 0;
547 } else {
548 j = ArrayIndex - 1;
549 }
550
551 // Word match, exit for saving
552 SaveStatus = TRUE;
553 break;
554 }
555 }
556 }
557
558 // Copy string to StatusStr
559 if ((HdtoutHeaderPtr->StatusStr[j] == 0) || SaveStatus) {
560 for (; i < BufferSize; j++, i++) {
561 HdtoutHeaderPtr->StatusStr[j] = Buffer[i];
562 }
563 }
564
565 if (!SaveStatus) {
566 // Mark the end of string if not done so
567 HdtoutHeaderPtr->StatusStr[j] = 0;
568 }
569 }
570}
571
572BOOLEAN
573AmdIdsHdtOutBreakPointUnit (
574 IN OUT BREAKPOINT_UNIT **pBpunitptr,
575 IN OUT UINT32 *numBp,
576 IN HDTOUT_HEADER *HdtoutHeaderPtr,
577 IN CHAR8 *Buffer
578 )
579{
580 BOOLEAN isMatched;
581 CHAR8 *PCmpStr;
582 CHAR8 *Pbpstr;
583 BREAKPOINT_UNIT *pBpunit;
584
585 pBpunit = *pBpunitptr;
586 if ((pBpunit == NULL) ||
587 (numBp == NULL) ||
588 (HdtoutHeaderPtr == NULL) ||
589 (*numBp == 0)) {
590 ASSERT (FALSE);
591 return FALSE;
592 }
593 //Get to be compared string
594 if (pBpunit->BpFlag == IDS_HDTOUT_BPFLAG_FORMAT_STR) {
595 PCmpStr = Buffer;
596 } else {
597 PCmpStr = HdtoutHeaderPtr->StatusStr;
598 }
599 //Get BreakPoint string
600 Pbpstr = HdtoutHeaderPtr->BreakpointList + pBpunit->BpStrOffset;
601 isMatched = AmdIdsSubStr (PCmpStr, Pbpstr);
602 //Point to next one, and decrease the numbp
603 *pBpunitptr = ++pBpunit;
604 (*numBp)--;
605 return isMatched;
606}
607/**
608 * Process HDTOUT breakpoint
609 *
610 * @param[in] Buffer - Point to input buffer
611 * @param[in] BufferSize - Buffer size
612 * @param[in] HdtoutHeaderPtr - Point to Hdtout Header
613 *
614**/
615VOID
616AmdIdsHdtOutBreakPoint (
617 IN CHAR8 *Buffer,
618 IN UINTN BufferSize,
619 IN HDTOUT_HEADER *HdtoutHeaderPtr
620 )
621{
622 UINT32 numBp;
623 BREAKPOINT_UNIT *Pbpunit;
624 BOOLEAN isMatched;
625 UINT32 i;
626 Pbpunit = (BREAKPOINT_UNIT *) &HdtoutHeaderPtr->BreakpointList[0];
627 numBp = HdtoutHeaderPtr->NumBreakpointUnit;
628
629 for (;;) {
630 if (Pbpunit->AndFlag == IDS_HDTOUT_BP_AND_ON) {
631 isMatched = TRUE;
632 do {
633 isMatched &= AmdIdsHdtOutBreakPointUnit (&Pbpunit, &numBp, HdtoutHeaderPtr, Buffer);
634 } while ((Pbpunit->AndFlag == IDS_HDTOUT_BP_AND_ON) &&
635 (isMatched == TRUE) &&
636 (numBp > 0));
637 //Next one is IDS_HDTOUT_BP_AND_OFF
638 if (numBp > 0) {
639 if (isMatched == TRUE) {
640 isMatched &= AmdIdsHdtOutBreakPointUnit (&Pbpunit, &numBp, HdtoutHeaderPtr, Buffer);
641 } else {
642 Pbpunit++;
643 numBp--;
644 }
645 }
646 } else {
647 isMatched = AmdIdsHdtOutBreakPointUnit (&Pbpunit, &numBp, HdtoutHeaderPtr, Buffer);
648 }
649 if ((isMatched == TRUE) || (numBp == 0)) {
650 break;
651 }
652 }
653 //Do action
654 if (isMatched) {
655// AmdIdsSerialPrint (Buffer, BufferSize, NULL);
656 Pbpunit--;
657 switch (Pbpunit->Action) {
658 case HDTOUT_BP_ACTION_HALT:
659 i = (UINT32) (Pbpunit - ((BREAKPOINT_UNIT *) &HdtoutHeaderPtr->BreakpointList[0]));
660 IdsOutPort (HDTOUT_BREAKPOINT, (UINT32) (UINTN) Buffer, ( i << 16) | (UINT32) BufferSize);
661 break;
662 case HDTOUT_BP_ACTION_PRINTON:
663 if (HdtoutHeaderPtr->PrintCtrl != 1) {
664 HdtoutHeaderPtr->PrintCtrl = 1;
665 if (HdtoutHeaderPtr->OutBufferMode == HDTOUT_BUFFER_MODE_ON) {
666 AmdIdsHdtOutPrintWithBuffer (Buffer, BufferSize, HdtoutHeaderPtr);
667 } else {
668 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINTN) Buffer, (UINT32) BufferSize);
669 }
670 }
671 break;
672 case HDTOUT_BP_ACTION_PRINTOFF:
673 if (HdtoutHeaderPtr->PrintCtrl != 0) {
674 HdtoutHeaderPtr->PrintCtrl = 0;
675 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINTN) Buffer, (UINT32)BufferSize);
676 }
677 break;
678 default:
679 ASSERT (FALSE);
680 }
681 }
682}
683
684
685/**
686 * Print formated string to HDTOUT
687 *
688 * @param[in] Buffer - Point to input buffer
689 * @param[in] BufferSize - Buffer size
690 * @param[in] debugPrintPrivate - Option
691 *
692**/
693VOID
694AmdIdsHdtOutPrint (
695 IN CHAR8 *Buffer,
696 IN UINTN BufferSize,
697 IN IDS_DEBUG_PRINT_PRIVATE_DATA *debugPrintPrivate
698 )
699{
700 HDTOUT_HEADER *HdtoutHeaderPtr;
701 if (AmdIdsHdtoutGetHeader (&HdtoutHeaderPtr, NULL)) {
702 //Print Function
703 if (HdtoutHeaderPtr->PrintCtrl == HDTOUT_PRINTCTRL_ON) {
704 if (HdtoutHeaderPtr->OutBufferMode == HDTOUT_BUFFER_MODE_ON) {
705 AmdIdsHdtOutPrintWithBuffer (Buffer, BufferSize, HdtoutHeaderPtr);
706 } else {
707 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINTN) Buffer, (UINT32) BufferSize);
708 }
709 }
710 //Check BreakPoint
711 if (HdtoutHeaderPtr->NumBreakpointUnit) {
712 AmdIdsHdtOutBreakPoint (Buffer, BufferSize, HdtoutHeaderPtr);
713 if (debugPrintPrivate->saveContext) {
714 AmdIdsHdtOutSaveContext (Buffer, BufferSize, HdtoutHeaderPtr);
715 debugPrintPrivate->saveContext = FALSE;
716 }
717 }
718 } else {
719 //No HDTOUT header found print directly without buffer
720 IdsOutPort (HDTOUT_PRINT, (UINT32) (UINTN) Buffer, (UINT32) BufferSize);
721 }
722}
723
724/**
725 * Init local private data for HDTOUT
726 *
727 * @param[in] Flag - filter flag
728 * @param[in] debugPrintPrivate - Point to debugPrintPrivate
729 *
730**/
731VOID
732AmdIdsHdtOutInitPrivateData (
733 IN UINT64 Flag,
734 IN IDS_DEBUG_PRINT_PRIVATE_DATA *debugPrintPrivate
735 )
736{
737 if (Flag == MEM_STATUS) {
738 debugPrintPrivate->saveContext = TRUE;
739 }
740}
741
742CONST IDS_DEBUG_PRINT ROMDATA IdsDebugPrintHdtoutInstance =
743{
744 AmdIdsHdtOutSupport,
745 AmdIdsHdtOutGetFilter,
746 AmdIdsHdtOutInitPrivateData,
747 AmdIdsHdtOutPrint
748};
749
750
751