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