{\r
EFI_STATUS Status;\r
QEMU_VIDEO_PRIVATE_DATA *Private;\r
- BOOLEAN PciAttributesSaved;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
PCI_TYPE00 Pci;\r
QEMU_VIDEO_CARD *Card;\r
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
EFI_PCI_IO_PROTOCOL *ChildPciIo;\r
\r
- PciAttributesSaved = FALSE;\r
//\r
// Allocate Private context data for GOP inteface.\r
//\r
Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
if (Private == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
//\r
// Set up context record\r
//\r
Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
- Private->Handle = NULL;\r
\r
//\r
// Open PCI I/O Protocol\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto FreePrivate;\r
}\r
\r
//\r
&Pci\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
\r
+ //\r
+ // Determine card variant.\r
+ //\r
Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
if (Card == NULL) {\r
Status = EFI_DEVICE_ERROR;\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
Private->Variant = Card->Variant;\r
\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
- PciAttributesSaved = TRUE;\r
\r
+ //\r
+ // Set new PCI attributes\r
+ //\r
Status = Private->PciIo->Attributes (\r
Private->PciIo,\r
EfiPciIoAttributeOperationEnable,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
\r
//\r
// Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).\r
//\r
if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
+\r
Status = Private->PciIo->GetBarAttributes (\r
Private->PciIo,\r
PCI_BAR_IDX2,\r
if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
Status = EFI_DEVICE_ERROR;\r
- goto Error;\r
+ goto RestoreAttributes;\r
}\r
}\r
\r
(VOID **) &ParentDevicePath\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto RestoreAttributes;\r
}\r
\r
//\r
// Set Gop Device Path\r
//\r
if (RemainingDevicePath == NULL) {\r
+ ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
+\r
ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
ParentDevicePath,\r
(EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
);\r
+ if (Private->GopDevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto RestoreAttributes;\r
+ }\r
} else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
//\r
// If RemainingDevicePath isn't the End of Device Path Node, \r
// only scan the specified device by RemainingDevicePath\r
//\r
Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
- } else {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node, \r
- // don't create child device and return EFI_SUCCESS\r
- //\r
- Private->GopDevicePath = NULL;\r
+ if (Private->GopDevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto RestoreAttributes;\r
+ }\r
}\r
- \r
+\r
+ //\r
+ // Create new child handle and install the device path protocol on it only if\r
+ // RemainingDevicePath equals NULL, or doesn't point to the End of Device\r
+ // Path Node.\r
+ //\r
if (Private->GopDevicePath != NULL) {\r
- //\r
- // Creat child handle and device path protocol firstly\r
- //\r
- Private->Handle = NULL;\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Private->Handle,\r
&gEfiDevicePathProtocolGuid,\r
Private->GopDevicePath,\r
NULL\r
);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeGopDevicePath;\r
+ }\r
}\r
\r
//\r
break;\r
}\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto UninstallGopDevicePath;\r
}\r
\r
+ //\r
+ // If RemainingDevicePath points to the End of Device Path Node, then we\r
+ // haven't created a child handle, and we're done.\r
+ //\r
if (Private->GopDevicePath == NULL) {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node, \r
- // don't create child device and return EFI_SUCCESS\r
- //\r
- Status = EFI_SUCCESS;\r
- } else {\r
-\r
- //\r
- // Start the GOP software stack.\r
- //\r
- Status = QemuVideoGraphicsOutputConstructor (Private);\r
- ASSERT_EFI_ERROR (Status);\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->Handle,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &Private->GraphicsOutput,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ //\r
+ // Start the GOP software stack.\r
+ //\r
+ Status = QemuVideoGraphicsOutputConstructor (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeModeData;\r
+ }\r
\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &ChildPciIo,\r
- This->DriverBindingHandle,\r
- Private->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Handle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &Private->GraphicsOutput,\r
+ NULL\r
);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto DestructQemuVideoGraphics;\r
}\r
\r
-Error:\r
+ //\r
+ // Reference parent handle from child handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &ChildPciIo,\r
+ This->DriverBindingHandle,\r
+ Private->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
if (EFI_ERROR (Status)) {\r
- if (Private) {\r
- if (Private->PciIo) {\r
- if (PciAttributesSaved == TRUE) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- Private->PciIo->Attributes (\r
- Private->PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- Private->OriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
- //\r
- // Close the PCI I/O Protocol\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Private->Handle\r
- );\r
- }\r
+ goto UninstallGop;\r
+ }\r
\r
- gBS->FreePool (Private);\r
- }\r
+ return EFI_SUCCESS;\r
+\r
+UninstallGop:\r
+ gBS->UninstallProtocolInterface (Private->Handle,\r
+ &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
+\r
+DestructQemuVideoGraphics:\r
+ QemuVideoGraphicsOutputDestructor (Private);\r
+\r
+FreeModeData:\r
+ FreePool (Private->ModeData);\r
+\r
+UninstallGopDevicePath:\r
+ //\r
+ // Handles the case transparently when Private->Handle and\r
+ // Private->GopDevicePath are NULL.\r
+ //\r
+ gBS->UninstallProtocolInterface (Private->Handle,\r
+ &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
+\r
+FreeGopDevicePath:\r
+ if (Private->GopDevicePath != NULL) {\r
+ FreePool (Private->GopDevicePath);\r
}\r
\r
+RestoreAttributes:\r
+ Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
+ Private->OriginalPciAttributes, NULL);\r
+\r
+ClosePciIo:\r
+ gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle, Controller);\r
+\r
+FreePrivate:\r
+ FreePool (Private);\r
+\r
return Status;\r
}\r
\r