]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootPayloadPkg/FbGop/FbGop.c
CorebootPayloadPkg/FbGop: Produces correct PixelsPerScanLine
[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
9c228fb0
MM
437\r
438 //\r
439 // Allocate the private device structure for video device\r
440 //\r
441 FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (\r
442 sizeof (FB_VIDEO_DEV)\r
443 );\r
444 if (NULL == FbGopPrivate) {\r
445 Status = EFI_OUT_OF_RESOURCES;\r
446 goto Done;\r
447 }\r
448\r
449 //\r
450 // See if this is a VGA compatible controller or not\r
451 //\r
452 Status = ParentPciIo->Pci.Read (\r
453 ParentPciIo,\r
454 EfiPciIoWidthUint32,\r
455 0,\r
456 sizeof (Pci) / sizeof (UINT32),\r
457 &Pci\r
458 );\r
459 if (EFI_ERROR (Status)) {\r
460 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
461 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
462 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
463 ParentDevicePath\r
464 );\r
465 goto Done;\r
466 }\r
467 \r
468 //\r
469 // Initialize the child private structure\r
470 //\r
471 FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;\r
472\r
473 //\r
474 // Fill in Graphics Output specific mode structures\r
475 // \r
476 FbGopPrivate->ModeData = NULL;\r
477 \r
478 FbGopPrivate->VbeFrameBuffer = NULL;\r
479\r
480 FbGopPrivate->EdidDiscovered.SizeOfEdid = 0;\r
481 FbGopPrivate->EdidDiscovered.Edid = NULL;\r
482 FbGopPrivate->EdidActive.SizeOfEdid = 0;\r
483 FbGopPrivate->EdidActive.Edid = NULL;\r
484 \r
485 //\r
486 // Fill in the Graphics Output Protocol\r
487 //\r
488 FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;\r
489 FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode;\r
490\r
491\r
492 //\r
493 // Allocate buffer for Graphics Output Protocol mode information\r
494 //\r
495 FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
496 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
497 );\r
498 if (NULL == FbGopPrivate->GraphicsOutput.Mode) {\r
499 Status = EFI_OUT_OF_RESOURCES;\r
500 goto Done;\r
501 }\r
502\r
503 FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
504 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
505 );\r
506 if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) {\r
507 Status = EFI_OUT_OF_RESOURCES;\r
508 goto Done;\r
509 }\r
510\r
511 //\r
512 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
513 //\r
514 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
515 if (RemainingDevicePath == NULL) {\r
516 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
517 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
518 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
519 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
520 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
521 \r
522 FbGopPrivate->GopDevicePath = AppendDevicePathNode (\r
523 ParentDevicePath,\r
524 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
525 );\r
526 } else {\r
527 FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
528 }\r
529 \r
530 //\r
531 // Creat child handle and device path protocol firstly\r
532 //\r
533 FbGopPrivate->Handle = NULL;\r
534 Status = gBS->InstallMultipleProtocolInterfaces (\r
535 &FbGopPrivate->Handle,\r
536 &gEfiDevicePathProtocolGuid,\r
537 FbGopPrivate->GopDevicePath,\r
538 NULL\r
539 );\r
540 if (EFI_ERROR (Status)) {\r
541 goto Done;\r
542 }\r
543 }\r
544 \r
545 //\r
546 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
547 //\r
548 FbGopPrivate->PciIo = ParentPciIo;\r
549\r
550 //\r
551 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
552 //\r
553 Status = FbGopCheckForVbe (FbGopPrivate);\r
554 DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status));\r
555 \r
556 if (EFI_ERROR (Status)) {\r
557 Status = EFI_UNSUPPORTED;\r
558 //goto Done; \r
559 }\r
560\r
9c228fb0
MM
561 //\r
562 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
563 //\r
564 Status = gBS->InstallMultipleProtocolInterfaces (\r
565 &FbGopPrivate->Handle,\r
566 &gEfiGraphicsOutputProtocolGuid,\r
567 &FbGopPrivate->GraphicsOutput, \r
568 &gEfiEdidDiscoveredProtocolGuid,\r
569 &FbGopPrivate->EdidDiscovered, \r
570 &gEfiEdidActiveProtocolGuid,\r
571 &FbGopPrivate->EdidActive, \r
572 NULL\r
573 );\r
574\r
575 if (!EFI_ERROR (Status)) {\r
576 //\r
577 // Open the Parent Handle for the child\r
578 //\r
579 Status = gBS->OpenProtocol (\r
580 ParentHandle,\r
581 &gEfiPciIoProtocolGuid,\r
582 (VOID **) &FbGopPrivate->PciIo,\r
583 This->DriverBindingHandle,\r
584 FbGopPrivate->Handle,\r
585 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
586 );\r
587 if (EFI_ERROR (Status)) {\r
588 goto Done;\r
589 }\r
9c228fb0
MM
590 }\r
591 \r
592Done:\r
593 if (EFI_ERROR (Status)) {\r
594 //\r
595 // Free private data structure\r
596 //\r
597 FbGopDeviceReleaseResource (FbGopPrivate);\r
598 }\r
599\r
600 return Status;\r
601}\r
602\r
603\r
604/**\r
605 Deregister an video child handle and free resources.\r
606\r
607 @param This Protocol instance pointer.\r
608 @param Controller Video controller handle\r
609 @param Handle Video child handle\r
610\r
611 @return EFI_STATUS\r
612\r
613**/\r
614EFI_STATUS\r
615FbGopChildHandleUninstall (\r
616 EFI_DRIVER_BINDING_PROTOCOL *This,\r
617 EFI_HANDLE Controller,\r
618 EFI_HANDLE Handle\r
619 )\r
620{\r
621 EFI_STATUS Status;\r
622 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; \r
623 FB_VIDEO_DEV *FbGopPrivate;\r
624 EFI_PCI_IO_PROTOCOL *PciIo;\r
625\r
626 FbGopPrivate = NULL;\r
627 GraphicsOutput = NULL;\r
628 PciIo = NULL;\r
629 Status = EFI_UNSUPPORTED;\r
630\r
631 Status = gBS->OpenProtocol (\r
632 Handle,\r
633 &gEfiGraphicsOutputProtocolGuid,\r
634 (VOID **) &GraphicsOutput,\r
635 This->DriverBindingHandle,\r
636 Handle,\r
637 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
638 );\r
639 if (!EFI_ERROR (Status)) {\r
640 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
641 }\r
642 \r
643 if (FbGopPrivate == NULL) {\r
644 return EFI_UNSUPPORTED;\r
645 }\r
646\r
647 //\r
648 // Close PCI I/O protocol that opened by child handle\r
649 //\r
650 Status = gBS->CloseProtocol (\r
651 Controller,\r
652 &gEfiPciIoProtocolGuid,\r
653 This->DriverBindingHandle,\r
654 Handle\r
655 );\r
656\r
657 //\r
658 // Uninstall protocols on child handle\r
659 //\r
660 Status = gBS->UninstallMultipleProtocolInterfaces (\r
661 FbGopPrivate->Handle,\r
662 &gEfiDevicePathProtocolGuid,\r
663 FbGopPrivate->GopDevicePath,\r
664 &gEfiGraphicsOutputProtocolGuid,\r
665 &FbGopPrivate->GraphicsOutput,\r
666 NULL\r
667 );\r
668 \r
669 if (EFI_ERROR (Status)) {\r
670 gBS->OpenProtocol (\r
671 Controller,\r
672 &gEfiPciIoProtocolGuid,\r
673 (VOID **) &PciIo,\r
674 This->DriverBindingHandle,\r
675 Handle,\r
676 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
677 );\r
678 return Status;\r
679 }\r
680 \r
681 //\r
682 // Release all allocated resources\r
683 //\r
684 FbGopDeviceReleaseResource (FbGopPrivate);\r
685\r
686 return EFI_SUCCESS;\r
687}\r
688\r
689\r
690/**\r
691 Release resource for biso video instance.\r
692\r
693 @param FbGopPrivate Video child device private data structure\r
694\r
695**/\r
696VOID\r
697FbGopDeviceReleaseResource (\r
698 FB_VIDEO_DEV *FbGopPrivate\r
699 )\r
700{\r
701 if (FbGopPrivate == NULL) {\r
702 return ;\r
703 }\r
704\r
705 //\r
706 // Release all the resourses occupied by the FB_VIDEO_DEV\r
707 //\r
708 \r
709 //\r
710 // Free VBE Frame Buffer\r
711 //\r
712 if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
713 FreePool (FbGopPrivate->VbeFrameBuffer);\r
714 }\r
715 \r
716 //\r
717 // Free mode data\r
718 //\r
719 if (FbGopPrivate->ModeData != NULL) {\r
720 FreePool (FbGopPrivate->ModeData);\r
721 } \r
722\r
723 //\r
724 // Free graphics output protocol occupied resource\r
725 //\r
726 if (FbGopPrivate->GraphicsOutput.Mode != NULL) {\r
727 if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {\r
728 FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);\r
729 FbGopPrivate->GraphicsOutput.Mode->Info = NULL;\r
730 }\r
731 FreePool (FbGopPrivate->GraphicsOutput.Mode);\r
732 FbGopPrivate->GraphicsOutput.Mode = NULL;\r
733 } \r
734\r
735 if (FbGopPrivate->GopDevicePath!= NULL) {\r
736 FreePool (FbGopPrivate->GopDevicePath);\r
737 }\r
738\r
739 FreePool (FbGopPrivate);\r
740\r
741 return ;\r
742}\r
743\r
744\r
745\r
746/**\r
747 Check if all video child handles have been uninstalled.\r
748\r
749 @param Controller Video controller handle\r
750\r
751 @return TRUE Child handles exist.\r
752 @return FALSE All video child handles have been uninstalled.\r
753\r
754**/\r
755BOOLEAN\r
756HasChildHandle (\r
757 IN EFI_HANDLE Controller\r
758 )\r
759{\r
760 UINTN Index;\r
761 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
762 UINTN EntryCount;\r
763 BOOLEAN HasChild;\r
9c228fb0
MM
764\r
765 EntryCount = 0;\r
766 HasChild = FALSE;\r
ca469b47
LE
767 gBS->OpenProtocolInformation (\r
768 Controller,\r
769 &gEfiPciIoProtocolGuid,\r
770 &OpenInfoBuffer,\r
771 &EntryCount\r
772 );\r
9c228fb0
MM
773 for (Index = 0; Index < EntryCount; Index++) {\r
774 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
775 HasChild = TRUE;\r
776 }\r
777 }\r
778 \r
779 return HasChild;\r
780}\r
781\r
782/**\r
783 Check for VBE device.\r
784\r
785 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure\r
786\r
787 @retval EFI_SUCCESS VBE device found\r
788\r
789**/\r
790EFI_STATUS\r
791FbGopCheckForVbe (\r
792 IN OUT FB_VIDEO_DEV *FbGopPrivate\r
793 )\r
794{\r
795 EFI_STATUS Status; \r
796 FB_VIDEO_MODE_DATA *ModeBuffer;\r
797 FB_VIDEO_MODE_DATA *CurrentModeData; \r
798 UINTN ModeNumber; \r
799 UINTN BitsPerPixel; \r
800 UINTN BytesPerScanLine;\r
801 UINT32 HorizontalResolution;\r
802 UINT32 VerticalResolution;\r
803 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; \r
804 EFI_HOB_GUID_TYPE *GuidHob;\r
805 FRAME_BUFFER_INFO *pFbInfo;\r
806 \r
807 Status = EFI_SUCCESS;\r
808 //\r
809 // Find the frame buffer information guid hob\r
810 //\r
811 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);\r
812 ASSERT (GuidHob != NULL);\r
813 pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);\r
814 \r
815 //\r
816 // Add mode to the list of available modes\r
817 //\r
818 VbeFrameBuffer = NULL;\r
819 ModeBuffer = NULL;\r
820 \r
821 ModeNumber = 1; \r
822 BitsPerPixel = pFbInfo->BitsPerPixel;\r
823 HorizontalResolution = pFbInfo->HorizontalResolution;\r
824 VerticalResolution = pFbInfo->VerticalResolution;\r
86470188 825 BytesPerScanLine = pFbInfo->BytesPerScanLine;\r
9c228fb0
MM
826 \r
827 ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (\r
828 ModeNumber * sizeof (FB_VIDEO_MODE_DATA)\r
829 );\r
830 if (NULL == ModeBuffer) {\r
831 Status = EFI_OUT_OF_RESOURCES;\r
832 goto Done;\r
833 }\r
834\r
835 VbeFrameBuffer =\r
836 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
837 BytesPerScanLine * VerticalResolution\r
838 );\r
839 if (NULL == VbeFrameBuffer) {\r
840 Status = EFI_OUT_OF_RESOURCES;\r
841 goto Done;\r
842 }\r
843 \r
844 if (FbGopPrivate->ModeData != NULL) {\r
845 FreePool (FbGopPrivate->ModeData);\r
846 }\r
847 \r
848 if (FbGopPrivate->VbeFrameBuffer != NULL) {\r
849 FreePool (FbGopPrivate->VbeFrameBuffer);\r
850 } \r
851 \r
852 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
853 CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;\r
854 \r
855 CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red); \r
856 CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue); \r
857 CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green); \r
858 CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved); \r
859 \r
860 CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel;\r
861 CurrentModeData->HorizontalResolution = HorizontalResolution;\r
862 CurrentModeData->VerticalResolution = VerticalResolution; \r
863 CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution; \r
864 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer;\r
865 CurrentModeData->VbeModeNumber = 0;\r
866 CurrentModeData->ColorDepth = 32;\r
867 CurrentModeData->RefreshRate = 60;\r
868 \r
869 CurrentModeData->PixelFormat = PixelBitMask;\r
870 if ((CurrentModeData->BitsPerPixel == 32) &&\r
871 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
872 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
873 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
874 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
875 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
876 }\r
877 } \r
878 \r
879 CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK)); \r
880 \r
881 FbGopPrivate->ModeData = ModeBuffer;\r
882 FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;\r
883 \r
884 //\r
885 // Assign Gop's Blt function\r
886 //\r
887 FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt;\r
888 \r
889 FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
890 FbGopPrivate->GraphicsOutput.Mode->Mode = 0; \r
891 FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;\r
892 FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;\r
893 FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution; \r
894 FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;\r
895 CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK)); \r
c0d9813c 896 FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = (UINT32)(BytesPerScanLine * 8 / BitsPerPixel);\r
9c228fb0
MM
897 FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
898 FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;\r
899 FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize;\r
900 \r
901 //\r
902 // Find the best mode to initialize\r
903 // \r
904\r
905Done:\r
906 //\r
907 // If there was an error, then free the mode structure\r
908 //\r
909 if (EFI_ERROR (Status)) {\r
910 \r
911 if (VbeFrameBuffer != NULL) {\r
912 FreePool (VbeFrameBuffer);\r
913 } \r
914 \r
915 if (ModeBuffer != NULL) {\r
916 FreePool (ModeBuffer);\r
917 } \r
918 }\r
919\r
920 return Status;\r
921}\r
922\r
923\r
924//\r
925// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
926//\r
927\r
928/**\r
929 Graphics Output protocol interface to get video mode.\r
930\r
931 @param This Protocol instance pointer.\r
932 @param ModeNumber The mode number to return information on.\r
933 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
934 buffer.\r
935 @param Info Caller allocated buffer that returns information\r
936 about ModeNumber.\r
937\r
938 @retval EFI_SUCCESS Mode information returned.\r
939 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
940 video mode.\r
941 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
942 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
943\r
944**/\r
945EFI_STATUS\r
946EFIAPI\r
947FbGopGraphicsOutputQueryMode (\r
948 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
949 IN UINT32 ModeNumber,\r
950 OUT UINTN *SizeOfInfo,\r
951 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
952 )\r
953{\r
954 FB_VIDEO_DEV *FbGopPrivate;\r
955 FB_VIDEO_MODE_DATA *ModeData;\r
956\r
957 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
958\r
959 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
960 return EFI_INVALID_PARAMETER;\r
961 }\r
962\r
963 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
964 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
965 );\r
966 if (NULL == *Info) {\r
967 return EFI_OUT_OF_RESOURCES;\r
968 }\r
969\r
970 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
971\r
972 ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
973 (*Info)->Version = 0;\r
974 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
975 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
976 (*Info)->PixelFormat = ModeData->PixelFormat;\r
977 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
978\r
979 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
980\r
981 return EFI_SUCCESS;\r
982}\r
983\r
984/**\r
985 Graphics Output protocol interface to set video mode.\r
986\r
987 @param This Protocol instance pointer.\r
988 @param ModeNumber The mode number to be set.\r
989\r
990 @retval EFI_SUCCESS Graphics mode was changed.\r
991 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
992 request.\r
993 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
994\r
995**/\r
996EFI_STATUS\r
997EFIAPI\r
998FbGopGraphicsOutputSetMode (\r
999 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1000 IN UINT32 ModeNumber\r
1001 )\r
1002{ \r
1003 FB_VIDEO_DEV *FbGopPrivate;\r
1004 FB_VIDEO_MODE_DATA *ModeData;\r
1005 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1006\r
1007 if (This == NULL) {\r
1008 return EFI_INVALID_PARAMETER;\r
1009 }\r
1010\r
1011 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1012\r
1013 ModeData = &FbGopPrivate->ModeData[ModeNumber];\r
1014\r
1015 if (ModeNumber >= This->Mode->MaxMode) {\r
1016 return EFI_UNSUPPORTED;\r
1017 }\r
1018 \r
1019 if (ModeNumber == This->Mode->Mode) {\r
1020 //\r
1021 // Clear screen to black\r
1022 // \r
1023 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1024 FbGopGraphicsOutputVbeBlt (\r
1025 This,\r
1026 &Background,\r
1027 EfiBltVideoFill,\r
1028 0,\r
1029 0,\r
1030 0,\r
1031 0,\r
1032 ModeData->HorizontalResolution,\r
1033 ModeData->VerticalResolution,\r
1034 0\r
1035 );\r
1036 return EFI_SUCCESS;\r
1037 } else {\r
1038 return EFI_UNSUPPORTED;\r
1039 }\r
1040 \r
1041}\r
1042\r
1043/**\r
1044 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1045\r
1046 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
1047 @param VbeBuffer The data to transfer to screen\r
1048 @param MemAddress Physical frame buffer base address\r
1049 @param DestinationX The X coordinate of the destination for BltOperation\r
1050 @param DestinationY The Y coordinate of the destination for BltOperation\r
1051 @param TotalBytes The total bytes of copy\r
1052 @param VbePixelWidth Bytes per pixel\r
1053 @param BytesPerScanLine Bytes per scan line\r
1054\r
1055**/\r
1056VOID\r
1057CopyVideoBuffer (\r
1058 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1059 IN UINT8 *VbeBuffer,\r
1060 IN VOID *MemAddress,\r
1061 IN UINTN DestinationX,\r
1062 IN UINTN DestinationY,\r
1063 IN UINTN TotalBytes,\r
1064 IN UINT32 VbePixelWidth,\r
1065 IN UINTN BytesPerScanLine\r
1066 )\r
1067{\r
1068 UINTN FrameBufferAddr;\r
1069 UINTN CopyBlockNum;\r
1070 UINTN RemainingBytes;\r
1071 UINTN UnalignedBytes;\r
1072 EFI_STATUS Status;\r
1073\r
1074 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
1075\r
1076 //\r
1077 // If TotalBytes is less than 4 bytes, only start byte copy.\r
1078 //\r
1079 if (TotalBytes < 4) {\r
1080 Status = PciIo->Mem.Write (\r
1081 PciIo,\r
1082 EfiPciIoWidthUint8,\r
1083 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1084 (UINT64) FrameBufferAddr,\r
1085 TotalBytes,\r
1086 VbeBuffer\r
1087 );\r
1088 ASSERT_EFI_ERROR (Status);\r
1089 return;\r
1090 }\r
1091\r
1092 //\r
1093 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
1094 //\r
1095 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
1096\r
1097 if (UnalignedBytes != 0) {\r
1098 Status = PciIo->Mem.Write (\r
1099 PciIo,\r
1100 EfiPciIoWidthUint8,\r
1101 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1102 (UINT64) FrameBufferAddr,\r
1103 UnalignedBytes,\r
1104 VbeBuffer\r
1105 );\r
1106 ASSERT_EFI_ERROR (Status);\r
1107 FrameBufferAddr += UnalignedBytes;\r
1108 VbeBuffer += UnalignedBytes;\r
1109 }\r
1110\r
1111 //\r
1112 // Calculate 4-byte block count and remaining bytes.\r
1113 //\r
1114 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
1115 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
1116\r
1117 //\r
1118 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
1119 //\r
1120 if (CopyBlockNum != 0) {\r
1121 Status = PciIo->Mem.Write (\r
1122 PciIo,\r
1123 EfiPciIoWidthUint32,\r
1124 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1125 (UINT64) FrameBufferAddr,\r
1126 CopyBlockNum,\r
1127 VbeBuffer\r
1128 );\r
1129 ASSERT_EFI_ERROR (Status);\r
1130 }\r
1131\r
1132 if (RemainingBytes != 0) {\r
1133 FrameBufferAddr += (CopyBlockNum << 2);\r
1134 VbeBuffer += (CopyBlockNum << 2);\r
1135 Status = PciIo->Mem.Write (\r
1136 PciIo,\r
1137 EfiPciIoWidthUint8,\r
1138 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1139 (UINT64) FrameBufferAddr,\r
1140 RemainingBytes,\r
1141 VbeBuffer\r
1142 );\r
1143 ASSERT_EFI_ERROR (Status);\r
1144 }\r
1145}\r
1146\r
1147/**\r
1148 Worker function to block transfer for VBE device.\r
1149\r
1150 @param FbGopPrivate Instance of FB_VIDEO_DEV\r
1151 @param BltBuffer The data to transfer to screen\r
1152 @param BltOperation The operation to perform\r
1153 @param SourceX The X coordinate of the source for BltOperation\r
1154 @param SourceY The Y coordinate of the source for BltOperation\r
1155 @param DestinationX The X coordinate of the destination for\r
1156 BltOperation\r
1157 @param DestinationY The Y coordinate of the destination for\r
1158 BltOperation\r
1159 @param Width The width of a rectangle in the blt rectangle in\r
1160 pixels\r
1161 @param Height The height of a rectangle in the blt rectangle in\r
1162 pixels\r
1163 @param Delta Not used for EfiBltVideoFill and\r
1164 EfiBltVideoToVideo operation. If a Delta of 0 is\r
1165 used, the entire BltBuffer will be operated on. If\r
1166 a subrectangle of the BltBuffer is used, then\r
1167 Delta represents the number of bytes in a row of\r
1168 the BltBuffer.\r
1169 @param Mode Mode data.\r
1170\r
1171 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
1172 @retval EFI_SUCCESS Blt operation success\r
1173\r
1174**/\r
1175EFI_STATUS\r
1176FbGopVbeBltWorker (\r
1177 IN FB_VIDEO_DEV *FbGopPrivate,\r
1178 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1179 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1180 IN UINTN SourceX,\r
1181 IN UINTN SourceY,\r
1182 IN UINTN DestinationX,\r
1183 IN UINTN DestinationY,\r
1184 IN UINTN Width,\r
1185 IN UINTN Height,\r
1186 IN UINTN Delta,\r
1187 IN FB_VIDEO_MODE_DATA *Mode\r
1188 )\r
1189{\r
1190 EFI_PCI_IO_PROTOCOL *PciIo;\r
1191 EFI_TPL OriginalTPL;\r
1192 UINTN DstY;\r
1193 UINTN SrcY;\r
1194 UINTN DstX;\r
1195 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
1196 VOID *MemAddress;\r
1197 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
1198 UINTN BytesPerScanLine;\r
1199 UINTN Index;\r
1200 UINT8 *VbeBuffer;\r
1201 UINT8 *VbeBuffer1;\r
1202 UINT8 *BltUint8;\r
1203 UINT32 VbePixelWidth;\r
1204 UINT32 Pixel;\r
1205 UINTN TotalBytes;\r
1206\r
1207 PciIo = FbGopPrivate->PciIo;\r
1208\r
1209 VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer;\r
1210 MemAddress = Mode->LinearFrameBuffer;\r
1211 BytesPerScanLine = Mode->BytesPerScanLine;\r
1212 VbePixelWidth = Mode->BitsPerPixel / 8;\r
1213 BltUint8 = (UINT8 *) BltBuffer;\r
1214 TotalBytes = Width * VbePixelWidth;\r
1215\r
1216 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
1217 return EFI_INVALID_PARAMETER;\r
1218 }\r
1219\r
1220 if (Width == 0 || Height == 0) {\r
1221 return EFI_INVALID_PARAMETER;\r
1222 }\r
1223 //\r
1224 // We need to fill the Virtual Screen buffer with the blt data.\r
1225 // The virtual screen is upside down, as the first row is the bootom row of\r
1226 // the image.\r
1227 //\r
1228 if (BltOperation == EfiBltVideoToBltBuffer) {\r
1229 //\r
1230 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
1231 //\r
1232 if (SourceY + Height > Mode->VerticalResolution) {\r
1233 return EFI_INVALID_PARAMETER;\r
1234 }\r
1235\r
1236 if (SourceX + Width > Mode->HorizontalResolution) {\r
1237 return EFI_INVALID_PARAMETER;\r
1238 }\r
1239 } else {\r
1240 //\r
1241 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
1242 //\r
1243 if (DestinationY + Height > Mode->VerticalResolution) {\r
1244 return EFI_INVALID_PARAMETER;\r
1245 }\r
1246\r
1247 if (DestinationX + Width > Mode->HorizontalResolution) {\r
1248 return EFI_INVALID_PARAMETER;\r
1249 }\r
1250 }\r
1251 //\r
1252 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
1253 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
1254 // the number of bytes in each row can be computed.\r
1255 //\r
1256 if (Delta == 0) {\r
1257 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
1258 }\r
1259 //\r
1260 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
1261 // We would not want a timer based event (Cursor, ...) to come in while we are\r
1262 // doing this operation.\r
1263 //\r
1264 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
1265\r
1266 switch (BltOperation) {\r
1267 case EfiBltVideoToBltBuffer:\r
1268 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
1269 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1270 //\r
1271 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
1272 //\r
1273 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
1274 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
1275 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
1276 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
1277 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
1278 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
1279 Blt->Reserved = 0;\r
1280 Blt++;\r
1281 VbeBuffer += VbePixelWidth;\r
1282 }\r
1283\r
1284 }\r
1285 break;\r
1286\r
1287 case EfiBltVideoToVideo:\r
1288 for (Index = 0; Index < Height; Index++) {\r
1289 if (DestinationY <= SourceY) {\r
1290 SrcY = SourceY + Index;\r
1291 DstY = DestinationY + Index;\r
1292 } else {\r
1293 SrcY = SourceY + Height - Index - 1;\r
1294 DstY = DestinationY + Height - Index - 1;\r
1295 }\r
1296\r
1297 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
1298 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
1299\r
1300 gBS->CopyMem (\r
1301 VbeBuffer,\r
1302 VbeBuffer1,\r
1303 TotalBytes\r
1304 );\r
1305\r
1306 //\r
1307 // Update physical frame buffer.\r
1308 //\r
1309 CopyVideoBuffer (\r
1310 PciIo,\r
1311 VbeBuffer,\r
1312 MemAddress,\r
1313 DestinationX,\r
1314 DstY,\r
1315 TotalBytes,\r
1316 VbePixelWidth,\r
1317 BytesPerScanLine\r
1318 );\r
1319 }\r
1320 break;\r
1321\r
1322 case EfiBltVideoFill:\r
1323 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
1324 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
1325 //\r
1326 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
1327 //\r
1328 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
1329 (\r
1330 (Blt->Green & Mode->Green.Mask) <<\r
1331 Mode->Green.Position\r
1332 ) |\r
1333 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
1334\r
1335 for (Index = 0; Index < Width; Index++) {\r
1336 gBS->CopyMem (\r
1337 VbeBuffer,\r
1338 &Pixel,\r
1339 VbePixelWidth\r
1340 );\r
1341 VbeBuffer += VbePixelWidth;\r
1342 }\r
1343\r
1344 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
1345 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
1346 gBS->CopyMem (\r
1347 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
1348 VbeBuffer,\r
1349 TotalBytes\r
1350 );\r
1351 }\r
1352\r
1353 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
1354 //\r
1355 // Update physical frame buffer.\r
1356 //\r
1357 CopyVideoBuffer (\r
1358 PciIo,\r
1359 VbeBuffer,\r
1360 MemAddress,\r
1361 DestinationX,\r
1362 DstY,\r
1363 TotalBytes,\r
1364 VbePixelWidth,\r
1365 BytesPerScanLine\r
1366 );\r
1367 }\r
1368 break;\r
1369\r
1370 case EfiBltBufferToVideo:\r
1371 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
1372 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1373 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
1374 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
1375 //\r
1376 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
1377 //\r
1378 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
1379 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
1380 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
1381 gBS->CopyMem (\r
1382 VbeBuffer,\r
1383 &Pixel,\r
1384 VbePixelWidth\r
1385 );\r
1386 Blt++;\r
1387 VbeBuffer += VbePixelWidth;\r
1388 }\r
1389\r
1390 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
1391\r
1392 //\r
1393 // Update physical frame buffer.\r
1394 //\r
1395 CopyVideoBuffer (\r
1396 PciIo,\r
1397 VbeBuffer,\r
1398 MemAddress,\r
1399 DestinationX,\r
1400 DstY,\r
1401 TotalBytes,\r
1402 VbePixelWidth,\r
1403 BytesPerScanLine\r
1404 );\r
1405 }\r
1406 break;\r
1407\r
1408 default: ;\r
1409 }\r
1410\r
1411 gBS->RestoreTPL (OriginalTPL);\r
1412\r
1413 return EFI_SUCCESS;\r
1414}\r
1415\r
1416/**\r
1417 Graphics Output protocol instance to block transfer for VBE device.\r
1418\r
1419 @param This Pointer to Graphics Output protocol instance\r
1420 @param BltBuffer The data to transfer to screen\r
1421 @param BltOperation The operation to perform\r
1422 @param SourceX The X coordinate of the source for BltOperation\r
1423 @param SourceY The Y coordinate of the source for BltOperation\r
1424 @param DestinationX The X coordinate of the destination for\r
1425 BltOperation\r
1426 @param DestinationY The Y coordinate of the destination for\r
1427 BltOperation\r
1428 @param Width The width of a rectangle in the blt rectangle in\r
1429 pixels\r
1430 @param Height The height of a rectangle in the blt rectangle in\r
1431 pixels\r
1432 @param Delta Not used for EfiBltVideoFill and\r
1433 EfiBltVideoToVideo operation. If a Delta of 0 is\r
1434 used, the entire BltBuffer will be operated on. If\r
1435 a subrectangle of the BltBuffer is used, then\r
1436 Delta represents the number of bytes in a row of\r
1437 the BltBuffer.\r
1438\r
1439 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
1440 @retval EFI_SUCCESS Blt operation success\r
1441\r
1442**/\r
1443EFI_STATUS\r
1444EFIAPI\r
1445FbGopGraphicsOutputVbeBlt (\r
1446 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1447 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1448 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1449 IN UINTN SourceX,\r
1450 IN UINTN SourceY,\r
1451 IN UINTN DestinationX,\r
1452 IN UINTN DestinationY,\r
1453 IN UINTN Width,\r
1454 IN UINTN Height,\r
1455 IN UINTN Delta\r
1456 )\r
1457{\r
1458 FB_VIDEO_DEV *FbGopPrivate;\r
1459 FB_VIDEO_MODE_DATA *Mode;\r
1460\r
1461 if (This == NULL) {\r
1462 return EFI_INVALID_PARAMETER;\r
1463 }\r
1464\r
1465 FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1466 Mode = &FbGopPrivate->ModeData[This->Mode->Mode];\r
1467\r
1468 return FbGopVbeBltWorker (\r
1469 FbGopPrivate,\r
1470 BltBuffer,\r
1471 BltOperation,\r
1472 SourceX,\r
1473 SourceY,\r
1474 DestinationX,\r
1475 DestinationY,\r
1476 Width,\r
1477 Height,\r
1478 Delta,\r
1479 Mode\r
1480 );\r
1481}\r
1482\r
1483\r
1484/**\r
1485 The user Entry Point for module UefiFbGop. The user code starts with this function.\r
1486\r
1487 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1488 @param[in] SystemTable A pointer to the EFI System Table.\r
1489\r
1490 @retval EFI_SUCCESS The entry point is executed successfully.\r
1491 @retval other Some error occurs when executing this entry point.\r
1492\r
1493**/\r
1494EFI_STATUS\r
1495EFIAPI\r
1496FbGopEntryPoint(\r
1497 IN EFI_HANDLE ImageHandle,\r
1498 IN EFI_SYSTEM_TABLE *SystemTable\r
1499 )\r
1500{\r
1501 EFI_STATUS Status;\r
1502 EFI_HOB_GUID_TYPE *GuidHob;\r
1503 \r
1504 //\r
1505 // Find the frame buffer information guid hob\r
1506 //\r
1507 GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);\r
1508 if (GuidHob != NULL) { \r
1509 //\r
1510 // Install driver model protocol(s).\r
1511 //\r
1512 Status = EfiLibInstallDriverBindingComponentName2 (\r
1513 ImageHandle,\r
1514 SystemTable,\r
1515 &gFbGopDriverBinding,\r
1516 ImageHandle,\r
1517 &gFbGopComponentName,\r
1518 &gFbGopComponentName2\r
1519 );\r
1520 ASSERT_EFI_ERROR (Status);\r
1521 } else {\r
1522 DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));\r
1523 Status = EFI_ABORTED;\r
1524 }\r
1525 return Status; \r
1526}\r
1527\r