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