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 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "DebugPort.h"
23 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
27 DEBUGPORT_DRIVER_VERSION
,
32 DEBUGPORT_DEVICE mDebugPortDevice
= {
33 DEBUGPORT_DEVICE_SIGNATURE
,
36 (EFI_DEVICE_PATH_PROTOCOL
*) NULL
,
44 (EFI_SERIAL_IO_PROTOCOL
*) NULL
,
45 DEBUGPORT_UART_DEFAULT_BAUDRATE
,
46 DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
,
47 DEBUGPORT_UART_DEFAULT_TIMEOUT
,
48 (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
,
49 DEBUGPORT_UART_DEFAULT_DATA_BITS
,
50 (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
54 Local worker function to obtain device path information from DebugPort variable.
56 Records requested settings in DebugPort device structure.
59 EFI_DEVICE_PATH_PROTOCOL
*
60 GetDebugPortVariable (
65 EFI_DEVICE_PATH_PROTOCOL
*DebugPortVariable
;
66 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
68 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME
, &gEfiDebugPortVariableGuid
, (VOID
**) &DebugPortVariable
, &DataSize
);
69 if (DebugPortVariable
== NULL
) {
73 DevicePath
= DebugPortVariable
;
74 while (!IsDevicePathEnd (DevicePath
) && !IS_UART_DEVICEPATH (DevicePath
)) {
75 DevicePath
= NextDevicePathNode (DevicePath
);
78 if (IsDevicePathEnd (DevicePath
)) {
79 FreePool (DebugPortVariable
);
83 &mDebugPortDevice
.BaudRate
,
84 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
85 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
87 mDebugPortDevice
.ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
88 mDebugPortDevice
.Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
90 &mDebugPortDevice
.Parity
,
91 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
92 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
95 &mDebugPortDevice
.DataBits
,
96 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
97 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
100 &mDebugPortDevice
.StopBits
,
101 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
102 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
104 return DebugPortVariable
;
109 Debug Port Driver entry point.
111 Reads DebugPort variable to determine what device and settings to use as the
112 debug port. Binds exclusively to SerialIo. Reverts to defaults if no variable
115 @param[in] ImageHandle The firmware allocated handle for the EFI image.
116 @param[in] SystemTable A pointer to the EFI System Table.
118 @retval EFI_SUCCESS The entry point is executed successfully.
119 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
120 @retval other Some error occurs when executing this entry point.
125 InitializeDebugPortDriver (
126 IN EFI_HANDLE ImageHandle
,
127 IN EFI_SYSTEM_TABLE
*SystemTable
133 // Install driver model protocol(s).
135 Status
= EfiLibInstallDriverBindingComponentName2 (
138 &gDebugPortDriverBinding
,
140 &gDebugPortComponentName
,
141 &gDebugPortComponentName2
143 ASSERT_EFI_ERROR (Status
);
149 Checks to see if there's not already a DebugPort interface somewhere.
151 If there's a DEBUGPORT variable, the device path must match exactly. If there's
152 no DEBUGPORT variable, then device path is not checked and does not matter.
153 Checks to see that there's a serial io interface on the controller handle
154 that can be bound BY_DRIVER | EXCLUSIVE.
155 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
156 or other error returned by OpenProtocol.
158 @param This Protocol instance pointer.
159 @param ControllerHandle Handle of device to test.
160 @param RemainingDevicePath Optional parameter use to pick a specific child
163 @retval EFI_SUCCESS This driver supports this device.
164 @retval EFI_UNSUPPORTED Debug Port device is not supported.
165 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
166 @retval others Some error occurs.
172 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
173 IN EFI_HANDLE ControllerHandle
,
174 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
178 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
179 EFI_DEVICE_PATH_PROTOCOL
*DebugPortVariable
;
180 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
181 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
182 EFI_HANDLE TempHandle
;
185 // Check to see that there's not a debugport protocol already published,
186 // since only one standard UART serial port could be supported by this driver.
188 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
189 return EFI_UNSUPPORTED
;
192 // Read DebugPort variable to determine debug port selection and parameters
194 DebugPortVariable
= GetDebugPortVariable ();
196 if (DebugPortVariable
!= NULL
) {
198 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
199 // the closest matching handle matches the controller handle, and if it does,
200 // check to see that the remaining device path has the DebugPort GUIDed messaging
201 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
203 DevicePath
= DebugPortVariable
;
204 Status
= gBS
->LocateDevicePath (
205 &gEfiSerialIoProtocolGuid
,
210 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
211 Status
= EFI_UNSUPPORTED
;
214 if (Status
== EFI_SUCCESS
&&
215 (DevicePath
->Type
!= MESSAGING_DEVICE_PATH
||
216 DevicePath
->SubType
!= MSG_VENDOR_DP
||
217 *((UINT16
*) DevicePath
->Length
) != sizeof (DEBUGPORT_DEVICE_PATH
))) {
219 Status
= EFI_UNSUPPORTED
;
222 if (Status
== EFI_SUCCESS
&& !CompareGuid (&gEfiDebugPortDevicePathGuid
, (GUID
*) (DevicePath
+ 1))) {
223 Status
= EFI_UNSUPPORTED
;
226 FreePool (DebugPortVariable
);
227 if (EFI_ERROR (Status
)) {
232 Status
= gBS
->OpenProtocol (
234 &gEfiSerialIoProtocolGuid
,
236 This
->DriverBindingHandle
,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
240 if (EFI_ERROR (Status
)) {
244 Status
= gBS
->CloseProtocol (
246 &gEfiSerialIoProtocolGuid
,
247 This
->DriverBindingHandle
,
255 Binds exclusively to serial io on the controller handle, Produces DebugPort
256 protocol and DevicePath on new handle.
258 @param This Protocol instance pointer.
259 @param ControllerHandle Handle of device to bind driver to.
260 @param RemainingDevicePath Optional parameter use to pick a specific child
263 @retval EFI_SUCCESS This driver is added to ControllerHandle.
264 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
265 @retval others Some error occurs.
271 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
272 IN EFI_HANDLE ControllerHandle
,
273 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
277 DEBUGPORT_DEVICE_PATH DebugPortDP
;
278 EFI_DEVICE_PATH_PROTOCOL EndDP
;
279 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
281 Status
= gBS
->OpenProtocol (
283 &gEfiSerialIoProtocolGuid
,
284 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
285 This
->DriverBindingHandle
,
287 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
289 if (EFI_ERROR (Status
)) {
293 mDebugPortDevice
.SerialIoDeviceHandle
= ControllerHandle
;
296 // Initialize the Serial Io interface...
298 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
299 mDebugPortDevice
.SerialIoBinding
,
300 mDebugPortDevice
.BaudRate
,
301 mDebugPortDevice
.ReceiveFifoDepth
,
302 mDebugPortDevice
.Timeout
,
303 mDebugPortDevice
.Parity
,
304 mDebugPortDevice
.DataBits
,
305 mDebugPortDevice
.StopBits
307 if (EFI_ERROR (Status
)) {
308 mDebugPortDevice
.BaudRate
= 0;
309 mDebugPortDevice
.Parity
= DefaultParity
;
310 mDebugPortDevice
.DataBits
= 0;
311 mDebugPortDevice
.StopBits
= DefaultStopBits
;
312 mDebugPortDevice
.ReceiveFifoDepth
= 0;
313 Status
= mDebugPortDevice
.SerialIoBinding
->SetAttributes (
314 mDebugPortDevice
.SerialIoBinding
,
315 mDebugPortDevice
.BaudRate
,
316 mDebugPortDevice
.ReceiveFifoDepth
,
317 mDebugPortDevice
.Timeout
,
318 mDebugPortDevice
.Parity
,
319 mDebugPortDevice
.DataBits
,
320 mDebugPortDevice
.StopBits
322 if (EFI_ERROR (Status
)) {
325 &gEfiSerialIoProtocolGuid
,
326 This
->DriverBindingHandle
,
333 mDebugPortDevice
.SerialIoBinding
->Reset (mDebugPortDevice
.SerialIoBinding
);
336 // Create device path instance for DebugPort
338 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
339 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
340 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
341 CopyGuid (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
);
343 Dp1
= DevicePathFromHandle (ControllerHandle
);
346 SetDevicePathEndNode (Dp1
);
349 mDebugPortDevice
.DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
350 if (mDebugPortDevice
.DebugPortDevicePath
== NULL
) {
351 return EFI_OUT_OF_RESOURCES
;
354 // Publish DebugPort and Device Path protocols
356 Status
= gBS
->InstallMultipleProtocolInterfaces (
357 &mDebugPortDevice
.DebugPortDeviceHandle
,
358 &gEfiDevicePathProtocolGuid
,
359 mDebugPortDevice
.DebugPortDevicePath
,
360 &gEfiDebugPortProtocolGuid
,
361 &mDebugPortDevice
.DebugPortInterface
,
365 if (EFI_ERROR (Status
)) {
368 &gEfiSerialIoProtocolGuid
,
369 This
->DriverBindingHandle
,
375 // Connect debugport child to serial io
377 Status
= gBS
->OpenProtocol (
379 &gEfiSerialIoProtocolGuid
,
380 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
381 This
->DriverBindingHandle
,
382 mDebugPortDevice
.DebugPortDeviceHandle
,
383 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
386 if (EFI_ERROR (Status
)) {
389 &gEfiSerialIoProtocolGuid
,
390 This
->DriverBindingHandle
,
400 Stop this driver on ControllerHandle by removing Serial IO protocol on
401 the ControllerHandle.
403 @param This Protocol instance pointer.
404 @param ControllerHandle Handle of device to stop driver on
405 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
406 children is zero stop the entire bus driver.
407 @param ChildHandleBuffer List of Child Handles to Stop.
409 @retval EFI_SUCCESS This driver is removed ControllerHandle.
410 @retval other This driver was not removed from this device.
416 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
417 IN EFI_HANDLE ControllerHandle
,
418 IN UINTN NumberOfChildren
,
419 IN EFI_HANDLE
*ChildHandleBuffer
424 if (NumberOfChildren
== 0) {
426 // Close the bus driver
430 &gEfiSerialIoProtocolGuid
,
431 This
->DriverBindingHandle
,
435 mDebugPortDevice
.SerialIoBinding
= NULL
;
439 &gEfiDevicePathProtocolGuid
,
440 This
->DriverBindingHandle
,
444 FreePool (mDebugPortDevice
.DebugPortDevicePath
);
449 // Disconnect SerialIo child handle
451 Status
= gBS
->CloseProtocol (
452 mDebugPortDevice
.SerialIoDeviceHandle
,
453 &gEfiSerialIoProtocolGuid
,
454 This
->DriverBindingHandle
,
455 mDebugPortDevice
.DebugPortDeviceHandle
458 if (EFI_ERROR (Status
)) {
462 // Unpublish our protocols (DevicePath, DebugPort)
464 Status
= gBS
->UninstallMultipleProtocolInterfaces (
465 mDebugPortDevice
.DebugPortDeviceHandle
,
466 &gEfiDevicePathProtocolGuid
,
467 mDebugPortDevice
.DebugPortDevicePath
,
468 &gEfiDebugPortProtocolGuid
,
469 &mDebugPortDevice
.DebugPortInterface
,
473 if (EFI_ERROR (Status
)) {
476 &gEfiSerialIoProtocolGuid
,
477 (VOID
**) &mDebugPortDevice
.SerialIoBinding
,
478 This
->DriverBindingHandle
,
479 mDebugPortDevice
.DebugPortDeviceHandle
,
480 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
483 mDebugPortDevice
.DebugPortDeviceHandle
= NULL
;
491 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
492 We cannot call SerialIo:SetAttributes because it uses pool services, which use
493 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
494 SerialIo:Reset() calls SetAttributes, so it can't be used either.
496 The port itself should be fine since it was set up during initialization.
498 @param This Protocol instance pointer.
500 @return EFI_SUCCESS Always.
506 IN EFI_DEBUGPORT_PROTOCOL
*This
512 while (This
->Poll (This
) == EFI_SUCCESS
) {
514 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
521 DebugPort protocol member function. Calls SerialIo:Read() after setting
522 if it's different than the last SerialIo access.
524 @param This Pointer to DebugPort protocol.
525 @param Timeout Timeout value.
526 @param BufferSize On input, the size of Buffer.
527 On output, the amount of data actually written.
528 @param Buffer Pointer to buffer to read.
537 IN EFI_DEBUGPORT_PROTOCOL
*This
,
539 IN OUT UINTN
*BufferSize
,
543 DEBUGPORT_DEVICE
*DebugPortDevice
;
544 UINTN LocalBufferSize
;
548 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
550 LocalBufferSize
= *BufferSize
;
553 Status
= DebugPortDevice
->SerialIoBinding
->Read (
554 DebugPortDevice
->SerialIoBinding
,
558 if (Status
== EFI_TIMEOUT
) {
559 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
560 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
564 } else if (EFI_ERROR (Status
)) {
568 BufferPtr
+= LocalBufferSize
;
569 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
570 } while (LocalBufferSize
!= 0 && Timeout
> 0);
572 *BufferSize
= (UINTN
) BufferPtr
- (UINTN
) Buffer
;
578 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
579 a time and does a GetControl between 8 byte writes to help insure reads are
580 interspersed This is poor-man's flow control.
582 @param This Pointer to DebugPort protocol.
583 @param Timeout Timeout value.
584 @param BufferSize On input, the size of Buffer.
585 On output, the amount of data actually written.
586 @param Buffer Pointer to buffer to read.
588 @retval EFI_SUCCESS The data was written.
589 @retval others Fails when writting datas to debug port device.
595 IN EFI_DEBUGPORT_PROTOCOL
*This
,
597 IN OUT UINTN
*BufferSize
,
601 DEBUGPORT_DEVICE
*DebugPortDevice
;
605 UINT32 SerialControl
;
607 Status
= EFI_SUCCESS
;
608 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
611 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
612 DebugPortDevice
->SerialIoBinding
->GetControl (
613 DebugPortDevice
->SerialIoBinding
,
616 if (*BufferSize
- Position
< 8) {
617 WriteSize
= *BufferSize
- Position
;
620 Status
= DebugPortDevice
->SerialIoBinding
->Write (
621 DebugPortDevice
->SerialIoBinding
,
623 &((UINT8
*) Buffer
)[Position
]
627 *BufferSize
= Position
;
632 DebugPort protocol member function. Calls SerialIo:Write() after setting
633 if it's different than the last SerialIo access.
635 @param This Pointer to DebugPort protocol.
637 @retval EFI_SUCCESS At least 1 character is ready to be read from
638 the DebugPort interface.
639 @retval EFI_NOT_READY There are no characters ready to read from the
641 @retval EFI_DEVICE_ERROR A hardware failure occured... (from SerialIo)
647 IN EFI_DEBUGPORT_PROTOCOL
*This
651 UINT32 SerialControl
;
652 DEBUGPORT_DEVICE
*DebugPortDevice
;
654 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
656 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
657 DebugPortDevice
->SerialIoBinding
,
661 if (!EFI_ERROR (Status
)) {
662 if ((SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
663 Status
= EFI_NOT_READY
;
665 Status
= EFI_SUCCESS
;
673 Unload function that is registered in the LoadImage protocol. It un-installs
674 protocols produced and deallocates pool used by the driver. Called by the core
675 when unloading the driver.
679 @retval EFI_SUCCESS Unload Debug Port driver successfully.
680 @retval EFI_ABORTED Serial IO is still binding.
686 EFI_HANDLE ImageHandle
691 VOID
*ComponentName2
;
693 if (mDebugPortDevice
.SerialIoBinding
!= NULL
) {
698 // Driver is stopped already.
700 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentNameProtocolGuid
, &ComponentName
);
701 if (EFI_ERROR (Status
)) {
702 ComponentName
= NULL
;
705 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiComponentName2ProtocolGuid
, &ComponentName2
);
706 if (EFI_ERROR (Status
)) {
707 ComponentName2
= NULL
;
710 if (ComponentName
== NULL
) {
711 if (ComponentName2
== NULL
) {
712 Status
= gBS
->UninstallMultipleProtocolInterfaces (
714 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
718 Status
= gBS
->UninstallMultipleProtocolInterfaces (
720 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
721 &gEfiComponentName2ProtocolGuid
, ComponentName2
,
726 if (ComponentName2
== NULL
) {
727 Status
= gBS
->UninstallMultipleProtocolInterfaces (
729 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
730 &gEfiComponentNameProtocolGuid
, ComponentName
,
734 Status
= gBS
->UninstallMultipleProtocolInterfaces (
736 &gEfiDriverBindingProtocolGuid
, &gDebugPortDriverBinding
,
737 &gEfiComponentNameProtocolGuid
, ComponentName
,
738 &gEfiComponentName2ProtocolGuid
, ComponentName2
,