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.
19 #include "DebugPort.h"
22 // Misc. functions local to this module..
26 GetDebugPortVariable (
27 DEBUGPORT_DEVICE
*DebugPortDevice
32 Local worker function to obtain device path information from DebugPort variable.
33 Records requested settings in DebugPort device structure.
36 DEBUGPORT_DEVICE *DebugPortDevice,
45 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
50 Status
= gRT
->GetVariable (
51 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
52 &gEfiDebugPortVariableGuid
,
55 DebugPortDevice
->DebugPortVariable
58 if (Status
== EFI_BUFFER_TOO_SMALL
) {
59 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
60 FreePool (gDebugPortDevice
->DebugPortVariable
);
63 DebugPortDevice
->DebugPortVariable
= AllocatePool (DataSize
);
64 if (DebugPortDevice
->DebugPortVariable
!= NULL
) {
66 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
67 &gEfiDebugPortVariableGuid
,
70 DebugPortDevice
->DebugPortVariable
72 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DebugPortDevice
->DebugPortVariable
;
73 while (!EfiIsDevicePathEnd (DevicePath
) && !EfiIsUartDevicePath (DevicePath
)) {
74 DevicePath
= EfiNextDevicePathNode (DevicePath
);
77 if (EfiIsDevicePathEnd (DevicePath
)) {
78 FreePool (gDebugPortDevice
->DebugPortVariable
);
79 DebugPortDevice
->DebugPortVariable
= NULL
;
82 &DebugPortDevice
->BaudRate
,
83 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
84 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
86 DebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
87 DebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
89 &DebugPortDevice
->Parity
,
90 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
91 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
94 &DebugPortDevice
->DataBits
,
95 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
96 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
99 &DebugPortDevice
->StopBits
,
100 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
101 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
112 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
116 DEBUGPORT_DRIVER_VERSION
,
121 DEBUGPORT_DEVICE
*gDebugPortDevice
;
124 // implementation code
129 InitializeDebugPortDriver (
130 IN EFI_HANDLE ImageHandle
,
131 IN EFI_SYSTEM_TABLE
*SystemTable
136 Driver entry point. Reads DebugPort variable to determine what device and settings
137 to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \
138 if no variable is found.
140 Creates debugport and devicepath protocols on new handle.
156 // Install driver model protocol(s).
158 Status
= EfiLibInstallDriverBindingComponentName2 (
161 &gDebugPortDriverBinding
,
163 &gDebugPortComponentName
,
164 &gDebugPortComponentName2
166 ASSERT_EFI_ERROR (Status
);
168 // Allocate and Initialize dev structure
170 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
171 if (gDebugPortDevice
== NULL
) {
172 return EFI_OUT_OF_RESOURCES
;
175 // Fill in static and default pieces of device structure first.
177 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
179 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
180 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
181 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
182 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
184 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
185 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
186 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
187 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
188 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
189 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
194 // DebugPort driver binding member functions...
199 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
200 IN EFI_HANDLE ControllerHandle
,
201 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
206 Checks to see that there's not already a DebugPort interface somewhere. If so,
209 If there's a DEBUGPORT variable, the device path must match exactly. If there's
210 no DEBUGPORT variable, then device path is not checked and does not matter.
212 Checks to see that there's a serial io interface on the controller handle
213 that can be bound BY_DRIVER | EXCLUSIVE.
215 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
216 or other error returned by OpenProtocol.
231 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
232 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
233 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
234 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
235 EFI_HANDLE TempHandle
;
238 // Check to see that there's not a debugport protocol already published
240 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
241 return EFI_UNSUPPORTED
;
244 // Read DebugPort variable to determine debug port selection and parameters
246 GetDebugPortVariable (gDebugPortDevice
);
248 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
250 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
251 // the closest matching handle matches the controller handle, and if it does,
252 // check to see that the remaining device path has the DebugPort GUIDed messaging
253 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
255 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
257 return EFI_OUT_OF_RESOURCES
;
262 Status
= gBS
->LocateDevicePath (
263 &gEfiSerialIoProtocolGuid
,
268 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
269 Status
= EFI_UNSUPPORTED
;
272 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
273 Status
= EFI_UNSUPPORTED
;
276 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
277 Status
= EFI_UNSUPPORTED
;
281 if (EFI_ERROR (Status
)) {
286 Status
= gBS
->OpenProtocol (
288 &gEfiSerialIoProtocolGuid
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
294 if (EFI_ERROR (Status
)) {
300 &gEfiSerialIoProtocolGuid
,
301 This
->DriverBindingHandle
,
311 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
312 IN EFI_HANDLE ControllerHandle
,
313 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
318 Binds exclusively to serial io on the controller handle. Produces DebugPort
319 protocol and DevicePath on new handle.
332 DEBUGPORT_DEVICE_PATH DebugPortDP
;
333 EFI_DEVICE_PATH_PROTOCOL EndDP
;
334 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
336 Status
= gBS
->OpenProtocol (
338 &gEfiSerialIoProtocolGuid
,
339 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
340 This
->DriverBindingHandle
,
342 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
344 if (EFI_ERROR (Status
)) {
348 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
351 // Initialize the Serial Io interface...
353 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
354 gDebugPortDevice
->SerialIoBinding
,
355 gDebugPortDevice
->BaudRate
,
356 gDebugPortDevice
->ReceiveFifoDepth
,
357 gDebugPortDevice
->Timeout
,
358 gDebugPortDevice
->Parity
,
359 gDebugPortDevice
->DataBits
,
360 gDebugPortDevice
->StopBits
362 if (EFI_ERROR (Status
)) {
363 gDebugPortDevice
->BaudRate
= 0;
364 gDebugPortDevice
->Parity
= DefaultParity
;
365 gDebugPortDevice
->DataBits
= 0;
366 gDebugPortDevice
->StopBits
= DefaultStopBits
;
367 gDebugPortDevice
->ReceiveFifoDepth
= 0;
368 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
369 gDebugPortDevice
->SerialIoBinding
,
370 gDebugPortDevice
->BaudRate
,
371 gDebugPortDevice
->ReceiveFifoDepth
,
372 gDebugPortDevice
->Timeout
,
373 gDebugPortDevice
->Parity
,
374 gDebugPortDevice
->DataBits
,
375 gDebugPortDevice
->StopBits
377 if (EFI_ERROR (Status
)) {
380 &gEfiSerialIoProtocolGuid
,
381 This
->DriverBindingHandle
,
388 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
391 // Create device path instance for DebugPort
393 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
394 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
395 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
396 CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
398 Dp1
= DevicePathFromHandle (ControllerHandle
);
401 SetDevicePathEndNode (Dp1
);
404 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
405 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
406 return EFI_OUT_OF_RESOURCES
;
409 // Publish DebugPort and Device Path protocols
411 Status
= gBS
->InstallMultipleProtocolInterfaces (
412 &gDebugPortDevice
->DebugPortDeviceHandle
,
413 &gEfiDevicePathProtocolGuid
,
414 gDebugPortDevice
->DebugPortDevicePath
,
415 &gEfiDebugPortProtocolGuid
,
416 &gDebugPortDevice
->DebugPortInterface
,
420 if (EFI_ERROR (Status
)) {
423 &gEfiSerialIoProtocolGuid
,
424 This
->DriverBindingHandle
,
430 // Connect debugport child to serial io
432 Status
= gBS
->OpenProtocol (
434 &gEfiSerialIoProtocolGuid
,
435 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
436 This
->DriverBindingHandle
,
437 gDebugPortDevice
->DebugPortDeviceHandle
,
438 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
441 if (EFI_ERROR (Status
)) {
447 &gDebugPortDevice
->DebugPortInterface
,
450 "DebugPort driver failed to open child controller\n\n"
456 &gEfiSerialIoProtocolGuid
,
457 This
->DriverBindingHandle
,
468 &gDebugPortDevice
->DebugPortInterface
,
471 "Hello World from the DebugPort driver\n\n"
481 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
482 IN EFI_HANDLE ControllerHandle
,
483 IN UINTN NumberOfChildren
,
484 IN EFI_HANDLE
*ChildHandleBuffer
489 We're never intending to be stopped via the driver model so this just returns
493 Per UEFI 2.0 driver model
503 if (NumberOfChildren
== 0) {
505 // Close the bus driver
509 &gEfiSerialIoProtocolGuid
,
510 This
->DriverBindingHandle
,
514 gDebugPortDevice
->SerialIoBinding
= NULL
;
518 &gEfiDevicePathProtocolGuid
,
519 This
->DriverBindingHandle
,
523 FreePool (gDebugPortDevice
->DebugPortDevicePath
);
528 // Disconnect SerialIo child handle
530 Status
= gBS
->CloseProtocol (
531 gDebugPortDevice
->SerialIoDeviceHandle
,
532 &gEfiSerialIoProtocolGuid
,
533 This
->DriverBindingHandle
,
534 gDebugPortDevice
->DebugPortDeviceHandle
537 if (EFI_ERROR (Status
)) {
541 // Unpublish our protocols (DevicePath, DebugPort)
543 Status
= gBS
->UninstallMultipleProtocolInterfaces (
544 gDebugPortDevice
->DebugPortDeviceHandle
,
545 &gEfiDevicePathProtocolGuid
,
546 gDebugPortDevice
->DebugPortDevicePath
,
547 &gEfiDebugPortProtocolGuid
,
548 &gDebugPortDevice
->DebugPortInterface
,
552 if (EFI_ERROR (Status
)) {
555 &gEfiSerialIoProtocolGuid
,
556 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
557 This
->DriverBindingHandle
,
558 gDebugPortDevice
->DebugPortDeviceHandle
,
559 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
562 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
569 // Debugport protocol member functions
574 IN EFI_DEBUGPORT_PROTOCOL
*This
579 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
580 We cannot call SerialIo:SetAttributes because it uses pool services, which use
581 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
582 SerialIo:Reset() calls SetAttributes, so it can't be used either.
584 The port itself should be fine since it was set up during initialization.
598 while (This
->Poll (This
) == EFI_SUCCESS
) {
600 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
609 IN EFI_DEBUGPORT_PROTOCOL
*This
,
611 IN OUT UINTN
*BufferSize
,
617 DebugPort protocol member function. Calls SerialIo:Read() after setting
618 if it's different than the last SerialIo access.
621 IN EFI_DEBUGPORT_PROTOCOL *This
623 IN OUT UINTN *BufferSize,
632 DEBUGPORT_DEVICE
*DebugPortDevice
;
633 UINTN LocalBufferSize
;
637 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
639 LocalBufferSize
= *BufferSize
;
641 Status
= DebugPortDevice
->SerialIoBinding
->Read (
642 DebugPortDevice
->SerialIoBinding
,
646 if (Status
== EFI_TIMEOUT
) {
647 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
648 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
652 } else if (EFI_ERROR (Status
)) {
656 BufferPtr
+= LocalBufferSize
;
657 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
658 } while (LocalBufferSize
!= 0 && Timeout
> 0);
660 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
668 IN EFI_DEBUGPORT_PROTOCOL
*This
,
670 IN OUT UINTN
*BufferSize
,
676 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
677 a time and does a GetControl between 8 byte writes to help insure reads are
678 interspersed This is poor-man's flow control..
681 This - Pointer to DebugPort protocol
682 Timeout - Timeout value
683 BufferSize - On input, the size of Buffer.
684 On output, the amount of data actually written.
685 Buffer - Pointer to buffer to write
688 EFI_SUCCESS - The data was written.
689 EFI_DEVICE_ERROR - The device reported an error.
690 EFI_TIMEOUT - The data write was stopped due to a timeout.
694 DEBUGPORT_DEVICE
*DebugPortDevice
;
698 UINT32 SerialControl
;
700 Status
= EFI_SUCCESS
;
701 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
704 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
705 DebugPortDevice
->SerialIoBinding
->GetControl (
706 DebugPortDevice
->SerialIoBinding
,
709 if (*BufferSize
- Position
< 8) {
710 WriteSize
= *BufferSize
- Position
;
713 Status
= DebugPortDevice
->SerialIoBinding
->Write (
714 DebugPortDevice
->SerialIoBinding
,
716 &((UINT8
*) Buffer
)[Position
]
720 *BufferSize
= Position
;
727 IN EFI_DEBUGPORT_PROTOCOL
*This
732 DebugPort protocol member function. Calls SerialIo:Write() after setting
733 if it's different than the last SerialIo access.
736 IN EFI_DEBUGPORT_PROTOCOL *This
739 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
740 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
741 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
746 UINT32 SerialControl
;
747 DEBUGPORT_DEVICE
*DebugPortDevice
;
749 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
751 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
752 DebugPortDevice
->SerialIoBinding
,
756 if (!EFI_ERROR (Status
)) {
757 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
758 Status
= EFI_NOT_READY
;
760 Status
= EFI_SUCCESS
;
770 EFI_HANDLE ImageHandle
775 Unload function that is registered in the LoadImage protocol. It un-installs
776 protocols produced and deallocates pool used by the driver. Called by the core
777 when unloading the driver.
780 EFI_HANDLE ImageHandle
790 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
794 Status
= gBS
->UninstallMultipleProtocolInterfaces (
796 &gEfiDriverBindingProtocolGuid
,
797 &gDebugPortDevice
->DriverBindingInterface
,
798 &gEfiComponentNameProtocolGuid
,
799 &gDebugPortDevice
->ComponentNameInterface
,
803 if (EFI_ERROR (Status
)) {
807 // Clean up allocations
809 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
810 FreePool (gDebugPortDevice
->DebugPortVariable
);
813 FreePool (gDebugPortDevice
);