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 
23 Module Name:
24 
25 
26   PlatformStatusCode.c
27 
28 Abstract:
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 
40 typedef 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 //
55 BOOLEAN
56 PeiCodeTypeToPostCode (
57   IN  EFI_STATUS_CODE_TYPE    CodeType,
58   IN  EFI_STATUS_CODE_VALUE   Value,
59   OUT UINT8                   *PostCode
60   );
61 
62 /**
Port80ReportStatusCode(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN CONST EFI_GUID * CallerId,IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL)63   Provide a port 80 status code
64 
65   @param Same as ReportStatusCode PPI
66 
67   @retval EFI_SUCCESS   Always returns success.
68 
69 **/
70 EFI_STATUS
71 EFIAPI
72 Port80ReportStatusCode (
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 /**
SerialReportStatusCode(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN CONST EFI_GUID * CallerId,IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL)108   Provide a serial status code
109 
110   @param Same as ReportStatusCode PPI
111 
112   @retval EFI_SUCCESS   Always returns success.
113 
114 **/
115 EFI_STATUS
116 EFIAPI
117 SerialReportStatusCode (
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.
PlatformReportStatusCode(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN CONST EFI_GUID * CallerId,IN CONST EFI_STATUS_CODE_DATA * Data OPTIONAL)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 **/
259 EFI_STATUS
260 EFIAPI
261 PlatformReportStatusCode (
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.
InstallMonoStatusCode(IN EFI_FFS_FILE_HEADER * FfsHeader,IN CONST EFI_PEI_SERVICES ** PeiServices)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 **/
290 EFI_STATUS
291 EFIAPI
292 InstallMonoStatusCode (
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 
317 extern PCH_STEPPING EFIAPI PchStepping (VOID);
318 
319 VOID
320 RamDebugInit (
321   VOID
322   );
323 
EnableInternalUart(VOID)324 /**
325   Enable legacy decoding on ICH6
326 
327   @param none
328 
329   @retval EFI_SUCCESS     Always returns success.
330 
331 **/
332 EFI_STATUS
333 EnableInternalUart(
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.
PlatformInitializeStatusCode(IN EFI_FFS_FILE_HEADER * FfsHeader,IN CONST EFI_PEI_SERVICES ** PeiServices)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 **/
374 VOID
375 EFIAPI
376 PlatformInitializeStatusCode (
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