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 gBS
->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 gBS
->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.
164 // Allocate and Initialize dev structure
166 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
167 if (gDebugPortDevice
== NULL
) {
168 return EFI_OUT_OF_RESOURCES
;
171 // Fill in static and default pieces of device structure first.
173 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
175 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
176 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
177 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
178 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
180 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
181 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
182 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
183 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
184 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
185 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
190 // DebugPort driver binding member functions...
195 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
196 IN EFI_HANDLE ControllerHandle
,
197 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
202 Checks to see that there's not already a DebugPort interface somewhere. If so,
205 If there's a DEBUGPORT variable, the device path must match exactly. If there's
206 no DEBUGPORT variable, then device path is not checked and does not matter.
208 Checks to see that there's a serial io interface on the controller handle
209 that can be bound BY_DRIVER | EXCLUSIVE.
211 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
212 or other error returned by OpenProtocol.
227 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
228 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
229 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
230 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
231 EFI_HANDLE TempHandle
;
234 // Check to see that there's not a debugport protocol already published
236 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
237 return EFI_UNSUPPORTED
;
240 // Read DebugPort variable to determine debug port selection and parameters
242 GetDebugPortVariable (gDebugPortDevice
);
244 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
246 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
247 // the closest matching handle matches the controller handle, and if it does,
248 // check to see that the remaining device path has the DebugPort GUIDed messaging
249 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
251 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
253 return EFI_OUT_OF_RESOURCES
;
258 Status
= gBS
->LocateDevicePath (
259 &gEfiSerialIoProtocolGuid
,
264 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
265 Status
= EFI_UNSUPPORTED
;
268 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
269 Status
= EFI_UNSUPPORTED
;
272 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
273 Status
= EFI_UNSUPPORTED
;
277 if (EFI_ERROR (Status
)) {
282 Status
= gBS
->OpenProtocol (
284 &gEfiSerialIoProtocolGuid
,
286 This
->DriverBindingHandle
,
288 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
290 if (EFI_ERROR (Status
)) {
296 &gEfiSerialIoProtocolGuid
,
297 This
->DriverBindingHandle
,
307 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
308 IN EFI_HANDLE ControllerHandle
,
309 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
314 Binds exclusively to serial io on the controller handle. Produces DebugPort
315 protocol and DevicePath on new handle.
328 DEBUGPORT_DEVICE_PATH DebugPortDP
;
329 EFI_DEVICE_PATH_PROTOCOL EndDP
;
330 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
332 Status
= gBS
->OpenProtocol (
334 &gEfiSerialIoProtocolGuid
,
335 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
336 This
->DriverBindingHandle
,
338 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
340 if (EFI_ERROR (Status
)) {
344 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
347 // Initialize the Serial Io interface...
349 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
350 gDebugPortDevice
->SerialIoBinding
,
351 gDebugPortDevice
->BaudRate
,
352 gDebugPortDevice
->ReceiveFifoDepth
,
353 gDebugPortDevice
->Timeout
,
354 gDebugPortDevice
->Parity
,
355 gDebugPortDevice
->DataBits
,
356 gDebugPortDevice
->StopBits
358 if (EFI_ERROR (Status
)) {
359 gDebugPortDevice
->BaudRate
= 0;
360 gDebugPortDevice
->Parity
= DefaultParity
;
361 gDebugPortDevice
->DataBits
= 0;
362 gDebugPortDevice
->StopBits
= DefaultStopBits
;
363 gDebugPortDevice
->ReceiveFifoDepth
= 0;
364 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
365 gDebugPortDevice
->SerialIoBinding
,
366 gDebugPortDevice
->BaudRate
,
367 gDebugPortDevice
->ReceiveFifoDepth
,
368 gDebugPortDevice
->Timeout
,
369 gDebugPortDevice
->Parity
,
370 gDebugPortDevice
->DataBits
,
371 gDebugPortDevice
->StopBits
373 if (EFI_ERROR (Status
)) {
376 &gEfiSerialIoProtocolGuid
,
377 This
->DriverBindingHandle
,
384 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
387 // Create device path instance for DebugPort
389 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
390 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
391 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
392 gBS
->CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
394 Dp1
= DevicePathFromHandle (ControllerHandle
);
397 SetDevicePathEndNode (Dp1
);
400 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
401 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
402 return EFI_OUT_OF_RESOURCES
;
405 // Publish DebugPort and Device Path protocols
407 Status
= gBS
->InstallMultipleProtocolInterfaces (
408 &gDebugPortDevice
->DebugPortDeviceHandle
,
409 &gEfiDevicePathProtocolGuid
,
410 gDebugPortDevice
->DebugPortDevicePath
,
411 &gEfiDebugPortProtocolGuid
,
412 &gDebugPortDevice
->DebugPortInterface
,
416 if (EFI_ERROR (Status
)) {
419 &gEfiSerialIoProtocolGuid
,
420 This
->DriverBindingHandle
,
426 // Connect debugport child to serial io
428 Status
= gBS
->OpenProtocol (
430 &gEfiSerialIoProtocolGuid
,
431 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
432 This
->DriverBindingHandle
,
433 gDebugPortDevice
->DebugPortDeviceHandle
,
434 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
437 if (EFI_ERROR (Status
)) {
443 &gDebugPortDevice
->DebugPortInterface
,
446 "DebugPort driver failed to open child controller\n\n"
452 &gEfiSerialIoProtocolGuid
,
453 This
->DriverBindingHandle
,
464 &gDebugPortDevice
->DebugPortInterface
,
467 "Hello World from the DebugPort driver\n\n"
477 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
478 IN EFI_HANDLE ControllerHandle
,
479 IN UINTN NumberOfChildren
,
480 IN EFI_HANDLE
*ChildHandleBuffer
485 We're never intending to be stopped via the driver model so this just returns
489 Per EFI 1.10 driver model
499 if (NumberOfChildren
== 0) {
501 // Close the bus driver
505 &gEfiSerialIoProtocolGuid
,
506 This
->DriverBindingHandle
,
510 gDebugPortDevice
->SerialIoBinding
= NULL
;
514 &gEfiDevicePathProtocolGuid
,
515 This
->DriverBindingHandle
,
519 gBS
->FreePool (gDebugPortDevice
->DebugPortDevicePath
);
524 // Disconnect SerialIo child handle
526 Status
= gBS
->CloseProtocol (
527 gDebugPortDevice
->SerialIoDeviceHandle
,
528 &gEfiSerialIoProtocolGuid
,
529 This
->DriverBindingHandle
,
530 gDebugPortDevice
->DebugPortDeviceHandle
533 if (EFI_ERROR (Status
)) {
537 // Unpublish our protocols (DevicePath, DebugPort)
539 Status
= gBS
->UninstallMultipleProtocolInterfaces (
540 gDebugPortDevice
->DebugPortDeviceHandle
,
541 &gEfiDevicePathProtocolGuid
,
542 gDebugPortDevice
->DebugPortDevicePath
,
543 &gEfiDebugPortProtocolGuid
,
544 &gDebugPortDevice
->DebugPortInterface
,
548 if (EFI_ERROR (Status
)) {
551 &gEfiSerialIoProtocolGuid
,
552 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
553 This
->DriverBindingHandle
,
554 gDebugPortDevice
->DebugPortDeviceHandle
,
555 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
558 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
565 // Debugport protocol member functions
570 IN EFI_DEBUGPORT_PROTOCOL
*This
575 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
576 We cannot call SerialIo:SetAttributes because it uses pool services, which use
577 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
578 SerialIo:Reset() calls SetAttributes, so it can't be used either.
580 The port itself should be fine since it was set up during initialization.
594 while (This
->Poll (This
) == EFI_SUCCESS
) {
596 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
605 IN EFI_DEBUGPORT_PROTOCOL
*This
,
607 IN OUT UINTN
*BufferSize
,
613 DebugPort protocol member function. Calls SerialIo:Read() after setting
614 if it's different than the last SerialIo access.
617 IN EFI_DEBUGPORT_PROTOCOL *This
619 IN OUT UINTN *BufferSize,
628 DEBUGPORT_DEVICE
*DebugPortDevice
;
629 UINTN LocalBufferSize
;
633 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
635 LocalBufferSize
= *BufferSize
;
637 Status
= DebugPortDevice
->SerialIoBinding
->Read (
638 DebugPortDevice
->SerialIoBinding
,
642 if (Status
== EFI_TIMEOUT
) {
643 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
644 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
648 } else if (EFI_ERROR (Status
)) {
652 BufferPtr
+= LocalBufferSize
;
653 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
654 } while (LocalBufferSize
!= 0 && Timeout
> 0);
656 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
664 IN EFI_DEBUGPORT_PROTOCOL
*This
,
666 IN OUT UINTN
*BufferSize
,
672 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
673 a time and does a GetControl between 8 byte writes to help insure reads are
674 interspersed This is poor-man's flow control..
677 This - Pointer to DebugPort protocol
678 Timeout - Timeout value
679 BufferSize - On input, the size of Buffer.
680 On output, the amount of data actually written.
681 Buffer - Pointer to buffer to write
684 EFI_SUCCESS - The data was written.
685 EFI_DEVICE_ERROR - The device reported an error.
686 EFI_TIMEOUT - The data write was stopped due to a timeout.
690 DEBUGPORT_DEVICE
*DebugPortDevice
;
694 UINT32 SerialControl
;
696 Status
= EFI_SUCCESS
;
697 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
700 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
701 DebugPortDevice
->SerialIoBinding
->GetControl (
702 DebugPortDevice
->SerialIoBinding
,
705 if (*BufferSize
- Position
< 8) {
706 WriteSize
= *BufferSize
- Position
;
709 Status
= DebugPortDevice
->SerialIoBinding
->Write (
710 DebugPortDevice
->SerialIoBinding
,
712 &((UINT8
*) Buffer
)[Position
]
716 *BufferSize
= Position
;
723 IN EFI_DEBUGPORT_PROTOCOL
*This
728 DebugPort protocol member function. Calls SerialIo:Write() after setting
729 if it's different than the last SerialIo access.
732 IN EFI_DEBUGPORT_PROTOCOL *This
735 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
736 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
737 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
742 UINT32 SerialControl
;
743 DEBUGPORT_DEVICE
*DebugPortDevice
;
745 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
747 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
748 DebugPortDevice
->SerialIoBinding
,
752 if (!EFI_ERROR (Status
)) {
753 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
754 Status
= EFI_NOT_READY
;
756 Status
= EFI_SUCCESS
;
766 EFI_HANDLE ImageHandle
771 Unload function that is registered in the LoadImage protocol. It un-installs
772 protocols produced and deallocates pool used by the driver. Called by the core
773 when unloading the driver.
776 EFI_HANDLE ImageHandle
786 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
790 Status
= gBS
->UninstallMultipleProtocolInterfaces (
792 &gEfiDriverBindingProtocolGuid
,
793 &gDebugPortDevice
->DriverBindingInterface
,
794 &gEfiComponentNameProtocolGuid
,
795 &gDebugPortDevice
->ComponentNameInterface
,
799 if (EFI_ERROR (Status
)) {
803 // Clean up allocations
805 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
806 gBS
->FreePool (gDebugPortDevice
->DebugPortVariable
);
809 gBS
->FreePool (gDebugPortDevice
);