2 Top level C file for debugport driver. Contains initialization function.
3 This driver layers on top of SerialIo.
4 ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM
7 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "DebugPort.h"
17 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
21 DEBUGPORT_DRIVER_VERSION
,
26 DEBUGPORT_DEVICE mDebugPortDevice
= {
27 DEBUGPORT_DEVICE_SIGNATURE
,
30 (EFI_DEVICE_PATH_PROTOCOL
*)NULL
,
38 (EFI_SERIAL_IO_PROTOCOL
*)NULL
,
39 DEBUGPORT_UART_DEFAULT_BAUDRATE
,
40 DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
,
41 DEBUGPORT_UART_DEFAULT_TIMEOUT
,
42 (EFI_PARITY_TYPE
)DEBUGPORT_UART_DEFAULT_PARITY
,
43 DEBUGPORT_UART_DEFAULT_DATA_BITS
,
44 (EFI_STOP_BITS_TYPE
)DEBUGPORT_UART_DEFAULT_STOP_BITS
48 Local worker function to obtain device path information from DebugPort variable.
50 Records requested settings in DebugPort device structure.
53 EFI_DEVICE_PATH_PROTOCOL
*
54 GetDebugPortVariable (
59 EFI_DEVICE_PATH_PROTOCOL
*DebugPortVariable
;
60 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
62 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME
, &gEfiDebugPortVariableGuid
, (VOID
**)&DebugPortVariable
, &DataSize
);
63 if (DebugPortVariable
== NULL
) {
67 DevicePath
= DebugPortVariable
;
68 while (!IsDevicePathEnd (DevicePath
) && !IS_UART_DEVICEPATH (DevicePath
)) {
69 DevicePath
= NextDevicePathNode (DevicePath
);
72 if (IsDevicePathEnd (DevicePath
)) {
73 FreePool (DebugPortVariable
);
77 &mDebugPortDevice
.BaudRate
,
78 &((UART_DEVICE_PATH
*)DevicePath
)->BaudRate
,
79 sizeof (((UART_DEVICE_PATH
*)DevicePath
)->BaudRate
)
81 mDebugPortDevice
.ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
82 mDebugPortDevice
.Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
84 &mDebugPortDevice
.Parity
,
85 &((UART_DEVICE_PATH
*)DevicePath
)->Parity
,
86 sizeof (((UART_DEVICE_PATH
*)DevicePath
)->Parity
)
89 &mDebugPortDevice
.DataBits
,
90 &((UART_DEVICE_PATH
*)DevicePath
)->DataBits
,
91 sizeof (((UART_DEVICE_PATH
*)DevicePath
)->DataBits
)
94 &mDebugPortDevice
.StopBits
,
95 &((UART_DEVICE_PATH
*)DevicePath
)->StopBits
,
96 sizeof (((UART_DEVICE_PATH
*)DevicePath
)->StopBits
)
98 return DebugPortVariable
;
103 Debug Port Driver entry point.
105 Reads DebugPort variable to determine what device and settings to use as the
106 debug port. Binds exclusively to SerialIo. Reverts to defaults if no variable
109 @param[in] ImageHandle The firmware allocated handle for the EFI image.
110 @param[in] SystemTable A pointer to the EFI System Table.
112 @retval EFI_SUCCESS The entry point is executed successfully.
113 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
114 @retval other Some error occurs when executing this entry point.
119 InitializeDebugPortDriver (
120 IN EFI_HANDLE ImageHandle
,
121 IN EFI_SYSTEM_TABLE
*SystemTable
127 // Install driver model protocol(s).
129 Status
= EfiLibInstallDriverBindingComponentName2 (
132 &gDebugPortDriverBinding
,
134 &gDebugPortComponentName
,
135 &gDebugPortComponentName2
137 ASSERT_EFI_ERROR (Status
);
143 Checks to see if there's not already a DebugPort interface somewhere.
145 If there's a DEBUGPORT variable, the device path must match exactly. If there's
146 no DEBUGPORT variable, then device path is not checked and does not matter.
147 Checks to see that there's a serial io interface on the controller handle
148 that can be bound BY_DRIVER | EXCLUSIVE.
149 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
150 or other error returned by OpenProtocol.
152 @param This Protocol instance pointer.
153 @param ControllerHandle Handle of device to test.
154 @param RemainingDevicePath Optional parameter use to pick a specific child
157 @retval EFI_SUCCESS This driver supports this device.
158 @retval EFI_UNSUPPORTED Debug Port device is not supported.
159 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
160 @retval others Some error occurs.
166 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
167 IN EFI_HANDLE ControllerHandle
,
168 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
172 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
173 EFI_DEVICE_PATH_PROTOCOL
*DebugPortVariable
;
174 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
175 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
176 EFI_HANDLE TempHandle
;
179 // Check to see that there's not a debugport protocol already published,
180 // since only one standard UART serial port could be supported by this driver.
182 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**)&DebugPortInterface
) != EFI_NOT_FOUND
) {
183 return EFI_UNSUPPORTED
;
187 // Read DebugPort variable to determine debug port selection and parameters
189 DebugPortVariable
= GetDebugPortVariable ();
191 if (DebugPortVariable
!= NULL
) {
193 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
194 // the closest matching handle matches the controller handle, and if it does,
195 // check to see that the remaining device path has the DebugPort GUIDed messaging
196 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
198 DevicePath
= DebugPortVariable
;
199 Status
= gBS
->LocateDevicePath (
200 &gEfiSerialIoProtocolGuid
,
205 if ((Status
== EFI_SUCCESS
) && (TempHandle
!= ControllerHandle
)) {
206 Status
= EFI_UNSUPPORTED
;
209 if ((Status
== EFI_SUCCESS
) &&
210 ((DevicePath
->Type
!= MESSAGING_DEVICE_PATH
) ||
211 (DevicePath
->SubType
!= MSG_VENDOR_DP
) ||
212 (*((UINT16
*)DevicePath
->Length
) != sizeof (DEBUGPORT_DEVICE_PATH
))))
214 Status
= EFI_UNSUPPORTED
;
217 if ((Status
== EFI_SUCCESS
) && !CompareGuid (&gEfiDebugPortDevicePathGuid
, (GUID
*)(DevicePath
+ 1))) {
218 Status
= EFI_UNSUPPORTED
;
221 FreePool (DebugPortVariable
);
222 if (EFI_ERROR (Status
)) {
227 Status
= gBS
->OpenProtocol (
229 &gEfiSerialIoProtocolGuid
,
231 This
->DriverBindingHandle
,
233 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
235 if (EFI_ERROR (Status
)) {
239 Status
= gBS
->CloseProtocol (
241 &gEfiSerialIoProtocolGuid
,
242 This
->DriverBindingHandle
,
250 Binds exclusively to serial io on the controller handle, Produces DebugPort
251 protocol and DevicePath on new handle.
253 @param This Protocol instance pointer.
254 @param ControllerHandle Handle of device to bind driver to.
255 @param RemainingDevicePath Optional parameter use to pick a specific child
258 @retval EFI_SUCCESS This driver is added to ControllerHandle.
259 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
260 @retval others Some error occurs.
266 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
267 IN EFI_HANDLE ControllerHandle
,
268 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
272 DEBUGPORT_DEVICE_PATH DebugPortDP
;
273 EFI_DEVICE_PATH_PROTOCOL EndDP
;
274 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
276 Status
= gBS
->OpenProtocol (
278 &gEfiSerialIoProtocolGuid
,
279 (VOID
**)&mDebugPortDevice
.SerialIoBinding
,
280 This
->DriverBindingHandle
,
282 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
284 if (EFI_ERROR (Status
)) {
288 mDebugPortDevice
.SerialIoDeviceHandle
= ControllerHandle
;
291 // Initialize the Serial Io interface...
293 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
294 mDebugPortDevice
.SerialIoBinding
,
295 mDebugPortDevice
.BaudRate
,
296 mDebugPortDevice
.ReceiveFifoDepth
,
297 mDebugPortDevice
.Timeout
,
298 mDebugPortDevice
.Parity
,
299 mDebugPortDevice
.DataBits
,
300 mDebugPortDevice
.StopBits
302 if (EFI_ERROR (Status
)) {
303 mDebugPortDevice
.BaudRate
= 0;
304 mDebugPortDevice
.Parity
= DefaultParity
;
305 mDebugPortDevice
.DataBits
= 0;
306 mDebugPortDevice
.StopBits
= DefaultStopBits
;
307 mDebugPortDevice
.ReceiveFifoDepth
= 0;
308 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
309 mDebugPortDevice
.SerialIoBinding
,
310 mDebugPortDevice
.BaudRate
,
311 mDebugPortDevice
.ReceiveFifoDepth
,
312 mDebugPortDevice
.Timeout
,
313 mDebugPortDevice
.Parity
,
314 mDebugPortDevice
.DataBits
,
315 mDebugPortDevice
.StopBits
317 if (EFI_ERROR (Status
)) {
320 &gEfiSerialIoProtocolGuid
,
321 This
->DriverBindingHandle
,
328 mDebugPortDevice
.SerialIoBinding
->Reset (mDebugPortDevice
.SerialIoBinding
);
331 // Create device path instance for DebugPort
333 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
334 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
335 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
336 CopyGuid (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
);
338 Dp1
= DevicePathFromHandle (ControllerHandle
);
341 SetDevicePathEndNode (Dp1
);
344 mDebugPortDevice
.DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*)&DebugPortDP
);
345 if (mDebugPortDevice
.DebugPortDevicePath
== NULL
) {
346 return EFI_OUT_OF_RESOURCES
;
350 // Publish DebugPort and Device Path protocols
352 Status
= gBS
->InstallMultipleProtocolInterfaces (
353 &mDebugPortDevice
.DebugPortDeviceHandle
,
354 &gEfiDevicePathProtocolGuid
,
355 mDebugPortDevice
.DebugPortDevicePath
,
356 &gEfiDebugPortProtocolGuid
,
357 &mDebugPortDevice
.DebugPortInterface
,
361 if (EFI_ERROR (Status
)) {
364 &gEfiSerialIoProtocolGuid
,
365 This
->DriverBindingHandle
,
372 // Connect debugport child to serial io
374 Status
= gBS
->OpenProtocol (
376 &gEfiSerialIoProtocolGuid
,
377 (VOID
**)&mDebugPortDevice
.SerialIoBinding
,
378 This
->DriverBindingHandle
,
379 mDebugPortDevice
.DebugPortDeviceHandle
,
380 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
383 if (EFI_ERROR (Status
)) {
386 &gEfiSerialIoProtocolGuid
,
387 This
->DriverBindingHandle
,
397 Stop this driver on ControllerHandle by removing Serial IO protocol on
398 the ControllerHandle.
400 @param This Protocol instance pointer.
401 @param ControllerHandle Handle of device to stop driver on
402 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
403 children is zero stop the entire bus driver.
404 @param ChildHandleBuffer List of Child Handles to Stop.
406 @retval EFI_SUCCESS This driver is removed ControllerHandle.
407 @retval other This driver was not removed from this device.
413 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
414 IN EFI_HANDLE ControllerHandle
,
415 IN UINTN NumberOfChildren
,
416 IN EFI_HANDLE
*ChildHandleBuffer
421 if (NumberOfChildren
== 0) {
423 // Close the bus driver
427 &gEfiSerialIoProtocolGuid
,
428 This
->DriverBindingHandle
,
432 mDebugPortDevice
.SerialIoBinding
= NULL
;
436 &gEfiDevicePathProtocolGuid
,
437 This
->DriverBindingHandle
,
441 FreePool (mDebugPortDevice
.DebugPortDevicePath
);
446 // Disconnect SerialIo child handle
448 Status
= gBS
->CloseProtocol (
449 mDebugPortDevice
.SerialIoDeviceHandle
,
450 &gEfiSerialIoProtocolGuid
,
451 This
->DriverBindingHandle
,
452 mDebugPortDevice
.DebugPortDeviceHandle
455 if (EFI_ERROR (Status
)) {
460 // Unpublish our protocols (DevicePath, DebugPort)
462 Status
= gBS
->UninstallMultipleProtocolInterfaces (
463 mDebugPortDevice
.DebugPortDeviceHandle
,
464 &gEfiDevicePathProtocolGuid
,
465 mDebugPortDevice
.DebugPortDevicePath
,
466 &gEfiDebugPortProtocolGuid
,
467 &mDebugPortDevice
.DebugPortInterface
,
471 if (EFI_ERROR (Status
)) {
474 &gEfiSerialIoProtocolGuid
,
475 (VOID
**)&mDebugPortDevice
.SerialIoBinding
,
476 This
->DriverBindingHandle
,
477 mDebugPortDevice
.DebugPortDeviceHandle
,
478 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
481 mDebugPortDevice
.DebugPortDeviceHandle
= NULL
;
489 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
490 We cannot call SerialIo:SetAttributes because it uses pool services, which use
491 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
492 SerialIo:Reset() calls SetAttributes, so it can't be used either.
494 The port itself should be fine since it was set up during initialization.
496 @param This Protocol instance pointer.
498 @return EFI_SUCCESS Always.
504 IN EFI_DEBUGPORT_PROTOCOL
*This
510 while (This
->Poll (This
) == EFI_SUCCESS
) {
512 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
519 DebugPort protocol member function. Calls SerialIo:Read() after setting
520 if it's different than the last SerialIo access.
522 @param This Pointer to DebugPort protocol.
523 @param Timeout Timeout value.
524 @param BufferSize On input, the size of Buffer.
525 On output, the amount of data actually written.
526 @param Buffer Pointer to buffer to read.
535 IN EFI_DEBUGPORT_PROTOCOL
*This
,
537 IN OUT UINTN
*BufferSize
,
541 DEBUGPORT_DEVICE
*DebugPortDevice
;
542 UINTN LocalBufferSize
;
546 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
548 LocalBufferSize
= *BufferSize
;
551 Status
= DebugPortDevice
->SerialIoBinding
->Read (
552 DebugPortDevice
->SerialIoBinding
,
556 if (Status
== EFI_TIMEOUT
) {
557 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
558 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
562 } else if (EFI_ERROR (Status
)) {
566 BufferPtr
+= LocalBufferSize
;
567 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*)Buffer
);
568 } while (LocalBufferSize
!= 0 && Timeout
> 0);
570 *BufferSize
= (UINTN
)BufferPtr
- (UINTN
)Buffer
;
576 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
577 a time and does a GetControl between 8 byte writes to help insure reads are
578 interspersed This is poor-man's flow control.
580 @param This Pointer to DebugPort protocol.
581 @param Timeout Timeout value.
582 @param BufferSize On input, the size of Buffer.
583 On output, the amount of data actually written.
584 @param Buffer Pointer to buffer to read.
586 @retval EFI_SUCCESS The data was written.
587 @retval others Fails when writting datas to debug port device.
593 IN EFI_DEBUGPORT_PROTOCOL
*This
,
595 IN OUT UINTN
*BufferSize
,
599 DEBUGPORT_DEVICE
*DebugPortDevice
;
603 UINT32 SerialControl
;
605 Status
= EFI_SUCCESS
;
606 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
609 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
610 DebugPortDevice
->SerialIoBinding
->GetControl (
611 DebugPortDevice
->SerialIoBinding
,
614 if (*BufferSize
- Position
< 8) {
615 WriteSize
= *BufferSize
- Position
;
618 Status
= DebugPortDevice
->SerialIoBinding
->Write (
619 DebugPortDevice
->SerialIoBinding
,
621 &((UINT8
*)Buffer
)[Position
]
625 *BufferSize
= Position
;
630 DebugPort protocol member function. Calls SerialIo:Write() after setting
631 if it's different than the last SerialIo access.
633 @param This Pointer to DebugPort protocol.
635 @retval EFI_SUCCESS At least 1 character is ready to be read from
636 the DebugPort interface.
637 @retval EFI_NOT_READY There are no characters ready to read from the
639 @retval EFI_DEVICE_ERROR A hardware failure occurred... (from SerialIo)
645 IN EFI_DEBUGPORT_PROTOCOL
*This
649 UINT32 SerialControl
;
650 DEBUGPORT_DEVICE
*DebugPortDevice
;
652 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
654 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
655 DebugPortDevice
->SerialIoBinding
,
659 if (!EFI_ERROR (Status
)) {
660 if ((SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
661 Status
= EFI_NOT_READY
;
663 Status
= EFI_SUCCESS
;
671 Unload function that is registered in the LoadImage protocol. It un-installs
672 protocols produced and deallocates pool used by the driver. Called by the core
673 when unloading the driver.
677 @retval EFI_SUCCESS Unload Debug Port driver successfully.
678 @retval EFI_ABORTED Serial IO is still binding.
684 EFI_HANDLE ImageHandle
689 VOID
*ComponentName2
;
691 if (mDebugPortDevice
.SerialIoBinding
!= NULL
) {
696 // Driver is stopped already.
698 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentNameProtocolGuid
, &ComponentName
);
699 if (EFI_ERROR (Status
)) {
700 ComponentName
= NULL
;
703 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentName2ProtocolGuid
, &ComponentName2
);
704 if (EFI_ERROR (Status
)) {
705 ComponentName2
= NULL
;
708 if (ComponentName
== NULL
) {
709 if (ComponentName2
== NULL
) {
710 Status
= gBS
->UninstallMultipleProtocolInterfaces (
712 &gEfiDriverBindingProtocolGuid
,
713 &gDebugPortDriverBinding
,
717 Status
= gBS
->UninstallMultipleProtocolInterfaces (
719 &gEfiDriverBindingProtocolGuid
,
720 &gDebugPortDriverBinding
,
721 &gEfiComponentName2ProtocolGuid
,
727 if (ComponentName2
== NULL
) {
728 Status
= gBS
->UninstallMultipleProtocolInterfaces (
730 &gEfiDriverBindingProtocolGuid
,
731 &gDebugPortDriverBinding
,
732 &gEfiComponentNameProtocolGuid
,
737 Status
= gBS
->UninstallMultipleProtocolInterfaces (
739 &gEfiDriverBindingProtocolGuid
,
740 &gDebugPortDriverBinding
,
741 &gEfiComponentNameProtocolGuid
,
743 &gEfiComponentName2ProtocolGuid
,