]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
I fixed following bugs in EDKII.
[mirror_edk2.git] / EdkModulePkg / Universal / Ebc / Dxe / EbcInt.c
index 2a5d48a431f5875ea364201184c074943245167a..e38f5be7309d10ba913a7d6997b01cbb86597951 100644 (file)
@@ -77,6 +77,32 @@ EbcGetVersion (
   IN OUT UINT64           *Version\r
   );\r
 \r
+EFI_STATUS\r
+EFIAPI\r
+InitializeEbcCallback (\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+CommonEbcExceptionHandler (\r
+  IN EFI_EXCEPTION_TYPE   InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+EbcPeriodicNotifyFunction (\r
+  IN EFI_EVENT     Event,\r
+  IN VOID          *Context\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+EbcDebugPeriodic (\r
+  IN VM_CONTEXT *VmPtr\r
+  );\r
+\r
 //\r
 // These two functions and the  GUID are used to produce an EBC test protocol.\r
 // This functionality is definitely not required for execution.\r
@@ -158,6 +184,12 @@ static EFI_PERIODIC_CALLBACK  mDebugPeriodicCallback
 static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
 static EFI_GUID               mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID;\r
 \r
+//\r
+// Event for Periodic callback\r
+//\r
+static EFI_EVENT              mEbcPeriodicEvent;\r
+VM_CONTEXT                    *mVmPtr = NULL;\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeEbcDriver (\r
@@ -190,6 +222,9 @@ Returns:
   UINTN                       Index;\r
   BOOLEAN                     Installed;\r
 \r
+  EbcProtocol      = NULL;\r
+  EbcDebugProtocol = NULL;\r
+\r
   //\r
   // Allocate memory for our protocol. Then fill in the blanks.\r
   //\r
@@ -271,7 +306,7 @@ Returns:
                   (VOID **) &EbcDebugProtocol\r
                   );\r
   if (Status != EFI_SUCCESS) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
   }\r
 \r
   EbcDebugProtocol->Isa                         = IsaEbc;\r
@@ -294,7 +329,14 @@ Returns:
   //\r
   if (EFI_ERROR (Status)) {\r
     gBS->FreePool (EbcDebugProtocol);\r
+    goto ErrorExit;\r
   }\r
+  //\r
+  // Install EbcDebugSupport Protocol Successfully\r
+  // Now we need to initialize the Ebc default Callback\r
+  //\r
+  Status = InitializeEbcCallback (EbcDebugProtocol);\r
+\r
   //\r
   // Produce a VM test interface protocol. Not required for execution.\r
   //\r
@@ -302,6 +344,44 @@ Returns:
     InitEbcVmTestProtocol (&ImageHandle);\r
   DEBUG_CODE_END ();\r
 \r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  HandleBuffer  = NULL;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiEbcProtocolGuid,\r
+                  NULL,\r
+                  &NumHandles,\r
+                  &HandleBuffer\r
+                  );\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Loop through the handles\r
+    //\r
+    for (Index = 0; Index < NumHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      HandleBuffer[Index],\r
+                      &gEfiEbcProtocolGuid,\r
+                      (VOID **) &OldEbcProtocol\r
+                      );\r
+      if (Status == EFI_SUCCESS) {\r
+        gBS->UninstallProtocolInterface (\r
+               HandleBuffer[Index],\r
+               &gEfiEbcProtocolGuid,\r
+               OldEbcProtocol\r
+               );\r
+      }\r
+    }\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    gBS->FreePool (HandleBuffer);\r
+    HandleBuffer = NULL;\r
+  }\r
+\r
+  gBS->FreePool (EbcProtocol);\r
+\r
   return Status;\r
 }\r
 \r
