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 - 2008, Intel Corporation. <BR>
8 All rights reserved. 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
*gDebugPortDevice
;
35 Local worker function to obtain device path information from DebugPort variable.
37 Records requested settings in DebugPort device structure.
39 @param DebugPortDevice Pointer to instance of dubug port device.
43 GetDebugPortVariable (
44 DEBUGPORT_DEVICE
*DebugPortDevice
48 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
53 Status
= gRT
->GetVariable (
54 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
55 &gEfiDebugPortVariableGuid
,
58 DebugPortDevice
->DebugPortVariable
61 if (Status
== EFI_BUFFER_TOO_SMALL
) {
62 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
63 FreePool (gDebugPortDevice
->DebugPortVariable
);
66 DebugPortDevice
->DebugPortVariable
= AllocatePool (DataSize
);
67 if (DebugPortDevice
->DebugPortVariable
!= NULL
) {
69 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
70 &gEfiDebugPortVariableGuid
,
73 DebugPortDevice
->DebugPortVariable
75 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DebugPortDevice
->DebugPortVariable
;
76 while (!EfiIsDevicePathEnd (DevicePath
) && !IS_UART_DEVICEPATH (DevicePath
)) {
77 DevicePath
= EfiNextDevicePathNode (DevicePath
);
80 if (EfiIsDevicePathEnd (DevicePath
)) {
81 FreePool (gDebugPortDevice
->DebugPortVariable
);
82 DebugPortDevice
->DebugPortVariable
= NULL
;
85 &DebugPortDevice
->BaudRate
,
86 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
87 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
89 DebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
90 DebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
92 &DebugPortDevice
->Parity
,
93 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
94 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
97 &DebugPortDevice
->DataBits
,
98 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
99 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
102 &DebugPortDevice
->StopBits
,
103 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
104 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
113 // implementation code
117 Debug Port Driver entry point.
119 Reads DebugPort variable to determine what device and settings to use as the
120 debug port. Binds exclusively to SerialIo. Reverts to defaults if no variable
123 @param[in] ImageHandle The firmware allocated handle for the EFI image.
124 @param[in] SystemTable A pointer to the EFI System Table.
126 @retval EFI_SUCCESS The entry point is executed successfully.
127 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
128 @retval other Some error occurs when executing this entry point.
133 InitializeDebugPortDriver (
134 IN EFI_HANDLE ImageHandle
,
135 IN EFI_SYSTEM_TABLE
*SystemTable
141 // Install driver model protocol(s).
143 Status
= EfiLibInstallDriverBindingComponentName2 (
146 &gDebugPortDriverBinding
,
148 &gDebugPortComponentName
,
149 &gDebugPortComponentName2
151 ASSERT_EFI_ERROR (Status
);
153 // Allocate and Initialize dev structure
155 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
156 if (gDebugPortDevice
== NULL
) {
157 return EFI_OUT_OF_RESOURCES
;
160 // Fill in static and default pieces of device structure first.
162 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
164 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
165 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
166 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
167 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
169 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
170 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
171 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
172 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
173 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
174 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
180 Checks to see if there's not already a DebugPort interface somewhere.
182 If there's a DEBUGPORT variable, the device path must match exactly. If there's
183 no DEBUGPORT variable, then device path is not checked and does not matter.
184 Checks to see that there's a serial io interface on the controller handle
185 that can be bound BY_DRIVER | EXCLUSIVE.
186 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
187 or other error returned by OpenProtocol.
189 @param This Protocol instance pointer.
190 @param ControllerHandle Handle of device to test.
191 @param RemainingDevicePath Optional parameter use to pick a specific child
194 @retval EFI_SUCCESS This driver supports this device.
195 @retval EFI_UNSUPPORTED Debug Port device is not supported.
196 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
197 @retval others Some error occurs.
203 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
204 IN EFI_HANDLE ControllerHandle
,
205 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
209 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
210 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
211 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
212 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
213 EFI_HANDLE TempHandle
;
216 // Check to see that there's not a debugport protocol already published
218 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
219 return EFI_UNSUPPORTED
;
222 // Read DebugPort variable to determine debug port selection and parameters
224 GetDebugPortVariable (gDebugPortDevice
);
226 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
228 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
229 // the closest matching handle matches the controller handle, and if it does,
230 // check to see that the remaining device path has the DebugPort GUIDed messaging
231 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
233 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
235 return EFI_OUT_OF_RESOURCES
;
240 Status
= gBS
->LocateDevicePath (
241 &gEfiSerialIoProtocolGuid
,
246 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
247 Status
= EFI_UNSUPPORTED
;
250 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
251 Status
= EFI_UNSUPPORTED
;
254 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
255 Status
= EFI_UNSUPPORTED
;
259 if (EFI_ERROR (Status
)) {
264 Status
= gBS
->OpenProtocol (
266 &gEfiSerialIoProtocolGuid
,
268 This
->DriverBindingHandle
,
270 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
272 if (EFI_ERROR (Status
)) {
278 &gEfiSerialIoProtocolGuid
,
279 This
->DriverBindingHandle
,
287 Binds exclusively to serial io on the controller handle, Produces DebugPort
288 protocol and DevicePath on new handle.
290 @param This Protocol instance pointer.
291 @param ControllerHandle Handle of device to bind driver to.
292 @param RemainingDevicePath Optional parameter use to pick a specific child
295 @retval EFI_SUCCESS This driver is added to ControllerHandle.
296 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
297 @retval others Some error occurs.
303 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
304 IN EFI_HANDLE ControllerHandle
,
305 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
309 DEBUGPORT_DEVICE_PATH DebugPortDP
;
310 EFI_DEVICE_PATH_PROTOCOL EndDP
;
311 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
313 Status
= gBS
->OpenProtocol (
315 &gEfiSerialIoProtocolGuid
,
316 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
317 This
->DriverBindingHandle
,
319 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
321 if (EFI_ERROR (Status
)) {
325 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
328 // Initialize the Serial Io interface...
330 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
331 gDebugPortDevice
->SerialIoBinding
,
332 gDebugPortDevice
->BaudRate
,
333 gDebugPortDevice
->ReceiveFifoDepth
,
334 gDebugPortDevice
->Timeout
,
335 gDebugPortDevice
->Parity
,
336 gDebugPortDevice
->DataBits
,
337 gDebugPortDevice
->StopBits
339 if (EFI_ERROR (Status
)) {
340 gDebugPortDevice
->BaudRate
= 0;
341 gDebugPortDevice
->Parity
= DefaultParity
;
342 gDebugPortDevice
->DataBits
= 0;
343 gDebugPortDevice
->StopBits
= DefaultStopBits
;
344 gDebugPortDevice
->ReceiveFifoDepth
= 0;
345 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
346 gDebugPortDevice
->SerialIoBinding
,
347 gDebugPortDevice
->BaudRate
,
348 gDebugPortDevice
->ReceiveFifoDepth
,
349 gDebugPortDevice
->Timeout
,
350 gDebugPortDevice
->Parity
,
351 gDebugPortDevice
->DataBits
,
352 gDebugPortDevice
->StopBits
354 if (EFI_ERROR (Status
)) {
357 &gEfiSerialIoProtocolGuid
,
358 This
->DriverBindingHandle
,
365 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
368 // Create device path instance for DebugPort
370 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
371 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
372 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
373 CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
375 Dp1
= DevicePathFromHandle (ControllerHandle
);
378 SetDevicePathEndNode (Dp1
);
381 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
382 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
383 return EFI_OUT_OF_RESOURCES
;
386 // Publish DebugPort and Device Path protocols
388 Status
= gBS
->InstallMultipleProtocolInterfaces (
389 &gDebugPortDevice
->DebugPortDeviceHandle
,
390 &gEfiDevicePathProtocolGuid
,
391 gDebugPortDevice
->DebugPortDevicePath
,
392 &gEfiDebugPortProtocolGuid
,
393 &gDebugPortDevice
->DebugPortInterface
,
397 if (EFI_ERROR (Status
)) {
400 &gEfiSerialIoProtocolGuid
,
401 This
->DriverBindingHandle
,
407 // Connect debugport child to serial io
409 Status
= gBS
->OpenProtocol (
411 &gEfiSerialIoProtocolGuid
,
412 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
413 This
->DriverBindingHandle
,
414 gDebugPortDevice
->DebugPortDeviceHandle
,
415 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
418 if (EFI_ERROR (Status
)) {
424 &gDebugPortDevice
->DebugPortInterface
,
427 "DebugPort driver failed to open child controller\n\n"
433 &gEfiSerialIoProtocolGuid
,
434 This
->DriverBindingHandle
,
445 &gDebugPortDevice
->DebugPortInterface
,
448 "Hello World from the DebugPort driver\n\n"
456 Stop this driver on ControllerHandle by removing Serial IO protocol on
457 the ControllerHandle.
459 @param This Protocol instance pointer.
460 @param ControllerHandle Handle of device to stop driver on
461 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
462 children is zero stop the entire bus driver.
463 @param ChildHandleBuffer List of Child Handles to Stop.
465 @retval EFI_SUCCESS This driver is removed ControllerHandle.
466 @retval other This driver was not removed from this device.
472 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
473 IN EFI_HANDLE ControllerHandle
,
474 IN UINTN NumberOfChildren
,
475 IN EFI_HANDLE
*ChildHandleBuffer
480 if (NumberOfChildren
== 0) {
482 // Close the bus driver
486 &gEfiSerialIoProtocolGuid
,
487 This
->DriverBindingHandle
,
491 gDebugPortDevice
->SerialIoBinding
= NULL
;
495 &gEfiDevicePathProtocolGuid
,
496 This
->DriverBindingHandle
,
500 FreePool (gDebugPortDevice
->DebugPortDevicePath
);
505 // Disconnect SerialIo child handle
507 Status
= gBS
->CloseProtocol (
508 gDebugPortDevice
->SerialIoDeviceHandle
,
509 &gEfiSerialIoProtocolGuid
,
510 This
->DriverBindingHandle
,
511 gDebugPortDevice
->DebugPortDeviceHandle
514 if (EFI_ERROR (Status
)) {
518 // Unpublish our protocols (DevicePath, DebugPort)
520 Status
= gBS
->UninstallMultipleProtocolInterfaces (
521 gDebugPortDevice
->DebugPortDeviceHandle
,
522 &gEfiDevicePathProtocolGuid
,
523 gDebugPortDevice
->DebugPortDevicePath
,
524 &gEfiDebugPortProtocolGuid
,
525 &gDebugPortDevice
->DebugPortInterface
,
529 if (EFI_ERROR (Status
)) {
532 &gEfiSerialIoProtocolGuid
,
533 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
534 This
->DriverBindingHandle
,
535 gDebugPortDevice
->DebugPortDeviceHandle
,
536 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
539 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
547 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
548 We cannot call SerialIo:SetAttributes because it uses pool services, which use
549 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
550 SerialIo:Reset() calls SetAttributes, so it can't be used either.
552 The port itself should be fine since it was set up during initialization.
554 @param This Protocol instance pointer.
556 @return EFI_SUCCESS Always.
562 IN EFI_DEBUGPORT_PROTOCOL
*This
568 while (This
->Poll (This
) == EFI_SUCCESS
) {
570 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
577 DebugPort protocol member function. Calls SerialIo:Read() after setting
578 if it's different than the last SerialIo access.
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.
593 IN EFI_DEBUGPORT_PROTOCOL
*This
,
595 IN OUT UINTN
*BufferSize
,
599 DEBUGPORT_DEVICE
*DebugPortDevice
;
600 UINTN LocalBufferSize
;
604 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
606 LocalBufferSize
= *BufferSize
;
608 Status
= DebugPortDevice
->SerialIoBinding
->Read (
609 DebugPortDevice
->SerialIoBinding
,
613 if (Status
== EFI_TIMEOUT
) {
614 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
615 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
619 } else if (EFI_ERROR (Status
)) {
623 BufferPtr
+= LocalBufferSize
;
624 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
625 } while (LocalBufferSize
!= 0 && Timeout
> 0);
627 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
633 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
634 a time and does a GetControl between 8 byte writes to help insure reads are
635 interspersed This is poor-man's flow control.
637 @param This Pointer to DebugPort protocol.
638 @param Timeout Timeout value.
639 @param BufferSize On input, the size of Buffer.
640 On output, the amount of data actually written.
641 @param Buffer Pointer to buffer to read.
643 @retval EFI_SUCCESS The data was written.
644 @retval others Fails when writting datas to debug port device.
650 IN EFI_DEBUGPORT_PROTOCOL
*This
,
652 IN OUT UINTN
*BufferSize
,
656 DEBUGPORT_DEVICE
*DebugPortDevice
;
660 UINT32 SerialControl
;
662 Status
= EFI_SUCCESS
;
663 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
666 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
667 DebugPortDevice
->SerialIoBinding
->GetControl (
668 DebugPortDevice
->SerialIoBinding
,
671 if (*BufferSize
- Position
< 8) {
672 WriteSize
= *BufferSize
- Position
;
675 Status
= DebugPortDevice
->SerialIoBinding
->Write (
676 DebugPortDevice
->SerialIoBinding
,
678 &((UINT8
*) Buffer
)[Position
]
682 *BufferSize
= Position
;
687 DebugPort protocol member function. Calls SerialIo:Write() after setting
688 if it's different than the last SerialIo access.
690 @param This Pointer to DebugPort protocol.
692 @retval EFI_SUCCESS At least 1 character is ready to be read from
693 the DebugPort interface.
694 @retval EFI_NOT_READY There are no characters ready to read from the
696 @retval EFI_DEVICE_ERROR A hardware failure occured... (from SerialIo)
702 IN EFI_DEBUGPORT_PROTOCOL
*This
706 UINT32 SerialControl
;
707 DEBUGPORT_DEVICE
*DebugPortDevice
;
709 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
711 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
712 DebugPortDevice
->SerialIoBinding
,
716 if (!EFI_ERROR (Status
)) {
717 if ((SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) != 0) {
718 Status
= EFI_NOT_READY
;
720 Status
= EFI_SUCCESS
;
728 Unload function that is registered in the LoadImage protocol. It un-installs
729 protocols produced and deallocates pool used by the driver. Called by the core
730 when unloading the driver.
734 @retval EFI_SUCCESS Unload Debug Port driver successfully.
735 @retval EFI_ABORTED Serial IO is still binding.
736 @retval others Fails to unload Debug Port driver.
742 EFI_HANDLE ImageHandle
747 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
751 Status
= gBS
->UninstallMultipleProtocolInterfaces (
753 &gEfiDriverBindingProtocolGuid
,
754 &gDebugPortDevice
->DriverBindingInterface
,
755 &gEfiComponentNameProtocolGuid
,
756 &gDebugPortDevice
->ComponentNameInterface
,
760 if (EFI_ERROR (Status
)) {
764 // Clean up allocations
766 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
767 FreePool (gDebugPortDevice
->DebugPortVariable
);
770 FreePool (gDebugPortDevice
);