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