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
= EfiLibInstallAllDriverProtocols (
171 &gDebugPortDriverBinding
,
173 &gDebugPortComponentName
,
177 ASSERT_EFI_ERROR (Status
);
179 // Allocate and Initialize dev structure
181 gDebugPortDevice
= AllocateZeroPool (sizeof (DEBUGPORT_DEVICE
));
182 if (gDebugPortDevice
== NULL
) {
183 return EFI_OUT_OF_RESOURCES
;
186 // Fill in static and default pieces of device structure first.
188 gDebugPortDevice
->Signature
= DEBUGPORT_DEVICE_SIGNATURE
;
190 gDebugPortDevice
->DebugPortInterface
.Reset
= DebugPortReset
;
191 gDebugPortDevice
->DebugPortInterface
.Read
= DebugPortRead
;
192 gDebugPortDevice
->DebugPortInterface
.Write
= DebugPortWrite
;
193 gDebugPortDevice
->DebugPortInterface
.Poll
= DebugPortPoll
;
195 gDebugPortDevice
->BaudRate
= DEBUGPORT_UART_DEFAULT_BAUDRATE
;
196 gDebugPortDevice
->ReceiveFifoDepth
= DEBUGPORT_UART_DEFAULT_FIFO_DEPTH
;
197 gDebugPortDevice
->Timeout
= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
198 gDebugPortDevice
->Parity
= (EFI_PARITY_TYPE
) DEBUGPORT_UART_DEFAULT_PARITY
;
199 gDebugPortDevice
->DataBits
= DEBUGPORT_UART_DEFAULT_DATA_BITS
;
200 gDebugPortDevice
->StopBits
= (EFI_STOP_BITS_TYPE
) DEBUGPORT_UART_DEFAULT_STOP_BITS
;
205 // DebugPort driver binding member functions...
210 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
211 IN EFI_HANDLE ControllerHandle
,
212 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
217 Checks to see that there's not already a DebugPort interface somewhere. If so,
220 If there's a DEBUGPORT variable, the device path must match exactly. If there's
221 no DEBUGPORT variable, then device path is not checked and does not matter.
223 Checks to see that there's a serial io interface on the controller handle
224 that can be bound BY_DRIVER | EXCLUSIVE.
226 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
227 or other error returned by OpenProtocol.
242 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
243 EFI_DEVICE_PATH_PROTOCOL
*Dp2
;
244 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
245 EFI_DEBUGPORT_PROTOCOL
*DebugPortInterface
;
246 EFI_HANDLE TempHandle
;
249 // Check to see that there's not a debugport protocol already published
251 if (gBS
->LocateProtocol (&gEfiDebugPortProtocolGuid
, NULL
, (VOID
**) &DebugPortInterface
) != EFI_NOT_FOUND
) {
252 return EFI_UNSUPPORTED
;
255 // Read DebugPort variable to determine debug port selection and parameters
257 GetDebugPortVariable (gDebugPortDevice
);
259 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
261 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
262 // the closest matching handle matches the controller handle, and if it does,
263 // check to see that the remaining device path has the DebugPort GUIDed messaging
264 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
266 Dp1
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) gDebugPortDevice
->DebugPortVariable
);
268 return EFI_OUT_OF_RESOURCES
;
273 Status
= gBS
->LocateDevicePath (
274 &gEfiSerialIoProtocolGuid
,
279 if (Status
== EFI_SUCCESS
&& TempHandle
!= ControllerHandle
) {
280 Status
= EFI_UNSUPPORTED
;
283 if (Status
== EFI_SUCCESS
&& (Dp2
->Type
!= 3 || Dp2
->SubType
!= 10 || *((UINT16
*) Dp2
->Length
) != 20)) {
284 Status
= EFI_UNSUPPORTED
;
287 if (Status
== EFI_SUCCESS
&& CompareMem (&gEfiDebugPortDevicePathGuid
, Dp2
+ 1, sizeof (EFI_GUID
))) {
288 Status
= EFI_UNSUPPORTED
;
292 if (EFI_ERROR (Status
)) {
297 Status
= gBS
->OpenProtocol (
299 &gEfiSerialIoProtocolGuid
,
301 This
->DriverBindingHandle
,
303 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
305 if (EFI_ERROR (Status
)) {
311 &gEfiSerialIoProtocolGuid
,
312 This
->DriverBindingHandle
,
322 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
323 IN EFI_HANDLE ControllerHandle
,
324 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
329 Binds exclusively to serial io on the controller handle. Produces DebugPort
330 protocol and DevicePath on new handle.
343 DEBUGPORT_DEVICE_PATH DebugPortDP
;
344 EFI_DEVICE_PATH_PROTOCOL EndDP
;
345 EFI_DEVICE_PATH_PROTOCOL
*Dp1
;
347 Status
= gBS
->OpenProtocol (
349 &gEfiSerialIoProtocolGuid
,
350 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
351 This
->DriverBindingHandle
,
353 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
355 if (EFI_ERROR (Status
)) {
359 gDebugPortDevice
->SerialIoDeviceHandle
= ControllerHandle
;
362 // Initialize the Serial Io interface...
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
)) {
374 gDebugPortDevice
->BaudRate
= 0;
375 gDebugPortDevice
->Parity
= DefaultParity
;
376 gDebugPortDevice
->DataBits
= 0;
377 gDebugPortDevice
->StopBits
= DefaultStopBits
;
378 gDebugPortDevice
->ReceiveFifoDepth
= 0;
379 Status
= gDebugPortDevice
->SerialIoBinding
->SetAttributes (
380 gDebugPortDevice
->SerialIoBinding
,
381 gDebugPortDevice
->BaudRate
,
382 gDebugPortDevice
->ReceiveFifoDepth
,
383 gDebugPortDevice
->Timeout
,
384 gDebugPortDevice
->Parity
,
385 gDebugPortDevice
->DataBits
,
386 gDebugPortDevice
->StopBits
388 if (EFI_ERROR (Status
)) {
391 &gEfiSerialIoProtocolGuid
,
392 This
->DriverBindingHandle
,
399 gDebugPortDevice
->SerialIoBinding
->Reset (gDebugPortDevice
->SerialIoBinding
);
402 // Create device path instance for DebugPort
404 DebugPortDP
.Header
.Type
= MESSAGING_DEVICE_PATH
;
405 DebugPortDP
.Header
.SubType
= MSG_VENDOR_DP
;
406 SetDevicePathNodeLength (&(DebugPortDP
.Header
), sizeof (DebugPortDP
));
407 CopyMem (&DebugPortDP
.Guid
, &gEfiDebugPortDevicePathGuid
, sizeof (EFI_GUID
));
409 Dp1
= DevicePathFromHandle (ControllerHandle
);
412 SetDevicePathEndNode (Dp1
);
415 gDebugPortDevice
->DebugPortDevicePath
= AppendDevicePathNode (Dp1
, (EFI_DEVICE_PATH_PROTOCOL
*) &DebugPortDP
);
416 if (gDebugPortDevice
->DebugPortDevicePath
== NULL
) {
417 return EFI_OUT_OF_RESOURCES
;
420 // Publish DebugPort and Device Path protocols
422 Status
= gBS
->InstallMultipleProtocolInterfaces (
423 &gDebugPortDevice
->DebugPortDeviceHandle
,
424 &gEfiDevicePathProtocolGuid
,
425 gDebugPortDevice
->DebugPortDevicePath
,
426 &gEfiDebugPortProtocolGuid
,
427 &gDebugPortDevice
->DebugPortInterface
,
431 if (EFI_ERROR (Status
)) {
434 &gEfiSerialIoProtocolGuid
,
435 This
->DriverBindingHandle
,
441 // Connect debugport child to serial io
443 Status
= gBS
->OpenProtocol (
445 &gEfiSerialIoProtocolGuid
,
446 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
447 This
->DriverBindingHandle
,
448 gDebugPortDevice
->DebugPortDeviceHandle
,
449 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
452 if (EFI_ERROR (Status
)) {
458 &gDebugPortDevice
->DebugPortInterface
,
461 "DebugPort driver failed to open child controller\n\n"
467 &gEfiSerialIoProtocolGuid
,
468 This
->DriverBindingHandle
,
479 &gDebugPortDevice
->DebugPortInterface
,
482 "Hello World from the DebugPort driver\n\n"
492 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
493 IN EFI_HANDLE ControllerHandle
,
494 IN UINTN NumberOfChildren
,
495 IN EFI_HANDLE
*ChildHandleBuffer
500 We're never intending to be stopped via the driver model so this just returns
504 Per EFI 1.10 driver model
514 if (NumberOfChildren
== 0) {
516 // Close the bus driver
520 &gEfiSerialIoProtocolGuid
,
521 This
->DriverBindingHandle
,
525 gDebugPortDevice
->SerialIoBinding
= NULL
;
529 &gEfiDevicePathProtocolGuid
,
530 This
->DriverBindingHandle
,
534 FreePool (gDebugPortDevice
->DebugPortDevicePath
);
539 // Disconnect SerialIo child handle
541 Status
= gBS
->CloseProtocol (
542 gDebugPortDevice
->SerialIoDeviceHandle
,
543 &gEfiSerialIoProtocolGuid
,
544 This
->DriverBindingHandle
,
545 gDebugPortDevice
->DebugPortDeviceHandle
548 if (EFI_ERROR (Status
)) {
552 // Unpublish our protocols (DevicePath, DebugPort)
554 Status
= gBS
->UninstallMultipleProtocolInterfaces (
555 gDebugPortDevice
->DebugPortDeviceHandle
,
556 &gEfiDevicePathProtocolGuid
,
557 gDebugPortDevice
->DebugPortDevicePath
,
558 &gEfiDebugPortProtocolGuid
,
559 &gDebugPortDevice
->DebugPortInterface
,
563 if (EFI_ERROR (Status
)) {
566 &gEfiSerialIoProtocolGuid
,
567 (VOID
**) &gDebugPortDevice
->SerialIoBinding
,
568 This
->DriverBindingHandle
,
569 gDebugPortDevice
->DebugPortDeviceHandle
,
570 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
573 gDebugPortDevice
->DebugPortDeviceHandle
= NULL
;
580 // Debugport protocol member functions
585 IN EFI_DEBUGPORT_PROTOCOL
*This
590 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
591 We cannot call SerialIo:SetAttributes because it uses pool services, which use
592 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
593 SerialIo:Reset() calls SetAttributes, so it can't be used either.
595 The port itself should be fine since it was set up during initialization.
609 while (This
->Poll (This
) == EFI_SUCCESS
) {
611 This
->Read (This
, 0, &BufferSize
, &BitBucket
);
620 IN EFI_DEBUGPORT_PROTOCOL
*This
,
622 IN OUT UINTN
*BufferSize
,
628 DebugPort protocol member function. Calls SerialIo:Read() after setting
629 if it's different than the last SerialIo access.
632 IN EFI_DEBUGPORT_PROTOCOL *This
634 IN OUT UINTN *BufferSize,
643 DEBUGPORT_DEVICE
*DebugPortDevice
;
644 UINTN LocalBufferSize
;
648 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
650 LocalBufferSize
= *BufferSize
;
652 Status
= DebugPortDevice
->SerialIoBinding
->Read (
653 DebugPortDevice
->SerialIoBinding
,
657 if (Status
== EFI_TIMEOUT
) {
658 if (Timeout
> DEBUGPORT_UART_DEFAULT_TIMEOUT
) {
659 Timeout
-= DEBUGPORT_UART_DEFAULT_TIMEOUT
;
663 } else if (EFI_ERROR (Status
)) {
667 BufferPtr
+= LocalBufferSize
;
668 LocalBufferSize
= *BufferSize
- (BufferPtr
- (UINT8
*) Buffer
);
669 } while (LocalBufferSize
!= 0 && Timeout
> 0);
671 *BufferSize
= (UINTN
) (BufferPtr
- (UINT8
*) Buffer
);
679 IN EFI_DEBUGPORT_PROTOCOL
*This
,
681 IN OUT UINTN
*BufferSize
,
687 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
688 a time and does a GetControl between 8 byte writes to help insure reads are
689 interspersed This is poor-man's flow control..
692 This - Pointer to DebugPort protocol
693 Timeout - Timeout value
694 BufferSize - On input, the size of Buffer.
695 On output, the amount of data actually written.
696 Buffer - Pointer to buffer to write
699 EFI_SUCCESS - The data was written.
700 EFI_DEVICE_ERROR - The device reported an error.
701 EFI_TIMEOUT - The data write was stopped due to a timeout.
705 DEBUGPORT_DEVICE
*DebugPortDevice
;
709 UINT32 SerialControl
;
711 Status
= EFI_SUCCESS
;
712 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
715 for (Position
= 0; Position
< *BufferSize
&& !EFI_ERROR (Status
); Position
+= WriteSize
) {
716 DebugPortDevice
->SerialIoBinding
->GetControl (
717 DebugPortDevice
->SerialIoBinding
,
720 if (*BufferSize
- Position
< 8) {
721 WriteSize
= *BufferSize
- Position
;
724 Status
= DebugPortDevice
->SerialIoBinding
->Write (
725 DebugPortDevice
->SerialIoBinding
,
727 &((UINT8
*) Buffer
)[Position
]
731 *BufferSize
= Position
;
738 IN EFI_DEBUGPORT_PROTOCOL
*This
743 DebugPort protocol member function. Calls SerialIo:Write() after setting
744 if it's different than the last SerialIo access.
747 IN EFI_DEBUGPORT_PROTOCOL *This
750 EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface
751 EFI_NOT_READY - There are no characters ready to read from the DebugPort interface
752 EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo)
757 UINT32 SerialControl
;
758 DEBUGPORT_DEVICE
*DebugPortDevice
;
760 DebugPortDevice
= DEBUGPORT_DEVICE_FROM_THIS (This
);
762 Status
= DebugPortDevice
->SerialIoBinding
->GetControl (
763 DebugPortDevice
->SerialIoBinding
,
767 if (!EFI_ERROR (Status
)) {
768 if (SerialControl
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) {
769 Status
= EFI_NOT_READY
;
771 Status
= EFI_SUCCESS
;
781 EFI_HANDLE ImageHandle
786 Unload function that is registered in the LoadImage protocol. It un-installs
787 protocols produced and deallocates pool used by the driver. Called by the core
788 when unloading the driver.
791 EFI_HANDLE ImageHandle
801 if (gDebugPortDevice
->SerialIoBinding
!= NULL
) {
805 Status
= gBS
->UninstallMultipleProtocolInterfaces (
807 &gEfiDriverBindingProtocolGuid
,
808 &gDebugPortDevice
->DriverBindingInterface
,
809 &gEfiComponentNameProtocolGuid
,
810 &gDebugPortDevice
->ComponentNameInterface
,
814 if (EFI_ERROR (Status
)) {
818 // Clean up allocations
820 if (gDebugPortDevice
->DebugPortVariable
!= NULL
) {
821 FreePool (gDebugPortDevice
->DebugPortVariable
);
824 FreePool (gDebugPortDevice
);