Home | History | Annotate | Download | only in MonoStatusCode
      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