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