@@ -508,8 +588,8 @@ Returns:
 {\r
   EFI_SYSTEM_CONTEXT_EBC  EbcContext;\r
   EFI_SYSTEM_CONTEXT      SystemContext;\r
-  EFI_STATUS_CODE_VALUE   StatusCodeValue;\r
-  BOOLEAN                 Report;\r
+\r
+  ASSERT ((ExceptionType >= 0) && (ExceptionType <= MAX_EBC_EXCEPTION));\r
   //\r
   // Save the exception in the context passed in\r
   //\r
@@ -522,156 +602,179 @@ Returns:
   if (ExceptionFlags & EXCEPTION_FLAG_FATAL) {\r
     VmPtr->StopFlags |= STOPFLAG_APP_DONE;\r
   }\r
-  //\r
-  // Initialize the context structure\r
-  //\r
-  EbcContext.R0                   = VmPtr->R[0];\r
-  EbcContext.R1                   = VmPtr->R[1];\r
-  EbcContext.R2                   = VmPtr->R[2];\r
-  EbcContext.R3                   = VmPtr->R[3];\r
-  EbcContext.R4                   = VmPtr->R[4];\r
-  EbcContext.R5                   = VmPtr->R[5];\r
-  EbcContext.R6                   = VmPtr->R[6];\r
-  EbcContext.R7                   = VmPtr->R[7];\r
-  EbcContext.Ip                   = (UINT64) (UINTN) VmPtr->Ip;\r
-  EbcContext.Flags                = VmPtr->Flags;\r
-  EbcContext.ControlFlags         = 0;\r
-  SystemContext.SystemContextEbc  = &EbcContext;\r
+\r
   //\r
   // If someone's registered for exception callbacks, then call them.\r
-  // Otherwise report the status code via the status code API\r
   //\r
-  if ((ExceptionType >= 0) && (ExceptionType <= MAX_EBC_EXCEPTION) &&\r
-      (mDebugExceptionCallback[ExceptionType] != NULL)) {\r
+  // EBC driver will register default exception callback to report the\r
+  // status code via the status code API\r
+  //\r
+  if (mDebugExceptionCallback[ExceptionType] != NULL) {\r
+\r
+    //\r
+    // Initialize the context structure\r
+    //\r
+    EbcContext.R0                   = VmPtr->R[0];\r
+    EbcContext.R1                   = VmPtr->R[1];\r
+    EbcContext.R2                   = VmPtr->R[2];\r
+    EbcContext.R3                   = VmPtr->R[3];\r
+    EbcContext.R4                   = VmPtr->R[4];\r
+    EbcContext.R5                   = VmPtr->R[5];\r
+    EbcContext.R6                   = VmPtr->R[6];\r
+    EbcContext.R7                   = VmPtr->R[7];\r
+    EbcContext.Ip                   = (UINT64)(UINTN)VmPtr->Ip;\r
+    EbcContext.Flags                = VmPtr->Flags;\r
+    EbcContext.ControlFlags         = 0;\r
+    SystemContext.SystemContextEbc  = &EbcContext;\r
+\r
     mDebugExceptionCallback[ExceptionType] (ExceptionType, SystemContext);\r
+    //\r
+    // Restore the context structure and continue to execute\r
+    //\r
+    VmPtr->R[0]  = EbcContext.R0;\r
+    VmPtr->R[1]  = EbcContext.R1;\r
+    VmPtr->R[2]  = EbcContext.R2;\r
+    VmPtr->R[3]  = EbcContext.R3;\r
+    VmPtr->R[4]  = EbcContext.R4;\r
+    VmPtr->R[5]  = EbcContext.R5;\r
+    VmPtr->R[6]  = EbcContext.R6;\r
+    VmPtr->R[7]  = EbcContext.R7;\r
+    VmPtr->Ip    = (VMIP)(UINTN)EbcContext.Ip;\r
+    VmPtr->Flags = EbcContext.Flags;\r
   }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeEbcCallback (\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  To install default Callback function for the VM interpreter.\r
+  \r
+Arguments:\r
+\r
+  This - pointer to the instance of DebugSupport protocol\r
+\r
+Returns:\r
+\r
+  None\r
+  \r
+--*/\r
+{\r
+  INTN       Index;\r
+  EFI_STATUS Status;\r
+\r
   //\r
-  // Determine if we should report the exception. We report all of them by default,\r
-  // but if a debugger is attached don't report the breakpoint, debug, and step exceptions.\r
-  // Note that EXCEPT_EBC_OVERFLOW is never reported by this VM implementation, so is\r
-  // not included in the switch statement.\r
-  //\r
-  Report = TRUE;\r
-  switch (ExceptionType) {\r
-  case EXCEPT_EBC_UNDEFINED:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_UNDEFINED;\r
-    break;\r
-\r
-  case EXCEPT_EBC_DIVIDE_ERROR:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_DIVIDE_ERROR;\r
-    break;\r
-\r
-  case EXCEPT_EBC_DEBUG:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_DEBUG;\r
-    Report          = (BOOLEAN) ((mDebugExceptionCallback[ExceptionType] == NULL) ? TRUE : FALSE);\r
-    break;\r
-\r
-  case EXCEPT_EBC_BREAKPOINT:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_BREAKPOINT;\r
-    Report          = (BOOLEAN) ((mDebugExceptionCallback[ExceptionType] == NULL) ? TRUE : FALSE);\r
-    break;\r
-\r
-  case EXCEPT_EBC_INVALID_OPCODE:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_INVALID_OPCODE;\r
-    break;\r
-\r
-  case EXCEPT_EBC_STACK_FAULT:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_STACK_FAULT;\r
-    break;\r
-\r
-  case EXCEPT_EBC_ALIGNMENT_CHECK:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_ALIGNMENT_CHECK;\r
-    break;\r
-\r
-  case EXCEPT_EBC_INSTRUCTION_ENCODING:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_INSTRUCTION_ENCODING;\r
-    break;\r
-\r
-  case EXCEPT_EBC_BAD_BREAK:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_BAD_BREAK;\r
-    break;\r
-\r
-  case EXCEPT_EBC_STEP:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_EBC_STEP;\r
-    Report          = (BOOLEAN) ((mDebugExceptionCallback[ExceptionType] == NULL) ? TRUE : FALSE);\r
-    break;\r
-\r
-  default:\r
-    StatusCodeValue = EFI_SOFTWARE_EBC_EXCEPTION | EFI_SW_EC_NON_SPECIFIC;\r
-    break;\r
+  // For ExceptionCallback\r
+  //\r
+  for (Index = 0; Index <= MAX_EBC_EXCEPTION; Index++) {\r
+    EbcDebugRegisterExceptionCallback (\r
+      This,\r
+      0,\r
+      CommonEbcExceptionHandler,\r
+      Index\r
+      );\r
   }\r
+\r
   //\r
-  // If we determined that we should report the condition, then do so now.\r
+  // For PeriodicCallback\r
   //\r
-  if (Report) {\r
-    REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, StatusCodeValue);\r
+  Status = gBS->CreateEvent (\r
+                  EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
+                  EFI_TPL_NOTIFY,\r
+                  EbcPeriodicNotifyFunction,\r
+                  &mVmPtr,\r
+                  &mEbcPeriodicEvent\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
   }\r
 \r
-  switch (ExceptionType) {\r
-  //\r
-  // If ReportStatusCode returned, then for most exceptions we do an assert. The\r
-  // ExceptionType++ is done simply to force the ASSERT() condition to be met.\r
-  // For breakpoints, assume a debugger did not insert a software breakpoint\r
-  // and skip the instruction.\r
-  //\r
-  case EXCEPT_EBC_BREAKPOINT:\r
-    VmPtr->Ip += 2;\r
-    break;\r
-\r
-  case EXCEPT_EBC_STEP:\r
-    break;\r
-\r
-  case EXCEPT_EBC_UNDEFINED:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_UNDEFINED);\r
-    break;\r
-\r
-  case EXCEPT_EBC_DIVIDE_ERROR:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_DIVIDE_ERROR);\r
-    break;\r
-\r
-  case EXCEPT_EBC_DEBUG:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_DEBUG);\r
-    break;\r
-\r
-  case EXCEPT_EBC_INVALID_OPCODE:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_INVALID_OPCODE);\r
-    break;\r
-\r
-  case EXCEPT_EBC_STACK_FAULT:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_STACK_FAULT);\r
-    break;\r
-\r
-  case EXCEPT_EBC_ALIGNMENT_CHECK:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_ALIGNMENT_CHECK);\r
-    break;\r
-\r
-  case EXCEPT_EBC_INSTRUCTION_ENCODING:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_INSTRUCTION_ENCODING);\r
-    break;\r
-\r
-  case EXCEPT_EBC_BAD_BREAK:\r
-    ExceptionType++;\r
-    ASSERT (ExceptionType == EXCEPT_EBC_BAD_BREAK);\r
-    break;\r
-\r
-  default:\r
-    //\r
-    // Unknown\r
-    //\r
-    ASSERT (0);\r
-    break;\r
+  Status = gBS->SetTimer (\r
+                  mEbcPeriodicEvent,\r
+                  TimerPeriodic,\r
+                  EBC_VM_PERIODIC_CALLBACK_RATE\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+VOID\r
+CommonEbcExceptionHandler (\r
+  IN EFI_EXCEPTION_TYPE   InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The default Exception Callback for the VM interpreter.\r
+  In this function, we report status code, and print debug information\r
+  about EBC_CONTEXT, then dead loop.\r
+  \r
+Arguments:\r
+\r
+  InterruptType - Interrupt type.\r
+  SystemContext - EBC system context.\r
+\r
+Returns:\r
+\r
+  None\r
+  \r
+--*/\r
+{\r
+  //\r
+  // We deadloop here to make it easy to debug this issue.\r
+  //\r
+  ASSERT (FALSE);\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+EbcPeriodicNotifyFunction (\r
+  IN EFI_EVENT     Event,\r
+  IN VOID          *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The periodic callback function for EBC VM interpreter, which is used\r
+  to support the EFI debug support protocol.\r
+  \r
+Arguments:\r
+\r
+  Event   - The Periodic Callback Event.\r
+  Context - It should be the address of VM_CONTEXT pointer.\r
+\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  VM_CONTEXT *VmPtr;\r
+\r
+  VmPtr = *(VM_CONTEXT **)Context;\r
+\r
+  if (VmPtr != NULL) {\r
+    EbcDebugPeriodic (VmPtr);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+\r
 EFI_STATUS\r
 EbcDebugPeriodic (\r
   IN VM_CONTEXT *VmPtr\r
@@ -693,6 +796,47 @@ Returns:
   \r
 --*/\r
 {\r
+  EFI_SYSTEM_CONTEXT_EBC   EbcContext;\r
+  EFI_SYSTEM_CONTEXT       SystemContext;\r
+  \r
+  //\r
+  // If someone's registered for periodic callbacks, then call them.\r
+  //\r
+  if (mDebugPeriodicCallback != NULL) {\r
+\r
+    //\r
+    // Initialize the context structure\r
+    //\r
+    EbcContext.R0                   = VmPtr->R[0];\r
+    EbcContext.R1                   = VmPtr->R[1];\r
+    EbcContext.R2                   = VmPtr->R[2];\r
+    EbcContext.R3                   = VmPtr->R[3];\r
+    EbcContext.R4                   = VmPtr->R[4];\r
+    EbcContext.R5                   = VmPtr->R[5];\r
+    EbcContext.R6                   = VmPtr->R[6];\r
+    EbcContext.R7                   = VmPtr->R[7];\r
+    EbcContext.Ip                   = (UINT64)(UINTN)VmPtr->Ip;\r
+    EbcContext.Flags                = VmPtr->Flags;\r
+    EbcContext.ControlFlags         = 0;\r
+    SystemContext.SystemContextEbc  = &EbcContext;\r
+\r
+    mDebugPeriodicCallback (SystemContext);\r
+\r
+    //\r
+    // Restore the context structure and continue to execute\r
+    //\r
+    VmPtr->R[0]  = EbcContext.R0;\r
+    VmPtr->R[1]  = EbcContext.R1;\r
+    VmPtr->R[2]  = EbcContext.R2;\r
+    VmPtr->R[3]  = EbcContext.R3;\r
+    VmPtr->R[4]  = EbcContext.R4;\r
+    VmPtr->R[5]  = EbcContext.R5;\r
+    VmPtr->R[6]  = EbcContext.R6;\r
+    VmPtr->R[7]  = EbcContext.R7;\r
+    VmPtr->Ip    = (VMIP)(UINTN)EbcContext.Ip;\r
+    VmPtr->Flags = EbcContext.Flags;\r
+  }\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r