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