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..
25 GetDebugPortVariable (
26 DEBUGPORT_DEVICE
*DebugPortDevice
31 Local worker function to obtain device path information from DebugPort variable.
32 Records requested settings in DebugPort device structure.
35 DEBUGPORT_DEVICE *DebugPortDevice,
44 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
49 Status
= gRT
->GetVariable (
50 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
51 &gEfiDebugPortVariableGuid
,
54 DebugPortDevice
->DebugPortVariable
57 if (Status
== EFI_BUFFER_TOO_SMALL
) {
58 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
59 FreePool (gDebugPortDevice
->DebugPortVariable
);
62 DebugPortDevice
->DebugPortVariable
= AllocatePool (DataSize
);
63 if (DebugPortDevice
->DebugPortVariable
!= NULL
) {
65 (CHAR16
*) EFI_DEBUGPORT_VARIABLE_NAME
,
66 &gEfiDebugPortVariableGuid
,
69 DebugPortDevice
->DebugPortVariable
71 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DebugPortDevice
->DebugPortVariable
;
72 while (!EfiIsDevicePathEnd (DevicePath
) && !EfiIsUartDevicePath (DevicePath
)) {
73 DevicePath
= EfiNextDevicePathNode (DevicePath
);
76 if (EfiIsDevicePathEnd (DevicePath
)) {
77 FreePool (gDebugPortDevice
->DebugPortVariable
);
78 DebugPortDevice
->DebugPortVariable
= NULL
;
81 &DebugPortDevice
->BaudRate
,
82 &((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
,
83 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->BaudRate
)
85 DebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
86 DebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
88 &DebugPortDevice
->Parity
,
89 &((UART_DEVICE_PATH
*) DevicePath
)->Parity
,
90 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->Parity
)
93 &DebugPortDevice
->DataBits
,
94 &((UART_DEVICE_PATH
*) DevicePath
)->DataBits
,
95 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->DataBits
)
98 &DebugPortDevice
->StopBits
,
99 &((UART_DEVICE_PATH
*) DevicePath
)->StopBits
,
100 sizeof (((UART_DEVICE_PATH
*) DevicePath
)->StopBits
)
111 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding
= {
115 DEBUGPORT_DRIVER_VERSION
,
120 DEBUGPORT_DEVICE
*gDebugPortDevice
;
123 // implementation code
128 InitializeDebugPortDriver (
129 IN EFI_HANDLE ImageHandle
,
130 IN EFI_SYSTEM_TABLE
*SystemTable
135 Driver entry point. Reads DebugPort variable to determine what device and settings
136 to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \
137 if no variable is found.
139 Creates debugport and devicepath protocols on new handle.
155 // Install driver model protocol(s).
157 Status
= EfiLibInstallDriverBindingComponentName2 (
160 &gDebugPortDriverBinding
,
162 &gDebugPortComponentName
,
163 &gDebugPortComponentName2
165 ASSERT_EFI_ERROR (Status
);
167 // Allocate and Initialize dev structure
169 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
170 if (gDebugPortDevice
== NULL
) {
171 return EFI_OUT_OF_RESOURCES
;
174 // Fill in static and default pieces of device structure first.
176 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
178 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
179 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
180 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
181 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
183 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
184 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
185 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
186 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
187 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
188 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
193 // DebugPort driver binding member functions...
198 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
199 IN EFI_HANDLE ControllerHandle
,
200 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
205 Checks to see that there's not already a DebugPort interface somewhere. If so,
208 If there's a DEBUGPORT variable, the device path must match exactly. If there's
209 no DEBUGPORT variable, then device path is not checked and does not matter.
211 Checks to see that there's a serial io interface on the controller handle
212 that can be bound BY_DRIVER | EXCLUSIVE.
214 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
215 or other error returned by OpenProtocol.
230 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
231 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
232 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
233 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
234 EFI_HANDLE TempHandle
;
237 // Check to see that there's not a debugport protocol already published
239 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
240 return EFI_UNSUPPORTED
;
243 // Read DebugPort variable to determine debug port selection and parameters
245 GetDebugPortVariable (gDebugPortDevice
);
247 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
249 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
250 // the closest matching handle matches the controller handle, and if it does,
251 // check to see that the remaining device path has the DebugPort GUIDed messaging
252 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
254 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
256 return EFI_OUT_OF_RESOURCES
;
261 Status
= gBS
->LocateDevicePath (
262 &gEfiSerialIoProtocolGuid
,
267 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
268 Status
= EFI_UNSUPPORTED
;
271 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
272 Status
= EFI_UNSUPPORTED
;
275 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
276 Status
= EFI_UNSUPPORTED
;
280 if (EFI_ERROR (Status
)) {
285 Status
= gBS
->OpenProtocol (
287 &gEfiSerialIoProtocolGuid
,
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
293 if (EFI_ERROR (Status
)) {
299 &gEfiSerialIoProtocolGuid
,
300 This
->DriverBindingHandle
,
310 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
311 IN EFI_HANDLE ControllerHandle
,
312 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
317 Binds exclusively to serial io on the controller handle. Produces DebugPort
318 protocol and DevicePath on new handle.
331 DEBUGPORT_DEVICE_PATH DebugPortDP
;
332 EFI_DEVICE_PATH_PROTOCOL EndDP
;
333 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
335 Status
= gBS
->OpenProtocol (
337 &gEfiSerialIoProtocolGuid
,
338 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
339 This
->DriverBindingHandle
,
341 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
343 if (EFI_ERROR (Status
)) {
347 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
350 // Initialize the Serial Io interface...
352 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
353 gDebugPortDevice
->SerialIoBinding
,
354 gDebugPortDevice
->BaudRate
,
355 gDebugPortDevice
->ReceiveFifoDepth
,
356 gDebugPortDevice
->Timeout
,
357 gDebugPortDevice
->Parity
,
358 gDebugPortDevice
->DataBits
,
359 gDebugPortDevice
->StopBits
361 if (EFI_ERROR (Status
)) {
362 gDebugPortDevice
->BaudRate
= 0;
363 gDebugPortDevice
->Parity
= DefaultParity
;
364 gDebugPortDevice
->DataBits
= 0;
365 gDebugPortDevice
->StopBits
= DefaultStopBits
;
366 gDebugPortDevice
->ReceiveFifoDepth
= 0;
367 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
368 gDebugPortDevice
->SerialIoBinding
,
369 gDebugPortDevice
->BaudRate
,
370 gDebugPortDevice
->ReceiveFifoDepth
,
371 gDebugPortDevice
->Timeout
,
372 gDebugPortDevice
->Parity
,
373 gDebugPortDevice
->DataBits
,
374 gDebugPortDevice
->StopBits
376 if (EFI_ERROR (Status
)) {
379 &gEfiSerialIoProtocolGuid
,
380 This
->DriverBindingHandle
,
387 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
390 // Create device path instance for DebugPort
392 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
393 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
394 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
395 CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
397 Dp1
= DevicePathFromHandle (ControllerHandle
);
400 SetDevicePathEndNode (Dp1
);
403 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
404 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
405 return EFI_OUT_OF_RESOURCES
;
408 // Publish DebugPort and Device Path protocols
410 Status
= gBS
->InstallMultipleProtocolInterfaces (
411 &gDebugPortDevice
->DebugPortDeviceHandle
,
412 &gEfiDevicePathProtocolGuid
,
413 gDebugPortDevice
->DebugPortDevicePath
,
414 &gEfiDebugPortProtocolGuid
,
415 &gDebugPortDevice
->DebugPortInterface
,
419 if (EFI_ERROR (Status
)) {
422 &gEfiSerialIoProtocolGuid
,
423 This
->DriverBindingHandle
,
429 // Connect debugport child to serial io
431 Status
= gBS
->OpenProtocol (
433 &gEfiSerialIoProtocolGuid
,
434 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
435 This
->DriverBindingHandle
,
436 gDebugPortDevice
->DebugPortDeviceHandle
,
437 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
440 if (EFI_ERROR (Status
)) {
446 &gDebugPortDevice
->DebugPortInterface
,
449 "DebugPort driver failed to open child controller\n\n"
455 &gEfiSerialIoProtocolGuid
,
456 This
->DriverBindingHandle
,
467 &gDebugPortDevice
->DebugPortInterface
,
470 "Hello World from the DebugPort driver\n\n"
480 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
481 IN EFI_HANDLE ControllerHandle
,
482 IN UINTN NumberOfChildren
,
483 IN EFI_HANDLE
*ChildHandleBuffer
488 We're never intending to be stopped via the driver model so this just returns
492 Per UEFI 2.0 driver model
502 if (NumberOfChildren
== 0) {
504 // Close the bus driver
508 &gEfiSerialIoProtocolGuid
,
509 This
->DriverBindingHandle
,
513 gDebugPortDevice
->SerialIoBinding
= NULL
;
517 &gEfiDevicePathProtocolGuid
,
518 This
->DriverBindingHandle
,
522 FreePool (gDebugPortDevice
->DebugPortDevicePath
);
527 // Disconnect SerialIo child handle
529 Status
= gBS
->CloseProtocol (
530 gDebugPortDevice
->SerialIoDeviceHandle
,
531 &gEfiSerialIoProtocolGuid
,
532 This
->DriverBindingHandle
,
533 gDebugPortDevice
->DebugPortDeviceHandle
536 if (EFI_ERROR (Status
)) {
540 // Unpublish our protocols (DevicePath, DebugPort)
542 Status
= gBS
->UninstallMultipleProtocolInterfaces (
543 gDebugPortDevice
->DebugPortDeviceHandle
,
544 &gEfiDevicePathProtocolGuid
,
545 gDebugPortDevice
->DebugPortDevicePath
,
546 &gEfiDebugPortProtocolGuid
,
547 &gDebugPortDevice
->DebugPortInterface
,
551 if (EFI_ERROR (Status
)) {
554 &gEfiSerialIoProtocolGuid
,
555 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
556 This
->DriverBindingHandle
,
557 gDebugPortDevice
->DebugPortDeviceHandle
,
558 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
561 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
568 // Debugport protocol member functions
573 IN EFI_DEBUGPORT_PROTOCOL
*This
578 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
579 We cannot call SerialIo:SetAttributes because it uses pool services, which use
580 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
581 SerialIo:Reset() calls SetAttributes, so it can't be used either.
583 The port itself should be fine since it was set up during initialization.
597 while (This
->Poll (This
) == EFI_SUCCESS
) {
599 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
608 IN EFI_DEBUGPORT_PROTOCOL
*This
,
610 IN OUT UINTN
*BufferSize
,
616 DebugPort protocol member function. Calls SerialIo:Read() after setting
617 if it's different than the last SerialIo access.
620 IN EFI_DEBUGPORT_PROTOCOL *This
622 IN OUT UINTN *BufferSize,
631 DEBUGPORT_DEVICE
*DebugPortDevice
;
632 UINTN LocalBufferSize
;
636 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
638 LocalBufferSize
= *BufferSize
;
640 Status
= DebugPortDevice
->SerialIoBinding
->Read (
641 DebugPortDevice
->SerialIoBinding
,
645 if (Status
== EFI_TIMEOUT
) {
646 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
647 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
651 } else if (EFI_ERROR (Status
)) {
655 BufferPtr
+= LocalBufferSize
;
656 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
657 } while (LocalBufferSize
!= 0 && Timeout
> 0);
659 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
667 IN EFI_DEBUGPORT_PROTOCOL
*This
,
669 IN OUT UINTN
*BufferSize
,
675 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
676 a time and does a GetControl between 8 byte writes to help insure reads are
677 interspersed This is poor-man's flow control..
680 This - Pointer to DebugPort protocol
681 Timeout - Timeout value
682 BufferSize - On input, the size of Buffer.
683 On output, the amount of data actually written.
684 Buffer - Pointer to buffer to write
687 EFI_SUCCESS - The data was written.
688 EFI_DEVICE_ERROR - The device reported an error.
689 EFI_TIMEOUT - The data write was stopped due to a timeout.
693 DEBUGPORT_DEVICE
*DebugPortDevice
;
697 UINT32 SerialControl
;
699 Status
= EFI_SUCCESS
;
700 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
703 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
704 DebugPortDevice
->SerialIoBinding
->GetControl (
705 DebugPortDevice
->SerialIoBinding
,
708 if (*BufferSize
- Position
< 8) {
709 WriteSize
= *BufferSize
- Position
;
712 Status
= DebugPortDevice
->SerialIoBinding
->Write (
713 DebugPortDevice
->SerialIoBinding
,
715 &((UINT8
*) Buffer
)[Position
]
719 *BufferSize
= Position
;
726 IN EFI_DEBUGPORT_PROTOCOL
*This
731 DebugPort protocol member function. Calls SerialIo:Write() after setting
732 if it's different than the last SerialIo access.
735 IN EFI_DEBUGPORT_PROTOCOL *This
738 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
739 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
740 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
745 UINT32 SerialControl
;
746 DEBUGPORT_DEVICE
*DebugPortDevice
;
748 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
750 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
751 DebugPortDevice
->SerialIoBinding
,
755 if (!EFI_ERROR (Status
)) {
756 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
757 Status
= EFI_NOT_READY
;
759 Status
= EFI_SUCCESS
;
769 EFI_HANDLE ImageHandle
774 Unload function that is registered in the LoadImage protocol. It un-installs
775 protocols produced and deallocates pool used by the driver. Called by the core
776 when unloading the driver.
779 EFI_HANDLE ImageHandle
789 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
793 Status
= gBS
->UninstallMultipleProtocolInterfaces (
795 &gEfiDriverBindingProtocolGuid
,
796 &gDebugPortDevice
->DriverBindingInterface
,
797 &gEfiComponentNameProtocolGuid
,
798 &gDebugPortDevice
->ComponentNameInterface
,
802 if (EFI_ERROR (Status
)) {
806 // Clean up allocations
808 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
809 FreePool (gDebugPortDevice
->DebugPortVariable
);
812 FreePool (gDebugPortDevice
);