EFI_STATUS GetGopDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath ) { UINTN Index; EFI_STATUS Status; EFI_HANDLE PciDeviceHandle; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; UINTN GopHandleCount; EFI_HANDLE *GopHandleBuffer; if (PciDevicePath == NULL || GopDevicePath == NULL) { return EFI_INVALID_PARAMETER; } // // Initialize the GopDevicePath to be PciDevicePath // *GopDevicePath = PciDevicePath; TempPciDevicePath = PciDevicePath; Status = gBS->LocateDevicePath ( &gEfiDevicePathProtocolGuid, &TempPciDevicePath, &PciDeviceHandle ); if (EFI_ERROR (Status)) { return Status; } // // Try to connect this handle, so that GOP dirver could start on this // device and create child handles with GraphicsOutput Protocol installed // on them, then we get device paths of these child handles and select // them as possible console device. // #if 0 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); #else { ACPI_ADR_DEVICE_PATH AcpiAdr; EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL; AcpiAdr.Header.Type = ACPI_DEVICE_PATH; AcpiAdr.Header.SubType = ACPI_ADR_DP; //AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 6, 0); //on bayleybay, CRT Device AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0); ; // on rambi, eDP C SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH)); MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr); gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE); FreePool(MyDevicePath); } #endif Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiGraphicsOutputProtocolGuid, NULL, &GopHandleCount, &GopHandleBuffer ); if (!EFI_ERROR (Status)) { // // Add all the child handles as possible Console Device // for (Index = 0; Index < GopHandleCount; Index++) { Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); if (EFI_ERROR (Status)) { continue; } if (CompareMem ( PciDevicePath, TempDevicePath, GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH ) == 0) { // // In current implementation, we only enable one of the child handles // as console device, i.e. sotre one of the child handle's device // path to variable "ConOut" // In futhure, we could select all child handles to be console device // *GopDevicePath = TempDevicePath; // // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() // Add the integrity GOP device path. // BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); } } gBS->FreePool (GopHandleBuffer); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI InitializeQemuRamfb ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_DEVICE_PATH_PROTOCOL *RamfbDevicePath; EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; VOID *DevicePath; VENDOR_DEVICE_PATH VendorDeviceNode; ACPI_ADR_DEVICE_PATH AcpiDeviceNode; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS FbBase; UINTN FbSize, MaxFbSize, Pages; UINTN FwCfgSize; UINTN Index; if (!QemuFwCfgIsAvailable ()) { DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n")); return EFI_NOT_FOUND; } Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } if (FwCfgSize != sizeof (RAMFB_CONFIG)) { DEBUG ((DEBUG_ERROR, "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n", (UINT64)sizeof (RAMFB_CONFIG), (UINT64)FwCfgSize)); return EFI_PROTOCOL_ERROR; } MaxFbSize = 0; for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) { mQemuRamfbModeInfo[Index].PixelsPerScanLine = mQemuRamfbModeInfo[Index].HorizontalResolution; mQemuRamfbModeInfo[Index].PixelFormat = PixelBlueGreenRedReserved8BitPerColor; FbSize = RAMFB_BPP * mQemuRamfbModeInfo[Index].HorizontalResolution * mQemuRamfbModeInfo[Index].VerticalResolution; if (MaxFbSize < FbSize) { MaxFbSize = FbSize; } DEBUG ((DEBUG_INFO, "Ramfb: Mode %lu: %ux%u, %lu kB\n", (UINT64)Index, mQemuRamfbModeInfo[Index].HorizontalResolution, mQemuRamfbModeInfo[Index].VerticalResolution, (UINT64)(FbSize / 1024))); } Pages = EFI_SIZE_TO_PAGES (MaxFbSize); MaxFbSize = EFI_PAGES_TO_SIZE (Pages); FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (Pages); if (FbBase == 0) { DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n", (UINT64)FbBase, (UINT64)(MaxFbSize / 1024), (UINT64)Pages)); mQemuRamfbMode.FrameBufferSize = MaxFbSize; mQemuRamfbMode.FrameBufferBase = FbBase; // // 800 x 600 // QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1); // // ramfb vendor devpath // VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH; VendorDeviceNode.Header.SubType = HW_VENDOR_DP; CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid); SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH)); RamfbDevicePath = AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode); if (RamfbDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeFramebuffer; } Status = gBS->InstallMultipleProtocolInterfaces ( &mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install Ramfb Vendor DevicePath failed: %r\n", Status)); goto FreeRamfbDevicePath; } // // gop devpath + protocol // AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR ( 1, // DeviceIdScheme 0, // HeadId 0, // NonVgaOutput 1, // BiosCanDetect 0, // VendorInfo ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type 0, // Port 0 // Index ); SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); GopDevicePath = AppendDevicePathNode (RamfbDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode); if (GopDevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto FreeRamfbHandle; } Status = gBS->InstallMultipleProtocolInterfaces ( &mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: install GOP DevicePath failed: %r\n", Status)); goto FreeGopDevicePath; } Status = gBS->OpenProtocol ( mRamfbHandle, &gEfiDevicePathProtocolGuid, &DevicePath, gImageHandle, mGopHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status)); goto FreeGopHandle; } return EFI_SUCCESS; FreeGopHandle: gBS->UninstallMultipleProtocolInterfaces ( mGopHandle, &gEfiDevicePathProtocolGuid, GopDevicePath, &gEfiGraphicsOutputProtocolGuid, &mQemuRamfbGraphicsOutput, NULL ); FreeGopDevicePath: FreePool (GopDevicePath); FreeRamfbHandle: gBS->UninstallMultipleProtocolInterfaces ( mRamfbHandle, &gEfiDevicePathProtocolGuid, RamfbDevicePath, NULL ); FreeRamfbDevicePath: FreePool (RamfbDevicePath); FreeFramebuffer: FreePages ((VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages); return Status; }