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