]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootPayloadPkg/FbGop/FbGop.c
CorebootPayloadPkg/FbGop: Locate correct framebuffer device
[mirror_edk2.git] / CorebootPayloadPkg / FbGop / FbGop.c
CommitLineData
9c228fb0
MM
1/** @file\r
2 ConsoleOut Routines that speak VGA.\r
3\r
4Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
5\r
d2e8b7e1 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
9c228fb0
MM
7\r
8**/\r
9\r
10#include "FbGop.h"\r
11\r
12EFI_PIXEL_BITMASK mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};\r
13\r
14//\r
15// Save controller attributes during first start\r
16//\r
17UINT64 mOriginalPciAttributes;\r
18BOOLEAN mPciAttributesSaved = FALSE;\r
ae2fb9ea 19FRAME_BUFFER_INFO *mFrameBufferInfo;\r
9c228fb0
MM
20\r
21//\r
22// EFI Driver Binding Protocol Instance\r
23//\r
24EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = {\r
25 FbGopDriverBindingSupported,\r
26 FbGopDriverBindingStart,\r
27 FbGopDriverBindingStop,\r
28 0x3,\r
29 NULL,\r
30 NULL\r
31};\r
32\r
33//\r
34// Native resolution in EDID DetailedTiming[0]\r
35//\r
36UINT32 mNativeModeHorizontal;\r
37UINT32 mNativeModeVertical;\r
38\r
39/**\r
40 Supported.\r
41\r
42 @param This Pointer to driver binding protocol\r
43 @param Controller Controller handle to connect\r
44 @param RemainingDevicePath A pointer to the remaining portion of a device\r
45 path\r
46\r
47 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this\r
48 driver, Otherwise, this controller cannot be\r
49 managed by this driver\r
50\r
51**/\r
52EFI_STATUS\r
53EFIAPI\r
54FbGopDriverBindingSupported (\r
55 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
56 IN EFI_HANDLE Controller,\r
57 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
58 )\r
59{\r
ae2fb9ea 60 EFI_STATUS Status;\r
9c228fb0 61 EFI_PCI_IO_PROTOCOL *PciIo;\r
ae2fb9ea 62 PCI_TYPE00 Pci;\r
9c228fb0 63 EFI_DEV_PATH *Node;\r
ae2fb9ea
MM
64 UINT8 Index;\r
65 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;\r
9c228fb0
MM
66\r
67 //\r
68 // Open the IO Abstraction(s) needed to perform the supported test\r
69 //\r
70 Status = gBS->OpenProtocol (\r
71 Controller,\r
72 &gEfiPciIoProtocolGuid,\r
73 (VOID **) &PciIo,\r
74 This->DriverBindingHandle,\r
75 Controller,\r
76 EFI_OPEN_PROTOCOL_BY_DRIVER\r
77 );\r
78 if (EFI_ERROR (Status)) {\r
79 return Status;\r
80 }\r
81\r
82 //\r
83 // See if this is a PCI Graphics Controller by looking at the Command register and\r
84 // Class Code Register\r
85 //\r
86 Status = PciIo->Pci.Read (\r
87 PciIo,\r
88 EfiPciIoWidthUint32,\r
89 0,\r
90 sizeof (Pci) / sizeof (UINT32),\r
91 &Pci\r
92 );\r
93 if (EFI_ERROR (Status)) {\r
94 Status = EFI_UNSUPPORTED;\r
95 goto Done;\r
96 }\r
97\r
98 Status = EFI_UNSUPPORTED;\r
ae2fb9ea 99 if (IS_PCI_DISPLAY (&Pci) || IS_PCI_OLD_VGA (&Pci)) {\r
9c228fb0 100 //\r
ae2fb9ea 101 // Check if PCI BAR matches the framebuffer base\r
9c228fb0 102 //\r
ae2fb9ea
MM
103 Status = EFI_UNSUPPORTED;\r
104 for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
105 Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources);\r
106 if (!EFI_ERROR (Status)) {\r
107 if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) &&\r
108 (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) &&\r
109 (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&\r
110 (Resources->AddrRangeMin == mFrameBufferInfo->LinearFrameBuffer)) {\r
111 DEBUG ((DEBUG_INFO, "Found matched framebuffer PCI BAR !\n"));\r
112 Status = EFI_SUCCESS;\r
113 break;\r
114 }\r
115 }\r
116 }\r
117\r
118 if (!EFI_ERROR (Status)) {\r
9c228fb0 119 //\r
ae2fb9ea
MM
120 // If this is a graphics controller,\r
121 // go further check RemainingDevicePath\r
9c228fb0 122 //\r
ae2fb9ea
MM
123 if (RemainingDevicePath != NULL) {\r
124 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
9c228fb0 125 //\r
ae2fb9ea
MM
126 // Check if RemainingDevicePath is the End of Device Path Node,\r
127 // if yes, return EFI_SUCCESS\r
9c228fb0 128 //\r
ae2fb9ea
MM
129 if (!IsDevicePathEnd (Node)) {\r
130 //\r
131 // Verify RemainingDevicePath\r
132 //\r
133 if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
134 Node->DevPath.SubType != ACPI_ADR_DP ||\r
135 DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {\r
136 Status = EFI_UNSUPPORTED;\r
137 }\r
9c228fb0
MM
138 }\r
139 }\r
140 }\r
141 }\r
142\r
143Done:\r
144 gBS->CloseProtocol (\r
145 Controller,\r
146 &gEfiPciIoProtocolGuid,\r
147 This->DriverBindingHandle,\r
148 Controller\r
149 );\r
150\r
151 return Status;\r
152}\r
153\r
154\r
155/**\r
156 Install Graphics Output Protocol onto VGA device handles.\r
157\r
158 @param This Pointer to driver binding protocol\r
159 @param Controller Controller handle to connect\r
160 @param RemainingDevicePath A pointer to the remaining portion of a device\r
161 path\r
162\r
163 @return EFI_STATUS\r
164\r
165**/\r
166EFI_STATUS\r
167EFIAPI\r
168FbGopDriverBindingStart (\r
169 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
170 IN EFI_HANDLE Controller,\r
171 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
172 )\r
173{\r
174 EFI_STATUS Status;\r
175 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
ae2fb9ea 176 EFI_PCI_IO_PROTOCOL *PciIo;\r
9c228fb0
MM
177 UINT64 Supports;\r
178\r
ae2fb9ea
MM
179 DEBUG ((DEBUG_INFO, "GOP START\n"));\r
180\r
9c228fb0
MM
181 //\r
182 // Initialize local variables\r
183 //\r
184 PciIo = NULL;\r
185 ParentDevicePath = NULL;\r
186\r
187 //\r
188 // Prepare for status code\r
189 //\r
190 Status = gBS->HandleProtocol (\r
191 Controller,\r
192 &gEfiDevicePathProtocolGuid,\r
193 (VOID **) &ParentDevicePath\r
194 );\r
195 if (EFI_ERROR (Status)) {\r
196 return Status;\r
197 }\r
198\r
199 //\r
200 // Open the IO Abstraction(s) needed\r
201 //\r
202 Status = gBS->OpenProtocol (\r
203 Controller,\r
204 &gEfiPciIoProtocolGuid,\r
205 (VOID **) &PciIo,\r
206 This->DriverBindingHandle,\r
207 Controller,\r
208 EFI_OPEN_PROTOCOL_BY_DRIVER\r
209 );\r
210 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
211 return Status;\r
212 }\r
213\r
214 //\r
215 // Save original PCI attributes\r
216 //\r
217 if (!mPciAttributesSaved) {\r
218 Status = PciIo->Attributes (\r
219 PciIo,\r
220 EfiPciIoAttributeOperationGet,\r
221 0,\r
222 &mOriginalPciAttributes\r
223 );\r
ae2fb9ea 224\r
9c228fb0
MM
225 if (EFI_ERROR (Status)) {\r
226 goto Done;\r
227 }\r
228 mPciAttributesSaved = TRUE;\r
229 }\r
230\r
231 //\r
232 // Get supported PCI attributes\r
233 //\r
234 Status = PciIo->Attributes (\r
235 PciIo,\r
236 EfiPciIoAttributeOperationSupported,\r
237 0,\r
238 &Supports\r
239 );\r
240 if (EFI_ERROR (Status)) {\r
241 goto Done;\r
242 }\r
243\r
244 Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
245 if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {\r
246 Status = EFI_UNSUPPORTED;\r
247 goto Done;\r
ae2fb9ea
MM
248 }\r
249\r
9c228fb0
MM
250 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
251 EFI_PROGRESS_CODE,\r
252 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,\r
253 ParentDevicePath\r
254 );\r
255 //\r
256 // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
257 //\r
258 Status = PciIo->Attributes (\r
259 PciIo,\r
260 EfiPciIoAttributeOperationEnable,\r
261 EFI_PCI_DEVICE_ENABLE,\r
262 NULL\r
263 );\r
264 if (EFI_ERROR (Status)) {\r
265 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
266 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
267 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,\r
268 ParentDevicePath\r
269 );\r
270 goto Done;\r
271 }\r
272\r
273 if (RemainingDevicePath != NULL) {\r
274 if (IsDevicePathEnd (RemainingDevicePath)) {\r
275 //\r
276 // If RemainingDevicePath is the End of Device Path Node,\r
68f87b25 277 // don't create any child device and return EFI_SUCCESS\r
9c228fb0
MM
278 Status = EFI_SUCCESS;\r
279 goto Done;\r
280 }\r
281 }\r
ae2fb9ea 282\r
9c228fb0
MM
283 //\r
284 // Create child handle and install GraphicsOutputProtocol on it\r
285 //\r
286 Status = FbGopChildHandleInstall (\r
287 This,\r
288 Controller,\r
289 PciIo,\r
290 NULL,\r
291 ParentDevicePath,\r
292 RemainingDevicePath\r
293 );\r
ae2fb9ea 294\r
9c228fb0
MM
295Done:\r
296 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
ae2fb9ea 297\r
9c228fb0
MM
298 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
299 EFI_PROGRESS_CODE,\r
300 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,\r
301 ParentDevicePath\r
302 );\r
303\r
304 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
305 EFI_PROGRESS_CODE,\r
306 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
307 ParentDevicePath\r
308 );\r
309 if (!HasChildHandle (Controller)) {\r
310 if (mPciAttributesSaved) {\r
311 //\r
312 // Restore original PCI attributes\r
313 //\r
314 PciIo->Attributes (\r
315 PciIo,\r
316 EfiPciIoAttributeOperationSet,\r
317 mOriginalPciAttributes,\r
318 NULL\r
319 );\r
320 }\r
321 }\r
322 //\r
323 // Release PCI I/O Protocols on the controller handle.\r
324 //\r
325 gBS->CloseProtocol (\r
326 Controller,\r
327 &gEfiPciIoProtocolGuid,\r
328 This->DriverBindingHandle,\r
329 Controller\r
330 );\r
331 }\r
332\r
333 return Status;\r
334}\r
335\r
336\r
337/**\r
338 Stop.\r
339\r
340 @param This Pointer to driver binding protocol\r
341 @param Controller Controller handle to connect\r
342 @param NumberOfChildren Number of children handle created by this driver\r
343 @param ChildHandleBuffer Buffer containing child handle created\r
344\r
345 @retval EFI_SUCCESS Driver disconnected successfully from controller\r
346 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure\r
347\r
348**/\r
349EFI_STATUS\r
350EFIAPI\r
351FbGopDriverBindingStop (\r
352 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
353 IN EFI_HANDLE Controller,\r
354 IN UINTN NumberOfChildren,\r
355 IN EFI_HANDLE *ChildHandleBuffer\r
356 )\r
357{\r
358 EFI_STATUS Status;\r
359 BOOLEAN AllChildrenStopped;\r
360 UINTN Index;\r
361 EFI_PCI_IO_PROTOCOL *PciIo;\r
362\r
363 AllChildrenStopped = TRUE;\r
364\r
365 if (NumberOfChildren == 0) {\r
366 //\r
367 // Close PCI I/O protocol on the controller handle\r
368 //\r
369 gBS->CloseProtocol (\r
370 Controller,\r
371 &gEfiPciIoProtocolGuid,\r
372 This->DriverBindingHandle,\r
373 Controller\r
374 );\r
375\r
376 return EFI_SUCCESS;\r
377 }\r
378\r
379 for (Index = 0; Index < NumberOfChildren; Index++) {\r
ae2fb9ea 380\r
9c228fb0
MM
381 Status = EFI_SUCCESS;\r
382\r
383 FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
384\r
385 if (EFI_ERROR (Status)) {\r
386 AllChildrenStopped = FALSE;\r
387 }\r
388 }\r
389\r
390 if (!AllChildrenStopped) {\r
391 return EFI_DEVICE_ERROR;\r
392 }\r
393\r
394 if (!HasChildHandle (Controller)) {\r
395 if (mPciAttributesSaved) {\r
396 Status = gBS->HandleProtocol (\r
397 Controller,\r
398 &gEfiPciIoProtocolGuid,\r
399 (VOID **) &PciIo\r
400 );\r
401 ASSERT_EFI_ERROR (Status);\r
ae2fb9ea 402\r
9c228fb0
MM
403 //\r
404 // Restore original PCI attributes\r
405 //\r
406 Status = PciIo->Attributes (\r
407 PciIo,\r
408 EfiPciIoAttributeOperationSet,\r
409 mOriginalPciAttributes,\r
410 NULL\r
411 );\r
412 ASSERT_EFI_ERROR (Status);\r
413 }\r
414 }\r
415\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420\r
421/**\r
422 Install child handles if the Handle supports MBR format.\r
423\r
424 @param This Calling context.\r
425 @param ParentHandle Parent Handle\r
426 @param ParentPciIo Parent PciIo interface\r
427 @param ParentLegacyBios Parent LegacyBios interface\r
428 @param ParentDevicePath Parent Device Path\r
429 @param RemainingDevicePath Remaining Device Path\r
430\r
431 @retval EFI_SUCCESS If a child handle was added\r
432 @retval other A child handle was not added\r
433\r
434**/\r
435EFI_STATUS\r
436FbGopChildHandleInstall (\r
437 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
438 IN EFI_HANDLE ParentHandle,\r
439 IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
440 IN VOID *ParentLegacyBios,\r
441 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
442 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
443 )\r
444{\r
445 EFI_STATUS Status;\r
446 FB_VIDEO_DEV *FbGopPrivate;\r
447 PCI_TYPE00 Pci;\r
448 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
9c228fb0
MM
449\r
450 //\r
451 // Allocate the private device structure for video device\r
452 //\r
453 FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (\r
454 sizeof (FB_VIDEO_DEV)\r
455 );\r
456 if (NULL == FbGopPrivate) {\r
457 Status = EFI_OUT_OF_RESOURCES;\r
458 goto Done;\r
459 }\r
460\r
461 //\r
462 // See if this is a VGA compatible controller or not\r
463 //\r
464 Status = ParentPciIo->Pci.Read (\r
465 ParentPciIo,\r
466 EfiPciIoWidthUint32,\r
467 0,\r
468 sizeof (Pci) / sizeof (UINT32),\r
469 &Pci\r
470 );\r
471 if (EFI_ERROR (Status)) {\r
472 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
473 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
474 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
475 ParentDevicePath\r
476 );\r
477 goto Done;\r
478 }\r
ae2fb9ea 479\r
9c228fb0
MM
480 //\r
481 // Initialize the child private structure\r
482 //\r
483 FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;\r
484\r
485 //\r
486 // Fill in Graphics Output specific mode structures\r
ae2fb9ea 487 //\r
9c228fb0 488 FbGopPrivate->ModeData = NULL;\r
ae2fb9ea 489\r
9c228fb0
MM
490 FbGopPrivate->VbeFrameBuffer = NULL;\r
491\r
492 FbGopPrivate->EdidDiscovered.SizeOfEdid = 0;\r
493 FbGopPrivate->EdidDiscovered.Edid = NULL;\r
494 FbGopPrivate->EdidActive.SizeOfEdid = 0;\r
495 FbGopPrivate->EdidActive.Edid = NULL;\r
ae2fb9ea 496\r
9c228fb0
MM
497 //\r
498 // Fill in the Graphics Output Protocol\r
499 //\r
500 FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;\r
501 FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode;\r
502\r
503\r
504 //\r
505 // Allocate buffer for Graphics Output Protocol mode information\r
506 //\r
507 FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
508 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
509 );\r
510 if (NULL == FbGopPrivate->GraphicsOutput.Mode) {\r
511 Status = EFI_OUT_OF_RESOURCES;\r
512 goto Done;\r
513 }\r
514\r
515 FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
516 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
517 );\r
518 if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) {\r
519 Status = EFI_OUT_OF_RESOURCES;\r
520 goto Done;\r
521 }\r
522\r
523 //\r
524 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
525 //\r
526 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
527 if (RemainingDevicePath == NULL) {\r
528 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
529 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
530 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
531 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
532 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
ae2fb9ea 533\r
9c228fb0
MM
534 FbGopPrivate->GopDevicePath = AppendDevicePathNode (\r
535 ParentDevicePath,\r
536 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
537 );\r
538 } else {\r
539 FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
540 }\r
ae2fb9ea 541\r
9c228fb0
MM
542 //\r
543 // Creat child handle and device path protocol firstly\r
544 //\r
545 FbGopPrivate->Handle = NULL;\r
546 Status = gBS->InstallMultipleProtocolInterfaces (\r
547 &FbGopPrivate->Handle,\r
548 &gEfiDevicePathProtocolGuid,\r
549 FbGopPrivate->GopDevicePath,\r
550 NULL\r
551 );\r
552 if (EFI_ERROR (Status)) {\r
553 goto Done;\r
554 }\r
555 }\r
ae2fb9ea 556\r
9c228fb0
MM
557 //\r
558 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
559 //\r
560 FbGopPrivate->PciIo = ParentPciIo;\r
561\r
562 //\r
563 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
564 //\r
565 Status = FbGopCheckForVbe (FbGopPrivate);\r
ae2fb9ea
MM
566 DEBUG ((DEBUG_INFO, "FbGopCheckForVbe - %r\n", Status));\r
567\r
9c228fb0
MM
568 if (EFI_ERROR (Status)) {\r
569 Status = EFI_UNSUPPORTED;\r
ae2fb9ea 570 //goto Done;\r
9c228fb0
MM
571 }\r
572\r
9c228fb0
MM
573 //\r
574 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
575 //\r
576 Status = gBS->InstallMultipleProtocolInterfaces (\r
577 &FbGopPrivate->Handle,\r
578 &gEfiGraphicsOutputProtocolGuid,\r
ae2fb9ea 579 &FbGopPrivate->GraphicsOutput,\r
9c228fb0 580 &gEfiEdidDiscoveredProtocolGuid,\r
ae2fb9ea 581 &FbGopPrivate->EdidDiscovered,\r
9c228fb0 582 &gEfiEdidActiveProtocolGuid,\r
ae2fb9ea 583 &FbGopPrivate->EdidActive,\r
9c228fb0
MM
584 NULL\r
585 );\r
586\r
587 if (!EFI_ERROR (Status)) {\r
588 //\r
589 // Open the Parent Handle for the child\r
590 //\r
591 Status = gBS->OpenProtocol (\r
592 ParentHandle,\r
593 &gEfiPciIoProtocolGuid,\r
594 (VOID **) &FbGopPrivate->PciIo,\r
595 This->DriverBindingHandle,\r
596 FbGopPrivate->Handle,\r
597 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
598 );\r
599 if (EFI_ERROR (Status)) {\r
600 goto Done;\r
601 }\r
9c228fb0 602 }\r
ae2fb9ea 603\r
9c228fb0
MM
604Done:\r
605 if (EFI_ERROR (Status)) {\r
606 //\r
607 // Free private data structure\r
608 //\r
609 FbGopDeviceReleaseResource (FbGopPrivate);\r
610 }\r
611\r
612 return Status;\r
613}\r
614\r
615\r
616/**\r
617 Deregister an video child handle and free resources.\r
618\r
619 @param This Protocol instance pointer.\r
620 @param Controller Video controller handle\r
621 @param Handle Video child handle\r
622\r
623 @return EFI_STATUS\r
624\r
625**/\r
626EFI_STATUS\r
627FbGopChildHandleUninstall (\r
628 EFI_DRIVER_BINDING_PROTOCOL *This,\r
629 EFI_HANDLE Controller,\r
630 EFI_HANDLE Handle\r
631 )\r
632{\r
633 EFI_STATUS Status;\r
ae2fb9ea 634 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
9c228fb0
MM
635 FB_VIDEO_DEV *FbGopPrivate;\r
636 EFI_PCI_IO_PROTOCOL *PciIo;\r
637\r
638 FbGopPrivate = NULL;\r
639 GraphicsOutput = NULL;\r
640 PciIo = NULL;\r
641 Status = EFI_UNSUPPORTED;\r
642\r
643 Status = gBS->OpenProtocol (\r
644 Handle,\r
645 &gEfiGraphicsOutputProtocolGuid,\r
646 (VOID **) &GraphicsOutput,\r
647 This->DriverBindingHandle,\r
648 Handle,\r
649 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
650 );\r
651 if (!EFI_ERROR (Status)) {\r
652 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
653 }\r
ae2fb9ea 654\r
9c228fb0
MM
655 if (FbGopPrivate == NULL) {\r
656 return EFI_UNSUPPORTED;\r
657 }\r
658\r
659 //\r
660 // Close PCI I/O protocol that opened by child handle\r
661 //\r
662 Status = gBS->CloseProtocol (\r
663 Controller,\r
664 &gEfiPciIoProtocolGuid,\r
665 This->DriverBindingHandle,\r
666 Handle\r
667 );\r
668\r
669 //\r
670 // Uninstall protocols on child handle\r
671 //\r
672 Status = gBS->UninstallMultipleProtocolInterfaces (\r
673 FbGopPrivate->Handle,\r
674 &gEfiDevicePathProtocolGuid,\r
675 FbGopPrivate->GopDevicePath,\r
676 &gEfiGraphicsOutputProtocolGuid,\r
677 &FbGopPrivate->GraphicsOutput,\r
678 NULL\r
679 );\r
ae2fb9ea 680\r
9c228fb0
MM
681 if (EFI_ERROR (Status)) {\r
682 gBS->OpenProtocol (\r
683 Controller,\r
684 &gEfiPciIoProtocolGuid,\r
685 (VOID **) &PciIo,\r
686 This->DriverBindingHandle,\r
687 Handle,\r
688 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
689 );\r
690 return Status;\r
691 }\r
ae2fb9ea 692\r
9c228fb0
MM
693 //\r
694 // Release all allocated resources\r
695 //\r
696 FbGopDeviceReleaseResource (FbGopPrivate);\r
697\r
698 return EFI_SUCCESS;\r
699}\r
700\r
701\r
702/**\r
68f87b25 703 Release resource for bios video instance.\r
9c228fb0
MM
704\r
705 @param FbGopPrivate Video child device private data structure\r
706\r
707**/\r
708VOID\r
709FbGopDeviceReleaseResource (\r
710 FB_VIDEO_DEV *FbGopPrivate\r
711 )\r
712{\r
713 if (FbGopPrivate == NULL) {\r
714 return ;\r
715 }\r
716\r
717 //\r
68f87b25 718 // Release all the resources occupied by the FB_VIDEO_DEV\r
9c228fb0 719 //\r
ae2fb9ea 720\r
9c228fb0
MM
721 //\r
722 // Free VBE Frame Buffer\r
723 //\r
724 if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
725 FreePool (FbGopPrivate->VbeFrameBuffer);\r
726 }\r
ae2fb9ea 727\r
9c228fb0
MM
728 //\r
729 // Free mode data\r
730 //\r
731 if (FbGopPrivate->ModeData != NULL) {\r
732 FreePool (FbGopPrivate->ModeData);\r
ae2fb9ea 733 }\r
9c228fb0
MM
734\r
735 //\r
736 // Free graphics output protocol occupied resource\r
737 //\r
738 if (FbGopPrivate->GraphicsOutput.Mode != NULL) {\r
739 if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {\r
740 FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);\r
741 FbGopPrivate->GraphicsOutput.Mode->Info = NULL;\r
742 }\r
743 FreePool (FbGopPrivate->GraphicsOutput.Mode);\r
744 FbGopPrivate->GraphicsOutput.Mode = NULL;\r
ae2fb9ea 745 }\r
9c228fb0
MM
746\r
747 if (FbGopPrivate->GopDevicePath!= NULL) {\r
748 FreePool (FbGopPrivate->GopDevicePath);\r
749 }\r
750\r
751 FreePool (FbGopPrivate);\r
752\r
753 return ;\r
754}\r
755\r
756\r
757\r
758/**\r
759 Check if all video child handles have been uninstalled.\r
760\r
761 @param Controller Video controller handle\r
762\r
763 @return TRUE Child handles exist.\r
764 @return FALSE All video child handles have been uninstalled.\r
765\r
766**/\r
767BOOLEAN\r
768HasChildHandle (\r
769 IN EFI_HANDLE Controller\r
770 )\r
771{\r
772 UINTN Index;\r
773 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
774 UINTN EntryCount;\r
775 BOOLEAN HasChild;\r
9c228fb0
MM
776\r
777 EntryCount = 0;\r
778 HasChild = FALSE;\r
ca469b47
LE
779 gBS->OpenProtocolInformation (\r
780 Controller,\r
781 &gEfiPciIoProtocolGuid,\r
782 &OpenInfoBuffer,\r
783 &EntryCount\r
784 );\r
9c228fb0
MM
785 for (Index = 0; Index < EntryCount; Index++) {\r
786 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
787 HasChild = TRUE;\r
788 }\r
789 }\r
ae2fb9ea 790\r
9c228fb0
MM
791 return HasChild;\r
792}\r
793\r
794/**\r
795 Check for VBE device.\r
796\r
797 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure\r
798\r
799 @retval EFI_SUCCESS VBE device found\r
800\r
801**/\r
802EFI_STATUS\r
803FbGopCheckForVbe (\r
804 IN OUT FB_VIDEO_DEV *FbGopPrivate\r
805 )\r
806{\r
ae2fb9ea 807 EFI_STATUS Status;\r
9c228fb0 808 FB_VIDEO_MODE_DATA *ModeBuffer;\r
ae2fb9ea
MM
809 FB_VIDEO_MODE_DATA *CurrentModeData;\r
810 UINTN ModeNumber;\r
811 UINTN BitsPerPixel;\r
9c228fb0
MM
812 UINTN BytesPerScanLine;\r
813 UINT32 HorizontalResolution;\r
814 UINT32 VerticalResolution;\r
ae2fb9ea
MM
815 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
816 FRAME_BUFFER_INFO *FbInfo;\r
817\r
9c228fb0 818 Status = EFI_SUCCESS;\r
ae2fb9ea
MM
819\r
820 FbInfo = mFrameBufferInfo;\r
821\r
9c228fb0
MM
822 //\r
823 // Add mode to the list of available modes\r
824 //\r
825 VbeFrameBuffer = NULL;\r
826 ModeBuffer = NULL;\r
ae2fb9ea
MM
827\r
828 ModeNumber = 1;\r
829 BitsPerPixel = FbInfo->BitsPerPixel;\r
830 HorizontalResolution = FbInfo->HorizontalResolution;\r
831 VerticalResolution = FbInfo->VerticalResolution;\r
832 BytesPerScanLine = FbInfo->BytesPerScanLine;\r
833\r
9c228fb0
MM
834 ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (\r
835 ModeNumber * sizeof (FB_VIDEO_MODE_DATA)\r
836 );\r
837 if (NULL == ModeBuffer) {\r
838 Status = EFI_OUT_OF_RESOURCES;\r
839 goto Done;\r
840 }\r
841\r
842 VbeFrameBuffer =\r
843 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
844 BytesPerScanLine * VerticalResolution\r
845 );\r
846 if (NULL == VbeFrameBuffer) {\r
847 Status = EFI_OUT_OF_RESOURCES;\r
848 goto Done;\r
849 }\r
ae2fb9ea 850\r
9c228fb0
MM
851 if (FbGopPrivate->ModeData != NULL) {\r
852 FreePool (FbGopPrivate->ModeData);\r
853 }\r
ae2fb9ea 854\r
9c228fb0
MM
855 if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
856 FreePool (FbGopPrivate->VbeFrameBuffer);\r
ae2fb9ea
MM
857 }\r
858\r
9c228fb0
MM
859 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
860 CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;\r
ae2fb9ea
MM
861\r
862 CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Red);\r
863 CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Blue);\r
864 CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Green);\r
865 CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(FbInfo->Reserved);\r
866\r
9c228fb0
MM
867 CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel;\r
868 CurrentModeData->HorizontalResolution = HorizontalResolution;\r
ae2fb9ea
MM
869 CurrentModeData->VerticalResolution = VerticalResolution;\r
870 CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;\r
871 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) FbInfo->LinearFrameBuffer;\r
9c228fb0
MM
872 CurrentModeData->VbeModeNumber = 0;\r
873 CurrentModeData->ColorDepth = 32;\r
874 CurrentModeData->RefreshRate = 60;\r
ae2fb9ea 875\r
9c228fb0
MM
876 CurrentModeData->PixelFormat = PixelBitMask;\r
877 if ((CurrentModeData->BitsPerPixel == 32) &&\r
878 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
879 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
880 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
881 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
882 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
883 }\r
ae2fb9ea
MM
884 }\r
885\r
886 CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));\r
887\r
9c228fb0
MM
888 FbGopPrivate->ModeData = ModeBuffer;\r
889 FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;\r
ae2fb9ea 890\r
9c228fb0
MM
891 //\r
892 // Assign Gop's Blt function\r
893 //\r
894 FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt;\r
ae2fb9ea 895\r
9c228fb0 896 FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
ae2fb9ea 897 FbGopPrivate->GraphicsOutput.Mode->Mode = 0;\r
9c228fb0
MM
898 FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
899 FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;\r
ae2fb9ea 900 FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution;\r
9c228fb0 901 FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;\r
ae2fb9ea 902 CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));\r
c0d9813c 903 FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = (UINT32)(BytesPerScanLine * 8 / BitsPerPixel);\r
9c228fb0
MM
904 FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
905 FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;\r
906 FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize;\r
ae2fb9ea 907\r
9c228fb0
MM
908 //\r
909 // Find the best mode to initialize\r
ae2fb9ea 910 //\r
9c228fb0
MM
911\r
912Done:\r
913 //\r
914 // If there was an error, then free the mode structure\r
915 //\r
916 if (EFI_ERROR (Status)) {\r
ae2fb9ea 917\r
9c228fb0
MM
918 if (VbeFrameBuffer != NULL) {\r
919 FreePool (VbeFrameBuffer);\r
ae2fb9ea
MM
920 }\r
921\r
9c228fb0
MM
922 if (ModeBuffer != NULL) {\r
923 FreePool (ModeBuffer);\r
ae2fb9ea 924 }\r
9c228fb0
MM
925 }\r
926\r
927 return Status;\r
928}\r
929\r
930\r
931//\r
932// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
933//\r
934\r
935/**\r
936 Graphics Output protocol interface to get video mode.\r
937\r
938 @param This Protocol instance pointer.\r
939 @param ModeNumber The mode number to return information on.\r
940 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
941 buffer.\r
942 @param Info Caller allocated buffer that returns information\r
943 about ModeNumber.\r
944\r
945 @retval EFI_SUCCESS Mode information returned.\r
946 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
947 video mode.\r
948 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
949 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
950\r
951**/\r
952EFI_STATUS\r
953EFIAPI\r
954FbGopGraphicsOutputQueryMode (\r
955 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
956 IN UINT32 ModeNumber,\r
957 OUT UINTN *SizeOfInfo,\r
958 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
959 )\r
960{\r
961 FB_VIDEO_DEV *FbGopPrivate;\r
962 FB_VIDEO_MODE_DATA *ModeData;\r
963\r
964 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
965\r
966 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
967 return EFI_INVALID_PARAMETER;\r
968 }\r
969\r
970 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
971 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
972 );\r
973 if (NULL == *Info) {\r
974 return EFI_OUT_OF_RESOURCES;\r
975 }\r
976\r
977 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
978\r
979 ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
980 (*Info)->Version = 0;\r
981 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
982 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
983 (*Info)->PixelFormat = ModeData->PixelFormat;\r
984 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
985\r
986 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
987\r
988 return EFI_SUCCESS;\r
989}\r
990\r
991/**\r
992 Graphics Output protocol interface to set video mode.\r
993\r
994 @param This Protocol instance pointer.\r
995 @param ModeNumber The mode number to be set.\r
996\r
997 @retval EFI_SUCCESS Graphics mode was changed.\r
998 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
999 request.\r
1000 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
1001\r
1002**/\r
1003EFI_STATUS\r
1004EFIAPI\r
1005FbGopGraphicsOutputSetMode (\r
1006 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1007 IN UINT32 ModeNumber\r
1008 )\r
ae2fb9ea 1009{\r
9c228fb0
MM
1010 FB_VIDEO_DEV *FbGopPrivate;\r
1011 FB_VIDEO_MODE_DATA *ModeData;\r
1012 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1013\r
1014 if (This == NULL) {\r
1015 return EFI_INVALID_PARAMETER;\r
1016 }\r
1017\r
1018 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1019\r
1020 ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
1021\r
1022 if (ModeNumber >= This->Mode->MaxMode) {\r
1023 return EFI_UNSUPPORTED;\r
1024 }\r
ae2fb9ea 1025\r
9c228fb0
MM
1026 if (ModeNumber == This->Mode->Mode) {\r
1027 //\r
1028 // Clear screen to black\r
ae2fb9ea 1029 //\r
9c228fb0
MM
1030 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1031 FbGopGraphicsOutputVbeBlt (\r
1032 This,\r
1033 &Background,\r
1034 EfiBltVideoFill,\r
1035 0,\r
1036 0,\r
1037 0,\r
1038 0,\r
1039 ModeData->HorizontalResolution,\r
1040 ModeData->VerticalResolution,\r
1041 0\r
1042 );\r
1043 return EFI_SUCCESS;\r
1044 } else {\r
1045 return EFI_UNSUPPORTED;\r
1046 }\r
ae2fb9ea 1047\r
9c228fb0
MM
1048}\r
1049\r
1050/**\r
1051 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1052\r
1053 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
1054 @param VbeBuffer The data to transfer to screen\r
1055 @param MemAddress Physical frame buffer base address\r
1056 @param DestinationX The X coordinate of the destination for BltOperation\r
1057 @param DestinationY The Y coordinate of the destination for BltOperation\r
1058 @param TotalBytes The total bytes of copy\r
1059 @param VbePixelWidth Bytes per pixel\r
1060 @param BytesPerScanLine Bytes per scan line\r
1061\r
1062**/\r
1063VOID\r
1064CopyVideoBuffer (\r
1065 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1066 IN UINT8 *VbeBuffer,\r
1067 IN VOID *MemAddress,\r
1068 IN UINTN DestinationX,\r
1069 IN UINTN DestinationY,\r
1070 IN UINTN TotalBytes,\r
1071 IN UINT32 VbePixelWidth,\r
1072 IN UINTN BytesPerScanLine\r
1073 )\r
1074{\r
1075 UINTN FrameBufferAddr;\r
1076 UINTN CopyBlockNum;\r
1077 UINTN RemainingBytes;\r
1078 UINTN UnalignedBytes;\r
1079 EFI_STATUS Status;\r
1080\r
1081 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
1082\r
1083 //\r
1084 // If TotalBytes is less than 4 bytes, only start byte copy.\r
1085 //\r
1086 if (TotalBytes < 4) {\r
1087 Status = PciIo->Mem.Write (\r
1088 PciIo,\r
1089 EfiPciIoWidthUint8,\r
1090 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1091 (UINT64) FrameBufferAddr,\r
1092 TotalBytes,\r
1093 VbeBuffer\r
1094 );\r
1095 ASSERT_EFI_ERROR (Status);\r
1096 return;\r
1097 }\r
1098\r
1099 //\r
1100 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
1101 //\r
1102 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
1103\r
1104 if (UnalignedBytes != 0) {\r
1105 Status = PciIo->Mem.Write (\r
1106 PciIo,\r
1107 EfiPciIoWidthUint8,\r
1108 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1109 (UINT64) FrameBufferAddr,\r
1110 UnalignedBytes,\r
1111 VbeBuffer\r
1112 );\r
1113 ASSERT_EFI_ERROR (Status);\r
1114 FrameBufferAddr += UnalignedBytes;\r
1115 VbeBuffer += UnalignedBytes;\r
1116 }\r
1117\r
1118 //\r
1119 // Calculate 4-byte block count and remaining bytes.\r
1120 //\r
1121 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
1122 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
1123\r
1124 //\r
1125 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
1126 //\r
1127 if (CopyBlockNum != 0) {\r
1128 Status = PciIo->Mem.Write (\r
1129 PciIo,\r
1130 EfiPciIoWidthUint32,\r
1131 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1132 (UINT64) FrameBufferAddr,\r
1133 CopyBlockNum,\r
1134 VbeBuffer\r
1135 );\r
1136 ASSERT_EFI_ERROR (Status);\r
1137 }\r
1138\r
1139 if (RemainingBytes != 0) {\r
1140 FrameBufferAddr += (CopyBlockNum << 2);\r
1141 VbeBuffer += (CopyBlockNum << 2);\r
1142 Status = PciIo->Mem.Write (\r
1143 PciIo,\r
1144 EfiPciIoWidthUint8,\r
1145 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1146 (UINT64) FrameBufferAddr,\r
1147 RemainingBytes,\r
1148 VbeBuffer\r
1149 );\r
1150 ASSERT_EFI_ERROR (Status);\r
1151 }\r
1152}\r
1153\r
1154/**\r
1155 Worker function to block transfer for VBE device.\r
1156\r
1157 @param FbGopPrivate Instance of FB_VIDEO_DEV\r
1158 @param BltBuffer The data to transfer to screen\r
1159 @param BltOperation The operation to perform\r
1160 @param SourceX The X coordinate of the source for BltOperation\r
1161 @param SourceY The Y coordinate of the source for BltOperation\r
1162 @param DestinationX The X coordinate of the destination for\r
1163 BltOperation\r
1164 @param DestinationY The Y coordinate of the destination for\r
1165 BltOperation\r
1166 @param Width The width of a rectangle in the blt rectangle in\r
1167 pixels\r
1168 @param Height The height of a rectangle in the blt rectangle in\r
1169 pixels\r
1170 @param Delta Not used for EfiBltVideoFill and\r
1171 EfiBltVideoToVideo operation. If a Delta of 0 is\r
1172 used, the entire BltBuffer will be operated on. If\r
1173 a subrectangle of the BltBuffer is used, then\r
1174 Delta represents the number of bytes in a row of\r
1175 the BltBuffer.\r
1176 @param Mode Mode data.\r
1177\r
1178 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
1179 @retval EFI_SUCCESS Blt operation success\r
1180\r
1181**/\r
1182EFI_STATUS\r
1183FbGopVbeBltWorker (\r
1184 IN FB_VIDEO_DEV *FbGopPrivate,\r
1185 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1186 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1187 IN UINTN SourceX,\r
1188 IN UINTN SourceY,\r
1189 IN UINTN DestinationX,\r
1190 IN UINTN DestinationY,\r
1191 IN UINTN Width,\r
1192 IN UINTN Height,\r
1193 IN UINTN Delta,\r
1194 IN FB_VIDEO_MODE_DATA *Mode\r
1195 )\r
1196{\r
1197 EFI_PCI_IO_PROTOCOL *PciIo;\r
1198 EFI_TPL OriginalTPL;\r
1199 UINTN DstY;\r
1200 UINTN SrcY;\r
1201 UINTN DstX;\r
1202 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
1203 VOID *MemAddress;\r
1204 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
1205 UINTN BytesPerScanLine;\r
1206 UINTN Index;\r
1207 UINT8 *VbeBuffer;\r
1208 UINT8 *VbeBuffer1;\r
1209 UINT8 *BltUint8;\r
1210 UINT32 VbePixelWidth;\r
1211 UINT32 Pixel;\r
1212 UINTN TotalBytes;\r
1213\r
1214 PciIo = FbGopPrivate->PciIo;\r
1215\r
1216 VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer;\r
1217 MemAddress = Mode->LinearFrameBuffer;\r
1218 BytesPerScanLine = Mode->BytesPerScanLine;\r
1219 VbePixelWidth = Mode->BitsPerPixel / 8;\r
1220 BltUint8 = (UINT8 *) BltBuffer;\r
1221 TotalBytes = Width * VbePixelWidth;\r
1222\r
1223 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
1224 return EFI_INVALID_PARAMETER;\r
1225 }\r
1226\r
1227 if (Width == 0 || Height == 0) {\r
1228 return EFI_INVALID_PARAMETER;\r
1229 }\r
1230 //\r
1231 // We need to fill the Virtual Screen buffer with the blt data.\r
68f87b25 1232 // The virtual screen is upside down, as the first row is the bottom row of\r
9c228fb0
MM
1233 // the image.\r
1234 //\r
1235 if (BltOperation == EfiBltVideoToBltBuffer) {\r
1236 //\r
1237 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
1238 //\r
1239 if (SourceY + Height > Mode->VerticalResolution) {\r
1240 return EFI_INVALID_PARAMETER;\r
1241 }\r
1242\r
1243 if (SourceX + Width > Mode->HorizontalResolution) {\r
1244 return EFI_INVALID_PARAMETER;\r
1245 }\r
1246 } else {\r
1247 //\r
1248 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
1249 //\r
1250 if (DestinationY + Height > Mode->VerticalResolution) {\r
1251 return EFI_INVALID_PARAMETER;\r
1252 }\r
1253\r
1254 if (DestinationX + Width > Mode->HorizontalResolution) {\r
1255 return EFI_INVALID_PARAMETER;\r
1256 }\r
1257 }\r
1258 //\r
1259 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
1260 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
1261 // the number of bytes in each row can be computed.\r
1262 //\r
1263 if (Delta == 0) {\r
1264 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
1265 }\r
1266 //\r
1267 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
1268 // We would not want a timer based event (Cursor, ...) to come in while we are\r
1269 // doing this operation.\r
1270 //\r
1271 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
1272\r
1273 switch (BltOperation) {\r
1274 case EfiBltVideoToBltBuffer:\r
1275 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
1276 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1277 //\r
1278 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
1279 //\r
1280 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
1281 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
1282 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
1283 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
1284 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
1285 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
1286 Blt->Reserved = 0;\r
1287 Blt++;\r
1288 VbeBuffer += VbePixelWidth;\r
1289 }\r
1290\r
1291 }\r
1292 break;\r
1293\r
1294 case EfiBltVideoToVideo:\r
1295 for (Index = 0; Index < Height; Index++) {\r
1296 if (DestinationY <= SourceY) {\r
1297 SrcY = SourceY + Index;\r
1298 DstY = DestinationY + Index;\r
1299 } else {\r
1300 SrcY = SourceY + Height - Index - 1;\r
1301 DstY = DestinationY + Height - Index - 1;\r
1302 }\r
1303\r
1304 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
1305 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
1306\r
1307 gBS->CopyMem (\r
1308 VbeBuffer,\r
1309 VbeBuffer1,\r
1310 TotalBytes\r
1311 );\r
1312\r
1313 //\r
1314 // Update physical frame buffer.\r
1315 //\r
1316 CopyVideoBuffer (\r
1317 PciIo,\r
1318 VbeBuffer,\r
1319 MemAddress,\r
1320 DestinationX,\r
1321 DstY,\r
1322 TotalBytes,\r
1323 VbePixelWidth,\r
1324 BytesPerScanLine\r
1325 );\r
1326 }\r
1327 break;\r
1328\r
1329 case EfiBltVideoFill:\r
1330 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
1331 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
1332 //\r
1333 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
1334 //\r
1335 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
1336 (\r
1337 (Blt->Green & Mode->Green.Mask) <<\r
1338 Mode->Green.Position\r
1339 ) |\r
1340 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
1341\r
1342 for (Index = 0; Index < Width; Index++) {\r
1343 gBS->CopyMem (\r
1344 VbeBuffer,\r
1345 &Pixel,\r
1346 VbePixelWidth\r
1347 );\r
1348 VbeBuffer += VbePixelWidth;\r
1349 }\r
1350\r
1351 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
1352 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
1353 gBS->CopyMem (\r
1354 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
1355 VbeBuffer,\r
1356 TotalBytes\r
1357 );\r
1358 }\r
1359\r
1360 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
1361 //\r
1362 // Update physical frame buffer.\r
1363 //\r
1364 CopyVideoBuffer (\r
1365 PciIo,\r
1366 VbeBuffer,\r
1367 MemAddress,\r
1368 DestinationX,\r
1369 DstY,\r
1370 TotalBytes,\r
1371 VbePixelWidth,\r
1372 BytesPerScanLine\r
1373 );\r
1374 }\r
1375 break;\r
1376\r
1377 case EfiBltBufferToVideo:\r
1378 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
1379 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1380 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
1381 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
1382 //\r
1383 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
1384 //\r
1385 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
1386 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
1387 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
1388 gBS->CopyMem (\r
1389 VbeBuffer,\r
1390 &Pixel,\r
1391 VbePixelWidth\r
1392 );\r
1393 Blt++;\r
1394 VbeBuffer += VbePixelWidth;\r
1395 }\r
1396\r
1397 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
1398\r
1399 //\r
1400 // Update physical frame buffer.\r
1401 //\r
1402 CopyVideoBuffer (\r
1403 PciIo,\r
1404 VbeBuffer,\r
1405 MemAddress,\r
1406 DestinationX,\r
1407 DstY,\r
1408 TotalBytes,\r
1409 VbePixelWidth,\r
1410 BytesPerScanLine\r
1411 );\r
1412 }\r
1413 break;\r
1414\r
1415 default: ;\r
1416 }\r
1417\r
1418 gBS->RestoreTPL (OriginalTPL);\r
1419\r
1420 return EFI_SUCCESS;\r
1421}\r
1422\r
1423/**\r
1424 Graphics Output protocol instance to block transfer for VBE device.\r
1425\r
1426 @param This Pointer to Graphics Output protocol instance\r
1427 @param BltBuffer The data to transfer to screen\r
1428 @param BltOperation The operation to perform\r
1429 @param SourceX The X coordinate of the source for BltOperation\r
1430 @param SourceY The Y coordinate of the source for BltOperation\r
1431 @param DestinationX The X coordinate of the destination for\r
1432 BltOperation\r
1433 @param DestinationY The Y coordinate of the destination for\r
1434 BltOperation\r
1435 @param Width The width of a rectangle in the blt rectangle in\r
1436 pixels\r
1437 @param Height The height of a rectangle in the blt rectangle in\r
1438 pixels\r
1439 @param Delta Not used for EfiBltVideoFill and\r
1440 EfiBltVideoToVideo operation. If a Delta of 0 is\r
1441 used, the entire BltBuffer will be operated on. If\r
1442 a subrectangle of the BltBuffer is used, then\r
1443 Delta represents the number of bytes in a row of\r
1444 the BltBuffer.\r
1445\r
1446 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
1447 @retval EFI_SUCCESS Blt operation success\r
1448\r
1449**/\r
1450EFI_STATUS\r
1451EFIAPI\r
1452FbGopGraphicsOutputVbeBlt (\r
1453 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1454 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1455 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1456 IN UINTN SourceX,\r
1457 IN UINTN SourceY,\r
1458 IN UINTN DestinationX,\r
1459 IN UINTN DestinationY,\r
1460 IN UINTN Width,\r
1461 IN UINTN Height,\r
1462 IN UINTN Delta\r
1463 )\r
1464{\r
1465 FB_VIDEO_DEV *FbGopPrivate;\r
1466 FB_VIDEO_MODE_DATA *Mode;\r
1467\r
1468 if (This == NULL) {\r
1469 return EFI_INVALID_PARAMETER;\r
1470 }\r
1471\r
1472 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1473 Mode = &FbGopPrivate->ModeData[This->Mode->Mode];\r
1474\r
1475 return FbGopVbeBltWorker (\r
1476 FbGopPrivate,\r
1477 BltBuffer,\r
1478 BltOperation,\r
1479 SourceX,\r
1480 SourceY,\r
1481 DestinationX,\r
1482 DestinationY,\r
1483 Width,\r
1484 Height,\r
1485 Delta,\r
1486 Mode\r
1487 );\r
1488}\r
1489\r
1490\r
1491/**\r
1492 The user Entry Point for module UefiFbGop. The user code starts with this function.\r
1493\r
1494 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1495 @param[in] SystemTable A pointer to the EFI System Table.\r
1496\r
1497 @retval EFI_SUCCESS The entry point is executed successfully.\r
1498 @retval other Some error occurs when executing this entry point.\r
1499\r
1500**/\r
1501EFI_STATUS\r
1502EFIAPI\r
1503FbGopEntryPoint(\r
1504 IN EFI_HANDLE ImageHandle,\r
1505 IN EFI_SYSTEM_TABLE *SystemTable\r
1506 )\r
1507{\r
1508 EFI_STATUS Status;\r
1509 EFI_HOB_GUID_TYPE *GuidHob;\r
ae2fb9ea 1510\r
9c228fb0
MM
1511 //\r
1512 // Find the frame buffer information guid hob\r
1513 //\r
1514 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);\r
ae2fb9ea
MM
1515 if (GuidHob != NULL) {\r
1516 mFrameBufferInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);\r
1517\r
9c228fb0
MM
1518 //\r
1519 // Install driver model protocol(s).\r
1520 //\r
1521 Status = EfiLibInstallDriverBindingComponentName2 (\r
1522 ImageHandle,\r
1523 SystemTable,\r
1524 &gFbGopDriverBinding,\r
1525 ImageHandle,\r
1526 &gFbGopComponentName,\r
1527 &gFbGopComponentName2\r
1528 );\r
1529 ASSERT_EFI_ERROR (Status);\r
1530 } else {\r
ae2fb9ea 1531 DEBUG ((DEBUG_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));\r
9c228fb0
MM
1532 Status = EFI_ABORTED;\r
1533 }\r
ae2fb9ea 1534 return Status;\r
9c228fb0
MM
1535}\r
1536\r