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
;
186 // Read DebugPort variable to determine debug port selection and parameters
188 DebugPortVariable
= GetDebugPortVariable ();
190 if (DebugPortVariable
!= NULL
) {
192 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
193 // the closest matching handle matches the controller handle, and if it does,
194 // check to see that the remaining device path has the DebugPort GUIDed messaging
195 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
197 DevicePath
= DebugPortVariable
;
198 Status
= gBS
->LocateDevicePath (
199 &gEfiSerialIoProtocolGuid
,
204 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
205 Status
= EFI_UNSUPPORTED
;
208 if (Status
== EFI_SUCCESS
&&
209 (DevicePath
->Type
!= MESSAGING_DEVICE_PATH
||
210 DevicePath
->SubType
!= MSG_VENDOR_DP
||
211 *((UINT16
*) DevicePath
->Length
) != sizeof (DEBUGPORT_DEVICE_PATH
))) {
213 Status
= EFI_UNSUPPORTED
;
216 if (Status
== EFI_SUCCESS
&& !CompareGuid (&gEfiDebugPortDevicePathGuid
, (GUID
*) (DevicePath
+ 1))) {
217 Status
= EFI_UNSUPPORTED
;
220 FreePool (DebugPortVariable
);
221 if (EFI_ERROR (Status
)) {
226 Status
= gBS
->OpenProtocol (
228 &gEfiSerialIoProtocolGuid
,
230 This
->DriverBindingHandle
,
232 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
234 if (EFI_ERROR (Status
)) {
238 Status
= gBS
->CloseProtocol (
240 &gEfiSerialIoProtocolGuid
,
241 This
->DriverBindingHandle
,
249 Binds exclusively to serial io on the controller handle, Produces DebugPort
250 protocol and DevicePath on new handle.
252 @param This Protocol instance pointer.
253 @param ControllerHandle Handle of device to bind driver to.
254 @param RemainingDevicePath Optional parameter use to pick a specific child
257 @retval EFI_SUCCESS This driver is added to ControllerHandle.
258 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
259 @retval others Some error occurs.
265 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
266 IN EFI_HANDLE ControllerHandle
,
267 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
271 DEBUGPORT_DEVICE_PATH DebugPortDP
;
272 EFI_DEVICE_PATH_PROTOCOL EndDP
;
273 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
275 Status
= gBS
->OpenProtocol (
277 &gEfiSerialIoProtocolGuid
,
278 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
279 This
->DriverBindingHandle
,
281 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
283 if (EFI_ERROR (Status
)) {
287 mDebugPortDevice
.SerialIoDeviceHandle
= ControllerHandle
;
290 // Initialize the Serial Io interface...
292 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
293 mDebugPortDevice
.SerialIoBinding
,
294 mDebugPortDevice
.BaudRate
,
295 mDebugPortDevice
.ReceiveFifoDepth
,
296 mDebugPortDevice
.Timeout
,
297 mDebugPortDevice
.Parity
,
298 mDebugPortDevice
.DataBits
,
299 mDebugPortDevice
.StopBits
301 if (EFI_ERROR (Status
)) {
302 mDebugPortDevice
.BaudRate
= 0;
303 mDebugPortDevice
.Parity
= DefaultParity
;
304 mDebugPortDevice
.DataBits
= 0;
305 mDebugPortDevice
.StopBits
= DefaultStopBits
;
306 mDebugPortDevice
.ReceiveFifoDepth
= 0;
307 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
308 mDebugPortDevice
.SerialIoBinding
,
309 mDebugPortDevice
.BaudRate
,
310 mDebugPortDevice
.ReceiveFifoDepth
,
311 mDebugPortDevice
.Timeout
,
312 mDebugPortDevice
.Parity
,
313 mDebugPortDevice
.DataBits
,
314 mDebugPortDevice
.StopBits
316 if (EFI_ERROR (Status
)) {
319 &gEfiSerialIoProtocolGuid
,
320 This
->DriverBindingHandle
,
327 mDebugPortDevice
.SerialIoBinding
->Reset (mDebugPortDevice
.SerialIoBinding
);
330 // Create device path instance for DebugPort
332 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
333 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
334 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
335 CopyGuid (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
);
337 Dp1
= DevicePathFromHandle (ControllerHandle
);
340 SetDevicePathEndNode (Dp1
);
343 mDebugPortDevice
.DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
344 if (mDebugPortDevice
.DebugPortDevicePath
== NULL
) {
345 return EFI_OUT_OF_RESOURCES
;
348 // Publish DebugPort and Device Path protocols
350 Status
= gBS
->InstallMultipleProtocolInterfaces (
351 &mDebugPortDevice
.DebugPortDeviceHandle
,
352 &gEfiDevicePathProtocolGuid
,
353 mDebugPortDevice
.DebugPortDevicePath
,
354 &gEfiDebugPortProtocolGuid
,
355 &mDebugPortDevice
.DebugPortInterface
,
359 if (EFI_ERROR (Status
)) {
362 &gEfiSerialIoProtocolGuid
,
363 This
->DriverBindingHandle
,
369 // Connect debugport child to serial io
371 Status
= gBS
->OpenProtocol (
373 &gEfiSerialIoProtocolGuid
,
374 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
375 This
->DriverBindingHandle
,
376 mDebugPortDevice
.DebugPortDeviceHandle
,
377 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
380 if (EFI_ERROR (Status
)) {
383 &gEfiSerialIoProtocolGuid
,
384 This
->DriverBindingHandle
,
394 Stop this driver on ControllerHandle by removing Serial IO protocol on
395 the ControllerHandle.
397 @param This Protocol instance pointer.
398 @param ControllerHandle Handle of device to stop driver on
399 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
400 children is zero stop the entire bus driver.
401 @param ChildHandleBuffer List of Child Handles to Stop.
403 @retval EFI_SUCCESS This driver is removed ControllerHandle.
404 @retval other This driver was not removed from this device.
410 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
411 IN EFI_HANDLE ControllerHandle
,
412 IN UINTN NumberOfChildren
,
413 IN EFI_HANDLE
*ChildHandleBuffer
418 if (NumberOfChildren
== 0) {
420 // Close the bus driver
424 &gEfiSerialIoProtocolGuid
,
425 This
->DriverBindingHandle
,
429 mDebugPortDevice
.SerialIoBinding
= NULL
;
433 &gEfiDevicePathProtocolGuid
,
434 This
->DriverBindingHandle
,
438 FreePool (mDebugPortDevice
.DebugPortDevicePath
);
443 // Disconnect SerialIo child handle
445 Status
= gBS
->CloseProtocol (
446 mDebugPortDevice
.SerialIoDeviceHandle
,
447 &gEfiSerialIoProtocolGuid
,
448 This
->DriverBindingHandle
,
449 mDebugPortDevice
.DebugPortDeviceHandle
452 if (EFI_ERROR (Status
)) {
456 // Unpublish our protocols (DevicePath, DebugPort)
458 Status
= gBS
->UninstallMultipleProtocolInterfaces (
459 mDebugPortDevice
.DebugPortDeviceHandle
,
460 &gEfiDevicePathProtocolGuid
,
461 mDebugPortDevice
.DebugPortDevicePath
,
462 &gEfiDebugPortProtocolGuid
,
463 &mDebugPortDevice
.DebugPortInterface
,
467 if (EFI_ERROR (Status
)) {
470 &gEfiSerialIoProtocolGuid
,
471 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
472 This
->DriverBindingHandle
,
473 mDebugPortDevice
.DebugPortDeviceHandle
,
474 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
477 mDebugPortDevice
.DebugPortDeviceHandle
= NULL
;
485 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
486 We cannot call SerialIo:SetAttributes because it uses pool services, which use
487 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
488 SerialIo:Reset() calls SetAttributes, so it can't be used either.
490 The port itself should be fine since it was set up during initialization.
492 @param This Protocol instance pointer.
494 @return EFI_SUCCESS Always.
500 IN EFI_DEBUGPORT_PROTOCOL
*This
506 while (This
->Poll (This
) == EFI_SUCCESS
) {
508 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
515 DebugPort protocol member function. Calls SerialIo:Read() after setting
516 if it's different than the last SerialIo access.
518 @param This Pointer to DebugPort protocol.
519 @param Timeout Timeout value.
520 @param BufferSize On input, the size of Buffer.
521 On output, the amount of data actually written.
522 @param Buffer Pointer to buffer to read.
531 IN EFI_DEBUGPORT_PROTOCOL
*This
,
533 IN OUT UINTN
*BufferSize
,
537 DEBUGPORT_DEVICE
*DebugPortDevice
;
538 UINTN LocalBufferSize
;
542 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
544 LocalBufferSize
= *BufferSize
;
547 Status
= DebugPortDevice
->SerialIoBinding
->Read (
548 DebugPortDevice
->SerialIoBinding
,
552 if (Status
== EFI_TIMEOUT
) {
553 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
554 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
558 } else if (EFI_ERROR (Status
)) {
562 BufferPtr
+= LocalBufferSize
;
563 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
564 } while (LocalBufferSize
!= 0 && Timeout
> 0);
566 *BufferSize
= (UINTN
) BufferPtr
- (UINTN
) Buffer
;
572 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
573 a time and does a GetControl between 8 byte writes to help insure reads are
574 interspersed This is poor-man's flow control.
576 @param This Pointer to DebugPort protocol.
577 @param Timeout Timeout value.
578 @param BufferSize On input, the size of Buffer.
579 On output, the amount of data actually written.
580 @param Buffer Pointer to buffer to read.
582 @retval EFI_SUCCESS The data was written.
583 @retval others Fails when writting datas to debug port device.
589 IN EFI_DEBUGPORT_PROTOCOL
*This
,
591 IN OUT UINTN
*BufferSize
,
595 DEBUGPORT_DEVICE
*DebugPortDevice
;
599 UINT32 SerialControl
;
601 Status
= EFI_SUCCESS
;
602 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
605 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
606 DebugPortDevice
->SerialIoBinding
->GetControl (
607 DebugPortDevice
->SerialIoBinding
,
610 if (*BufferSize
- Position
< 8) {
611 WriteSize
= *BufferSize
- Position
;
614 Status
= DebugPortDevice
->SerialIoBinding
->Write (
615 DebugPortDevice
->SerialIoBinding
,
617 &((UINT8
*) Buffer
)[Position
]
621 *BufferSize
= Position
;
626 DebugPort protocol member function. Calls SerialIo:Write() after setting
627 if it's different than the last SerialIo access.
629 @param This Pointer to DebugPort protocol.
631 @retval EFI_SUCCESS At least 1 character is ready to be read from
632 the DebugPort interface.
633 @retval EFI_NOT_READY There are no characters ready to read from the
635 @retval EFI_DEVICE_ERROR A hardware failure occured... (from SerialIo)
641 IN EFI_DEBUGPORT_PROTOCOL
*This
645 UINT32 SerialControl
;
646 DEBUGPORT_DEVICE
*DebugPortDevice
;
648 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
650 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
651 DebugPortDevice
->SerialIoBinding
,
655 if (!EFI_ERROR (Status
)) {
656 if ((SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
657 Status
= EFI_NOT_READY
;
659 Status
= EFI_SUCCESS
;
667 Unload function that is registered in the LoadImage protocol. It un-installs
668 protocols produced and deallocates pool used by the driver. Called by the core
669 when unloading the driver.
673 @retval EFI_SUCCESS Unload Debug Port driver successfully.
674 @retval EFI_ABORTED Serial IO is still binding.
680 EFI_HANDLE ImageHandle
685 VOID
*ComponentName2
;
687 if (mDebugPortDevice
.SerialIoBinding
!= NULL
) {
692 // Driver is stopped already.
694 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentNameProtocolGuid
, &ComponentName
);
695 if (EFI_ERROR (Status
)) {
696 ComponentName
= NULL
;
699 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentName2ProtocolGuid
, &ComponentName2
);
700 if (EFI_ERROR (Status
)) {
701 ComponentName2
= NULL
;
704 if (ComponentName
== NULL
) {
705 if (ComponentName2
== NULL
) {
706 Status
= gBS
->UninstallMultipleProtocolInterfaces (
708 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
712 Status
= gBS
->UninstallMultipleProtocolInterfaces (
714 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
715 &gEfiComponentName2ProtocolGuid
, ComponentName2
,
720 if (ComponentName2
== NULL
) {
721 Status
= gBS
->UninstallMultipleProtocolInterfaces (
723 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
724 &gEfiComponentNameProtocolGuid
, ComponentName
,
728 Status
= gBS
->UninstallMultipleProtocolInterfaces (
730 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
731 &gEfiComponentNameProtocolGuid
, ComponentName
,
732 &gEfiComponentName2ProtocolGuid
, ComponentName2
,