3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Top level C file for debugport driver. Contains initialization function.
19 This driver layers on top of SerialIo.
21 ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM
29 #include "DebugPort.h"
32 // Misc. functions local to this module..
36 GetDebugPortVariable (
37 DEBUGPORT_DEVICE
*DebugPortDevice
42 Local worker function to obtain device path information from DebugPort variable.
43 Records requested settings in DebugPort device structure.
46 DEBUGPORT_DEVICE *DebugPortDevice,
55 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
60 Status
= gRT
->GetVariable (
61 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
62 &gEfiDebugPortVariableGuid
,
65 DebugPortDevice
->DebugPortVariable
68 if (Status
== EFI_BUFFER_TOO_SMALL
) {
69 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
70 FreePool (gDebugPortDevice
->DebugPortVariable
);
73 DebugPortDevice
->DebugPortVariable
= AllocatePool (DataSize
);
74 if (DebugPortDevice
->DebugPortVariable
!= NULL
) {
76 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
77 &gEfiDebugPortVariableGuid
,
80 DebugPortDevice
->DebugPortVariable
82 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DebugPortDevice
->DebugPortVariable
;
83 while (!EfiIsDevicePathEnd (DevicePath
) && !EfiIsUartDevicePath (DevicePath
)) {
84 DevicePath
= EfiNextDevicePathNode (DevicePath
);
87 if (EfiIsDevicePathEnd (DevicePath
)) {
88 FreePool (gDebugPortDevice
->DebugPortVariable
);
89 DebugPortDevice
->DebugPortVariable
= NULL
;
92 &DebugPortDevice
->BaudRate
,
93 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
94 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
96 DebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
97 DebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
99 &DebugPortDevice
->Parity
,
100 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
101 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
104 &DebugPortDevice
->DataBits
,
105 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
106 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
109 &DebugPortDevice
->StopBits
,
110 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
111 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
122 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
126 DEBUGPORT_DRIVER_VERSION
,
131 DEBUGPORT_DEVICE
*gDebugPortDevice
;
134 // implementation code
139 InitializeDebugPortDriver (
140 IN EFI_HANDLE ImageHandle
,
141 IN EFI_SYSTEM_TABLE
*SystemTable
146 Driver entry point. Reads DebugPort variable to determine what device and settings
147 to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \
148 if no variable is found.
150 Creates debugport and devicepath protocols on new handle.
166 // Install driver model protocol(s).
168 Status
= EfiLibInstallDriverBindingComponentName2 (
171 &gDebugPortDriverBinding
,
173 &gDebugPortComponentName
,
174 &gDebugPortComponentName2
176 ASSERT_EFI_ERROR (Status
);
178 // Allocate and Initialize dev structure
180 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
181 if (gDebugPortDevice
== NULL
) {
182 return EFI_OUT_OF_RESOURCES
;
185 // Fill in static and default pieces of device structure first.
187 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
189 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
190 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
191 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
192 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
194 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
195 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
196 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
197 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
198 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
199 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
204 // DebugPort driver binding member functions...
209 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
210 IN EFI_HANDLE ControllerHandle
,
211 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
216 Checks to see that there's not already a DebugPort interface somewhere. If so,
219 If there's a DEBUGPORT variable, the device path must match exactly. If there's
220 no DEBUGPORT variable, then device path is not checked and does not matter.
222 Checks to see that there's a serial io interface on the controller handle
223 that can be bound BY_DRIVER | EXCLUSIVE.
225 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
226 or other error returned by OpenProtocol.
241 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
242 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
243 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
244 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
245 EFI_HANDLE TempHandle
;
248 // Check to see that there's not a debugport protocol already published
250 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
251 return EFI_UNSUPPORTED
;
254 // Read DebugPort variable to determine debug port selection and parameters
256 GetDebugPortVariable (gDebugPortDevice
);
258 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
260 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
261 // the closest matching handle matches the controller handle, and if it does,
262 // check to see that the remaining device path has the DebugPort GUIDed messaging
263 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
265 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
267 return EFI_OUT_OF_RESOURCES
;
272 Status
= gBS
->LocateDevicePath (
273 &gEfiSerialIoProtocolGuid
,
278 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
279 Status
= EFI_UNSUPPORTED
;
282 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
283 Status
= EFI_UNSUPPORTED
;
286 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
287 Status
= EFI_UNSUPPORTED
;
291 if (EFI_ERROR (Status
)) {
296 Status
= gBS
->OpenProtocol (
298 &gEfiSerialIoProtocolGuid
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
304 if (EFI_ERROR (Status
)) {
310 &gEfiSerialIoProtocolGuid
,
311 This
->DriverBindingHandle
,
321 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
322 IN EFI_HANDLE ControllerHandle
,
323 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
328 Binds exclusively to serial io on the controller handle. Produces DebugPort
329 protocol and DevicePath on new handle.
342 DEBUGPORT_DEVICE_PATH DebugPortDP
;
343 EFI_DEVICE_PATH_PROTOCOL EndDP
;
344 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
346 Status
= gBS
->OpenProtocol (
348 &gEfiSerialIoProtocolGuid
,
349 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
350 This
->DriverBindingHandle
,
352 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
354 if (EFI_ERROR (Status
)) {
358 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
361 // Initialize the Serial Io interface...
363 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
364 gDebugPortDevice
->SerialIoBinding
,
365 gDebugPortDevice
->BaudRate
,
366 gDebugPortDevice
->ReceiveFifoDepth
,
367 gDebugPortDevice
->Timeout
,
368 gDebugPortDevice
->Parity
,
369 gDebugPortDevice
->DataBits
,
370 gDebugPortDevice
->StopBits
372 if (EFI_ERROR (Status
)) {
373 gDebugPortDevice
->BaudRate
= 0;
374 gDebugPortDevice
->Parity
= DefaultParity
;
375 gDebugPortDevice
->DataBits
= 0;
376 gDebugPortDevice
->StopBits
= DefaultStopBits
;
377 gDebugPortDevice
->ReceiveFifoDepth
= 0;
378 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
379 gDebugPortDevice
->SerialIoBinding
,
380 gDebugPortDevice
->BaudRate
,
381 gDebugPortDevice
->ReceiveFifoDepth
,
382 gDebugPortDevice
->Timeout
,
383 gDebugPortDevice
->Parity
,
384 gDebugPortDevice
->DataBits
,
385 gDebugPortDevice
->StopBits
387 if (EFI_ERROR (Status
)) {
390 &gEfiSerialIoProtocolGuid
,
391 This
->DriverBindingHandle
,
398 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
401 // Create device path instance for DebugPort
403 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
404 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
405 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
406 CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
408 Dp1
= DevicePathFromHandle (ControllerHandle
);
411 SetDevicePathEndNode (Dp1
);
414 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
415 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
416 return EFI_OUT_OF_RESOURCES
;
419 // Publish DebugPort and Device Path protocols
421 Status
= gBS
->InstallMultipleProtocolInterfaces (
422 &gDebugPortDevice
->DebugPortDeviceHandle
,
423 &gEfiDevicePathProtocolGuid
,
424 gDebugPortDevice
->DebugPortDevicePath
,
425 &gEfiDebugPortProtocolGuid
,
426 &gDebugPortDevice
->DebugPortInterface
,
430 if (EFI_ERROR (Status
)) {
433 &gEfiSerialIoProtocolGuid
,
434 This
->DriverBindingHandle
,
440 // Connect debugport child to serial io
442 Status
= gBS
->OpenProtocol (
444 &gEfiSerialIoProtocolGuid
,
445 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
446 This
->DriverBindingHandle
,
447 gDebugPortDevice
->DebugPortDeviceHandle
,
448 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
451 if (EFI_ERROR (Status
)) {
457 &gDebugPortDevice
->DebugPortInterface
,
460 "DebugPort driver failed to open child controller\n\n"
466 &gEfiSerialIoProtocolGuid
,
467 This
->DriverBindingHandle
,
478 &gDebugPortDevice
->DebugPortInterface
,
481 "Hello World from the DebugPort driver\n\n"
491 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
492 IN EFI_HANDLE ControllerHandle
,
493 IN UINTN NumberOfChildren
,
494 IN EFI_HANDLE
*ChildHandleBuffer
499 We're never intending to be stopped via the driver model so this just returns
503 Per UEFI 2.0 driver model
513 if (NumberOfChildren
== 0) {
515 // Close the bus driver
519 &gEfiSerialIoProtocolGuid
,
520 This
->DriverBindingHandle
,
524 gDebugPortDevice
->SerialIoBinding
= NULL
;
528 &gEfiDevicePathProtocolGuid
,
529 This
->DriverBindingHandle
,
533 FreePool (gDebugPortDevice
->DebugPortDevicePath
);
538 // Disconnect SerialIo child handle
540 Status
= gBS
->CloseProtocol (
541 gDebugPortDevice
->SerialIoDeviceHandle
,
542 &gEfiSerialIoProtocolGuid
,
543 This
->DriverBindingHandle
,
544 gDebugPortDevice
->DebugPortDeviceHandle
547 if (EFI_ERROR (Status
)) {
551 // Unpublish our protocols (DevicePath, DebugPort)
553 Status
= gBS
->UninstallMultipleProtocolInterfaces (
554 gDebugPortDevice
->DebugPortDeviceHandle
,
555 &gEfiDevicePathProtocolGuid
,
556 gDebugPortDevice
->DebugPortDevicePath
,
557 &gEfiDebugPortProtocolGuid
,
558 &gDebugPortDevice
->DebugPortInterface
,
562 if (EFI_ERROR (Status
)) {
565 &gEfiSerialIoProtocolGuid
,
566 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
567 This
->DriverBindingHandle
,
568 gDebugPortDevice
->DebugPortDeviceHandle
,
569 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
572 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
579 // Debugport protocol member functions
584 IN EFI_DEBUGPORT_PROTOCOL
*This
589 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
590 We cannot call SerialIo:SetAttributes because it uses pool services, which use
591 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
592 SerialIo:Reset() calls SetAttributes, so it can't be used either.
594 The port itself should be fine since it was set up during initialization.
608 while (This
->Poll (This
) == EFI_SUCCESS
) {
610 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
619 IN EFI_DEBUGPORT_PROTOCOL
*This
,
621 IN OUT UINTN
*BufferSize
,
627 DebugPort protocol member function. Calls SerialIo:Read() after setting
628 if it's different than the last SerialIo access.
631 IN EFI_DEBUGPORT_PROTOCOL *This
633 IN OUT UINTN *BufferSize,
642 DEBUGPORT_DEVICE
*DebugPortDevice
;
643 UINTN LocalBufferSize
;
647 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
649 LocalBufferSize
= *BufferSize
;
651 Status
= DebugPortDevice
->SerialIoBinding
->Read (
652 DebugPortDevice
->SerialIoBinding
,
656 if (Status
== EFI_TIMEOUT
) {
657 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
658 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
662 } else if (EFI_ERROR (Status
)) {
666 BufferPtr
+= LocalBufferSize
;
667 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
668 } while (LocalBufferSize
!= 0 && Timeout
> 0);
670 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
678 IN EFI_DEBUGPORT_PROTOCOL
*This
,
680 IN OUT UINTN
*BufferSize
,
686 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
687 a time and does a GetControl between 8 byte writes to help insure reads are
688 interspersed This is poor-man's flow control..
691 This - Pointer to DebugPort protocol
692 Timeout - Timeout value
693 BufferSize - On input, the size of Buffer.
694 On output, the amount of data actually written.
695 Buffer - Pointer to buffer to write
698 EFI_SUCCESS - The data was written.
699 EFI_DEVICE_ERROR - The device reported an error.
700 EFI_TIMEOUT - The data write was stopped due to a timeout.
704 DEBUGPORT_DEVICE
*DebugPortDevice
;
708 UINT32 SerialControl
;
710 Status
= EFI_SUCCESS
;
711 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
714 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
715 DebugPortDevice
->SerialIoBinding
->GetControl (
716 DebugPortDevice
->SerialIoBinding
,
719 if (*BufferSize
- Position
< 8) {
720 WriteSize
= *BufferSize
- Position
;
723 Status
= DebugPortDevice
->SerialIoBinding
->Write (
724 DebugPortDevice
->SerialIoBinding
,
726 &((UINT8
*) Buffer
)[Position
]
730 *BufferSize
= Position
;
737 IN EFI_DEBUGPORT_PROTOCOL
*This
742 DebugPort protocol member function. Calls SerialIo:Write() after setting
743 if it's different than the last SerialIo access.
746 IN EFI_DEBUGPORT_PROTOCOL *This
749 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
750 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
751 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
756 UINT32 SerialControl
;
757 DEBUGPORT_DEVICE
*DebugPortDevice
;
759 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
761 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
762 DebugPortDevice
->SerialIoBinding
,
766 if (!EFI_ERROR (Status
)) {
767 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
768 Status
= EFI_NOT_READY
;
770 Status
= EFI_SUCCESS
;
780 EFI_HANDLE ImageHandle
785 Unload function that is registered in the LoadImage protocol. It un-installs
786 protocols produced and deallocates pool used by the driver. Called by the core
787 when unloading the driver.
790 EFI_HANDLE ImageHandle
800 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
804 Status
= gBS
->UninstallMultipleProtocolInterfaces (
806 &gEfiDriverBindingProtocolGuid
,
807 &gDebugPortDevice
->DriverBindingInterface
,
808 &gEfiComponentNameProtocolGuid
,
809 &gDebugPortDevice
->ComponentNameInterface
,
813 if (EFI_ERROR (Status
)) {
817 // Clean up allocations
819 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
820 FreePool (gDebugPortDevice
->DebugPortVariable
);
823 FreePool (gDebugPortDevice
);