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