text: /** @file
    CPU Exception Handler Library common functions.
  
    Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
    SPDX-License-Identifier: BSD-2-Clause-Patent
  
  **/
  
  #include "CpuExceptionCommon.h"
  
  //
  // Error code flag indicating whether or not an error code will be
  // pushed on the stack if an exception occurs.
  //
  // 1 means an error code will be pushed, otherwise 0
  //
  CONST UINT32  mErrorCodeFlag = 0x20227d00;
  
  //
  // Define the maximum message length
  //
  #define MAX_DEBUG_MESSAGE_LENGTH  0x100
  
  CONST CHAR8  mExceptionReservedStr[] = "Reserved";
  CONST CHAR8  *mExceptionNameStr[]    = {
    "#DE - Divide Error",
    "#DB - Debug",
    "NMI Interrupt",
    "#BP - Breakpoint",
    "#OF - Overflow",
    "#BR - BOUND Range Exceeded",
    "#UD - Invalid Opcode",
    "#NM - Device Not Available",
    "#DF - Double Fault",
    "Coprocessor Segment Overrun",
    "#TS - Invalid TSS",
    "#NP - Segment Not Present",
    "#SS - Stack Fault Fault",
    "#GP - General Protection",
    "#PF - Page-Fault",
    "Reserved",
    "#MF - x87 FPU Floating-Point Error",
    "#AC - Alignment Check",
    "#MC - Machine-Check",
    "#XM - SIMD floating-point",
    "#VE - Virtualization",
    "#CP - Control Protection",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "Reserved",
    "#VC - VMM Communication",
  };
  
  #define EXCEPTION_KNOWN_NAME_NUM  (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
  
  /**
    Get ASCII format string exception name by exception type.
  
    @param ExceptionType  Exception type.
  
    @return  ASCII format string exception name.
  **/
  CONST CHAR8 *
  GetExceptionNameStr (
    IN EFI_EXCEPTION_TYPE  ExceptionType
    )
  {
    if ((UINTN)ExceptionType < EXCEPTION_KNOWN_NAME_NUM) {
      return mExceptionNameStr[ExceptionType];
    } else {
      return mExceptionReservedStr;
    }
  }
  
  /**
    Prints a message to the serial port.
  
    @param  Format      Format string for the message to print.
    @param  ...         Variable argument list whose contents are accessed
                        based on the format string specified by Format.
  
  **/
  VOID
  EFIAPI
  InternalPrintMessage (
    IN  CONST CHAR8  *Format,
    ...
    )
  {
    CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
    VA_LIST  Marker;
  
    //
    // Convert the message to an ASCII String
    //
    VA_START (Marker, Format);
    AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
    VA_END (Marker);
  
    //
    // Send the print string to a Serial Port
    //
    SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
  }
  
  /**
    Find and display image base address and return image base and its entry point.
  
    @param CurrentEip      Current instruction pointer.
  
  **/
  VOID
  DumpModuleImageInfo (
    IN  UINTN  CurrentEip
    )
  {
    EFI_STATUS  Status;
    UINTN       Pe32Data;
    VOID        *PdbPointer;
    VOID        *EntryPoint;
  
    Pe32Data = PeCoffSearchImageBase (CurrentEip);
    if (Pe32Data == 0) {
      InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
    } else {
      //
      // Find Image Base entry point
      //
      Status = PeCoffLoaderGetEntryPoint ((VOID *)Pe32Data, &EntryPoint);
      if (EFI_ERROR (Status)) {
        EntryPoint = NULL;
      }
  
      InternalPrintMessage ("!!!! Find image based on IP(0x%x) ", CurrentEip);
      PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data);
      if (PdbPointer != NULL) {
        InternalPrintMessage ("%a", PdbPointer);
      } else {
        InternalPrintMessage ("(No PDB) ");
      }
  
      InternalPrintMessage (
        " (ImageBase=%016lp, EntryPoint=%016p) !!!!\n",
        (VOID *)Pe32Data,
        EntryPoint
        );
    }
  }
  
  /**
    Read and save reserved vector information
  
    @param[in]  VectorInfo        Pointer to reserved vector list.
    @param[out] ReservedVector    Pointer to reserved vector data buffer.
    @param[in]  VectorCount       Vector number to be updated.
  
    @return EFI_SUCCESS           Read and save vector info successfully.
    @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
  
  **/
  EFI_STATUS
  ReadAndVerifyVectorInfo (
    IN  EFI_VECTOR_HANDOFF_INFO  *VectorInfo,
    OUT RESERVED_VECTORS_DATA    *ReservedVector,
    IN  UINTN                    VectorCount
    )
  {
    while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
      if (VectorInfo->Attribute > EFI_VECTOR_HANDOFF_HOOK_AFTER) {
        //
        // If vector attrubute is invalid
        //
        return EFI_INVALID_PARAMETER;
      }
  
      if (VectorInfo->VectorNumber < VectorCount) {
        ReservedVector[VectorInfo->VectorNumber].Attribute = VectorInfo->Attribute;
      }
  
      VectorInfo++;
    }
  
    return EFI_SUCCESS;
  }
  