]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
ArmPlatformPkg: Fix Ecc error 5007 in LcdGraphicsOutputDxe
[mirror_edk2.git] / ArmPlatformPkg / Drivers / LcdGraphicsOutputDxe / LcdGraphicsOutputDxe.c
CommitLineData
1e57a462 1/** @file\r
4257dfaa 2 This file implements the Graphics Output protocol for Arm platforms\r
1e57a462 3\r
eb97f138 4 Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.<BR>\r
f4dfad05 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1e57a462 6\r
b1b69d26 7**/\r
1e57a462 8\r
9#include <PiDxe.h>\r
10#include <Library/BaseMemoryLib.h>\r
11#include <Library/DevicePathLib.h>\r
12#include <Library/UefiBootServicesTableLib.h>\r
13#include <Library/UefiRuntimeServicesTableLib.h>\r
14#include <Library/MemoryAllocationLib.h>\r
15\r
16#include <Guid/GlobalVariable.h>\r
17\r
18#include "LcdGraphicsOutputDxe.h"\r
19\r
1e57a462 20//\r
21// Global variables\r
22//\r
23\r
24BOOLEAN mDisplayInitialized = FALSE;\r
25\r
26LCD_INSTANCE mLcdTemplate = {\r
27 LCD_INSTANCE_SIGNATURE,\r
28 NULL, // Handle\r
29 { // ModeInfo\r
30 0, // Version\r
31 0, // HorizontalResolution\r
32 0, // VerticalResolution\r
33 PixelBltOnly, // PixelFormat\r
b0fdce95 34 { 0 }, // PixelInformation\r
1e57a462 35 0, // PixelsPerScanLine\r
36 },\r
37 {\r
38 0, // MaxMode;\r
39 0, // Mode;\r
40 NULL, // Info;\r
41 0, // SizeOfInfo;\r
42 0, // FrameBufferBase;\r
43 0 // FrameBufferSize;\r
44 },\r
45 { // Gop\r
46 LcdGraphicsQueryMode, // QueryMode\r
47 LcdGraphicsSetMode, // SetMode\r
48 LcdGraphicsBlt, // Blt\r
49 NULL // *Mode\r
50 },\r
51 { // DevicePath\r
52 {\r
53 {\r
54 HARDWARE_DEVICE_PATH, HW_VENDOR_DP,\r
b1b69d26
GP
55 {\r
56 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
57 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
58 },\r
1e57a462 59 },\r
60 // Hardware Device Path for Lcd\r
61 EFI_CALLER_ID_GUID // Use the driver's GUID\r
62 },\r
63\r
64 {\r
65 END_DEVICE_PATH_TYPE,\r
66 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
b1b69d26
GP
67 {\r
68 sizeof (EFI_DEVICE_PATH_PROTOCOL),\r
69 0\r
70 }\r
1e57a462 71 }\r
72 },\r
b1b69d26 73 (EFI_EVENT)NULL // ExitBootServicesEvent\r
1e57a462 74};\r
75\r
76EFI_STATUS\r
77LcdInstanceContructor (\r
78 OUT LCD_INSTANCE** NewInstance\r
79 )\r
80{\r
81 LCD_INSTANCE* Instance;\r
82\r
b1b69d26 83 Instance = AllocateCopyPool (sizeof (LCD_INSTANCE), &mLcdTemplate);\r
1e57a462 84 if (Instance == NULL) {\r
85 return EFI_OUT_OF_RESOURCES;\r
86 }\r
87\r
88 Instance->Gop.Mode = &Instance->Mode;\r
89 Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();\r
90 Instance->Mode.Info = &Instance->ModeInfo;\r
91\r
92 *NewInstance = Instance;\r
93 return EFI_SUCCESS;\r
94}\r
95\r
96//\r
97// Function Definitions\r
98//\r
99\r
100EFI_STATUS\r
101InitializeDisplay (\r
102 IN LCD_INSTANCE* Instance\r
103 )\r
104{\r
eb97f138 105 EFI_STATUS Status;\r
1e57a462 106 EFI_PHYSICAL_ADDRESS VramBaseAddress;\r
107 UINTN VramSize;\r
108\r
109 Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);\r
b1b69d26 110 if (EFI_ERROR (Status)) {\r
1e57a462 111 return Status;\r
112 }\r
113\r
114 // Setup the LCD\r
115 Status = LcdInitialize (VramBaseAddress);\r
b1b69d26 116 if (EFI_ERROR (Status)) {\r
1e57a462 117 goto EXIT_ERROR_LCD_SHUTDOWN;\r
118 }\r
119\r
120 Status = LcdPlatformInitializeDisplay (Instance->Handle);\r
b1b69d26 121 if (EFI_ERROR (Status)) {\r
1e57a462 122 goto EXIT_ERROR_LCD_SHUTDOWN;\r
123 }\r
124\r
125 // Setup all the relevant mode information\r
b1b69d26 126 Instance->Gop.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1e57a462 127 Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;\r
1e57a462 128\r
129 // Set the flag before changing the mode, to avoid infinite loops\r
130 mDisplayInitialized = TRUE;\r
131\r
132 // All is ok, so don't deal with any errors\r
133 goto EXIT;\r
134\r
135EXIT_ERROR_LCD_SHUTDOWN:\r
b1b69d26
GP
136 DEBUG ((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));\r
137\r
1e57a462 138 LcdShutdown ();\r
139\r
140EXIT:\r
141 return Status;\r
142}\r
143\r
144EFI_STATUS\r
145EFIAPI\r
146LcdGraphicsOutputDxeInitialize (\r
147 IN EFI_HANDLE ImageHandle,\r
148 IN EFI_SYSTEM_TABLE *SystemTable\r
149 )\r
150{\r
eb97f138 151 EFI_STATUS Status;\r
1e57a462 152 LCD_INSTANCE* Instance;\r
153\r
9dc94d98 154 Status = LcdIdentify ();\r
b1b69d26 155 if (EFI_ERROR (Status)) {\r
9dc94d98
AB
156 goto EXIT;\r
157 }\r
158\r
1e57a462 159 Status = LcdInstanceContructor (&Instance);\r
b1b69d26 160 if (EFI_ERROR (Status)) {\r
1e57a462 161 goto EXIT;\r
162 }\r
163\r
91c38d4e 164 // Install the Graphics Output Protocol and the Device Path\r
b1b69d26
GP
165 Status = gBS->InstallMultipleProtocolInterfaces (\r
166 &Instance->Handle,\r
167 &gEfiGraphicsOutputProtocolGuid,\r
168 &Instance->Gop,\r
169 &gEfiDevicePathProtocolGuid,\r
170 &Instance->DevicePath,\r
171 NULL\r
172 );\r
173\r
174 if (EFI_ERROR (Status)) {\r
175 DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));\r
91c38d4e
RC
176 goto EXIT;\r
177 }\r
178\r
179 // Register for an ExitBootServicesEvent\r
b1b69d26
GP
180 // When ExitBootServices starts, this function will make sure that the\r
181 // graphics driver shuts down properly, i.e. it will free up all\r
182 // allocated memory and perform any necessary hardware re-configuration.\r
91c38d4e 183 Status = gBS->CreateEvent (\r
b1b69d26
GP
184 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
185 TPL_NOTIFY,\r
186 LcdGraphicsExitBootServicesEvent,\r
187 NULL,\r
188 &Instance->ExitBootServicesEvent\r
189 );\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 DEBUG ((DEBUG_ERROR, "LcdGraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));\r
91c38d4e
RC
193 goto EXIT_ERROR_UNINSTALL_PROTOCOL;\r
194 }\r
195\r
196 // To get here, everything must be fine, so just exit\r
197 goto EXIT;\r
1e57a462 198\r
199EXIT_ERROR_UNINSTALL_PROTOCOL:\r
b1b69d26
GP
200 // The following function could return an error message,\r
201 // however, to get here something must have gone wrong already,\r
202 // so preserve the original error, i.e. don't change\r
203 // the Status variable, even it fails to uninstall the protocol.\r
91c38d4e 204 gBS->UninstallMultipleProtocolInterfaces (\r
b1b69d26
GP
205 Instance->Handle,\r
206 &gEfiGraphicsOutputProtocolGuid,\r
207 &Instance->Gop, // Uninstall Graphics Output protocol\r
208 &gEfiDevicePathProtocolGuid,\r
209 &Instance->DevicePath, // Uninstall device path\r
210 NULL\r
211 );\r
1e57a462 212\r
213EXIT:\r
91c38d4e 214 return Status;\r
1e57a462 215}\r
216\r
b1b69d26
GP
217/** This function should be called\r
218 on Event: ExitBootServices\r
219 to free up memory, stop the driver\r
220 and uninstall the protocols\r
221**/\r
1e57a462 222VOID\r
223LcdGraphicsExitBootServicesEvent (\r
224 IN EFI_EVENT Event,\r
225 IN VOID *Context\r
226 )\r
227{\r
b1b69d26
GP
228 // By default, this PCD is FALSE. But if a platform starts a predefined OS\r
229 // that does not use a framebuffer then we might want to disable the display\r
230 // controller to avoid to display corrupted information on the screen.\r
d8c4bb9a
OM
231 if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {\r
232 // Turn-off the Display controller\r
233 LcdShutdown ();\r
234 }\r
1e57a462 235}\r
236\r
b1b69d26
GP
237/** GraphicsOutput Protocol function, mapping to\r
238 EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode\r
239**/\r
1e57a462 240EFI_STATUS\r
241EFIAPI\r
242LcdGraphicsQueryMode (\r
243 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
91c38d4e
RC
244 IN UINT32 ModeNumber,\r
245 OUT UINTN *SizeOfInfo,\r
246 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
247 )\r
1e57a462 248{\r
eb97f138 249 EFI_STATUS Status;\r
91c38d4e 250 LCD_INSTANCE *Instance;\r
1e57a462 251\r
b1b69d26 252 Instance = LCD_INSTANCE_FROM_GOP_THIS (This);\r
1e57a462 253\r
254 // Setup the hardware if not already done\r
b1b69d26
GP
255 if (!mDisplayInitialized) {\r
256 Status = InitializeDisplay (Instance);\r
257 if (EFI_ERROR (Status)) {\r
1e57a462 258 goto EXIT;\r
259 }\r
260 }\r
261\r
91c38d4e 262 // Error checking\r
b1b69d26
GP
263 if ((This == NULL) ||\r
264 (Info == NULL) ||\r
265 (SizeOfInfo == NULL) ||\r
266 (ModeNumber >= This->Mode->MaxMode)) {\r
267 DEBUG ((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber));\r
91c38d4e
RC
268 Status = EFI_INVALID_PARAMETER;\r
269 goto EXIT;\r
270 }\r
1e57a462 271\r
91c38d4e 272 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
1e57a462 273 if (*Info == NULL) {\r
274 Status = EFI_OUT_OF_RESOURCES;\r
275 goto EXIT;\r
276 }\r
277\r
b1b69d26 278 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1e57a462 279\r
b1b69d26
GP
280 Status = LcdPlatformQueryMode (ModeNumber, *Info);\r
281 if (EFI_ERROR (Status)) {\r
282 FreePool (*Info);\r
1e57a462 283 }\r
284\r
285EXIT:\r
91c38d4e 286 return Status;\r
1e57a462 287}\r
288\r
b1b69d26
GP
289/** GraphicsOutput Protocol function, mapping to\r
290 EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode\r
291**/\r
1e57a462 292EFI_STATUS\r
293EFIAPI\r
294LcdGraphicsSetMode (\r
295 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
91c38d4e
RC
296 IN UINT32 ModeNumber\r
297 )\r
1e57a462 298{\r
eb97f138 299 EFI_STATUS Status;\r
91c38d4e
RC
300 EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;\r
301 LCD_INSTANCE* Instance;\r
302 LCD_BPP Bpp;\r
1e57a462 303\r
91c38d4e 304 Instance = LCD_INSTANCE_FROM_GOP_THIS (This);\r
1e57a462 305\r
306 // Setup the hardware if not already done\r
b1b69d26 307 if (!mDisplayInitialized) {\r
1e57a462 308 Status = InitializeDisplay (Instance);\r
b1b69d26 309 if (EFI_ERROR (Status)) {\r
1e57a462 310 goto EXIT;\r
311 }\r
312 }\r
313\r
314 // Check if this mode is supported\r
b1b69d26
GP
315 if (ModeNumber >= This->Mode->MaxMode) {\r
316 DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber));\r
1e57a462 317 Status = EFI_UNSUPPORTED;\r
318 goto EXIT;\r
319 }\r
320\r
91c38d4e 321 // Set the oscillator frequency to support the new mode\r
1e57a462 322 Status = LcdPlatformSetMode (ModeNumber);\r
b1b69d26 323 if (EFI_ERROR (Status)) {\r
1e57a462 324 Status = EFI_DEVICE_ERROR;\r
325 goto EXIT;\r
326 }\r
327\r
91c38d4e
RC
328 // Update the UEFI mode information\r
329 This->Mode->Mode = ModeNumber;\r
b1b69d26
GP
330 LcdPlatformQueryMode (ModeNumber, &Instance->ModeInfo);\r
331 Status = LcdPlatformGetBpp (ModeNumber, &Bpp);\r
332 if (EFI_ERROR (Status)) {\r
91c38d4e
RC
333 DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));\r
334 goto EXIT;\r
335 }\r
336 This->Mode->FrameBufferSize = Instance->ModeInfo.VerticalResolution\r
b1b69d26
GP
337 * Instance->ModeInfo.PixelsPerScanLine\r
338 * GetBytesPerPixel (Bpp);\r
1e57a462 339\r
340 // Set the hardware to the new mode\r
91c38d4e 341 Status = LcdSetMode (ModeNumber);\r
b1b69d26 342 if (EFI_ERROR (Status)) {\r
1e57a462 343 Status = EFI_DEVICE_ERROR;\r
344 goto EXIT;\r
345 }\r
346\r
b1b69d26
GP
347 // The UEFI spec requires that we now clear the visible portions of the\r
348 // output display to black.\r
1e57a462 349\r
350 // Set the fill colour to black\r
351 SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
352\r
353 // Fill the entire visible area with the same colour.\r
354 Status = This->Blt (\r
355 This,\r
356 &FillColour,\r
357 EfiBltVideoFill,\r
358 0,\r
359 0,\r
360 0,\r
361 0,\r
362 This->Mode->Info->HorizontalResolution,\r
363 This->Mode->Info->VerticalResolution,\r
b1b69d26
GP
364 0\r
365 );\r
1e57a462 366\r
367EXIT:\r
91c38d4e 368 return Status;\r
1e57a462 369}\r
370\r
371UINTN\r
372GetBytesPerPixel (\r
373 IN LCD_BPP Bpp\r
374 )\r
375{\r
b1b69d26 376 switch (Bpp) {\r
1e57a462 377 case LCD_BITS_PER_PIXEL_24:\r
378 return 4;\r
379\r
380 case LCD_BITS_PER_PIXEL_16_565:\r
381 case LCD_BITS_PER_PIXEL_16_555:\r
382 case LCD_BITS_PER_PIXEL_12_444:\r
383 return 2;\r
384\r
385 case LCD_BITS_PER_PIXEL_8:\r
386 case LCD_BITS_PER_PIXEL_4:\r
387 case LCD_BITS_PER_PIXEL_2:\r
388 case LCD_BITS_PER_PIXEL_1:\r
389 return 1;\r
390\r
391 default:\r
392 return 0;\r
393 }\r
394}\r