]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
MdeModulePkg: Fix spelling mistake for occurred
[mirror_edk2.git] / MdeModulePkg / Universal / DebugPortDxe / DebugPort.c
1 /** @file
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
5 INTERRUPT CONTEXT
6
7 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include "DebugPort.h"
13
14 //
15 // Globals
16 //
17 EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = {
18 DebugPortSupported,
19 DebugPortStart,
20 DebugPortStop,
21 DEBUGPORT_DRIVER_VERSION,
22 NULL,
23 NULL
24 };
25
26 DEBUGPORT_DEVICE mDebugPortDevice = {
27 DEBUGPORT_DEVICE_SIGNATURE,
28 (EFI_HANDLE) 0,
29 (EFI_HANDLE) 0,
30 (EFI_DEVICE_PATH_PROTOCOL *) NULL,
31 {
32 DebugPortReset,
33 DebugPortWrite,
34 DebugPortRead,
35 DebugPortPoll
36 },
37 (EFI_HANDLE) 0,
38 (EFI_SERIAL_IO_PROTOCOL *) NULL,
39 DEBUGPORT_UART_DEFAULT_BAUDRATE,
40 DEBUGPORT_UART_DEFAULT_FIFO_DEPTH,
41 DEBUGPORT_UART_DEFAULT_TIMEOUT,
42 (EFI_PARITY_TYPE) DEBUGPORT_UART_DEFAULT_PARITY,
43 DEBUGPORT_UART_DEFAULT_DATA_BITS,
44 (EFI_STOP_BITS_TYPE) DEBUGPORT_UART_DEFAULT_STOP_BITS
45 };
46
47 /**
48 Local worker function to obtain device path information from DebugPort variable.
49
50 Records requested settings in DebugPort device structure.
51
52 **/
53 EFI_DEVICE_PATH_PROTOCOL *
54 GetDebugPortVariable (
55 VOID
56 )
57 {
58 UINTN DataSize;
59 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;
60 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
61
62 GetVariable2 (EFI_DEBUGPORT_VARIABLE_NAME, &gEfiDebugPortVariableGuid, (VOID **) &DebugPortVariable, &DataSize);
63 if (DebugPortVariable == NULL) {
64 return NULL;
65 }
66
67 DevicePath = DebugPortVariable;
68 while (!IsDevicePathEnd (DevicePath) && !IS_UART_DEVICEPATH (DevicePath)) {
69 DevicePath = NextDevicePathNode (DevicePath);
70 }
71
72 if (IsDevicePathEnd (DevicePath)) {
73 FreePool (DebugPortVariable);
74 return NULL;
75 } else {
76 CopyMem (
77 &mDebugPortDevice.BaudRate,
78 &((UART_DEVICE_PATH *) DevicePath)->BaudRate,
79 sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate)
80 );
81 mDebugPortDevice.ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH;
82 mDebugPortDevice.Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT;
83 CopyMem (
84 &mDebugPortDevice.Parity,
85 &((UART_DEVICE_PATH *) DevicePath)->Parity,
86 sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity)
87 );
88 CopyMem (
89 &mDebugPortDevice.DataBits,
90 &((UART_DEVICE_PATH *) DevicePath)->DataBits,
91 sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits)
92 );
93 CopyMem (
94 &mDebugPortDevice.StopBits,
95 &((UART_DEVICE_PATH *) DevicePath)->StopBits,
96 sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits)
97 );
98 return DebugPortVariable;
99 }
100 }
101
102 /**
103 Debug Port Driver entry point.
104
105 Reads DebugPort variable to determine what device and settings to use as the
106 debug port. Binds exclusively to SerialIo. Reverts to defaults if no variable
107 is found.
108
109 @param[in] ImageHandle The firmware allocated handle for the EFI image.
110 @param[in] SystemTable A pointer to the EFI System Table.
111
112 @retval EFI_SUCCESS The entry point is executed successfully.
113 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
114 @retval other Some error occurs when executing this entry point.
115
116 **/
117 EFI_STATUS
118 EFIAPI
119 InitializeDebugPortDriver (
120 IN EFI_HANDLE ImageHandle,
121 IN EFI_SYSTEM_TABLE *SystemTable
122 )
123 {
124 EFI_STATUS Status;
125
126 //
127 // Install driver model protocol(s).
128 //
129 Status = EfiLibInstallDriverBindingComponentName2 (
130 ImageHandle,
131 SystemTable,
132 &gDebugPortDriverBinding,
133 ImageHandle,
134 &gDebugPortComponentName,
135 &gDebugPortComponentName2
136 );
137 ASSERT_EFI_ERROR (Status);
138
139 return Status;
140 }
141
142 /**
143 Checks to see if there's not already a DebugPort interface somewhere.
144
145 If there's a DEBUGPORT variable, the device path must match exactly. If there's
146 no DEBUGPORT variable, then device path is not checked and does not matter.
147 Checks to see that there's a serial io interface on the controller handle
148 that can be bound BY_DRIVER | EXCLUSIVE.
149 If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED
150 or other error returned by OpenProtocol.
151
152 @param This Protocol instance pointer.
153 @param ControllerHandle Handle of device to test.
154 @param RemainingDevicePath Optional parameter use to pick a specific child
155 device to start.
156
157 @retval EFI_SUCCESS This driver supports this device.
158 @retval EFI_UNSUPPORTED Debug Port device is not supported.
159 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
160 @retval others Some error occurs.
161
162 **/
163 EFI_STATUS
164 EFIAPI
165 DebugPortSupported (
166 IN EFI_DRIVER_BINDING_PROTOCOL *This,
167 IN EFI_HANDLE ControllerHandle,
168 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
169 )
170 {
171 EFI_STATUS Status;
172 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
173 EFI_DEVICE_PATH_PROTOCOL *DebugPortVariable;
174 EFI_SERIAL_IO_PROTOCOL *SerialIo;
175 EFI_DEBUGPORT_PROTOCOL *DebugPortInterface;
176 EFI_HANDLE TempHandle;
177
178 //
179 // Check to see that there's not a debugport protocol already published,
180 // since only one standard UART serial port could be supported by this driver.
181 //
182 if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **) &DebugPortInterface) != EFI_NOT_FOUND) {
183 return EFI_UNSUPPORTED;
184 }
185 //
186 // Read DebugPort variable to determine debug port selection and parameters
187 //
188 DebugPortVariable = GetDebugPortVariable ();
189
190 if (DebugPortVariable != NULL) {
191 //
192 // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if
193 // the closest matching handle matches the controller handle, and if it does,
194 // check to see that the remaining device path has the DebugPort GUIDed messaging
195 // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned.
196 //
197 DevicePath = DebugPortVariable;
198 Status = gBS->LocateDevicePath (
199 &gEfiSerialIoProtocolGuid,
200 &DevicePath,
201 &TempHandle
202 );
203
204 if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) {
205 Status = EFI_UNSUPPORTED;
206 }
207
208 if (Status == EFI_SUCCESS &&
209 (DevicePath->Type != MESSAGING_DEVICE_PATH ||
210 DevicePath->SubType != MSG_VENDOR_DP ||
211 *((UINT16 *) DevicePath->Length) != sizeof (DEBUGPORT_DEVICE_PATH))) {
212
213 Status = EFI_UNSUPPORTED;
214 }
215
216 if (Status == EFI_SUCCESS && !CompareGuid (&gEfiDebugPortDevicePathGuid, (GUID *) (DevicePath + 1))) {
217 Status = EFI_UNSUPPORTED;
218 }
219
220 FreePool (DebugPortVariable);
221 if (EFI_ERROR (Status)) {
222 return Status;
223 }
224 }
225
226 Status = gBS->OpenProtocol (
227 ControllerHandle,
228 &gEfiSerialIoProtocolGuid,
229 (VOID **) &SerialIo,
230 This->DriverBindingHandle,
231 ControllerHandle,
232 EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
233 );
234 if (EFI_ERROR (Status)) {
235 return Status;
236 }
237
238 Status = gBS->CloseProtocol (
239 ControllerHandle,
240 &gEfiSerialIoProtocolGuid,
241 This->DriverBindingHandle,
242 ControllerHandle
243 );
244
245 return Status;
246 }
247
248 /**
249 Binds exclusively to serial io on the controller handle, Produces DebugPort
250 protocol and DevicePath on new handle.
251
252 @param This Protocol instance pointer.
253 @param ControllerHandle Handle of device to bind driver to.
254 @param RemainingDevicePath Optional parameter use to pick a specific child
255 device to start.
256
257 @retval EFI_SUCCESS This driver is added to ControllerHandle.
258 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory for device.
259 @retval others Some error occurs.
260
261 **/
262 EFI_STATUS
263 EFIAPI
264 DebugPortStart (
265 IN EFI_DRIVER_BINDING_PROTOCOL *This,
266 IN EFI_HANDLE ControllerHandle,
267 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
268 )
269 {
270 EFI_STATUS Status;
271 DEBUGPORT_DEVICE_PATH DebugPortDP;
272 EFI_DEVICE_PATH_PROTOCOL EndDP;
273 EFI_DEVICE_PATH_PROTOCOL *Dp1;
274
275 Status = gBS->OpenProtocol (
276 ControllerHandle,
277 &gEfiSerialIoProtocolGuid,
278 (VOID **) &mDebugPortDevice.SerialIoBinding,
279 This->DriverBindingHandle,
280 ControllerHandle,
281 EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
282 );
283 if (EFI_ERROR (Status)) {
284 return Status;
285 }
286
287 mDebugPortDevice.SerialIoDeviceHandle = ControllerHandle;
288
289 //
290 // Initialize the Serial Io interface...
291 //
292 Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
293 mDebugPortDevice.SerialIoBinding,
294 mDebugPortDevice.BaudRate,
295 mDebugPortDevice.ReceiveFifoDepth,
296 mDebugPortDevice.Timeout,
297 mDebugPortDevice.Parity,
298 mDebugPortDevice.DataBits,
299 mDebugPortDevice.StopBits
300 );
301 if (EFI_ERROR (Status)) {
302 mDebugPortDevice.BaudRate = 0;
303 mDebugPortDevice.Parity = DefaultParity;
304 mDebugPortDevice.DataBits = 0;
305 mDebugPortDevice.StopBits = DefaultStopBits;
306 mDebugPortDevice.ReceiveFifoDepth = 0;
307 Status = mDebugPortDevice.SerialIoBinding->SetAttributes (
308 mDebugPortDevice.SerialIoBinding,
309 mDebugPortDevice.BaudRate,
310 mDebugPortDevice.ReceiveFifoDepth,
311 mDebugPortDevice.Timeout,
312 mDebugPortDevice.Parity,
313 mDebugPortDevice.DataBits,
314 mDebugPortDevice.StopBits
315 );
316 if (EFI_ERROR (Status)) {
317 gBS->CloseProtocol (
318 ControllerHandle,
319 &gEfiSerialIoProtocolGuid,
320 This->DriverBindingHandle,
321 ControllerHandle
322 );
323 return Status;
324 }
325 }
326
327 mDebugPortDevice.SerialIoBinding->Reset (mDebugPortDevice.SerialIoBinding);
328
329 //
330 // Create device path instance for DebugPort
331 //
332 DebugPortDP.Header.Type = MESSAGING_DEVICE_PATH;
333 DebugPortDP.Header.SubType = MSG_VENDOR_DP;
334 SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP));
335 CopyGuid (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid);
336
337 Dp1 = DevicePathFromHandle (ControllerHandle);
338 if (Dp1 == NULL) {
339 Dp1 = &EndDP;
340 SetDevicePathEndNode (Dp1);
341 }
342
343 mDebugPortDevice.DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP);
344 if (mDebugPortDevice.DebugPortDevicePath == NULL) {
345 return EFI_OUT_OF_RESOURCES;
346 }
347 //
348 // Publish DebugPort and Device Path protocols
349 //
350 Status = gBS->InstallMultipleProtocolInterfaces (
351 &mDebugPortDevice.DebugPortDeviceHandle,
352 &gEfiDevicePathProtocolGuid,
353 mDebugPortDevice.DebugPortDevicePath,
354 &gEfiDebugPortProtocolGuid,
355 &mDebugPortDevice.DebugPortInterface,
356 NULL
357 );
358
359 if (EFI_ERROR (Status)) {
360 gBS->CloseProtocol (
361 ControllerHandle,
362 &gEfiSerialIoProtocolGuid,
363 This->DriverBindingHandle,
364 ControllerHandle
365 );
366 return Status;
367 }
368 //
369 // Connect debugport child to serial io
370 //
371 Status = gBS->OpenProtocol (
372 ControllerHandle,
373 &gEfiSerialIoProtocolGuid,
374 (VOID **) &mDebugPortDevice.SerialIoBinding,
375 This->DriverBindingHandle,
376 mDebugPortDevice.DebugPortDeviceHandle,
377 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
378 );
379
380 if (EFI_ERROR (Status)) {
381 gBS->CloseProtocol (
382 ControllerHandle,
383 &gEfiSerialIoProtocolGuid,
384 This->DriverBindingHandle,
385 ControllerHandle
386 );
387 return Status;
388 }
389
390 return EFI_SUCCESS;
391 }
392
393 /**
394 Stop this driver on ControllerHandle by removing Serial IO protocol on
395 the ControllerHandle.
396
397 @param This Protocol instance pointer.
398 @param ControllerHandle Handle of device to stop driver on
399 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
400 children is zero stop the entire bus driver.
401 @param ChildHandleBuffer List of Child Handles to Stop.
402
403 @retval EFI_SUCCESS This driver is removed ControllerHandle.
404 @retval other This driver was not removed from this device.
405
406 **/
407 EFI_STATUS
408 EFIAPI
409 DebugPortStop (
410 IN EFI_DRIVER_BINDING_PROTOCOL *This,
411 IN EFI_HANDLE ControllerHandle,
412 IN UINTN NumberOfChildren,
413 IN EFI_HANDLE *ChildHandleBuffer
414 )
415 {
416 EFI_STATUS Status;
417
418 if (NumberOfChildren == 0) {
419 //
420 // Close the bus driver
421 //
422 gBS->CloseProtocol (
423 ControllerHandle,
424 &gEfiSerialIoProtocolGuid,
425 This->DriverBindingHandle,
426 ControllerHandle
427 );
428
429 mDebugPortDevice.SerialIoBinding = NULL;
430
431 gBS->CloseProtocol (
432 ControllerHandle,
433 &gEfiDevicePathProtocolGuid,
434 This->DriverBindingHandle,
435 ControllerHandle
436 );
437
438 FreePool (mDebugPortDevice.DebugPortDevicePath);
439
440 return EFI_SUCCESS;
441 } else {
442 //
443 // Disconnect SerialIo child handle
444 //
445 Status = gBS->CloseProtocol (
446 mDebugPortDevice.SerialIoDeviceHandle,
447 &gEfiSerialIoProtocolGuid,
448 This->DriverBindingHandle,
449 mDebugPortDevice.DebugPortDeviceHandle
450 );
451
452 if (EFI_ERROR (Status)) {
453 return Status;
454 }
455 //
456 // Unpublish our protocols (DevicePath, DebugPort)
457 //
458 Status = gBS->UninstallMultipleProtocolInterfaces (
459 mDebugPortDevice.DebugPortDeviceHandle,
460 &gEfiDevicePathProtocolGuid,
461 mDebugPortDevice.DebugPortDevicePath,
462 &gEfiDebugPortProtocolGuid,
463 &mDebugPortDevice.DebugPortInterface,
464 NULL
465 );
466
467 if (EFI_ERROR (Status)) {
468 gBS->OpenProtocol (
469 ControllerHandle,
470 &gEfiSerialIoProtocolGuid,
471 (VOID **) &mDebugPortDevice.SerialIoBinding,
472 This->DriverBindingHandle,
473 mDebugPortDevice.DebugPortDeviceHandle,
474 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
475 );
476 } else {
477 mDebugPortDevice.DebugPortDeviceHandle = NULL;
478 }
479 }
480
481 return Status;
482 }
483
484 /**
485 DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer.
486 We cannot call SerialIo:SetAttributes because it uses pool services, which use
487 locks, which affect TPL, so it's not interrupt context safe or re-entrant.
488 SerialIo:Reset() calls SetAttributes, so it can't be used either.
489
490 The port itself should be fine since it was set up during initialization.
491
492 @param This Protocol instance pointer.
493
494 @return EFI_SUCCESS Always.
495
496 **/
497 EFI_STATUS
498 EFIAPI
499 DebugPortReset (
500 IN EFI_DEBUGPORT_PROTOCOL *This
501 )
502 {
503 UINTN BufferSize;
504 UINTN BitBucket;
505
506 while (This->Poll (This) == EFI_SUCCESS) {
507 BufferSize = 1;
508 This->Read (This, 0, &BufferSize, &BitBucket);
509 }
510
511 return EFI_SUCCESS;
512 }
513
514 /**
515 DebugPort protocol member function. Calls SerialIo:Read() after setting
516 if it's different than the last SerialIo access.
517
518 @param This Pointer to DebugPort protocol.
519 @param Timeout Timeout value.
520 @param BufferSize On input, the size of Buffer.
521 On output, the amount of data actually written.
522 @param Buffer Pointer to buffer to read.
523
524 @retval EFI_SUCCESS
525 @retval others
526
527 **/
528 EFI_STATUS
529 EFIAPI
530 DebugPortRead (
531 IN EFI_DEBUGPORT_PROTOCOL *This,
532 IN UINT32 Timeout,
533 IN OUT UINTN *BufferSize,
534 IN VOID *Buffer
535 )
536 {
537 DEBUGPORT_DEVICE *DebugPortDevice;
538 UINTN LocalBufferSize;
539 EFI_STATUS Status;
540 UINT8 *BufferPtr;
541
542 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
543 BufferPtr = Buffer;
544 LocalBufferSize = *BufferSize;
545
546 do {
547 Status = DebugPortDevice->SerialIoBinding->Read (
548 DebugPortDevice->SerialIoBinding,
549 &LocalBufferSize,
550 BufferPtr
551 );
552 if (Status == EFI_TIMEOUT) {
553 if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) {
554 Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT;
555 } else {
556 Timeout = 0;
557 }
558 } else if (EFI_ERROR (Status)) {
559 break;
560 }
561
562 BufferPtr += LocalBufferSize;
563 LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer);
564 } while (LocalBufferSize != 0 && Timeout > 0);
565
566 *BufferSize = (UINTN) BufferPtr - (UINTN) Buffer;
567
568 return Status;
569 }
570
571 /**
572 DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at
573 a time and does a GetControl between 8 byte writes to help insure reads are
574 interspersed This is poor-man's flow control.
575
576 @param This Pointer to DebugPort protocol.
577 @param Timeout Timeout value.
578 @param BufferSize On input, the size of Buffer.
579 On output, the amount of data actually written.
580 @param Buffer Pointer to buffer to read.
581
582 @retval EFI_SUCCESS The data was written.
583 @retval others Fails when writting datas to debug port device.
584
585 **/
586 EFI_STATUS
587 EFIAPI
588 DebugPortWrite (
589 IN EFI_DEBUGPORT_PROTOCOL *This,
590 IN UINT32 Timeout,
591 IN OUT UINTN *BufferSize,
592 OUT VOID *Buffer
593 )
594 {
595 DEBUGPORT_DEVICE *DebugPortDevice;
596 UINTN Position;
597 UINTN WriteSize;
598 EFI_STATUS Status;
599 UINT32 SerialControl;
600
601 Status = EFI_SUCCESS;
602 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
603
604 WriteSize = 8;
605 for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) {
606 DebugPortDevice->SerialIoBinding->GetControl (
607 DebugPortDevice->SerialIoBinding,
608 &SerialControl
609 );
610 if (*BufferSize - Position < 8) {
611 WriteSize = *BufferSize - Position;
612 }
613
614 Status = DebugPortDevice->SerialIoBinding->Write (
615 DebugPortDevice->SerialIoBinding,
616 &WriteSize,
617 &((UINT8 *) Buffer)[Position]
618 );
619 }
620
621 *BufferSize = Position;
622 return Status;
623 }
624
625 /**
626 DebugPort protocol member function. Calls SerialIo:Write() after setting
627 if it's different than the last SerialIo access.
628
629 @param This Pointer to DebugPort protocol.
630
631 @retval EFI_SUCCESS At least 1 character is ready to be read from
632 the DebugPort interface.
633 @retval EFI_NOT_READY There are no characters ready to read from the
634 DebugPort interface
635 @retval EFI_DEVICE_ERROR A hardware failure occurred... (from SerialIo)
636
637 **/
638 EFI_STATUS
639 EFIAPI
640 DebugPortPoll (
641 IN EFI_DEBUGPORT_PROTOCOL *This
642 )
643 {
644 EFI_STATUS Status;
645 UINT32 SerialControl;
646 DEBUGPORT_DEVICE *DebugPortDevice;
647
648 DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This);
649
650 Status = DebugPortDevice->SerialIoBinding->GetControl (
651 DebugPortDevice->SerialIoBinding,
652 &SerialControl
653 );
654
655 if (!EFI_ERROR (Status)) {
656 if ((SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
657 Status = EFI_NOT_READY;
658 } else {
659 Status = EFI_SUCCESS;
660 }
661 }
662
663 return Status;
664 }
665
666 /**
667 Unload function that is registered in the LoadImage protocol. It un-installs
668 protocols produced and deallocates pool used by the driver. Called by the core
669 when unloading the driver.
670
671 @param ImageHandle
672
673 @retval EFI_SUCCESS Unload Debug Port driver successfully.
674 @retval EFI_ABORTED Serial IO is still binding.
675
676 **/
677 EFI_STATUS
678 EFIAPI
679 ImageUnloadHandler (
680 EFI_HANDLE ImageHandle
681 )
682 {
683 EFI_STATUS Status;
684 VOID *ComponentName;
685 VOID *ComponentName2;
686
687 if (mDebugPortDevice.SerialIoBinding != NULL) {
688 return EFI_ABORTED;
689 }
690
691 //
692 // Driver is stopped already.
693 //
694 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentNameProtocolGuid, &ComponentName);
695 if (EFI_ERROR (Status)) {
696 ComponentName = NULL;
697 }
698
699 Status = gBS->HandleProtocol (ImageHandle, &gEfiComponentName2ProtocolGuid, &ComponentName2);
700 if (EFI_ERROR (Status)) {
701 ComponentName2 = NULL;
702 }
703
704 if (ComponentName == NULL) {
705 if (ComponentName2 == NULL) {
706 Status = gBS->UninstallMultipleProtocolInterfaces (
707 ImageHandle,
708 &gEfiDriverBindingProtocolGuid, &gDebugPortDriverBinding,
709 NULL
710 );
711 } else {
712 Status = gBS->UninstallMultipleProtocolInterfaces (
713 ImageHandle,
714 &gEfiDriverBindingProtocolGuid, &gDebugPortDriverBinding,
715 &gEfiComponentName2ProtocolGuid, ComponentName2,
716 NULL
717 );
718 }
719 } else {
720 if (ComponentName2 == NULL) {
721 Status = gBS->UninstallMultipleProtocolInterfaces (
722 ImageHandle,
723 &gEfiDriverBindingProtocolGuid, &gDebugPortDriverBinding,
724 &gEfiComponentNameProtocolGuid, ComponentName,
725 NULL
726 );
727 } else {
728 Status = gBS->UninstallMultipleProtocolInterfaces (
729 ImageHandle,
730 &gEfiDriverBindingProtocolGuid, &gDebugPortDriverBinding,
731 &gEfiComponentNameProtocolGuid, ComponentName,
732 &gEfiComponentName2ProtocolGuid, ComponentName2,
733 NULL
734 );
735 }
736 }
737
738 return Status;
739 }