\r
Copyright (C) 2016, Red Hat, Inc.\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
**/\r
VOID\r
ReleaseGopResources (\r
- IN OUT VGPU_GOP *VgpuGop,\r
- IN BOOLEAN DisableHead\r
+ IN OUT VGPU_GOP *VgpuGop,\r
+ IN BOOLEAN DisableHead\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
ASSERT (VgpuGop->ResourceId != 0);\r
ASSERT (VgpuGop->BackingStore != NULL);\r
//\r
Status = VirtioGpuSetScanout (\r
VgpuGop->ParentBus, // VgpuDev\r
- 0, 0, 0, 0, // X, Y, Width, Height\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0, // X, Y, Width, Height\r
0, // ScanoutId\r
0 // ResourceId\r
);\r
}\r
\r
//\r
- // Release backing pages.\r
+ // Unmap and release backing pages.\r
//\r
- FreePages (VgpuGop->BackingStore, VgpuGop->NumberOfPages);\r
- VgpuGop->BackingStore = NULL;\r
- VgpuGop->NumberOfPages = 0;\r
+ VirtioGpuUnmapAndFreeBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ VgpuGop->NumberOfPages, // NumberOfPages\r
+ VgpuGop->BackingStore, // HostAddress\r
+ VgpuGop->BackingStoreMap // Mapping\r
+ );\r
+ VgpuGop->BackingStore = NULL;\r
+ VgpuGop->NumberOfPages = 0;\r
+ VgpuGop->BackingStoreMap = NULL;\r
\r
//\r
// Destroy the currently used 2D host resource.\r
if (EFI_ERROR (Status)) {\r
CpuDeadLoop ();\r
}\r
+\r
VgpuGop->ResourceId = 0;\r
}\r
\r
// The resolutions supported by this driver.\r
//\r
typedef struct {\r
- UINT32 Width;\r
- UINT32 Height;\r
+ UINT32 Width;\r
+ UINT32 Height;\r
} GOP_RESOLUTION;\r
\r
-STATIC CONST GOP_RESOLUTION mGopResolutions[] = {\r
- { 640, 480 },\r
- { 800, 480 },\r
- { 800, 600 },\r
- { 832, 624 },\r
- { 960, 640 },\r
- { 1024, 600 },\r
- { 1024, 768 },\r
- { 1152, 864 },\r
- { 1152, 870 },\r
- { 1280, 720 },\r
- { 1280, 760 },\r
- { 1280, 768 },\r
- { 1280, 800 },\r
- { 1280, 960 },\r
+STATIC CONST GOP_RESOLUTION mGopResolutions[] = {\r
+ { 640, 480 },\r
+ { 800, 480 },\r
+ { 800, 600 },\r
+ { 832, 624 },\r
+ { 960, 640 },\r
+ { 1024, 600 },\r
+ { 1024, 768 },\r
+ { 1152, 864 },\r
+ { 1152, 870 },\r
+ { 1280, 720 },\r
+ { 1280, 760 },\r
+ { 1280, 768 },\r
+ { 1280, 800 },\r
+ { 1280, 960 },\r
{ 1280, 1024 },\r
- { 1360, 768 },\r
- { 1366, 768 },\r
+ { 1360, 768 },\r
+ { 1366, 768 },\r
{ 1400, 1050 },\r
- { 1440, 900 },\r
- { 1600, 900 },\r
+ { 1440, 900 },\r
+ { 1600, 900 },\r
{ 1600, 1200 },\r
{ 1680, 1050 },\r
{ 1920, 1080 },\r
EFI_STATUS\r
EFIAPI\r
GopQueryMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber,\r
- OUT UINTN *SizeOfInfo,\r
- OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber,\r
+ OUT UINTN *SizeOfInfo,\r
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
)\r
{\r
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopModeInfo;\r
\r
if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
return EFI_INVALID_PARAMETER;\r
GopModeInfo->PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
\r
*SizeOfInfo = sizeof *GopModeInfo;\r
- *Info = GopModeInfo;\r
+ *Info = GopModeInfo;\r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
GopSetMode (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN UINT32 ModeNumber\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN UINT32 ModeNumber\r
)\r
{\r
- VGPU_GOP *VgpuGop;\r
- UINT32 NewResourceId;\r
- UINTN NewNumberOfBytes;\r
- UINTN NewNumberOfPages;\r
- VOID *NewBackingStore;\r
- EFI_STATUS Status;\r
- EFI_STATUS Status2;\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
+\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status2;\r
\r
if (ModeNumber >= ARRAY_SIZE (mGopResolutions)) {\r
return EFI_UNSUPPORTED;\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
+ 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
\r
//\r
- // Allocate guest backing store.\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
NewNumberOfPages = EFI_SIZE_TO_PAGES (NewNumberOfBytes);\r
- NewBackingStore = AllocatePages (NewNumberOfPages);\r
- if (NewBackingStore == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
+ Status = VirtioGpuAllocateZeroAndMapBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ NewNumberOfPages, // NumberOfPages\r
+ &NewBackingStore, // HostAddress\r
+ &NewBackingStoreDeviceAddress, // DeviceAddress\r
+ &NewBackingStoreMap // Mapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
goto DestroyHostResource;\r
}\r
- //\r
- // Fill visible part of backing store with black.\r
- //\r
- ZeroMem (NewBackingStore, NewNumberOfBytes);\r
\r
//\r
// Attach backing store to the host resource.\r
Status = VirtioGpuResourceAttachBacking (\r
VgpuGop->ParentBus, // VgpuDev\r
NewResourceId, // ResourceId\r
- (UINTN)NewBackingStore, // BackingStoreDeviceAddress\r
+ NewBackingStoreDeviceAddress, // BackingStoreDeviceAddress\r
NewNumberOfPages // NumberOfPages\r
);\r
if (EFI_ERROR (Status)) {\r
- goto FreeBackingStore;\r
+ goto UnmapAndFreeBackingStore;\r
}\r
\r
//\r
if (EFI_ERROR (Status2)) {\r
CpuDeadLoop ();\r
}\r
+\r
goto DetachBackingStore;\r
}\r
\r
ASSERT (VgpuGop->ResourceId == 0);\r
ASSERT (VgpuGop->BackingStore == NULL);\r
\r
- VgpuGop->ResourceId = NewResourceId;\r
- VgpuGop->BackingStore = NewBackingStore;\r
- VgpuGop->NumberOfPages = NewNumberOfPages;\r
+ VgpuGop->ResourceId = NewResourceId;\r
+ VgpuGop->BackingStore = NewBackingStore;\r
+ VgpuGop->NumberOfPages = NewNumberOfPages;\r
+ VgpuGop->BackingStoreMap = NewBackingStoreMap;\r
\r
//\r
// Populate Mode and ModeInfo (mutable fields only).\r
//\r
- VgpuGop->GopMode.Mode = ModeNumber;\r
+ VgpuGop->GopMode.Mode = ModeNumber;\r
VgpuGop->GopModeInfo.HorizontalResolution =\r
- mGopResolutions[ModeNumber].Width;\r
+ mGopResolutions[ModeNumber].Width;\r
VgpuGop->GopModeInfo.VerticalResolution = mGopResolutions[ModeNumber].Height;\r
- VgpuGop->GopModeInfo.PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
+ VgpuGop->GopModeInfo.PixelsPerScanLine = mGopResolutions[ModeNumber].Width;\r
return EFI_SUCCESS;\r
\r
DetachBackingStore:\r
CpuDeadLoop ();\r
}\r
\r
-FreeBackingStore:\r
- FreePages (NewBackingStore, NewNumberOfPages);\r
+UnmapAndFreeBackingStore:\r
+ VirtioGpuUnmapAndFreeBackingStore (\r
+ VgpuGop->ParentBus, // VgpuDev\r
+ NewNumberOfPages, // NumberOfPages\r
+ NewBackingStore, // HostAddress\r
+ NewBackingStoreMap // Mapping\r
+ );\r
\r
DestroyHostResource:\r
Status2 = VirtioGpuResourceUnref (VgpuGop->ParentBus, NewResourceId);\r
EFI_STATUS\r
EFIAPI\r
GopBlt (\r
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
- IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
- IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
- IN UINTN SourceX,\r
- IN UINTN SourceY,\r
- IN UINTN DestinationX,\r
- IN UINTN DestinationY,\r
- IN UINTN Width,\r
- IN UINTN Height,\r
- IN UINTN Delta OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
+ IN UINTN SourceX,\r
+ IN UINTN SourceY,\r
+ IN UINTN DestinationX,\r
+ IN UINTN DestinationY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN UINTN Delta OPTIONAL\r
)\r
{\r
- VGPU_GOP *VgpuGop;\r
- UINT32 CurrentHorizontal;\r
- UINT32 CurrentVertical;\r
- UINTN SegmentSize;\r
- UINTN Y;\r
- UINTN ResourceOffset;\r
- EFI_STATUS Status;\r
-\r
- VgpuGop = VGPU_GOP_FROM_GOP (This);\r
+ VGPU_GOP *VgpuGop;\r
+ UINT32 CurrentHorizontal;\r
+ UINT32 CurrentVertical;\r
+ UINTN SegmentSize;\r
+ UINTN Y;\r
+ UINTN ResourceOffset;\r
+ EFI_STATUS Status;\r
+\r
+ VgpuGop = VGPU_GOP_FROM_GOP (This);\r
CurrentHorizontal = VgpuGop->GopModeInfo.HorizontalResolution;\r
CurrentVertical = VgpuGop->GopModeInfo.VerticalResolution;\r
\r
// zero, then Width is the entire width of BltBuffer, and the stride is\r
// supposed to be calculated from Width.\r
//\r
- if (BltOperation == EfiBltVideoToBltBuffer ||\r
- BltOperation == EfiBltBufferToVideo) {\r
+ if ((BltOperation == EfiBltVideoToBltBuffer) ||\r
+ (BltOperation == EfiBltBufferToVideo))\r
+ {\r
if (Delta == 0) {\r
Delta = SegmentSize;\r
}\r
// For operations that write to the display, check if the destination fits\r
// onto the display.\r
//\r
- if (BltOperation == EfiBltVideoFill ||\r
- BltOperation == EfiBltBufferToVideo ||\r
- BltOperation == EfiBltVideoToVideo) {\r
- if (DestinationX > CurrentHorizontal ||\r
- Width > CurrentHorizontal - DestinationX ||\r
- DestinationY > CurrentVertical ||\r
- Height > CurrentVertical - DestinationY) {\r
+ if ((BltOperation == EfiBltVideoFill) ||\r
+ (BltOperation == EfiBltBufferToVideo) ||\r
+ (BltOperation == EfiBltVideoToVideo))\r
+ {\r
+ if ((DestinationX > CurrentHorizontal) ||\r
+ (Width > CurrentHorizontal - DestinationX) ||\r
+ (DestinationY > CurrentVertical) ||\r
+ (Height > CurrentVertical - DestinationY))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
// For operations that read from the display, check if the source fits onto\r
// the display.\r
//\r
- if (BltOperation == EfiBltVideoToBltBuffer ||\r
- BltOperation == EfiBltVideoToVideo) {\r
- if (SourceX > CurrentHorizontal ||\r
- Width > CurrentHorizontal - SourceX ||\r
- SourceY > CurrentVertical ||\r
- Height > CurrentVertical - SourceY) {\r
+ if ((BltOperation == EfiBltVideoToBltBuffer) ||\r
+ (BltOperation == EfiBltVideoToVideo))\r
+ {\r
+ if ((SourceX > CurrentHorizontal) ||\r
+ (Width > CurrentHorizontal - SourceX) ||\r
+ (SourceY > CurrentVertical) ||\r
+ (Height > CurrentVertical - SourceY))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
// won't be further steps.\r
//\r
switch (BltOperation) {\r
- case EfiBltVideoFill:\r
- //\r
- // Write data from the BltBuffer pixel (0, 0) directly to every pixel of\r
- // the video display rectangle (DestinationX, DestinationY) (DestinationX +\r
- // Width, DestinationY + Height). Only one pixel will be used from the\r
- // BltBuffer. Delta is NOT used.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- SetMem32 (\r
- VgpuGop->BackingStore +\r
+ case EfiBltVideoFill:\r
+ //\r
+ // Write data from the BltBuffer pixel (0, 0) directly to every pixel of\r
+ // the video display rectangle (DestinationX, DestinationY) (DestinationX +\r
+ // Width, DestinationY + Height). Only one pixel will be used from the\r
+ // BltBuffer. Delta is NOT used.\r
+ //\r
+ for (Y = 0; Y < Height; ++Y) {\r
+ SetMem32 (\r
+ VgpuGop->BackingStore +\r
(DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- SegmentSize,\r
- *(UINT32 *)BltBuffer\r
- );\r
- }\r
- break;\r
-\r
- case EfiBltVideoToBltBuffer:\r
- //\r
- // Read data from the video display rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) and place it in the BltBuffer rectangle\r
- // (DestinationX, DestinationY ) (DestinationX + Width, DestinationY +\r
- // Height). If DestinationX or DestinationY is not zero then Delta must be\r
- // set to the length in bytes of a row in the BltBuffer.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- CopyMem (\r
- (UINT8 *)BltBuffer +\r
- (DestinationY + Y) * Delta + DestinationX * sizeof *BltBuffer,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
- SegmentSize\r
- );\r
- }\r
- return EFI_SUCCESS;\r
+ SegmentSize,\r
+ *(UINT32 *)BltBuffer\r
+ );\r
+ }\r
\r
- case EfiBltBufferToVideo:\r
- //\r
- // Write data from the BltBuffer rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) directly to the video display rectangle\r
- // (DestinationX, DestinationY) (DestinationX + Width, DestinationY +\r
- // Height). If SourceX or SourceY is not zero then Delta must be set to the\r
- // length in bytes of a row in the BltBuffer.\r
- //\r
- for (Y = 0; Y < Height; ++Y) {\r
- CopyMem (\r
- VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- (UINT8 *)BltBuffer +\r
- (SourceY + Y) * Delta + SourceX * sizeof *BltBuffer,\r
- SegmentSize\r
- );\r
- }\r
- break;\r
+ break;\r
\r
- case EfiBltVideoToVideo:\r
- //\r
- // Copy from the video display rectangle (SourceX, SourceY) (SourceX +\r
- // Width, SourceY + Height) to the video display rectangle (DestinationX,\r
- // DestinationY) (DestinationX + Width, DestinationY + Height). The\r
- // BltBuffer and Delta are not used in this mode.\r
- //\r
- // A single invocation of CopyMem() handles overlap between source and\r
- // destination (that is, within a single line), but for multiple\r
- // invocations, we must handle overlaps.\r
- //\r
- if (SourceY < DestinationY) {\r
- Y = Height;\r
- while (Y > 0) {\r
- --Y;\r
+ case EfiBltVideoToBltBuffer:\r
+ //\r
+ // Read data from the video display rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) and place it in the BltBuffer rectangle\r
+ // (DestinationX, DestinationY ) (DestinationX + Width, DestinationY +\r
+ // Height). If DestinationX or DestinationY is not zero then Delta must be\r
+ // set to the length in bytes of a row in the BltBuffer.\r
+ //\r
+ for (Y = 0; Y < Height; ++Y) {\r
CopyMem (\r
+ (UINT8 *)BltBuffer +\r
+ (DestinationY + Y) * Delta + DestinationX * sizeof *BltBuffer,\r
VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
SegmentSize\r
);\r
}\r
- } else {\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ case EfiBltBufferToVideo:\r
+ //\r
+ // Write data from the BltBuffer rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) directly to the video display rectangle\r
+ // (DestinationX, DestinationY) (DestinationX + Width, DestinationY +\r
+ // Height). If SourceX or SourceY is not zero then Delta must be set to the\r
+ // length in bytes of a row in the BltBuffer.\r
+ //\r
for (Y = 0; Y < Height; ++Y) {\r
CopyMem (\r
VgpuGop->BackingStore +\r
- (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
- VgpuGop->BackingStore +\r
- (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ (UINT8 *)BltBuffer +\r
+ (SourceY + Y) * Delta + SourceX * sizeof *BltBuffer,\r
SegmentSize\r
);\r
}\r
- }\r
- break;\r
\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
+ break;\r
+\r
+ case EfiBltVideoToVideo:\r
+ //\r
+ // Copy from the video display rectangle (SourceX, SourceY) (SourceX +\r
+ // Width, SourceY + Height) to the video display rectangle (DestinationX,\r
+ // DestinationY) (DestinationX + Width, DestinationY + Height). The\r
+ // BltBuffer and Delta are not used in this mode.\r
+ //\r
+ // A single invocation of CopyMem() handles overlap between source and\r
+ // destination (that is, within a single line), but for multiple\r
+ // invocations, we must handle overlaps.\r
+ //\r
+ if (SourceY < DestinationY) {\r
+ Y = Height;\r
+ while (Y > 0) {\r
+ --Y;\r
+ CopyMem (\r
+ VgpuGop->BackingStore +\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ VgpuGop->BackingStore +\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ SegmentSize\r
+ );\r
+ }\r
+ } else {\r
+ for (Y = 0; Y < Height; ++Y) {\r
+ CopyMem (\r
+ VgpuGop->BackingStore +\r
+ (DestinationY + Y) * CurrentHorizontal + DestinationX,\r
+ VgpuGop->BackingStore +\r
+ (SourceY + Y) * CurrentHorizontal + SourceX,\r
+ SegmentSize\r
+ );\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
//\r
// Template for initializing VGPU_GOP.Gop.\r
//\r
-CONST EFI_GRAPHICS_OUTPUT_PROTOCOL mGopTemplate = {\r
+CONST EFI_GRAPHICS_OUTPUT_PROTOCOL mGopTemplate = {\r
GopQueryMode,\r
GopSetMode,\r
GopBlt,\r