diff options
author | bbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-04-21 22:54:32 +0000 |
---|---|---|
committer | bbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-04-21 22:54:32 +0000 |
commit | 878ddf1fc3540a715f63594ed22b6929e881afb4 (patch) | |
tree | c56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c | |
download | edk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz |
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c')
-rw-r--r-- | EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c | 833 |
1 files changed, 833 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c new file mode 100644 index 0000000000..a24bfd06d5 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c @@ -0,0 +1,833 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DebugPort.c
+
+Abstract:
+
+ Top level C file for debugport driver. Contains initialization function.
+ This driver layers on top of SerialIo.
+
+ ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM
+ INTERRUPT CONTEXT.
+
+Revision History
+
+--*/
+
+
+#include "DebugPort.h"
+
+//
+// Misc. functions local to this module
+//
+STATIC
+VOID
+GetDebugPortVariable (
+ DEBUGPORT_DEVICE *DebugPortDevice
+ );
+
+EFI_STATUS
+EFIAPI
+ImageUnloadHandler (
+ EFI_HANDLE ImageHandle
+ );
+
+//
+// Globals
+//
+
+EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = {
+ DebugPortSupported,
+ DebugPortStart,
+ DebugPortStop,
+ DEBUGPORT_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+DEBUGPORT_DEVICE *gDebugPortDevice;
+static UINT32 mHid16550;
+static UINT32 mHidStdPcComPort;
+
+//
+// implementation code
+//
+
+EFI_STATUS
+EFIAPI
+InitializeDebugPortDriver (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Driver entry point. Reads DebugPort variable to determine what device and settings
+ to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \
+ if no variable is found.
+
+ Creates debugport and devicepath protocols on new handle.
+
+Arguments:
+ ImageHandle,
+ SystemTable
+
+Returns:
+
+ EFI_UNSUPPORTED
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ mHid16550 = EFI_ACPI_16550UART_HID;
+ mHidStdPcComPort = EFI_ACPI_PC_COMPORT_HID;
+
+ //
+ // Allocate and Initialize dev structure
+ //
+ gDebugPortDevice = AllocateZeroPool (sizeof (DEBUGPORT_DEVICE));
+ if (gDebugPortDevice == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Fill in static and default pieces of device structure first.
+ //
+ gDebugPortDevice->Signature = DEBUGPORT_DEVICE_SIGNATURE;
+
+ gDebugPortDevice->DebugPortInterface.Reset = DebugPortReset;
+ gDebugPortDevice->DebugPortInterface.Read = DebugPortRead;
+ gDebugPortDevice->DebugPortInterface.Write = DebugPortWrite;
+ gDebugPortDevice->DebugPortInterface.Poll = DebugPortPoll;
+
+ gDebugPortDevice->BaudRate = DEBUGPORT_UART_DEFAULT_BAUDRATE;
+ gDebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
+ gDebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;
+ gDebugPortDevice->Parity = DEBUGPORT_UART_DEFAULT_PARITY;
+ gDebugPortDevice->DataBits = DEBUGPORT_UART_DEFAULT_DATA_BITS;
+ gDebugPortDevice->StopBits = DEBUGPORT_UART_DEFAULT_STOP_BITS;
+
+ return EFI_SUCCESS;
+}
+//
+// DebugPort driver binding member functions...
+//
+EFI_STATUS
+EFIAPI
+DebugPortSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+ Checks to see that there's not already a DebugPort interface somewhere. If so,
+ fail.
+
+ If there's a DEBUGPORT variable, the device path must match exactly. If there's
+ no DEBUGPORT variable, then device path is not checked and does not matter.
+
+ Checks to see that there's a serial io interface on the controller handle
+ that can be bound BY_DRIVER | EXCLUSIVE.
+
+ If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
+ or other error returned by OpenProtocol.
+
+Arguments:
+ This
+ ControllerHandle
+ RemainingDevicePath
+
+Returns:
+ EFI_UNSUPPORTED
+ EFI_OUT_OF_RESOURCES
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp1;
+ EFI_DEVICE_PATH_PROTOCOL *Dp2;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;
+ EFI_HANDLE TempHandle;
+
+ //
+ // Check to see that there's not a debugport protocol already published
+ //
+ if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **) &DebugPortInterface) != EFI_NOT_FOUND) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Read DebugPort variable to determine debug port selection and parameters
+ //
+ GetDebugPortVariable (gDebugPortDevice);
+
+ if (gDebugPortDevice->DebugPortVariable != NULL) {
+ //
+ // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
+ // the closest matching handle matches the controller handle, and if it does,
+ // check to see that the remaining device path has the DebugPort GUIDed messaging
+ // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
+ //
+ Dp1 = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) gDebugPortDevice->DebugPortVariable);
+ if (Dp1 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dp2 = Dp1;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiSerialIoProtocolGuid,
+ &Dp2,
+ &TempHandle
+ );
+
+ if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (Status == EFI_SUCCESS && (Dp2->Type != 3 || Dp2->SubType != 10 || *((UINT16 *) Dp2->Length) != 20)) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (Status == EFI_SUCCESS && CompareMem (&gEfiDebugPortDevicePathGuid, Dp2 + 1, sizeof (EFI_GUID))) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->FreePool (Dp1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugPortStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+ Binds exclusively to serial io on the controller handle. Produces DebugPort
+ protocol and DevicePath on new handle.
+
+Arguments:
+ This
+ ControllerHandle
+ RemainingDevicePath
+
+Returns:
+ EFI_OUT_OF_RESOURCES
+ EFI_SUCCESS
+--*/
+{
+ EFI_STATUS Status;
+ DEBUGPORT_DEVICE_PATH DebugPortDP;
+ EFI_DEVICE_PATH_PROTOCOL EndDP;
+ EFI_DEVICE_PATH_PROTOCOL *Dp1;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &gDebugPortDevice->SerialIoBinding,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gDebugPortDevice->SerialIoDeviceHandle = ControllerHandle;
+
+ //
+ // Initialize the Serial Io interface...
+ //
+ Status = gDebugPortDevice->SerialIoBinding->SetAttributes (
+ gDebugPortDevice->SerialIoBinding,
+ gDebugPortDevice->BaudRate,
+ gDebugPortDevice->ReceiveFifoDepth,
+ gDebugPortDevice->Timeout,
+ gDebugPortDevice->Parity,
+ gDebugPortDevice->DataBits,
+ gDebugPortDevice->StopBits
+ );
+ if (EFI_ERROR (Status)) {
+ gDebugPortDevice->BaudRate = 0;
+ gDebugPortDevice->Parity = DefaultParity;
+ gDebugPortDevice->DataBits = 0;
+ gDebugPortDevice->StopBits = DefaultStopBits;
+ gDebugPortDevice->ReceiveFifoDepth = 0;
+ Status = gDebugPortDevice->SerialIoBinding->SetAttributes (
+ gDebugPortDevice->SerialIoBinding,
+ gDebugPortDevice->BaudRate,
+ gDebugPortDevice->ReceiveFifoDepth,
+ gDebugPortDevice->Timeout,
+ gDebugPortDevice->Parity,
+ gDebugPortDevice->DataBits,
+ gDebugPortDevice->StopBits
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+ }
+
+ gDebugPortDevice->SerialIoBinding->Reset (gDebugPortDevice->SerialIoBinding);
+
+ //
+ // Create device path instance for DebugPort
+ //
+ DebugPortDP.Header.Type = MESSAGING_DEVICE_PATH;
+ DebugPortDP.Header.SubType = MSG_VENDOR_DP;
+ SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP));
+ gBS->CopyMem (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid, sizeof (EFI_GUID));
+
+ Dp1 = DevicePathFromHandle (ControllerHandle);
+ if (Dp1 == NULL) {
+ Dp1 = &EndDP;
+ SetDevicePathEndNode (Dp1);
+ }
+
+ gDebugPortDevice->DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);
+ if (gDebugPortDevice->DebugPortDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Publish DebugPort and Device Path protocols
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gDebugPortDevice->DebugPortDeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ gDebugPortDevice->DebugPortDevicePath,
+ &gEfiDebugPortProtocolGuid,
+ &gDebugPortDevice->DebugPortInterface,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+ //
+ // Connect debugport child to serial io
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &gDebugPortDevice->SerialIoBinding,
+ This->DriverBindingHandle,
+ gDebugPortDevice->DebugPortDeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG_CODE (
+ UINTN BufferSize;
+
+ BufferSize = 48;
+ DebugPortWrite (
+ &gDebugPortDevice->DebugPortInterface,
+ 0,
+ &BufferSize,
+ "DebugPort driver failed to open child controller\n\n"
+ );
+ );
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+
+ DEBUG_CODE (
+ UINTN BufferSize;
+
+ BufferSize = 38;
+ DebugPortWrite (
+ &gDebugPortDevice->DebugPortInterface,
+ 0,
+ &BufferSize,
+ "Hello World from the DebugPort driver\n\n"
+ );
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugPortStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+ We're never intending to be stopped via the driver model so this just returns
+ EFI_UNSUPPORTED
+
+Arguments:
+ Per EFI 1.10 driver model
+
+Returns:
+ EFI_UNSUPPORTED
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ gDebugPortDevice->SerialIoBinding = NULL;
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ gBS->FreePool (gDebugPortDevice->DebugPortDevicePath);
+
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Disconnect SerialIo child handle
+ //
+ Status = gBS->CloseProtocol (
+ gDebugPortDevice->SerialIoDeviceHandle,
+ &gEfiSerialIoProtocolGuid,
+ This->DriverBindingHandle,
+ gDebugPortDevice->DebugPortDeviceHandle
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Unpublish our protocols (DevicePath, DebugPort)
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ gDebugPortDevice->DebugPortDeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ gDebugPortDevice->DebugPortDevicePath,
+ &gEfiDebugPortProtocolGuid,
+ &gDebugPortDevice->DebugPortInterface,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &gDebugPortDevice->SerialIoBinding,
+ This->DriverBindingHandle,
+ gDebugPortDevice->DebugPortDeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gDebugPortDevice->DebugPortDeviceHandle = NULL;
+ }
+ }
+
+ return Status;
+}
+//
+// Debugport protocol member functions
+//
+EFI_STATUS
+EFIAPI
+DebugPortReset (
+ IN EFI_DEBUGPORT_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
+ We cannot call SerialIo:SetAttributes because it uses pool services, which use
+ locks, which affect TPL, so it's not interrupt context safe or re-entrant.
+ SerialIo:Reset() calls SetAttributes, so it can't be used either.
+
+ The port itself should be fine since it was set up during initialization.
+
+Arguments:
+ This
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ DEBUGPORT_DEVICE *DebugPortDevice;
+ UINTN BufferSize;
+ UINTN BitBucket;
+
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
+ while (This->Poll (This) == EFI_SUCCESS) {
+ BufferSize = 1;
+ This->Read (This, 0, &BufferSize, &BitBucket);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugPortRead (
+ IN EFI_DEBUGPORT_PROTOCOL *This,
+ IN UINT32 Timeout,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ DebugPort protocol member function. Calls SerialIo:Read() after setting
+ if it's different than the last SerialIo access.
+
+Arguments:
+ IN EFI_DEBUGPORT_PROTOCOL *This
+ IN UINT32 Timeout,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ DEBUGPORT_DEVICE *DebugPortDevice;
+ UINTN LocalBufferSize;
+ EFI_STATUS Status;
+ UINT8 *BufferPtr;
+
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
+ BufferPtr = Buffer;
+ LocalBufferSize = *BufferSize;
+ do {
+ Status = DebugPortDevice->SerialIoBinding->Read (
+ DebugPortDevice->SerialIoBinding,
+ &LocalBufferSize,
+ BufferPtr
+ );
+ if (Status == EFI_TIMEOUT) {
+ if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {
+ Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT;
+ } else {
+ Timeout = 0;
+ }
+ } else if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ BufferPtr += LocalBufferSize;
+ LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer);
+ } while (LocalBufferSize != 0 && Timeout > 0);
+
+ *BufferSize = (UINTN) (BufferPtr - (UINT8 *) Buffer);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugPortWrite (
+ IN EFI_DEBUGPORT_PROTOCOL *This,
+ IN UINT32 Timeout,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
+ a time and does a GetControl between 8 byte writes to help insure reads are
+ interspersed This is poor-man's flow control..
+
+Arguments:
+ This - Pointer to DebugPort protocol
+ Timeout - Timeout value
+ BufferSize - On input, the size of Buffer.
+ On output, the amount of data actually written.
+ Buffer - Pointer to buffer to write
+
+Returns:
+ EFI_SUCCESS - The data was written.
+ EFI_DEVICE_ERROR - The device reported an error.
+ EFI_TIMEOUT - The data write was stopped due to a timeout.
+
+--*/
+{
+ DEBUGPORT_DEVICE *DebugPortDevice;
+ UINTN Position;
+ UINTN WriteSize;
+ EFI_STATUS Status;
+ UINT32 SerialControl;
+
+ Status = EFI_SUCCESS;
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
+
+ WriteSize = 8;
+ for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {
+ DebugPortDevice->SerialIoBinding->GetControl (
+ DebugPortDevice->SerialIoBinding,
+ &SerialControl
+ );
+ if (*BufferSize - Position < 8) {
+ WriteSize = *BufferSize - Position;
+ }
+
+ Status = DebugPortDevice->SerialIoBinding->Write (
+ DebugPortDevice->SerialIoBinding,
+ &WriteSize,
+ &((UINT8 *) Buffer)[Position]
+ );
+ }
+
+ *BufferSize = Position;
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugPortPoll (
+ IN EFI_DEBUGPORT_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ DebugPort protocol member function. Calls SerialIo:Write() after setting
+ if it's different than the last SerialIo access.
+
+Arguments:
+ IN EFI_DEBUGPORT_PROTOCOL *This
+
+Returns:
+ EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
+ EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
+ EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 SerialControl;
+ DEBUGPORT_DEVICE *DebugPortDevice;
+
+ DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
+
+ Status = DebugPortDevice->SerialIoBinding->GetControl (
+ DebugPortDevice->SerialIoBinding,
+ &SerialControl
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) {
+ Status = EFI_NOT_READY;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+}
+//
+// Misc. functions local to this module..
+//
+STATIC
+VOID
+GetDebugPortVariable (
+ DEBUGPORT_DEVICE *DebugPortDevice
+ )
+/*++
+
+Routine Description:
+ Local worker function to obtain device path information from DebugPort variable.
+ Records requested settings in DebugPort device structure.
+
+Arguments:
+ DEBUGPORT_DEVICE *DebugPortDevice,
+
+Returns:
+
+ Nothing
+
+--*/
+{
+ UINTN DataSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+
+ DataSize = 0;
+
+ Status = gRT->GetVariable (
+ (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME,
+ &gEfiDebugPortVariableGuid,
+ NULL,
+ &DataSize,
+ DebugPortDevice->DebugPortVariable
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (gDebugPortDevice->DebugPortVariable != NULL) {
+ gBS->FreePool (gDebugPortDevice->DebugPortVariable);
+ }
+
+ DebugPortDevice->DebugPortVariable = AllocatePool (DataSize);
+ if (DebugPortDevice->DebugPortVariable != NULL) {
+ gRT->GetVariable (
+ (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME,
+ &gEfiDebugPortVariableGuid,
+ NULL,
+ &DataSize,
+ DebugPortDevice->DebugPortVariable
+ );
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DebugPortDevice->DebugPortVariable;
+ while (!EfiIsDevicePathEnd (DevicePath) && !EfiIsUartDevicePath (DevicePath)) {
+ DevicePath = EfiNextDevicePathNode (DevicePath);
+ }
+
+ if (EfiIsDevicePathEnd (DevicePath)) {
+ gBS->FreePool (gDebugPortDevice->DebugPortVariable);
+ DebugPortDevice->DebugPortVariable = NULL;
+ } else {
+ gBS->CopyMem (
+ &DebugPortDevice->BaudRate,
+ &((UART_DEVICE_PATH *) DevicePath)->BaudRate,
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)
+ );
+ DebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
+ DebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;
+ gBS->CopyMem (
+ &DebugPortDevice->Parity,
+ &((UART_DEVICE_PATH *) DevicePath)->Parity,
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)
+ );
+ gBS->CopyMem (
+ &DebugPortDevice->DataBits,
+ &((UART_DEVICE_PATH *) DevicePath)->DataBits,
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)
+ );
+ gBS->CopyMem (
+ &DebugPortDevice->StopBits,
+ &((UART_DEVICE_PATH *) DevicePath)->StopBits,
+ sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)
+ );
+ }
+ }
+ }
+}
+
+EFI_STATUS
+EFIAPI
+ImageUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+ Unload function that is registered in the LoadImage protocol. It un-installs
+ protocols produced and deallocates pool used by the driver. Called by the core
+ when unloading the driver.
+
+Arguments:
+ EFI_HANDLE ImageHandle
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (gDebugPortDevice->SerialIoBinding != NULL) {
+ return EFI_ABORTED;
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDebugPortDevice->DriverBindingInterface,
+ &gEfiComponentNameProtocolGuid,
+ &gDebugPortDevice->ComponentNameInterface,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Clean up allocations
+ //
+ if (gDebugPortDevice->DebugPortVariable != NULL) {
+ gBS->FreePool (gDebugPortDevice->DebugPortVariable);
+ }
+
+ gBS->FreePool (gDebugPortDevice);
+
+ return EFI_SUCCESS;
+}
|