1 /** @file 2 Serial driver for PCI or SIO UARTS. 3 4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Serial.h" 16 17 // 18 // ISA Serial Driver Global Variables 19 // 20 21 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = { 22 SerialControllerDriverSupported, 23 SerialControllerDriverStart, 24 SerialControllerDriverStop, 25 0xa, 26 NULL, 27 NULL 28 }; 29 30 CONTROLLER_DEVICE_PATH mControllerDevicePathTemplate = { 31 { 32 HARDWARE_DEVICE_PATH, 33 HW_CONTROLLER_DP, 34 { 35 (UINT8) (sizeof (CONTROLLER_DEVICE_PATH)), 36 (UINT8) ((sizeof (CONTROLLER_DEVICE_PATH)) >> 8) 37 } 38 }, 39 0 40 }; 41 42 SERIAL_DEV gSerialDevTemplate = { 43 SERIAL_DEV_SIGNATURE, 44 NULL, 45 { 46 SERIAL_IO_INTERFACE_REVISION, 47 SerialReset, 48 SerialSetAttributes, 49 SerialSetControl, 50 SerialGetControl, 51 SerialWrite, 52 SerialRead, 53 NULL 54 }, // SerialIo 55 { 56 SERIAL_PORT_SUPPORT_CONTROL_MASK, 57 SERIAL_PORT_DEFAULT_TIMEOUT, 58 0, 59 16, 60 0, 61 0, 62 0 63 }, // SerialMode 64 NULL, // DevicePath 65 NULL, // ParentDevicePath 66 { 67 { 68 MESSAGING_DEVICE_PATH, 69 MSG_UART_DP, 70 { 71 (UINT8) (sizeof (UART_DEVICE_PATH)), 72 (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) 73 } 74 }, 75 0, 0, 0, 0, 0 76 }, // UartDevicePath 77 0, // BaseAddress 78 FALSE, // MmioAccess 79 1, // RegisterStride 80 0, // ClockRate 81 16, // ReceiveFifoDepth 82 { 0, 0 }, // Receive; 83 16, // TransmitFifoDepth 84 { 0, 0 }, // Transmit; 85 FALSE, // SoftwareLoopbackEnable; 86 FALSE, // HardwareFlowControl; 87 NULL, // *ControllerNameTable; 88 FALSE, // ContainsControllerNode; 89 0, // Instance; 90 NULL // *PciDeviceInfo; 91 }; 92 93 /** 94 Check the device path node whether it's the Flow Control node or not. 95 96 @param[in] FlowControl The device path node to be checked. 97 98 @retval TRUE It's the Flow Control node. 99 @retval FALSE It's not. 100 101 **/ 102 BOOLEAN 103 IsUartFlowControlDevicePathNode ( 104 IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl 105 ) 106 { 107 return (BOOLEAN) ( 108 (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && 109 (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && 110 (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) 111 ); 112 } 113 114 /** 115 The user Entry Point for module PciSioSerial. The user code starts with this function. 116 117 @param[in] ImageHandle The firmware allocated handle for the EFI image. 118 @param[in] SystemTable A pointer to the EFI System Table. 119 120 @retval EFI_SUCCESS The entry point is executed successfully. 121 @retval other Some error occurs when executing this entry point. 122 123 **/ 124 EFI_STATUS 125 EFIAPI 126 InitializePciSioSerial ( 127 IN EFI_HANDLE ImageHandle, 128 IN EFI_SYSTEM_TABLE *SystemTable 129 ) 130 { 131 EFI_STATUS Status; 132 133 // 134 // Install driver model protocol(s). 135 // 136 Status = EfiLibInstallDriverBindingComponentName2 ( 137 ImageHandle, 138 SystemTable, 139 &gSerialControllerDriver, 140 ImageHandle, 141 &gPciSioSerialComponentName, 142 &gPciSioSerialComponentName2 143 ); 144 ASSERT_EFI_ERROR (Status); 145 146 // 147 // Initialize UART default setting in gSerialDevTempate 148 // 149 gSerialDevTemplate.SerialMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); 150 gSerialDevTemplate.SerialMode.DataBits = PcdGet8 (PcdUartDefaultDataBits); 151 gSerialDevTemplate.SerialMode.Parity = PcdGet8 (PcdUartDefaultParity); 152 gSerialDevTemplate.SerialMode.StopBits = PcdGet8 (PcdUartDefaultStopBits); 153 gSerialDevTemplate.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); 154 gSerialDevTemplate.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits); 155 gSerialDevTemplate.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity); 156 gSerialDevTemplate.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits); 157 gSerialDevTemplate.ClockRate = PcdGet32 (PcdSerialClockRate); 158 159 return Status; 160 } 161 162 /** 163 Return whether the controller is a SIO serial controller. 164 165 @param Controller The controller handle. 166 167 @retval EFI_SUCCESS The controller is a SIO serial controller. 168 @retval others The controller is not a SIO serial controller. 169 **/ 170 EFI_STATUS 171 IsSioSerialController ( 172 EFI_HANDLE Controller 173 ) 174 { 175 EFI_STATUS Status; 176 EFI_SIO_PROTOCOL *Sio; 177 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 178 ACPI_HID_DEVICE_PATH *Acpi; 179 180 // 181 // Open the IO Abstraction(s) needed to perform the supported test 182 // 183 Status = gBS->OpenProtocol ( 184 Controller, 185 &gEfiSioProtocolGuid, 186 (VOID **) &Sio, 187 gSerialControllerDriver.DriverBindingHandle, 188 Controller, 189 EFI_OPEN_PROTOCOL_BY_DRIVER 190 ); 191 if (Status == EFI_ALREADY_STARTED) { 192 return EFI_SUCCESS; 193 } 194 195 if (!EFI_ERROR (Status)) { 196 // 197 // Close the I/O Abstraction(s) used to perform the supported test 198 // 199 gBS->CloseProtocol ( 200 Controller, 201 &gEfiSioProtocolGuid, 202 gSerialControllerDriver.DriverBindingHandle, 203 Controller 204 ); 205 206 Status = gBS->OpenProtocol ( 207 Controller, 208 &gEfiDevicePathProtocolGuid, 209 (VOID **) &DevicePath, 210 gSerialControllerDriver.DriverBindingHandle, 211 Controller, 212 EFI_OPEN_PROTOCOL_BY_DRIVER 213 ); 214 ASSERT (Status != EFI_ALREADY_STARTED); 215 216 if (!EFI_ERROR (Status)) { 217 do { 218 Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; 219 DevicePath = NextDevicePathNode (DevicePath); 220 } while (!IsDevicePathEnd (DevicePath)); 221 222 if (DevicePathType (Acpi) != ACPI_DEVICE_PATH || 223 (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP) || 224 Acpi->HID != EISA_PNP_ID (0x501) 225 ) { 226 Status = EFI_UNSUPPORTED; 227 } 228 } 229 230 // 231 // Close protocol, don't use device path protocol in the Support() function 232 // 233 gBS->CloseProtocol ( 234 Controller, 235 &gEfiDevicePathProtocolGuid, 236 gSerialControllerDriver.DriverBindingHandle, 237 Controller 238 ); 239 } 240 return Status; 241 } 242 243 /** 244 Return whether the controller is a PCI serial controller. 245 246 @param Controller The controller handle. 247 248 @retval EFI_SUCCESS The controller is a PCI serial controller. 249 @retval others The controller is not a PCI serial controller. 250 **/ 251 EFI_STATUS 252 IsPciSerialController ( 253 EFI_HANDLE Controller 254 ) 255 { 256 EFI_STATUS Status; 257 EFI_PCI_IO_PROTOCOL *PciIo; 258 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 259 PCI_TYPE00 Pci; 260 PCI_SERIAL_PARAMETER *PciSerialParameter; 261 262 // 263 // Open the IO Abstraction(s) needed to perform the supported test 264 // 265 Status = gBS->OpenProtocol ( 266 Controller, 267 &gEfiPciIoProtocolGuid, 268 (VOID **) &PciIo, 269 gSerialControllerDriver.DriverBindingHandle, 270 Controller, 271 EFI_OPEN_PROTOCOL_BY_DRIVER 272 ); 273 if (Status == EFI_ALREADY_STARTED) { 274 return EFI_SUCCESS; 275 } 276 277 if (!EFI_ERROR (Status)) { 278 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); 279 if (!EFI_ERROR (Status)) { 280 if (!IS_PCI_16550_SERIAL (&Pci)) { 281 for (PciSerialParameter = (PCI_SERIAL_PARAMETER *) PcdGetPtr (PcdPciSerialParameters) 282 ; PciSerialParameter->VendorId != 0xFFFF 283 ; PciSerialParameter++ 284 ) { 285 if ((Pci.Hdr.VendorId == PciSerialParameter->VendorId) && 286 (Pci.Hdr.DeviceId == PciSerialParameter->DeviceId) 287 ) { 288 break; 289 } 290 } 291 if (PciSerialParameter->VendorId == 0xFFFF) { 292 Status = EFI_UNSUPPORTED; 293 } else { 294 Status = EFI_SUCCESS; 295 } 296 } 297 } 298 299 // 300 // Close the I/O Abstraction(s) used to perform the supported test 301 // 302 gBS->CloseProtocol ( 303 Controller, 304 &gEfiPciIoProtocolGuid, 305 gSerialControllerDriver.DriverBindingHandle, 306 Controller 307 ); 308 } 309 if (EFI_ERROR (Status)) { 310 return Status; 311 } 312 313 // 314 // Open the EFI Device Path protocol needed to perform the supported test 315 // 316 Status = gBS->OpenProtocol ( 317 Controller, 318 &gEfiDevicePathProtocolGuid, 319 (VOID **) &DevicePath, 320 gSerialControllerDriver.DriverBindingHandle, 321 Controller, 322 EFI_OPEN_PROTOCOL_BY_DRIVER 323 ); 324 ASSERT (Status != EFI_ALREADY_STARTED); 325 326 // 327 // Close protocol, don't use device path protocol in the Support() function 328 // 329 gBS->CloseProtocol ( 330 Controller, 331 &gEfiDevicePathProtocolGuid, 332 gSerialControllerDriver.DriverBindingHandle, 333 Controller 334 ); 335 336 return Status; 337 } 338 339 /** 340 Check to see if this driver supports the given controller 341 342 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 343 @param Controller The handle of the controller to test. 344 @param RemainingDevicePath A pointer to the remaining portion of a device path. 345 346 @return EFI_SUCCESS This driver can support the given controller 347 348 **/ 349 EFI_STATUS 350 EFIAPI 351 SerialControllerDriverSupported ( 352 IN EFI_DRIVER_BINDING_PROTOCOL *This, 353 IN EFI_HANDLE Controller, 354 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 355 ) 356 357 { 358 EFI_STATUS Status; 359 UART_DEVICE_PATH *Uart; 360 UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 361 362 // 363 // Test RemainingDevicePath 364 // 365 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) { 366 Status = EFI_UNSUPPORTED; 367 368 Uart = SkipControllerDevicePathNode (RemainingDevicePath, NULL, NULL); 369 if (DevicePathType (Uart) != MESSAGING_DEVICE_PATH || 370 DevicePathSubType (Uart) != MSG_UART_DP || 371 DevicePathNodeLength (Uart) != sizeof (UART_DEVICE_PATH) 372 ) { 373 return EFI_UNSUPPORTED; 374 } 375 376 // 377 // Do a rough check because Clock Rate is unknown until DriverBindingStart() 378 // 379 if (!VerifyUartParameters (0, Uart->BaudRate, Uart->DataBits, Uart->Parity, Uart->StopBits, NULL, NULL)) { 380 return EFI_UNSUPPORTED; 381 } 382 383 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 384 if (IsUartFlowControlDevicePathNode (FlowControl)) { 385 // 386 // If the second node is Flow Control Node, 387 // return error when it request other than hardware flow control. 388 // 389 if ((ReadUnaligned32 (&FlowControl->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { 390 return EFI_UNSUPPORTED; 391 } 392 } 393 } 394 395 Status = IsSioSerialController (Controller); 396 if (EFI_ERROR (Status)) { 397 Status = IsPciSerialController (Controller); 398 } 399 return Status; 400 } 401 402 /** 403 Create the child serial device instance. 404 405 @param Controller The parent controller handle. 406 @param Uart Pointer to the UART device path node in RemainingDevicePath, 407 or NULL if RemainingDevicePath is NULL. 408 @param ParentDevicePath Pointer to the parent device path. 409 @param CreateControllerNode TRUE to create the controller node. 410 @param Instance Instance number of the serial device. 411 The value will be set to the controller node 412 if CreateControllerNode is TRUE. 413 @param ParentIo A union type pointer to either Sio or PciIo. 414 @param PciSerialParameter The PCI serial parameter to be used by current serial device. 415 NULL for SIO serial device. 416 @param PciDeviceInfo The PCI device info for the current serial device. 417 NULL for SIO serial device. 418 419 @retval EFI_SUCCESS The serial device was created successfully. 420 @retval others The serial device wasn't created. 421 **/ 422 EFI_STATUS 423 CreateSerialDevice ( 424 IN EFI_HANDLE Controller, 425 IN UART_DEVICE_PATH *Uart, 426 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 427 IN BOOLEAN CreateControllerNode, 428 IN UINT32 Instance, 429 IN PARENT_IO_PROTOCOL_PTR ParentIo, 430 IN PCI_SERIAL_PARAMETER *PciSerialParameter, OPTIONAL 431 IN PCI_DEVICE_INFO *PciDeviceInfo OPTIONAL 432 ) 433 { 434 EFI_STATUS Status; 435 SERIAL_DEV *SerialDevice; 436 UINT8 BarIndex; 437 UINT64 Offset; 438 UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 439 UINT32 FlowControlMap; 440 ACPI_RESOURCE_HEADER_PTR Resources; 441 EFI_ACPI_IO_PORT_DESCRIPTOR *Io; 442 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo; 443 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace; 444 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 445 446 BarIndex = 0; 447 Offset = 0; 448 FlowControl = NULL; 449 FlowControlMap = 0; 450 451 // 452 // Initialize the serial device instance 453 // 454 SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTemplate); 455 ASSERT (SerialDevice != NULL); 456 457 SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode); 458 SerialDevice->ParentDevicePath = ParentDevicePath; 459 SerialDevice->PciDeviceInfo = PciDeviceInfo; 460 SerialDevice->Instance = Instance; 461 462 if (Uart != NULL) { 463 CopyMem (&SerialDevice->UartDevicePath, Uart, sizeof (UART_DEVICE_PATH)); 464 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 465 if (IsUartFlowControlDevicePathNode (FlowControl)) { 466 FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap); 467 } else { 468 FlowControl = NULL; 469 } 470 } 471 472 // 473 // For PCI serial device, use the information from PCD 474 // 475 if (PciSerialParameter != NULL) { 476 BarIndex = (PciSerialParameter->BarIndex == PCI_BAR_ALL) ? 0 : PciSerialParameter->BarIndex; 477 Offset = PciSerialParameter->Offset; 478 if (PciSerialParameter->RegisterStride != 0) { 479 SerialDevice->RegisterStride = PciSerialParameter->RegisterStride; 480 } 481 if (PciSerialParameter->ClockRate != 0) { 482 SerialDevice->ClockRate = PciSerialParameter->ClockRate; 483 } 484 if (PciSerialParameter->ReceiveFifoDepth != 0) { 485 SerialDevice->ReceiveFifoDepth = PciSerialParameter->ReceiveFifoDepth; 486 } 487 if (PciSerialParameter->TransmitFifoDepth != 0) { 488 SerialDevice->TransmitFifoDepth = PciSerialParameter->TransmitFifoDepth; 489 } 490 } 491 492 // 493 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade. 494 // DriverBindingStart() shouldn't create a handle with different UART device path. 495 // 496 if (!VerifyUartParameters (SerialDevice->ClockRate, SerialDevice->UartDevicePath.BaudRate, SerialDevice->UartDevicePath.DataBits, 497 SerialDevice->UartDevicePath.Parity, SerialDevice->UartDevicePath.StopBits, NULL, NULL 498 )) { 499 Status = EFI_INVALID_PARAMETER; 500 goto CreateError; 501 } 502 503 if (PciSerialParameter == NULL) { 504 Status = ParentIo.Sio->GetResources (ParentIo.Sio, &Resources); 505 } else { 506 Status = ParentIo.PciIo->GetBarAttributes (ParentIo.PciIo, BarIndex, NULL, (VOID **) &Resources); 507 } 508 509 if (!EFI_ERROR (Status)) { 510 // 511 // Get the base address information from ACPI resource descriptor. 512 // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio; 513 // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo. 514 // 515 while ((Resources.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) && (SerialDevice->BaseAddress == 0)) { 516 switch (Resources.SmallHeader->Byte) { 517 case ACPI_IO_PORT_DESCRIPTOR: 518 Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) Resources.SmallHeader; 519 if (Io->Length != 0) { 520 SerialDevice->BaseAddress = Io->BaseAddressMin; 521 } 522 break; 523 524 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: 525 FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) Resources.SmallHeader; 526 if (FixedIo->Length != 0) { 527 SerialDevice->BaseAddress = FixedIo->BaseAddress; 528 } 529 break; 530 531 case ACPI_ADDRESS_SPACE_DESCRIPTOR: 532 AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Resources.SmallHeader; 533 if (AddressSpace->AddrLen != 0) { 534 if (AddressSpace->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { 535 SerialDevice->MmioAccess = TRUE; 536 } 537 SerialDevice->BaseAddress = AddressSpace->AddrRangeMin + Offset; 538 } 539 break; 540 } 541 542 if (Resources.SmallHeader->Bits.Type == 0) { 543 Resources.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) Resources.SmallHeader 544 + Resources.SmallHeader->Bits.Length 545 + sizeof (*Resources.SmallHeader)); 546 } else { 547 Resources.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) Resources.LargeHeader 548 + Resources.LargeHeader->Length 549 + sizeof (*Resources.LargeHeader)); 550 } 551 } 552 } 553 554 if (SerialDevice->BaseAddress == 0) { 555 Status = EFI_INVALID_PARAMETER; 556 goto CreateError; 557 } 558 559 SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); 560 561 // 562 // Report status code the serial present 563 // 564 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 565 EFI_PROGRESS_CODE, 566 EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT, 567 SerialDevice->ParentDevicePath 568 ); 569 570 if (!SerialPresent (SerialDevice)) { 571 Status = EFI_DEVICE_ERROR; 572 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 573 EFI_ERROR_CODE, 574 EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT, 575 SerialDevice->ParentDevicePath 576 ); 577 goto CreateError; 578 } 579 580 // 581 // 1. Append Controller device path node. 582 // 583 if (CreateControllerNode) { 584 mControllerDevicePathTemplate.ControllerNumber = SerialDevice->Instance; 585 SerialDevice->DevicePath = AppendDevicePathNode ( 586 SerialDevice->ParentDevicePath, 587 (EFI_DEVICE_PATH_PROTOCOL *) &mControllerDevicePathTemplate 588 ); 589 SerialDevice->ContainsControllerNode = TRUE; 590 } 591 592 // 593 // 2. Append UART device path node. 594 // The Uart setings are zero here. 595 // SetAttribute() will update them to match the default setings. 596 // 597 TempDevicePath = SerialDevice->DevicePath; 598 if (TempDevicePath != NULL) { 599 SerialDevice->DevicePath = AppendDevicePathNode ( 600 TempDevicePath, 601 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath 602 ); 603 FreePool (TempDevicePath); 604 } else { 605 SerialDevice->DevicePath = AppendDevicePathNode ( 606 SerialDevice->ParentDevicePath, 607 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath 608 ); 609 } 610 // 611 // 3. Append the Flow Control device path node. 612 // Only produce the Flow Control node when remaining device path has it 613 // 614 if (FlowControl != NULL) { 615 TempDevicePath = SerialDevice->DevicePath; 616 if (TempDevicePath != NULL) { 617 SerialDevice->DevicePath = AppendDevicePathNode ( 618 TempDevicePath, 619 (EFI_DEVICE_PATH_PROTOCOL *) FlowControl 620 ); 621 FreePool (TempDevicePath); 622 } 623 } 624 ASSERT (SerialDevice->DevicePath != NULL); 625 626 // 627 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. 628 // 629 SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate; 630 SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits; 631 SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity; 632 SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits; 633 634 // 635 // Issue a reset to initialize the COM port 636 // 637 Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo); 638 if (EFI_ERROR (Status)) { 639 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 640 EFI_ERROR_CODE, 641 EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT, 642 SerialDevice->DevicePath 643 ); 644 goto CreateError; 645 } 646 647 AddName (SerialDevice, Instance); 648 // 649 // Install protocol interfaces for the serial device. 650 // 651 Status = gBS->InstallMultipleProtocolInterfaces ( 652 &SerialDevice->Handle, 653 &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 654 &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 655 NULL 656 ); 657 if (EFI_ERROR (Status)) { 658 goto CreateError; 659 } 660 // 661 // Open For Child Device 662 // 663 Status = gBS->OpenProtocol ( 664 Controller, 665 PciSerialParameter != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 666 (VOID **) &ParentIo, 667 gSerialControllerDriver.DriverBindingHandle, 668 SerialDevice->Handle, 669 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 670 ); 671 672 if (EFI_ERROR (Status)) { 673 gBS->UninstallMultipleProtocolInterfaces ( 674 &SerialDevice->Handle, 675 &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 676 &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 677 NULL 678 ); 679 } 680 681 CreateError: 682 if (EFI_ERROR (Status)) { 683 if (SerialDevice->DevicePath != NULL) { 684 FreePool (SerialDevice->DevicePath); 685 } 686 if (SerialDevice->ControllerNameTable != NULL) { 687 FreeUnicodeStringTable (SerialDevice->ControllerNameTable); 688 } 689 FreePool (SerialDevice); 690 } 691 return Status; 692 } 693 694 /** 695 Returns an array of pointers containing all the child serial device pointers. 696 697 @param Controller The parent controller handle. 698 @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid 699 or equals to gEfiPciIoProtocolGuid. 700 @param Count Count of the serial devices. 701 702 @return An array of pointers containing all the child serial device pointers. 703 **/ 704 SERIAL_DEV ** 705 GetChildSerialDevices ( 706 IN EFI_HANDLE Controller, 707 IN EFI_GUID *IoProtocolGuid, 708 OUT UINTN *Count 709 ) 710 { 711 EFI_STATUS Status; 712 UINTN Index; 713 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; 714 UINTN EntryCount; 715 SERIAL_DEV **SerialDevices; 716 EFI_SERIAL_IO_PROTOCOL *SerialIo; 717 BOOLEAN OpenByDriver; 718 719 *Count = 0; 720 // 721 // If the SerialIo instance specified by RemainingDevicePath is already created, 722 // update the attributes/control. 723 // 724 Status = gBS->OpenProtocolInformation ( 725 Controller, 726 IoProtocolGuid, 727 &OpenInfoBuffer, 728 &EntryCount 729 ); 730 if (EFI_ERROR (Status)) { 731 return NULL; 732 } 733 734 SerialDevices = AllocatePool (EntryCount * sizeof (SERIAL_DEV *)); 735 ASSERT (SerialDevices != NULL); 736 737 *Count = 0; 738 OpenByDriver = FALSE; 739 for (Index = 0; Index < EntryCount; Index++) { 740 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { 741 Status = gBS->OpenProtocol ( 742 OpenInfoBuffer[Index].ControllerHandle, 743 &gEfiSerialIoProtocolGuid, 744 (VOID **) &SerialIo, 745 gSerialControllerDriver.DriverBindingHandle, 746 Controller, 747 EFI_OPEN_PROTOCOL_GET_PROTOCOL 748 ); 749 if (!EFI_ERROR (Status)) { 750 SerialDevices[(*Count)++] = SERIAL_DEV_FROM_THIS (SerialIo); 751 } 752 } 753 754 755 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { 756 ASSERT (OpenInfoBuffer[Index].AgentHandle == gSerialControllerDriver.DriverBindingHandle); 757 OpenByDriver = TRUE; 758 } 759 } 760 if (OpenInfoBuffer != NULL) { 761 FreePool (OpenInfoBuffer); 762 } 763 764 ASSERT ((*Count == 0) || (OpenByDriver)); 765 766 return SerialDevices; 767 } 768 769 /** 770 Start to management the controller passed in 771 772 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 773 @param Controller The handle of the controller to test. 774 @param RemainingDevicePath A pointer to the remaining portion of a device path. 775 776 @return EFI_SUCCESS Driver is started successfully 777 **/ 778 EFI_STATUS 779 EFIAPI 780 SerialControllerDriverStart ( 781 IN EFI_DRIVER_BINDING_PROTOCOL *This, 782 IN EFI_HANDLE Controller, 783 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 784 ) 785 { 786 EFI_STATUS Status; 787 UINTN Index; 788 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 789 EFI_DEVICE_PATH_PROTOCOL *Node; 790 EFI_SERIAL_IO_PROTOCOL *SerialIo; 791 UINT32 ControllerNumber; 792 UART_DEVICE_PATH *Uart; 793 UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 794 UINT32 Control; 795 PARENT_IO_PROTOCOL_PTR ParentIo; 796 ACPI_HID_DEVICE_PATH *Acpi; 797 EFI_GUID *IoProtocolGuid; 798 PCI_SERIAL_PARAMETER *PciSerialParameter; 799 PCI_SERIAL_PARAMETER DefaultPciSerialParameter; 800 PCI_TYPE00 Pci; 801 UINT32 PciSerialCount; 802 SERIAL_DEV **SerialDevices; 803 UINTN SerialDeviceCount; 804 PCI_DEVICE_INFO *PciDeviceInfo; 805 UINT64 Supports; 806 BOOLEAN ContainsControllerNode; 807 808 // 809 // Get the Parent Device Path 810 // 811 Status = gBS->OpenProtocol ( 812 Controller, 813 &gEfiDevicePathProtocolGuid, 814 (VOID **) &ParentDevicePath, 815 This->DriverBindingHandle, 816 Controller, 817 EFI_OPEN_PROTOCOL_BY_DRIVER 818 ); 819 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 820 return Status; 821 } 822 // 823 // Report status code enable the serial 824 // 825 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 826 EFI_PROGRESS_CODE, 827 EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT, 828 ParentDevicePath 829 ); 830 831 // 832 // Grab the IO abstraction we need to get any work done 833 // 834 IoProtocolGuid = &gEfiSioProtocolGuid; 835 Status = gBS->OpenProtocol ( 836 Controller, 837 IoProtocolGuid, 838 (VOID **) &ParentIo, 839 This->DriverBindingHandle, 840 Controller, 841 EFI_OPEN_PROTOCOL_BY_DRIVER 842 ); 843 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 844 IoProtocolGuid = &gEfiPciIoProtocolGuid; 845 Status = gBS->OpenProtocol ( 846 Controller, 847 IoProtocolGuid, 848 (VOID **) &ParentIo, 849 This->DriverBindingHandle, 850 Controller, 851 EFI_OPEN_PROTOCOL_BY_DRIVER 852 ); 853 } 854 ASSERT (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED); 855 856 // 857 // Do nothing for END device path node 858 // 859 if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { 860 return EFI_SUCCESS; 861 } 862 863 ControllerNumber = 0; 864 ContainsControllerNode = FALSE; 865 SerialDevices = GetChildSerialDevices (Controller, IoProtocolGuid, &SerialDeviceCount); 866 // 867 // If the SerialIo instance specified by RemainingDevicePath is already created, 868 // update the attributes/control. 869 // 870 if ((SerialDeviceCount != 0) && (RemainingDevicePath != NULL)) { 871 Uart = (UART_DEVICE_PATH *) SkipControllerDevicePathNode (RemainingDevicePath, &ContainsControllerNode, &ControllerNumber); 872 for (Index = 0; Index < SerialDeviceCount; Index++) { 873 ASSERT ((SerialDevices != NULL) && (SerialDevices[Index] != NULL)); 874 if ((!SerialDevices[Index]->ContainsControllerNode && !ContainsControllerNode) || 875 (SerialDevices[Index]->ContainsControllerNode && ContainsControllerNode && SerialDevices[Index]->Instance == ControllerNumber) 876 ) { 877 SerialIo = &SerialDevices[Index]->SerialIo; 878 Status = EFI_INVALID_PARAMETER; 879 // 880 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade. 881 // DriverBindingStart() shouldn't create a handle with different UART device path. 882 // 883 if (VerifyUartParameters (SerialDevices[Index]->ClockRate, Uart->BaudRate, Uart->DataBits, 884 (EFI_PARITY_TYPE) Uart->Parity, (EFI_STOP_BITS_TYPE) Uart->StopBits, NULL, NULL)) { 885 Status = SerialIo->SetAttributes ( 886 SerialIo, 887 Uart->BaudRate, 888 SerialIo->Mode->ReceiveFifoDepth, 889 SerialIo->Mode->Timeout, 890 (EFI_PARITY_TYPE) Uart->Parity, 891 Uart->DataBits, 892 (EFI_STOP_BITS_TYPE) Uart->StopBits 893 ); 894 } 895 FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 896 if (!EFI_ERROR (Status) && IsUartFlowControlDevicePathNode (FlowControl)) { 897 Status = SerialIo->GetControl (SerialIo, &Control); 898 if (!EFI_ERROR (Status)) { 899 if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) { 900 Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; 901 } else { 902 Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; 903 } 904 // 905 // Clear the bits that are not allowed to pass to SetControl 906 // 907 Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | 908 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | 909 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); 910 Status = SerialIo->SetControl (SerialIo, Control); 911 } 912 } 913 break; 914 } 915 } 916 if (Index != SerialDeviceCount) { 917 // 918 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated. 919 // Otherwise continue to create the instance specified by RemainingDevicePath. 920 // 921 if (SerialDevices != NULL) { 922 FreePool (SerialDevices); 923 } 924 return Status; 925 } 926 } 927 928 if (RemainingDevicePath != NULL) { 929 Uart = (UART_DEVICE_PATH *) SkipControllerDevicePathNode (RemainingDevicePath, &ContainsControllerNode, &ControllerNumber); 930 } else { 931 Uart = NULL; 932 } 933 934 PciDeviceInfo = NULL; 935 if (IoProtocolGuid == &gEfiSioProtocolGuid) { 936 Status = EFI_NOT_FOUND; 937 if (RemainingDevicePath == NULL || !ContainsControllerNode) { 938 Node = ParentDevicePath; 939 do { 940 Acpi = (ACPI_HID_DEVICE_PATH *) Node; 941 Node = NextDevicePathNode (Node); 942 } while (!IsDevicePathEnd (Node)); 943 Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, FALSE, Acpi->UID, ParentIo, NULL, NULL); 944 DEBUG ((EFI_D_INFO, "PciSioSerial: Create SIO child serial device - %r\n", Status)); 945 } 946 } else { 947 Status = ParentIo.PciIo->Pci.Read (ParentIo.PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); 948 if (!EFI_ERROR (Status)) { 949 // 950 // PcdPciSerialParameters takes the higher priority. 951 // 952 PciSerialCount = 0; 953 for (PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); PciSerialParameter->VendorId != 0xFFFF; PciSerialParameter++) { 954 if ((PciSerialParameter->VendorId == Pci.Hdr.VendorId) && 955 (PciSerialParameter->DeviceId == Pci.Hdr.DeviceId) 956 ) { 957 PciSerialCount++; 958 } 959 } 960 961 if (SerialDeviceCount == 0) { 962 // 963 // Enable the IO & MEM decoding when creating the first child. 964 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0). 965 // 966 PciDeviceInfo = AllocatePool (sizeof (PCI_DEVICE_INFO)); 967 ASSERT (PciDeviceInfo != NULL); 968 PciDeviceInfo->ChildCount = 0; 969 PciDeviceInfo->PciIo = ParentIo.PciIo; 970 Status = ParentIo.PciIo->Attributes ( 971 ParentIo.PciIo, 972 EfiPciIoAttributeOperationGet, 973 0, 974 &PciDeviceInfo->PciAttributes 975 ); 976 977 if (!EFI_ERROR (Status)) { 978 Status = ParentIo.PciIo->Attributes ( 979 ParentIo.PciIo, 980 EfiPciIoAttributeOperationSupported, 981 0, 982 &Supports 983 ); 984 if (!EFI_ERROR (Status)) { 985 Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY); 986 Status = ParentIo.PciIo->Attributes ( 987 ParentIo.PciIo, 988 EfiPciIoAttributeOperationEnable, 989 Supports, 990 NULL 991 ); 992 } 993 } 994 } else { 995 // 996 // Re-use the PciDeviceInfo stored in existing children. 997 // 998 ASSERT ((SerialDevices != NULL) && (SerialDevices[0] != NULL)); 999 PciDeviceInfo = SerialDevices[0]->PciDeviceInfo; 1000 ASSERT (PciDeviceInfo != NULL); 1001 } 1002 1003 Status = EFI_NOT_FOUND; 1004 if (PciSerialCount <= 1) { 1005 // 1006 // PCI serial device contains only one UART 1007 // 1008 if (RemainingDevicePath == NULL || !ContainsControllerNode) { 1009 // 1010 // This PCI serial device is matched by class code in Supported() 1011 // 1012 if (PciSerialCount == 0) { 1013 DefaultPciSerialParameter.VendorId = Pci.Hdr.VendorId; 1014 DefaultPciSerialParameter.DeviceId = Pci.Hdr.DeviceId; 1015 DefaultPciSerialParameter.BarIndex = 0; 1016 DefaultPciSerialParameter.Offset = 0; 1017 DefaultPciSerialParameter.RegisterStride = 0; 1018 DefaultPciSerialParameter.ClockRate = 0; 1019 PciSerialParameter = &DefaultPciSerialParameter; 1020 } else if (PciSerialCount == 1) { 1021 PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); 1022 } 1023 1024 Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, FALSE, 0, ParentIo, PciSerialParameter, PciDeviceInfo); 1025 DEBUG ((EFI_D_INFO, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status)); 1026 if (!EFI_ERROR (Status)) { 1027 PciDeviceInfo->ChildCount++; 1028 } 1029 } 1030 } else { 1031 // 1032 // PCI serial device contains multiple UARTs 1033 // 1034 if (RemainingDevicePath == NULL || ContainsControllerNode) { 1035 PciSerialCount = 0; 1036 for (PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); PciSerialParameter->VendorId != 0xFFFF; PciSerialParameter++) { 1037 if ((PciSerialParameter->VendorId == Pci.Hdr.VendorId) && 1038 (PciSerialParameter->DeviceId == Pci.Hdr.DeviceId) && 1039 ((RemainingDevicePath == NULL) || (ControllerNumber == PciSerialCount)) 1040 ) { 1041 // 1042 // Create controller node when PCI serial device contains multiple UARTs 1043 // 1044 Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, TRUE, PciSerialCount, ParentIo, PciSerialParameter, PciDeviceInfo); 1045 PciSerialCount++; 1046 DEBUG ((EFI_D_INFO, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status)); 1047 if (!EFI_ERROR (Status)) { 1048 PciDeviceInfo->ChildCount++; 1049 } 1050 } 1051 } 1052 } 1053 } 1054 } 1055 } 1056 1057 if (SerialDevices != NULL) { 1058 FreePool (SerialDevices); 1059 } 1060 1061 // 1062 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully 1063 // 1064 if ((PciDeviceInfo != NULL) && (PciDeviceInfo->ChildCount != 0)) { 1065 Status = EFI_SUCCESS; 1066 } 1067 1068 if (EFI_ERROR (Status) && (SerialDeviceCount == 0)) { 1069 if (PciDeviceInfo != NULL) { 1070 Status = ParentIo.PciIo->Attributes ( 1071 ParentIo.PciIo, 1072 EfiPciIoAttributeOperationSet, 1073 PciDeviceInfo->PciAttributes, 1074 NULL 1075 ); 1076 ASSERT_EFI_ERROR (Status); 1077 FreePool (PciDeviceInfo); 1078 } 1079 gBS->CloseProtocol ( 1080 Controller, 1081 &gEfiDevicePathProtocolGuid, 1082 This->DriverBindingHandle, 1083 Controller 1084 ); 1085 gBS->CloseProtocol ( 1086 Controller, 1087 IoProtocolGuid, 1088 This->DriverBindingHandle, 1089 Controller 1090 ); 1091 } 1092 1093 return Status; 1094 } 1095 1096 /** 1097 Disconnect this driver with the controller, uninstall related protocol instance 1098 1099 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 1100 @param Controller The handle of the controller to test. 1101 @param NumberOfChildren Number of child device. 1102 @param ChildHandleBuffer A pointer to the remaining portion of a device path. 1103 1104 @retval EFI_SUCCESS Operation successfully 1105 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully 1106 1107 **/ 1108 EFI_STATUS 1109 EFIAPI 1110 SerialControllerDriverStop ( 1111 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1112 IN EFI_HANDLE Controller, 1113 IN UINTN NumberOfChildren, 1114 IN EFI_HANDLE *ChildHandleBuffer 1115 ) 1116 1117 { 1118 EFI_STATUS Status; 1119 UINTN Index; 1120 BOOLEAN AllChildrenStopped; 1121 EFI_SERIAL_IO_PROTOCOL *SerialIo; 1122 SERIAL_DEV *SerialDevice; 1123 VOID *IoProtocol; 1124 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 1125 PCI_DEVICE_INFO *PciDeviceInfo; 1126 1127 PciDeviceInfo = NULL; 1128 1129 Status = gBS->HandleProtocol ( 1130 Controller, 1131 &gEfiDevicePathProtocolGuid, 1132 (VOID **) &DevicePath 1133 ); 1134 1135 // 1136 // Report the status code disable the serial 1137 // 1138 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 1139 EFI_PROGRESS_CODE, 1140 EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT, 1141 DevicePath 1142 ); 1143 1144 if (NumberOfChildren == 0) { 1145 // 1146 // Close the bus driver 1147 // 1148 Status = gBS->OpenProtocol ( 1149 Controller, 1150 &gEfiPciIoProtocolGuid, 1151 &IoProtocol, 1152 This->DriverBindingHandle, 1153 Controller, 1154 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 1155 ); 1156 gBS->CloseProtocol ( 1157 Controller, 1158 !EFI_ERROR (Status) ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1159 This->DriverBindingHandle, 1160 Controller 1161 ); 1162 1163 gBS->CloseProtocol ( 1164 Controller, 1165 &gEfiDevicePathProtocolGuid, 1166 This->DriverBindingHandle, 1167 Controller 1168 ); 1169 return EFI_SUCCESS; 1170 } 1171 1172 AllChildrenStopped = TRUE; 1173 1174 for (Index = 0; Index < NumberOfChildren; Index++) { 1175 1176 Status = gBS->OpenProtocol ( 1177 ChildHandleBuffer[Index], 1178 &gEfiSerialIoProtocolGuid, 1179 (VOID **) &SerialIo, 1180 This->DriverBindingHandle, 1181 Controller, 1182 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1183 ); 1184 if (!EFI_ERROR (Status)) { 1185 1186 SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); 1187 ASSERT ((PciDeviceInfo == NULL) || (PciDeviceInfo == SerialDevice->PciDeviceInfo)); 1188 PciDeviceInfo = SerialDevice->PciDeviceInfo; 1189 1190 Status = gBS->CloseProtocol ( 1191 Controller, 1192 PciDeviceInfo != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1193 This->DriverBindingHandle, 1194 ChildHandleBuffer[Index] 1195 ); 1196 1197 Status = gBS->UninstallMultipleProtocolInterfaces ( 1198 ChildHandleBuffer[Index], 1199 &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 1200 &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 1201 NULL 1202 ); 1203 if (EFI_ERROR (Status)) { 1204 gBS->OpenProtocol ( 1205 Controller, 1206 PciDeviceInfo != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1207 &IoProtocol, 1208 This->DriverBindingHandle, 1209 ChildHandleBuffer[Index], 1210 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1211 ); 1212 } else { 1213 FreePool (SerialDevice->DevicePath); 1214 FreeUnicodeStringTable (SerialDevice->ControllerNameTable); 1215 FreePool (SerialDevice); 1216 1217 if (PciDeviceInfo != NULL) { 1218 ASSERT (PciDeviceInfo->ChildCount != 0); 1219 PciDeviceInfo->ChildCount--; 1220 } 1221 } 1222 } 1223 1224 if (EFI_ERROR (Status)) { 1225 AllChildrenStopped = FALSE; 1226 } 1227 } 1228 1229 if (!AllChildrenStopped) { 1230 return EFI_DEVICE_ERROR; 1231 } else { 1232 // 1233 // If all children are destroyed, restore the PCI attributes. 1234 // 1235 if ((PciDeviceInfo != NULL) && (PciDeviceInfo->ChildCount == 0)) { 1236 ASSERT (PciDeviceInfo->PciIo != NULL); 1237 Status = PciDeviceInfo->PciIo->Attributes ( 1238 PciDeviceInfo->PciIo, 1239 EfiPciIoAttributeOperationSet, 1240 PciDeviceInfo->PciAttributes, 1241 NULL 1242 ); 1243 ASSERT_EFI_ERROR (Status); 1244 FreePool (PciDeviceInfo); 1245 } 1246 return EFI_SUCCESS; 1247 } 1248 } 1249