]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/EmuGopDxe/GopScreen.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmulatorPkg / EmuGopDxe / GopScreen.c
1 /*++ @file
2
3 Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 Module Name:
8
9 EmuGopScreen.c
10
11 Abstract:
12
13 This file produces the graphics abstration of UGA. It is called by
14 EmuGopDriver.c file which deals with the EFI 1.1 driver model.
15 This file just does graphics.
16
17 **/
18
19 #include "Gop.h"
20
21 EFI_EVENT mGopScreenExitBootServicesEvent;
22
23 GOP_MODE_DATA mGopModeData[] = {
24 { 800, 600, 0, 0 },
25 { 640, 480, 0, 0 },
26 { 720, 400, 0, 0 },
27 { 1024, 768, 0, 0 },
28 { 1280, 1024, 0, 0 }
29 };
30
31 /**
32 Returns information for an available graphics mode that the graphics device
33 and the set of active video output devices supports.
34
35 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
36 @param ModeNumber The mode number to return information on.
37 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
38 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
39
40 @retval EFI_SUCCESS Mode information returned.
41 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
42 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
43 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
44 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
45
46 **/
47 EFI_STATUS
48 EFIAPI
49 EmuGopQuerytMode (
50 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
51 IN UINT32 ModeNumber,
52 OUT UINTN *SizeOfInfo,
53 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
54 )
55 {
56 GOP_PRIVATE_DATA *Private;
57
58 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
59
60 if ((Info == NULL) || (SizeOfInfo == NULL) || ((UINTN)ModeNumber >= This->Mode->MaxMode)) {
61 return EFI_INVALID_PARAMETER;
62 }
63
64 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
65 if (*Info == NULL) {
66 return EFI_OUT_OF_RESOURCES;
67 }
68
69 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
70
71 (*Info)->Version = 0;
72 (*Info)->HorizontalResolution = Private->ModeData[ModeNumber].HorizontalResolution;
73 (*Info)->VerticalResolution = Private->ModeData[ModeNumber].VerticalResolution;
74 (*Info)->PixelFormat = PixelBltOnly;
75 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
76
77 return EFI_SUCCESS;
78 }
79
80 /**
81 Set the video device into the specified mode and clears the visible portions of
82 the output display to black.
83
84 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
85 @param ModeNumber Abstraction that defines the current video mode.
86
87 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
88 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
89 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
90
91 **/
92 EFI_STATUS
93 EFIAPI
94 EmuGopSetMode (
95 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
96 IN UINT32 ModeNumber
97 )
98 {
99 EFI_STATUS Status;
100 GOP_PRIVATE_DATA *Private;
101 GOP_MODE_DATA *ModeData;
102 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
103
104 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
105
106 if (ModeNumber >= This->Mode->MaxMode) {
107 return EFI_UNSUPPORTED;
108 }
109
110 ModeData = &Private->ModeData[ModeNumber];
111
112 if (Private->HardwareNeedsStarting) {
113 Status = EmuGopStartWindow (
114 Private,
115 ModeData->HorizontalResolution,
116 ModeData->VerticalResolution,
117 ModeData->ColorDepth,
118 ModeData->RefreshRate
119 );
120 if (EFI_ERROR (Status)) {
121 return EFI_DEVICE_ERROR;
122 }
123
124 Private->HardwareNeedsStarting = FALSE;
125 }
126
127 This->Mode->Mode = ModeNumber;
128 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
129 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
130 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
131
132 Status = Private->EmuGraphicsWindow->Size (
133 Private->EmuGraphicsWindow,
134 ModeData->HorizontalResolution,
135 ModeData->VerticalResolution
136 );
137
138 Fill.Red = 0;
139 Fill.Green = 0;
140 Fill.Blue = 0;
141 This->Blt (
142 This,
143 &Fill,
144 EfiBltVideoFill,
145 0,
146 0,
147 0,
148 0,
149 ModeData->HorizontalResolution,
150 ModeData->VerticalResolution,
151 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
152 );
153 return EFI_SUCCESS;
154 }
155
156 /**
157 Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
158
159 @param This Protocol instance pointer.
160 @param BltBuffer Buffer containing data to blit into video buffer. This
161 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
162 @param BltOperation Operation to perform on BlitBuffer and video memory
163 @param SourceX X coordinate of source for the BltBuffer.
164 @param SourceY Y coordinate of source for the BltBuffer.
165 @param DestinationX X coordinate of destination for the BltBuffer.
166 @param DestinationY Y coordinate of destination for the BltBuffer.
167 @param Width Width of rectangle in BltBuffer in pixels.
168 @param Height Hight of rectangle in BltBuffer in pixels.
169 @param Delta OPTIONAL
170
171 @retval EFI_SUCCESS The Blt operation completed.
172 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
173 @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
174
175 **/
176 EFI_STATUS
177 EFIAPI
178 EmuGopBlt (
179 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
180 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
181 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
182 IN UINTN SourceX,
183 IN UINTN SourceY,
184 IN UINTN DestinationX,
185 IN UINTN DestinationY,
186 IN UINTN Width,
187 IN UINTN Height,
188 IN UINTN Delta OPTIONAL
189 )
190 {
191 GOP_PRIVATE_DATA *Private;
192 EFI_TPL OriginalTPL;
193 EFI_STATUS Status;
194 EMU_GRAPHICS_WINDOWS__BLT_ARGS GopBltArgs;
195
196 Private = GOP_PRIVATE_DATA_FROM_THIS (This);
197
198 if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
199 return EFI_INVALID_PARAMETER;
200 }
201
202 if ((Width == 0) || (Height == 0)) {
203 return EFI_INVALID_PARAMETER;
204 }
205
206 //
207 // If Delta is zero, then the entire BltBuffer is being used, so Delta
208 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
209 // the number of bytes in each row can be computed.
210 //
211 if (Delta == 0) {
212 Delta = Width * sizeof (EFI_UGA_PIXEL);
213 }
214
215 //
216 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
217 // We would not want a timer based event (Cursor, ...) to come in while we are
218 // doing this operation.
219 //
220 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
221
222 //
223 // Pack UGA Draw protocol parameters to EMU_GRAPHICS_WINDOWS__BLT_ARGS structure to adapt to
224 // GopBlt() API of Unix UGA IO protocol.
225 //
226 GopBltArgs.DestinationX = DestinationX;
227 GopBltArgs.DestinationY = DestinationY;
228 GopBltArgs.Height = Height;
229 GopBltArgs.Width = Width;
230 GopBltArgs.SourceX = SourceX;
231 GopBltArgs.SourceY = SourceY;
232 GopBltArgs.Delta = Delta;
233 Status = Private->EmuGraphicsWindow->Blt (
234 Private->EmuGraphicsWindow,
235 (EFI_UGA_PIXEL *)BltBuffer,
236 (EFI_UGA_BLT_OPERATION)BltOperation,
237 &GopBltArgs
238 );
239
240 gBS->RestoreTPL (OriginalTPL);
241
242 return Status;
243 }
244
245 //
246 // Construction and Destruction functions
247 //
248
249 EFI_STATUS
250 EmuGopSupported (
251 IN EMU_IO_THUNK_PROTOCOL *EmuIoThunk
252 )
253 {
254 //
255 // Check to see if the IO abstraction represents a device type we support.
256 //
257 // This would be replaced a check of PCI subsystem ID, etc.
258 //
259 if (!CompareGuid (EmuIoThunk->Protocol, &gEmuGraphicsWindowProtocolGuid)) {
260 return EFI_UNSUPPORTED;
261 }
262
263 return EFI_SUCCESS;
264 }
265
266 EFI_STATUS
267 EmuGopStartWindow (
268 IN GOP_PRIVATE_DATA *Private,
269 IN UINT32 HorizontalResolution,
270 IN UINT32 VerticalResolution,
271 IN UINT32 ColorDepth,
272 IN UINT32 RefreshRate
273 )
274 {
275 EFI_STATUS Status;
276
277 //
278 // Register to be notified on exit boot services so we can destroy the window.
279 //
280 Status = gBS->CreateEvent (
281 EVT_SIGNAL_EXIT_BOOT_SERVICES,
282 TPL_CALLBACK,
283 ShutdownGopEvent,
284 Private,
285 &mGopScreenExitBootServicesEvent
286 );
287
288 Status = Private->EmuIoThunk->Open (Private->EmuIoThunk);
289 if (!EFI_ERROR (Status)) {
290 Private->EmuGraphicsWindow = Private->EmuIoThunk->Interface;
291
292 // Register callback to support RegisterKeyNotify()
293 Status = Private->EmuGraphicsWindow->RegisterKeyNotify (
294 Private->EmuGraphicsWindow,
295 GopPrivateMakeCallbackFunction,
296 GopPrivateBreakCallbackFunction,
297 Private
298 );
299 ASSERT_EFI_ERROR (Status);
300 }
301
302 return Status;
303 }
304
305 EFI_STATUS
306 EmuGopConstructor (
307 GOP_PRIVATE_DATA *Private
308 )
309 {
310 Private->ModeData = mGopModeData;
311
312 Private->GraphicsOutput.QueryMode = EmuGopQuerytMode;
313 Private->GraphicsOutput.SetMode = EmuGopSetMode;
314 Private->GraphicsOutput.Blt = EmuGopBlt;
315
316 //
317 // Allocate buffer for Graphics Output Protocol mode information
318 //
319 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
320 if (Private->GraphicsOutput.Mode == NULL) {
321 return EFI_OUT_OF_RESOURCES;
322 }
323
324 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
325 if (Private->GraphicsOutput.Mode->Info == NULL) {
326 return EFI_OUT_OF_RESOURCES;
327 }
328
329 Private->GraphicsOutput.Mode->MaxMode = sizeof (mGopModeData) / sizeof (GOP_MODE_DATA);
330 //
331 // Till now, we have no idea about the window size.
332 //
333 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
334 Private->GraphicsOutput.Mode->Info->Version = 0;
335 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
336 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
337 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBltOnly;
338 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
339 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)NULL;
340 Private->GraphicsOutput.Mode->FrameBufferSize = 0;
341
342 Private->HardwareNeedsStarting = TRUE;
343 Private->EmuGraphicsWindow = NULL;
344
345 EmuGopInitializeSimpleTextInForWindow (Private);
346
347 EmuGopInitializeSimplePointerForWindow (Private);
348
349 return EFI_SUCCESS;
350 }
351
352 EFI_STATUS
353 EmuGopDestructor (
354 GOP_PRIVATE_DATA *Private
355 )
356 {
357 if (!Private->HardwareNeedsStarting) {
358 Private->EmuIoThunk->Close (Private->EmuIoThunk);
359 Private->EmuGraphicsWindow = NULL;
360 }
361
362 //
363 // Free graphics output protocol occupied resource
364 //
365 if (Private->GraphicsOutput.Mode != NULL) {
366 if (Private->GraphicsOutput.Mode->Info != NULL) {
367 FreePool (Private->GraphicsOutput.Mode->Info);
368 }
369
370 FreePool (Private->GraphicsOutput.Mode);
371 }
372
373 return EFI_SUCCESS;
374 }
375
376 VOID
377 EFIAPI
378 ShutdownGopEvent (
379 IN EFI_EVENT Event,
380 IN VOID *Context
381 )
382
383 /*++
384
385 Routine Description:
386
387 This is the UGA screen's callback notification function for exit-boot-services.
388 All we do here is call EmuGopDestructor().
389
390 Arguments:
391
392 Event - not used
393 Context - pointer to the Private structure.
394
395 Returns:
396
397 None.
398
399 **/
400 {
401 EmuGopDestructor (Context);
402 }