**/\r
\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
\r
#include "VirtioGpu.h"\r
\r
#define VGPU_GOP_FROM_GOP(GopPointer) \\r
CR (GopPointer, VGPU_GOP, Gop, VGPU_GOP_SIG)\r
\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopNativeResolution (\r
+ IN VGPU_GOP *VgpuGop,\r
+ OUT UINT32 *XRes,\r
+ OUT UINT32 *YRes\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESP_DISPLAY_INFO DisplayInfo;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ Status = VirtioGpuGetDisplayInfo (VgpuGop->ParentBus, &DisplayInfo);\r
+ if (Status != EFI_SUCCESS) {\r
+ return;\r
+ }\r
+\r
+ for (Index = 0; Index < VIRTIO_GPU_MAX_SCANOUTS; Index++) {\r
+ if (!DisplayInfo.Pmodes[Index].Enabled ||\r
+ !DisplayInfo.Pmodes[Index].Rectangle.Width ||\r
+ !DisplayInfo.Pmodes[Index].Rectangle.Height)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: #%d: %dx%d\n",\r
+ __FUNCTION__,\r
+ Index,\r
+ DisplayInfo.Pmodes[Index].Rectangle.Width,\r
+ DisplayInfo.Pmodes[Index].Rectangle.Height\r
+ ));\r
+ if ((*XRes == 0) || (*YRes == 0)) {\r
+ *XRes = DisplayInfo.Pmodes[Index].Rectangle.Width;\r
+ *YRes = DisplayInfo.Pmodes[Index].Rectangle.Height;\r
+ }\r
+ }\r
+}\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GopInitialize (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This\r
+ )\r
+{\r
+ VGPU_GOP *VgpuGop;\r
+ EFI_STATUS Status;\r
+ UINT32 XRes = 0, YRes = 0, Index;\r
+\r
+ VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+\r
+ //\r
+ // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
+ // (nonzero) constant fields.\r
+ //\r
+ // No direct framebuffer access is supported, only Blt() is.\r
+ //\r
+ VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
+\r
+ VgpuGop->GopMode.MaxMode = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
+ VgpuGop->GopMode.Info = &VgpuGop->GopModeInfo;\r
+ VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
+\r
+ VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
+\r
+ //\r
+ // query host for display resolution\r
+ //\r
+ GopNativeResolution (VgpuGop, &XRes, &YRes);\r
+ if ((XRes == 0) || (YRes == 0)) {\r
+ return;\r
+ }\r
+\r
+ if (PcdGet8 (PcdVideoResolutionSource) == 0) {\r
+ Status = PcdSet32S (PcdVideoHorizontalResolution, XRes);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ Status = PcdSet32S (PcdVideoVerticalResolution, YRes);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ Status = PcdSet8S (PcdVideoResolutionSource, 2);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ }\r
+\r
+ VgpuGop->NativeXRes = XRes;\r
+ VgpuGop->NativeYRes = YRes;\r
+ for (Index = 0; Index < ARRAY_SIZE (mGopResolutions); Index++) {\r
+ if ((mGopResolutions[Index].Width == XRes) &&\r
+ (mGopResolutions[Index].Height == YRes))\r
+ {\r
+ // native resolution already is in mode list\r
+ return;\r
+ }\r
+ }\r
+\r
+ // add to mode list\r
+ VgpuGop->GopMode.MaxMode++;\r
+}\r
+\r
//\r
// EFI_GRAPHICS_OUTPUT_PROTOCOL member functions.\r
//\r
{\r
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
\r
- if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
+ if (ModeNumber >= This->Mode->MaxMode) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
- GopModeInfo->VerticalResolution = mGopResolutions[ModeNumber].Height;\r
- GopModeInfo->PixelFormat = PixelBltOnly;\r
- GopModeInfo->PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
+ if (ModeNumber < ARRAY_SIZE (mGopResolutions)) {\r
+ GopModeInfo->HorizontalResolution = mGopResolutions[ModeNumber].Width;\r
+ GopModeInfo->VerticalResolution = mGopResolutions[ModeNumber].Height;\r
+ } else {\r
+ VGPU_GOP *VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+ GopModeInfo->HorizontalResolution = VgpuGop->NativeXRes;\r
+ GopModeInfo->VerticalResolution = VgpuGop->NativeYRes;\r
+ }\r
+\r
+ GopModeInfo->PixelFormat = PixelBltOnly;\r
+ GopModeInfo->PixelsPerScanLine = GopModeInfo->HorizontalResolution;\r
\r
*SizeOfInfo = sizeof *GopModeInfo;\r
*Info = GopModeInfo;\r
IN UINT32 ModeNumber\r
)\r
{\r
- VGPU_GOP *VgpuGop;\r
- UINT32 NewResourceId;\r
- UINTN NewNumberOfBytes;\r
- UINTN NewNumberOfPages;\r
- VOID *NewBackingStore;\r
- EFI_PHYSICAL_ADDRESS NewBackingStoreDeviceAddress;\r
- VOID *NewBackingStoreMap;\r
+ VGPU_GOP *VgpuGop;\r
+ UINT32 NewResourceId;\r
+ UINTN NewNumberOfBytes;\r
+ UINTN NewNumberOfPages;\r
+ VOID *NewBackingStore;\r
+ EFI_PHYSICAL_ADDRESS NewBackingStoreDeviceAddress;\r
+ VOID *NewBackingStoreMap;\r
+ UINTN SizeOfInfo;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
\r
EFI_STATUS Status;\r
EFI_STATUS Status2;\r
\r
- if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
- return EFI_UNSUPPORTED;\r
+ if (!This->Mode) {\r
+ // SetMode() call in InitVgpuGop() triggers this.\r
+ GopInitialize (This);\r
+ }\r
+\r
+ Status = GopQueryMode (This, ModeNumber, &SizeOfInfo, &GopModeInfo);\r
+ if (Status != EFI_SUCCESS) {\r
+ return Status;\r
}\r
\r
VgpuGop = VGPU_GOP_FROM_GOP (This);\r
// calls.\r
//\r
if (VgpuGop->ResourceId == 0) {\r
- //\r
- // Set up the Gop -> GopMode -> GopModeInfo pointer chain, and the other\r
- // (nonzero) constant fields.\r
- //\r
- // No direct framebuffer access is supported, only Blt() is.\r
- //\r
- VgpuGop->Gop.Mode = &VgpuGop->GopMode;\r
-\r
- VgpuGop->GopMode.MaxMode = (UINT32)(ARRAY_SIZE (mGopResolutions));\r
- VgpuGop->GopMode.Info = &VgpuGop->GopModeInfo;\r
- VgpuGop->GopMode.SizeOfInfo = sizeof VgpuGop->GopModeInfo;\r
-\r
- VgpuGop->GopModeInfo.PixelFormat = PixelBltOnly;\r
-\r
//\r
// This is the first time we create a host side resource.\r
//\r
VgpuGop->ParentBus, // VgpuDev\r
NewResourceId, // ResourceId\r
VirtioGpuFormatB8G8R8X8Unorm, // Format\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution // Height\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
// Allocate, zero and map guest backing store, for bus master common buffer\r
// operation.\r
//\r
- NewNumberOfBytes = mGopResolutions[ModeNumber].Width *\r
- mGopResolutions[ModeNumber].Height * sizeof (UINT32);\r
+ NewNumberOfBytes = GopModeInfo->HorizontalResolution *\r
+ GopModeInfo->VerticalResolution * sizeof (UINT32);\r
NewNumberOfPages = EFI_SIZE_TO_PAGES (NewNumberOfBytes);\r
Status = VirtioGpuAllocateZeroAndMapBackingStore (\r
VgpuGop->ParentBus, // VgpuDev\r
VgpuGop->ParentBus, // VgpuDev\r
0, // X\r
0, // Y\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height, // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution, // Height\r
0, // ScanoutId\r
NewResourceId // ResourceId\r
);\r
VgpuGop->ParentBus, // VgpuDev\r
0, // X\r
0, // Y\r
- mGopResolutions[ModeNumber].Width, // Width\r
- mGopResolutions[ModeNumber].Height, // Height\r
+ GopModeInfo->HorizontalResolution, // Width\r
+ GopModeInfo->VerticalResolution, // Height\r
NewResourceId // ResourceId\r
);\r
if (EFI_ERROR (Status)) {\r
// therefore non-recoverable.\r
//\r
Status2 = VirtioGpuSetScanout (\r
- VgpuGop->ParentBus, // VgpuDev\r
- 0, // X\r
- 0, // Y\r
- mGopResolutions[This->Mode->Mode].Width, // Width\r
- mGopResolutions[This->Mode->Mode].Height, // Height\r
- 0, // ScanoutId\r
- VgpuGop->ResourceId // ResourceId\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ 0, // X\r
+ 0, // Y\r
+ VgpuGop->GopModeInfo.HorizontalResolution, // Width\r
+ VgpuGop->GopModeInfo.VerticalResolution, // Height\r
+ 0, // ScanoutId\r
+ VgpuGop->ResourceId // ResourceId\r
);\r
ASSERT_EFI_ERROR (Status2);\r
if (EFI_ERROR (Status2)) {\r
//\r
// Populate Mode and ModeInfo (mutable fields only).\r
//\r
- VgpuGop->GopMode.Mode = ModeNumber;\r
- VgpuGop->GopModeInfo.HorizontalResolution =\r
- mGopResolutions[ModeNumber].Width;\r
- VgpuGop->GopModeInfo.VerticalResolution = mGopResolutions[ModeNumber].Height;\r
- VgpuGop->GopModeInfo.PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
+ VgpuGop->GopMode.Mode = ModeNumber;\r
+ VgpuGop->GopModeInfo = *GopModeInfo;\r
+ FreePool (GopModeInfo);\r
return EFI_SUCCESS;\r
\r
DetachBackingStore:\r
CpuDeadLoop ();\r
}\r
\r
+ FreePool (GopModeInfo);\r
return Status;\r
}\r
\r