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