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