3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Top level C file for debugport driver. Contains initialization function.
19 This driver layers on top of SerialIo.
21 ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM
29 #include "DebugPort.h"
32 // Misc. functions local to this module
36 GetDebugPortVariable (
37 DEBUGPORT_DEVICE
*DebugPortDevice
43 EFI_HANDLE ImageHandle
50 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
54 DEBUGPORT_DRIVER_VERSION
,
59 DEBUGPORT_DEVICE
*gDebugPortDevice
;
60 static UINT32 mHid16550
;
61 static UINT32 mHidStdPcComPort
;
64 // implementation code
69 InitializeDebugPortDriver (
70 IN EFI_HANDLE ImageHandle
,
71 IN EFI_SYSTEM_TABLE
*SystemTable
76 Driver entry point. Reads DebugPort variable to determine what device and settings
77 to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \
78 if no variable is found.
80 Creates debugport and devicepath protocols on new handle.
93 mHid16550
= EFI_ACPI_16550UART_HID
;
94 mHidStdPcComPort
= EFI_ACPI_PC_COMPORT_HID
;
97 // Allocate and Initialize dev structure
99 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
100 if (gDebugPortDevice
== NULL
) {
101 return EFI_OUT_OF_RESOURCES
;
104 // Fill in static and default pieces of device structure first.
106 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
108 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
109 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
110 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
111 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
113 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
114 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
115 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
116 gDebugPortDevice
->Parity
= DEBUGPORT_UART_DEFAULT_PARITY
;
117 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
118 gDebugPortDevice
->StopBits
= DEBUGPORT_UART_DEFAULT_STOP_BITS
;
123 // DebugPort driver binding member functions...
128 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
129 IN EFI_HANDLE ControllerHandle
,
130 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
135 Checks to see that there's not already a DebugPort interface somewhere. If so,
138 If there's a DEBUGPORT variable, the device path must match exactly. If there's
139 no DEBUGPORT variable, then device path is not checked and does not matter.
141 Checks to see that there's a serial io interface on the controller handle
142 that can be bound BY_DRIVER | EXCLUSIVE.
144 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
145 or other error returned by OpenProtocol.
160 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
161 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
162 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
163 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
164 EFI_HANDLE TempHandle
;
167 // Check to see that there's not a debugport protocol already published
169 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
170 return EFI_UNSUPPORTED
;
173 // Read DebugPort variable to determine debug port selection and parameters
175 GetDebugPortVariable (gDebugPortDevice
);
177 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
179 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
180 // the closest matching handle matches the controller handle, and if it does,
181 // check to see that the remaining device path has the DebugPort GUIDed messaging
182 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
184 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
186 return EFI_OUT_OF_RESOURCES
;
191 Status
= gBS
->LocateDevicePath (
192 &gEfiSerialIoProtocolGuid
,
197 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
198 Status
= EFI_UNSUPPORTED
;
201 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
202 Status
= EFI_UNSUPPORTED
;
205 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
206 Status
= EFI_UNSUPPORTED
;
210 if (EFI_ERROR (Status
)) {
215 Status
= gBS
->OpenProtocol (
217 &gEfiSerialIoProtocolGuid
,
219 This
->DriverBindingHandle
,
221 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
223 if (EFI_ERROR (Status
)) {
229 &gEfiSerialIoProtocolGuid
,
230 This
->DriverBindingHandle
,
240 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
241 IN EFI_HANDLE ControllerHandle
,
242 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
247 Binds exclusively to serial io on the controller handle. Produces DebugPort
248 protocol and DevicePath on new handle.
261 DEBUGPORT_DEVICE_PATH DebugPortDP
;
262 EFI_DEVICE_PATH_PROTOCOL EndDP
;
263 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
265 Status
= gBS
->OpenProtocol (
267 &gEfiSerialIoProtocolGuid
,
268 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
269 This
->DriverBindingHandle
,
271 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
273 if (EFI_ERROR (Status
)) {
277 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
280 // Initialize the Serial Io interface...
282 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
283 gDebugPortDevice
->SerialIoBinding
,
284 gDebugPortDevice
->BaudRate
,
285 gDebugPortDevice
->ReceiveFifoDepth
,
286 gDebugPortDevice
->Timeout
,
287 gDebugPortDevice
->Parity
,
288 gDebugPortDevice
->DataBits
,
289 gDebugPortDevice
->StopBits
291 if (EFI_ERROR (Status
)) {
292 gDebugPortDevice
->BaudRate
= 0;
293 gDebugPortDevice
->Parity
= DefaultParity
;
294 gDebugPortDevice
->DataBits
= 0;
295 gDebugPortDevice
->StopBits
= DefaultStopBits
;
296 gDebugPortDevice
->ReceiveFifoDepth
= 0;
297 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
298 gDebugPortDevice
->SerialIoBinding
,
299 gDebugPortDevice
->BaudRate
,
300 gDebugPortDevice
->ReceiveFifoDepth
,
301 gDebugPortDevice
->Timeout
,
302 gDebugPortDevice
->Parity
,
303 gDebugPortDevice
->DataBits
,
304 gDebugPortDevice
->StopBits
306 if (EFI_ERROR (Status
)) {
309 &gEfiSerialIoProtocolGuid
,
310 This
->DriverBindingHandle
,
317 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
320 // Create device path instance for DebugPort
322 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
323 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
324 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
325 gBS
->CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
327 Dp1
= DevicePathFromHandle (ControllerHandle
);
330 SetDevicePathEndNode (Dp1
);
333 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
334 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
335 return EFI_OUT_OF_RESOURCES
;
338 // Publish DebugPort and Device Path protocols
340 Status
= gBS
->InstallMultipleProtocolInterfaces (
341 &gDebugPortDevice
->DebugPortDeviceHandle
,
342 &gEfiDevicePathProtocolGuid
,
343 gDebugPortDevice
->DebugPortDevicePath
,
344 &gEfiDebugPortProtocolGuid
,
345 &gDebugPortDevice
->DebugPortInterface
,
349 if (EFI_ERROR (Status
)) {
352 &gEfiSerialIoProtocolGuid
,
353 This
->DriverBindingHandle
,
359 // Connect debugport child to serial io
361 Status
= gBS
->OpenProtocol (
363 &gEfiSerialIoProtocolGuid
,
364 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
365 This
->DriverBindingHandle
,
366 gDebugPortDevice
->DebugPortDeviceHandle
,
367 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
370 if (EFI_ERROR (Status
)) {
376 &gDebugPortDevice
->DebugPortInterface
,
379 "DebugPort driver failed to open child controller\n\n"
385 &gEfiSerialIoProtocolGuid
,
386 This
->DriverBindingHandle
,
397 &gDebugPortDevice
->DebugPortInterface
,
400 "Hello World from the DebugPort driver\n\n"
410 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
411 IN EFI_HANDLE ControllerHandle
,
412 IN UINTN NumberOfChildren
,
413 IN EFI_HANDLE
*ChildHandleBuffer
418 We're never intending to be stopped via the driver model so this just returns
422 Per EFI 1.10 driver model
432 if (NumberOfChildren
== 0) {
434 // Close the bus driver
438 &gEfiSerialIoProtocolGuid
,
439 This
->DriverBindingHandle
,
443 gDebugPortDevice
->SerialIoBinding
= NULL
;
447 &gEfiDevicePathProtocolGuid
,
448 This
->DriverBindingHandle
,
452 gBS
->FreePool (gDebugPortDevice
->DebugPortDevicePath
);
457 // Disconnect SerialIo child handle
459 Status
= gBS
->CloseProtocol (
460 gDebugPortDevice
->SerialIoDeviceHandle
,
461 &gEfiSerialIoProtocolGuid
,
462 This
->DriverBindingHandle
,
463 gDebugPortDevice
->DebugPortDeviceHandle
466 if (EFI_ERROR (Status
)) {
470 // Unpublish our protocols (DevicePath, DebugPort)
472 Status
= gBS
->UninstallMultipleProtocolInterfaces (
473 gDebugPortDevice
->DebugPortDeviceHandle
,
474 &gEfiDevicePathProtocolGuid
,
475 gDebugPortDevice
->DebugPortDevicePath
,
476 &gEfiDebugPortProtocolGuid
,
477 &gDebugPortDevice
->DebugPortInterface
,
481 if (EFI_ERROR (Status
)) {
484 &gEfiSerialIoProtocolGuid
,
485 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
486 This
->DriverBindingHandle
,
487 gDebugPortDevice
->DebugPortDeviceHandle
,
488 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
491 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
498 // Debugport protocol member functions
503 IN EFI_DEBUGPORT_PROTOCOL
*This
508 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
509 We cannot call SerialIo:SetAttributes because it uses pool services, which use
510 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
511 SerialIo:Reset() calls SetAttributes, so it can't be used either.
513 The port itself should be fine since it was set up during initialization.
524 DEBUGPORT_DEVICE
*DebugPortDevice
;
528 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
529 while (This
->Poll (This
) == EFI_SUCCESS
) {
531 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
540 IN EFI_DEBUGPORT_PROTOCOL
*This
,
542 IN OUT UINTN
*BufferSize
,
548 DebugPort protocol member function. Calls SerialIo:Read() after setting
549 if it's different than the last SerialIo access.
552 IN EFI_DEBUGPORT_PROTOCOL *This
554 IN OUT UINTN *BufferSize,
563 DEBUGPORT_DEVICE
*DebugPortDevice
;
564 UINTN LocalBufferSize
;
568 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
570 LocalBufferSize
= *BufferSize
;
572 Status
= DebugPortDevice
->SerialIoBinding
->Read (
573 DebugPortDevice
->SerialIoBinding
,
577 if (Status
== EFI_TIMEOUT
) {
578 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
579 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
583 } else if (EFI_ERROR (Status
)) {
587 BufferPtr
+= LocalBufferSize
;
588 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
589 } while (LocalBufferSize
!= 0 && Timeout
> 0);
591 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
599 IN EFI_DEBUGPORT_PROTOCOL
*This
,
601 IN OUT UINTN
*BufferSize
,
607 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
608 a time and does a GetControl between 8 byte writes to help insure reads are
609 interspersed This is poor-man's flow control..
612 This - Pointer to DebugPort protocol
613 Timeout - Timeout value
614 BufferSize - On input, the size of Buffer.
615 On output, the amount of data actually written.
616 Buffer - Pointer to buffer to write
619 EFI_SUCCESS - The data was written.
620 EFI_DEVICE_ERROR - The device reported an error.
621 EFI_TIMEOUT - The data write was stopped due to a timeout.
625 DEBUGPORT_DEVICE
*DebugPortDevice
;
629 UINT32 SerialControl
;
631 Status
= EFI_SUCCESS
;
632 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
635 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
636 DebugPortDevice
->SerialIoBinding
->GetControl (
637 DebugPortDevice
->SerialIoBinding
,
640 if (*BufferSize
- Position
< 8) {
641 WriteSize
= *BufferSize
- Position
;
644 Status
= DebugPortDevice
->SerialIoBinding
->Write (
645 DebugPortDevice
->SerialIoBinding
,
647 &((UINT8
*) Buffer
)[Position
]
651 *BufferSize
= Position
;
658 IN EFI_DEBUGPORT_PROTOCOL
*This
663 DebugPort protocol member function. Calls SerialIo:Write() after setting
664 if it's different than the last SerialIo access.
667 IN EFI_DEBUGPORT_PROTOCOL *This
670 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
671 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
672 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
677 UINT32 SerialControl
;
678 DEBUGPORT_DEVICE
*DebugPortDevice
;
680 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
682 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
683 DebugPortDevice
->SerialIoBinding
,
687 if (!EFI_ERROR (Status
)) {
688 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
689 Status
= EFI_NOT_READY
;
691 Status
= EFI_SUCCESS
;
698 // Misc. functions local to this module..
702 GetDebugPortVariable (
703 DEBUGPORT_DEVICE
*DebugPortDevice
708 Local worker function to obtain device path information from DebugPort variable.
709 Records requested settings in DebugPort device structure.
712 DEBUGPORT_DEVICE *DebugPortDevice,
721 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
726 Status
= gRT
->GetVariable (
727 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
728 &gEfiDebugPortVariableGuid
,
731 DebugPortDevice
->DebugPortVariable
734 if (Status
== EFI_BUFFER_TOO_SMALL
) {
735 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
736 gBS
->FreePool (gDebugPortDevice
->DebugPortVariable
);
739 DebugPortDevice
->DebugPortVariable
= AllocatePool (DataSize
);
740 if (DebugPortDevice
->DebugPortVariable
!= NULL
) {
742 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
743 &gEfiDebugPortVariableGuid
,
746 DebugPortDevice
->DebugPortVariable
748 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DebugPortDevice
->DebugPortVariable
;
749 while (!EfiIsDevicePathEnd (DevicePath
) && !EfiIsUartDevicePath (DevicePath
)) {
750 DevicePath
= EfiNextDevicePathNode (DevicePath
);
753 if (EfiIsDevicePathEnd (DevicePath
)) {
754 gBS
->FreePool (gDebugPortDevice
->DebugPortVariable
);
755 DebugPortDevice
->DebugPortVariable
= NULL
;
758 &DebugPortDevice
->BaudRate
,
759 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
760 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
762 DebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
763 DebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
765 &DebugPortDevice
->Parity
,
766 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
767 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
770 &DebugPortDevice
->DataBits
,
771 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
772 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
775 &DebugPortDevice
->StopBits
,
776 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
777 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
787 EFI_HANDLE ImageHandle
792 Unload function that is registered in the LoadImage protocol. It un-installs
793 protocols produced and deallocates pool used by the driver. Called by the core
794 when unloading the driver.
797 EFI_HANDLE ImageHandle
807 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
811 Status
= gBS
->UninstallMultipleProtocolInterfaces (
813 &gEfiDriverBindingProtocolGuid
,
814 &gDebugPortDevice
->DriverBindingInterface
,
815 &gEfiComponentNameProtocolGuid
,
816 &gDebugPortDevice
->ComponentNameInterface
,
820 if (EFI_ERROR (Status
)) {
824 // Clean up allocations
826 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
827 gBS
->FreePool (gDebugPortDevice
->DebugPortVariable
);
830 gBS
->FreePool (gDebugPortDevice
);