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 Status; 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 Status = gBS->CloseProtocol ( 245 ControllerHandle, 246 &gEfiSerialIoProtocolGuid, 247 This->DriverBindingHandle, 248 ControllerHandle 249 ); 250 251 return Status; 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 } 746