1 /** @file 2 3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 4 5 This program and the accompanying materials are licensed and made available under 7 the terms and conditions of the BSD License that accompanies this distribution. 9 The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 13 15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 21 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 /** 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 /** 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. 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. 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 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. 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