]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c
IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / BiosThunk / VideoDxe / BiosVideo.c
CommitLineData
bcecde14 1/** @file\r
2 ConsoleOut Routines that speak VGA.\r
3\r
4Copyright (c) 2007 - 2011, 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 "BiosVideo.h"\r
18\r
19//\r
20// EFI Driver Binding Protocol Instance\r
21//\r
22EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {\r
23 BiosVideoDriverBindingSupported,\r
24 BiosVideoDriverBindingStart,\r
25 BiosVideoDriverBindingStop,\r
26 0x3,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
31//\r
32// Global lookup tables for VGA graphics modes\r
33//\r
34UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
35\r
36UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
37\r
38UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
39\r
40EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
41 { 0x00, 0x00, 0x00, 0x00 },\r
42 { 0x98, 0x00, 0x00, 0x00 },\r
43 { 0x00, 0x98, 0x00, 0x00 },\r
44 { 0x98, 0x98, 0x00, 0x00 },\r
45 { 0x00, 0x00, 0x98, 0x00 },\r
46 { 0x98, 0x00, 0x98, 0x00 },\r
47 { 0x00, 0x98, 0x98, 0x00 },\r
48 { 0x98, 0x98, 0x98, 0x00 },\r
49 { 0x10, 0x10, 0x10, 0x00 },\r
50 { 0xff, 0x10, 0x10, 0x00 },\r
51 { 0x10, 0xff, 0x10, 0x00 },\r
52 { 0xff, 0xff, 0x10, 0x00 },\r
53 { 0x10, 0x10, 0xff, 0x00 },\r
54 { 0xf0, 0x10, 0xff, 0x00 },\r
55 { 0x10, 0xff, 0xff, 0x00 },\r
56 { 0xff, 0xff, 0xff, 0x00 }\r
57};\r
58\r
59//\r
60// Standard timing defined by VESA EDID\r
61//\r
62VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {\r
63 //\r
64 // Established Timing I\r
65 //\r
66 {800, 600, 60},\r
67 {800, 600, 56},\r
68 {640, 480, 75},\r
69 {640, 480, 72},\r
70 {640, 480, 67},\r
71 {640, 480, 60},\r
72 {720, 400, 88},\r
73 {720, 400, 70},\r
74 //\r
75 // Established Timing II\r
76 //\r
77 {1280, 1024, 75},\r
78 {1024, 768, 75},\r
79 {1024, 768, 70},\r
80 {1024, 768, 60},\r
81 {1024, 768, 87},\r
82 {832, 624, 75},\r
83 {800, 600, 75},\r
84 {800, 600, 72},\r
85 //\r
86 // Established Timing III\r
87 //\r
88 {1152, 870, 75}\r
89};\r
90\r
91/**\r
92 Supported.\r
93\r
94 @param This Pointer to driver binding protocol\r
95 @param Controller Controller handle to connect\r
96 @param RemainingDevicePath A pointer to the remaining portion of a device\r
97 path\r
98\r
99 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this\r
100 driver, Otherwise, this controller cannot be\r
101 managed by this driver\r
102\r
103**/\r
104EFI_STATUS\r
105EFIAPI\r
106BiosVideoDriverBindingSupported (\r
107 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
108 IN EFI_HANDLE Controller,\r
109 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
110 )\r
111{\r
112 EFI_STATUS Status;\r
113 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
114 EFI_PCI_IO_PROTOCOL *PciIo;\r
115 PCI_TYPE00 Pci;\r
116 EFI_DEV_PATH *Node;\r
117\r
118 //\r
119 // See if the Legacy BIOS Protocol is available\r
120 //\r
121 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
122 if (EFI_ERROR (Status)) {\r
123 return Status;\r
124 }\r
125\r
126 //\r
127 // Open the IO Abstraction(s) needed to perform the supported test\r
128 //\r
129 Status = gBS->OpenProtocol (\r
130 Controller,\r
131 &gEfiPciIoProtocolGuid,\r
132 (VOID **) &PciIo,\r
133 This->DriverBindingHandle,\r
134 Controller,\r
135 EFI_OPEN_PROTOCOL_BY_DRIVER\r
136 );\r
137 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
138 return Status;\r
139 }\r
140\r
141 if (Status == EFI_ALREADY_STARTED) {\r
142 //\r
143 // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,\r
144 // because VgaMiniPort protocol is installed on controller handle directly.\r
145 //\r
146 Status = gBS->OpenProtocol (\r
147 Controller,\r
148 &gEfiVgaMiniPortProtocolGuid,\r
149 NULL,\r
150 NULL,\r
151 NULL,\r
152 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
153 );\r
154 if (!EFI_ERROR (Status)) {\r
155 return EFI_ALREADY_STARTED;\r
156 }\r
157 }\r
158 //\r
159 // See if this is a PCI Graphics Controller by looking at the Command register and\r
160 // Class Code Register\r
161 //\r
162 Status = PciIo->Pci.Read (\r
163 PciIo,\r
164 EfiPciIoWidthUint32,\r
165 0,\r
166 sizeof (Pci) / sizeof (UINT32),\r
167 &Pci\r
168 );\r
169 if (EFI_ERROR (Status)) {\r
170 Status = EFI_UNSUPPORTED;\r
171 goto Done;\r
172 }\r
173\r
174 Status = EFI_UNSUPPORTED;\r
175 if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {\r
176\r
177 Status = EFI_SUCCESS;\r
178 //\r
179 // If this is a graphics controller,\r
180 // go further check RemainingDevicePath validation\r
181 //\r
182 if (RemainingDevicePath != NULL) {\r
183 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
184 //\r
185 // Check if RemainingDevicePath is the End of Device Path Node, \r
186 // if yes, return EFI_SUCCESS\r
187 //\r
188 if (!IsDevicePathEnd (Node)) {\r
189 //\r
190 // If RemainingDevicePath isn't the End of Device Path Node,\r
191 // check its validation\r
192 //\r
193 if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
194 Node->DevPath.SubType != ACPI_ADR_DP ||\r
195 DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
196 Status = EFI_UNSUPPORTED;\r
197 }\r
198 }\r
199 }\r
200 }\r
201\r
202Done:\r
203 gBS->CloseProtocol (\r
204 Controller,\r
205 &gEfiPciIoProtocolGuid,\r
206 This->DriverBindingHandle,\r
207 Controller\r
208 );\r
209\r
210 return Status;\r
211}\r
212\r
213\r
214/**\r
215 Install Graphics Output Protocol onto VGA device handles.\r
216\r
217 @param This Pointer to driver binding protocol\r
218 @param Controller Controller handle to connect\r
219 @param RemainingDevicePath A pointer to the remaining portion of a device\r
220 path\r
221\r
222 @return EFI_STATUS\r
223\r
224**/\r
225EFI_STATUS\r
226EFIAPI\r
227BiosVideoDriverBindingStart (\r
228 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
229 IN EFI_HANDLE Controller,\r
230 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
235 EFI_PCI_IO_PROTOCOL *PciIo;\r
236 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
237 UINTN Flags;\r
238 UINT64 OriginalPciAttributes;\r
239 UINT64 Supports;\r
240 BOOLEAN PciAttributesSaved;\r
241\r
242 //\r
243 // Initialize local variables\r
244 //\r
245 PciIo = NULL;\r
246 ParentDevicePath = NULL;\r
247\r
248 //\r
249 //\r
250 // See if the Legacy BIOS Protocol is available\r
251 //\r
252 Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
253 if (EFI_ERROR (Status)) {\r
254 return Status;\r
255 }\r
256\r
257 //\r
258 // Open the IO Abstraction(s) needed\r
259 //\r
260 Status = gBS->OpenProtocol (\r
261 Controller,\r
262 &gEfiPciIoProtocolGuid,\r
263 (VOID **) &PciIo,\r
264 This->DriverBindingHandle,\r
265 Controller,\r
266 EFI_OPEN_PROTOCOL_BY_DRIVER\r
267 );\r
268 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
269 return Status;\r
270 }\r
271\r
272 PciAttributesSaved = FALSE;\r
273 //\r
274 // Save original PCI attributes\r
275 //\r
276 Status = PciIo->Attributes (\r
277 PciIo,\r
278 EfiPciIoAttributeOperationGet,\r
279 0,\r
280 &OriginalPciAttributes\r
281 );\r
282\r
283 if (EFI_ERROR (Status)) {\r
284 goto Done;\r
285 }\r
286 PciAttributesSaved = TRUE;\r
287\r
288 //\r
289 // Get supported PCI attributes\r
290 //\r
291 Status = PciIo->Attributes (\r
292 PciIo,\r
293 EfiPciIoAttributeOperationSupported,\r
294 0,\r
295 &Supports\r
296 );\r
297 if (EFI_ERROR (Status)) {\r
298 goto Done;\r
299 }\r
300\r
301 Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
302 if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {\r
303 Status = EFI_UNSUPPORTED;\r
304 goto Done;\r
305 } \r
306\r
307 //\r
308 // Prepare for status code\r
309 //\r
310 Status = gBS->HandleProtocol (\r
311 Controller,\r
312 &gEfiDevicePathProtocolGuid,\r
313 (VOID **) &ParentDevicePath\r
314 );\r
315 if (EFI_ERROR (Status)) {\r
316 goto Done;\r
317 }\r
318\r
319 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
320 EFI_PROGRESS_CODE,\r
321 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,\r
322 ParentDevicePath\r
323 );\r
324 //\r
325 // Enable the device and make sure VGA cycles are being forwarded to this VGA device\r
326 //\r
327 Status = PciIo->Attributes (\r
328 PciIo,\r
329 EfiPciIoAttributeOperationEnable,\r
330 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Supports,\r
331 NULL\r
332 );\r
333 if (EFI_ERROR (Status)) {\r
334 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
335 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
336 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,\r
337 ParentDevicePath\r
338 );\r
339 goto Done;\r
340 }\r
341 //\r
342 // Check to see if there is a legacy option ROM image associated with this PCI device\r
343 //\r
344 Status = LegacyBios->CheckPciRom (\r
345 LegacyBios,\r
346 Controller,\r
347 NULL,\r
348 NULL,\r
349 &Flags\r
350 );\r
351 if (EFI_ERROR (Status)) {\r
352 goto Done;\r
353 }\r
354 //\r
355 // Post the legacy option ROM if it is available.\r
356 //\r
357 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
358 EFI_PROGRESS_CODE,\r
359 EFI_P_PC_RESET,\r
360 ParentDevicePath\r
361 );\r
362 Status = LegacyBios->InstallPciRom (\r
363 LegacyBios,\r
364 Controller,\r
365 NULL,\r
366 &Flags,\r
367 NULL,\r
368 NULL,\r
369 NULL,\r
370 NULL\r
371 );\r
372 if (EFI_ERROR (Status)) {\r
373 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
374 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
375 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
376 ParentDevicePath\r
377 );\r
378 goto Done;\r
379 }\r
380\r
381 if (RemainingDevicePath != NULL) {\r
382 if (IsDevicePathEnd (RemainingDevicePath) && \r
383 (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable))) {\r
384 //\r
385 // If RemainingDevicePath is the End of Device Path Node,\r
386 // don't create any child device and return EFI_SUCESS\r
387 Status = EFI_SUCCESS;\r
388 goto Done;\r
389 }\r
390 }\r
391\r
392 //\r
393 // Create child handle and install GraphicsOutputProtocol on it\r
394 //\r
395 Status = BiosVideoChildHandleInstall (\r
396 This,\r
397 Controller,\r
398 PciIo,\r
399 LegacyBios,\r
400 ParentDevicePath,\r
401 RemainingDevicePath,\r
402 OriginalPciAttributes\r
403 );\r
404\r
405Done:\r
406 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
407 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
408 EFI_PROGRESS_CODE,\r
409 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,\r
410 ParentDevicePath\r
411 );\r
412\r
413 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
414 EFI_PROGRESS_CODE,\r
415 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,\r
416 ParentDevicePath\r
417 );\r
418 if (PciAttributesSaved) {\r
419 //\r
420 // Restore original PCI attributes\r
421 //\r
422 PciIo->Attributes (\r
423 PciIo,\r
424 EfiPciIoAttributeOperationSet,\r
425 OriginalPciAttributes,\r
426 NULL\r
427 );\r
428 }\r
429 //\r
430 // Release PCI I/O Protocols on the controller handle.\r
431 //\r
432 gBS->CloseProtocol (\r
433 Controller,\r
434 &gEfiPciIoProtocolGuid,\r
435 This->DriverBindingHandle,\r
436 Controller\r
437 );\r
438 }\r
439\r
440 return Status;\r
441}\r
442\r
443\r
444/**\r
445 Stop.\r
446\r
447 @param This Pointer to driver binding protocol\r
448 @param Controller Controller handle to connect\r
449 @param NumberOfChildren Number of children handle created by this driver\r
450 @param ChildHandleBuffer Buffer containing child handle created\r
451\r
452 @retval EFI_SUCCESS Driver disconnected successfully from controller\r
453 @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure\r
454\r
455**/\r
456EFI_STATUS\r
457EFIAPI\r
458BiosVideoDriverBindingStop (\r
459 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
460 IN EFI_HANDLE Controller,\r
461 IN UINTN NumberOfChildren,\r
462 IN EFI_HANDLE *ChildHandleBuffer\r
463 )\r
464{\r
465 EFI_STATUS Status;\r
466 BOOLEAN AllChildrenStopped;\r
467 UINTN Index;\r
468\r
469 AllChildrenStopped = TRUE;\r
470\r
471 if (NumberOfChildren == 0) {\r
472 //\r
473 // Close PCI I/O protocol on the controller handle\r
474 //\r
475 gBS->CloseProtocol (\r
476 Controller,\r
477 &gEfiPciIoProtocolGuid,\r
478 This->DriverBindingHandle,\r
479 Controller\r
480 );\r
481\r
482 return EFI_SUCCESS;\r
483 }\r
484\r
485 for (Index = 0; Index < NumberOfChildren; Index++) {\r
486 Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);\r
487\r
488 if (EFI_ERROR (Status)) {\r
489 AllChildrenStopped = FALSE;\r
490 }\r
491 }\r
492\r
493 if (!AllChildrenStopped) {\r
494 return EFI_DEVICE_ERROR;\r
495 }\r
496\r
497 return EFI_SUCCESS;\r
498}\r
499\r
500\r
501/**\r
502 Install child handles if the Handle supports MBR format.\r
503\r
504 @param This Calling context.\r
505 @param ParentHandle Parent Handle\r
506 @param ParentPciIo Parent PciIo interface\r
507 @param ParentLegacyBios Parent LegacyBios interface\r
508 @param ParentDevicePath Parent Device Path\r
509 @param RemainingDevicePath Remaining Device Path\r
510 @param OriginalPciAttributes Original PCI Attributes\r
511\r
512 @retval EFI_SUCCESS If a child handle was added\r
513 @retval other A child handle was not added\r
514\r
515**/\r
516EFI_STATUS\r
517BiosVideoChildHandleInstall (\r
518 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
519 IN EFI_HANDLE ParentHandle,\r
520 IN EFI_PCI_IO_PROTOCOL *ParentPciIo,\r
521 IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios,\r
522 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
523 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,\r
524 IN UINT64 OriginalPciAttributes\r
525 )\r
526{\r
527 EFI_STATUS Status;\r
528 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
529 PCI_TYPE00 Pci;\r
530 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
531 BOOLEAN ProtocolInstalled;\r
532\r
533 //\r
534 // Allocate the private device structure for video device\r
535 //\r
536 BiosVideoPrivate = (BIOS_VIDEO_DEV *) AllocateZeroPool (\r
537 sizeof (BIOS_VIDEO_DEV)\r
538 );\r
539 if (NULL == BiosVideoPrivate) {\r
540 Status = EFI_OUT_OF_RESOURCES;\r
541 goto Done;\r
542 }\r
543\r
544 //\r
545 // See if this is a VGA compatible controller or not\r
546 //\r
547 Status = ParentPciIo->Pci.Read (\r
548 ParentPciIo,\r
549 EfiPciIoWidthUint32,\r
550 0,\r
551 sizeof (Pci) / sizeof (UINT32),\r
552 &Pci\r
553 );\r
554 if (EFI_ERROR (Status)) {\r
555 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
556 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
557 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,\r
558 ParentDevicePath\r
559 );\r
560 goto Done;\r
561 }\r
562 BiosVideoPrivate->VgaCompatible = FALSE;\r
563 if (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01) {\r
564 BiosVideoPrivate->VgaCompatible = TRUE;\r
565 }\r
566\r
567 if (Pci.Hdr.ClassCode[2] == 0x03 && Pci.Hdr.ClassCode[1] == 0x00 && Pci.Hdr.ClassCode[0] == 0x00) {\r
568 BiosVideoPrivate->VgaCompatible = TRUE;\r
569 }\r
570\r
571 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
572 //\r
573 // Create EXIT_BOOT_SERIVES Event\r
574 //\r
575 Status = gBS->CreateEventEx (\r
576 EVT_NOTIFY_SIGNAL,\r
577 TPL_NOTIFY,\r
578 BiosVideoNotifyExitBootServices,\r
579 BiosVideoPrivate,\r
580 &gEfiEventExitBootServicesGuid,\r
581 &BiosVideoPrivate->ExitBootServicesEvent\r
582 );\r
583 if (EFI_ERROR (Status)) {\r
584 goto Done;\r
585 }\r
586 }\r
587\r
588 //\r
589 // Initialize the child private structure\r
590 //\r
591 BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
592\r
593 //\r
594 // Fill in Graphics Output specific mode structures\r
595 //\r
596 BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
597 BiosVideoPrivate->ModeData = NULL;\r
598 BiosVideoPrivate->LineBuffer = NULL;\r
599 BiosVideoPrivate->VgaFrameBuffer = NULL;\r
600 BiosVideoPrivate->VbeFrameBuffer = NULL;\r
601\r
602 //\r
603 // Fill in the Graphics Output Protocol\r
604 //\r
605 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
606 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
607\r
608\r
609 //\r
610 // Allocate buffer for Graphics Output Protocol mode information\r
611 //\r
612 BiosVideoPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (\r
613 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)\r
614 );\r
615 if (NULL == BiosVideoPrivate->GraphicsOutput.Mode) {\r
616 Status = EFI_OUT_OF_RESOURCES;\r
617 goto Done;\r
618 }\r
619\r
620 BiosVideoPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
621 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
622 );\r
623 if (NULL == BiosVideoPrivate->GraphicsOutput.Mode->Info) {\r
624 Status = EFI_OUT_OF_RESOURCES;\r
625 goto Done;\r
626 }\r
627\r
628 //\r
629 // Assume that Graphics Output Protocol will be produced until proven otherwise\r
630 //\r
631 BiosVideoPrivate->ProduceGraphicsOutput = TRUE;\r
632\r
633 //\r
634 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.\r
635 //\r
636 if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {\r
637 if (RemainingDevicePath == NULL) {\r
638 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
639 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
640 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
641 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
642 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
643 \r
644 BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (\r
645 ParentDevicePath,\r
646 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
647 );\r
648 } else {\r
649 BiosVideoPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
650 }\r
651 \r
652 //\r
653 // Creat child handle and device path protocol firstly\r
654 //\r
655 BiosVideoPrivate->Handle = NULL;\r
656 Status = gBS->InstallMultipleProtocolInterfaces (\r
657 &BiosVideoPrivate->Handle,\r
658 &gEfiDevicePathProtocolGuid,\r
659 BiosVideoPrivate->GopDevicePath,\r
660 NULL\r
661 );\r
662 if (EFI_ERROR (Status)) {\r
663 goto Done;\r
664 }\r
665 }\r
666\r
667 //\r
668 // Fill in the VGA Mini Port Protocol fields\r
669 //\r
670 BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode;\r
671 BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000;\r
672 BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;\r
673 BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5;\r
674 BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
675 BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
676 BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR;\r
677\r
678 //\r
679 // Child handle need to consume the Legacy Bios protocol\r
680 //\r
681 BiosVideoPrivate->LegacyBios = ParentLegacyBios;\r
682\r
683 //\r
684 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally\r
685 //\r
686 BiosVideoPrivate->PciIo = ParentPciIo;\r
687 BiosVideoPrivate->OriginalPciAttributes = OriginalPciAttributes;\r
688\r
689 //\r
690 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
691 //\r
692 if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) {\r
693 Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
694 DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status));\r
695 } else {\r
696 Status = EFI_UNSUPPORTED;\r
697 }\r
698 if (EFI_ERROR (Status)) {\r
699 //\r
700 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support\r
701 // for the standard 640x480 16 color VGA mode\r
702 //\r
703 DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompatible));\r
704 if (BiosVideoPrivate->VgaCompatible) {\r
705 if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) {\r
706 Status = BiosVideoCheckForVga (BiosVideoPrivate);\r
707 DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status));\r
708 } else {\r
709 Status = EFI_UNSUPPORTED;\r
710 }\r
711 }\r
712\r
713 if (EFI_ERROR (Status)) {\r
714 //\r
715 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do\r
716 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.\r
717 //\r
718 BiosVideoPrivate->ProduceGraphicsOutput = FALSE;\r
719\r
720 //\r
721 // INT services are available, so on the 80x25 and 80x50 text mode are supported\r
722 //\r
723 BiosVideoPrivate->VgaMiniPort.MaxMode = 2;\r
724 }\r
725 }\r
726\r
727 ProtocolInstalled = FALSE;\r
728\r
729 if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
730 //\r
731 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
732 //\r
733 Status = gBS->InstallMultipleProtocolInterfaces (\r
734 &BiosVideoPrivate->Handle,\r
735 &gEfiGraphicsOutputProtocolGuid,\r
736 &BiosVideoPrivate->GraphicsOutput,\r
737 &gEfiEdidDiscoveredProtocolGuid,\r
738 &BiosVideoPrivate->EdidDiscovered,\r
739 &gEfiEdidActiveProtocolGuid,\r
740 &BiosVideoPrivate->EdidActive,\r
741 NULL\r
742 );\r
743\r
744 if (!EFI_ERROR (Status)) {\r
745 //\r
746 // Open the Parent Handle for the child\r
747 //\r
748 Status = gBS->OpenProtocol (\r
749 ParentHandle,\r
750 &gEfiPciIoProtocolGuid,\r
751 (VOID **) &BiosVideoPrivate->PciIo,\r
752 This->DriverBindingHandle,\r
753 BiosVideoPrivate->Handle,\r
754 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
755 );\r
756 if (EFI_ERROR (Status)) {\r
757 goto Done;\r
758 }\r
759 ProtocolInstalled = TRUE;\r
760 }\r
761 }\r
762\r
763 if (!ProtocolInstalled) {\r
764 //\r
765 // Install VGA Mini Port Protocol\r
766 //\r
767 Status = gBS->InstallMultipleProtocolInterfaces (\r
768 &ParentHandle,\r
769 &gEfiVgaMiniPortProtocolGuid,\r
770 &BiosVideoPrivate->VgaMiniPort,\r
771 NULL\r
772 );\r
773 }\r
774\r
775Done:\r
776 if (EFI_ERROR (Status)) {\r
777 if ((BiosVideoPrivate != NULL) && (BiosVideoPrivate->ExitBootServicesEvent != NULL)) {\r
778 gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
779 } \r
780 //\r
781 // Free private data structure\r
782 //\r
783 BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
784 }\r
785\r
786 return Status;\r
787}\r
788\r
789\r
790/**\r
791 Deregister an video child handle and free resources.\r
792\r
793 @param This Protocol instance pointer.\r
794 @param Controller Video controller handle\r
795 @param Handle Video child handle\r
796\r
797 @return EFI_STATUS\r
798\r
799**/\r
800EFI_STATUS\r
801BiosVideoChildHandleUninstall (\r
802 EFI_DRIVER_BINDING_PROTOCOL *This,\r
803 EFI_HANDLE Controller,\r
804 EFI_HANDLE Handle\r
805 )\r
806{\r
807 EFI_STATUS Status;\r
808 EFI_IA32_REGISTER_SET Regs;\r
809 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
810 EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;\r
811 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
812 EFI_PCI_IO_PROTOCOL *PciIo;\r
813\r
814 BiosVideoPrivate = NULL;\r
815 GraphicsOutput = NULL;\r
816 PciIo = NULL;\r
817 Status = EFI_UNSUPPORTED;\r
818\r
819 Status = gBS->OpenProtocol (\r
820 Handle,\r
821 &gEfiGraphicsOutputProtocolGuid,\r
822 (VOID **) &GraphicsOutput,\r
823 This->DriverBindingHandle,\r
824 Handle,\r
825 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
826 );\r
827 if (!EFI_ERROR (Status)) {\r
828 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
829 }\r
830\r
831 if (EFI_ERROR (Status)) {\r
832 Status = gBS->OpenProtocol (\r
833 Handle,\r
834 &gEfiVgaMiniPortProtocolGuid,\r
835 (VOID **) &VgaMiniPort,\r
836 This->DriverBindingHandle,\r
837 Handle,\r
838 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
839 );\r
840 if (!EFI_ERROR (Status)) {\r
841 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);\r
842 }\r
843 }\r
844\r
845 if (BiosVideoPrivate == NULL) {\r
846 return EFI_UNSUPPORTED;\r
847 }\r
848\r
849 //\r
850 // Set the 80x25 Text VGA Mode\r
851 //\r
852 Regs.H.AH = 0x00;\r
853 Regs.H.AL = 0x03;\r
854 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
855\r
856 Regs.H.AH = 0x11;\r
857 Regs.H.AL = 0x14;\r
858 Regs.H.BL = 0;\r
859 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
860\r
861 //\r
862 // Restore original PCI attributes\r
863 //\r
864 Status = BiosVideoPrivate->PciIo->Attributes (\r
865 BiosVideoPrivate->PciIo,\r
866 EfiPciIoAttributeOperationSet,\r
867 BiosVideoPrivate->OriginalPciAttributes,\r
868 NULL\r
869 );\r
870 ASSERT_EFI_ERROR (Status);\r
871\r
872 //\r
873 // Close PCI I/O protocol that opened by child handle\r
874 //\r
875 Status = gBS->CloseProtocol (\r
876 Controller,\r
877 &gEfiPciIoProtocolGuid,\r
878 This->DriverBindingHandle,\r
879 Handle\r
880 );\r
881\r
882 //\r
883 // Uninstall protocols on child handle\r
884 //\r
885 if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
886 Status = gBS->UninstallMultipleProtocolInterfaces (\r
887 BiosVideoPrivate->Handle,\r
888 &gEfiDevicePathProtocolGuid,\r
889 BiosVideoPrivate->GopDevicePath,\r
890 &gEfiGraphicsOutputProtocolGuid,\r
891 &BiosVideoPrivate->GraphicsOutput,\r
892 &gEfiEdidDiscoveredProtocolGuid,\r
893 &BiosVideoPrivate->EdidDiscovered,\r
894 &gEfiEdidActiveProtocolGuid,\r
895 &BiosVideoPrivate->EdidActive,\r
896 NULL\r
897 );\r
898 }\r
899 if (!BiosVideoPrivate->ProduceGraphicsOutput) {\r
900 Status = gBS->UninstallMultipleProtocolInterfaces (\r
901 Controller,\r
902 &gEfiVgaMiniPortProtocolGuid,\r
903 &BiosVideoPrivate->VgaMiniPort,\r
904 NULL\r
905 );\r
906 }\r
907\r
908 if (EFI_ERROR (Status)) {\r
909 gBS->OpenProtocol (\r
910 Controller,\r
911 &gEfiPciIoProtocolGuid,\r
912 (VOID **) &PciIo,\r
913 This->DriverBindingHandle,\r
914 Handle,\r
915 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
916 );\r
917 return Status;\r
918 }\r
919\r
920 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) {\r
921 //\r
922 // Close EXIT_BOOT_SERIVES Event\r
923 //\r
924 gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent);\r
925 }\r
926\r
927 //\r
928 // Release all allocated resources\r
929 //\r
930 BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
931\r
932 return EFI_SUCCESS;\r
933}\r
934\r
935\r
936/**\r
937 Release resource for biso video instance.\r
938\r
939 @param BiosVideoPrivate Video child device private data structure\r
940\r
941**/\r
942VOID\r
943BiosVideoDeviceReleaseResource (\r
944 BIOS_VIDEO_DEV *BiosVideoPrivate\r
945 )\r
946{\r
947 if (BiosVideoPrivate == NULL) {\r
948 return ;\r
949 }\r
950\r
951 //\r
952 // Release all the resourses occupied by the BIOS_VIDEO_DEV\r
953 //\r
954\r
955 //\r
956 // Free VGA Frame Buffer\r
957 //\r
958 if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
959 FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
960 }\r
961 //\r
962 // Free VBE Frame Buffer\r
963 //\r
964 if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
965 FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
966 }\r
967 //\r
968 // Free line buffer\r
969 //\r
970 if (BiosVideoPrivate->LineBuffer != NULL) {\r
971 FreePool (BiosVideoPrivate->LineBuffer);\r
972 }\r
973 //\r
974 // Free mode data\r
975 //\r
976 if (BiosVideoPrivate->ModeData != NULL) {\r
977 FreePool (BiosVideoPrivate->ModeData);\r
978 }\r
979 //\r
980 // Free memory allocated below 1MB\r
981 //\r
982 if (BiosVideoPrivate->PagesBelow1MB != 0) {\r
983 gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);\r
984 }\r
985\r
986 if (BiosVideoPrivate->VbeSaveRestorePages != 0) {\r
987 gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);\r
988 }\r
989\r
990 //\r
991 // Free graphics output protocol occupied resource\r
992 //\r
993 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
994 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
995 FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
996 }\r
997 FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
998 }\r
999 //\r
1000 // Free EDID discovered protocol occupied resource\r
1001 //\r
1002 if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {\r
1003 FreePool (BiosVideoPrivate->EdidDiscovered.Edid);\r
1004 }\r
1005 //\r
1006 // Free EDID active protocol occupied resource\r
1007 //\r
1008 if (BiosVideoPrivate->EdidActive.Edid != NULL) {\r
1009 FreePool (BiosVideoPrivate->EdidActive.Edid);\r
1010 }\r
1011\r
1012 if (BiosVideoPrivate->GopDevicePath!= NULL) {\r
1013 FreePool (BiosVideoPrivate->GopDevicePath);\r
1014 }\r
1015\r
1016 FreePool (BiosVideoPrivate);\r
1017\r
1018 return ;\r
1019}\r
1020\r
1021\r
1022/**\r
1023 Generate a search key for a specified timing data.\r
1024\r
1025 @param EdidTiming Pointer to EDID timing\r
1026\r
1027 @return The 32 bit unique key for search.\r
1028\r
1029**/\r
1030UINT32\r
1031CalculateEdidKey (\r
1032 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
1033 )\r
1034{\r
1035 UINT32 Key;\r
1036\r
1037 //\r
1038 // Be sure no conflicts for all standard timing defined by VESA.\r
1039 //\r
1040 Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;\r
1041 return Key;\r
1042}\r
1043\r
1044\r
1045/**\r
1046 Parse the Established Timing and Standard Timing in EDID data block.\r
1047\r
1048 @param EdidBuffer Pointer to EDID data block\r
1049 @param ValidEdidTiming Valid EDID timing information\r
1050\r
1051 @retval TRUE The EDID data is valid.\r
1052 @retval FALSE The EDID data is invalid.\r
1053\r
1054**/\r
1055BOOLEAN\r
1056ParseEdidData (\r
1057 UINT8 *EdidBuffer,\r
1058 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming\r
1059 )\r
1060{\r
1061 UINT8 CheckSum;\r
1062 UINT32 Index;\r
1063 UINT32 ValidNumber;\r
1064 UINT32 TimingBits;\r
1065 UINT8 *BufferIndex;\r
1066 UINT16 HorizontalResolution;\r
1067 UINT16 VerticalResolution;\r
1068 UINT8 AspectRatio;\r
1069 UINT8 RefreshRate;\r
1070 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming;\r
1071 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;\r
1072\r
1073 EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;\r
1074\r
1075 //\r
1076 // Check the checksum of EDID data\r
1077 //\r
1078 CheckSum = 0;\r
1079 for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {\r
1080 CheckSum = (UINT8) (CheckSum + EdidBuffer[Index]);\r
1081 }\r
1082 if (CheckSum != 0) {\r
1083 return FALSE;\r
1084 }\r
1085\r
1086 ValidNumber = 0;\r
1087 gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);\r
1088\r
1089 if ((EdidDataBlock->EstablishedTimings[0] != 0) ||\r
1090 (EdidDataBlock->EstablishedTimings[1] != 0) ||\r
1091 (EdidDataBlock->EstablishedTimings[2] != 0)\r
1092 ) {\r
1093 //\r
1094 // Established timing data\r
1095 //\r
1096 TimingBits = EdidDataBlock->EstablishedTimings[0] |\r
1097 (EdidDataBlock->EstablishedTimings[1] << 8) |\r
1098 ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;\r
1099 for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {\r
1100 if ((TimingBits & 0x1) != 0) {\r
1101 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
1102 ValidNumber ++;\r
1103 }\r
1104 TimingBits = TimingBits >> 1;\r
1105 }\r
1106 } else {\r
1107 //\r
1108 // If no Established timing data, read the standard timing data\r
1109 //\r
1110 BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
1111 for (Index = 0; Index < 8; Index ++) {\r
1112 if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
1113 //\r
1114 // A valid Standard Timing\r
1115 //\r
1116 HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
1117 AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
1118 switch (AspectRatio) {\r
1119 case 0:\r
1120 VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
1121 break;\r
1122 case 1:\r
1123 VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
1124 break;\r
1125 case 2:\r
1126 VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
1127 break;\r
1128 case 3:\r
1129 VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
1130 break;\r
1131 default:\r
1132 VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
1133 break;\r
1134 }\r
1135 RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
1136 TempTiming.HorizontalResolution = HorizontalResolution;\r
1137 TempTiming.VerticalResolution = VerticalResolution;\r
1138 TempTiming.RefreshRate = RefreshRate;\r
1139 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
1140 ValidNumber ++;\r
1141 }\r
1142 BufferIndex += 2;\r
1143 }\r
1144 }\r
1145\r
1146 ValidEdidTiming->ValidNumber = ValidNumber;\r
1147 return TRUE;\r
1148}\r
1149\r
1150\r
1151/**\r
1152 Search a specified Timing in all the valid EDID timings.\r
1153\r
1154 @param ValidEdidTiming All valid EDID timing information.\r
1155 @param EdidTiming The Timing to search for.\r
1156\r
1157 @retval TRUE Found.\r
1158 @retval FALSE Not found.\r
1159\r
1160**/\r
1161BOOLEAN\r
1162SearchEdidTiming (\r
1163 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,\r
1164 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
1165 )\r
1166{\r
1167 UINT32 Index;\r
1168 UINT32 Key;\r
1169\r
1170 Key = CalculateEdidKey (EdidTiming);\r
1171\r
1172 for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {\r
1173 if (Key == ValidEdidTiming->Key[Index]) {\r
1174 return TRUE;\r
1175 }\r
1176 }\r
1177\r
1178 return FALSE;\r
1179}\r
1180\r
1181\r
1182/**\r
1183 Check for VBE device.\r
1184\r
1185 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
1186\r
1187 @retval EFI_SUCCESS VBE device found\r
1188\r
1189**/\r
1190EFI_STATUS\r
1191BiosVideoCheckForVbe (\r
1192 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
1193 )\r
1194{\r
1195 EFI_STATUS Status;\r
1196 EFI_IA32_REGISTER_SET Regs;\r
1197 UINT16 *ModeNumberPtr;\r
1198 BOOLEAN ModeFound;\r
1199 BOOLEAN EdidFound;\r
1200 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
1201 BIOS_VIDEO_MODE_DATA *CurrentModeData;\r
1202 UINTN PreferMode;\r
1203 UINTN ModeNumber;\r
1204 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;\r
1205 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;\r
1206 EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;\r
1207 UINT32 EdidAttributes;\r
1208 BOOLEAN EdidOverrideFound;\r
1209 UINTN EdidOverrideDataSize;\r
1210 UINT8 *EdidOverrideDataBlock;\r
1211 UINTN EdidActiveDataSize;\r
1212 UINT8 *EdidActiveDataBlock;\r
1213\r
1214 EdidFound = TRUE;\r
1215 EdidOverrideFound = FALSE;\r
1216 EdidOverrideDataBlock = NULL;\r
1217 EdidActiveDataSize = 0;\r
1218 EdidActiveDataBlock = NULL;\r
1219\r
1220 //\r
1221 // Allocate buffer under 1MB for VBE data structures\r
1222 //\r
1223 BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
1224 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +\r
1225 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
1226 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +\r
1227 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
1228 );\r
1229\r
1230 BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
1231\r
1232 Status = gBS->AllocatePages (\r
1233 AllocateMaxAddress,\r
1234 EfiBootServicesData,\r
1235 BiosVideoPrivate->NumberOfPagesBelow1MB,\r
1236 &BiosVideoPrivate->PagesBelow1MB\r
1237 );\r
1238 if (EFI_ERROR (Status)) {\r
1239 return Status;\r
1240 }\r
1241\r
1242 ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
1243 \r
1244 //\r
1245 // Fill in the VBE related data structures\r
1246 //\r
1247 BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
1248 BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
1249 BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
1250 BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);\r
1251 BiosVideoPrivate->VbeSaveRestorePages = 0;\r
1252 BiosVideoPrivate->VbeSaveRestoreBuffer = 0;\r
1253\r
1254 //\r
1255 // Test to see if the Video Adapter is compliant with VBE 3.0\r
1256 //\r
1257 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1258 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
1259 gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
1260 BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
1261 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1262 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1263\r
1264 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1265\r
1266 Status = EFI_DEVICE_ERROR;\r
1267\r
1268 //\r
1269 // See if the VESA call succeeded\r
1270 //\r
1271 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1272 return Status;\r
1273 }\r
1274 //\r
1275 // Check for 'VESA' signature\r
1276 //\r
1277 if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
1278 return Status;\r
1279 }\r
1280 //\r
1281 // Check to see if this is VBE 2.0 or higher\r
1282 //\r
1283 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
1284 return Status;\r
1285 }\r
1286\r
1287 EdidFound = FALSE;\r
1288 EdidAttributes = 0xff;\r
1289 EdidOverrideDataSize = 0;\r
1290\r
1291 //\r
1292 // Find EDID Override protocol firstly, this protocol is installed by platform if needed.\r
1293 //\r
1294 Status = gBS->LocateProtocol (\r
1295 &gEfiEdidOverrideProtocolGuid,\r
1296 NULL,\r
1297 (VOID **) &EdidOverride\r
1298 );\r
1299 if (!EFI_ERROR (Status)) {\r
1300 //\r
1301 // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow\r
1302 //\r
1303 EdidOverrideDataBlock = AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2));\r
1304 if (NULL == EdidOverrideDataBlock) {\r
1305 Status = EFI_OUT_OF_RESOURCES;\r
1306 goto Done;\r
1307 }\r
1308\r
1309 Status = EdidOverride->GetEdid (\r
1310 EdidOverride,\r
1311 BiosVideoPrivate->Handle,\r
1312 &EdidAttributes,\r
1313 &EdidOverrideDataSize,\r
1314 (UINT8 **) &EdidOverrideDataBlock\r
1315 );\r
1316 if (!EFI_ERROR (Status) &&\r
1317 EdidAttributes == 0 &&\r
1318 EdidOverrideDataSize != 0) {\r
1319 //\r
1320 // Succeeded to get EDID Override Data\r
1321 //\r
1322 EdidOverrideFound = TRUE;\r
1323 }\r
1324 }\r
1325\r
1326 if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {\r
1327 //\r
1328 // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,\r
1329 // read EDID information through INT10 call\r
1330 //\r
1331\r
1332 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1333 Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
1334 Regs.X.BX = 1;\r
1335 Regs.X.CX = 0;\r
1336 Regs.X.DX = 0;\r
1337 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1338 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1339\r
1340 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1341 //\r
1342 // See if the VESA call succeeded\r
1343 //\r
1344 if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1345 //\r
1346 // Set EDID Discovered Data\r
1347 //\r
1348 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1349 BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (\r
1350 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
1351 BiosVideoPrivate->VbeEdidDataBlock\r
1352 );\r
1353\r
1354 if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {\r
1355 Status = EFI_OUT_OF_RESOURCES;\r
1356 goto Done;\r
1357 }\r
1358\r
1359 EdidFound = TRUE;\r
1360 }\r
1361 }\r
1362\r
1363 if (EdidFound) {\r
1364 EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1365 EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;\r
1366 } else if (EdidOverrideFound) {\r
1367 EdidActiveDataSize = EdidOverrideDataSize;\r
1368 EdidActiveDataBlock = EdidOverrideDataBlock;\r
1369 EdidFound = TRUE;\r
1370 }\r
1371\r
1372 if (EdidFound) {\r
1373 //\r
1374 // Parse EDID data structure to retrieve modes supported by monitor\r
1375 //\r
1376 if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {\r
1377 //\r
1378 // Copy EDID Override Data to EDID Active Data\r
1379 //\r
1380 BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;\r
1381 BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (\r
1382 EdidActiveDataSize,\r
1383 EdidActiveDataBlock\r
1384 );\r
1385 if (NULL == BiosVideoPrivate->EdidActive.Edid) {\r
1386 Status = EFI_OUT_OF_RESOURCES;\r
1387 goto Done;\r
1388 }\r
1389 }\r
1390 } else {\r
1391 BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
1392 BiosVideoPrivate->EdidActive.Edid = NULL;\r
1393 EdidFound = FALSE;\r
1394 }\r
1395\r
1396 //\r
1397 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
1398 //\r
1399 ModeNumberPtr = (UINT16 *)\r
1400 (\r
1401 (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
1402 ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
1403 );\r
1404\r
1405 PreferMode = 0;\r
1406 ModeNumber = 0;\r
1407\r
1408 for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
1409 //\r
1410 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
1411 //\r
1412 if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
1413 continue;\r
1414 }\r
1415 //\r
1416 // Get the information about the mode\r
1417 //\r
1418 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1419 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
1420 Regs.X.CX = *ModeNumberPtr;\r
1421 gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
1422 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1423 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1424\r
1425 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1426\r
1427 //\r
1428 // See if the call succeeded. If it didn't, then try the next mode.\r
1429 //\r
1430 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1431 continue;\r
1432 }\r
1433 //\r
1434 // See if the mode supports color. If it doesn't then try the next mode.\r
1435 //\r
1436 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
1437 continue;\r
1438 }\r
1439 //\r
1440 // See if the mode supports graphics. If it doesn't then try the next mode.\r
1441 //\r
1442 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
1443 continue;\r
1444 }\r
1445 //\r
1446 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
1447 //\r
1448 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
1449 continue;\r
1450 }\r
1451 //\r
1452 // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
1453 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
1454 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
1455 //\r
1456 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
1457 continue;\r
1458 }\r
1459\r
1460 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
1461 continue;\r
1462 }\r
1463\r
1464 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
1465 continue;\r
1466 }\r
1467 //\r
1468 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
1469 //\r
1470 if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
1471 continue;\r
1472 }\r
1473\r
1474 if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
1475 //\r
1476 // EDID exist, check whether this mode match with any mode in EDID\r
1477 //\r
1478 Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1479 Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1480 if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {\r
1481 continue;\r
1482 }\r
1483 }\r
1484\r
1485 //\r
1486 // Select a reasonable mode to be set for current display mode\r
1487 //\r
1488 ModeFound = FALSE;\r
1489\r
1490 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
1491 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
1492 ) {\r
1493 ModeFound = TRUE;\r
1494 }\r
1495 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
1496 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
1497 ) {\r
1498 ModeFound = TRUE;\r
1499 PreferMode = ModeNumber;\r
1500 }\r
1501 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
1502 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
1503 ) {\r
1504 ModeFound = TRUE;\r
1505 }\r
1506\r
1507 if ((!EdidFound) && (!ModeFound)) {\r
1508 //\r
1509 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
1510 //\r
1511 continue;\r
1512 }\r
1513\r
1514 //\r
1515 // Add mode to the list of available modes\r
1516 //\r
1517 ModeNumber ++;\r
1518 ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
1519 ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)\r
1520 );\r
1521 if (NULL == ModeBuffer) {\r
1522 Status = EFI_OUT_OF_RESOURCES;\r
1523 goto Done;\r
1524 }\r
1525\r
1526 if (ModeNumber > 1) {\r
1527 CopyMem (\r
1528 ModeBuffer,\r
1529 BiosVideoPrivate->ModeData,\r
1530 (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
1531 );\r
1532 }\r
1533\r
1534 if (BiosVideoPrivate->ModeData != NULL) {\r
1535 FreePool (BiosVideoPrivate->ModeData);\r
1536 }\r
1537\r
1538 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
1539 CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
1540 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
1541 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
1542 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
1543 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
1544 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
1545 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
1546 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
1547 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
1548 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
1549 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
1550 } else {\r
1551 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
1552 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
1553 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
1554 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
1555 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
1556 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
1557 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
1558 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
1559 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
1560 }\r
1561\r
1562 CurrentModeData->PixelFormat = PixelBitMask;\r
1563 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
1564 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
1565 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
1566 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
1567 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
1568 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
1569 }\r
1570 }\r
1571\r
1572 CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
1573 CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
1574 CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
1575 CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
1576 CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
1577\r
1578 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
1579 CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1580 CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1581\r
1582 CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
1583\r
1584 BiosVideoPrivate->ModeData = ModeBuffer;\r
1585 }\r
1586 //\r
1587 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
1588 //\r
1589 if (ModeNumber == 0) {\r
1590 Status = EFI_DEVICE_ERROR;\r
1591 goto Done;\r
1592 }\r
1593\r
1594 //\r
1595 // Assign Gop's Blt function\r
1596 //\r
1597 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
1598\r
1599 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;\r
1600 //\r
1601 // Current mode is unknow till now, set it to an invalid mode.\r
1602 //\r
1603 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1604\r
1605 //\r
1606 // Find the best mode to initialize\r
1607 //\r
1608 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
1609 if (EFI_ERROR (Status)) {\r
1610 for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
1611 Status = BiosVideoGraphicsOutputSetMode (\r
1612 &BiosVideoPrivate->GraphicsOutput,\r
1613 (UINT32) PreferMode\r
1614 );\r
1615 if (!EFI_ERROR (Status)) {\r
1616 break;\r
1617 }\r
1618 }\r
1619 if (PreferMode == ModeNumber) {\r
1620 //\r
1621 // None mode is set successfully.\r
1622 //\r
1623 goto Done;\r
1624 }\r
1625 }\r
1626\r
1627Done:\r
1628 //\r
1629 // If there was an error, then free the mode structure\r
1630 //\r
1631 if (EFI_ERROR (Status)) {\r
1632 if (BiosVideoPrivate->ModeData != NULL) {\r
1633 FreePool (BiosVideoPrivate->ModeData);\r
1634 BiosVideoPrivate->ModeData = NULL;\r
1635 BiosVideoPrivate->MaxMode = 0;\r
1636 }\r
1637 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1638 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1639 FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1640 BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
1641 }\r
1642 FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1643 BiosVideoPrivate->GraphicsOutput.Mode= NULL;\r
1644 }\r
1645 if (EdidOverrideDataBlock != NULL) {\r
1646 FreePool (EdidOverrideDataBlock);\r
1647 }\r
1648 }\r
1649\r
1650 return Status;\r
1651}\r
1652\r
1653\r
1654/**\r
1655 Check for VGA device.\r
1656\r
1657 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
1658\r
1659 @retval EFI_SUCCESS Standard VGA device found\r
1660\r
1661**/\r
1662EFI_STATUS\r
1663BiosVideoCheckForVga (\r
1664 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
1665 )\r
1666{\r
1667 EFI_STATUS Status;\r
1668 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
1669\r
1670 Status = EFI_UNSUPPORTED;\r
1671\r
1672 //\r
1673 // Assign Gop's Blt function\r
1674 //\r
1675 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
1676\r
1677 //\r
1678 // Add mode to the list of available modes\r
1679 // caller should guarantee that Mode has been allocated.\r
1680 //\r
1681 ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);\r
1682 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
1683\r
1684 ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
1685 sizeof (BIOS_VIDEO_MODE_DATA)\r
1686 );\r
1687 if (NULL == ModeBuffer) {\r
1688 Status = EFI_OUT_OF_RESOURCES;\r
1689 goto Done;\r
1690 }\r
1691\r
1692 ModeBuffer->VbeModeNumber = 0x0012;\r
1693 ModeBuffer->BytesPerScanLine = 640;\r
1694 ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
1695 ModeBuffer->HorizontalResolution = 640;\r
1696 ModeBuffer->VerticalResolution = 480;\r
1697 ModeBuffer->PixelFormat = PixelBltOnly;\r
1698 ModeBuffer->BitsPerPixel = 8;\r
1699 ModeBuffer->ColorDepth = 32;\r
1700 ModeBuffer->RefreshRate = 60;\r
1701\r
1702 BiosVideoPrivate->ModeData = ModeBuffer;\r
1703\r
1704 //\r
1705 // Test to see if the Video Adapter support the 640x480 16 color mode\r
1706 //\r
1707 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1708 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
1709\r
1710Done:\r
1711 //\r
1712 // If there was an error, then free the mode structure\r
1713 //\r
1714 if (EFI_ERROR (Status)) {\r
1715 if (BiosVideoPrivate->ModeData != NULL) {\r
1716 FreePool (BiosVideoPrivate->ModeData);\r
1717 BiosVideoPrivate->ModeData = NULL;\r
1718 }\r
1719 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1720 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1721 FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1722 BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
1723 }\r
1724 FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1725 BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
1726 }\r
1727 }\r
1728 return Status;\r
1729}\r
1730\r
1731//\r
1732// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
1733//\r
1734\r
1735/**\r
1736 Graphics Output protocol interface to get video mode.\r
1737\r
1738 @param This Protocol instance pointer.\r
1739 @param ModeNumber The mode number to return information on.\r
1740 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
1741 buffer.\r
1742 @param Info Caller allocated buffer that returns information\r
1743 about ModeNumber.\r
1744\r
1745 @retval EFI_SUCCESS Mode information returned.\r
1746 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
1747 video mode.\r
1748 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
1749 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
1750\r
1751**/\r
1752EFI_STATUS\r
1753EFIAPI\r
1754BiosVideoGraphicsOutputQueryMode (\r
1755 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1756 IN UINT32 ModeNumber,\r
1757 OUT UINTN *SizeOfInfo,\r
1758 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
1759 )\r
1760{\r
1761 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1762 BIOS_VIDEO_MODE_DATA *ModeData;\r
1763\r
1764 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1765\r
1766 if (BiosVideoPrivate->HardwareNeedsStarting) {\r
1767 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1768 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1769 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
1770 BiosVideoPrivate->GopDevicePath\r
1771 );\r
1772 return EFI_NOT_STARTED;\r
1773 }\r
1774\r
1775 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
1776 return EFI_INVALID_PARAMETER;\r
1777 }\r
1778\r
1779 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
1780 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
1781 );\r
1782 if (NULL == *Info) {\r
1783 return EFI_OUT_OF_RESOURCES;\r
1784 }\r
1785\r
1786 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1787\r
1788 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1789 (*Info)->Version = 0;\r
1790 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
1791 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
1792 (*Info)->PixelFormat = ModeData->PixelFormat;\r
1793 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
1794\r
1795 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1796\r
1797 return EFI_SUCCESS;\r
1798}\r
1799\r
1800/**\r
1801 Worker function to set video mode.\r
1802\r
1803 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.\r
1804 @param ModeData The mode data to be set.\r
1805 @param DevicePath Pointer to Device Path Protocol.\r
1806\r
1807 @retval EFI_SUCCESS Graphics mode was changed.\r
1808 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
1809 request.\r
1810 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
1811\r
1812**/\r
1813EFI_STATUS\r
1814BiosVideoSetModeWorker (\r
1815 IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
1816 IN BIOS_VIDEO_MODE_DATA *ModeData,\r
1817 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1818 )\r
1819{\r
1820 EFI_STATUS Status;\r
1821 EFI_IA32_REGISTER_SET Regs;\r
1822\r
1823 if (BiosVideoPrivate->LineBuffer != NULL) {\r
1824 FreePool (BiosVideoPrivate->LineBuffer);\r
1825 }\r
1826\r
1827 if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
1828 FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
1829 }\r
1830\r
1831 if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
1832 FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
1833 }\r
1834\r
1835 BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (\r
1836 ModeData->BytesPerScanLine\r
1837 );\r
1838 if (NULL == BiosVideoPrivate->LineBuffer) {\r
1839 return EFI_OUT_OF_RESOURCES;\r
1840 }\r
1841 //\r
1842 // Clear all registers\r
1843 //\r
1844 ZeroMem (&Regs, sizeof (Regs));\r
1845\r
1846 if (ModeData->VbeModeNumber < 0x100) {\r
1847 //\r
1848 // Allocate a working buffer for BLT operations to the VGA frame buffer\r
1849 //\r
1850 BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);\r
1851 if (NULL == BiosVideoPrivate->VgaFrameBuffer) {\r
1852 return EFI_OUT_OF_RESOURCES;\r
1853 }\r
1854 //\r
1855 // Set VGA Mode\r
1856 //\r
1857 Regs.X.AX = ModeData->VbeModeNumber;\r
1858 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1859\r
1860 } else {\r
1861 //\r
1862 // Allocate a working buffer for BLT operations to the VBE frame buffer\r
1863 //\r
1864 BiosVideoPrivate->VbeFrameBuffer =\r
1865 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
1866 ModeData->BytesPerScanLine * ModeData->VerticalResolution\r
1867 );\r
1868 if (NULL == BiosVideoPrivate->VbeFrameBuffer) {\r
1869 return EFI_OUT_OF_RESOURCES;\r
1870 }\r
1871 //\r
1872 // Set VBE mode\r
1873 //\r
1874 Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
1875 Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
1876 ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));\r
1877 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1878 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1879 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1880\r
1881 //\r
1882 // Check to see if the call succeeded\r
1883 //\r
1884 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1885 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1886 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1887 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
1888 DevicePath\r
1889 );\r
1890 return EFI_DEVICE_ERROR;\r
1891 }\r
1892 //\r
1893 // Initialize the state of the VbeFrameBuffer\r
1894 //\r
1895 Status = BiosVideoPrivate->PciIo->Mem.Read (\r
1896 BiosVideoPrivate->PciIo,\r
1897 EfiPciIoWidthUint32,\r
1898 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1899 (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
1900 (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
1901 BiosVideoPrivate->VbeFrameBuffer\r
1902 );\r
1903 if (EFI_ERROR (Status)) {\r
1904 return Status;\r
1905 }\r
1906 }\r
1907\r
1908 return EFI_SUCCESS;\r
1909}\r
1910\r
1911/**\r
1912 Graphics Output protocol interface to set video mode.\r
1913\r
1914 @param This Protocol instance pointer.\r
1915 @param ModeNumber The mode number to be set.\r
1916\r
1917 @retval EFI_SUCCESS Graphics mode was changed.\r
1918 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
1919 request.\r
1920 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
1921\r
1922**/\r
1923EFI_STATUS\r
1924EFIAPI\r
1925BiosVideoGraphicsOutputSetMode (\r
1926 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1927 IN UINT32 ModeNumber\r
1928 )\r
1929{\r
1930 EFI_STATUS Status;\r
1931 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1932 BIOS_VIDEO_MODE_DATA *ModeData;\r
1933 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
1934\r
1935 if (This == NULL) {\r
1936 return EFI_INVALID_PARAMETER;\r
1937 }\r
1938\r
1939 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1940\r
1941 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1942\r
1943 if (ModeNumber >= This->Mode->MaxMode) {\r
1944 return EFI_UNSUPPORTED;\r
1945 }\r
1946 \r
1947 if (ModeNumber == This->Mode->Mode) {\r
1948 //\r
1949 // Clear screen to black\r
1950 // \r
1951 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
1952 BiosVideoGraphicsOutputVbeBlt (\r
1953 This,\r
1954 &Background,\r
1955 EfiBltVideoFill,\r
1956 0,\r
1957 0,\r
1958 0,\r
1959 0,\r
1960 ModeData->HorizontalResolution,\r
1961 ModeData->VerticalResolution,\r
1962 0\r
1963 );\r
1964 return EFI_SUCCESS;\r
1965 }\r
1966\r
1967 Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);\r
1968 if (EFI_ERROR (Status)) {\r
1969 return Status;\r
1970 }\r
1971\r
1972 This->Mode->Mode = ModeNumber;\r
1973 This->Mode->Info->Version = 0;\r
1974 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
1975 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
1976 This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
1977 CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));\r
1978 This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1979 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1980\r
1981 //\r
1982 // Frame BufferSize remain unchanged\r
1983 //\r
1984 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
1985 This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
1986\r
1987 BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
1988\r
1989 return EFI_SUCCESS;\r
1990}\r
1991\r
1992/**\r
1993 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1994\r
1995 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
1996 @param VbeBuffer The data to transfer to screen\r
1997 @param MemAddress Physical frame buffer base address\r
1998 @param DestinationX The X coordinate of the destination for BltOperation\r
1999 @param DestinationY The Y coordinate of the destination for BltOperation\r
2000 @param TotalBytes The total bytes of copy\r
2001 @param VbePixelWidth Bytes per pixel\r
2002 @param BytesPerScanLine Bytes per scan line\r
2003\r
2004**/\r
2005VOID\r
2006CopyVideoBuffer (\r
2007 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2008 IN UINT8 *VbeBuffer,\r
2009 IN VOID *MemAddress,\r
2010 IN UINTN DestinationX,\r
2011 IN UINTN DestinationY,\r
2012 IN UINTN TotalBytes,\r
2013 IN UINT32 VbePixelWidth,\r
2014 IN UINTN BytesPerScanLine\r
2015 )\r
2016{\r
2017 UINTN FrameBufferAddr;\r
2018 UINTN CopyBlockNum;\r
2019 UINTN RemainingBytes;\r
2020 UINTN UnalignedBytes;\r
2021 EFI_STATUS Status;\r
2022\r
2023 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
2024\r
2025 //\r
2026 // If TotalBytes is less than 4 bytes, only start byte copy.\r
2027 //\r
2028 if (TotalBytes < 4) {\r
2029 Status = PciIo->Mem.Write (\r
2030 PciIo,\r
2031 EfiPciIoWidthUint8,\r
2032 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2033 (UINT64) FrameBufferAddr,\r
2034 TotalBytes,\r
2035 VbeBuffer\r
2036 );\r
2037 ASSERT_EFI_ERROR (Status);\r
2038 return;\r
2039 }\r
2040\r
2041 //\r
2042 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
2043 //\r
2044 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
2045\r
2046 if (UnalignedBytes != 0) {\r
2047 Status = PciIo->Mem.Write (\r
2048 PciIo,\r
2049 EfiPciIoWidthUint8,\r
2050 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2051 (UINT64) FrameBufferAddr,\r
2052 UnalignedBytes,\r
2053 VbeBuffer\r
2054 );\r
2055 ASSERT_EFI_ERROR (Status);\r
2056 FrameBufferAddr += UnalignedBytes;\r
2057 VbeBuffer += UnalignedBytes;\r
2058 }\r
2059\r
2060 //\r
2061 // Calculate 4-byte block count and remaining bytes.\r
2062 //\r
2063 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
2064 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
2065\r
2066 //\r
2067 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
2068 //\r
2069 if (CopyBlockNum != 0) {\r
2070 Status = PciIo->Mem.Write (\r
2071 PciIo,\r
2072 EfiPciIoWidthUint32,\r
2073 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2074 (UINT64) FrameBufferAddr,\r
2075 CopyBlockNum,\r
2076 VbeBuffer\r
2077 );\r
2078 ASSERT_EFI_ERROR (Status);\r
2079 }\r
2080\r
2081 if (RemainingBytes != 0) {\r
2082 FrameBufferAddr += (CopyBlockNum << 2);\r
2083 VbeBuffer += (CopyBlockNum << 2);\r
2084 Status = PciIo->Mem.Write (\r
2085 PciIo,\r
2086 EfiPciIoWidthUint8,\r
2087 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2088 (UINT64) FrameBufferAddr,\r
2089 RemainingBytes,\r
2090 VbeBuffer\r
2091 );\r
2092 ASSERT_EFI_ERROR (Status);\r
2093 }\r
2094}\r
2095\r
2096/**\r
2097 Worker function to block transfer for VBE device.\r
2098\r
2099 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV\r
2100 @param BltBuffer The data to transfer to screen\r
2101 @param BltOperation The operation to perform\r
2102 @param SourceX The X coordinate of the source for BltOperation\r
2103 @param SourceY The Y coordinate of the source for BltOperation\r
2104 @param DestinationX The X coordinate of the destination for\r
2105 BltOperation\r
2106 @param DestinationY The Y coordinate of the destination for\r
2107 BltOperation\r
2108 @param Width The width of a rectangle in the blt rectangle in\r
2109 pixels\r
2110 @param Height The height of a rectangle in the blt rectangle in\r
2111 pixels\r
2112 @param Delta Not used for EfiBltVideoFill and\r
2113 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2114 used, the entire BltBuffer will be operated on. If\r
2115 a subrectangle of the BltBuffer is used, then\r
2116 Delta represents the number of bytes in a row of\r
2117 the BltBuffer.\r
2118 @param Mode Mode data.\r
2119\r
2120 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2121 @retval EFI_SUCCESS Blt operation success\r
2122\r
2123**/\r
2124EFI_STATUS\r
2125BiosVideoVbeBltWorker (\r
2126 IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
2127 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2128 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2129 IN UINTN SourceX,\r
2130 IN UINTN SourceY,\r
2131 IN UINTN DestinationX,\r
2132 IN UINTN DestinationY,\r
2133 IN UINTN Width,\r
2134 IN UINTN Height,\r
2135 IN UINTN Delta,\r
2136 IN BIOS_VIDEO_MODE_DATA *Mode\r
2137 )\r
2138{\r
2139 EFI_PCI_IO_PROTOCOL *PciIo;\r
2140 EFI_TPL OriginalTPL;\r
2141 UINTN DstY;\r
2142 UINTN SrcY;\r
2143 UINTN DstX;\r
2144 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
2145 VOID *MemAddress;\r
2146 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
2147 UINTN BytesPerScanLine;\r
2148 UINTN Index;\r
2149 UINT8 *VbeBuffer;\r
2150 UINT8 *VbeBuffer1;\r
2151 UINT8 *BltUint8;\r
2152 UINT32 VbePixelWidth;\r
2153 UINT32 Pixel;\r
2154 UINTN TotalBytes;\r
2155\r
2156 PciIo = BiosVideoPrivate->PciIo;\r
2157\r
2158 VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
2159 MemAddress = Mode->LinearFrameBuffer;\r
2160 BytesPerScanLine = Mode->BytesPerScanLine;\r
2161 VbePixelWidth = Mode->BitsPerPixel / 8;\r
2162 BltUint8 = (UINT8 *) BltBuffer;\r
2163 TotalBytes = Width * VbePixelWidth;\r
2164\r
2165 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
2166 return EFI_INVALID_PARAMETER;\r
2167 }\r
2168\r
2169 if (Width == 0 || Height == 0) {\r
2170 return EFI_INVALID_PARAMETER;\r
2171 }\r
2172 //\r
2173 // We need to fill the Virtual Screen buffer with the blt data.\r
2174 // The virtual screen is upside down, as the first row is the bootom row of\r
2175 // the image.\r
2176 //\r
2177 if (BltOperation == EfiBltVideoToBltBuffer) {\r
2178 //\r
2179 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2180 //\r
2181 if (SourceY + Height > Mode->VerticalResolution) {\r
2182 return EFI_INVALID_PARAMETER;\r
2183 }\r
2184\r
2185 if (SourceX + Width > Mode->HorizontalResolution) {\r
2186 return EFI_INVALID_PARAMETER;\r
2187 }\r
2188 } else {\r
2189 //\r
2190 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2191 //\r
2192 if (DestinationY + Height > Mode->VerticalResolution) {\r
2193 return EFI_INVALID_PARAMETER;\r
2194 }\r
2195\r
2196 if (DestinationX + Width > Mode->HorizontalResolution) {\r
2197 return EFI_INVALID_PARAMETER;\r
2198 }\r
2199 }\r
2200 //\r
2201 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2202 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2203 // the number of bytes in each row can be computed.\r
2204 //\r
2205 if (Delta == 0) {\r
2206 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
2207 }\r
2208 //\r
2209 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2210 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2211 // doing this operation.\r
2212 //\r
2213 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2214\r
2215 switch (BltOperation) {\r
2216 case EfiBltVideoToBltBuffer:\r
2217 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
2218 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
2219 //\r
2220 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
2221 //\r
2222 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
2223 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2224 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
2225 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
2226 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
2227 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
2228 Blt->Reserved = 0;\r
2229 Blt++;\r
2230 VbeBuffer += VbePixelWidth;\r
2231 }\r
2232\r
2233 }\r
2234 break;\r
2235\r
2236 case EfiBltVideoToVideo:\r
2237 for (Index = 0; Index < Height; Index++) {\r
2238 if (DestinationY <= SourceY) {\r
2239 SrcY = SourceY + Index;\r
2240 DstY = DestinationY + Index;\r
2241 } else {\r
2242 SrcY = SourceY + Height - Index - 1;\r
2243 DstY = DestinationY + Height - Index - 1;\r
2244 }\r
2245\r
2246 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
2247 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
2248\r
2249 gBS->CopyMem (\r
2250 VbeBuffer,\r
2251 VbeBuffer1,\r
2252 TotalBytes\r
2253 );\r
2254\r
2255 //\r
2256 // Update physical frame buffer.\r
2257 //\r
2258 CopyVideoBuffer (\r
2259 PciIo,\r
2260 VbeBuffer,\r
2261 MemAddress,\r
2262 DestinationX,\r
2263 DstY,\r
2264 TotalBytes,\r
2265 VbePixelWidth,\r
2266 BytesPerScanLine\r
2267 );\r
2268 }\r
2269 break;\r
2270\r
2271 case EfiBltVideoFill:\r
2272 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2273 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
2274 //\r
2275 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
2276 //\r
2277 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2278 (\r
2279 (Blt->Green & Mode->Green.Mask) <<\r
2280 Mode->Green.Position\r
2281 ) |\r
2282 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2283\r
2284 for (Index = 0; Index < Width; Index++) {\r
2285 gBS->CopyMem (\r
2286 VbeBuffer,\r
2287 &Pixel,\r
2288 VbePixelWidth\r
2289 );\r
2290 VbeBuffer += VbePixelWidth;\r
2291 }\r
2292\r
2293 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2294 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
2295 gBS->CopyMem (\r
2296 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
2297 VbeBuffer,\r
2298 TotalBytes\r
2299 );\r
2300 }\r
2301\r
2302 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
2303 //\r
2304 // Update physical frame buffer.\r
2305 //\r
2306 CopyVideoBuffer (\r
2307 PciIo,\r
2308 VbeBuffer,\r
2309 MemAddress,\r
2310 DestinationX,\r
2311 DstY,\r
2312 TotalBytes,\r
2313 VbePixelWidth,\r
2314 BytesPerScanLine\r
2315 );\r
2316 }\r
2317 break;\r
2318\r
2319 case EfiBltBufferToVideo:\r
2320 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
2321 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
2322 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2323 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2324 //\r
2325 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
2326 //\r
2327 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2328 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
2329 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2330 gBS->CopyMem (\r
2331 VbeBuffer,\r
2332 &Pixel,\r
2333 VbePixelWidth\r
2334 );\r
2335 Blt++;\r
2336 VbeBuffer += VbePixelWidth;\r
2337 }\r
2338\r
2339 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2340\r
2341 //\r
2342 // Update physical frame buffer.\r
2343 //\r
2344 CopyVideoBuffer (\r
2345 PciIo,\r
2346 VbeBuffer,\r
2347 MemAddress,\r
2348 DestinationX,\r
2349 DstY,\r
2350 TotalBytes,\r
2351 VbePixelWidth,\r
2352 BytesPerScanLine\r
2353 );\r
2354 }\r
2355 break;\r
2356\r
2357 default: ;\r
2358 }\r
2359\r
2360 gBS->RestoreTPL (OriginalTPL);\r
2361\r
2362 return EFI_SUCCESS;\r
2363}\r
2364\r
2365/**\r
2366 Graphics Output protocol instance to block transfer for VBE device.\r
2367\r
2368 @param This Pointer to Graphics Output protocol instance\r
2369 @param BltBuffer The data to transfer to screen\r
2370 @param BltOperation The operation to perform\r
2371 @param SourceX The X coordinate of the source for BltOperation\r
2372 @param SourceY The Y coordinate of the source for BltOperation\r
2373 @param DestinationX The X coordinate of the destination for\r
2374 BltOperation\r
2375 @param DestinationY The Y coordinate of the destination for\r
2376 BltOperation\r
2377 @param Width The width of a rectangle in the blt rectangle in\r
2378 pixels\r
2379 @param Height The height of a rectangle in the blt rectangle in\r
2380 pixels\r
2381 @param Delta Not used for EfiBltVideoFill and\r
2382 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2383 used, the entire BltBuffer will be operated on. If\r
2384 a subrectangle of the BltBuffer is used, then\r
2385 Delta represents the number of bytes in a row of\r
2386 the BltBuffer.\r
2387\r
2388 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2389 @retval EFI_SUCCESS Blt operation success\r
2390\r
2391**/\r
2392EFI_STATUS\r
2393EFIAPI\r
2394BiosVideoGraphicsOutputVbeBlt (\r
2395 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2396 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2397 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2398 IN UINTN SourceX,\r
2399 IN UINTN SourceY,\r
2400 IN UINTN DestinationX,\r
2401 IN UINTN DestinationY,\r
2402 IN UINTN Width,\r
2403 IN UINTN Height,\r
2404 IN UINTN Delta\r
2405 )\r
2406{\r
2407 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2408 BIOS_VIDEO_MODE_DATA *Mode;\r
2409\r
2410 if (This == NULL) {\r
2411 return EFI_INVALID_PARAMETER;\r
2412 }\r
2413\r
2414 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2415 Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
2416\r
2417 return BiosVideoVbeBltWorker (\r
2418 BiosVideoPrivate,\r
2419 BltBuffer,\r
2420 BltOperation,\r
2421 SourceX,\r
2422 SourceY,\r
2423 DestinationX,\r
2424 DestinationY,\r
2425 Width,\r
2426 Height,\r
2427 Delta,\r
2428 Mode\r
2429 );\r
2430}\r
2431\r
2432/**\r
2433 Write graphics controller registers.\r
2434\r
2435 @param PciIo Pointer to PciIo protocol instance of the\r
2436 controller\r
2437 @param Address Register address\r
2438 @param Data Data to be written to register\r
2439\r
2440 @return None\r
2441\r
2442**/\r
2443VOID\r
2444WriteGraphicsController (\r
2445 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2446 IN UINTN Address,\r
2447 IN UINTN Data\r
2448 )\r
2449{\r
2450 Address = Address | (Data << 8);\r
2451 PciIo->Io.Write (\r
2452 PciIo,\r
2453 EfiPciIoWidthUint16,\r
2454 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2455 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
2456 1,\r
2457 &Address\r
2458 );\r
2459}\r
2460\r
2461\r
2462/**\r
2463 Read the four bit plane of VGA frame buffer.\r
2464\r
2465 @param PciIo Pointer to PciIo protocol instance of the\r
2466 controller\r
2467 @param HardwareBuffer Hardware VGA frame buffer address\r
2468 @param MemoryBuffer Memory buffer address\r
2469 @param WidthInBytes Number of bytes in a line to read\r
2470 @param Height Height of the area to read\r
2471\r
2472 @return None\r
2473\r
2474**/\r
2475VOID\r
2476VgaReadBitPlanes (\r
2477 EFI_PCI_IO_PROTOCOL *PciIo,\r
2478 UINT8 *HardwareBuffer,\r
2479 UINT8 *MemoryBuffer,\r
2480 UINTN WidthInBytes,\r
2481 UINTN Height\r
2482 )\r
2483{\r
2484 UINTN BitPlane;\r
2485 UINTN Rows;\r
2486 UINTN FrameBufferOffset;\r
2487 UINT8 *Source;\r
2488 UINT8 *Destination;\r
2489\r
2490 //\r
2491 // Program the Mode Register Write mode 0, Read mode 0\r
2492 //\r
2493 WriteGraphicsController (\r
2494 PciIo,\r
2495 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2496 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
2497 );\r
2498\r
2499 for (BitPlane = 0, FrameBufferOffset = 0;\r
2500 BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
2501 BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
2502 ) {\r
2503 //\r
2504 // Program the Read Map Select Register to select the correct bit plane\r
2505 //\r
2506 WriteGraphicsController (\r
2507 PciIo,\r
2508 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
2509 BitPlane\r
2510 );\r
2511\r
2512 Source = HardwareBuffer;\r
2513 Destination = MemoryBuffer + FrameBufferOffset;\r
2514\r
2515 for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
2516 PciIo->Mem.Read (\r
2517 PciIo,\r
2518 EfiPciIoWidthUint8,\r
2519 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2520 (UINT64) (UINTN) Source,\r
2521 WidthInBytes,\r
2522 (VOID *) Destination\r
2523 );\r
2524 }\r
2525 }\r
2526}\r
2527\r
2528\r
2529/**\r
2530 Internal routine to convert VGA color to Grahpics Output color.\r
2531\r
2532 @param MemoryBuffer Buffer containing VGA color\r
2533 @param CoordinateX The X coordinate of pixel on screen\r
2534 @param CoordinateY The Y coordinate of pixel on screen\r
2535 @param BltBuffer Buffer to contain converted Grahpics Output color\r
2536\r
2537 @return None\r
2538\r
2539**/\r
2540VOID\r
2541VgaConvertToGraphicsOutputColor (\r
2542 UINT8 *MemoryBuffer,\r
2543 UINTN CoordinateX,\r
2544 UINTN CoordinateY,\r
2545 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2546 )\r
2547{\r
2548 UINTN Mask;\r
2549 UINTN Bit;\r
2550 UINTN Color;\r
2551\r
2552 MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));\r
2553 Mask = mVgaBitMaskTable[CoordinateX & 0x07];\r
2554 for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
2555 if ((*MemoryBuffer & Mask) != 0) {\r
2556 Color |= Bit;\r
2557 }\r
2558 }\r
2559\r
2560 *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
2561}\r
2562\r
2563/**\r
2564 Internal routine to convert Grahpics Output color to VGA color.\r
2565\r
2566 @param BltBuffer buffer containing Grahpics Output color\r
2567\r
2568 @return Converted VGA color\r
2569\r
2570**/\r
2571UINT8\r
2572VgaConvertColor (\r
2573 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2574 )\r
2575{\r
2576 UINT8 Color;\r
2577\r
2578 Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
2579 if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
2580 Color |= 0x08;\r
2581 }\r
2582\r
2583 return Color;\r
2584}\r
2585\r
2586\r
2587/**\r
2588 Grahpics Output protocol instance to block transfer for VGA device.\r
2589\r
2590 @param This Pointer to Grahpics Output protocol instance\r
2591 @param BltBuffer The data to transfer to screen\r
2592 @param BltOperation The operation to perform\r
2593 @param SourceX The X coordinate of the source for BltOperation\r
2594 @param SourceY The Y coordinate of the source for BltOperation\r
2595 @param DestinationX The X coordinate of the destination for\r
2596 BltOperation\r
2597 @param DestinationY The Y coordinate of the destination for\r
2598 BltOperation\r
2599 @param Width The width of a rectangle in the blt rectangle in\r
2600 pixels\r
2601 @param Height The height of a rectangle in the blt rectangle in\r
2602 pixels\r
2603 @param Delta Not used for EfiBltVideoFill and\r
2604 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2605 used, the entire BltBuffer will be operated on. If\r
2606 a subrectangle of the BltBuffer is used, then\r
2607 Delta represents the number of bytes in a row of\r
2608 the BltBuffer.\r
2609\r
2610 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2611 @retval EFI_SUCCESS Blt operation success\r
2612\r
2613**/\r
2614EFI_STATUS\r
2615EFIAPI\r
2616BiosVideoGraphicsOutputVgaBlt (\r
2617 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2618 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2619 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2620 IN UINTN SourceX,\r
2621 IN UINTN SourceY,\r
2622 IN UINTN DestinationX,\r
2623 IN UINTN DestinationY,\r
2624 IN UINTN Width,\r
2625 IN UINTN Height,\r
2626 IN UINTN Delta\r
2627 )\r
2628{\r
2629 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2630 EFI_TPL OriginalTPL;\r
2631 UINT8 *MemAddress;\r
2632 UINTN BytesPerScanLine;\r
2633 UINTN Bit;\r
2634 UINTN Index;\r
2635 UINTN Index1;\r
2636 UINTN StartAddress;\r
2637 UINTN Bytes;\r
2638 UINTN Offset;\r
2639 UINT8 LeftMask;\r
2640 UINT8 RightMask;\r
2641 UINTN Address;\r
2642 UINTN AddressFix;\r
2643 UINT8 *Address1;\r
2644 UINT8 *SourceAddress;\r
2645 UINT8 *DestinationAddress;\r
2646 EFI_PCI_IO_PROTOCOL *PciIo;\r
2647 UINT8 Data;\r
2648 UINT8 PixelColor;\r
2649 UINT8 *VgaFrameBuffer;\r
2650 UINTN SourceOffset;\r
2651 UINTN SourceWidth;\r
2652 UINTN Rows;\r
2653 UINTN Columns;\r
2654 UINTN CoordinateX;\r
2655 UINTN CoordinateY;\r
2656 UINTN CurrentMode;\r
2657\r
2658 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
2659 return EFI_INVALID_PARAMETER;\r
2660 }\r
2661\r
2662 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2663\r
2664 CurrentMode = This->Mode->Mode;\r
2665 PciIo = BiosVideoPrivate->PciIo;\r
2666 MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
2667 BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
2668 VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
2669\r
2670\r
2671 if (Width == 0 || Height == 0) {\r
2672 return EFI_INVALID_PARAMETER;\r
2673 }\r
2674 //\r
2675 // We need to fill the Virtual Screen buffer with the blt data.\r
2676 // The virtual screen is upside down, as the first row is the bootom row of\r
2677 // the image.\r
2678 //\r
2679 if (BltOperation == EfiBltVideoToBltBuffer) {\r
2680 //\r
2681 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2682 //\r
2683 if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
2684 return EFI_INVALID_PARAMETER;\r
2685 }\r
2686\r
2687 if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
2688 return EFI_INVALID_PARAMETER;\r
2689 }\r
2690 } else {\r
2691 //\r
2692 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2693 //\r
2694 if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
2695 return EFI_INVALID_PARAMETER;\r
2696 }\r
2697\r
2698 if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
2699 return EFI_INVALID_PARAMETER;\r
2700 }\r
2701 }\r
2702 //\r
2703 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2704 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2705 // the number of bytes in each row can be computed.\r
2706 //\r
2707 if (Delta == 0) {\r
2708 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
2709 }\r
2710 //\r
2711 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2712 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2713 // doing this operation.\r
2714 //\r
2715 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2716\r
2717 //\r
2718 // Compute some values we need for VGA\r
2719 //\r
2720 switch (BltOperation) {\r
2721 case EfiBltVideoToBltBuffer:\r
2722\r
2723 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2724 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2725\r
2726 //\r
2727 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2728 //\r
2729 VgaReadBitPlanes (\r
2730 PciIo,\r
2731 MemAddress + SourceOffset,\r
2732 VgaFrameBuffer + SourceOffset,\r
2733 SourceWidth,\r
2734 Height\r
2735 );\r
2736\r
2737 //\r
2738 // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
2739 //\r
2740 BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
2741 for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {\r
2742 for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {\r
2743 VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);\r
2744 }\r
2745\r
2746 BltBuffer -= Width;\r
2747 }\r
2748\r
2749 break;\r
2750\r
2751 case EfiBltVideoToVideo:\r
2752 //\r
2753 // Check for an aligned Video to Video operation\r
2754 //\r
2755 if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
2756 //\r
2757 // Program the Mode Register Write mode 1, Read mode 0\r
2758 //\r
2759 WriteGraphicsController (\r
2760 PciIo,\r
2761 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2762 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
2763 );\r
2764\r
2765 SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
2766 DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2767 Bytes = Width >> 3;\r
2768 for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
2769 PciIo->CopyMem (\r
2770 PciIo,\r
2771 EfiPciIoWidthUint8,\r
2772 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2773 (UINT64) (UINTN) (DestinationAddress + Offset),\r
2774 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2775 (UINT64) (UINTN) (SourceAddress + Offset),\r
2776 Bytes\r
2777 );\r
2778 }\r
2779 } else {\r
2780 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2781 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2782\r
2783 //\r
2784 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2785 //\r
2786 VgaReadBitPlanes (\r
2787 PciIo,\r
2788 MemAddress + SourceOffset,\r
2789 VgaFrameBuffer + SourceOffset,\r
2790 SourceWidth,\r
2791 Height\r
2792 );\r
2793 }\r
2794\r
2795 break;\r
2796\r
2797 case EfiBltVideoFill:\r
2798 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2799 Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
2800 LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
2801 RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
2802 if (Bytes == 0) {\r
2803 LeftMask = (UINT8) (LeftMask & RightMask);\r
2804 RightMask = 0;\r
2805 }\r
2806\r
2807 if (LeftMask == 0xff) {\r
2808 StartAddress--;\r
2809 Bytes++;\r
2810 LeftMask = 0;\r
2811 }\r
2812\r
2813 if (RightMask == 0xff) {\r
2814 Bytes++;\r
2815 RightMask = 0;\r
2816 }\r
2817\r
2818 PixelColor = VgaConvertColor (BltBuffer);\r
2819\r
2820 //\r
2821 // Program the Mode Register Write mode 2, Read mode 0\r
2822 //\r
2823 WriteGraphicsController (\r
2824 PciIo,\r
2825 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2826 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2827 );\r
2828\r
2829 //\r
2830 // Program the Data Rotate/Function Select Register to replace\r
2831 //\r
2832 WriteGraphicsController (\r
2833 PciIo,\r
2834 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2835 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2836 );\r
2837\r
2838 if (LeftMask != 0) {\r
2839 //\r
2840 // Program the BitMask register with the Left column mask\r
2841 //\r
2842 WriteGraphicsController (\r
2843 PciIo,\r
2844 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2845 LeftMask\r
2846 );\r
2847\r
2848 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2849 //\r
2850 // Read data from the bit planes into the latches\r
2851 //\r
2852 PciIo->Mem.Read (\r
2853 PciIo,\r
2854 EfiPciIoWidthUint8,\r
2855 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2856 (UINT64) (UINTN) Address,\r
2857 1,\r
2858 &Data\r
2859 );\r
2860 //\r
2861 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2862 //\r
2863 PciIo->Mem.Write (\r
2864 PciIo,\r
2865 EfiPciIoWidthUint8,\r
2866 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2867 (UINT64) (UINTN) Address,\r
2868 1,\r
2869 &PixelColor\r
2870 );\r
2871 }\r
2872 }\r
2873\r
2874 if (Bytes > 1) {\r
2875 //\r
2876 // Program the BitMask register with the middle column mask of 0xff\r
2877 //\r
2878 WriteGraphicsController (\r
2879 PciIo,\r
2880 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2881 0xff\r
2882 );\r
2883\r
2884 for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
2885 PciIo->Mem.Write (\r
2886 PciIo,\r
2887 EfiPciIoWidthFillUint8,\r
2888 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2889 (UINT64) (UINTN) Address,\r
2890 Bytes - 1,\r
2891 &PixelColor\r
2892 );\r
2893 }\r
2894 }\r
2895\r
2896 if (RightMask != 0) {\r
2897 //\r
2898 // Program the BitMask register with the Right column mask\r
2899 //\r
2900 WriteGraphicsController (\r
2901 PciIo,\r
2902 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2903 RightMask\r
2904 );\r
2905\r
2906 for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
2907 //\r
2908 // Read data from the bit planes into the latches\r
2909 //\r
2910 PciIo->Mem.Read (\r
2911 PciIo,\r
2912 EfiPciIoWidthUint8,\r
2913 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2914 (UINT64) (UINTN) Address,\r
2915 1,\r
2916 &Data\r
2917 );\r
2918 //\r
2919 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2920 //\r
2921 PciIo->Mem.Write (\r
2922 PciIo,\r
2923 EfiPciIoWidthUint8,\r
2924 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2925 (UINT64) (UINTN) Address,\r
2926 1,\r
2927 &PixelColor\r
2928 );\r
2929 }\r
2930 }\r
2931 break;\r
2932\r
2933 case EfiBltBufferToVideo:\r
2934 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2935 LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
2936\r
2937 //\r
2938 // Program the Mode Register Write mode 2, Read mode 0\r
2939 //\r
2940 WriteGraphicsController (\r
2941 PciIo,\r
2942 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2943 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2944 );\r
2945\r
2946 //\r
2947 // Program the Data Rotate/Function Select Register to replace\r
2948 //\r
2949 WriteGraphicsController (\r
2950 PciIo,\r
2951 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2952 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2953 );\r
2954\r
2955 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2956 for (Index1 = 0; Index1 < Width; Index1++) {\r
2957 BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
2958 }\r
2959 AddressFix = Address;\r
2960\r
2961 for (Bit = 0; Bit < 8; Bit++) {\r
2962 //\r
2963 // Program the BitMask register with the Left column mask\r
2964 //\r
2965 WriteGraphicsController (\r
2966 PciIo,\r
2967 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2968 LeftMask\r
2969 );\r
2970\r
2971 for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
2972 //\r
2973 // Read data from the bit planes into the latches\r
2974 //\r
2975 PciIo->Mem.Read (\r
2976 PciIo,\r
2977 EfiPciIoWidthUint8,\r
2978 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2979 (UINT64) (UINTN) Address1,\r
2980 1,\r
2981 &Data\r
2982 );\r
2983\r
2984 PciIo->Mem.Write (\r
2985 PciIo,\r
2986 EfiPciIoWidthUint8,\r
2987 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2988 (UINT64) (UINTN) Address1,\r
2989 1,\r
2990 &BiosVideoPrivate->LineBuffer[Index1]\r
2991 );\r
2992 }\r
2993\r
2994 LeftMask = (UINT8) (LeftMask >> 1);\r
2995 if (LeftMask == 0) {\r
2996 LeftMask = 0x80;\r
2997 AddressFix++;\r
2998 }\r
2999 }\r
3000 }\r
3001\r
3002 break;\r
3003\r
3004 default: ;\r
3005 }\r
3006\r
3007 gBS->RestoreTPL (OriginalTPL);\r
3008\r
3009 return EFI_SUCCESS;\r
3010}\r
3011\r
3012//\r
3013// VGA Mini Port Protocol Functions\r
3014//\r
3015\r
3016/**\r
3017 VgaMiniPort protocol interface to set mode.\r
3018\r
3019 @param This Pointer to VgaMiniPort protocol instance\r
3020 @param ModeNumber The index of the mode\r
3021\r
3022 @retval EFI_UNSUPPORTED The requested mode is not supported\r
3023 @retval EFI_SUCCESS The requested mode is set successfully\r
3024\r
3025**/\r
3026EFI_STATUS\r
3027EFIAPI\r
3028BiosVideoVgaMiniPortSetMode (\r
3029 IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
3030 IN UINTN ModeNumber\r
3031 )\r
3032{\r
3033 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
3034 EFI_IA32_REGISTER_SET Regs;\r
3035\r
3036 if (This == NULL) {\r
3037 return EFI_INVALID_PARAMETER;\r
3038 }\r
3039\r
3040 //\r
3041 // Make sure the ModeNumber is a valid value\r
3042 //\r
3043 if (ModeNumber >= This->MaxMode) {\r
3044 return EFI_UNSUPPORTED;\r
3045 }\r
3046 //\r
3047 // Get the device structure for this device\r
3048 //\r
3049 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
3050\r
3051 switch (ModeNumber) {\r
3052 case 0:\r
3053 //\r
3054 // Set the 80x25 Text VGA Mode\r
3055 //\r
3056 Regs.H.AH = 0x00;\r
3057 Regs.H.AL = 0x83;\r
3058 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3059\r
3060 Regs.H.AH = 0x11;\r
3061 Regs.H.AL = 0x14;\r
3062 Regs.H.BL = 0;\r
3063 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3064 break;\r
3065\r
3066 case 1:\r
3067 //\r
3068 // Set the 80x50 Text VGA Mode\r
3069 //\r
3070 Regs.H.AH = 0x00;\r
3071 Regs.H.AL = 0x83;\r
3072 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3073 Regs.H.AH = 0x11;\r
3074 Regs.H.AL = 0x12;\r
3075 Regs.H.BL = 0;\r
3076 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3077 break;\r
3078\r
3079 default:\r
3080 return EFI_UNSUPPORTED;\r
3081 }\r
3082\r
3083 return EFI_SUCCESS;\r
3084}\r
3085\r
3086/**\r
3087 Event handler for Exit Boot Service.\r
3088\r
3089 @param Event The event that be siganlled when exiting boot service.\r
3090 @param Context Pointer to instance of BIOS_VIDEO_DEV.\r
3091\r
3092**/\r
3093VOID\r
3094EFIAPI\r
3095BiosVideoNotifyExitBootServices (\r
3096 IN EFI_EVENT Event,\r
3097 IN VOID *Context\r
3098 )\r
3099{\r
3100 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
3101 EFI_IA32_REGISTER_SET Regs;\r
3102\r
3103 BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context;\r
3104\r
3105 //\r
3106 // Set the 80x25 Text VGA Mode\r
3107 //\r
3108 Regs.H.AH = 0x00;\r
3109 Regs.H.AL = 0x03;\r
3110 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3111\r
3112 Regs.H.AH = 0x00;\r
3113 Regs.H.AL = 0x83;\r
3114 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3115\r
3116 Regs.H.AH = 0x11;\r
3117 Regs.H.AL = 0x04;\r
3118 Regs.H.BL = 0;\r
3119 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3120}\r
3121\r
3122/**\r
3123 The user Entry Point for module UefiBiosVideo. The user code starts with this function.\r
3124\r
3125 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
3126 @param[in] SystemTable A pointer to the EFI System Table.\r
3127\r
3128 @retval EFI_SUCCESS The entry point is executed successfully.\r
3129 @retval other Some error occurs when executing this entry point.\r
3130\r
3131**/\r
3132EFI_STATUS\r
3133EFIAPI\r
3134BiosVideoEntryPoint(\r
3135 IN EFI_HANDLE ImageHandle,\r
3136 IN EFI_SYSTEM_TABLE *SystemTable\r
3137 )\r
3138{\r
3139 EFI_STATUS Status;\r
3140\r
3141 //\r
3142 // Install driver model protocol(s).\r
3143 //\r
3144 Status = EfiLibInstallDriverBindingComponentName2 (\r
3145 ImageHandle,\r
3146 SystemTable,\r
3147 &gBiosVideoDriverBinding,\r
3148 ImageHandle,\r
3149 &gBiosVideoComponentName,\r
3150 &gBiosVideoComponentName2\r
3151 );\r
3152 ASSERT_EFI_ERROR (Status);\r
3153\r
3154 //\r
3155 // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver\r
3156 //\r
3157 return gBS->InstallMultipleProtocolInterfaces (\r
3158 &ImageHandle,\r
3159 &gEfiLegacyBiosGuid,\r
3160 NULL,\r
3161 NULL\r
3162 );\r
3163}\r
3164\r