1/** @file
2
3  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4
5
6  This program and the accompanying materials are licensed and made available under
7
8  the terms and conditions of the BSD License that accompanies this distribution.
9
10  The full text of the license may be found at
11
12  http://opensource.org/licenses/bsd-license.php.
13
14
15
16  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17
18  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19
20
21
22
23Module Name:
24
25
26  PlatformStatusCode.c
27
28Abstract:
29
30  Contains Platform specific implementations required to use status codes.
31
32--*/
33
34#include "PlatformStatusCode.h"
35#include <PchRegs.h>
36#include <PlatformBaseAddresses.h>
37#include <Library/PeiServicesLib.h>
38#include <Library/PcdLib.h>
39
40typedef struct {
41  EFI_STATUS_CODE_DATA  DataHeader;
42  EFI_HANDLE            Handle;
43} PEIM_FILE_HANDLE_EXTENDED_DATA;
44
45#define CONFIG_PORT0    0x4E
46#define PCI_IDX         0xCF8
47#define PCI_DAT         0xCFC
48
49#define PCI_LPC_BASE    (0x8000F800)
50#define PCI_LPC_REG(x)  (PCI_LPC_BASE + (x))
51
52//
53// Function implementations
54//
55BOOLEAN
56PeiCodeTypeToPostCode (
57  IN  EFI_STATUS_CODE_TYPE    CodeType,
58  IN  EFI_STATUS_CODE_VALUE   Value,
59  OUT UINT8                   *PostCode
60  );
61
62/**
63  Provide a port 80 status code
64
65  @param Same as ReportStatusCode PPI
66
67  @retval EFI_SUCCESS   Always returns success.
68
69**/
70EFI_STATUS
71EFIAPI
72Port80ReportStatusCode (
73  IN CONST EFI_PEI_SERVICES         **PeiServices,
74  IN EFI_STATUS_CODE_TYPE           CodeType,
75  IN EFI_STATUS_CODE_VALUE          Value,
76  IN UINT32                         Instance,
77  IN CONST EFI_GUID                 *CallerId,
78  IN CONST EFI_STATUS_CODE_DATA     *Data OPTIONAL
79  )
80
81{
82  EFI_STATUS               Status;
83  EFI_FV_FILE_INFO         FvFileInfo;
84  UINT16                   Port80Code = 0;
85
86  //
87  // Progress or error code, Output Port 80h card.
88  //
89  if (!PeiCodeTypeToPostCode (CodeType, Value, (UINT8 *)&Port80Code)) {
90    if ((Data != NULL) && (Value ==(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN))){
91      Status = PeiServicesFfsGetFileInfo (
92                 ((PEIM_FILE_HANDLE_EXTENDED_DATA *) (Data + 1))->Handle,
93                 &FvFileInfo
94                 );
95      if (!EFI_ERROR (Status)) {
96        Port80Code = (FvFileInfo.FileName.Data4[6]<<8) + (FvFileInfo.FileName.Data4[7]);
97      }
98    }
99  }
100  if (Port80Code != 0){
101    IoWrite16 (0x80, (UINT16) Port80Code);
102    DEBUG ((EFI_D_ERROR, "POSTCODE=<%04x>\n", Port80Code));
103  }
104  return  EFI_SUCCESS;
105}
106
107/**
108  Provide a serial status code
109
110  @param Same as ReportStatusCode PPI
111
112  @retval EFI_SUCCESS   Always returns success.
113
114**/
115EFI_STATUS
116EFIAPI
117SerialReportStatusCode (
118  IN CONST EFI_PEI_SERVICES         **PeiServices,
119  IN EFI_STATUS_CODE_TYPE           CodeType,
120  IN EFI_STATUS_CODE_VALUE          Value,
121  IN UINT32                         Instance,
122  IN CONST EFI_GUID                 * CallerId,
123  IN CONST EFI_STATUS_CODE_DATA     * Data OPTIONAL
124  )
125{
126  CHAR8           *Filename;
127  CHAR8           *Description;
128  CHAR8           *Format;
129  CHAR8           Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
130  UINT32          ErrorLevel;
131  UINT32          LineNumber;
132  UINTN           CharCount;
133  BASE_LIST       Marker;
134
135  Buffer[0] = '\0';
136
137  if (Data != NULL &&
138      ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
139    //
140    // Print ASSERT() information into output buffer.
141    //
142    CharCount = AsciiSPrint (
143                  Buffer,
144                  sizeof (Buffer),
145                  "\n\rPEI_ASSERT!: %a (%d): %a\n\r",
146                  Filename,
147                  LineNumber,
148                  Description
149                  );
150  } else if (Data != NULL &&
151             ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
152    //
153    // Print DEBUG() information into output buffer.
154    //
155    CharCount = AsciiBSPrint (
156                  Buffer,
157                  sizeof (Buffer),
158                  Format,
159                  Marker
160                  );
161  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
162    //
163    // Print ERROR information into output buffer.
164    //
165    CharCount = AsciiSPrint (
166                  Buffer,
167                  sizeof (Buffer),
168                  "ERROR: C%x:V%x I%x",
169                  CodeType,
170                  Value,
171                  Instance
172                  );
173
174    ASSERT(CharCount > 0);
175
176    if (CallerId != NULL) {
177      CharCount += AsciiSPrint (
178                     &Buffer[CharCount],
179                     (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
180                     " %g",
181                     CallerId
182                     );
183    }
184
185    if (Data != NULL) {
186      CharCount += AsciiSPrint (
187                     &Buffer[CharCount],
188                     (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
189                     " %x",
190                     Data
191                     );
192    }
193
194    CharCount += AsciiSPrint (
195                   &Buffer[CharCount],
196                   (sizeof (Buffer) - (sizeof (Buffer[0]) * CharCount)),
197                   "\n\r"
198                   );
199  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
200    //
201    // Print PROGRESS information into output buffer.
202    //
203    CharCount = AsciiSPrint (
204                  Buffer,
205                  sizeof (Buffer),
206                  "PROGRESS CODE: V%x I%x\n\r",
207                  Value,
208                  Instance
209                  );
210  } else if (Data != NULL &&
211             CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeStringGuid) &&
212             ((EFI_STATUS_CODE_STRING_DATA *) Data)->StringType == EfiStringAscii) {
213    //
214    // EFI_STATUS_CODE_STRING_DATA
215    //
216    CharCount = AsciiSPrint (
217                  Buffer,
218                  sizeof (Buffer),
219                  "%a\n\r",
220                  ((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii
221                  );
222  } else {
223    //
224    // Code type is not defined.
225    //
226    CharCount = AsciiSPrint (
227                  Buffer,
228                  sizeof (Buffer),
229                  "Undefined: C%x:V%x I%x\n\r",
230                  CodeType,
231                  Value,
232                  Instance
233                  );
234  }
235
236  //
237  // Call SerialPort Lib function to do print.
238  //
239  SerialPortWrite ((UINT8 *) Buffer, CharCount);
240
241  return EFI_SUCCESS;
242}
243
244/**
245
246  Call all status code listeners in the MonoStatusCode.
247
248  @param PeiServices    The PEI core services table.
249  @param CodeType       Type of Status Code.
250  @param Value          Value to output for Status Code.
251  @param Instance       Instance Number of this status code.
252  @param CallerId       ID of the caller of this status code.
253  @param Data           Optional data associated with this status code.
254
255  @retval EFI_SUCCESS              If status code is successfully reported.
256  @retval EFI_NOT_AVAILABLE_YET    If StatusCodePpi has not been installed.
257
258**/
259EFI_STATUS
260EFIAPI
261PlatformReportStatusCode (
262  IN  CONST EFI_PEI_SERVICES        **PeiServices,
263  IN EFI_STATUS_CODE_TYPE           CodeType,
264  IN EFI_STATUS_CODE_VALUE          Value,
265  IN UINT32                         Instance,
266  IN CONST EFI_GUID                 * CallerId,
267  IN CONST EFI_STATUS_CODE_DATA     * Data OPTIONAL
268  )
269{
270  //
271  // If we are in debug mode, we will allow serial status codes
272  //
273  SerialReportStatusCode (PeiServices, CodeType, Value, Instance, CallerId, Data);
274
275  Port80ReportStatusCode (PeiServices, CodeType, Value, Instance, CallerId, Data);
276
277  return EFI_SUCCESS;
278}
279
280/**
281  Install the PEIM.  Initialize listeners, publish the PPI and HOB for PEI and
282  DXE use respectively.
283
284  @param FfsHeader      FV this PEIM was loaded from.
285  @param PeiServices    General purpose services available to every PEIM.
286
287  @retval EFI_SUCCESS   The function always returns success.
288
289**/
290EFI_STATUS
291EFIAPI
292InstallMonoStatusCode (
293  IN EFI_FFS_FILE_HEADER       *FfsHeader,
294  IN CONST EFI_PEI_SERVICES    **PeiServices
295  )
296{
297
298  //
299  // Initialize all listeners
300  //
301  InitializeMonoStatusCode (FfsHeader, PeiServices);
302
303  //
304  // Publish the listener in a HOB for DXE use.
305  //
306  InitializeDxeReportStatusCode (PeiServices);
307
308  return EFI_SUCCESS;
309}
310
311#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3             BIT3 // UART IRQ3 Enable
312#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ4             BIT4 // UART IRQ4 Enable
313#define PCIEX_BASE_ADDRESS                        0xE0000000
314#define PciD31F0RegBase                           PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
315#define SB_RCBA                                   0xfed1c000
316
317extern PCH_STEPPING EFIAPI PchStepping (VOID);
318
319VOID
320RamDebugInit (
321  VOID
322  );
323
324/**
325  Enable legacy decoding on ICH6
326
327  @param none
328
329  @retval EFI_SUCCESS     Always returns success.
330
331**/
332EFI_STATUS
333EnableInternalUart(
334  VOID
335  )
336{
337
338  //
339  // Program and enable PMC Base.
340  //
341  IoWrite32 (PCI_IDX,  PCI_LPC_REG(R_PCH_LPC_PMC_BASE));
342  IoWrite32 (PCI_DAT,  (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN));
343
344  //
345  // Enable COM1 for debug message output.
346  //
347  MmioAndThenOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, (UINT32) (~(B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR + B_PCH_PMC_GEN_PMCON_PWROK_FLR)), BIT24);
348
349  //
350  // Silicon Steppings
351  //
352  if (PchStepping()>= PchB0)
353    MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ4);
354  else
355    MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3);
356  MmioAnd32(IO_BASE_ADDRESS + 0x0520, (UINT32)~(0x00000187));
357  MmioOr32 (IO_BASE_ADDRESS + 0x0520, (UINT32)0x81); // UART3_RXD-L
358  MmioAnd32(IO_BASE_ADDRESS + 0x0530, (UINT32)~(0x00000007));
359  MmioOr32 (IO_BASE_ADDRESS + 0x0530, (UINT32)0x1); // UART3_RXD-L
360  MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN);
361
362  return  EFI_SUCCESS;
363}
364
365/**
366  INIT the SIO. Ported this code and I don't undertand the comments either.
367
368  @param FfsHeader    FV this PEIM was loaded from.
369  @param PeiServices  General purpose services available to every PEIM.
370
371  None
372
373**/
374VOID
375EFIAPI
376PlatformInitializeStatusCode (
377  IN EFI_FFS_FILE_HEADER       *FfsHeader,
378  IN CONST EFI_PEI_SERVICES    **PeiServices
379  )
380{
381
382  //
383  // Enable internal COM1 on South Cluster.
384  //
385	EnableInternalUart();
386
387
388  //
389  // Initialize additional debug status code listeners.
390  //
391   SerialPortInitialize();
392
393}
394//#endif //EFI_DEBUG
395
396