PcdPeiPcdDatabaseGetSizeEnabled|gEfiEdkModulePkgTokenSpaceGuid|TRUE\r
PcdPeiPcdDatabaseCallbackOnSetEnabled|gEfiEdkModulePkgTokenSpaceGuid|TRUE\r
PcdPeiPcdDatabaseExEnabled|gEfiEdkModulePkgTokenSpaceGuid|TRUE\r
+ PcdNtEmulatorEnable|gEfiEdkModulePkgTokenSpaceGuid|FALSE\r
\r
# PcdStatusCodeUseOEM|gEfiIntelFrameworkModulePkgTokenSpaceGuid|FALSE\r
\r
${WORKSPACE}/MdeModulePkg/Universal/WatchDogTimerDxe/WatchDogTimer.inf\r
${WORKSPACE}/MdeModulePkg/Universal/VariablePei/Variable.inf\r
${WORKSPACE}/MdeModulePkg/Universal/VariableRuntimeDxe/Variable.inf\r
+ ${WORKSPACE}/MdeModulePkg/Universal/DebugSupportDxe/DebugSupport.inf\r
+ ${WORKSPACE}/MdeModulePkg/Universal/DebugPortDxe/DebugPort.inf\r
${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.inf\r
${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf\r
$(WORKSPACE)/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+ ComponentName.c\r
+\r
+Abstract:\r
+ Component name protocol member functions for DebugPort...\r
+ \r
+--*/\r
+\r
+#include "DebugPort.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+EFI_COMPONENT_NAME_PROTOCOL gDebugPortComponentName = {\r
+ DebugPortComponentNameGetDriverName,\r
+ DebugPortComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+static EFI_UNICODE_STRING_TABLE mDebugPortDriverNameTable[] = {\r
+ {\r
+ "eng",\r
+ (CHAR16 *) L"DebugPort Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ Language - A pointer to a three character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller \r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a \r
+ driver is up to the driver writer.\r
+ DriverName - A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language \r
+ specified by Language.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned \r
+ in DriverName.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - DriverName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the \r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return LookupUnicodeString (\r
+ Language,\r
+ gDebugPortComponentName.SupportedLanguages,\r
+ mDebugPortDriverNameTable,\r
+ DriverName\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ The debug port driver does not support GetControllerName, so this function\r
+ is just stubbed and returns EFI_UNSUPPORTED.\r
+\r
+ Arguments:\r
+ Per EFI 1.10 driver model\r
+\r
+ Returns:\r
+ EFI_UNSUPPORTED\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ DebugPort.c\r
+\r
+Abstract:\r
+\r
+ Top level C file for debugport driver. Contains initialization function.\r
+ This driver layers on top of SerialIo.\r
+ \r
+ ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM\r
+ INTERRUPT CONTEXT.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+\r
+#include "DebugPort.h"\r
+\r
+//\r
+// Misc. functions local to this module..\r
+//\r
+STATIC\r
+VOID\r
+GetDebugPortVariable (\r
+ DEBUGPORT_DEVICE *DebugPortDevice\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Local worker function to obtain device path information from DebugPort variable.\r
+ Records requested settings in DebugPort device structure.\r
+ \r
+Arguments:\r
+ DEBUGPORT_DEVICE *DebugPortDevice,\r
+\r
+Returns:\r
+\r
+ Nothing\r
+\r
+--*/\r
+{\r
+ UINTN DataSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_STATUS Status;\r
+\r
+ DataSize = 0;\r
+\r
+ Status = gRT->GetVariable (\r
+ (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME,\r
+ &gEfiDebugPortVariableGuid,\r
+ NULL,\r
+ &DataSize,\r
+ DebugPortDevice->DebugPortVariable\r
+ );\r
+\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (gDebugPortDevice->DebugPortVariable != NULL) {\r
+ FreePool (gDebugPortDevice->DebugPortVariable);\r
+ }\r
+\r
+ DebugPortDevice->DebugPortVariable = AllocatePool (DataSize);\r
+ if (DebugPortDevice->DebugPortVariable != NULL) {\r
+ gRT->GetVariable (\r
+ (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME,\r
+ &gEfiDebugPortVariableGuid,\r
+ NULL,\r
+ &DataSize,\r
+ DebugPortDevice->DebugPortVariable\r
+ );\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DebugPortDevice->DebugPortVariable;\r
+ while (!EfiIsDevicePathEnd (DevicePath) && !EfiIsUartDevicePath (DevicePath)) {\r
+ DevicePath = EfiNextDevicePathNode (DevicePath);\r
+ }\r
+\r
+ if (EfiIsDevicePathEnd (DevicePath)) {\r
+ FreePool (gDebugPortDevice->DebugPortVariable);\r
+ DebugPortDevice->DebugPortVariable = NULL;\r
+ } else {\r
+ CopyMem (\r
+ &DebugPortDevice->BaudRate,\r
+ &((UART_DEVICE_PATH *) DevicePath)->BaudRate,\r
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)\r
+ );\r
+ DebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;\r
+ DebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;\r
+ CopyMem (\r
+ &DebugPortDevice->Parity,\r
+ &((UART_DEVICE_PATH *) DevicePath)->Parity,\r
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)\r
+ );\r
+ CopyMem (\r
+ &DebugPortDevice->DataBits,\r
+ &((UART_DEVICE_PATH *) DevicePath)->DataBits,\r
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)\r
+ );\r
+ CopyMem (\r
+ &DebugPortDevice->StopBits,\r
+ &((UART_DEVICE_PATH *) DevicePath)->StopBits,\r
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)\r
+ );\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+//\r
+// Globals\r
+//\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = {\r
+ DebugPortSupported,\r
+ DebugPortStart,\r
+ DebugPortStop,\r
+ DEBUGPORT_DRIVER_VERSION,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+DEBUGPORT_DEVICE *gDebugPortDevice;\r
+\r
+//\r
+// implementation code\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeDebugPortDriver (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Driver entry point. Reads DebugPort variable to determine what device and settings\r
+ to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \\r
+ if no variable is found. \r
+ \r
+ Creates debugport and devicepath protocols on new handle.\r
+\r
+Arguments:\r
+ ImageHandle,\r
+ SystemTable\r
+\r
+Returns:\r
+\r
+ EFI_UNSUPPORTED\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Install driver model protocol(s).\r
+ //\r
+ Status = EfiLibInstallAllDriverProtocols (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gDebugPortDriverBinding,\r
+ ImageHandle,\r
+ &gDebugPortComponentName,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Allocate and Initialize dev structure\r
+ //\r
+ gDebugPortDevice = AllocateZeroPool (sizeof (DEBUGPORT_DEVICE));\r
+ if (gDebugPortDevice == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Fill in static and default pieces of device structure first.\r
+ //\r
+ gDebugPortDevice->Signature = DEBUGPORT_DEVICE_SIGNATURE;\r
+\r
+ gDebugPortDevice->DebugPortInterface.Reset = DebugPortReset;\r
+ gDebugPortDevice->DebugPortInterface.Read = DebugPortRead;\r
+ gDebugPortDevice->DebugPortInterface.Write = DebugPortWrite;\r
+ gDebugPortDevice->DebugPortInterface.Poll = DebugPortPoll;\r
+\r
+ gDebugPortDevice->BaudRate = DEBUGPORT_UART_DEFAULT_BAUDRATE;\r
+ gDebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;\r
+ gDebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;\r
+ gDebugPortDevice->Parity = (EFI_PARITY_TYPE) DEBUGPORT_UART_DEFAULT_PARITY;\r
+ gDebugPortDevice->DataBits = DEBUGPORT_UART_DEFAULT_DATA_BITS;\r
+ gDebugPortDevice->StopBits = (EFI_STOP_BITS_TYPE) DEBUGPORT_UART_DEFAULT_STOP_BITS;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+// DebugPort driver binding member functions...\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Checks to see that there's not already a DebugPort interface somewhere. If so,\r
+ fail.\r
+ \r
+ If there's a DEBUGPORT variable, the device path must match exactly. If there's\r
+ no DEBUGPORT variable, then device path is not checked and does not matter.\r
+ \r
+ Checks to see that there's a serial io interface on the controller handle\r
+ that can be bound BY_DRIVER | EXCLUSIVE.\r
+ \r
+ If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED\r
+ or other error returned by OpenProtocol.\r
+\r
+Arguments:\r
+ This\r
+ ControllerHandle\r
+ RemainingDevicePath\r
+ \r
+Returns:\r
+ EFI_UNSUPPORTED\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_SUCCESS\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dp1;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dp2;\r
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
+ EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;\r
+ EFI_HANDLE TempHandle;\r
+\r
+ //\r
+ // Check to see that there's not a debugport protocol already published\r
+ //\r
+ if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **) &DebugPortInterface) != EFI_NOT_FOUND) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Read DebugPort variable to determine debug port selection and parameters\r
+ //\r
+ GetDebugPortVariable (gDebugPortDevice);\r
+\r
+ if (gDebugPortDevice->DebugPortVariable != NULL) {\r
+ //\r
+ // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if\r
+ // the closest matching handle matches the controller handle, and if it does,\r
+ // check to see that the remaining device path has the DebugPort GUIDed messaging\r
+ // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.\r
+ //\r
+ Dp1 = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) gDebugPortDevice->DebugPortVariable);\r
+ if (Dp1 == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Dp2 = Dp1;\r
+\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSerialIoProtocolGuid,\r
+ &Dp2,\r
+ &TempHandle\r
+ );\r
+\r
+ if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Status == EFI_SUCCESS && (Dp2->Type != 3 || Dp2->SubType != 10 || *((UINT16 *) Dp2->Length) != 20)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Status == EFI_SUCCESS && CompareMem (&gEfiDebugPortDevicePathGuid, Dp2 + 1, sizeof (EFI_GUID))) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ FreePool (Dp1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &SerialIo,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Binds exclusively to serial io on the controller handle. Produces DebugPort\r
+ protocol and DevicePath on new handle.\r
+\r
+Arguments:\r
+ This\r
+ ControllerHandle\r
+ RemainingDevicePath\r
+ \r
+Returns:\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_SUCCESS\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEBUGPORT_DEVICE_PATH DebugPortDP;\r
+ EFI_DEVICE_PATH_PROTOCOL EndDP;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dp1;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &gDebugPortDevice->SerialIoBinding,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gDebugPortDevice->SerialIoDeviceHandle = ControllerHandle;\r
+\r
+ //\r
+ // Initialize the Serial Io interface...\r
+ //\r
+ Status = gDebugPortDevice->SerialIoBinding->SetAttributes (\r
+ gDebugPortDevice->SerialIoBinding,\r
+ gDebugPortDevice->BaudRate,\r
+ gDebugPortDevice->ReceiveFifoDepth,\r
+ gDebugPortDevice->Timeout,\r
+ gDebugPortDevice->Parity,\r
+ gDebugPortDevice->DataBits,\r
+ gDebugPortDevice->StopBits\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gDebugPortDevice->BaudRate = 0;\r
+ gDebugPortDevice->Parity = DefaultParity;\r
+ gDebugPortDevice->DataBits = 0;\r
+ gDebugPortDevice->StopBits = DefaultStopBits;\r
+ gDebugPortDevice->ReceiveFifoDepth = 0;\r
+ Status = gDebugPortDevice->SerialIoBinding->SetAttributes (\r
+ gDebugPortDevice->SerialIoBinding,\r
+ gDebugPortDevice->BaudRate,\r
+ gDebugPortDevice->ReceiveFifoDepth,\r
+ gDebugPortDevice->Timeout,\r
+ gDebugPortDevice->Parity,\r
+ gDebugPortDevice->DataBits,\r
+ gDebugPortDevice->StopBits\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ gDebugPortDevice->SerialIoBinding->Reset (gDebugPortDevice->SerialIoBinding);\r
+\r
+ //\r
+ // Create device path instance for DebugPort\r
+ //\r
+ DebugPortDP.Header.Type = MESSAGING_DEVICE_PATH;\r
+ DebugPortDP.Header.SubType = MSG_VENDOR_DP;\r
+ SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP));\r
+ CopyMem (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid, sizeof (EFI_GUID));\r
+\r
+ Dp1 = DevicePathFromHandle (ControllerHandle);\r
+ if (Dp1 == NULL) {\r
+ Dp1 = &EndDP;\r
+ SetDevicePathEndNode (Dp1);\r
+ }\r
+\r
+ gDebugPortDevice->DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);\r
+ if (gDebugPortDevice->DebugPortDevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Publish DebugPort and Device Path protocols\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &gDebugPortDevice->DebugPortDeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ gDebugPortDevice->DebugPortDevicePath,\r
+ &gEfiDebugPortProtocolGuid,\r
+ &gDebugPortDevice->DebugPortInterface,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+ return Status;\r
+ }\r
+ //\r
+ // Connect debugport child to serial io\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &gDebugPortDevice->SerialIoBinding,\r
+ This->DriverBindingHandle,\r
+ gDebugPortDevice->DebugPortDeviceHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN BufferSize;\r
+\r
+ BufferSize = 48;\r
+ DebugPortWrite (\r
+ &gDebugPortDevice->DebugPortInterface,\r
+ 0,\r
+ &BufferSize,\r
+ "DebugPort driver failed to open child controller\n\n"\r
+ );\r
+ DEBUG_CODE_END ();\r
+\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN BufferSize;\r
+\r
+ BufferSize = 38;\r
+ DebugPortWrite (\r
+ &gDebugPortDevice->DebugPortInterface,\r
+ 0,\r
+ &BufferSize,\r
+ "Hello World from the DebugPort driver\n\n"\r
+ );\r
+ DEBUG_CODE_END ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ We're never intending to be stopped via the driver model so this just returns\r
+ EFI_UNSUPPORTED\r
+\r
+Arguments:\r
+ Per EFI 1.10 driver model\r
+ \r
+Returns:\r
+ EFI_UNSUPPORTED\r
+ EFI_SUCCESS\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (NumberOfChildren == 0) {\r
+ //\r
+ // Close the bus driver\r
+ //\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+\r
+ gDebugPortDevice->SerialIoBinding = NULL;\r
+\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
+\r
+ FreePool (gDebugPortDevice->DebugPortDevicePath);\r
+\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Disconnect SerialIo child handle\r
+ //\r
+ Status = gBS->CloseProtocol (\r
+ gDebugPortDevice->SerialIoDeviceHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ gDebugPortDevice->DebugPortDeviceHandle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Unpublish our protocols (DevicePath, DebugPort)\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ gDebugPortDevice->DebugPortDeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ gDebugPortDevice->DebugPortDevicePath,\r
+ &gEfiDebugPortProtocolGuid,\r
+ &gDebugPortDevice->DebugPortInterface,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &gDebugPortDevice->SerialIoBinding,\r
+ This->DriverBindingHandle,\r
+ gDebugPortDevice->DebugPortDeviceHandle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ } else {\r
+ gDebugPortDevice->DebugPortDeviceHandle = NULL;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+//\r
+// Debugport protocol member functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortReset (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.\r
+ We cannot call SerialIo:SetAttributes because it uses pool services, which use\r
+ locks, which affect TPL, so it's not interrupt context safe or re-entrant.\r
+ SerialIo:Reset() calls SetAttributes, so it can't be used either.\r
+ \r
+ The port itself should be fine since it was set up during initialization. \r
+ \r
+Arguments:\r
+ This\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ UINTN BufferSize;\r
+ UINTN BitBucket;\r
+\r
+ while (This->Poll (This) == EFI_SUCCESS) {\r
+ BufferSize = 1;\r
+ This->Read (This, 0, &BufferSize, &BitBucket);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortRead (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This,\r
+ IN UINT32 Timeout,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugPort protocol member function. Calls SerialIo:Read() after setting\r
+ if it's different than the last SerialIo access.\r
+ \r
+Arguments:\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+ IN UINT32 Timeout,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
+{\r
+ DEBUGPORT_DEVICE *DebugPortDevice;\r
+ UINTN LocalBufferSize;\r
+ EFI_STATUS Status;\r
+ UINT8 *BufferPtr;\r
+\r
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);\r
+ BufferPtr = Buffer;\r
+ LocalBufferSize = *BufferSize;\r
+ do {\r
+ Status = DebugPortDevice->SerialIoBinding->Read (\r
+ DebugPortDevice->SerialIoBinding,\r
+ &LocalBufferSize,\r
+ BufferPtr\r
+ );\r
+ if (Status == EFI_TIMEOUT) {\r
+ if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {\r
+ Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT;\r
+ } else {\r
+ Timeout = 0;\r
+ }\r
+ } else if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ BufferPtr += LocalBufferSize;\r
+ LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer);\r
+ } while (LocalBufferSize != 0 && Timeout > 0);\r
+\r
+ *BufferSize = (UINTN) (BufferPtr - (UINT8 *) Buffer);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortWrite (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This,\r
+ IN UINT32 Timeout,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at\r
+ a time and does a GetControl between 8 byte writes to help insure reads are\r
+ interspersed This is poor-man's flow control..\r
+ \r
+Arguments:\r
+ This - Pointer to DebugPort protocol\r
+ Timeout - Timeout value\r
+ BufferSize - On input, the size of Buffer. \r
+ On output, the amount of data actually written.\r
+ Buffer - Pointer to buffer to write\r
+\r
+Returns:\r
+ EFI_SUCCESS - The data was written.\r
+ EFI_DEVICE_ERROR - The device reported an error.\r
+ EFI_TIMEOUT - The data write was stopped due to a timeout.\r
+\r
+--*/\r
+{\r
+ DEBUGPORT_DEVICE *DebugPortDevice;\r
+ UINTN Position;\r
+ UINTN WriteSize;\r
+ EFI_STATUS Status;\r
+ UINT32 SerialControl;\r
+\r
+ Status = EFI_SUCCESS;\r
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);\r
+\r
+ WriteSize = 8;\r
+ for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {\r
+ DebugPortDevice->SerialIoBinding->GetControl (\r
+ DebugPortDevice->SerialIoBinding,\r
+ &SerialControl\r
+ );\r
+ if (*BufferSize - Position < 8) {\r
+ WriteSize = *BufferSize - Position;\r
+ }\r
+\r
+ Status = DebugPortDevice->SerialIoBinding->Write (\r
+ DebugPortDevice->SerialIoBinding,\r
+ &WriteSize,\r
+ &((UINT8 *) Buffer)[Position]\r
+ );\r
+ }\r
+\r
+ *BufferSize = Position;\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortPoll (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugPort protocol member function. Calls SerialIo:Write() after setting\r
+ if it's different than the last SerialIo access.\r
+ \r
+Arguments:\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+\r
+Returns:\r
+ EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface\r
+ EFI_NOT_READY - There are no characters ready to read from the DebugPort interface\r
+ EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 SerialControl;\r
+ DEBUGPORT_DEVICE *DebugPortDevice;\r
+\r
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);\r
+\r
+ Status = DebugPortDevice->SerialIoBinding->GetControl (\r
+ DebugPortDevice->SerialIoBinding,\r
+ &SerialControl\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) {\r
+ Status = EFI_NOT_READY;\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ImageUnloadHandler (\r
+ EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Unload function that is registered in the LoadImage protocol. It un-installs\r
+ protocols produced and deallocates pool used by the driver. Called by the core\r
+ when unloading the driver.\r
+ \r
+Arguments:\r
+ EFI_HANDLE ImageHandle\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (gDebugPortDevice->SerialIoBinding != NULL) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gDebugPortDevice->DriverBindingInterface,\r
+ &gEfiComponentNameProtocolGuid,\r
+ &gDebugPortDevice->ComponentNameInterface,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Clean up allocations\r
+ //\r
+ if (gDebugPortDevice->DebugPortVariable != NULL) {\r
+ FreePool (gDebugPortDevice->DebugPortVariable);\r
+ }\r
+\r
+ FreePool (gDebugPortDevice);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+ DebugPort.h\r
+\r
+Abstract:\r
+ Definitions and prototypes for DebugPort driver\r
+\r
+--*/\r
+\r
+#ifndef __DEBUGPORT_H__\r
+#define __DEBUGPORT_H__\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <Uefi.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/ComponentName.h>\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/SerialIo.h>\r
+#include <Protocol/DebugPort.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+//\r
+// Driver Binding Externs\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL gDebugPortComponentName;\r
+\r
+//\r
+// local type definitions\r
+//\r
+#define DEBUGPORT_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('D', 'B', 'G', 'P')\r
+\r
+//\r
+// Device structure used by driver\r
+//\r
+typedef struct {\r
+ UINT32 Signature;\r
+ EFI_HANDLE DriverBindingHandle;\r
+ EFI_HANDLE DebugPortDeviceHandle;\r
+ VOID *DebugPortVariable;\r
+\r
+ EFI_DRIVER_BINDING_PROTOCOL DriverBindingInterface;\r
+ EFI_COMPONENT_NAME_PROTOCOL ComponentNameInterface;\r
+ EFI_DEVICE_PATH_PROTOCOL *DebugPortDevicePath;\r
+ EFI_DEBUGPORT_PROTOCOL DebugPortInterface;\r
+\r
+ EFI_HANDLE SerialIoDeviceHandle;\r
+ EFI_SERIAL_IO_PROTOCOL *SerialIoBinding;\r
+ UINT64 BaudRate;\r
+ UINT32 ReceiveFifoDepth;\r
+ UINT32 Timeout;\r
+ EFI_PARITY_TYPE Parity;\r
+ UINT8 DataBits;\r
+ EFI_STOP_BITS_TYPE StopBits;\r
+} DEBUGPORT_DEVICE;\r
+\r
+#define DEBUGPORT_DEVICE_FROM_THIS(a) CR (a, DEBUGPORT_DEVICE, DebugPortInterface, DEBUGPORT_DEVICE_SIGNATURE)\r
+\r
+#define EFI_ACPI_PC_COMPORT_HID EISA_PNP_ID (0x0500)\r
+#define EFI_ACPI_16550UART_HID EISA_PNP_ID (0x0501)\r
+\r
+#define DEBUGPORT_UART_DEFAULT_BAUDRATE 115200\r
+#define DEBUGPORT_UART_DEFAULT_PARITY 0\r
+#define DEBUGPORT_UART_DEFAULT_FIFO_DEPTH 16\r
+#define DEBUGPORT_UART_DEFAULT_TIMEOUT 50000 // 5 ms\r
+#define DEBUGPORT_UART_DEFAULT_DATA_BITS 8\r
+#define DEBUGPORT_UART_DEFAULT_STOP_BITS 1\r
+\r
+#define DEBUGPORT_DRIVER_VERSION 1\r
+\r
+#define EfiIsUartDevicePath(dp) (DevicePathType (dp) == MESSAGING_DEVICE_PATH && DevicePathSubType (dp) == MSG_UART_DP)\r
+\r
+//\r
+// globals\r
+//\r
+extern DEBUGPORT_DEVICE *gDebugPortDevice;\r
+\r
+//\r
+// Driver binding interface functions...\r
+//\r
+EFI_STATUS\r
+DebugPortEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+;\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+;\r
+\r
+//\r
+// DebugPort member functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortReset (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortRead (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This,\r
+ IN UINT32 Timeout,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortWrite (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This,\r
+ IN UINT32 Timeout,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DebugPortPoll (\r
+ IN EFI_DEBUGPORT_PROTOCOL *This\r
+ )\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/** @file\r
+# Component description file for DebugPort module.\r
+#\r
+# This driver binds exclusively to serial io on the controller handle,\r
+# and initializes serial Io interface, publishs DebugPort and device path Protocol.\r
+# Copyright (c) 2006 - 2007, Intel Corporation\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DebugPort\r
+ FILE_GUID = 73E9457A-CEA1-4917-9A9C-9F1F0F0FD322\r
+ MODULE_TYPE = UEFI_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializeDebugPortDriver\r
+ UNLOAD_IMAGE = ImageUnloadHandler\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+# DRIVER_BINDING = gDebugPortDriverBinding \r
+# COMPONENT_NAME = gDebugPortComponentName \r
+# Variable Guid C Name: gEfiDebugPortProtocolGuid Variable Name: L"DEBUGPORT"\r
+#\r
+#\r
+\r
+################################################################################\r
+#\r
+# Sources Section - list of files that are required for the build to succeed.\r
+#\r
+################################################################################\r
+\r
+[Sources.common]\r
+ ComponentName.c\r
+ DebugPort.c\r
+ DebugPort.h\r
+\r
+\r
+################################################################################\r
+#\r
+# Package Dependency Section - list of Package files that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+\r
+\r
+################################################################################\r
+#\r
+# Library Class Section - list of Library Classes that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ UefiRuntimeServicesTableLib\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ BaseMemoryLib\r
+ UefiLib\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+\r
+\r
+################################################################################\r
+#\r
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names\r
+# that this module uses or produces.\r
+#\r
+################################################################################\r
+\r
+[Protocols]\r
+ gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiComponentNameProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSerialIoProtocolGuid # PROTOCOL TO_START\r
+ gEfiDevicePathProtocolGuid # PROTOCOL BY_START\r
+ gEfiDebugPortProtocolGuid # PROTOCOL BY_START\r
+\r
+\r
+################################################################################\r
+#\r
+# Dependency Expression Section - list of Dependency expressions that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[Depex]\r
+ TRUE\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>DebugPort</ModuleName>\r
+ <ModuleType>UEFI_DRIVER</ModuleType>\r
+ <GuidValue>73E9457A-CEA1-4917-9A9C-9F1F0F0FD322</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component description file for DebugPort module.</Abstract>\r
+ <Description>This driver binds exclusively to serial io on the controller handle,\r
+ and initializes serial Io interface, publishs DebugPort and device path Protocol.</Description>\r
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>DebugPort</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DevicePathLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>DebugPort.h</Filename>\r
+ <Filename>DebugPort.c</Filename>\r
+ <Filename>ComponentName.c</Filename>\r
+ <Filename>DebugPort.dxs</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="BY_START">\r
+ <ProtocolCName>gEfiDebugPortProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="BY_START">\r
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="TO_START">\r
+ <ProtocolCName>gEfiSerialIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiComponentNameProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDriverBindingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Variables>\r
+ <Variable Usage="SOMETIMES_CONSUMED">\r
+ <VariableName>0x0044 0x0045 0x0042 0x0055 0x0047 0x0050 0x004F 0x0052 0x0054</VariableName>\r
+ <GuidC_Name>gEfiDebugPortProtocolGuid</GuidC_Name>\r
+ <HelpText>L"DEBUGPORT" variable is specified. gEfiDebugPortVariableGuid is\r
+ one virtual guid, which can't be described in this section.\r
+ So gEfiDebugPortProtocolGuid name is instead of it.</HelpText>\r
+ </Variable>\r
+ </Variables>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>InitializeDebugPortDriver</ModuleEntryPoint>\r
+ </Extern>\r
+ <Extern>\r
+ <ModuleUnloadImage>ImageUnloadHandler</ModuleUnloadImage>\r
+ </Extern>\r
+ <Extern>\r
+ <DriverBinding>gDebugPortDriverBinding</DriverBinding>\r
+ <ComponentName>gDebugPortComponentName</ComponentName>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ DebugSupport.c\r
+\r
+Abstract:\r
+\r
+ Top level C file for debug support driver. Contains initialization function.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+//\r
+// private header files\r
+//\r
+#include "plDebugSupport.h"\r
+\r
+//\r
+// This is a global that is the actual interface\r
+//\r
+EFI_DEBUG_SUPPORT_PROTOCOL gDebugSupportProtocolInterface = {\r
+ EFI_ISA,\r
+ GetMaximumProcessorIndex,\r
+ RegisterPeriodicCallback,\r
+ RegisterExceptionCallback,\r
+ InvalidateInstructionCache\r
+};\r
+\r
+//\r
+// Driver Entry Point\r
+//\r
+EFI_STATUS\r
+InitializeDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Driver entry point. Checks to see there's not already a DebugSupport protocol\r
+ installed for the selected processor before installing protocol.\r
+\r
+Arguments:\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
+// TODO: ImageHandle - add argument and description to function comment\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolPtr;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE *HandlePtr;\r
+ UINTN NumHandles;\r
+ EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupportProtocolPtr;\r
+\r
+ //\r
+ // Install Protocol Interface...\r
+ //\r
+ // First check to see that the debug support protocol for this processor\r
+ // type is not already installed\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDebugSupportProtocolGuid,\r
+ NULL,\r
+ &NumHandles,\r
+ &HandlePtr\r
+ );\r
+\r
+ if (Status != EFI_NOT_FOUND) {\r
+ do {\r
+ NumHandles--;\r
+ Status = gBS->OpenProtocol (\r
+ HandlePtr[NumHandles],\r
+ &gEfiDebugSupportProtocolGuid,\r
+ (VOID **) &DebugSupportProtocolPtr,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (Status == EFI_SUCCESS && DebugSupportProtocolPtr->Isa == EFI_ISA) {\r
+ FreePool (HandlePtr);\r
+ Status = EFI_ALREADY_STARTED;\r
+ goto ErrExit;\r
+ }\r
+ } while (NumHandles > 0);\r
+ FreePool (HandlePtr);\r
+ }\r
+\r
+ //\r
+ // Get our image information and install platform specific unload handler\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImageProtocolPtr,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ if (Status != EFI_SUCCESS) {\r
+ goto ErrExit;\r
+ }\r
+\r
+ LoadedImageProtocolPtr->Unload = plUnloadDebugSupportDriver;\r
+\r
+ //\r
+ // Call hook for platform specific initialization\r
+ //\r
+ Status = plInitializeDebugSupportDriver ();\r
+ ASSERT (!EFI_ERROR (Status));\r
+ if (Status != EFI_SUCCESS) {\r
+ goto ErrExit;\r
+ }\r
+\r
+ //\r
+ // Install DebugSupport protocol to new handle\r
+ //\r
+ Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Handle,\r
+ &gEfiDebugSupportProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gDebugSupportProtocolInterface\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ if (Status != EFI_SUCCESS) {\r
+ goto ErrExit;\r
+ }\r
+\r
+ErrExit:\r
+ return Status;\r
+}\r
--- /dev/null
+#/** @file\r
+# Component description file for DebugSupport module.\r
+#\r
+# This driver installs DebugSupport protocol for the selected processor.\r
+# Copyright (c) 2006 - 2007, Intel Corporation\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DebugSupport\r
+ FILE_GUID = 911D584C-35F7-4955-BEF9-B452769DDC3A\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializeDebugSupportDriver\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF\r
+#\r
+\r
+################################################################################\r
+#\r
+# Sources Section - list of files that are required for the build to succeed.\r
+#\r
+################################################################################\r
+\r
+[Sources.common]\r
+ DebugSupport.c\r
+\r
+[Sources.Ia32]\r
+ Ia32/plDebugSupport.c\r
+ Ia32/plDebugSupport.h\r
+ Ia32/AsmFuncs.S\r
+ Ia32/AsmFuncs.asm\r
+\r
+[Sources.X64]\r
+ x64/plDebugSupport.c\r
+ x64/plDebugSupport.h\r
+ x64/AsmFuncs.S\r
+ x64/AsmFuncs.asm\r
+\r
+[Sources.IPF]\r
+ ipf/plDebugSupport.h\r
+ ipf/plDebugSupport.c\r
+ ipf/Ds64Macros.i\r
+ ipf/common.i\r
+ ipf/AsmFuncs.s\r
+\r
+\r
+################################################################################\r
+#\r
+# Package Dependency Section - list of Package files that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+################################################################################\r
+#\r
+# Library Class Section - list of Library Classes that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[LibraryClasses]\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ BaseMemoryLib\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+\r
+[LibraryClasses.IA32]\r
+ PcdLib\r
+ BaseLib\r
+\r
+[LibraryClasses.X64]\r
+ BaseLib\r
+\r
+\r
+################################################################################\r
+#\r
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names\r
+# that this module uses or produces.\r
+#\r
+################################################################################\r
+\r
+[Protocols]\r
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDebugSupportProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
+\r
+\r
+################################################################################\r
+#\r
+# Pcd FEATURE_FLAG - list of PCDs that this module is coded for.\r
+#\r
+################################################################################\r
+\r
+[PcdsFeatureFlag.IA32]\r
+ PcdNtEmulatorEnable|gEfiEdkModulePkgTokenSpaceGuid\r
+\r
+\r
+################################################################################\r
+#\r
+# Dependency Expression Section - list of Dependency expressions that are required for\r
+# this module.\r
+#\r
+################################################################################\r
+\r
+[Depex]\r
+ TRUE\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>DebugSupport</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>911D584C-35F7-4955-BEF9-B452769DDC3A</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component description file for DebugSupport module.</Abstract>\r
+ <Description>This driver installs DebugSupport protocol for the selected processor.</Description>\r
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>DebugSupport</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED" SupArchList="IA32 X64">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED" SupArchList="IA32">\r
+ <Keyword>PcdLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>DebugSupport.c</Filename>\r
+ <Filename>DebugSupport.dxs</Filename>\r
+ <Filename SupArchList="IA32" ToolChainFamily="MSFT">Ia32/AsmFuncs.asm</Filename>\r
+ <Filename SupArchList="IA32" ToolChainFamily="GCC">Ia32/AsmFuncs.S</Filename>\r
+ <Filename SupArchList="IA32">Ia32/plDebugSupport.h</Filename>\r
+ <Filename SupArchList="IA32">Ia32/plDebugSupport.c</Filename>\r
+ <Filename SupArchList="IPF">ipf/AsmFuncs.s</Filename>\r
+ <Filename SupArchList="IPF">ipf/common.i</Filename>\r
+ <Filename SupArchList="IPF">ipf/Ds64Macros.i</Filename>\r
+ <Filename SupArchList="IPF">ipf/plDebugSupport.c</Filename>\r
+ <Filename SupArchList="IPF">ipf/plDebugSupport.h</Filename>\r
+ <Filename SupArchList="X64" ToolChainFamily="MSFT">x64/AsmFuncs.asm</Filename>\r
+ <Filename SupArchList="X64" ToolChainFamily="GCC">x64/AsmFuncs.S</Filename>\r
+ <Filename SupArchList="X64">x64/plDebugSupport.h</Filename>\r
+ <Filename SupArchList="X64">x64/plDebugSupport.c</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>\r
+ <Package PackageGuid="BA0D78D6-2CAF-414b-BD4D-B6762A894288"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="SOMETIMES_PRODUCED">\r
+ <ProtocolCName>gEfiDebugSupportProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>InitializeDebugSupportDriver</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+ <PcdCoded>\r
+ <PcdEntry PcdItemType="FEATURE_FLAG" Usage="ALWAYS_CONSUMED" SupArchList="IA32">\r
+ <C_Name>PcdNtEmulatorEnable</C_Name>\r
+ <TokenSpaceGuidCName>gEfiEdkModulePkgTokenSpaceGuid</TokenSpaceGuidCName>\r
+ <HelpText>If this PCD is set as TRUE, NT emulator will be endabled.</HelpText>\r
+ </PcdEntry>\r
+ </PcdCoded>\r
+</ModuleSurfaceArea>\r
--- /dev/null
+#******************************************************************************\r
+#*\r
+#* Copyright (c) 2006, Intel Corporation \r
+#* All rights reserved. This program and the accompanying materials \r
+#* are licensed and made available under the terms and conditions of the BSD License \r
+#* which accompanies this distribution. The full text of the license may be found at \r
+#* http://opensource.org/licenses/bsd-license.php \r
+#* \r
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+#*\r
+#******************************************************************************\r
+\r
+.globl ASM_PFX(OrigVector)\r
+.globl ASM_PFX(InterruptEntryStub)\r
+.globl ASM_PFX(StubSize)\r
+.globl ASM_PFX(CommonIdtEntry)\r
+.globl ASM_PFX(FxStorSupport)\r
+\r
+ASM_PFX(AppEsp): .long 0x11111111 # ?\r
+ASM_PFX(DebugEsp): .long 0x22222222 # ?\r
+ASM_PFX(ExtraPush): .long 0x33333333 # ?\r
+ASM_PFX(ExceptData): .long 0x44444444 # ?\r
+ASM_PFX(Eflags): .long 0x55555555 # ?\r
+ASM_PFX(OrigVector): .long 0x66666666 # ?\r
+ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)\r
+\r
+.globl ASM_PFX(FxStorSupport)\r
+ASM_PFX(FxStorSupport):\r
+ push %ebx\r
+ mov $0x1,%eax\r
+ cpuid \r
+ mov %edx,%eax\r
+ and $0x1000000,%eax\r
+ shr $0x18,%eax\r
+ pop %ebx\r
+ ret \r
+\r
+.globl ASM_PFX(GetIdtr)\r
+ASM_PFX(GetIdtr):\r
+ push %ebp\r
+ mov %esp,%ebp\r
+ add $0xfffffff8,%esp\r
+ sidtl 0xfffffffa(%ebp)\r
+ mov 0xfffffffc(%ebp),%eax\r
+ leave \r
+ ret \r
+\r
+.globl ASM_PFX(WriteInterruptFlag)\r
+ASM_PFX(WriteInterruptFlag):\r
+ push %ebp\r
+ mov %esp,%ebp\r
+ pushf \r
+ pop %eax\r
+ and $0x200,%eax\r
+ shr $0x9,%eax\r
+ mov 0x8(%ebp),%ecx\r
+ or %cl,%cl\r
+ jne ASM_PFX(WriteInterruptFlag+0x17)\r
+ cli \r
+ jmp ASM_PFX(WriteInterruptFlag+0x18)\r
+ sti \r
+ leave \r
+ ret \r
+\r
+.globl ASM_PFX(Vect2Desc)\r
+ASM_PFX(Vect2Desc):\r
+ push %ebp\r
+ mov %esp,%ebp\r
+ mov 0xc(%ebp),%eax\r
+ mov 0x8(%ebp),%ecx\r
+ mov %ax,(%ecx)\r
+ movw $0x20,0x2(%ecx)\r
+ movw $0x8e00,0x4(%ecx)\r
+ shr $0x10,%eax\r
+ mov %ax,0x6(%ecx)\r
+ leave \r
+ ret \r
+\r
+.globl ASM_PFX(InterruptEntryStub)\r
+ASM_PFX(InterruptEntryStub):\r
+ mov %esp,0x0\r
+ mov $0x0,%esp\r
+ push $0x0\r
+ jmp ASM_PFX(CommonIdtEntry)\r
+.globl ASM_PFX(InterruptEntryStubEnd)\r
+ASM_PFX(InterruptEntryStubEnd):\r
+\r
+.globl ASM_PFX(CommonIdtEntry)\r
+ASM_PFX(CommonIdtEntry):\r
+ pusha \r
+ pushf \r
+ pop %eax\r
+ mov %eax,0x0\r
+ cmpl $0x8,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x20)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0xa,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x35)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0xb,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x4a)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0xc,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x5f)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0xd,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x74)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0xe,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x89)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ cmpl $0x11,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0x9e)\r
+ movl $0x1,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xa8)\r
+ movl $0x0,0x0\r
+ cmpl $0x1,0x0\r
+ jne ASM_PFX(CommonIdtEntry+0xc8)\r
+ mov 0x0,%eax\r
+ mov (%eax),%ebx\r
+ mov %ebx,0x0\r
+ add $0x4,%eax\r
+ mov %eax,0x0\r
+ jmp ASM_PFX(CommonIdtEntry+0xd2)\r
+ movl $0x0,0x0\r
+ mov 0xc(%esp),%eax\r
+ mov %eax,0x0\r
+ mov 0x0,%eax\r
+ add $0xc,%eax\r
+ mov %eax,0xc(%esp)\r
+ mov %ss,%eax\r
+ push %eax\r
+ mov 0x0,%eax\r
+ movzwl 0x4(%eax),%eax\r
+ push %eax\r
+ mov %ds,%eax\r
+ push %eax\r
+ mov %es,%eax\r
+ push %eax\r
+ mov %fs,%eax\r
+ push %eax\r
+ mov %gs,%eax\r
+ push %eax\r
+ mov 0x0,%eax\r
+ pushl (%eax)\r
+ push $0x0\r
+ push $0x0\r
+ sidtl (%esp)\r
+ push $0x0\r
+ push $0x0\r
+ sgdtl (%esp)\r
+ xor %eax,%eax\r
+ str %eax\r
+ push %eax\r
+ sldt %eax\r
+ push %eax\r
+ mov 0x0,%eax\r
+ pushl 0x8(%eax)\r
+ mov %cr4,%eax\r
+ or $0x208,%eax\r
+ mov %eax,%cr4\r
+ push %eax\r
+ mov %cr3,%eax\r
+ push %eax\r
+ mov %cr2,%eax\r
+ push %eax\r
+ push $0x0\r
+ mov %cr0,%eax\r
+ push %eax\r
+ mov %db7,%eax\r
+ push %eax\r
+ xor %eax,%eax\r
+ mov %eax,%db7\r
+ mov %db6,%eax\r
+ push %eax\r
+ xor %eax,%eax\r
+ mov %eax,%db6\r
+ mov %db3,%eax\r
+ push %eax\r
+ mov %db2,%eax\r
+ push %eax\r
+ mov %db1,%eax\r
+ push %eax\r
+ mov %db0,%eax\r
+ push %eax\r
+ sub $0x200,%esp\r
+ mov %esp,%edi\r
+ fxsave (%edi)\r
+ mov 0x0,%eax\r
+ push %eax\r
+ mov %esp,%eax\r
+ push %eax\r
+ mov 0x0,%eax\r
+ push %eax\r
+ call ASM_PFX(CommonIdtEntry+0x184)\r
+ add $0x8,%esp\r
+ add $0x4,%esp\r
+ mov %esp,%esi\r
+ fxrstor (%esi)\r
+ add $0x200,%esp\r
+ pop %eax\r
+ mov %eax,%db0\r
+ pop %eax\r
+ mov %eax,%db1\r
+ pop %eax\r
+ mov %eax,%db2\r
+ pop %eax\r
+ mov %eax,%db3\r
+ add $0x4,%esp\r
+ pop %eax\r
+ mov %eax,%db7\r
+ pop %eax\r
+ mov %eax,%cr0\r
+ add $0x4,%esp\r
+ pop %eax\r
+ mov %eax,%cr2\r
+ pop %eax\r
+ mov %eax,%cr3\r
+ pop %eax\r
+ mov %eax,%cr4\r
+ mov 0x0,%eax\r
+ popl 0x8(%eax)\r
+ add $0x18,%esp\r
+ popl (%eax)\r
+ pop %gs\r
+ pop %fs\r
+ pop %es\r
+ pop %ds\r
+ popl 0x4(%eax)\r
+ pop %ss\r
+ mov 0xc(%esp),%ebx\r
+ mov 0x0,%eax\r
+ add $0xc,%eax\r
+ cmp %eax,%ebx\r
+ je ASM_PFX(CommonIdtEntry+0x202)\r
+ mov 0x0,%eax\r
+ mov (%eax),%ecx\r
+ mov %ecx,(%ebx)\r
+ mov 0x4(%eax),%ecx\r
+ mov %ecx,0x4(%ebx)\r
+ mov 0x8(%eax),%ecx\r
+ mov %ecx,0x8(%ebx)\r
+ mov %ebx,%eax\r
+ mov %eax,0x0\r
+ mov 0x0,%eax\r
+ mov %eax,0xc(%esp)\r
+ cmpl $0x68,0x0\r
+ jne PhonyIretd+0xd\r
+ mov 0x0,%eax\r
+ mov 0x8(%eax),%ebx\r
+ and $0xfffffcff,%ebx\r
+ push %ebx\r
+ push %cs\r
+ push $0x0\r
+ iret \r
+\r
+PhonyIretd:\r
+ popa \r
+ mov 0x0,%esp\r
+ jmp *0x0\r
+ popa \r
+ mov 0x0,%esp\r
+ iret \r
--- /dev/null
+;******************************************************************************\r
+;*\r
+;* Copyright (c) 2006, Intel Corporation \r
+;* All rights reserved. This program and the accompanying materials \r
+;* are licensed and made available under the terms and conditions of the BSD License \r
+;* which accompanies this distribution. The full text of the license may be found at \r
+;* http://opensource.org/licenses/bsd-license.php \r
+;* \r
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+;*\r
+;******************************************************************************\r
+\r
+.586p\r
+.MODEL FLAT, C\r
+\r
+EXCPT32_DIVIDE_ERROR EQU 0\r
+EXCPT32_DEBUG EQU 1\r
+EXCPT32_NMI EQU 2\r
+EXCPT32_BREAKPOINT EQU 3\r
+EXCPT32_OVERFLOW EQU 4\r
+EXCPT32_BOUND EQU 5\r
+EXCPT32_INVALID_OPCODE EQU 6\r
+EXCPT32_DOUBLE_FAULT EQU 8\r
+EXCPT32_INVALID_TSS EQU 10\r
+EXCPT32_SEG_NOT_PRESENT EQU 11\r
+EXCPT32_STACK_FAULT EQU 12\r
+EXCPT32_GP_FAULT EQU 13\r
+EXCPT32_PAGE_FAULT EQU 14\r
+EXCPT32_FP_ERROR EQU 16\r
+EXCPT32_ALIGNMENT_CHECK EQU 17\r
+EXCPT32_MACHINE_CHECK EQU 18\r
+EXCPT32_SIMD EQU 19\r
+\r
+FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags\r
+\r
+;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,\r
+;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver\r
+;; MUST check the CPUID feature flags to see that these instructions are available\r
+;; and fail to init if they are not.\r
+\r
+;; fxstor [edi]\r
+FXSTOR_EDI MACRO\r
+ db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [edi]\r
+ENDM\r
+\r
+;; fxrstor [esi]\r
+FXRSTOR_ESI MACRO\r
+ db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [esi]\r
+ENDM\r
+.DATA\r
+\r
+public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport\r
+\r
+StubSize dd InterruptEntryStubEnd - InterruptEntryStub\r
+AppEsp dd 11111111h ; ?\r
+DebugEsp dd 22222222h ; ?\r
+ExtraPush dd 33333333h ; ?\r
+ExceptData dd 44444444h ; ?\r
+Eflags dd 55555555h ; ?\r
+OrigVector dd 66666666h ; ?\r
+\r
+;; The declarations below define the memory region that will be used for the debug stack.\r
+;; The context record will be built by pushing register values onto this stack.\r
+;; It is imparitive that alignment be carefully managed, since the FXSTOR and\r
+;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r
+;;\r
+;; The stub will switch stacks from the application stack to the debuger stack\r
+;; and pushes the exception number.\r
+;;\r
+;; Then we building the context record on the stack. Since the stack grows down,\r
+;; we push the fields of the context record from the back to the front. There\r
+;; are 132 bytes of stack used prior allocating the 512 bytes of stack to be\r
+;; used as the memory buffer for the fxstor instruction. Therefore address of\r
+;; the buffer used for the FXSTOR instruction is &Eax - 132 - 512, which\r
+;; must be 16 byte aligned.\r
+;;\r
+;; We carefully locate the stack to make this happen.\r
+;;\r
+;; For reference, the context structure looks like this:\r
+;; struct {\r
+;; UINT32 ExceptionData;\r
+;; FX_SAVE_STATE_IA32 FxSaveState; // 512 bytes, must be 16 byte aligned\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+;; UINT32 EFlags;\r
+;; UINT32 Ldtr, Tr;\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+;; UINT32 Eip;\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record\r
+\r
+\r
+align 16\r
+DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment\r
+ dd 1ffdh dup (000000000h) ;; 32K should be enough stack\r
+ ;; This allocation is coocked to insure \r
+ ;; that the the buffer for the FXSTORE instruction\r
+ ;; will be 16 byte aligned also.\r
+ ;;\r
+ExceptionNumber dd ? ;; first entry will be the vector number pushed by the stub\r
+\r
+DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub\r
+\r
+.CODE\r
+\r
+externdef InterruptDistrubutionHub:near\r
+\r
+;------------------------------------------------------------------------------\r
+; BOOLEAN\r
+; FxStorSupport (\r
+; void\r
+; )\r
+;\r
+; Abstract: Returns TRUE if FxStor instructions are supported\r
+;\r
+FxStorSupport PROC C PUBLIC\r
+\r
+;\r
+; cpuid corrupts ebx which must be preserved per the C calling convention\r
+;\r
+ push ebx\r
+ mov eax, 1\r
+ cpuid\r
+ mov eax, edx\r
+ and eax, FXSTOR_FLAG\r
+ shr eax, 24\r
+ pop ebx\r
+ ret\r
+FxStorSupport ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; DESCRIPTOR *\r
+; GetIdtr (\r
+; void\r
+; )\r
+;\r
+; Abstract: Returns physical address of IDTR\r
+;\r
+GetIdtr PROC C PUBLIC\r
+ LOCAL IdtrBuf:FWORD\r
+\r
+ sidt IdtrBuf\r
+ mov eax, DWORD PTR IdtrBuf + 2\r
+ ret\r
+GetIdtr ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; BOOLEAN\r
+; WriteInterruptFlag (\r
+; BOOLEAN NewState\r
+; )\r
+;\r
+; Abstract: Programs interrupt flag to the requested state and returns previous\r
+; state.\r
+;\r
+WriteInterruptFlag PROC C PUBLIC State:DWORD\r
+\r
+ pushfd\r
+ pop eax\r
+ and eax, 200h\r
+ shr eax, 9\r
+ mov ecx, State\r
+ .IF cl == 0\r
+ cli\r
+ .ELSE\r
+ sti\r
+ .ENDIF\r
+ ret\r
+\r
+WriteInterruptFlag ENDP\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; void\r
+; Vect2Desc (\r
+; DESCRIPTOR * DestDesc,\r
+; void (*Vector) (void)\r
+; )\r
+;\r
+; Abstract: Encodes an IDT descriptor with the given physical address\r
+;\r
+Vect2Desc PROC C PUBLIC DestPtr:DWORD, Vector:DWORD\r
+\r
+ mov eax, Vector\r
+ mov ecx, DestPtr\r
+ mov word ptr [ecx], ax ; write bits 15..0 of offset\r
+ mov dx, cs\r
+ mov word ptr [ecx+2], dx ; SYS_CODE_SEL from GDT\r
+ mov word ptr [ecx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present\r
+ shr eax, 16\r
+ mov word ptr [ecx+6], ax ; write bits 31..16 of offset\r
+\r
+ ret\r
+\r
+Vect2Desc ENDP\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; InterruptEntryStub\r
+;\r
+; Abstract: This code is not a function, but is a small piece of code that is\r
+; copied and fixed up once for each IDT entry that is hooked.\r
+;\r
+InterruptEntryStub::\r
+ mov AppEsp, esp ; save stack top\r
+ mov esp, offset DebugStackBegin ; switch to debugger stack\r
+ push 0 ; push vector number - will be modified before installed\r
+ db 0e9h ; jump rel32\r
+ dd 0 ; fixed up to relative address of CommonIdtEntry\r
+InterruptEntryStubEnd:\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; CommonIdtEntry\r
+;\r
+; Abstract: This code is not a function, but is the common part for all IDT\r
+; vectors.\r
+;\r
+CommonIdtEntry::\r
+;;\r
+;; At this point, the stub has saved the current application stack esp into AppEsp\r
+;; and switched stacks to the debug stack, where it pushed the vector number\r
+;;\r
+;; The application stack looks like this:\r
+;;\r
+;; ...\r
+;; (last application stack entry)\r
+;; eflags from interrupted task\r
+;; CS from interrupted task\r
+;; EIP from interrupted task\r
+;; Error code <-------------------- Only present for some exeption types\r
+;;\r
+;;\r
+\r
+\r
+;; The stub switched us to the debug stack and pushed the interrupt number.\r
+;;\r
+;; Next, construct the context record. It will be build on the debug stack by\r
+;; pushing the registers in the correct order so as to create the context structure\r
+;; on the debug stack. The context record must be built from the end back to the\r
+;; beginning because the stack grows down...\r
+;\r
+;; For reference, the context record looks like this:\r
+;;\r
+;; typedef\r
+;; struct {\r
+;; UINT32 ExceptionData;\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; UINT32 Cr0, Cr2, Cr3, Cr4;\r
+;; UINT32 EFlags;\r
+;; UINT32 Ldtr, Tr;\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+;; UINT32 Eip;\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ pushad\r
+\r
+;; Save interrupt state eflags register...\r
+ pushfd\r
+ pop eax\r
+ mov dword ptr Eflags, eax\r
+\r
+;; We need to determine if any extra data was pushed by the exception, and if so, save it\r
+;; To do this, we check the exception number pushed by the stub, and cache the\r
+;; result in a variable since we'll need this again.\r
+ .IF ExceptionNumber == EXCPT32_DOUBLE_FAULT\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_INVALID_TSS\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_SEG_NOT_PRESENT\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_STACK_FAULT\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_GP_FAULT\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_PAGE_FAULT\r
+ mov ExtraPush, 1\r
+ .ELSEIF ExceptionNumber == EXCPT32_ALIGNMENT_CHECK\r
+ mov ExtraPush, 1\r
+ .ELSE\r
+ mov ExtraPush, 0\r
+ .ENDIF\r
+\r
+;; If there's some extra data, save it also, and modify the saved AppEsp to effectively\r
+;; pop this value off the application's stack.\r
+ .IF ExtraPush == 1\r
+ mov eax, AppEsp\r
+ mov ebx, [eax]\r
+ mov ExceptData, ebx\r
+ add eax, 4\r
+ mov AppEsp, eax\r
+ .ELSE\r
+ mov ExceptData, 0\r
+ .ENDIF\r
+\r
+;; The "pushad" above pushed the debug stack esp. Since what we're actually doing\r
+;; is building the context record on the debug stack, we need to save the pushed\r
+;; debug ESP, and replace it with the application's last stack entry...\r
+ mov eax, [esp + 12]\r
+ mov DebugEsp, eax\r
+ mov eax, AppEsp\r
+ add eax, 12\r
+ ; application stack has eflags, cs, & eip, so\r
+ ; last actual application stack entry is\r
+ ; 12 bytes into the application stack.\r
+ mov [esp + 12], eax\r
+\r
+;; continue building context record\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ mov eax, ss\r
+ push eax\r
+\r
+ ; CS from application is one entry back in application stack\r
+ mov eax, AppEsp\r
+ movzx eax, word ptr [eax + 4]\r
+ push eax\r
+\r
+ mov eax, ds\r
+ push eax\r
+ mov eax, es\r
+ push eax\r
+ mov eax, fs\r
+ push eax\r
+ mov eax, gs\r
+ push eax\r
+\r
+;; UINT32 Eip;\r
+ ; Eip from application is on top of application stack\r
+ mov eax, AppEsp\r
+ push dword ptr [eax]\r
+\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+ push 0\r
+ push 0\r
+ sidt fword ptr [esp]\r
+ push 0\r
+ push 0\r
+ sgdt fword ptr [esp]\r
+\r
+;; UINT32 Ldtr, Tr;\r
+ xor eax, eax\r
+ str ax\r
+ push eax\r
+ sldt ax\r
+ push eax\r
+\r
+;; UINT32 EFlags;\r
+;; Eflags from application is two entries back in application stack\r
+ mov eax, AppEsp\r
+ push dword ptr [eax + 8]\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+;; insure FXSAVE/FXRSTOR is enabled in CR4...\r
+;; ... while we're at it, make sure DE is also enabled...\r
+ mov eax, cr4\r
+ or eax, 208h\r
+ mov cr4, eax\r
+ push eax\r
+ mov eax, cr3\r
+ push eax\r
+ mov eax, cr2\r
+ push eax\r
+ push 0\r
+ mov eax, cr0\r
+ push eax\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov eax, dr7\r
+ push eax\r
+;; clear Dr7 while executing debugger itself\r
+ xor eax, eax\r
+ mov dr7, eax\r
+\r
+ mov eax, dr6\r
+ push eax\r
+;; insure all status bits in dr6 are clear...\r
+ xor eax, eax\r
+ mov dr6, eax\r
+\r
+ mov eax, dr3\r
+ push eax\r
+ mov eax, dr2\r
+ push eax\r
+ mov eax, dr1\r
+ push eax\r
+ mov eax, dr0\r
+ push eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ sub esp, 512\r
+ mov edi, esp\r
+ ; IMPORTANT!! The debug stack has been carefully constructed to\r
+ ; insure that esp and edi are 16 byte aligned when we get here.\r
+ ; They MUST be. If they are not, a GP fault will occur.\r
+ FXSTOR_EDI\r
+\r
+;; UINT32 ExceptionData;\r
+ mov eax, ExceptData\r
+ push eax\r
+\r
+; call to C code which will in turn call registered handler\r
+; pass in the vector number\r
+ mov eax, esp\r
+ push eax\r
+ mov eax, ExceptionNumber\r
+ push eax\r
+ call InterruptDistrubutionHub\r
+ add esp, 8\r
+\r
+; restore context...\r
+;; UINT32 ExceptionData;\r
+ add esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ mov esi, esp\r
+ FXRSTOR_ESI\r
+ add esp, 512\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop eax\r
+ mov dr0, eax\r
+ pop eax\r
+ mov dr1, eax\r
+ pop eax\r
+ mov dr2, eax\r
+ pop eax\r
+ mov dr3, eax\r
+;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add esp, 4\r
+ pop eax\r
+ mov dr7, eax\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ pop eax\r
+ mov cr0, eax\r
+ add esp, 4\r
+ pop eax\r
+ mov cr2, eax\r
+ pop eax\r
+ mov cr3, eax\r
+ pop eax\r
+ mov cr4, eax\r
+\r
+;; UINT32 EFlags;\r
+ mov eax, AppEsp\r
+ pop dword ptr [eax + 8]\r
+\r
+;; UINT32 Ldtr, Tr;\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+ add esp, 24\r
+\r
+;; UINT32 Eip;\r
+ pop dword ptr [eax]\r
+\r
+;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;\r
+;; NOTE - modified segment registers could hang the debugger... We\r
+;; could attempt to insulate ourselves against this possibility,\r
+;; but that poses risks as well.\r
+;;\r
+\r
+ pop gs\r
+ pop fs\r
+ pop es\r
+ pop ds\r
+ pop [eax + 4]\r
+ pop ss\r
+\r
+;; The next stuff to restore is the general purpose registers that were pushed\r
+;; using the "pushad" instruction.\r
+;;\r
+;; The value of ESP as stored in the context record is the application ESP\r
+;; including the 3 entries on the application stack caused by the exception\r
+;; itself. It may have been modified by the debug agent, so we need to\r
+;; determine if we need to relocate the application stack.\r
+\r
+ mov ebx, [esp + 12] ; move the potentially modified AppEsp into ebx\r
+ mov eax, AppEsp\r
+ add eax, 12\r
+ cmp ebx, eax\r
+ je NoAppStackMove\r
+\r
+ mov eax, AppEsp\r
+ mov ecx, [eax] ; EIP\r
+ mov [ebx], ecx\r
+\r
+ mov ecx, [eax + 4] ; CS\r
+ mov [ebx + 4], ecx\r
+\r
+ mov ecx, [eax + 8] ; EFLAGS\r
+ mov [ebx + 8], ecx\r
+\r
+ mov eax, ebx ; modify the saved AppEsp to the new AppEsp\r
+ mov AppEsp, eax\r
+NoAppStackMove:\r
+ mov eax, DebugEsp ; restore the DebugEsp on the debug stack\r
+ ; so our "popad" will not cause a stack switch\r
+ mov [esp + 12], eax\r
+\r
+ cmp ExceptionNumber, 068h\r
+ jne NoChain\r
+\r
+Chain:\r
+\r
+;; Restore eflags so when we chain, the flags will be exactly as if we were never here.\r
+;; We gin up the stack to do an iretd so we can get ALL the flags.\r
+ mov eax, AppEsp\r
+ mov ebx, [eax + 8]\r
+ and ebx, NOT 300h ; special handling for IF and TF\r
+ push ebx\r
+ push cs\r
+ push PhonyIretd\r
+ iretd\r
+PhonyIretd:\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ popad\r
+\r
+;; Switch back to application stack\r
+ mov esp, AppEsp\r
+\r
+;; Jump to original handler\r
+ jmp OrigVector\r
+\r
+NoChain:\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ popad\r
+\r
+;; Switch back to application stack\r
+ mov esp, AppEsp\r
+\r
+;; We're outa here...\r
+ iretd\r
+END\r
+\r
+\r
+\r
--- /dev/null
+/**@file\r
+ IA32 specific debug support functions\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// private header files\r
+//\r
+#include "plDebugSupport.h"\r
+\r
+//\r
+// This the global main table to keep track of the interrupts\r
+//\r
+IDT_ENTRY *IdtEntryTable = NULL;\r
+DESCRIPTOR NullDesc = 0;\r
+\r
+STATIC\r
+EFI_STATUS\r
+CreateEntryStub (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ OUT VOID **Stub\r
+ )\r
+/*++\r
+\r
+Routine Description: Allocate pool for a new IDT entry stub. Copy the generic\r
+ stub into the new buffer and fixup the vector number and jump target address.\r
+\r
+Arguments:\r
+ ExceptionType - This is the exception type that the new stub will be created\r
+ for.\r
+ Stub - On successful exit, *Stub contains the newly allocated entry stub.\r
+Returns:\r
+ Typically EFI_SUCCESS\r
+ other possibilities are passed through from AllocatePool\r
+\r
+--*/\r
+{\r
+ UINT8 *StubCopy;\r
+\r
+ StubCopy = *Stub;\r
+\r
+ //\r
+ // Fixup the stub code for this vector\r
+ //\r
+\r
+ // The stub code looks like this:\r
+ //\r
+ // 00000000 89 25 00000004 R mov AppEsp, esp ; save stack top\r
+ // 00000006 BC 00008014 R mov esp, offset DbgStkBot ; switch to debugger stack\r
+ // 0000000B 6A 00 push 0 ; push vector number - will be modified before installed\r
+ // 0000000D E9 db 0e9h ; jump rel32\r
+ // 0000000E 00000000 dd 0 ; fixed up to relative address of CommonIdtEntry\r
+ //\r
+\r
+ //\r
+ // poke in the exception type so the second push pushes the exception type\r
+ //\r
+ StubCopy[0x0c] = (UINT8) ExceptionType;\r
+\r
+ //\r
+ // fixup the jump target to point to the common entry\r
+ //\r
+ *(UINT32 *) &StubCopy[0x0e] = (UINT32) CommonIdtEntry - (UINT32) &StubCopy[StubSize];\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+HookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN VOID (*NewCallback) ()\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Creates a nes entry stub. Then saves the current IDT entry and replaces it\r
+ with an interrupt gate for the new entry point. The IdtEntryTable is updated\r
+ with the new registered function.\r
+\r
+ This code executes in boot services context. The stub entry executes in interrupt\r
+ context.\r
+\r
+Arguments:\r
+ ExceptionType - specifies which vector to hook.\r
+ NewCallback - a pointer to the new function to be registered.\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Other possibilities are passed through by CreateEntryStub\r
+\r
+--*/\r
+{\r
+ BOOLEAN OldIntFlagState;\r
+ EFI_STATUS Status;\r
+\r
+ Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry);\r
+ if (Status == EFI_SUCCESS) {\r
+ OldIntFlagState = WriteInterruptFlag (0);\r
+ ReadIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+\r
+ ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[0] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[0];\r
+ ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[1] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[3];\r
+\r
+ Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);\r
+ IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
+ WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));\r
+ WriteInterruptFlag (OldIntFlagState);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+UnhookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Undoes HookEntry. This code executes in boot services context.\r
+\r
+Arguments:\r
+ ExceptionType - specifies which entry to unhook\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ BOOLEAN OldIntFlagState;\r
+\r
+ OldIntFlagState = WriteInterruptFlag (0);\r
+ WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+ WriteInterruptFlag (OldIntFlagState);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ManageIdtEntryTable (\r
+ VOID (*NewCallback)(),\r
+ EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the main worker function that manages the state of the interrupt\r
+ handlers. It both installs and uninstalls interrupt handlers based on the\r
+ value of NewCallback. If NewCallback is NULL, then uninstall is indicated.\r
+ If NewCallback is non-NULL, then install is indicated.\r
+\r
+Arguments:\r
+ NewCallback - If non-NULL, NewCallback specifies the new handler to register.\r
+ If NULL, specifies that the previously registered handler should\r
+ be uninstalled.\r
+ ExceptionType - Indicates which entry to manage\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (FeaturePcdGet (PcdNtEmulatorEnable)) {\r
+ if (CompareDescriptor (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc)) {\r
+ //\r
+ // we've already installed to this vector\r
+ //\r
+ if (NewCallback != NULL) {\r
+ //\r
+ // if the input handler is non-null, error\r
+ //\r
+ Status = EFI_ALREADY_STARTED;\r
+ } else {\r
+ Status = UnhookEntry (ExceptionType);\r
+ }\r
+ } else {\r
+ //\r
+ // no user handler installed on this vector\r
+ //\r
+ if (NewCallback == NULL) {\r
+ //\r
+ // if the input handler is null, error\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Status = HookEntry (ExceptionType, NewCallback);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+{\r
+ *MaxProcessorIndex = 0;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ return ManageIdtEntryTable (NewCallback, ExceptionType);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+ Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+{\r
+ AsmWbinvd ();\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initializes driver's handler registration database.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_UNSUPPORTED - if IA32 processor does not support FXSTOR/FXRSTOR instructions,\r
+ the context save will fail, so these processor's are not supported.\r
+ EFI_OUT_OF_RESOURCES - not resource to finish initialization\r
+\r
+--*/\r
+{\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ if (!FxStorSupport ()) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);\r
+ if (IdtEntryTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize);\r
+ if (IdtEntryTable[ExceptionType].StubEntry == NULL) {\r
+ goto ErrorCleanup;\r
+ }\r
+\r
+ CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);\r
+ }\r
+ return EFI_SUCCESS;\r
+\r
+ErrorCleanup:\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
+ FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
+ }\r
+ }\r
+ FreePool (IdtEntryTable);\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the callback that is written to the LoadedImage protocol instance\r
+ on the image handle. It uninstalls all registered handlers and frees all entry\r
+ stub memory.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ ImageHandle - The image handle of the unload handler\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+{\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ ManageIdtEntryTable (NULL, ExceptionType);\r
+ }\r
+\r
+ FreePool (IdtEntryTable);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InterruptDistrubutionHub (\r
+ EFI_EXCEPTION_TYPE ExceptionType,\r
+ EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
+ )\r
+/*++\r
+\r
+Routine Description: Common piece of code that invokes the registered handlers.\r
+\r
+ This code executes in exception context so no efi calls are allowed.\r
+\r
+Arguments:\r
+ ExceptionType - exception type\r
+ ContextRecord - system context\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
+ if (ExceptionType != SYSTEM_TIMER_VECTOR) {\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);\r
+ } else {\r
+ OrigVector = IdtEntryTable[ExceptionType].OrigVector;\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/**@file\r
+ IA32 specific debug support macros, typedefs and prototypes.\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+#ifndef _PLDEBUG_SUPPORT_H\r
+#define _PLDEBUG_SUPPORT_H\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/DebugSupport.h>\r
+#include <Protocol/LoadedImage.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#define NUM_IDT_ENTRIES 0x78\r
+#define SYSTEM_TIMER_VECTOR 0x68\r
+#define VECTOR_ENTRY_PAGES 1\r
+#define CopyDescriptor(Dest, Src) CopyMem ((Dest), (Src), sizeof (DESCRIPTOR))\r
+#define ZeroDescriptor(Dest) CopyDescriptor ((Dest), &NullDesc)\r
+#define ReadIdt(Vector, Dest) CopyDescriptor ((Dest), &((GetIdtr ())[(Vector)]))\r
+#define WriteIdt(Vector, Src) CopyDescriptor (&((GetIdtr ())[(Vector)]), (Src))\r
+#define CompareDescriptor(Desc1, Desc2) CompareMem ((Desc1), (Desc2), sizeof (DESCRIPTOR))\r
+#define EFI_ISA IsaIa32\r
+#define FF_FXSR (1 << 24)\r
+\r
+typedef UINT64 DESCRIPTOR;\r
+\r
+typedef\r
+VOID\r
+(*DEBUG_PROC) (\r
+ VOID\r
+ )\r
+;\r
+\r
+typedef struct {\r
+ DESCRIPTOR OrigDesc;\r
+ DEBUG_PROC OrigVector;\r
+ DESCRIPTOR NewDesc;\r
+ DEBUG_PROC StubEntry;\r
+ VOID (*RegisteredCallback) ();\r
+} IDT_ENTRY;\r
+\r
+extern EFI_SYSTEM_CONTEXT SystemContext;\r
+extern UINT8 InterruptEntryStub[];\r
+extern UINT32 StubSize;\r
+extern VOID (*OrigVector) (VOID);\r
+\r
+VOID\r
+CommonIdtEntry (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Generic IDT entry\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+\r
+BOOLEAN\r
+FxStorSupport (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check whether FXSTOR is supported\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ TRUE - supported\r
+ FALSE - not supported\r
+\r
+--*/\r
+;\r
+\r
+DESCRIPTOR *\r
+GetIdtr (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Return the physical address of IDTR\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ The physical address of IDTR\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+Vect2Desc (\r
+ DESCRIPTOR * DestDesc,\r
+ VOID (*Vector) (VOID)\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Encodes an IDT descriptor with the given physical address\r
+\r
+Arguments:\r
+\r
+ DestDesc - The IDT descriptor address\r
+ Vector - The interrupt vector entry\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+WriteInterruptFlag (\r
+ BOOLEAN NewState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Programs interrupt flag to the requested state and returns previous\r
+ state.\r
+\r
+Arguments:\r
+\r
+ NewState - New interrupt status\r
+\r
+Returns:\r
+\r
+ Old interrupt status\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initializes driver's handler registration database.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_UNSUPPORTED - if IA32 processor does not support FXSTOR/FXRSTOR instructions,\r
+ the context save will fail, so these processor's are not supported.\r
+ EFI_OUT_OF_RESOURCES - not resource to finish initialization\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the callback that is written to the LoadedImage protocol instance\r
+ on the image handle. It uninstalls all registered handlers and frees all entry\r
+ stub memory.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ ImageHandle - The image handle of the unload handler\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// DebugSupport protocol member functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+ Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+//++\r
+// Copyright (c) 2006, Intel Corporation \r
+// All rights reserved. This program and the accompanying materials \r
+// are licensed and made available under the terms and conditions of the BSD License \r
+// which accompanies this distribution. The full text of the license may be found at \r
+// http://opensource.org/licenses/bsd-license.php \r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+// \r
+// Module Name:\r
+//\r
+// AsmFuncs.s\r
+//\r
+// Abstract:\r
+//\r
+// Low level IPF routines used by the debug support driver\r
+//\r
+// Revision History:\r
+//\r
+//--\r
+\r
+\r
+#include "common.i"\r
+#include "Ds64Macros.i"\r
+\r
+.globl PatchSaveBuffer\r
+.globl IpfContextBuf\r
+.globl CommonHandler\r
+.globl ExternalInterruptCount\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// InstructionCacheFlush\r
+//\r
+// Description:\r
+// Flushes instruction cache for specified number of bytes\r
+//\r
+ .globl InstructionCacheFlush\r
+ .proc InstructionCacheFlush\r
+ .align 32\r
+InstructionCacheFlush::\r
+ { .mii\r
+ alloc r3=2, 0, 0, 0\r
+ cmp4.leu p0,p6=32, r33;;\r
+ (p6) mov r33=32;;\r
+ }\r
+ { .mii\r
+ nop.m 0\r
+ zxt4 r29=r33;;\r
+ dep.z r30=r29, 0, 5;;\r
+ }\r
+ { .mii\r
+ cmp4.eq p0,p7=r0, r30\r
+ shr.u r28=r29, 5;;\r
+ (p7) adds r28=1, r28;;\r
+ }\r
+ { .mii\r
+ nop.m 0\r
+ shl r27=r28, 5;;\r
+ zxt4 r26=r27;;\r
+ }\r
+ { .mfb\r
+ add r31=r26, r32\r
+ nop.f 0\r
+ nop.b 0\r
+ }\r
+LoopBack: // $L143:\r
+ { .mii\r
+ fc r32\r
+ adds r32=32, r32;;\r
+ cmp.ltu p14,p15=r32, r31\r
+ }\r
+ { .mfb\r
+ nop.m 0\r
+ nop.f 0\r
+ //(p14) br.cond.dptk.few $L143#;;\r
+ (p14) br.cond.dptk.few LoopBack;;\r
+ }\r
+ { .mmi\r
+ sync.i;;\r
+ srlz.i\r
+ nop.i 0;;\r
+ }\r
+ { .mfb\r
+ nop.m 0\r
+ nop.f 0\r
+ br.ret.sptk.few b0;;\r
+ }\r
+ .endp InstructionCacheFlush\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// ChainHandler\r
+//\r
+// Description:\r
+// Chains an interrupt handler\r
+//\r
+// The purpose of this function is to enable chaining of the external interrupt.\r
+// Since there's no clean SAL abstraction for doing this, we must do it\r
+// surreptitiously.\r
+//\r
+// The reserved IVT entry at offset 0x3400 is coopted for use by this handler.\r
+// According to Itanium architecture, it is reserved. Strictly speaking, this is\r
+// not safe, as we're cheating and violating the Itanium architecture. However,\r
+// as long as we're the only ones cheating, we should be OK. Without hooks in\r
+// the SAL to enable IVT management, there aren't many good options.\r
+//\r
+// The strategy is to replace the first bundle of the external interrupt handler\r
+// with our own that will branch into a piece of code we've supplied and located\r
+// in the reserved IVT entry. Only the first bundle of the external interrupt\r
+// IVT entry is modified.\r
+//\r
+// The original bundle is moved and relocated to space\r
+// allocated within the reserved IVT entry. The next bundle following is\r
+// is generated to go a hard coded branch back to the second bundle of the\r
+// external interrupt IVT entry just in case the first bundle had no branch.\r
+//\r
+// Our new code will execute our handler, and then fall through to the\r
+// original bundle after restoring all context appropriately.\r
+//\r
+// The following is a representation of what the IVT memory map looks like with\r
+// our chained handler installed:\r
+//\r
+//\r
+// \r
+// \r
+// \r
+// This IVT entry is Failsafe bundle \r
+// reserved by the \r
+// Itanium architecture Original bundle 0 \r
+// and is used for \r
+// for locating our \r
+// handler and the \r
+// original bundle Patch code... \r
+// zero of the ext \r
+// interrupt handler \r
+// \r
+// RSVD (3400) Unused \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// \r
+// EXT_INT (3000) Bundle 0 Bundle zero - This one is\r
+// modified, all other bundles\r
+// in the EXT_INT entry are\r
+// untouched.\r
+//\r
+//\r
+// Arguments:\r
+//\r
+// Returns:\r
+//\r
+// Notes:\r
+//\r
+//\r
+ .globl ChainHandler\r
+ .proc ChainHandler\r
+ChainHandler:\r
+\r
+ NESTED_SETUP( 0,2+3,3,0 )\r
+\r
+ mov r8=1 // r8 = success\r
+ mov r2=cr.iva;;\r
+//\r
+// NOTE: There's a potential hazard here in that we're simply stealing a bunch of\r
+// bundles (memory) from the IVT and assuming there's no catastrophic side effect.\r
+//\r
+// First, save IVT area we're taking over with the patch so we can restore it later\r
+//\r
+ addl out0=PATCH_ENTRY_OFFSET, r2 // out0 = source buffer\r
+ movl out1=PatchSaveBuffer // out1 = destination buffer\r
+ mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+// Next, copy the patch code into the IVT\r
+ movl out0=PatchCode // out0 = source buffer of patch code\r
+ addl out1=PATCH_OFFSET, r2 // out1 = destination buffer - in IVT\r
+ mov out2=NUM_PATCH_BUNDLES;; // out2 = number of bundles to copy\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+\r
+// copy original bundle 0 from the external interrupt handler to the\r
+// appropriate place in the reserved IVT interrupt slot\r
+ addl out0=EXT_INT_ENTRY_OFFSET, r2 // out0 = source buffer\r
+ addl out1=RELOCATED_EXT_INT, r2 // out1 = destination buffer - in reserved IVT\r
+ mov out2=1;; // out2 = copy 1 bundle\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+// Now relocate it there because it very likely had a branch instruction that\r
+// that must now be fixed up.\r
+ addl out0=RELOCATED_EXT_INT, r2 // out0 = new runtime address of bundle - in reserved IVT\r
+ addl out1=EXT_INT_ENTRY_OFFSET, r2;;// out1 = IP address of previous location\r
+ mov out2=out0;; // out2 = IP address of new location\r
+ br.call.sptk.few b0 = RelocateBundle\r
+\r
+// Now copy into the failsafe branch into the next bundle just in case\r
+// the original ext int bundle 0 bundle did not contain a branch instruction\r
+ movl out0=FailsafeBranch // out0 = source buffer\r
+ addl out1=FAILSAFE_BRANCH_OFFSET, r2 // out1 = destination buffer - in reserved IVT\r
+ mov out2=1;; // out2 = copy 1 bundle\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+// Last, copy in our replacement for the external interrupt IVT entry bundle 0\r
+ movl out0=PatchCodeNewBun0 // out0 = source buffer - our replacement bundle 0\r
+ addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - bundle 0 of External interrupt entry\r
+ mov out2=1;; // out2 = copy 1 bundle\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+ChainHandlerDone:\r
+ NESTED_RETURN\r
+\r
+ .endp ChainHandler\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// UnchainHandler\r
+//\r
+// Description:\r
+// Unchains an interrupt handler\r
+//\r
+// Arguments:\r
+//\r
+// Returns:\r
+//\r
+// Notes:\r
+//\r
+//\r
+ .globl UnchainHandler\r
+ .proc UnchainHandler\r
+\r
+UnchainHandler:\r
+\r
+ NESTED_SETUP( 0,2+3,3,0 )\r
+\r
+ mov r8=1 // r8 = success\r
+ mov r2=cr.iva;; // r2 = interrupt vector address\r
+\r
+// First copy original Ext Int bundle 0 back to it's proper home...\r
+ addl out0=RELOCATED_EXT_INT, r2 // out0 = source - in reserved IVT\r
+ addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - first bundle of Ext Int entry\r
+ mov out2=1;; // out2 = copy 1 bundle\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+// Now, relocate it again...\r
+ addl out0=EXT_INT_ENTRY_OFFSET, r2 // out1 = New runtime address\r
+ addl out1=RELOCATED_EXT_INT, r2;; // out0 = IP address of previous location\r
+ mov out2=out0;; // out2 = IP address of new location\r
+ br.call.sptk.few b0 = RelocateBundle\r
+\r
+// Last, restore the patch area\r
+ movl out0=PatchSaveBuffer // out0 = source buffer\r
+ addl out1=PATCH_ENTRY_OFFSET, r2 // out1 = destination buffer\r
+ mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry\r
+ br.call.sptk.few b0 = CopyBundles\r
+\r
+UnchainHandlerDone:\r
+ NESTED_RETURN\r
+\r
+ .endp UnchainHandler\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// CopyBundles\r
+//\r
+// Description:\r
+// Copies instruction bundles - flushes icache as necessary\r
+//\r
+// Arguments:\r
+// in0 - Bundle source\r
+// in1 - Bundle destination\r
+// in2 - Bundle count\r
+//\r
+// Returns:\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+ .proc CopyBundles\r
+\r
+CopyBundles:\r
+\r
+ NESTED_SETUP(3,2+1,0,0)\r
+\r
+ shl in2=in2, 1;; // in2 = count of 8 byte blocks to copy\r
+\r
+CopyBundlesLoop:\r
+\r
+ cmp.eq p14, p15 = 0, in2;; // Check if done\r
+(p14) br.sptk.few CopyBundlesDone;;\r
+\r
+ ld8 loc2=[in0], 0x8;; // loc2 = source bytes\r
+ st8 [in1]=loc2;; // [in1] = destination bytes\r
+ fc in1;; // Flush instruction cache\r
+ sync.i;; // Ensure local and remote data/inst caches in sync\r
+ srlz.i;; // Ensure sync has been observed\r
+ add in1=0x8, in1;; // in1 = next destination\r
+ add in2=-1, in2;; // in2 = decrement 8 bytes blocks to copy\r
+ br.sptk.few CopyBundlesLoop;;\r
+\r
+CopyBundlesDone:\r
+ NESTED_RETURN\r
+\r
+ .endp CopyBundles\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// RelocateBundle\r
+//\r
+// Description:\r
+// Relocates an instruction bundle by updating any ip-relative branch instructions.\r
+//\r
+// Arguments:\r
+// in0 - Runtime address of bundle\r
+// in1 - IP address of previous location of bundle\r
+// in2 - IP address of new location of bundle\r
+//\r
+// Returns:\r
+// in0 - 1 if successful or 0 if unsuccessful\r
+//\r
+// Notes:\r
+// This routine examines all slots in the given bundle that are destined for the\r
+// branch execution unit. If any of these slots contain an IP-relative branch\r
+// namely instructions B1, B2, B3, or B6, the slot is fixed-up with a new relative\r
+// address. Errors can occur if a branch cannot be reached.\r
+//\r
+ .proc RelocateBundle\r
+\r
+RelocateBundle:\r
+\r
+ NESTED_SETUP(3,2+4,3,0)\r
+\r
+ mov loc2=SLOT0 // loc2 = slot index\r
+ mov loc5=in0;; // loc5 = runtime address of bundle\r
+ mov in0=1;; // in0 = success\r
+\r
+RelocateBundleNextSlot:\r
+\r
+ cmp.ge p14, p15 = SLOT2, loc2;; // Check if maximum slot\r
+(p15) br.sptk.few RelocateBundleDone\r
+\r
+ mov out0=loc5;; // out0 = runtime address of bundle\r
+ br.call.sptk.few b0 = GetTemplate\r
+ mov loc3=out0;; // loc3 = instruction template\r
+ mov out0=loc5 // out0 = runtime address of bundle\r
+ mov out1=loc2;; // out1 = instruction slot number\r
+ br.call.sptk.few b0 = GetSlot\r
+ mov loc4=out0;; // loc4 = instruction encoding\r
+ mov out0=loc4 // out0 = instuction encoding\r
+ mov out1=loc2 // out1 = instruction slot number\r
+ mov out2=loc3;; // out2 = instruction template\r
+ br.call.sptk.few b0 = IsSlotBranch\r
+ cmp.eq p14, p15 = 1, out0;; // Check if branch slot\r
+(p15) add loc2=1,loc2 // Increment slot\r
+(p15) br.sptk.few RelocateBundleNextSlot\r
+ mov out0=loc4 // out0 = instuction encoding\r
+ mov out1=in1 // out1 = IP address of previous location\r
+ mov out2=in2;; // out2 = IP address of new location\r
+ br.call.sptk.few b0 = RelocateSlot\r
+ cmp.eq p14, p15 = 1, out1;; // Check if relocated slot\r
+(p15) mov in0=0 // in0 = failure\r
+(p15) br.sptk.few RelocateBundleDone\r
+ mov out2=out0;; // out2 = instruction encoding\r
+ mov out0=loc5 // out0 = runtime address of bundle\r
+ mov out1=loc2;; // out1 = instruction slot number\r
+ br.call.sptk.few b0 = SetSlot\r
+ add loc2=1,loc2;; // Increment slot\r
+ br.sptk.few RelocateBundleNextSlot\r
+\r
+RelocateBundleDone:\r
+ NESTED_RETURN\r
+\r
+ .endp RelocateBundle\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// RelocateSlot\r
+//\r
+// Description:\r
+// Relocates an instruction bundle by updating any ip-relative branch instructions.\r
+//\r
+// Arguments:\r
+// in0 - Instruction encoding (41-bits, right justified)\r
+// in1 - IP address of previous location of bundle\r
+// in2 - IP address of new location of bundle\r
+//\r
+// Returns:\r
+// in0 - Instruction encoding (41-bits, right justified)\r
+// in1 - 1 if successful otherwise 0\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+ .proc RelocateSlot\r
+\r
+RelocateSlot:\r
+ NESTED_SETUP(3,2+5,0,0)\r
+ extr.u loc2=in0, 37, 4;; // loc2 = instruction opcode\r
+ cmp.eq p14, p15 = 4, loc2;; // IP-relative branch (B1) or\r
+ // IP-relative counted branch (B2)\r
+(p15) cmp.eq p14, p15 = 5, loc2;; // IP-relative call (B3)\r
+(p15) cmp.eq p14, p15 = 7, loc2;; // IP-relative predict (B6)\r
+(p15) mov in1=1 // Instruction did not need to be reencoded\r
+(p15) br.sptk.few RelocateSlotDone\r
+ tbit.nz p14, p15 = in0, 36;; // put relative offset sign bit in p14\r
+ extr.u loc2=in0, 13, 20;; // loc2 = relative offset in instruction\r
+(p14) movl loc3=0xfffffffffff00000;; // extend sign\r
+(p14) or loc2=loc2, loc3;;\r
+ shl loc2=loc2,4;; // convert to byte offset instead of bundle offset\r
+ add loc3=loc2, in1;; // loc3 = physical address of branch target\r
+(p14) sub loc2=r0,loc2;; // flip sign in loc2 if offset is negative\r
+ sub loc4=loc3,in2;; // loc4 = relative offset from new ip to branch target\r
+ cmp.lt p15, p14 = 0, loc4;; // get new sign bit \r
+(p14) sub loc5=r0,loc4 // get absolute value of offset\r
+(p15) mov loc5=loc4;;\r
+ movl loc6=0x0FFFFFF;; // maximum offset in bytes for ip-rel branch\r
+ cmp.gt p14, p15 = loc5, loc6;; // check to see we're not out of range for an ip-relative branch\r
+(p14) br.sptk.few RelocateSlotError\r
+ cmp.lt p15, p14 = 0, loc4;; // store sign in p14 again\r
+(p14) dep in0=1,in0,36,1 // store sign bit in instruction\r
+(p15) dep in0=0,in0,36,1\r
+ shr loc4=loc4, 4;; // convert back to bundle offset\r
+ dep in0=loc4,in0,13,16;; // put first 16 bits of new offset into instruction\r
+ shr loc4=loc4,16;;\r
+ dep in0=loc4,in0,13+16,4 // put last 4 bits of new offset into instruction\r
+ mov in1=1;; // in1 = success\r
+ br.sptk.few RelocateSlotDone;;\r
+\r
+RelocateSlotError:\r
+ mov in1=0;; // in1 = failure\r
+\r
+RelocateSlotDone:\r
+ NESTED_RETURN\r
+\r
+ .endp RelocateSlot\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// IsSlotBranch\r
+//\r
+// Description:\r
+// Determines if the given instruction is a branch instruction.\r
+//\r
+// Arguments:\r
+// in0 - Instruction encoding (41-bits, right justified)\r
+// in1 - Instruction slot number\r
+// in2 - Bundle template\r
+//\r
+// Returns:\r
+// in0 - 1 if branch or 0 if not branch\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+// IsSlotBranch recognizes all branch instructions by looking at the provided template.\r
+// The instruction encoding is only passed to this routine for future expansion.\r
+//\r
+ .proc IsSlotBranch\r
+\r
+IsSlotBranch:\r
+\r
+ NESTED_SETUP (3,2+0,0,0)\r
+\r
+ mov in0=1;; // in0 = 1 which destroys the instruction\r
+ andcm in2=in2,in0;; // in2 = even template to reduce compares\r
+ mov in0=0;; // in0 = not a branch\r
+ cmp.eq p14, p15 = 0x16, in2;; // Template 0x16 is BBB\r
+(p14) br.sptk.few IsSlotBranchTrue\r
+ cmp.eq p14, p15 = SLOT0, in1;; // Slot 0 has no other possiblities\r
+(p14) br.sptk.few IsSlotBranchDone\r
+ cmp.eq p14, p15 = 0x12, in2;; // Template 0x12 is MBB\r
+(p14) br.sptk.few IsSlotBranchTrue\r
+ cmp.eq p14, p15 = SLOT1, in1;; // Slot 1 has no other possiblities\r
+(p14) br.sptk.few IsSlotBranchDone\r
+ cmp.eq p14, p15 = 0x10, in2;; // Template 0x10 is MIB\r
+(p14) br.sptk.few IsSlotBranchTrue\r
+ cmp.eq p14, p15 = 0x18, in2;; // Template 0x18 is MMB\r
+(p14) br.sptk.few IsSlotBranchTrue\r
+ cmp.eq p14, p15 = 0x1C, in2;; // Template 0x1C is MFB\r
+(p14) br.sptk.few IsSlotBranchTrue\r
+ br.sptk.few IsSlotBranchDone\r
+\r
+IsSlotBranchTrue:\r
+ mov in0=1;; // in0 = branch\r
+\r
+IsSlotBranchDone:\r
+ NESTED_RETURN\r
+\r
+ .endp IsSlotBranch\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// GetTemplate\r
+//\r
+// Description:\r
+// Retrieves the instruction template for an instruction bundle\r
+//\r
+// Arguments:\r
+// in0 - Runtime address of bundle\r
+//\r
+// Returns:\r
+// in0 - Instruction template (5-bits, right-justified)\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+ .proc GetTemplate\r
+\r
+GetTemplate:\r
+\r
+ NESTED_SETUP (1,2+2,0,0)\r
+\r
+ ld8 loc2=[in0], 0x8 // loc2 = first 8 bytes of branch bundle\r
+ movl loc3=MASK_0_4;; // loc3 = template mask\r
+ and loc2=loc2,loc3;; // loc2 = template, right justified\r
+ mov in0=loc2;; // in0 = template, right justified\r
+\r
+ NESTED_RETURN\r
+\r
+ .endp GetTemplate\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// GetSlot\r
+//\r
+// Description:\r
+// Gets the instruction encoding for an instruction slot and bundle\r
+//\r
+// Arguments:\r
+// in0 - Runtime address of bundle\r
+// in1 - Instruction slot (either 0, 1, or 2)\r
+//\r
+// Returns:\r
+// in0 - Instruction encoding (41-bits, right justified)\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+// Slot0 - [in0 + 0x8] Bits 45-5\r
+// Slot1 - [in0 + 0x8] Bits 63-46 and [in0] Bits 22-0\r
+// Slot2 - [in0] Bits 63-23\r
+//\r
+ .proc GetSlot\r
+\r
+GetSlot:\r
+ NESTED_SETUP (2,2+3,0,0)\r
+\r
+ ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of branch bundle\r
+ ld8 loc3=[in0];; // loc3 = second 8 bytes of branch bundle\r
+ cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified\r
+ (p14) br.cond.sptk.few GetSlot2;; // get slot 2\r
+ cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified\r
+ (p14) br.cond.sptk.few GetSlot1;; // get slot 1\r
+\r
+GetSlot0:\r
+ extr.u in0=loc2, 5, 45 // in0 = extracted slot 0\r
+ br.sptk.few GetSlotDone;;\r
+\r
+GetSlot1:\r
+ extr.u in0=loc2, 46, 18 // in0 = bits 63-46 of loc2 right-justified\r
+ extr.u loc4=loc3, 0, 23;; // loc4 = bits 22-0 of loc3 right-justified\r
+ dep in0=loc4, in0, 18, 15;;\r
+ shr.u loc4=loc4,15;;\r
+ dep in0=loc4, in0, 33, 8;; // in0 = extracted slot 1\r
+ br.sptk.few GetSlotDone;;\r
+\r
+GetSlot2:\r
+ extr.u in0=loc3, 23, 41;; // in0 = extracted slot 2\r
+\r
+GetSlotDone:\r
+ NESTED_RETURN\r
+\r
+ .endp GetSlot\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// SetSlot\r
+//\r
+// Description:\r
+// Sets the instruction encoding for an instruction slot and bundle\r
+//\r
+// Arguments:\r
+// in0 - Runtime address of bundle\r
+// in1 - Instruction slot (either 0, 1, or 2)\r
+// in2 - Instruction encoding (41-bits, right justified)\r
+//\r
+// Returns:\r
+//\r
+// Notes:\r
+// This procedure is a leaf routine\r
+//\r
+ .proc SetSlot\r
+\r
+SetSlot:\r
+ NESTED_SETUP (3,2+3,0,0)\r
+\r
+ ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of bundle\r
+ ld8 loc3=[in0];; // loc3 = second 8 bytes of bundle\r
+ cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified\r
+ (p14) br.cond.sptk.few SetSlot2;; // set slot 2\r
+ cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified\r
+ (p14) br.cond.sptk.few SetSlot1;; // set slot 1\r
+\r
+SetSlot0:\r
+ dep loc2=0, loc2, 5, 41;; // remove old instruction from slot 0\r
+ shl loc4=in2, 5;; // loc4 = new instruction ready to be inserted\r
+ or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle\r
+ add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle\r
+ st8 [loc4]=loc2 // [loc4] = updated bundle\r
+ br.sptk.few SetSlotDone;;\r
+ ;;\r
+\r
+SetSlot1:\r
+ dep loc2=0, loc2, 46, 18 // remove old instruction from slot 1\r
+ dep loc3=0, loc3, 0, 23;;\r
+ shl loc4=in2, 46;; // loc4 = partial instruction ready to be inserted\r
+ or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle\r
+ add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle\r
+ st8 [loc4]=loc2;; // [loc4] = updated bundle\r
+ shr.u loc4=in2, 18;; // loc4 = partial instruction ready to be inserted\r
+ or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle\r
+ st8 [in0]=loc3;; // [in0] = updated bundle\r
+ br.sptk.few SetSlotDone;;\r
+\r
+SetSlot2:\r
+ dep loc3=0, loc3, 23, 41;; // remove old instruction from slot 2\r
+ shl loc4=in2, 23;; // loc4 = instruction ready to be inserted\r
+ or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle\r
+ st8 [in0]=loc3;; // [in0] = updated bundle\r
+\r
+SetSlotDone:\r
+\r
+ NESTED_RETURN\r
+ .endp SetSlot\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// GetIva\r
+//\r
+// Description:\r
+// C callable function to obtain the current value of IVA\r
+//\r
+// Returns:\r
+// Current value if IVA\r
+\r
+ .globl GetIva\r
+ .proc GetIva\r
+GetIva:\r
+ mov r8=cr2;;\r
+ br.ret.sptk.many b0\r
+\r
+ .endp GetIva\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// ProgramInterruptFlags\r
+//\r
+// Description:\r
+// C callable function to enable/disable interrupts\r
+//\r
+// Returns:\r
+// Previous state of psr.ic\r
+//\r
+ .globl ProgramInterruptFlags\r
+ .proc ProgramInterruptFlags\r
+ProgramInterruptFlags:\r
+ alloc loc0=1,2,0,0;;\r
+ mov loc0=psr\r
+ mov loc1=0x6000;;\r
+ and r8=loc0, loc1 // obtain current psr.ic and psr.i state\r
+ and in0=in0, loc1 // insure no extra bits set in input\r
+ andcm loc0=loc0,loc1;; // clear original psr.i and psr.ic\r
+ or loc0=loc0,in0;; // OR in new psr.ic value\r
+ mov psr.l=loc0;; // write new psr\r
+ srlz.d\r
+ br.ret.sptk.many b0 // return\r
+\r
+ .endp ProgramInterruptFlags\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// SpillContext\r
+//\r
+// Description:\r
+// Saves system context to context record.\r
+//\r
+// Arguments:\r
+// in0 = 512 byte aligned context record address\r
+// in1 = original B0\r
+// in2 = original ar.bsp\r
+// in3 = original ar.bspstore\r
+// in4 = original ar.rnat\r
+// in5 = original ar.pfs\r
+//\r
+// Notes:\r
+// loc0 - scratch\r
+// loc1 - scratch\r
+// loc2 - temporary application unat storage\r
+// loc3 - temporary exception handler unat storage\r
+\r
+ .proc SpillContext\r
+\r
+SpillContext:\r
+ alloc loc0=6,4,0,0;; // alloc 6 input, 4 locals, 0 outs\r
+ mov loc2=ar.unat;; // save application context unat (spilled later)\r
+ mov ar.unat=r0;; // set UNAT=0\r
+ st8.spill [in0]=r0,8;;\r
+ st8.spill [in0]=r1,8;; // save R1 - R31\r
+ st8.spill [in0]=r2,8;;\r
+ st8.spill [in0]=r3,8;;\r
+ st8.spill [in0]=r4,8;;\r
+ st8.spill [in0]=r5,8;;\r
+ st8.spill [in0]=r6,8;;\r
+ st8.spill [in0]=r7,8;;\r
+ st8.spill [in0]=r8,8;;\r
+ st8.spill [in0]=r9,8;;\r
+ st8.spill [in0]=r10,8;;\r
+ st8.spill [in0]=r11,8;;\r
+ st8.spill [in0]=r12,8;;\r
+ st8.spill [in0]=r13,8;;\r
+ st8.spill [in0]=r14,8;;\r
+ st8.spill [in0]=r15,8;;\r
+ st8.spill [in0]=r16,8;;\r
+ st8.spill [in0]=r17,8;;\r
+ st8.spill [in0]=r18,8;;\r
+ st8.spill [in0]=r19,8;;\r
+ st8.spill [in0]=r20,8;;\r
+ st8.spill [in0]=r21,8;;\r
+ st8.spill [in0]=r22,8;;\r
+ st8.spill [in0]=r23,8;;\r
+ st8.spill [in0]=r24,8;;\r
+ st8.spill [in0]=r25,8;;\r
+ st8.spill [in0]=r26,8;;\r
+ st8.spill [in0]=r27,8;;\r
+ st8.spill [in0]=r28,8;;\r
+ st8.spill [in0]=r29,8;;\r
+ st8.spill [in0]=r30,8;;\r
+ st8.spill [in0]=r31,8;;\r
+ mov loc3=ar.unat;; // save debugger context unat (spilled later)\r
+ stf.spill [in0]=f2,16;; // save f2 - f31\r
+ stf.spill [in0]=f3,16;;\r
+ stf.spill [in0]=f4,16;;\r
+ stf.spill [in0]=f5,16;;\r
+ stf.spill [in0]=f6,16;;\r
+ stf.spill [in0]=f7,16;;\r
+ stf.spill [in0]=f8,16;;\r
+ stf.spill [in0]=f9,16;;\r
+ stf.spill [in0]=f10,16;;\r
+ stf.spill [in0]=f11,16;;\r
+ stf.spill [in0]=f12,16;;\r
+ stf.spill [in0]=f13,16;;\r
+ stf.spill [in0]=f14,16;;\r
+ stf.spill [in0]=f15,16;;\r
+ stf.spill [in0]=f16,16;;\r
+ stf.spill [in0]=f17,16;;\r
+ stf.spill [in0]=f18,16;;\r
+ stf.spill [in0]=f19,16;;\r
+ stf.spill [in0]=f20,16;;\r
+ stf.spill [in0]=f21,16;;\r
+ stf.spill [in0]=f22,16;;\r
+ stf.spill [in0]=f23,16;;\r
+ stf.spill [in0]=f24,16;;\r
+ stf.spill [in0]=f25,16;;\r
+ stf.spill [in0]=f26,16;;\r
+ stf.spill [in0]=f27,16;;\r
+ stf.spill [in0]=f28,16;;\r
+ stf.spill [in0]=f29,16;;\r
+ stf.spill [in0]=f30,16;;\r
+ stf.spill [in0]=f31,16;;\r
+ mov loc0=pr;; // save predicates\r
+ st8.spill [in0]=loc0,8;;\r
+ st8.spill [in0]=in1,8;; // save b0 - b7... in1 already equals saved b0\r
+ mov loc0=b1;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b2;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b3;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b4;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b5;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b6;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=b7;;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.rsc;; // save ar.rsc\r
+ st8.spill [in0]=loc0,8;;\r
+ st8.spill [in0]=in2,8;; // save ar.bsp (in2)\r
+ st8.spill [in0]=in3,8;; // save ar.bspstore (in3)\r
+ st8.spill [in0]=in4,8;; // save ar.rnat (in4)\r
+ mov loc0=ar.fcr;; // save ar.fcr (ar21 - IA32 floating-point control register)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.eflag;; // save ar.eflag (ar24)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.csd;; // save ar.csd (ar25 - ia32 CS descriptor)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.ssd;; // save ar.ssd (ar26 - ia32 ss descriptor)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.cflg;; // save ar.cflg (ar27 - ia32 cr0 and cr4)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.fsr;; // save ar.fsr (ar28 - ia32 floating-point status register)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.fir;; // save ar.fir (ar29 - ia32 floating-point instruction register)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.fdr;; // save ar.fdr (ar30 - ia32 floating-point data register)\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.ccv;; // save ar.ccv\r
+ st8.spill [in0]=loc0,8;;\r
+ st8.spill [in0]=loc2,8;; // save ar.unat (saved to loc2 earlier)\r
+ mov loc0=ar.fpsr;; // save floating point status register\r
+ st8.spill [in0]=loc0,8;;\r
+ st8.spill [in0]=in5,8;; // save ar.pfs\r
+ mov loc0=ar.lc;; // save ar.lc\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ar.ec;; // save ar.ec\r
+ st8.spill [in0]=loc0,8;;\r
+\r
+ // save control registers\r
+ mov loc0=cr.dcr;; // save dcr\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.itm;; // save itm\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.iva;; // save iva\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.pta;; // save pta\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.ipsr;; // save ipsr\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.isr;; // save isr\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.iip;; // save iip\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.ifa;; // save ifa\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.itir;; // save itir\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.iipa;; // save iipa\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.ifs;; // save ifs\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.iim;; // save iim\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=cr.iha;; // save iha\r
+ st8.spill [in0]=loc0,8;;\r
+\r
+ // save debug registers\r
+ mov loc0=dbr[r0];; // save dbr0 - dbr7\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=1;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=2;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=3;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=4;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=5;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=6;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=7;;\r
+ mov loc0=dbr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ mov loc0=ibr[r0];; // save ibr0 - ibr7\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=1;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=2;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=3;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=4;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=5;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=6;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ movl loc1=7;;\r
+ mov loc0=ibr[loc1];;\r
+ st8.spill [in0]=loc0,8;;\r
+ st8.spill [in0]=loc3;;\r
+\r
+ br.ret.sptk.few b0\r
+\r
+ .endp SpillContext\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// FillContext\r
+//\r
+// Description:\r
+// Restores register context from context record.\r
+//\r
+// Arguments:\r
+// in0 = address of last element 512 byte aligned context record address\r
+// in1 = modified B0\r
+// in2 = modified ar.bsp\r
+// in3 = modified ar.bspstore\r
+// in4 = modified ar.rnat\r
+// in5 = modified ar.pfs\r
+//\r
+// Notes:\r
+// loc0 - scratch\r
+// loc1 - scratch\r
+// loc2 - temporary application unat storage\r
+// loc3 - temporary exception handler unat storage\r
+\r
+ .proc FillContext\r
+FillContext:\r
+ alloc loc0=6,4,0,0;; // alloc 6 inputs, 4 locals, 0 outs\r
+ ld8.fill loc3=[in0],-8;; // int_nat (nat bits for R1-31)\r
+ movl loc1=7;; // ibr7\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=6;; // ibr6\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=5;; // ibr5\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=4;; // ibr4\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=3;; // ibr3\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=2;; // ibr2\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ movl loc1=1;; // ibr1\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov ibr[loc1]=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ibr0\r
+ mov ibr[r0]=loc0;;\r
+ movl loc1=7;; // dbr7\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=6;; // dbr6\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=5;; // dbr5\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=4;; // dbr4\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=3;; // dbr3\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=2;; // dbr2\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ movl loc1=1;; // dbr1\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov dbr[loc1]=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // dbr0\r
+ mov dbr[r0]=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // iha\r
+ mov cr.iha=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // iim\r
+ mov cr.iim=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ifs\r
+ mov cr.ifs=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // iipa\r
+ mov cr.iipa=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // itir\r
+ mov cr.itir=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ifa\r
+ mov cr.ifa=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // iip\r
+ mov cr.iip=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // isr\r
+ mov cr.isr=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ipsr\r
+ mov cr.ipsr=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // pta\r
+ mov cr.pta=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // iva\r
+ mov cr.iva=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // itm\r
+ mov cr.itm=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // dcr\r
+ mov cr.dcr=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ec\r
+ mov ar.ec=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // lc\r
+ mov ar.lc=loc0;;\r
+ ld8.fill in5=[in0],-8;; // ar.pfs\r
+ ld8.fill loc0=[in0],-8;; // ar.fpsr\r
+ mov ar.fpsr=loc0;;\r
+ ld8.fill loc2=[in0],-8;; // ar.unat - restored later...\r
+ ld8.fill loc0=[in0],-8;; // ar.ccv\r
+ mov ar.ccv=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.fdr\r
+ mov ar.fdr=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.fir\r
+ mov ar.fir=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.fsr\r
+ mov ar.fsr=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.cflg\r
+ mov ar.cflg=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.ssd\r
+ mov ar.ssd=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.csd\r
+ mov ar.csd=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.eflag\r
+ mov ar.eflag=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // ar.fcr\r
+ mov ar.fcr=loc0;;\r
+ ld8.fill in4=[in0],-8;; // ar.rnat\r
+ ld8.fill in3=[in0],-8;; // bspstore\r
+ ld8.fill in2=[in0],-8;; // bsp\r
+ ld8.fill loc0=[in0],-8;; // ar.rsc\r
+ mov ar.rsc=loc0;;\r
+ ld8.fill loc0=[in0],-8;; // B7 - B0\r
+ mov b7=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b6=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b5=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b4=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b3=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b2=loc0;;\r
+ ld8.fill loc0=[in0],-8;;\r
+ mov b1=loc0;;\r
+ ld8.fill in1=[in0],-8;; // b0 is temporarily stored in in1\r
+ ld8.fill loc0=[in0],-16;; // predicates\r
+ mov pr=loc0;;\r
+ ldf.fill f31=[in0],-16;;\r
+ ldf.fill f30=[in0],-16;;\r
+ ldf.fill f29=[in0],-16;;\r
+ ldf.fill f28=[in0],-16;;\r
+ ldf.fill f27=[in0],-16;;\r
+ ldf.fill f26=[in0],-16;;\r
+ ldf.fill f25=[in0],-16;;\r
+ ldf.fill f24=[in0],-16;;\r
+ ldf.fill f23=[in0],-16;;\r
+ ldf.fill f22=[in0],-16;;\r
+ ldf.fill f21=[in0],-16;;\r
+ ldf.fill f20=[in0],-16;;\r
+ ldf.fill f19=[in0],-16;;\r
+ ldf.fill f18=[in0],-16;;\r
+ ldf.fill f17=[in0],-16;;\r
+ ldf.fill f16=[in0],-16;;\r
+ ldf.fill f15=[in0],-16;;\r
+ ldf.fill f14=[in0],-16;;\r
+ ldf.fill f13=[in0],-16;;\r
+ ldf.fill f12=[in0],-16;;\r
+ ldf.fill f11=[in0],-16;;\r
+ ldf.fill f10=[in0],-16;;\r
+ ldf.fill f9=[in0],-16;;\r
+ ldf.fill f8=[in0],-16;;\r
+ ldf.fill f7=[in0],-16;;\r
+ ldf.fill f6=[in0],-16;;\r
+ ldf.fill f5=[in0],-16;;\r
+ ldf.fill f4=[in0],-16;;\r
+ ldf.fill f3=[in0],-16;;\r
+ ldf.fill f2=[in0],-8;;\r
+ mov ar.unat=loc3;; // restore unat (int_nat) before fill of general registers\r
+ ld8.fill r31=[in0],-8;;\r
+ ld8.fill r30=[in0],-8;;\r
+ ld8.fill r29=[in0],-8;;\r
+ ld8.fill r28=[in0],-8;;\r
+ ld8.fill r27=[in0],-8;;\r
+ ld8.fill r26=[in0],-8;;\r
+ ld8.fill r25=[in0],-8;;\r
+ ld8.fill r24=[in0],-8;;\r
+ ld8.fill r23=[in0],-8;;\r
+ ld8.fill r22=[in0],-8;;\r
+ ld8.fill r21=[in0],-8;;\r
+ ld8.fill r20=[in0],-8;;\r
+ ld8.fill r19=[in0],-8;;\r
+ ld8.fill r18=[in0],-8;;\r
+ ld8.fill r17=[in0],-8;;\r
+ ld8.fill r16=[in0],-8;;\r
+ ld8.fill r15=[in0],-8;;\r
+ ld8.fill r14=[in0],-8;;\r
+ ld8.fill r13=[in0],-8;;\r
+ ld8.fill r12=[in0],-8;;\r
+ ld8.fill r11=[in0],-8;;\r
+ ld8.fill r10=[in0],-8;;\r
+ ld8.fill r9=[in0],-8;;\r
+ ld8.fill r8=[in0],-8;;\r
+ ld8.fill r7=[in0],-8;;\r
+ ld8.fill r6=[in0],-8;;\r
+ ld8.fill r5=[in0],-8;;\r
+ ld8.fill r4=[in0],-8;;\r
+ ld8.fill r3=[in0],-8;;\r
+ ld8.fill r2=[in0],-8;;\r
+ ld8.fill r1=[in0],-8;;\r
+ mov ar.unat=loc2;; // restore application context unat\r
+\r
+ br.ret.sptk.many b0\r
+\r
+ .endp FillContext\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// HookHandler\r
+//\r
+// Description:\r
+// Common branch target from hooked IVT entries. Runs in interrupt context.\r
+// Responsible for saving and restoring context and calling common C\r
+// handler. Banked registers running on bank 0 at entry.\r
+//\r
+// Arguments:\r
+// All arguments are passed in banked registers:\r
+// B0_REG = Original B0\r
+// SCRATCH_REG1 = IVT entry index\r
+//\r
+// Returns:\r
+// Returns via rfi\r
+//\r
+// Notes:\r
+// loc0 - scratch\r
+// loc1 - scratch\r
+// loc2 - vector number / mask\r
+// loc3 - 16 byte aligned context record address\r
+// loc4 - temporary storage of last address in context record\r
+\r
+HookHandler:\r
+ flushrs;; // Synch RSE with backing store\r
+ mov SCRATCH_REG2=ar.bsp // save interrupted context bsp\r
+ mov SCRATCH_REG3=ar.bspstore // save interrupted context bspstore\r
+ mov SCRATCH_REG4=ar.rnat // save interrupted context rnat\r
+ mov SCRATCH_REG6=cr.ifs;; // save IFS in case we need to chain...\r
+ cover;; // creates new frame, moves old\r
+ // CFM to IFS.\r
+ alloc SCRATCH_REG5=0,5,6,0 // alloc 5 locals, 6 outs\r
+ ;;\r
+ // save banked registers to locals\r
+ mov out1=B0_REG // out1 = Original B0\r
+ mov out2=SCRATCH_REG2 // out2 = original ar.bsp\r
+ mov out3=SCRATCH_REG3 // out3 = original ar.bspstore\r
+ mov out4=SCRATCH_REG4 // out4 = original ar.rnat\r
+ mov out5=SCRATCH_REG5 // out5 = original ar.pfs\r
+ mov loc2=SCRATCH_REG1;; // loc2 = vector number + chain flag\r
+ bsw.1;; // switch banked registers to bank 1\r
+ srlz.d // explicit serialize required\r
+ // now fill in context record structure\r
+ movl loc3=IpfContextBuf // Insure context record is aligned\r
+ add loc0=-0x200,r0;; // mask the lower 9 bits (align on 512 byte boundary)\r
+ and loc3=loc3,loc0;;\r
+ add loc3=0x200,loc3;; // move to next 512 byte boundary\r
+ // loc3 now contains the 512 byte aligned context record\r
+ // spill register context into context record\r
+ mov out0=loc3;; // Context record base in out0\r
+ // original B0 in out1 already\r
+ // original ar.bsp in out2 already\r
+ // original ar.bspstore in out3 already\r
+ br.call.sptk.few b0=SpillContext;; // spill context\r
+ mov loc4=out0 // save modified address\r
+\r
+ // At this point, the context has been saved to the context record and we're\r
+ // ready to call the C part of the handler...\r
+\r
+ movl loc0=CommonHandler;; // obtain address of plabel\r
+ ld8 loc1=[loc0];; // get entry point of CommonHandler\r
+ mov b6=loc1;; // put it in a branch register\r
+ adds loc1= 8, loc0;; // index to GP in plabel\r
+ ld8 r1=[loc1];; // set up gp for C call\r
+ mov loc1=0xfffff;; // mask off so only vector bits are present\r
+ and out0=loc2,loc1;; // pass vector number (exception type)\r
+ mov out1=loc3;; // pass context record address\r
+ br.call.sptk.few b0=b6;; // call C handler\r
+\r
+ // We've returned from the C call, so restore the context and either rfi\r
+ // back to interrupted thread, or chain into the SAL if this was an external interrupt\r
+ mov out0=loc4;; // pass address of last element in context record\r
+ br.call.sptk.few b0=FillContext;; // Fill context\r
+ mov b0=out1 // fill in b0\r
+ mov ar.rnat=out4\r
+ mov ar.pfs=out5\r
+\r
+ // Loadrs is necessary because the debugger may have changed some values in\r
+ // the backing store. The processor, however may not be aware that the\r
+ // stacked registers need to be reloaded from the backing store. Therefore,\r
+ // we explicitly cause the RSE to refresh the stacked register's contents\r
+ // from the backing store. \r
+ mov loc0=ar.rsc // get RSC value\r
+ mov loc1=ar.rsc // save it so we can restore it\r
+ movl loc3=0xffffffffc000ffff;; // create mask for clearing RSC.loadrs\r
+ and loc0=loc0,loc3;; // create value for RSC with RSC.loadrs==0\r
+ mov ar.rsc=loc0;; // modify RSC\r
+ loadrs;; // invalidate register stack\r
+ mov ar.rsc=loc1;; // restore original RSC\r
+\r
+ bsw.0;; // switch banked registers back to bank 0\r
+ srlz.d;; // explicit serialize required\r
+ mov PR_REG=pr // save predicates - to be restored after chaining decision\r
+ mov B0_REG=b0 // save b0 - required by chain code\r
+ mov loc2=EXCPT_EXTERNAL_INTERRUPT;;\r
+ cmp.eq p7,p0=SCRATCH_REG1,loc2;; // check to see if this is the timer tick\r
+ (p7) br.cond.dpnt.few DO_CHAIN;;\r
+\r
+NO_CHAIN:\r
+ mov pr=PR_REG;;\r
+ rfi;; // we're outa here.\r
+\r
+DO_CHAIN:\r
+ mov pr=PR_REG\r
+ mov SCRATCH_REG1=cr.iva\r
+ mov SCRATCH_REG2=PATCH_RETURN_OFFSET;;\r
+ add SCRATCH_REG1=SCRATCH_REG1, SCRATCH_REG2;;\r
+ mov b0=SCRATCH_REG1;;\r
+ br.cond.sptk.few b0;;\r
+\r
+EndHookHandler:\r
+\r
+\r
+/////////////////////////////////////////////\r
+//\r
+// Name:\r
+// HookStub\r
+//\r
+// Description:\r
+// HookStub will be copied from it's loaded location into the IVT when\r
+// an IVT entry is hooked. The IVT entry does an indirect jump via B0 to\r
+// HookHandler, which in turn calls into the default C handler, which calls\r
+// the user-installed C handler. The calls return and HookHandler executes\r
+// an rfi.\r
+//\r
+// Notes:\r
+// Saves B0 to B0_REG\r
+// Saves IVT index to SCRATCH_REG1 (immediate value is fixed up when code is copied\r
+// to the IVT entry.\r
+\r
+ .globl HookStub\r
+ .proc HookStub\r
+HookStub:\r
+\r
+ mov B0_REG=b0\r
+ movl SCRATCH_REG1=HookHandler;;\r
+ mov b0=SCRATCH_REG1;;\r
+ mov SCRATCH_REG1=0;;// immediate value is fixed up during install of handler to be the vector number\r
+ br.cond.sptk.few b0\r
+\r
+ .endp HookStub\r
+\r
+\r
+/////////////////////////////////////////////\r
+// The following code is moved into IVT entry 14 (offset 3400) which is reserved\r
+// in the Itanium architecture. The patch code is located at the end of the\r
+// IVT entry.\r
+\r
+PatchCode:\r
+ mov SCRATCH_REG0=psr\r
+ mov SCRATCH_REG6=cr.ipsr\r
+ mov PR_REG=pr\r
+ mov B0_REG=b0;;\r
+\r
+ // turn off any virtual translations\r
+ movl SCRATCH_REG1 = ~( MASK(PSR_DT,1) | MASK(PSR_RT,1));;\r
+ and SCRATCH_REG1 = SCRATCH_REG0, SCRATCH_REG1;;\r
+ mov psr.l = SCRATCH_REG1;;\r
+ srlz.d \r
+ tbit.z p14, p15 = SCRATCH_REG6, PSR_IS;; // Check to see if we were\r
+ // interrupted from IA32\r
+ // context. If so, bail out\r
+ // and chain to SAL immediately\r
+ (p15) br.cond.sptk.few Stub_IVT_Passthru;;\r
+ // we only want to take 1 out of 32 external interrupts to minimize the\r
+ // impact to system performance. Check our interrupt count and bail\r
+ // out if we're not up to 32\r
+ movl SCRATCH_REG1=ExternalInterruptCount;;\r
+ ld8 SCRATCH_REG2=[SCRATCH_REG1];; // ExternalInterruptCount\r
+ tbit.z p14, p15 = SCRATCH_REG2, 5;; // bit 5 set?\r
+ (p14) add SCRATCH_REG2=1, SCRATCH_REG2;; // No? Then increment\r
+ // ExternalInterruptCount\r
+ // and Chain to SAL\r
+ // immediately\r
+ (p14) st8 [SCRATCH_REG1]=SCRATCH_REG2;;\r
+ (p14) br.cond.sptk.few Stub_IVT_Passthru;;\r
+ (p15) mov SCRATCH_REG2=0;; // Yes? Then reset\r
+ // ExternalInterruptCount\r
+ // and branch to\r
+ // HookHandler\r
+ (p15) st8 [SCRATCH_REG1]=SCRATCH_REG2;;\r
+ mov pr=PR_REG\r
+ movl SCRATCH_REG1=HookHandler;; // SCRATCH_REG1 = entrypoint of HookHandler\r
+ mov b0=SCRATCH_REG1;; // b0 = entrypoint of HookHandler\r
+ mov SCRATCH_REG1=EXCPT_EXTERNAL_INTERRUPT;;\r
+ br.sptk.few b0;; // branch to HookHandler\r
+\r
+PatchCodeRet:\r
+ // fake-up an rfi to get RSE back to being coherent and insure psr has\r
+ // original contents when interrupt occured, then exit to SAL\r
+ // at this point:\r
+ // cr.ifs has been modified by previous "cover"\r
+ // SCRATCH_REG6 has original cr.ifs\r
+\r
+ mov SCRATCH_REG5=cr.ipsr\r
+ mov SCRATCH_REG4=cr.iip;;\r
+ mov cr.ipsr=SCRATCH_REG0\r
+ mov SCRATCH_REG1=ip;;\r
+ add SCRATCH_REG1=0x30, SCRATCH_REG1;;\r
+ mov cr.iip=SCRATCH_REG1;;\r
+ rfi;; // rfi to next instruction\r
+\r
+Stub_RfiTarget:\r
+ mov cr.ifs=SCRATCH_REG6\r
+ mov cr.ipsr=SCRATCH_REG5\r
+ mov cr.iip=SCRATCH_REG4;;\r
+\r
+Stub_IVT_Passthru:\r
+ mov pr=PR_REG // pr = saved predicate registers\r
+ mov b0=B0_REG;; // b0 = saved b0\r
+EndPatchCode:\r
+\r
+\r
+/////////////////////////////////////////////\r
+// The following bundle is moved into IVT entry 14 (offset 0x3400) which is reserved\r
+// in the Itanium architecture. This bundle will be the last bundle and will\r
+// be located at offset 0x37F0 in the IVT.\r
+\r
+FailsafeBranch:\r
+{\r
+ .mib\r
+ nop.m 0\r
+ nop.i 0\r
+ br.sptk.few -(FAILSAFE_BRANCH_OFFSET - EXT_INT_ENTRY_OFFSET - 0x10)\r
+}\r
+\r
+\r
+/////////////////////////////////////////////\r
+// The following bundle is moved into IVT entry 13 (offset 0x3000) which is the\r
+// external interrupt. It branches to the patch code.\r
+\r
+PatchCodeNewBun0:\r
+{\r
+ .mib\r
+ nop.m 0\r
+ nop.i 0\r
+ br.cond.sptk.few PATCH_BRANCH\r
+}\r
--- /dev/null
+//++\r
+// Copyright (c) 2006, Intel Corporation \r
+// All rights reserved. This program and the accompanying materials \r
+// are licensed and made available under the terms and conditions of the BSD License \r
+// which accompanies this distribution. The full text of the license may be found at \r
+// http://opensource.org/licenses/bsd-license.php \r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+// \r
+// Module Name:\r
+//\r
+// Ds64Macros.i\r
+//\r
+// Abstract:\r
+//\r
+// This is set of macros used in calculating offsets in the IVT\r
+//\r
+// Revision History:\r
+//\r
+//--\r
+\r
+#define EXCPT_EXTERNAL_INTERRUPT 12\r
+#define MASK_0_4 0x000000000000001F // mask bits 0 through 4\r
+#define SLOT0 0\r
+#define SLOT1 1\r
+#define SLOT2 2\r
+\r
+#define PSR_DT 17\r
+#define PSR_TB 26\r
+#define PSR_RT 27\r
+#define PSR_IS 34\r
+#define PSR_IT 36\r
+#define PSR_IC 13\r
+#define PSR_I 14\r
+#define PSR_SS 40\r
+#define PSR_BN 44\r
+#define PSR_RI_MASK 0x60000000000\r
+\r
+#define EXCPT_EXTERNAL_INTERRUPT 12\r
+\r
+#define SCRATCH_REG0 r23\r
+#define SCRATCH_REG1 r24\r
+#define SCRATCH_REG2 r25\r
+#define SCRATCH_REG3 r26\r
+#define SCRATCH_REG4 r27\r
+#define SCRATCH_REG5 r28\r
+#define SCRATCH_REG6 r29\r
+#define PR_REG r30\r
+#define B0_REG r31\r
+\r
+\r
+// EXT_INT_OFFSET is the offset of the external interrupt entry in the IVT\r
+#define EXT_INT_ENTRY_OFFSET 0x03000\r
+\r
+// PATCH_ENTRY_OFFSET is the offset into the IVT of the entry that is coopted (stolen)\r
+// for use by the handler. The entire entry is restored when the handler is\r
+// unloaded.\r
+#define PATCH_ENTRY_OFFSET 0x03400\r
+\r
+// PATCH_BUNDLES is the number of bundles actually in the patch\r
+#define NUM_PATCH_BUNDLES ((EndPatchCode - PatchCode) / 0x10)\r
+\r
+// A hard coded branch back into the external interrupt IVT entry's second bundle\r
+// is put here, just in case the original bundle zero did not have a branch\r
+// This is the last bundle in the reserved IVT entry\r
+#define FAILSAFE_BRANCH_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - 0x10)\r
+\r
+// the original external interrupt IVT entry bundle zero is copied and relocated\r
+// here... also in the reserved IVT entry\r
+// This is the second-to-last bundle in the reserved IVT entry\r
+#define RELOCATED_EXT_INT (PATCH_ENTRY_OFFSET + 0x400 - 0x20)\r
+\r
+// The patch is actually stored at the end of IVT:PATCH_ENTRY. The PATCH_OFFSET\r
+// is the offset into IVT where the patch is actually stored. It is carefully\r
+// located so that when we run out of patch code, the next bundle is the\r
+// relocated bundle 0 from the original external interrupt handler\r
+#define PATCH_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - ( EndPatchCode - PatchCode ) - 0x20)\r
+\r
+#define PATCH_RETURN_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - ( EndPatchCode - PatchCodeRet ) - 0x20)\r
+\r
+// PATCH_BRANCH is used only in the new bundle that is placed at the beginning\r
+// of the external interrupt IVT entry.\r
+#define PATCH_BRANCH (PATCH_OFFSET - EXT_INT_ENTRY_OFFSET)\r
+\r
--- /dev/null
+//++\r
+// Copyright (c) 2006, Intel Corporation \r
+// All rights reserved. This program and the accompanying materials \r
+// are licensed and made available under the terms and conditions of the BSD License \r
+// which accompanies this distribution. The full text of the license may be found at \r
+// http://opensource.org/licenses/bsd-license.php \r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+// \r
+// Module Name:\r
+//\r
+// Common.i\r
+//\r
+// Abstract:\r
+//\r
+// This is set of useful macros\r
+//\r
+// Revision History:\r
+//\r
+//--\r
+\r
+#define NESTED_SETUP(i,l,o,r) \\r
+ alloc loc1=ar##.##pfs,i,l,o,r ; \\r
+ mov loc0=b0 ;;\r
+\r
+\r
+#define NESTED_RETURN \\r
+ mov b0=loc0 ; \\r
+ mov ar##.##pfs=loc1 ;; \\r
+ br##.##ret##.##dpnt b0 ;;\r
+\r
+#define MASK(bp,value) (value << bp)\r
+\r
--- /dev/null
+/**@file\r
+ IPF specific debug support functions\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+//\r
+// private header files\r
+//\r
+#include "plDebugSupport.h"\r
+\r
+typedef struct {\r
+ UINT64 low;\r
+ UINT64 high;\r
+} BUNDLE;\r
+\r
+//\r
+// number of bundles to swap in ivt\r
+//\r
+#define NUM_BUNDLES_IN_STUB 5\r
+#define NUM_IVT_ENTRIES 64\r
+\r
+typedef struct {\r
+ BUNDLE OrigBundles[NUM_BUNDLES_IN_STUB];\r
+ VOID (*RegisteredCallback) ();\r
+} IVT_ENTRY;\r
+\r
+STATIC\r
+EFI_STATUS\r
+ManageIvtEntryTable (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN BUNDLE NewBundles[4],\r
+ IN VOID (*NewCallback) ()\r
+ );\r
+\r
+STATIC\r
+VOID\r
+HookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN BUNDLE NewBundles[4],\r
+ IN VOID (*NewCallback) ()\r
+ );\r
+\r
+STATIC\r
+VOID\r
+UnhookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ );\r
+\r
+STATIC\r
+VOID\r
+ChainExternalInterrupt (\r
+ IN VOID (*NewCallback) ()\r
+ );\r
+\r
+STATIC\r
+VOID\r
+UnchainExternalInterrupt (\r
+ VOID\r
+ );\r
+\r
+STATIC\r
+VOID\r
+GetHandlerEntryPoint (\r
+ UINTN HandlerIndex,\r
+ VOID **EntryPoint\r
+ );\r
+\r
+IVT_ENTRY IvtEntryTable[NUM_IVT_ENTRIES];\r
+\r
+//\r
+// IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists\r
+// within the buffer and still have a large enough buffer to hold a whole IPF context record.\r
+//\r
+UINT8 IpfContextBuf[sizeof (EFI_SYSTEM_CONTEXT_IPF) + 512];\r
+\r
+//\r
+// The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched\r
+// with the common handler.\r
+//\r
+UINT8 PatchSaveBuffer[0x400];\r
+UINTN ExternalInterruptCount;\r
+\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ IPF specific DebugSupport driver initialization. Must be public because it's\r
+ referenced from DebugSupport.c\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ SetMem (IvtEntryTable, sizeof (IvtEntryTable), 0);\r
+ ExternalInterruptCount = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Unload handler that is called during UnloadImage() - deallocates pool memory\r
+ used by the driver. Must be public because it's referenced from DebugSuport.c\r
+\r
+Arguments:\r
+ ImageHandle - Image handle\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+{\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IVT_ENTRIES; ExceptionType++) {\r
+ ManageIvtEntryTable (ExceptionType, NULL, NULL);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CommonHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN EFI_SYSTEM_CONTEXT Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ C routine that is called for all registered exceptions. This is the main\r
+ exception dispatcher. Must be public because it's referenced from AsmFuncs.s.\r
+\r
+Arguments:\r
+ ExceptionType - Exception Type\r
+ Context - System Context\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ static BOOLEAN InHandler = FALSE;\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ if (InHandler) {\r
+ DEBUG ((EFI_D_INFO, "ERROR: Re-entered debugger!\n"\r
+ " ExceptionType == %X\n"\r
+ " Context == %X\n"\r
+ " Context.SystemContextIpf->CrIip == %X\n"\r
+ " Context.SystemContextIpf->CrIpsr == %X\n"\r
+ " InHandler == %X\n",\r
+ ExceptionType, \r
+ Context, \r
+ Context.SystemContextIpf->CrIip,\r
+ Context.SystemContextIpf->CrIpsr,\r
+ InHandler));\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ ASSERT (!InHandler);\r
+ InHandler = TRUE;\r
+ if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
+ if (ExceptionType != EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
+ IvtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, Context.SystemContextIpf);\r
+ } else {\r
+ IvtEntryTable[ExceptionType].RegisteredCallback (Context.SystemContextIpf);\r
+ }\r
+ } else {\r
+ ASSERT (0);\r
+ }\r
+\r
+ InHandler = FALSE;\r
+}\r
+\r
+STATIC\r
+VOID\r
+GetHandlerEntryPoint (\r
+ UINTN HandlerIndex,\r
+ VOID **EntryPoint\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Given an integer number, return the physical address of the entry point in the IFT\r
+ \r
+Arguments:\r
+ HandlerIndex - Index of the Handler \r
+ EntryPoint - IFT Entrypoint\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ UINT8 *TempPtr;\r
+\r
+ //\r
+ // get base address of IVT\r
+ //\r
+ TempPtr = GetIva ();\r
+\r
+ if (HandlerIndex < 20) {\r
+ //\r
+ // first 20 provide 64 bundles per vector\r
+ //\r
+ TempPtr += 0x400 * HandlerIndex;\r
+ } else {\r
+ //\r
+ // the rest provide 16 bundles per vector\r
+ //\r
+ TempPtr += 0x5000 + 0x100 * (HandlerIndex - 20);\r
+ }\r
+\r
+ *EntryPoint = (VOID *) TempPtr;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+ManageIvtEntryTable (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB],\r
+ IN VOID (*NewCallback) ()\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the worker function that installs and removes all handlers\r
+ \r
+Arguments:\r
+ ExceptionType - Exception Type\r
+ NewBundles - New Boundles\r
+ NewCallback - New Callback\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not\r
+ satisfied.\r
+ EFI_ALEADY_STARTED - Ivt already hooked.\r
+ \r
+--*/\r
+{\r
+ BUNDLE *B0Ptr;\r
+ UINT64 InterruptFlags;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Get address of bundle 0\r
+ //\r
+ GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
+\r
+ if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
+ //\r
+ // we've already installed to this vector\r
+ //\r
+ if (NewCallback != NULL) {\r
+ //\r
+ // if the input handler is non-null, error\r
+ //\r
+ return EFI_ALREADY_STARTED;\r
+ } else {\r
+ //\r
+ // else remove the previously installed handler\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+ InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS);\r
+ if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
+ UnchainExternalInterrupt ();\r
+ } else {\r
+ UnhookEntry (ExceptionType);\r
+ }\r
+\r
+ ProgramInterruptFlags (InterruptFlags);\r
+ gBS->RestoreTPL (OldTpl);\r
+ //\r
+ // re-init IvtEntryTable\r
+ //\r
+ SetMem (&IvtEntryTable[ExceptionType], sizeof (IVT_ENTRY), 0);\r
+ }\r
+ } else {\r
+ //\r
+ // no user handler installed on this vector\r
+ //\r
+ if (NewCallback != NULL) {\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+ InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS);\r
+ if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
+ ChainExternalInterrupt (NewCallback);\r
+ } else {\r
+ HookEntry (ExceptionType, NewBundles, NewCallback);\r
+ }\r
+\r
+ ProgramInterruptFlags (InterruptFlags);\r
+ gBS->RestoreTPL (OldTpl);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+HookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN BUNDLE NewBundles[4],\r
+ IN VOID (*NewCallback) ()\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Saves original IVT contents and inserts a few new bundles which are fixed up\r
+ to store the ExceptionType and then call the common handler.\r
+ \r
+Arguments:\r
+ ExceptionType - Exception Type\r
+ NewBundles - New Boundles\r
+ NewCallback - New Callback\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ BUNDLE *FixupBundle;\r
+ BUNDLE *B0Ptr;\r
+\r
+ //\r
+ // Get address of bundle 0\r
+ //\r
+ GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
+\r
+ //\r
+ // copy original bundles from IVT to IvtEntryTable so we can restore them later\r
+ //\r
+ CopyMem (\r
+ IvtEntryTable[ExceptionType].OrigBundles,\r
+ B0Ptr,\r
+ sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB\r
+ );\r
+ //\r
+ // insert new B0\r
+ //\r
+ CopyMem (B0Ptr, NewBundles, sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB);\r
+\r
+ //\r
+ // fixup IVT entry so it stores its index and whether or not to chain...\r
+ //\r
+ FixupBundle = B0Ptr + 2;\r
+ FixupBundle->high |= ExceptionType << 36;\r
+\r
+ InstructionCacheFlush (B0Ptr, 5);\r
+ IvtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
+}\r
+\r
+STATIC\r
+VOID\r
+UnhookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Restores original IVT contents when unregistering a callback function\r
+ \r
+Arguments:\r
+ ExceptionType - Exception Type\r
+ NewBundles - New Boundles\r
+ NewCallback - New Callback\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ BUNDLE *B0Ptr;\r
+\r
+ //\r
+ // Get address of bundle 0\r
+ //\r
+ GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
+ //\r
+ // restore original bundles in IVT\r
+ //\r
+ CopyMem (\r
+ B0Ptr,\r
+ IvtEntryTable[ExceptionType].OrigBundles,\r
+ sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB\r
+ );\r
+ InstructionCacheFlush (B0Ptr, 5);\r
+}\r
+\r
+STATIC\r
+VOID\r
+ChainExternalInterrupt (\r
+ IN VOID (*NewCallback) ()\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Sets up cache flush and calls assembly function to chain external interrupt.\r
+ Records new callback in IvtEntryTable.\r
+ \r
+Arguments:\r
+ NewCallback - New Callback\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ VOID *Start;\r
+\r
+ Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400);\r
+ IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NewCallback;\r
+ ChainHandler ();\r
+ InstructionCacheFlush (Start, 0x400);\r
+}\r
+\r
+STATIC\r
+VOID\r
+UnchainExternalInterrupt (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Sets up cache flush and calls assembly function to restore external interrupt.\r
+ Removes registered callback from IvtEntryTable.\r
+ \r
+Arguments:\r
+ Nothing\r
+ \r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+{\r
+ VOID *Start;\r
+\r
+ Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400);\r
+ UnchainHandler ();\r
+ InstructionCacheFlush (Start, 0x400);\r
+ IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NULL;\r
+}\r
+\r
+//\r
+// The rest of the functions in this file are all member functions for the\r
+// DebugSupport protocol\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function. Hard\r
+ coded to support only 1 processor for now.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+{\r
+ *MaxProcessorIndex = 0;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK NewPeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+{\r
+ return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT, NULL, NewPeriodicCallback);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+{\r
+ return ManageIvtEntryTable (\r
+ ExceptionType,\r
+ (BUNDLE *) ((EFI_PLABEL *) HookStub)->EntryPoint,\r
+ NewCallback\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINTN Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function. Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ InstructionCacheFlush (Start, Length);\r
+ return (EFI_SUCCESS);\r
+}\r
--- /dev/null
+/**@file\r
+ IPF specific debugsupport types, macros, and definitions.\r
+ \r
+Copyright (c) 2004 - 2006 Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+#ifndef _PLDEBUG_SUPPORT_H\r
+#define _PLDEBUG_SUPPORT_H\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/DebugSupport.h>\r
+#include <Protocol/LoadedImage.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#define DISABLE_INTERRUPTS 0UL\r
+\r
+//\r
+// The remaining definitions comprise the protocol members.\r
+//\r
+#define EFI_ISA IsaIpf\r
+\r
+//\r
+// processor specific functions that must be public\r
+//\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ IPF specific DebugSupport driver initialization. Must be public because it's\r
+ referenced from DebugSupport.c\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Unload handler that is called during UnloadImage() - deallocates pool memory\r
+ used by the driver. Must be public because it's referenced from DebugSuport.c\r
+\r
+Arguments:\r
+ ImageHandle - Image handle\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// Assembly worker functions and data referenced from plDebugSupport.c\r
+//\r
+VOID *\r
+GetIva (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ C callable function to obtain the current value of IVA\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ Current value if IVA\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+HookStub (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ HookStub will be copied from it's loaded location into the IVT when\r
+ an IVT entry is hooked.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+ChainHandler (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Chains an interrupt handler\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+UnchainHandler (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Unchains an interrupt handler\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+UINT64\r
+ProgramInterruptFlags (\r
+ IN UINT64 NewInterruptState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ C callable function to enable/disable interrupts\r
+\r
+Arguments:\r
+\r
+ NewInterruptState - New Interrupt State\r
+\r
+Returns:\r
+\r
+ Previous state of psr.ic\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+InstructionCacheFlush (\r
+ IN VOID *StartAddress,\r
+ IN UINTN SizeInBytes\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Flushes instruction cache for specified number of bytes\r
+\r
+Arguments:\r
+\r
+ StartAddress - Cache Start Address\r
+ SizeInBytes - Cache Size\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function. Hard\r
+ coded to support only 1 processor for now.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewHandler,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINTN Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ DebugSupport protocol member function. Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+CommonHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN EFI_SYSTEM_CONTEXT Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ C routine that is called for all registered exceptions. This is the main\r
+ exception dispatcher. Must be public because it's referenced from AsmFuncs.s.\r
+\r
+Arguments:\r
+ ExceptionType - Exception Type\r
+ Context - System Context\r
+\r
+Returns:\r
+\r
+ Nothing\r
+ \r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#******************************************************************************\r
+#*\r
+#* Copyright (c) 2007, Intel Corporation \r
+#* All rights reserved. This program and the accompanying materials \r
+#* are licensed and made available under the terms and conditions of the BSD License \r
+#* which accompanies this distribution. The full text of the license may be found at \r
+#* http://opensource.org/licenses/bsd-license.php \r
+#* \r
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+#*\r
+#******************************************************************************\r
+\r
+.globl _OrigVector\r
+.globl _InterruptEntryStub\r
+.globl _StubSize\r
+.globl _CommonIdtEntry\r
+.globl _FxStorSupport\r
+\r
+_AppEsp: .long 0x11111111 # ?\r
+_DebugEsp: .long 0x22222222 # ?\r
+_ExtraPush: .long 0x33333333 # ?\r
+_ExceptData: .long 0x44444444 # ?\r
+_Eflags: .long 0x55555555 # ?\r
+_OrigVector: .long 0x66666666 # ?\r
+_StubSize: .long _InterruptEntryStubEnd - _InterruptEntryStub\r
+\r
+.globl _FxStorSupport\r
+_FxStorSupport:\r
+ ret \r
+\r
+.globl _GetIdtr\r
+_GetIdtr:\r
+ ret \r
+\r
+.globl _WriteInterruptFlag\r
+_WriteInterruptFlag:\r
+ ret \r
+\r
+.globl _Vect2Desc\r
+_Vect2Desc:\r
+ ret \r
+\r
+.globl _InterruptEntryStub\r
+_InterruptEntryStub:\r
+ ret \r
+\r
+.globl _InterruptEntryStubEnd\r
+_InterruptEntryStubEnd:\r
+ ret \r
+\r
+.globl _CommonIdtEntry\r
+_CommonIdtEntry:\r
+ ret \r
+\r
+PhonyIretd:\r
+ iret \r
--- /dev/null
+;******************************************************************************\r
+;*\r
+;* Copyright (c) 2006, Intel Corporation \r
+;* All rights reserved. This program and the accompanying materials \r
+;* are licensed and made available under the terms and conditions of the BSD License \r
+;* which accompanies this distribution. The full text of the license may be found at \r
+;* http://opensource.org/licenses/bsd-license.php \r
+;* \r
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+;*\r
+;******************************************************************************\r
+\r
+EXCPT64_DIVIDE_ERROR EQU 0\r
+EXCPT64_DEBUG EQU 1\r
+EXCPT64_NMI EQU 2\r
+EXCPT64_BREAKPOINT EQU 3\r
+EXCPT64_OVERFLOW EQU 4\r
+EXCPT64_BOUND EQU 5\r
+EXCPT64_INVALID_OPCODE EQU 6\r
+EXCPT64_DOUBLE_FAULT EQU 8\r
+EXCPT64_INVALID_TSS EQU 10\r
+EXCPT64_SEG_NOT_PRESENT EQU 11\r
+EXCPT64_STACK_FAULT EQU 12\r
+EXCPT64_GP_FAULT EQU 13\r
+EXCPT64_PAGE_FAULT EQU 14\r
+EXCPT64_FP_ERROR EQU 16\r
+EXCPT64_ALIGNMENT_CHECK EQU 17\r
+EXCPT64_MACHINE_CHECK EQU 18\r
+EXCPT64_SIMD EQU 19\r
+\r
+FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags\r
+\r
+;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,\r
+;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver\r
+;; MUST check the CPUID feature flags to see that these instructions are available\r
+;; and fail to init if they are not.\r
+\r
+;; fxstor [rdi]\r
+FXSTOR_RDI MACRO\r
+ db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [rdi]\r
+ENDM\r
+\r
+;; fxrstor [rsi]\r
+FXRSTOR_RSI MACRO\r
+ db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [rsi]\r
+ENDM\r
+\r
+data SEGMENT\r
+\r
+public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport\r
+\r
+StubSize dd InterruptEntryStubEnd - InterruptEntryStub\r
+AppRsp dq 1111111111111111h ; ?\r
+DebugRsp dq 2222222222222222h ; ?\r
+ExtraPush dq 3333333333333333h ; ?\r
+ExceptData dq 4444444444444444h ; ?\r
+Rflags dq 5555555555555555h ; ?\r
+OrigVector dq 6666666666666666h ; ?\r
+\r
+;; The declarations below define the memory region that will be used for the debug stack.\r
+;; The context record will be built by pushing register values onto this stack.\r
+;; It is imparitive that alignment be carefully managed, since the FXSTOR and\r
+;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r
+;;\r
+;; The stub will switch stacks from the application stack to the debuger stack\r
+;; and pushes the exception number.\r
+;;\r
+;; Then we building the context record on the stack. Since the stack grows down,\r
+;; we push the fields of the context record from the back to the front. There\r
+;; are 336 bytes of stack used prior allocating the 512 bytes of stack to be\r
+;; used as the memory buffer for the fxstor instruction. Therefore address of\r
+;; the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which\r
+;; must be 16 byte aligned.\r
+;;\r
+;; We carefully locate the stack to make this happen.\r
+;;\r
+;; For reference, the context structure looks like this:\r
+;; struct {\r
+;; UINT64 ExceptionData;\r
+;; FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+;; UINT64 RFlags;\r
+;; UINT64 Ldtr, Tr;\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+;; UINT64 Rip;\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r
+\r
+align 16\r
+DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment\r
+ dd 1ffch dup (000000000h) ;; 32K should be enough stack\r
+ ;; This allocation is coocked to insure \r
+ ;; that the the buffer for the FXSTORE instruction\r
+ ;; will be 16 byte aligned also.\r
+ ;;\r
+ExceptionNumber dq ? ;; first entry will be the vector number pushed by the stub\r
+\r
+DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub\r
+\r
+data ENDS\r
+\r
+text SEGMENT\r
+\r
+externdef InterruptDistrubutionHub:near\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; EfiWbinvd (\r
+; VOID\r
+; )\r
+;\r
+; Abstract: Writeback and invalidate cache\r
+;\r
+EfiWbinvd PROC PUBLIC\r
+ wbinvd\r
+ ret\r
+EfiWbinvd ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; BOOLEAN\r
+; FxStorSupport (\r
+; void\r
+; )\r
+;\r
+; Abstract: Returns TRUE if FxStor instructions are supported\r
+;\r
+FxStorSupport PROC PUBLIC\r
+\r
+;\r
+; cpuid corrupts rbx which must be preserved per the C calling convention\r
+;\r
+ push rbx\r
+ mov rax, 1\r
+ cpuid\r
+ mov eax, edx\r
+ and rax, FXSTOR_FLAG\r
+ shr rax, 24\r
+ pop rbx\r
+ ret\r
+FxStorSupport ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; DESCRIPTOR *\r
+; GetIdtr (\r
+; void\r
+; )\r
+;\r
+; Abstract: Returns physical address of IDTR\r
+;\r
+GetIdtr PROC PUBLIC\r
+ push rbp\r
+ mov rbp, rsp\r
+\r
+ sidt QWORD PTR [rbp - 0ah]\r
+ mov rax, QWORD PTR [rbp - 8h]\r
+\r
+ mov rsp, rbp\r
+ pop rbp\r
+ ret\r
+GetIdtr ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; BOOLEAN\r
+; WriteInterruptFlag (\r
+; BOOLEAN NewState // rcx\r
+; )\r
+;\r
+; Abstract: Programs interrupt flag to the requested state and returns previous\r
+; state.\r
+;\r
+WriteInterruptFlag PROC PUBLIC\r
+\r
+ pushfq\r
+ pop rax\r
+ and rax, 200h\r
+ shr rax, 9\r
+ cmp rcx, 0\r
+ jnz EnableIF\r
+ cli\r
+ ret\r
+EnableIF:\r
+ sti\r
+ ret\r
+\r
+WriteInterruptFlag ENDP\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; void\r
+; Vect2Desc (\r
+; DESCRIPTOR * DestDesc, // rcx\r
+; void (*Vector) (void) // rdx\r
+; )\r
+;\r
+; Abstract: Encodes an IDT descriptor with the given physical address\r
+;\r
+Vect2Desc PROC PUBLIC\r
+\r
+ mov rax, rdx\r
+ mov word ptr [rcx], ax ; write bits 15..0 of offset\r
+ mov dx, cs\r
+ mov word ptr [rcx+2], dx ; SYS_CODE_SEL from GDT\r
+ mov word ptr [rcx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present\r
+ shr rax, 16\r
+ mov word ptr [rcx+6], ax ; write bits 31..16 of offset\r
+ shr rax, 16\r
+ mov dword ptr [rcx+8], eax ; write bits 63..32 of offset\r
+\r
+ ret\r
+\r
+Vect2Desc ENDP\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; InterruptEntryStub\r
+;\r
+; Abstract: This code is not a function, but is a small piece of code that is\r
+; copied and fixed up once for each IDT entry that is hooked.\r
+;\r
+InterruptEntryStub::\r
+ push 0 ; push vector number - will be modified before installed\r
+ db 0e9h ; jump rel32\r
+ dd 0 ; fixed up to relative address of CommonIdtEntry\r
+InterruptEntryStubEnd:\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; CommonIdtEntry\r
+;\r
+; Abstract: This code is not a function, but is the common part for all IDT\r
+; vectors.\r
+;\r
+CommonIdtEntry::\r
+;;\r
+;; At this point, the stub has saved the current application stack esp into AppRsp\r
+;; and switched stacks to the debug stack, where it pushed the vector number\r
+;;\r
+;; The application stack looks like this:\r
+;;\r
+;; ...\r
+;; (last application stack entry)\r
+;; [16 bytes alignment, do not care it]\r
+;; SS from interrupted task\r
+;; RSP from interrupted task\r
+;; rflags from interrupted task\r
+;; CS from interrupted task\r
+;; RIP from interrupted task\r
+;; Error code <-------------------- Only present for some exeption types\r
+;;\r
+;; Vector Number <----------------- pushed in our IDT Entry\r
+;;\r
+\r
+\r
+;; The stub switched us to the debug stack and pushed the interrupt number.\r
+;;\r
+;; Next, construct the context record. It will be build on the debug stack by\r
+;; pushing the registers in the correct order so as to create the context structure\r
+;; on the debug stack. The context record must be built from the end back to the\r
+;; beginning because the stack grows down...\r
+;\r
+;; For reference, the context record looks like this:\r
+;;\r
+;; typedef\r
+;; struct {\r
+;; UINT64 ExceptionData;\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;\r
+;; UINT64 RFlags;\r
+;; UINT64 Ldtr, Tr;\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+;; UINT64 Rip;\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r
+\r
+;; NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp\r
+ push rax\r
+ mov rax, qword ptr [rsp][8] ; save vector number\r
+ mov ExceptionNumber, rax ; save vector number\r
+ pop rax\r
+ add rsp, 8 ; pop vector number\r
+ mov AppRsp, rsp ; save stack top\r
+ mov rsp, offset DebugStackBegin ; switch to debugger stack\r
+ sub rsp, 8 ; leave space for vector number\r
+\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ push r15\r
+ push r14\r
+ push r13\r
+ push r12\r
+ push r11\r
+ push r10\r
+ push r9\r
+ push r8\r
+ push rax\r
+ push rcx\r
+ push rdx\r
+ push rbx\r
+ push rsp\r
+ push rbp\r
+ push rsi\r
+ push rdi\r
+\r
+;; Save interrupt state rflags register...\r
+ pushfq\r
+ pop rax\r
+ mov qword ptr Rflags, rax\r
+\r
+;; We need to determine if any extra data was pushed by the exception, and if so, save it\r
+;; To do this, we check the exception number pushed by the stub, and cache the\r
+;; result in a variable since we'll need this again.\r
+ cmp ExceptionNumber, EXCPT64_DOUBLE_FAULT\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_INVALID_TSS\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_SEG_NOT_PRESENT\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_STACK_FAULT\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_GP_FAULT\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_PAGE_FAULT\r
+ jz ExtraPushOne\r
+ cmp ExceptionNumber, EXCPT64_ALIGNMENT_CHECK\r
+ jz ExtraPushOne\r
+ mov ExtraPush, 0\r
+ mov ExceptData, 0\r
+ jmp ExtraPushDone\r
+ExtraPushOne:\r
+ mov ExtraPush, 1\r
+\r
+;; If there's some extra data, save it also, and modify the saved AppRsp to effectively\r
+;; pop this value off the application's stack.\r
+ mov rax, AppRsp\r
+ mov rbx, [rax]\r
+ mov ExceptData, rbx\r
+ add rax, 8\r
+ mov AppRsp, rax\r
+\r
+ExtraPushDone:\r
+\r
+;; The "push" above pushed the debug stack rsp. Since what we're actually doing\r
+;; is building the context record on the debug stack, we need to save the pushed\r
+;; debug RSP, and replace it with the application's last stack entry...\r
+ mov rax, [rsp + 24]\r
+ mov DebugRsp, rax\r
+ mov rax, AppRsp\r
+ add rax, 40\r
+ ; application stack has ss, rsp, rflags, cs, & rip, so\r
+ ; last actual application stack entry is\r
+ ; 40 bytes into the application stack.\r
+ mov [rsp + 24], rax\r
+\r
+;; continue building context record\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ mov rax, ss\r
+ push rax\r
+\r
+ ; CS from application is one entry back in application stack\r
+ mov rax, AppRsp\r
+ movzx rax, word ptr [rax + 8]\r
+ push rax\r
+\r
+ mov rax, ds\r
+ push rax\r
+ mov rax, es\r
+ push rax\r
+ mov rax, fs\r
+ push rax\r
+ mov rax, gs\r
+ push rax\r
+\r
+;; UINT64 Rip;\r
+ ; Rip from application is on top of application stack\r
+ mov rax, AppRsp\r
+ push qword ptr [rax]\r
+\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+ push 0\r
+ push 0\r
+ sidt fword ptr [rsp]\r
+ push 0\r
+ push 0\r
+ sgdt fword ptr [rsp]\r
+\r
+;; UINT64 Ldtr, Tr;\r
+ xor rax, rax\r
+ str ax\r
+ push rax\r
+ sldt ax\r
+ push rax\r
+\r
+;; UINT64 RFlags;\r
+;; Rflags from application is two entries back in application stack\r
+ mov rax, AppRsp\r
+ push qword ptr [rax + 16]\r
+\r
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+;; insure FXSAVE/FXRSTOR is enabled in CR4...\r
+;; ... while we're at it, make sure DE is also enabled...\r
+ mov rax, cr8\r
+ push rax\r
+ mov rax, cr4\r
+ or rax, 208h\r
+ mov cr4, rax\r
+ push rax\r
+ mov rax, cr3\r
+ push rax\r
+ mov rax, cr2\r
+ push rax\r
+ push 0\r
+ mov rax, cr0\r
+ push rax\r
+\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov rax, dr7\r
+ push rax\r
+;; clear Dr7 while executing debugger itself\r
+ xor rax, rax\r
+ mov dr7, rax\r
+\r
+ mov rax, dr6\r
+ push rax\r
+;; insure all status bits in dr6 are clear...\r
+ xor rax, rax\r
+ mov dr6, rax\r
+\r
+ mov rax, dr3\r
+ push rax\r
+ mov rax, dr2\r
+ push rax\r
+ mov rax, dr1\r
+ push rax\r
+ mov rax, dr0\r
+ push rax\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+ sub rsp, 512\r
+ mov rdi, rsp\r
+ ; IMPORTANT!! The debug stack has been carefully constructed to\r
+ ; insure that rsp and rdi are 16 byte aligned when we get here.\r
+ ; They MUST be. If they are not, a GP fault will occur.\r
+ FXSTOR_RDI\r
+\r
+;; UINT64 ExceptionData;\r
+ mov rax, ExceptData\r
+ push rax\r
+\r
+; call to C code which will in turn call registered handler\r
+; pass in the vector number\r
+ mov rdx, rsp\r
+ mov rcx, ExceptionNumber\r
+ sub rsp, 40\r
+ call InterruptDistrubutionHub\r
+ add rsp, 40\r
+\r
+; restore context...\r
+;; UINT64 ExceptionData;\r
+ add rsp, 8\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+ mov rsi, rsp\r
+ FXRSTOR_RSI\r
+ add rsp, 512\r
+\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop rax\r
+ mov dr0, rax\r
+ pop rax\r
+ mov dr1, rax\r
+ pop rax\r
+ mov dr2, rax\r
+ pop rax\r
+ mov dr3, rax\r
+;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add rsp, 8\r
+ pop rax\r
+ mov dr7, rax\r
+\r
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ pop rax\r
+ mov cr0, rax\r
+ add rsp, 8\r
+ pop rax\r
+ mov cr2, rax\r
+ pop rax\r
+ mov cr3, rax\r
+ pop rax\r
+ mov cr4, rax\r
+ pop rax\r
+ mov cr8, rax\r
+\r
+;; UINT64 RFlags;\r
+ mov rax, AppRsp\r
+ pop qword ptr [rax + 16]\r
+\r
+;; UINT64 Ldtr, Tr;\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+ add rsp, 48\r
+\r
+;; UINT64 Rip;\r
+ pop qword ptr [rax]\r
+\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger... We\r
+;; could attempt to insulate ourselves against this possibility,\r
+;; but that poses risks as well.\r
+;;\r
+\r
+ pop rax\r
+ ; mov gs, rax\r
+ pop rax\r
+ ; mov fs, rax\r
+ pop rax\r
+ mov es, rax\r
+ pop rax\r
+ mov ds, rax\r
+ mov rax, AppRsp\r
+ pop qword ptr [rax + 8]\r
+ pop rax\r
+ mov ss, rax\r
+\r
+;; The next stuff to restore is the general purpose registers that were pushed\r
+;; using the "push" instruction.\r
+;;\r
+;; The value of RSP as stored in the context record is the application RSP\r
+;; including the 5 entries on the application stack caused by the exception\r
+;; itself. It may have been modified by the debug agent, so we need to\r
+;; determine if we need to relocate the application stack.\r
+\r
+ mov rbx, [rsp + 24] ; move the potentially modified AppRsp into rbx\r
+ mov rax, AppRsp\r
+ add rax, 40\r
+ cmp rbx, rax\r
+ je NoAppStackMove\r
+\r
+ mov rax, AppRsp\r
+ mov rcx, [rax] ; RIP\r
+ mov [rbx], rcx\r
+\r
+ mov rcx, [rax + 8] ; CS\r
+ mov [rbx + 8], rcx\r
+\r
+ mov rcx, [rax + 16] ; RFLAGS\r
+ mov [rbx + 16], rcx\r
+\r
+ mov rcx, [rax + 24] ; RSP\r
+ mov [rbx + 24], rcx\r
+\r
+ mov rcx, [rax + 32] ; SS\r
+ mov [rbx + 32], rcx\r
+\r
+ mov rax, rbx ; modify the saved AppRsp to the new AppRsp\r
+ mov AppRsp, rax\r
+NoAppStackMove:\r
+ mov rax, DebugRsp ; restore the DebugRsp on the debug stack\r
+ ; so our "pop" will not cause a stack switch\r
+ mov [rsp + 24], rax\r
+\r
+ cmp ExceptionNumber, 068h\r
+ jne NoChain\r
+\r
+Chain:\r
+\r
+;; Restore rflags so when we chain, the flags will be exactly as if we were never here.\r
+;; We gin up the stack to do an iretq so we can get ALL the flags.\r
+ mov rax, AppRsp\r
+ mov rbx, [rax + 40]\r
+ push rbx\r
+ mov rax, ss\r
+ push rax\r
+ mov rax, rsp\r
+ add rax, 16\r
+ push rax\r
+ mov rax, AppRsp\r
+ mov rbx, [rax + 16]\r
+ and rbx, NOT 300h ; special handling for IF and TF\r
+ push rbx\r
+ mov rax, cs\r
+ push rax\r
+ mov rax, offset PhonyIretq\r
+ push rax\r
+ iretq\r
+PhonyIretq:\r
+\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pop rdi\r
+ pop rsi\r
+ pop rbp\r
+ pop rsp\r
+ pop rbx\r
+ pop rdx\r
+ pop rcx\r
+ pop rax\r
+ pop r8\r
+ pop r9\r
+ pop r10\r
+ pop r11\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+\r
+;; Switch back to application stack\r
+ mov rsp, AppRsp\r
+\r
+;; Jump to original handler\r
+ jmp OrigVector\r
+\r
+NoChain:\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pop rdi\r
+ pop rsi\r
+ pop rbp\r
+ pop rsp\r
+ pop rbx\r
+ pop rdx\r
+ pop rcx\r
+ pop rax\r
+ pop r8\r
+ pop r9\r
+ pop r10\r
+ pop r11\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+\r
+;; Switch back to application stack\r
+ mov rsp, AppRsp\r
+\r
+;; We're outa here...\r
+ iretq\r
+text ENDS\r
+\r
+END\r
+\r
+\r
+\r
--- /dev/null
+/**@file\r
+ X64 specific debug support functions\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+//\r
+// private header files\r
+//\r
+#include "plDebugSupport.h"\r
+\r
+//\r
+// This the global main table to keep track of the interrupts\r
+//\r
+IDT_ENTRY *IdtEntryTable = NULL;\r
+DESCRIPTOR NullDesc = {0, 0};\r
+\r
+STATIC\r
+EFI_STATUS\r
+CreateEntryStub (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ OUT VOID **Stub\r
+ )\r
+/*++\r
+\r
+Routine Description: Allocate pool for a new IDT entry stub. Copy the generic\r
+ stub into the new buffer and fixup the vector number and jump target address.\r
+\r
+Arguments:\r
+ ExceptionType - This is the exception type that the new stub will be created\r
+ for.\r
+ Stub - On successful exit, *Stub contains the newly allocated entry stub.\r
+Returns:\r
+ Typically EFI_SUCCESS\r
+ other possibilities are passed through from AllocatePool\r
+\r
+--*/\r
+{\r
+ UINT8 *StubCopy;\r
+\r
+ StubCopy = *Stub;\r
+\r
+ //\r
+ // Fixup the stub code for this vector\r
+ //\r
+\r
+ // The stub code looks like this:\r
+ //\r
+ // 00000000 6A 00 push 0 ; push vector number - will be modified before installed\r
+ // 00000002 E9 db 0e9h ; jump rel32\r
+ // 00000003 00000000 dd 0 ; fixed up to relative address of CommonIdtEntry\r
+ //\r
+\r
+ //\r
+ // poke in the exception type so the second push pushes the exception type\r
+ //\r
+ StubCopy[0x1] = (UINT8) ExceptionType;\r
+\r
+ //\r
+ // fixup the jump target to point to the common entry\r
+ //\r
+ *(UINT32 *) &StubCopy[0x3] = (UINT32)((UINTN) CommonIdtEntry - (UINTN) &StubCopy[StubSize]);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+HookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN VOID (*NewCallback) ()\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Creates a nes entry stub. Then saves the current IDT entry and replaces it\r
+ with an interrupt gate for the new entry point. The IdtEntryTable is updated\r
+ with the new registered function.\r
+\r
+ This code executes in boot services context. The stub entry executes in interrupt\r
+ context.\r
+\r
+Arguments:\r
+ ExceptionType - specifies which vector to hook.\r
+ NewCallback - a pointer to the new function to be registered.\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Other possibilities are passed through by CreateEntryStub\r
+\r
+--*/\r
+{\r
+ BOOLEAN OldIntFlagState;\r
+ EFI_STATUS Status;\r
+\r
+ Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry);\r
+ if (Status == EFI_SUCCESS) {\r
+ OldIntFlagState = WriteInterruptFlag (0);\r
+ ReadIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+\r
+ ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[0] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc.Low)[0];\r
+ ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[1] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc.Low)[3];\r
+ ((UINT32 *) &IdtEntryTable[ExceptionType].OrigVector)[1] = ((UINT32 *) &IdtEntryTable[ExceptionType].OrigDesc.High)[0];\r
+\r
+ Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);\r
+ IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
+ WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));\r
+ WriteInterruptFlag (OldIntFlagState);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+UnhookEntry (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Undoes HookEntry. This code executes in boot services context.\r
+\r
+Arguments:\r
+ ExceptionType - specifies which entry to unhook\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ BOOLEAN OldIntFlagState;\r
+\r
+ OldIntFlagState = WriteInterruptFlag (0);\r
+ WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+ WriteInterruptFlag (OldIntFlagState);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ManageIdtEntryTable (\r
+ VOID (*NewCallback)(),\r
+ EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the main worker function that manages the state of the interrupt\r
+ handlers. It both installs and uninstalls interrupt handlers based on the\r
+ value of NewCallback. If NewCallback is NULL, then uninstall is indicated.\r
+ If NewCallback is non-NULL, then install is indicated.\r
+\r
+Arguments:\r
+ NewCallback - If non-NULL, NewCallback specifies the new handler to register.\r
+ If NULL, specifies that the previously registered handler should\r
+ be uninstalled.\r
+ ExceptionType - Indicates which entry to manage\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (CompareDescriptor (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc)) {\r
+ //\r
+ // we've already installed to this vector\r
+ //\r
+ if (NewCallback != NULL) {\r
+ //\r
+ // if the input handler is non-null, error\r
+ //\r
+ Status = EFI_ALREADY_STARTED;\r
+ } else {\r
+ Status = UnhookEntry (ExceptionType);\r
+ }\r
+ } else {\r
+ //\r
+ // no user handler installed on this vector\r
+ //\r
+ if (NewCallback == NULL) {\r
+ //\r
+ // if the input handler is null, error\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Status = HookEntry (ExceptionType, NewCallback);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+{\r
+ *MaxProcessorIndex = 0;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+{\r
+ return ManageIdtEntryTable (NewCallback, ExceptionType);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+ Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+{\r
+ AsmWbinvd ();\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initializes driver's handler registration database.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_UNSUPPORTED - if X64 processor does not support FXSTOR/FXRSTOR instructions,\r
+ the context save will fail, so these processor's are not supported.\r
+ EFI_OUT_OF_RESOURCES - not resource to finish initialization\r
+\r
+--*/\r
+{\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ if (!FxStorSupport ()) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);\r
+ if (IdtEntryTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize);\r
+ if (IdtEntryTable[ExceptionType].StubEntry == NULL) {\r
+ goto ErrorCleanup;\r
+ }\r
+\r
+ CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);\r
+ }\r
+ return EFI_SUCCESS;\r
+\r
+ErrorCleanup:\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
+ FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
+ }\r
+ }\r
+ FreePool (IdtEntryTable);\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the callback that is written to the LoadedImage protocol instance\r
+ on the image handle. It uninstalls all registered handlers and frees all entry\r
+ stub memory.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ ImageHandle - The image handle of the unload handler\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+{\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ ManageIdtEntryTable (NULL, ExceptionType);\r
+ }\r
+\r
+ FreePool (IdtEntryTable);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InterruptDistrubutionHub (\r
+ EFI_EXCEPTION_TYPE ExceptionType,\r
+ EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
+ )\r
+/*++\r
+\r
+Routine Description: Common piece of code that invokes the registered handlers.\r
+\r
+ This code executes in exception context so no efi calls are allowed.\r
+\r
+Arguments:\r
+ ExceptionType - exception type\r
+ ContextRecord - system context\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
+ if (ExceptionType != SYSTEM_TIMER_VECTOR) {\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);\r
+ } else {\r
+ OrigVector = IdtEntryTable[ExceptionType].OrigVector;\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/**@file\r
+ X64 specific debug support macros, typedefs and prototypes.\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+#ifndef _PLDEBUG_SUPPORT_H\r
+#define _PLDEBUG_SUPPORT_H\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/DebugSupport.h>\r
+#include <Protocol/LoadedImage.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+#include <Library/PcdLib.h>\r
+#define NUM_IDT_ENTRIES 0x78\r
+#define SYSTEM_TIMER_VECTOR 0x68\r
+#define VECTOR_ENTRY_PAGES 1\r
+#define CopyDescriptor(Dest, Src) CopyMem ((Dest), (Src), sizeof (DESCRIPTOR))\r
+#define ZeroDescriptor(Dest) CopyDescriptor ((Dest), &NullDesc)\r
+#define ReadIdt(Vector, Dest) CopyDescriptor ((Dest), &((GetIdtr ())[(Vector)]))\r
+#define WriteIdt(Vector, Src) CopyDescriptor (&((GetIdtr ())[(Vector)]), (Src))\r
+#define CompareDescriptor(Desc1, Desc2) CompareMem ((Desc1), (Desc2), sizeof (DESCRIPTOR))\r
+#define EFI_ISA IsaX64\r
+#define FF_FXSR (1 << 24)\r
+\r
+typedef struct {\r
+ UINT64 Low;\r
+ UINT64 High;\r
+} DESCRIPTOR;\r
+\r
+typedef\r
+VOID\r
+(*DEBUG_PROC) (\r
+ VOID\r
+ )\r
+;\r
+\r
+typedef struct {\r
+ DESCRIPTOR OrigDesc;\r
+ DEBUG_PROC OrigVector;\r
+ DESCRIPTOR NewDesc;\r
+ DEBUG_PROC StubEntry;\r
+ VOID (*RegisteredCallback) ();\r
+} IDT_ENTRY;\r
+\r
+extern EFI_SYSTEM_CONTEXT SystemContext;\r
+extern UINT8 InterruptEntryStub[];\r
+extern UINT32 StubSize;\r
+extern VOID (*OrigVector) (VOID);\r
+\r
+VOID\r
+CommonIdtEntry (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Generic IDT entry\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+\r
+BOOLEAN\r
+FxStorSupport (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check whether FXSTOR is supported\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ TRUE - supported\r
+ FALSE - not supported\r
+\r
+--*/\r
+;\r
+\r
+DESCRIPTOR *\r
+GetIdtr (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Return the physical address of IDTR\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ The physical address of IDTR\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+Vect2Desc (\r
+ DESCRIPTOR * DestDesc,\r
+ VOID (*Vector) (VOID)\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Encodes an IDT descriptor with the given physical address\r
+\r
+Arguments:\r
+\r
+ DestDesc - The IDT descriptor address\r
+ Vector - The interrupt vector entry\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+BOOLEAN\r
+WriteInterruptFlag (\r
+ BOOLEAN NewState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Programs interrupt flag to the requested state and returns previous\r
+ state.\r
+\r
+Arguments:\r
+\r
+ NewState - New interrupt status\r
+\r
+Returns:\r
+\r
+ Old interrupt status\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+plInitializeDebugSupportDriver (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initializes driver's handler registration database.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_UNSUPPORTED - if X64 processor does not support FXSTOR/FXRSTOR instructions,\r
+ the context save will fail, so these processor's are not supported.\r
+ EFI_OUT_OF_RESOURCES - not resource to finish initialization\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+plUnloadDebugSupportDriver (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is the callback that is written to the LoadedImage protocol instance\r
+ on the image handle. It uninstalls all registered handlers and frees all entry\r
+ stub memory.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ ImageHandle - The image handle of the unload handler\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// DebugSupport protocol member functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+GetMaximumProcessorIndex (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ MaxProcessorIndex - The maximuim supported processor index\r
+\r
+Returns:\r
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterPeriodicCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ )\r
+/*++\r
+\r
+Routine Description: This is a DebugSupport protocol member function.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ PeriodicCallback - Callback function\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterExceptionCallback (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK NewCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+\r
+ This code executes in boot services context.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ NewCallback - Callback function\r
+ ExceptionType - Which exception to hook\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS\r
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has\r
+ no handler registered for it\r
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.\r
+\r
+ Other possible return values are passed through from UnHookEntry and HookEntry.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InvalidateInstructionCache (\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This is a DebugSupport protocol member function.\r
+ Calls assembly routine to flush cache.\r
+\r
+Arguments:\r
+ This - The DebugSupport instance\r
+ ProcessorIndex - Which processor the callback applies to.\r
+ Start - Physical base of the memory range to be invalidated\r
+ Length - mininum number of bytes in instruction cache to invalidate\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - always return success\r
+\r
+--*/\r
+;\r
+\r
+#endif\r