]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/CpuDxe/Exception.c
Fix bug
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / Exception.c
index bc67fc44ceb179a482f97a1ba623e236e6be23e2..f795c431a2dd8109edeabcb4a86e82f96f26080a 100644 (file)
@@ -14,7 +14,6 @@
 \r
 #include "CpuDxe.h" \r
 \r
-EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;\r
 \r
 VOID\r
 ExceptionHandlersStart (\r
@@ -123,126 +122,6 @@ RegisterDebuggerInterruptHandler (
 \r
 \r
 \r
-\r
-CHAR8 *\r
-GetImageName (\r
-  IN  UINT32  FaultAddress,\r
-  OUT UINT32  *ImageBase,\r
-  OUT UINT32  *PeCoffSizeOfHeaders\r
-  )\r
-{\r
-  EFI_DEBUG_IMAGE_INFO  *DebugTable;\r
-  UINTN                 Entry;\r
-  CHAR8                 *Address;\r
-\r
-  \r
-  DebugTable = gDebugImageTableHeader->EfiDebugImageInfoTable;\r
-  if (DebugTable == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  Address = (CHAR8 *)(UINTN)FaultAddress;\r
-  for (Entry = 0; Entry < gDebugImageTableHeader->TableSize; Entry++, DebugTable++) {\r
-    if (DebugTable->NormalImage != NULL) {\r
-      if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && \r
-          (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {\r
-        if ((Address >= (CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) &&\r
-            (Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize))) {\r
-          *ImageBase = (UINT32)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;\r
-          *PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*ImageBase);\r
-          return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);\r
-        }           \r
-      }\r
-    }  \r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-typedef struct {\r
-  UINT32  Bit;\r
-  CHAR8   Char;\r
-} CPSR_CHAR;\r
-\r
-CPSR_CHAR gCpsrChar[] = {\r
-  { 31, 'n' },\r
-  { 30, 'z' },\r
-  { 29, 'c' },\r
-  { 28, 'v' },\r
-  { 27, 'q' },\r
-\r
-  { 8, 'a' },\r
-  { 7, 'i' },\r
-  { 6, 'f' },\r
-  { 5, 't' },\r
-  { 0, '?' }\r
-};\r
-\r
-\r
-VOID\r
-CpsrString (\r
-  IN  UINT32  Cpsr,\r
-  OUT CHAR8   *ReturnStr\r
-  )\r
-{\r
-  UINTN Index;\r
-  CHAR8 *Str = ReturnStr;\r
-  CHAR8 *ModeStr;\r
-  \r
-  for (Index = 0; gCpsrChar[Index].Bit != 0; Index++, Str++) {\r
-    *Str = gCpsrChar[Index].Char;\r
-    if ((Cpsr & (1 << gCpsrChar[Index].Bit)) != 0) {\r
-      // Concert to upper case if bit is set\r
-      *Str &= ~0x20;\r
-    }\r
-  }\r
-  \r
-  *Str++ = '_';\r
-  *Str = '\0';\r
-  \r
-  switch (Cpsr & 0x1f) {\r
-  case 0x17:\r
-    ModeStr = "abt";\r
-    break;\r
-  case 0x011:\r
-    ModeStr = "fiq";\r
-    break;\r
-  case 0x12:\r
-    ModeStr = "irq";\r
-    break;\r
-  case 0x13:\r
-    ModeStr = "svc";\r
-    break;\r
-  case 0x1f:\r
-    ModeStr = "sys";\r
-    break;\r
-  case 0x1b:\r
-    ModeStr = "und";\r
-    break;\r
-  case 0x10:\r
-    ModeStr = "usr";\r
-    break;\r
-  \r
-  default:\r
-    ModeStr = "???";\r
-    break;\r
-  }\r
-  \r
-  AsciiStrCat (Str, ModeStr);\r
-  return;\r
-}  \r
-  \r
-CHAR8 *gExceptionTypeString[] = {\r
-  "Reset",\r
-  "Undefined Instruction",\r
-  "SWI",\r
-  "Prefetch Abort",\r
-  "Data Abort",\r
-  "Undefined",\r
-  "IRQ",\r
-  "FIQ"\r
-};\r
-\r
 VOID\r
 EFIAPI\r
 CommonCExceptionHandler (\r
@@ -285,43 +164,7 @@ CommonCExceptionHandler (
     return;\r
   }\r
 \r
-  //\r
-  // Code after here is the default exception handler... Dump the context\r
-  //\r
-  DEBUG ((EFI_D_ERROR, "\n%a Exception PC at 0x%08x  CPSR 0x%08x ", gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR));\r
-  DEBUG_CODE_BEGIN ();\r
-    CHAR8   *Pdb;\r
-    UINT32  ImageBase;\r
-    UINT32  PeCoffSizeOfHeader;\r
-    UINT32  Offset;\r
-    CHAR8   CpsrStr[32];  // char per bit. Lower 5-bits are mode that is a 3 char string\r
-    \r
-    CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);\r
-    DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));\r
-  \r
-    Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);\r
-    Offset = SystemContext.SystemContextArm->PC - ImageBase;\r
-    if (Pdb != NULL) {\r
-      DEBUG ((EFI_D_ERROR, "%a\n", Pdb));\r
-\r
-      //\r
-      // A PE/COFF image loads its headers into memory so the headers are \r
-      // included in the linked addressess. ELF and Mach-O images do not\r
-      // include the headers so the first byte of the image is usually\r
-      // text (code). If you look at link maps from ELF or Mach-O images\r
-      // you need to subtact out the size of the PE/COFF header to get\r
-      // get the offset that matches the link map. \r
-      //\r
-      DEBUG ((EFI_D_ERROR, "loadded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));\r
-    }\r
-  DEBUG_CODE_END ();\r
-  DEBUG ((EFI_D_ERROR, "\n  R0 0x%08x   R1 0x%08x   R2 0x%08x   R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3));\r
-  DEBUG ((EFI_D_ERROR, "  R4 0x%08x   R5 0x%08x   R6 0x%08x   R7 0x%08x\n", SystemContext.SystemContextArm->R4, SystemContext.SystemContextArm->R5, SystemContext.SystemContextArm->R6, SystemContext.SystemContextArm->R7));\r
-  DEBUG ((EFI_D_ERROR, "  R8 0x%08x   R9 0x%08x  R10 0x%08x  R11 0x%08x\n", SystemContext.SystemContextArm->R8, SystemContext.SystemContextArm->R9, SystemContext.SystemContextArm->R10, SystemContext.SystemContextArm->R11));\r
-  DEBUG ((EFI_D_ERROR, " R12 0x%08x   SP 0x%08x   LR 0x%08x   PC 0x%08x\n", SystemContext.SystemContextArm->R12, SystemContext.SystemContextArm->SP, SystemContext.SystemContextArm->LR, SystemContext.SystemContextArm->PC));\r
-  DEBUG ((EFI_D_ERROR, "DFSR 0x%08x DFAR 0x%08x IFSR 0x%08x IFAR 0x%08x\n\n", SystemContext.SystemContextArm->DFSR, SystemContext.SystemContextArm->DFAR, SystemContext.SystemContextArm->IFSR, SystemContext.SystemContextArm->IFAR));\r
-\r
-  ASSERT (FALSE);\r
+  DefaultExceptionHandler (ExceptionType, SystemContext);\r
 }\r
 \r
 \r
@@ -335,31 +178,24 @@ InitializeExceptions (
   UINTN                Offset;\r
   UINTN                Length;\r
   UINTN                Index;\r
-  BOOLEAN              Enabled;\r
+  BOOLEAN              IrqEnabled;\r
+  BOOLEAN              FiqEnabled;\r
   EFI_PHYSICAL_ADDRESS Base;\r
-\r
-  Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader);\r
-  if (EFI_ERROR (Status)) {\r
-    gDebugImageTableHeader = NULL;\r
-  }\r
+  UINT32               *VectorBase;\r
 \r
   //\r
   // Disable interrupts\r
   //\r
-  Cpu->GetInterruptState (Cpu, &Enabled);\r
+  Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
   Cpu->DisableInterrupt (Cpu);\r
 \r
   //\r
-  // Initialize the C entry points for interrupts\r
+  // EFI does not use the FIQ, but a debugger might so we must disable \r
+  // as we take over the exception vectors. \r
   //\r
-  for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
-    Status = RegisterInterruptHandler (Index, NULL);\r
-    ASSERT_EFI_ERROR (Status);\r
-    \r
-    Status = RegisterDebuggerInterruptHandler (Index, NULL);\r
-    ASSERT_EFI_ERROR (Status);\r
-  }\r
-  \r
+  FiqEnabled = ArmGetFiqState ();\r
+  ArmDisableFiq ();\r
+\r
   //\r
   // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
   //\r
@@ -369,6 +205,7 @@ InitializeExceptions (
   // Reserve space for the exception handlers\r
   //\r
   Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);\r
+  VectorBase = (UINT32 *)(UINTN)Base;\r
   Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);\r
   // If the request was for memory that's not in the memory map (which is often the case for 0x00000000\r
   // on embedded systems, for example, we don't want to hang up.  So we'll check here for a status of \r
@@ -377,7 +214,25 @@ InitializeExceptions (
     ASSERT_EFI_ERROR (Status);\r
   }\r
 \r
-  CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length);\r
+  // Save existing vector table, in case debugger is already hooked in\r
+  CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));\r
+\r
+  //\r
+  // Initialize the C entry points for interrupts\r
+  //\r
+  for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
+    Status = RegisterInterruptHandler (Index, NULL);\r
+    ASSERT_EFI_ERROR (Status);\r
+    \r
+    if (VectorBase[Index] == 0xEAFFFFFE) {\r
+      // Exception handler contains branch to vector location (jmp $) so no handler\r
+      // NOTE: This code assumes vectors are ARM and not Thumb code\r
+      gDebuggerExceptionHandlers[Index] = NULL;\r
+    }\r
+  }\r
+\r
+  // Copy our assembly code into the page that contains the exception vectors. \r
+  CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
 \r
   //\r
   // Patch in the common Assembly exception handler\r
@@ -388,7 +243,11 @@ InitializeExceptions (
   // Flush Caches since we updated executable stuff\r
   InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);\r
 \r
-  if (Enabled) {\r
+  if (FiqEnabled) {\r
+    ArmEnableFiq ();\r
+  }\r
+\r
+  if (IrqEnabled) {\r
     // \r
     // Restore interrupt state\r
     //\r