]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/BiosVideo.c
Currently restoring PCI attributes are put in child uninstall logic, if one child...
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / BiosThunk / VideoDxe / BiosVideo.c
CommitLineData
bcecde14 1/** @file\r
2 ConsoleOut Routines that speak VGA.\r
3\r
eca7d271 4Copyright (c) 2007 - 2012, 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
201 DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
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
1132 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);\r
1133 ValidNumber ++;\r
1134 }\r
1135 TimingBits = TimingBits >> 1;\r
1136 }\r
1137 } else {\r
1138 //\r
1139 // If no Established timing data, read the standard timing data\r
1140 //\r
1141 BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];\r
1142 for (Index = 0; Index < 8; Index ++) {\r
1143 if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){\r
1144 //\r
1145 // A valid Standard Timing\r
1146 //\r
1147 HorizontalResolution = (UINT16) (BufferIndex[0] * 8 + 248);\r
1148 AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
1149 switch (AspectRatio) {\r
1150 case 0:\r
1151 VerticalResolution = (UINT16) (HorizontalResolution / 16 * 10);\r
1152 break;\r
1153 case 1:\r
1154 VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
1155 break;\r
1156 case 2:\r
1157 VerticalResolution = (UINT16) (HorizontalResolution / 5 * 4);\r
1158 break;\r
1159 case 3:\r
1160 VerticalResolution = (UINT16) (HorizontalResolution / 16 * 9);\r
1161 break;\r
1162 default:\r
1163 VerticalResolution = (UINT16) (HorizontalResolution / 4 * 3);\r
1164 break;\r
1165 }\r
1166 RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
1167 TempTiming.HorizontalResolution = HorizontalResolution;\r
1168 TempTiming.VerticalResolution = VerticalResolution;\r
1169 TempTiming.RefreshRate = RefreshRate;\r
1170 ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);\r
1171 ValidNumber ++;\r
1172 }\r
1173 BufferIndex += 2;\r
1174 }\r
1175 }\r
1176\r
1177 ValidEdidTiming->ValidNumber = ValidNumber;\r
1178 return TRUE;\r
1179}\r
1180\r
1181\r
1182/**\r
1183 Search a specified Timing in all the valid EDID timings.\r
1184\r
1185 @param ValidEdidTiming All valid EDID timing information.\r
1186 @param EdidTiming The Timing to search for.\r
1187\r
1188 @retval TRUE Found.\r
1189 @retval FALSE Not found.\r
1190\r
1191**/\r
1192BOOLEAN\r
1193SearchEdidTiming (\r
1194 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,\r
1195 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
1196 )\r
1197{\r
1198 UINT32 Index;\r
1199 UINT32 Key;\r
1200\r
1201 Key = CalculateEdidKey (EdidTiming);\r
1202\r
1203 for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {\r
1204 if (Key == ValidEdidTiming->Key[Index]) {\r
1205 return TRUE;\r
1206 }\r
1207 }\r
1208\r
1209 return FALSE;\r
1210}\r
1211\r
eca7d271 1212/**\r
1213 Check if all video child handles have been uninstalled.\r
1214\r
1215 @param Controller Video controller handle\r
1216\r
1217 @return TRUE Child handles exist.\r
1218 @return FALSE All video child handles have been uninstalled.\r
1219\r
1220**/\r
1221BOOLEAN\r
1222HasChildHandle (\r
1223 IN EFI_HANDLE Controller\r
1224 )\r
1225{\r
1226 UINTN Index;\r
1227 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
1228 UINTN EntryCount;\r
1229 BOOLEAN HasChild;\r
1230 EFI_STATUS Status;\r
1231\r
1232 EntryCount = 0;\r
1233 HasChild = FALSE;\r
1234 Status = gBS->OpenProtocolInformation (\r
1235 Controller,\r
1236 &gEfiPciIoProtocolGuid,\r
1237 &OpenInfoBuffer,\r
1238 &EntryCount\r
1239 );\r
1240 for (Index = 0; Index < EntryCount; Index++) {\r
1241 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
1242 HasChild = TRUE;\r
1243 }\r
1244 }\r
1245 \r
1246 return HasChild;\r
1247}\r
bcecde14 1248\r
1249/**\r
1250 Check for VBE device.\r
1251\r
1252 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
1253\r
1254 @retval EFI_SUCCESS VBE device found\r
1255\r
1256**/\r
1257EFI_STATUS\r
1258BiosVideoCheckForVbe (\r
1259 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
1260 )\r
1261{\r
1262 EFI_STATUS Status;\r
1263 EFI_IA32_REGISTER_SET Regs;\r
1264 UINT16 *ModeNumberPtr;\r
1265 BOOLEAN ModeFound;\r
1266 BOOLEAN EdidFound;\r
1267 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
1268 BIOS_VIDEO_MODE_DATA *CurrentModeData;\r
1269 UINTN PreferMode;\r
1270 UINTN ModeNumber;\r
1271 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing;\r
1272 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;\r
1273 EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride;\r
1274 UINT32 EdidAttributes;\r
1275 BOOLEAN EdidOverrideFound;\r
1276 UINTN EdidOverrideDataSize;\r
1277 UINT8 *EdidOverrideDataBlock;\r
1278 UINTN EdidActiveDataSize;\r
1279 UINT8 *EdidActiveDataBlock;\r
675253b4 1280 UINT32 HighestHorizontalResolution;\r
1281 UINT32 HighestVerticalResolution;\r
1282 UINTN HighestResolutionMode;\r
bcecde14 1283\r
1284 EdidFound = TRUE;\r
1285 EdidOverrideFound = FALSE;\r
1286 EdidOverrideDataBlock = NULL;\r
1287 EdidActiveDataSize = 0;\r
1288 EdidActiveDataBlock = NULL;\r
675253b4 1289 HighestHorizontalResolution = 0;\r
1290 HighestVerticalResolution = 0;\r
1291 HighestResolutionMode = 0;\r
bcecde14 1292\r
1293 //\r
1294 // Allocate buffer under 1MB for VBE data structures\r
1295 //\r
1296 BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
1297 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +\r
1298 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +\r
1299 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +\r
1300 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)\r
1301 );\r
1302\r
1303 BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;\r
1304\r
1305 Status = gBS->AllocatePages (\r
1306 AllocateMaxAddress,\r
1307 EfiBootServicesData,\r
1308 BiosVideoPrivate->NumberOfPagesBelow1MB,\r
1309 &BiosVideoPrivate->PagesBelow1MB\r
1310 );\r
1311 if (EFI_ERROR (Status)) {\r
1312 return Status;\r
1313 }\r
1314\r
1315 ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
1316 \r
1317 //\r
1318 // Fill in the VBE related data structures\r
1319 //\r
1320 BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);\r
1321 BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);\r
1322 BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);\r
1323 BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);\r
1324 BiosVideoPrivate->VbeSaveRestorePages = 0;\r
1325 BiosVideoPrivate->VbeSaveRestoreBuffer = 0;\r
1326\r
1327 //\r
1328 // Test to see if the Video Adapter is compliant with VBE 3.0\r
1329 //\r
1330 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1331 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
1332 gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
1333 BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
1334 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1335 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1336\r
1337 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1338\r
1339 Status = EFI_DEVICE_ERROR;\r
1340\r
1341 //\r
1342 // See if the VESA call succeeded\r
1343 //\r
1344 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1345 return Status;\r
1346 }\r
1347 //\r
1348 // Check for 'VESA' signature\r
1349 //\r
1350 if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
1351 return Status;\r
1352 }\r
1353 //\r
1354 // Check to see if this is VBE 2.0 or higher\r
1355 //\r
1356 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
1357 return Status;\r
1358 }\r
1359\r
1360 EdidFound = FALSE;\r
1361 EdidAttributes = 0xff;\r
1362 EdidOverrideDataSize = 0;\r
1363\r
1364 //\r
1365 // Find EDID Override protocol firstly, this protocol is installed by platform if needed.\r
1366 //\r
1367 Status = gBS->LocateProtocol (\r
1368 &gEfiEdidOverrideProtocolGuid,\r
1369 NULL,\r
1370 (VOID **) &EdidOverride\r
1371 );\r
1372 if (!EFI_ERROR (Status)) {\r
1373 //\r
1374 // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow\r
1375 //\r
1376 EdidOverrideDataBlock = AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE * 2));\r
1377 if (NULL == EdidOverrideDataBlock) {\r
1378 Status = EFI_OUT_OF_RESOURCES;\r
1379 goto Done;\r
1380 }\r
1381\r
1382 Status = EdidOverride->GetEdid (\r
1383 EdidOverride,\r
1384 BiosVideoPrivate->Handle,\r
1385 &EdidAttributes,\r
1386 &EdidOverrideDataSize,\r
1387 (UINT8 **) &EdidOverrideDataBlock\r
1388 );\r
1389 if (!EFI_ERROR (Status) &&\r
1390 EdidAttributes == 0 &&\r
1391 EdidOverrideDataSize != 0) {\r
1392 //\r
1393 // Succeeded to get EDID Override Data\r
1394 //\r
1395 EdidOverrideFound = TRUE;\r
1396 }\r
1397 }\r
1398\r
1399 if (!EdidOverrideFound || EdidAttributes == EFI_EDID_OVERRIDE_DONT_OVERRIDE) {\r
1400 //\r
1401 // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,\r
1402 // read EDID information through INT10 call\r
1403 //\r
1404\r
1405 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1406 Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
1407 Regs.X.BX = 1;\r
1408 Regs.X.CX = 0;\r
1409 Regs.X.DX = 0;\r
1410 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1411 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1412\r
1413 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1414 //\r
1415 // See if the VESA call succeeded\r
1416 //\r
1417 if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1418 //\r
1419 // Set EDID Discovered Data\r
1420 //\r
1421 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1422 BiosVideoPrivate->EdidDiscovered.Edid = (UINT8 *) AllocateCopyPool (\r
1423 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
1424 BiosVideoPrivate->VbeEdidDataBlock\r
1425 );\r
1426\r
1427 if (NULL == BiosVideoPrivate->EdidDiscovered.Edid) {\r
1428 Status = EFI_OUT_OF_RESOURCES;\r
1429 goto Done;\r
1430 }\r
1431\r
1432 EdidFound = TRUE;\r
1433 }\r
1434 }\r
1435\r
1436 if (EdidFound) {\r
1437 EdidActiveDataSize = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1438 EdidActiveDataBlock = BiosVideoPrivate->EdidDiscovered.Edid;\r
1439 } else if (EdidOverrideFound) {\r
1440 EdidActiveDataSize = EdidOverrideDataSize;\r
1441 EdidActiveDataBlock = EdidOverrideDataBlock;\r
1442 EdidFound = TRUE;\r
1443 }\r
1444\r
1445 if (EdidFound) {\r
1446 //\r
1447 // Parse EDID data structure to retrieve modes supported by monitor\r
1448 //\r
1449 if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) {\r
1450 //\r
1451 // Copy EDID Override Data to EDID Active Data\r
1452 //\r
1453 BiosVideoPrivate->EdidActive.SizeOfEdid = (UINT32) EdidActiveDataSize;\r
1454 BiosVideoPrivate->EdidActive.Edid = (UINT8 *) AllocateCopyPool (\r
1455 EdidActiveDataSize,\r
1456 EdidActiveDataBlock\r
1457 );\r
1458 if (NULL == BiosVideoPrivate->EdidActive.Edid) {\r
1459 Status = EFI_OUT_OF_RESOURCES;\r
1460 goto Done;\r
1461 }\r
1462 }\r
1463 } else {\r
1464 BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
1465 BiosVideoPrivate->EdidActive.Edid = NULL;\r
1466 EdidFound = FALSE;\r
1467 }\r
1468\r
1469 //\r
1470 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
1471 //\r
1472 ModeNumberPtr = (UINT16 *)\r
1473 (\r
1474 (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
1475 ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
1476 );\r
1477\r
1478 PreferMode = 0;\r
1479 ModeNumber = 0;\r
1480\r
1481 for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
1482 //\r
1483 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
1484 //\r
1485 if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
1486 continue;\r
1487 }\r
1488 //\r
1489 // Get the information about the mode\r
1490 //\r
1491 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1492 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
1493 Regs.X.CX = *ModeNumberPtr;\r
1494 gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
1495 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1496 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1497\r
1498 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1499\r
1500 //\r
1501 // See if the call succeeded. If it didn't, then try the next mode.\r
1502 //\r
1503 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1504 continue;\r
1505 }\r
1506 //\r
1507 // See if the mode supports color. If it doesn't then try the next mode.\r
1508 //\r
1509 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
1510 continue;\r
1511 }\r
1512 //\r
1513 // See if the mode supports graphics. If it doesn't then try the next mode.\r
1514 //\r
1515 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
1516 continue;\r
1517 }\r
1518 //\r
1519 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
1520 //\r
1521 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
1522 continue;\r
1523 }\r
1524 //\r
1525 // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
1526 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
1527 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
1528 //\r
1529 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
1530 continue;\r
1531 }\r
1532\r
1533 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
1534 continue;\r
1535 }\r
1536\r
1537 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
1538 continue;\r
1539 }\r
1540 //\r
1541 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
1542 //\r
1543 if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
1544 continue;\r
1545 }\r
1546\r
1547 if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
1548 //\r
1549 // EDID exist, check whether this mode match with any mode in EDID\r
1550 //\r
1551 Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1552 Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1553 if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) {\r
1554 continue;\r
1555 }\r
1556 }\r
1557\r
1558 //\r
1559 // Select a reasonable mode to be set for current display mode\r
1560 //\r
1561 ModeFound = FALSE;\r
1562\r
1563 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
1564 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
1565 ) {\r
1566 ModeFound = TRUE;\r
1567 }\r
1568 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
1569 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
1570 ) {\r
1571 ModeFound = TRUE;\r
1572 PreferMode = ModeNumber;\r
1573 }\r
1574 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
1575 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
1576 ) {\r
1577 ModeFound = TRUE;\r
1578 }\r
1579\r
1580 if ((!EdidFound) && (!ModeFound)) {\r
1581 //\r
1582 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
1583 //\r
1584 continue;\r
1585 }\r
1586\r
675253b4 1587 //\r
1588 // Record the highest resolution mode to set later\r
1589 //\r
1590 if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution >= HighestHorizontalResolution) &&\r
1591 (BiosVideoPrivate->VbeModeInformationBlock->YResolution >= HighestVerticalResolution)) {\r
1592 HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1593 HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1594 HighestResolutionMode = ModeNumber;\r
1595 }\r
1596\r
bcecde14 1597 //\r
1598 // Add mode to the list of available modes\r
1599 //\r
1600 ModeNumber ++;\r
1601 ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
1602 ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA)\r
1603 );\r
1604 if (NULL == ModeBuffer) {\r
1605 Status = EFI_OUT_OF_RESOURCES;\r
1606 goto Done;\r
1607 }\r
1608\r
1609 if (ModeNumber > 1) {\r
1610 CopyMem (\r
1611 ModeBuffer,\r
1612 BiosVideoPrivate->ModeData,\r
1613 (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
1614 );\r
1615 }\r
1616\r
1617 if (BiosVideoPrivate->ModeData != NULL) {\r
1618 FreePool (BiosVideoPrivate->ModeData);\r
1619 }\r
1620\r
1621 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
1622 CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
1623 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
1624 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
1625 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
1626 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
1627 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
1628 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
1629 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
1630 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
1631 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
1632 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
1633 } else {\r
1634 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
1635 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
1636 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
1637 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
1638 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
1639 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
1640 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
1641 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
1642 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
1643 }\r
1644\r
1645 CurrentModeData->PixelFormat = PixelBitMask;\r
1646 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
1647 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
1648 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
1649 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
1650 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
1651 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
1652 }\r
1653 }\r
1654\r
1655 CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
1656 CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
1657 CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
1658 CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
1659 CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
1660\r
1661 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
1662 CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1663 CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1664\r
1665 CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
1666\r
1667 BiosVideoPrivate->ModeData = ModeBuffer;\r
1668 }\r
1669 //\r
1670 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
1671 //\r
1672 if (ModeNumber == 0) {\r
1673 Status = EFI_DEVICE_ERROR;\r
1674 goto Done;\r
1675 }\r
1676\r
1677 //\r
1678 // Assign Gop's Blt function\r
1679 //\r
1680 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
1681\r
1682 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = (UINT32) ModeNumber;\r
1683 //\r
1684 // Current mode is unknow till now, set it to an invalid mode.\r
1685 //\r
1686 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1687\r
1688 //\r
1689 // Find the best mode to initialize\r
1690 //\r
675253b4 1691 if ((PcdGet32 (PcdVideoHorizontalResolution) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution) == 0x0)) {\r
1692 DEBUG_CODE (\r
1693 BIOS_VIDEO_MODE_DATA *ModeData;\r
1694 ModeData = &BiosVideoPrivate->ModeData[HighestResolutionMode];\r
1695 DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n",\r
1696 ModeData->HorizontalResolution, ModeData->VerticalResolution));\r
1697 );\r
1698 PreferMode = HighestResolutionMode;\r
1699 }\r
bcecde14 1700 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
1701 if (EFI_ERROR (Status)) {\r
1702 for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
1703 Status = BiosVideoGraphicsOutputSetMode (\r
1704 &BiosVideoPrivate->GraphicsOutput,\r
1705 (UINT32) PreferMode\r
1706 );\r
1707 if (!EFI_ERROR (Status)) {\r
1708 break;\r
1709 }\r
1710 }\r
1711 if (PreferMode == ModeNumber) {\r
1712 //\r
1713 // None mode is set successfully.\r
1714 //\r
1715 goto Done;\r
1716 }\r
1717 }\r
1718\r
1719Done:\r
1720 //\r
1721 // If there was an error, then free the mode structure\r
1722 //\r
1723 if (EFI_ERROR (Status)) {\r
1724 if (BiosVideoPrivate->ModeData != NULL) {\r
1725 FreePool (BiosVideoPrivate->ModeData);\r
1726 BiosVideoPrivate->ModeData = NULL;\r
1727 BiosVideoPrivate->MaxMode = 0;\r
1728 }\r
bcecde14 1729 if (EdidOverrideDataBlock != NULL) {\r
1730 FreePool (EdidOverrideDataBlock);\r
1731 }\r
1732 }\r
1733\r
1734 return Status;\r
1735}\r
1736\r
1737\r
1738/**\r
1739 Check for VGA device.\r
1740\r
1741 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure\r
1742\r
1743 @retval EFI_SUCCESS Standard VGA device found\r
1744\r
1745**/\r
1746EFI_STATUS\r
1747BiosVideoCheckForVga (\r
1748 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
1749 )\r
1750{\r
1751 EFI_STATUS Status;\r
1752 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
1753\r
1754 Status = EFI_UNSUPPORTED;\r
1755\r
1756 //\r
1757 // Assign Gop's Blt function\r
1758 //\r
1759 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
1760\r
1761 //\r
1762 // Add mode to the list of available modes\r
1763 // caller should guarantee that Mode has been allocated.\r
1764 //\r
1765 ASSERT (BiosVideoPrivate->GraphicsOutput.Mode != NULL);\r
1766 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
1767\r
1768 ModeBuffer = (BIOS_VIDEO_MODE_DATA *) AllocatePool (\r
1769 sizeof (BIOS_VIDEO_MODE_DATA)\r
1770 );\r
1771 if (NULL == ModeBuffer) {\r
1772 Status = EFI_OUT_OF_RESOURCES;\r
1773 goto Done;\r
1774 }\r
1775\r
1776 ModeBuffer->VbeModeNumber = 0x0012;\r
1777 ModeBuffer->BytesPerScanLine = 640;\r
1778 ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
1779 ModeBuffer->HorizontalResolution = 640;\r
1780 ModeBuffer->VerticalResolution = 480;\r
1781 ModeBuffer->PixelFormat = PixelBltOnly;\r
1782 ModeBuffer->BitsPerPixel = 8;\r
1783 ModeBuffer->ColorDepth = 32;\r
1784 ModeBuffer->RefreshRate = 60;\r
1785\r
1786 BiosVideoPrivate->ModeData = ModeBuffer;\r
1787\r
1788 //\r
1789 // Test to see if the Video Adapter support the 640x480 16 color mode\r
1790 //\r
1791 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1792 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
1793\r
1794Done:\r
1795 //\r
1796 // If there was an error, then free the mode structure\r
1797 //\r
1798 if (EFI_ERROR (Status)) {\r
1799 if (BiosVideoPrivate->ModeData != NULL) {\r
1800 FreePool (BiosVideoPrivate->ModeData);\r
1801 BiosVideoPrivate->ModeData = NULL;\r
1802 }\r
1803 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1804 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1805 FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1806 BiosVideoPrivate->GraphicsOutput.Mode->Info = NULL;\r
1807 }\r
1808 FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1809 BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
1810 }\r
1811 }\r
1812 return Status;\r
1813}\r
1814\r
1815//\r
1816// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
1817//\r
1818\r
1819/**\r
1820 Graphics Output protocol interface to get video mode.\r
1821\r
1822 @param This Protocol instance pointer.\r
1823 @param ModeNumber The mode number to return information on.\r
1824 @param SizeOfInfo A pointer to the size, in bytes, of the Info\r
1825 buffer.\r
1826 @param Info Caller allocated buffer that returns information\r
1827 about ModeNumber.\r
1828\r
1829 @retval EFI_SUCCESS Mode information returned.\r
1830 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the\r
1831 video mode.\r
1832 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
1833 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
1834\r
1835**/\r
1836EFI_STATUS\r
1837EFIAPI\r
1838BiosVideoGraphicsOutputQueryMode (\r
1839 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1840 IN UINT32 ModeNumber,\r
1841 OUT UINTN *SizeOfInfo,\r
1842 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
1843 )\r
1844{\r
1845 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1846 BIOS_VIDEO_MODE_DATA *ModeData;\r
1847\r
1848 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1849\r
1850 if (BiosVideoPrivate->HardwareNeedsStarting) {\r
1851 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1852 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1853 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
1854 BiosVideoPrivate->GopDevicePath\r
1855 );\r
1856 return EFI_NOT_STARTED;\r
1857 }\r
1858\r
1859 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
1860 return EFI_INVALID_PARAMETER;\r
1861 }\r
1862\r
1863 *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (\r
1864 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)\r
1865 );\r
1866 if (NULL == *Info) {\r
1867 return EFI_OUT_OF_RESOURCES;\r
1868 }\r
1869\r
1870 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1871\r
1872 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1873 (*Info)->Version = 0;\r
1874 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
1875 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
1876 (*Info)->PixelFormat = ModeData->PixelFormat;\r
1877 CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));\r
1878\r
1879 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1880\r
1881 return EFI_SUCCESS;\r
1882}\r
1883\r
1884/**\r
1885 Worker function to set video mode.\r
1886\r
1887 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.\r
1888 @param ModeData The mode data to be set.\r
1889 @param DevicePath Pointer to Device Path Protocol.\r
1890\r
1891 @retval EFI_SUCCESS Graphics mode was changed.\r
1892 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
1893 request.\r
1894 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
1895\r
1896**/\r
1897EFI_STATUS\r
1898BiosVideoSetModeWorker (\r
1899 IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
1900 IN BIOS_VIDEO_MODE_DATA *ModeData,\r
1901 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1902 )\r
1903{\r
1904 EFI_STATUS Status;\r
1905 EFI_IA32_REGISTER_SET Regs;\r
1906\r
1907 if (BiosVideoPrivate->LineBuffer != NULL) {\r
1908 FreePool (BiosVideoPrivate->LineBuffer);\r
1909 }\r
1910\r
1911 if (BiosVideoPrivate->VgaFrameBuffer != NULL) {\r
1912 FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
1913 }\r
1914\r
1915 if (BiosVideoPrivate->VbeFrameBuffer != NULL) {\r
1916 FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
1917 }\r
1918\r
1919 BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (\r
1920 ModeData->BytesPerScanLine\r
1921 );\r
1922 if (NULL == BiosVideoPrivate->LineBuffer) {\r
1923 return EFI_OUT_OF_RESOURCES;\r
1924 }\r
1925 //\r
1926 // Clear all registers\r
1927 //\r
1928 ZeroMem (&Regs, sizeof (Regs));\r
1929\r
1930 if (ModeData->VbeModeNumber < 0x100) {\r
1931 //\r
1932 // Allocate a working buffer for BLT operations to the VGA frame buffer\r
1933 //\r
1934 BiosVideoPrivate->VgaFrameBuffer = (UINT8 *) AllocatePool (4 * 480 * 80);\r
1935 if (NULL == BiosVideoPrivate->VgaFrameBuffer) {\r
1936 return EFI_OUT_OF_RESOURCES;\r
1937 }\r
1938 //\r
1939 // Set VGA Mode\r
1940 //\r
1941 Regs.X.AX = ModeData->VbeModeNumber;\r
1942 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1943\r
1944 } else {\r
1945 //\r
1946 // Allocate a working buffer for BLT operations to the VBE frame buffer\r
1947 //\r
1948 BiosVideoPrivate->VbeFrameBuffer =\r
1949 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (\r
1950 ModeData->BytesPerScanLine * ModeData->VerticalResolution\r
1951 );\r
1952 if (NULL == BiosVideoPrivate->VbeFrameBuffer) {\r
1953 return EFI_OUT_OF_RESOURCES;\r
1954 }\r
1955 //\r
1956 // Set VBE mode\r
1957 //\r
1958 Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
1959 Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
1960 ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK));\r
1961 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1962 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1963 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
1964\r
1965 //\r
1966 // Check to see if the call succeeded\r
1967 //\r
1968 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1969 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1970 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1971 EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR,\r
1972 DevicePath\r
1973 );\r
1974 return EFI_DEVICE_ERROR;\r
1975 }\r
1976 //\r
1977 // Initialize the state of the VbeFrameBuffer\r
1978 //\r
1979 Status = BiosVideoPrivate->PciIo->Mem.Read (\r
1980 BiosVideoPrivate->PciIo,\r
1981 EfiPciIoWidthUint32,\r
1982 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1983 (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
1984 (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
1985 BiosVideoPrivate->VbeFrameBuffer\r
1986 );\r
1987 if (EFI_ERROR (Status)) {\r
1988 return Status;\r
1989 }\r
1990 }\r
1991\r
1992 return EFI_SUCCESS;\r
1993}\r
1994\r
1995/**\r
1996 Graphics Output protocol interface to set video mode.\r
1997\r
1998 @param This Protocol instance pointer.\r
1999 @param ModeNumber The mode number to be set.\r
2000\r
2001 @retval EFI_SUCCESS Graphics mode was changed.\r
2002 @retval EFI_DEVICE_ERROR The device had an error and could not complete the\r
2003 request.\r
2004 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
2005\r
2006**/\r
2007EFI_STATUS\r
2008EFIAPI\r
2009BiosVideoGraphicsOutputSetMode (\r
2010 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
2011 IN UINT32 ModeNumber\r
2012 )\r
2013{\r
2014 EFI_STATUS Status;\r
2015 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2016 BIOS_VIDEO_MODE_DATA *ModeData;\r
2017 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
2018\r
2019 if (This == NULL) {\r
2020 return EFI_INVALID_PARAMETER;\r
2021 }\r
2022\r
2023 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2024\r
2025 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
2026\r
2027 if (ModeNumber >= This->Mode->MaxMode) {\r
2028 return EFI_UNSUPPORTED;\r
2029 }\r
2030 \r
2031 if (ModeNumber == This->Mode->Mode) {\r
2032 //\r
2033 // Clear screen to black\r
2034 // \r
2035 ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
2036 BiosVideoGraphicsOutputVbeBlt (\r
2037 This,\r
2038 &Background,\r
2039 EfiBltVideoFill,\r
2040 0,\r
2041 0,\r
2042 0,\r
2043 0,\r
2044 ModeData->HorizontalResolution,\r
2045 ModeData->VerticalResolution,\r
2046 0\r
2047 );\r
2048 return EFI_SUCCESS;\r
2049 }\r
2050\r
2051 Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->GopDevicePath);\r
2052 if (EFI_ERROR (Status)) {\r
2053 return Status;\r
2054 }\r
2055\r
2056 This->Mode->Mode = ModeNumber;\r
2057 This->Mode->Info->Version = 0;\r
2058 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
2059 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
2060 This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
2061 CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask), sizeof (ModeData->PixelBitMask));\r
2062 This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
2063 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
2064\r
2065 //\r
2066 // Frame BufferSize remain unchanged\r
2067 //\r
2068 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData->LinearFrameBuffer;\r
2069 This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
2070\r
2071 BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
2072\r
2073 return EFI_SUCCESS;\r
2074}\r
2075\r
2076/**\r
2077 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
2078\r
2079 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL\r
2080 @param VbeBuffer The data to transfer to screen\r
2081 @param MemAddress Physical frame buffer base address\r
2082 @param DestinationX The X coordinate of the destination for BltOperation\r
2083 @param DestinationY The Y coordinate of the destination for BltOperation\r
2084 @param TotalBytes The total bytes of copy\r
2085 @param VbePixelWidth Bytes per pixel\r
2086 @param BytesPerScanLine Bytes per scan line\r
2087\r
2088**/\r
2089VOID\r
2090CopyVideoBuffer (\r
2091 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2092 IN UINT8 *VbeBuffer,\r
2093 IN VOID *MemAddress,\r
2094 IN UINTN DestinationX,\r
2095 IN UINTN DestinationY,\r
2096 IN UINTN TotalBytes,\r
2097 IN UINT32 VbePixelWidth,\r
2098 IN UINTN BytesPerScanLine\r
2099 )\r
2100{\r
2101 UINTN FrameBufferAddr;\r
2102 UINTN CopyBlockNum;\r
2103 UINTN RemainingBytes;\r
2104 UINTN UnalignedBytes;\r
2105 EFI_STATUS Status;\r
2106\r
2107 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
2108\r
2109 //\r
2110 // If TotalBytes is less than 4 bytes, only start byte copy.\r
2111 //\r
2112 if (TotalBytes < 4) {\r
2113 Status = PciIo->Mem.Write (\r
2114 PciIo,\r
2115 EfiPciIoWidthUint8,\r
2116 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2117 (UINT64) FrameBufferAddr,\r
2118 TotalBytes,\r
2119 VbeBuffer\r
2120 );\r
2121 ASSERT_EFI_ERROR (Status);\r
2122 return;\r
2123 }\r
2124\r
2125 //\r
2126 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
2127 //\r
2128 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
2129\r
2130 if (UnalignedBytes != 0) {\r
2131 Status = PciIo->Mem.Write (\r
2132 PciIo,\r
2133 EfiPciIoWidthUint8,\r
2134 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2135 (UINT64) FrameBufferAddr,\r
2136 UnalignedBytes,\r
2137 VbeBuffer\r
2138 );\r
2139 ASSERT_EFI_ERROR (Status);\r
2140 FrameBufferAddr += UnalignedBytes;\r
2141 VbeBuffer += UnalignedBytes;\r
2142 }\r
2143\r
2144 //\r
2145 // Calculate 4-byte block count and remaining bytes.\r
2146 //\r
2147 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
2148 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
2149\r
2150 //\r
2151 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
2152 //\r
2153 if (CopyBlockNum != 0) {\r
2154 Status = PciIo->Mem.Write (\r
2155 PciIo,\r
2156 EfiPciIoWidthUint32,\r
2157 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2158 (UINT64) FrameBufferAddr,\r
2159 CopyBlockNum,\r
2160 VbeBuffer\r
2161 );\r
2162 ASSERT_EFI_ERROR (Status);\r
2163 }\r
2164\r
2165 if (RemainingBytes != 0) {\r
2166 FrameBufferAddr += (CopyBlockNum << 2);\r
2167 VbeBuffer += (CopyBlockNum << 2);\r
2168 Status = PciIo->Mem.Write (\r
2169 PciIo,\r
2170 EfiPciIoWidthUint8,\r
2171 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2172 (UINT64) FrameBufferAddr,\r
2173 RemainingBytes,\r
2174 VbeBuffer\r
2175 );\r
2176 ASSERT_EFI_ERROR (Status);\r
2177 }\r
2178}\r
2179\r
2180/**\r
2181 Worker function to block transfer for VBE device.\r
2182\r
2183 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV\r
2184 @param BltBuffer The data to transfer to screen\r
2185 @param BltOperation The operation to perform\r
2186 @param SourceX The X coordinate of the source for BltOperation\r
2187 @param SourceY The Y coordinate of the source for BltOperation\r
2188 @param DestinationX The X coordinate of the destination for\r
2189 BltOperation\r
2190 @param DestinationY The Y coordinate of the destination for\r
2191 BltOperation\r
2192 @param Width The width of a rectangle in the blt rectangle in\r
2193 pixels\r
2194 @param Height The height of a rectangle in the blt rectangle in\r
2195 pixels\r
2196 @param Delta Not used for EfiBltVideoFill and\r
2197 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2198 used, the entire BltBuffer will be operated on. If\r
2199 a subrectangle of the BltBuffer is used, then\r
2200 Delta represents the number of bytes in a row of\r
2201 the BltBuffer.\r
2202 @param Mode Mode data.\r
2203\r
2204 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2205 @retval EFI_SUCCESS Blt operation success\r
2206\r
2207**/\r
2208EFI_STATUS\r
2209BiosVideoVbeBltWorker (\r
2210 IN BIOS_VIDEO_DEV *BiosVideoPrivate,\r
2211 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2212 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2213 IN UINTN SourceX,\r
2214 IN UINTN SourceY,\r
2215 IN UINTN DestinationX,\r
2216 IN UINTN DestinationY,\r
2217 IN UINTN Width,\r
2218 IN UINTN Height,\r
2219 IN UINTN Delta,\r
2220 IN BIOS_VIDEO_MODE_DATA *Mode\r
2221 )\r
2222{\r
2223 EFI_PCI_IO_PROTOCOL *PciIo;\r
2224 EFI_TPL OriginalTPL;\r
2225 UINTN DstY;\r
2226 UINTN SrcY;\r
2227 UINTN DstX;\r
2228 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
2229 VOID *MemAddress;\r
2230 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
2231 UINTN BytesPerScanLine;\r
2232 UINTN Index;\r
2233 UINT8 *VbeBuffer;\r
2234 UINT8 *VbeBuffer1;\r
2235 UINT8 *BltUint8;\r
2236 UINT32 VbePixelWidth;\r
2237 UINT32 Pixel;\r
2238 UINTN TotalBytes;\r
2239\r
2240 PciIo = BiosVideoPrivate->PciIo;\r
2241\r
2242 VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
2243 MemAddress = Mode->LinearFrameBuffer;\r
2244 BytesPerScanLine = Mode->BytesPerScanLine;\r
2245 VbePixelWidth = Mode->BitsPerPixel / 8;\r
2246 BltUint8 = (UINT8 *) BltBuffer;\r
2247 TotalBytes = Width * VbePixelWidth;\r
2248\r
2249 if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
2250 return EFI_INVALID_PARAMETER;\r
2251 }\r
2252\r
2253 if (Width == 0 || Height == 0) {\r
2254 return EFI_INVALID_PARAMETER;\r
2255 }\r
2256 //\r
2257 // We need to fill the Virtual Screen buffer with the blt data.\r
2258 // The virtual screen is upside down, as the first row is the bootom row of\r
2259 // the image.\r
2260 //\r
2261 if (BltOperation == EfiBltVideoToBltBuffer) {\r
2262 //\r
2263 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2264 //\r
2265 if (SourceY + Height > Mode->VerticalResolution) {\r
2266 return EFI_INVALID_PARAMETER;\r
2267 }\r
2268\r
2269 if (SourceX + Width > Mode->HorizontalResolution) {\r
2270 return EFI_INVALID_PARAMETER;\r
2271 }\r
2272 } else {\r
2273 //\r
2274 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2275 //\r
2276 if (DestinationY + Height > Mode->VerticalResolution) {\r
2277 return EFI_INVALID_PARAMETER;\r
2278 }\r
2279\r
2280 if (DestinationX + Width > Mode->HorizontalResolution) {\r
2281 return EFI_INVALID_PARAMETER;\r
2282 }\r
2283 }\r
2284 //\r
2285 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2286 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2287 // the number of bytes in each row can be computed.\r
2288 //\r
2289 if (Delta == 0) {\r
2290 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
2291 }\r
2292 //\r
2293 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2294 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2295 // doing this operation.\r
2296 //\r
2297 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2298\r
2299 switch (BltOperation) {\r
2300 case EfiBltVideoToBltBuffer:\r
2301 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
2302 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
2303 //\r
2304 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
2305 //\r
2306 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
2307 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2308 Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;\r
2309 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
2310 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
2311 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
2312 Blt->Reserved = 0;\r
2313 Blt++;\r
2314 VbeBuffer += VbePixelWidth;\r
2315 }\r
2316\r
2317 }\r
2318 break;\r
2319\r
2320 case EfiBltVideoToVideo:\r
2321 for (Index = 0; Index < Height; Index++) {\r
2322 if (DestinationY <= SourceY) {\r
2323 SrcY = SourceY + Index;\r
2324 DstY = DestinationY + Index;\r
2325 } else {\r
2326 SrcY = SourceY + Height - Index - 1;\r
2327 DstY = DestinationY + Height - Index - 1;\r
2328 }\r
2329\r
2330 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
2331 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
2332\r
2333 gBS->CopyMem (\r
2334 VbeBuffer,\r
2335 VbeBuffer1,\r
2336 TotalBytes\r
2337 );\r
2338\r
2339 //\r
2340 // Update physical frame buffer.\r
2341 //\r
2342 CopyVideoBuffer (\r
2343 PciIo,\r
2344 VbeBuffer,\r
2345 MemAddress,\r
2346 DestinationX,\r
2347 DstY,\r
2348 TotalBytes,\r
2349 VbePixelWidth,\r
2350 BytesPerScanLine\r
2351 );\r
2352 }\r
2353 break;\r
2354\r
2355 case EfiBltVideoFill:\r
2356 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2357 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
2358 //\r
2359 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
2360 //\r
2361 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2362 (\r
2363 (Blt->Green & Mode->Green.Mask) <<\r
2364 Mode->Green.Position\r
2365 ) |\r
2366 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2367\r
2368 for (Index = 0; Index < Width; Index++) {\r
2369 gBS->CopyMem (\r
2370 VbeBuffer,\r
2371 &Pixel,\r
2372 VbePixelWidth\r
2373 );\r
2374 VbeBuffer += VbePixelWidth;\r
2375 }\r
2376\r
2377 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2378 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
2379 gBS->CopyMem (\r
2380 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
2381 VbeBuffer,\r
2382 TotalBytes\r
2383 );\r
2384 }\r
2385\r
2386 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
2387 //\r
2388 // Update physical frame buffer.\r
2389 //\r
2390 CopyVideoBuffer (\r
2391 PciIo,\r
2392 VbeBuffer,\r
2393 MemAddress,\r
2394 DestinationX,\r
2395 DstY,\r
2396 TotalBytes,\r
2397 VbePixelWidth,\r
2398 BytesPerScanLine\r
2399 );\r
2400 }\r
2401 break;\r
2402\r
2403 case EfiBltBufferToVideo:\r
2404 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
2405 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
2406 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2407 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2408 //\r
2409 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
2410 //\r
2411 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2412 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
2413 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2414 gBS->CopyMem (\r
2415 VbeBuffer,\r
2416 &Pixel,\r
2417 VbePixelWidth\r
2418 );\r
2419 Blt++;\r
2420 VbeBuffer += VbePixelWidth;\r
2421 }\r
2422\r
2423 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2424\r
2425 //\r
2426 // Update physical frame buffer.\r
2427 //\r
2428 CopyVideoBuffer (\r
2429 PciIo,\r
2430 VbeBuffer,\r
2431 MemAddress,\r
2432 DestinationX,\r
2433 DstY,\r
2434 TotalBytes,\r
2435 VbePixelWidth,\r
2436 BytesPerScanLine\r
2437 );\r
2438 }\r
2439 break;\r
2440\r
2441 default: ;\r
2442 }\r
2443\r
2444 gBS->RestoreTPL (OriginalTPL);\r
2445\r
2446 return EFI_SUCCESS;\r
2447}\r
2448\r
2449/**\r
2450 Graphics Output protocol instance to block transfer for VBE device.\r
2451\r
2452 @param This Pointer to Graphics Output protocol instance\r
2453 @param BltBuffer The data to transfer to screen\r
2454 @param BltOperation The operation to perform\r
2455 @param SourceX The X coordinate of the source for BltOperation\r
2456 @param SourceY The Y coordinate of the source for BltOperation\r
2457 @param DestinationX The X coordinate of the destination for\r
2458 BltOperation\r
2459 @param DestinationY The Y coordinate of the destination for\r
2460 BltOperation\r
2461 @param Width The width of a rectangle in the blt rectangle in\r
2462 pixels\r
2463 @param Height The height of a rectangle in the blt rectangle in\r
2464 pixels\r
2465 @param Delta Not used for EfiBltVideoFill and\r
2466 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2467 used, the entire BltBuffer will be operated on. If\r
2468 a subrectangle of the BltBuffer is used, then\r
2469 Delta represents the number of bytes in a row of\r
2470 the BltBuffer.\r
2471\r
2472 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2473 @retval EFI_SUCCESS Blt operation success\r
2474\r
2475**/\r
2476EFI_STATUS\r
2477EFIAPI\r
2478BiosVideoGraphicsOutputVbeBlt (\r
2479 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2480 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2481 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2482 IN UINTN SourceX,\r
2483 IN UINTN SourceY,\r
2484 IN UINTN DestinationX,\r
2485 IN UINTN DestinationY,\r
2486 IN UINTN Width,\r
2487 IN UINTN Height,\r
2488 IN UINTN Delta\r
2489 )\r
2490{\r
2491 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2492 BIOS_VIDEO_MODE_DATA *Mode;\r
2493\r
2494 if (This == NULL) {\r
2495 return EFI_INVALID_PARAMETER;\r
2496 }\r
2497\r
2498 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2499 Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
2500\r
2501 return BiosVideoVbeBltWorker (\r
2502 BiosVideoPrivate,\r
2503 BltBuffer,\r
2504 BltOperation,\r
2505 SourceX,\r
2506 SourceY,\r
2507 DestinationX,\r
2508 DestinationY,\r
2509 Width,\r
2510 Height,\r
2511 Delta,\r
2512 Mode\r
2513 );\r
2514}\r
2515\r
2516/**\r
2517 Write graphics controller registers.\r
2518\r
2519 @param PciIo Pointer to PciIo protocol instance of the\r
2520 controller\r
2521 @param Address Register address\r
2522 @param Data Data to be written to register\r
2523\r
2524 @return None\r
2525\r
2526**/\r
2527VOID\r
2528WriteGraphicsController (\r
2529 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2530 IN UINTN Address,\r
2531 IN UINTN Data\r
2532 )\r
2533{\r
2534 Address = Address | (Data << 8);\r
2535 PciIo->Io.Write (\r
2536 PciIo,\r
2537 EfiPciIoWidthUint16,\r
2538 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2539 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
2540 1,\r
2541 &Address\r
2542 );\r
2543}\r
2544\r
2545\r
2546/**\r
2547 Read the four bit plane of VGA frame buffer.\r
2548\r
2549 @param PciIo Pointer to PciIo protocol instance of the\r
2550 controller\r
2551 @param HardwareBuffer Hardware VGA frame buffer address\r
2552 @param MemoryBuffer Memory buffer address\r
2553 @param WidthInBytes Number of bytes in a line to read\r
2554 @param Height Height of the area to read\r
2555\r
2556 @return None\r
2557\r
2558**/\r
2559VOID\r
2560VgaReadBitPlanes (\r
2561 EFI_PCI_IO_PROTOCOL *PciIo,\r
2562 UINT8 *HardwareBuffer,\r
2563 UINT8 *MemoryBuffer,\r
2564 UINTN WidthInBytes,\r
2565 UINTN Height\r
2566 )\r
2567{\r
2568 UINTN BitPlane;\r
2569 UINTN Rows;\r
2570 UINTN FrameBufferOffset;\r
2571 UINT8 *Source;\r
2572 UINT8 *Destination;\r
2573\r
2574 //\r
2575 // Program the Mode Register Write mode 0, Read mode 0\r
2576 //\r
2577 WriteGraphicsController (\r
2578 PciIo,\r
2579 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2580 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
2581 );\r
2582\r
2583 for (BitPlane = 0, FrameBufferOffset = 0;\r
2584 BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
2585 BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
2586 ) {\r
2587 //\r
2588 // Program the Read Map Select Register to select the correct bit plane\r
2589 //\r
2590 WriteGraphicsController (\r
2591 PciIo,\r
2592 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
2593 BitPlane\r
2594 );\r
2595\r
2596 Source = HardwareBuffer;\r
2597 Destination = MemoryBuffer + FrameBufferOffset;\r
2598\r
2599 for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
2600 PciIo->Mem.Read (\r
2601 PciIo,\r
2602 EfiPciIoWidthUint8,\r
2603 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2604 (UINT64) (UINTN) Source,\r
2605 WidthInBytes,\r
2606 (VOID *) Destination\r
2607 );\r
2608 }\r
2609 }\r
2610}\r
2611\r
2612\r
2613/**\r
2614 Internal routine to convert VGA color to Grahpics Output color.\r
2615\r
2616 @param MemoryBuffer Buffer containing VGA color\r
2617 @param CoordinateX The X coordinate of pixel on screen\r
2618 @param CoordinateY The Y coordinate of pixel on screen\r
2619 @param BltBuffer Buffer to contain converted Grahpics Output color\r
2620\r
2621 @return None\r
2622\r
2623**/\r
2624VOID\r
2625VgaConvertToGraphicsOutputColor (\r
2626 UINT8 *MemoryBuffer,\r
2627 UINTN CoordinateX,\r
2628 UINTN CoordinateY,\r
2629 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2630 )\r
2631{\r
2632 UINTN Mask;\r
2633 UINTN Bit;\r
2634 UINTN Color;\r
2635\r
2636 MemoryBuffer += ((CoordinateY << 6) + (CoordinateY << 4) + (CoordinateX >> 3));\r
2637 Mask = mVgaBitMaskTable[CoordinateX & 0x07];\r
2638 for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
2639 if ((*MemoryBuffer & Mask) != 0) {\r
2640 Color |= Bit;\r
2641 }\r
2642 }\r
2643\r
2644 *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
2645}\r
2646\r
2647/**\r
2648 Internal routine to convert Grahpics Output color to VGA color.\r
2649\r
2650 @param BltBuffer buffer containing Grahpics Output color\r
2651\r
2652 @return Converted VGA color\r
2653\r
2654**/\r
2655UINT8\r
2656VgaConvertColor (\r
2657 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2658 )\r
2659{\r
2660 UINT8 Color;\r
2661\r
2662 Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
2663 if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
2664 Color |= 0x08;\r
2665 }\r
2666\r
2667 return Color;\r
2668}\r
2669\r
2670\r
2671/**\r
2672 Grahpics Output protocol instance to block transfer for VGA device.\r
2673\r
2674 @param This Pointer to Grahpics Output protocol instance\r
2675 @param BltBuffer The data to transfer to screen\r
2676 @param BltOperation The operation to perform\r
2677 @param SourceX The X coordinate of the source for BltOperation\r
2678 @param SourceY The Y coordinate of the source for BltOperation\r
2679 @param DestinationX The X coordinate of the destination for\r
2680 BltOperation\r
2681 @param DestinationY The Y coordinate of the destination for\r
2682 BltOperation\r
2683 @param Width The width of a rectangle in the blt rectangle in\r
2684 pixels\r
2685 @param Height The height of a rectangle in the blt rectangle in\r
2686 pixels\r
2687 @param Delta Not used for EfiBltVideoFill and\r
2688 EfiBltVideoToVideo operation. If a Delta of 0 is\r
2689 used, the entire BltBuffer will be operated on. If\r
2690 a subrectangle of the BltBuffer is used, then\r
2691 Delta represents the number of bytes in a row of\r
2692 the BltBuffer.\r
2693\r
2694 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2695 @retval EFI_SUCCESS Blt operation success\r
2696\r
2697**/\r
2698EFI_STATUS\r
2699EFIAPI\r
2700BiosVideoGraphicsOutputVgaBlt (\r
2701 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2702 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2703 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2704 IN UINTN SourceX,\r
2705 IN UINTN SourceY,\r
2706 IN UINTN DestinationX,\r
2707 IN UINTN DestinationY,\r
2708 IN UINTN Width,\r
2709 IN UINTN Height,\r
2710 IN UINTN Delta\r
2711 )\r
2712{\r
2713 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2714 EFI_TPL OriginalTPL;\r
2715 UINT8 *MemAddress;\r
2716 UINTN BytesPerScanLine;\r
2717 UINTN Bit;\r
2718 UINTN Index;\r
2719 UINTN Index1;\r
2720 UINTN StartAddress;\r
2721 UINTN Bytes;\r
2722 UINTN Offset;\r
2723 UINT8 LeftMask;\r
2724 UINT8 RightMask;\r
2725 UINTN Address;\r
2726 UINTN AddressFix;\r
2727 UINT8 *Address1;\r
2728 UINT8 *SourceAddress;\r
2729 UINT8 *DestinationAddress;\r
2730 EFI_PCI_IO_PROTOCOL *PciIo;\r
2731 UINT8 Data;\r
2732 UINT8 PixelColor;\r
2733 UINT8 *VgaFrameBuffer;\r
2734 UINTN SourceOffset;\r
2735 UINTN SourceWidth;\r
2736 UINTN Rows;\r
2737 UINTN Columns;\r
2738 UINTN CoordinateX;\r
2739 UINTN CoordinateY;\r
2740 UINTN CurrentMode;\r
2741\r
2742 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
2743 return EFI_INVALID_PARAMETER;\r
2744 }\r
2745\r
2746 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
2747\r
2748 CurrentMode = This->Mode->Mode;\r
2749 PciIo = BiosVideoPrivate->PciIo;\r
2750 MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
2751 BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
2752 VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
2753\r
2754\r
2755 if (Width == 0 || Height == 0) {\r
2756 return EFI_INVALID_PARAMETER;\r
2757 }\r
2758 //\r
2759 // We need to fill the Virtual Screen buffer with the blt data.\r
2760 // The virtual screen is upside down, as the first row is the bootom row of\r
2761 // the image.\r
2762 //\r
2763 if (BltOperation == EfiBltVideoToBltBuffer) {\r
2764 //\r
2765 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2766 //\r
2767 if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
2768 return EFI_INVALID_PARAMETER;\r
2769 }\r
2770\r
2771 if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
2772 return EFI_INVALID_PARAMETER;\r
2773 }\r
2774 } else {\r
2775 //\r
2776 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2777 //\r
2778 if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
2779 return EFI_INVALID_PARAMETER;\r
2780 }\r
2781\r
2782 if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
2783 return EFI_INVALID_PARAMETER;\r
2784 }\r
2785 }\r
2786 //\r
2787 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2788 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2789 // the number of bytes in each row can be computed.\r
2790 //\r
2791 if (Delta == 0) {\r
2792 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
2793 }\r
2794 //\r
2795 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2796 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2797 // doing this operation.\r
2798 //\r
2799 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2800\r
2801 //\r
2802 // Compute some values we need for VGA\r
2803 //\r
2804 switch (BltOperation) {\r
2805 case EfiBltVideoToBltBuffer:\r
2806\r
2807 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2808 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2809\r
2810 //\r
2811 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2812 //\r
2813 VgaReadBitPlanes (\r
2814 PciIo,\r
2815 MemAddress + SourceOffset,\r
2816 VgaFrameBuffer + SourceOffset,\r
2817 SourceWidth,\r
2818 Height\r
2819 );\r
2820\r
2821 //\r
2822 // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
2823 //\r
2824 BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
2825 for (Rows = 0, CoordinateY = SourceY; Rows < Height; Rows++, CoordinateY++, BltBuffer += (Delta >> 2)) {\r
2826 for (Columns = 0, CoordinateX = SourceX; Columns < Width; Columns++, CoordinateX++, BltBuffer++) {\r
2827 VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, CoordinateY, BltBuffer);\r
2828 }\r
2829\r
2830 BltBuffer -= Width;\r
2831 }\r
2832\r
2833 break;\r
2834\r
2835 case EfiBltVideoToVideo:\r
2836 //\r
2837 // Check for an aligned Video to Video operation\r
2838 //\r
2839 if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
2840 //\r
2841 // Program the Mode Register Write mode 1, Read mode 0\r
2842 //\r
2843 WriteGraphicsController (\r
2844 PciIo,\r
2845 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2846 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
2847 );\r
2848\r
2849 SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
2850 DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2851 Bytes = Width >> 3;\r
2852 for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
2853 PciIo->CopyMem (\r
2854 PciIo,\r
2855 EfiPciIoWidthUint8,\r
2856 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2857 (UINT64) (UINTN) (DestinationAddress + Offset),\r
2858 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2859 (UINT64) (UINTN) (SourceAddress + Offset),\r
2860 Bytes\r
2861 );\r
2862 }\r
2863 } else {\r
2864 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2865 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2866\r
2867 //\r
2868 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2869 //\r
2870 VgaReadBitPlanes (\r
2871 PciIo,\r
2872 MemAddress + SourceOffset,\r
2873 VgaFrameBuffer + SourceOffset,\r
2874 SourceWidth,\r
2875 Height\r
2876 );\r
2877 }\r
2878\r
2879 break;\r
2880\r
2881 case EfiBltVideoFill:\r
2882 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2883 Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
2884 LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
2885 RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
2886 if (Bytes == 0) {\r
2887 LeftMask = (UINT8) (LeftMask & RightMask);\r
2888 RightMask = 0;\r
2889 }\r
2890\r
2891 if (LeftMask == 0xff) {\r
2892 StartAddress--;\r
2893 Bytes++;\r
2894 LeftMask = 0;\r
2895 }\r
2896\r
2897 if (RightMask == 0xff) {\r
2898 Bytes++;\r
2899 RightMask = 0;\r
2900 }\r
2901\r
2902 PixelColor = VgaConvertColor (BltBuffer);\r
2903\r
2904 //\r
2905 // Program the Mode Register Write mode 2, Read mode 0\r
2906 //\r
2907 WriteGraphicsController (\r
2908 PciIo,\r
2909 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2910 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2911 );\r
2912\r
2913 //\r
2914 // Program the Data Rotate/Function Select Register to replace\r
2915 //\r
2916 WriteGraphicsController (\r
2917 PciIo,\r
2918 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2919 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2920 );\r
2921\r
2922 if (LeftMask != 0) {\r
2923 //\r
2924 // Program the BitMask register with the Left column mask\r
2925 //\r
2926 WriteGraphicsController (\r
2927 PciIo,\r
2928 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2929 LeftMask\r
2930 );\r
2931\r
2932 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2933 //\r
2934 // Read data from the bit planes into the latches\r
2935 //\r
2936 PciIo->Mem.Read (\r
2937 PciIo,\r
2938 EfiPciIoWidthUint8,\r
2939 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2940 (UINT64) (UINTN) Address,\r
2941 1,\r
2942 &Data\r
2943 );\r
2944 //\r
2945 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2946 //\r
2947 PciIo->Mem.Write (\r
2948 PciIo,\r
2949 EfiPciIoWidthUint8,\r
2950 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2951 (UINT64) (UINTN) Address,\r
2952 1,\r
2953 &PixelColor\r
2954 );\r
2955 }\r
2956 }\r
2957\r
2958 if (Bytes > 1) {\r
2959 //\r
2960 // Program the BitMask register with the middle column mask of 0xff\r
2961 //\r
2962 WriteGraphicsController (\r
2963 PciIo,\r
2964 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2965 0xff\r
2966 );\r
2967\r
2968 for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
2969 PciIo->Mem.Write (\r
2970 PciIo,\r
2971 EfiPciIoWidthFillUint8,\r
2972 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2973 (UINT64) (UINTN) Address,\r
2974 Bytes - 1,\r
2975 &PixelColor\r
2976 );\r
2977 }\r
2978 }\r
2979\r
2980 if (RightMask != 0) {\r
2981 //\r
2982 // Program the BitMask register with the Right column mask\r
2983 //\r
2984 WriteGraphicsController (\r
2985 PciIo,\r
2986 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2987 RightMask\r
2988 );\r
2989\r
2990 for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
2991 //\r
2992 // Read data from the bit planes into the latches\r
2993 //\r
2994 PciIo->Mem.Read (\r
2995 PciIo,\r
2996 EfiPciIoWidthUint8,\r
2997 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2998 (UINT64) (UINTN) Address,\r
2999 1,\r
3000 &Data\r
3001 );\r
3002 //\r
3003 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
3004 //\r
3005 PciIo->Mem.Write (\r
3006 PciIo,\r
3007 EfiPciIoWidthUint8,\r
3008 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3009 (UINT64) (UINTN) Address,\r
3010 1,\r
3011 &PixelColor\r
3012 );\r
3013 }\r
3014 }\r
3015 break;\r
3016\r
3017 case EfiBltBufferToVideo:\r
3018 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
3019 LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
3020\r
3021 //\r
3022 // Program the Mode Register Write mode 2, Read mode 0\r
3023 //\r
3024 WriteGraphicsController (\r
3025 PciIo,\r
3026 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
3027 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
3028 );\r
3029\r
3030 //\r
3031 // Program the Data Rotate/Function Select Register to replace\r
3032 //\r
3033 WriteGraphicsController (\r
3034 PciIo,\r
3035 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
3036 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
3037 );\r
3038\r
3039 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
3040 for (Index1 = 0; Index1 < Width; Index1++) {\r
3041 BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
3042 }\r
3043 AddressFix = Address;\r
3044\r
3045 for (Bit = 0; Bit < 8; Bit++) {\r
3046 //\r
3047 // Program the BitMask register with the Left column mask\r
3048 //\r
3049 WriteGraphicsController (\r
3050 PciIo,\r
3051 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
3052 LeftMask\r
3053 );\r
3054\r
3055 for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
3056 //\r
3057 // Read data from the bit planes into the latches\r
3058 //\r
3059 PciIo->Mem.Read (\r
3060 PciIo,\r
3061 EfiPciIoWidthUint8,\r
3062 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3063 (UINT64) (UINTN) Address1,\r
3064 1,\r
3065 &Data\r
3066 );\r
3067\r
3068 PciIo->Mem.Write (\r
3069 PciIo,\r
3070 EfiPciIoWidthUint8,\r
3071 EFI_PCI_IO_PASS_THROUGH_BAR,\r
3072 (UINT64) (UINTN) Address1,\r
3073 1,\r
3074 &BiosVideoPrivate->LineBuffer[Index1]\r
3075 );\r
3076 }\r
3077\r
3078 LeftMask = (UINT8) (LeftMask >> 1);\r
3079 if (LeftMask == 0) {\r
3080 LeftMask = 0x80;\r
3081 AddressFix++;\r
3082 }\r
3083 }\r
3084 }\r
3085\r
3086 break;\r
3087\r
3088 default: ;\r
3089 }\r
3090\r
3091 gBS->RestoreTPL (OriginalTPL);\r
3092\r
3093 return EFI_SUCCESS;\r
3094}\r
3095\r
3096//\r
3097// VGA Mini Port Protocol Functions\r
3098//\r
3099\r
3100/**\r
3101 VgaMiniPort protocol interface to set mode.\r
3102\r
3103 @param This Pointer to VgaMiniPort protocol instance\r
3104 @param ModeNumber The index of the mode\r
3105\r
3106 @retval EFI_UNSUPPORTED The requested mode is not supported\r
3107 @retval EFI_SUCCESS The requested mode is set successfully\r
3108\r
3109**/\r
3110EFI_STATUS\r
3111EFIAPI\r
3112BiosVideoVgaMiniPortSetMode (\r
3113 IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
3114 IN UINTN ModeNumber\r
3115 )\r
3116{\r
3117 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
3118 EFI_IA32_REGISTER_SET Regs;\r
3119\r
3120 if (This == NULL) {\r
3121 return EFI_INVALID_PARAMETER;\r
3122 }\r
3123\r
3124 //\r
3125 // Make sure the ModeNumber is a valid value\r
3126 //\r
3127 if (ModeNumber >= This->MaxMode) {\r
3128 return EFI_UNSUPPORTED;\r
3129 }\r
3130 //\r
3131 // Get the device structure for this device\r
3132 //\r
3133 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
3134\r
3135 switch (ModeNumber) {\r
3136 case 0:\r
3137 //\r
3138 // Set the 80x25 Text VGA Mode\r
3139 //\r
3140 Regs.H.AH = 0x00;\r
3141 Regs.H.AL = 0x83;\r
3142 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3143\r
3144 Regs.H.AH = 0x11;\r
3145 Regs.H.AL = 0x14;\r
3146 Regs.H.BL = 0;\r
3147 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3148 break;\r
3149\r
3150 case 1:\r
3151 //\r
3152 // Set the 80x50 Text VGA Mode\r
3153 //\r
3154 Regs.H.AH = 0x00;\r
3155 Regs.H.AL = 0x83;\r
3156 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3157 Regs.H.AH = 0x11;\r
3158 Regs.H.AL = 0x12;\r
3159 Regs.H.BL = 0;\r
3160 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3161 break;\r
3162\r
3163 default:\r
3164 return EFI_UNSUPPORTED;\r
3165 }\r
3166\r
3167 return EFI_SUCCESS;\r
3168}\r
3169\r
3170/**\r
3171 Event handler for Exit Boot Service.\r
3172\r
3173 @param Event The event that be siganlled when exiting boot service.\r
3174 @param Context Pointer to instance of BIOS_VIDEO_DEV.\r
3175\r
3176**/\r
3177VOID\r
3178EFIAPI\r
3179BiosVideoNotifyExitBootServices (\r
3180 IN EFI_EVENT Event,\r
3181 IN VOID *Context\r
3182 )\r
3183{\r
3184 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
3185 EFI_IA32_REGISTER_SET Regs;\r
3186\r
3187 BiosVideoPrivate = (BIOS_VIDEO_DEV *)Context;\r
3188\r
3189 //\r
3190 // Set the 80x25 Text VGA Mode\r
3191 //\r
3192 Regs.H.AH = 0x00;\r
3193 Regs.H.AL = 0x03;\r
3194 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3195\r
3196 Regs.H.AH = 0x00;\r
3197 Regs.H.AL = 0x83;\r
3198 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3199\r
3200 Regs.H.AH = 0x11;\r
3201 Regs.H.AL = 0x04;\r
3202 Regs.H.BL = 0;\r
3203 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);\r
3204}\r
3205\r
3206/**\r
3207 The user Entry Point for module UefiBiosVideo. The user code starts with this function.\r
3208\r
3209 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
3210 @param[in] SystemTable A pointer to the EFI System Table.\r
3211\r
3212 @retval EFI_SUCCESS The entry point is executed successfully.\r
3213 @retval other Some error occurs when executing this entry point.\r
3214\r
3215**/\r
3216EFI_STATUS\r
3217EFIAPI\r
3218BiosVideoEntryPoint(\r
3219 IN EFI_HANDLE ImageHandle,\r
3220 IN EFI_SYSTEM_TABLE *SystemTable\r
3221 )\r
3222{\r
3223 EFI_STATUS Status;\r
3224\r
3225 //\r
3226 // Install driver model protocol(s).\r
3227 //\r
3228 Status = EfiLibInstallDriverBindingComponentName2 (\r
3229 ImageHandle,\r
3230 SystemTable,\r
3231 &gBiosVideoDriverBinding,\r
3232 ImageHandle,\r
3233 &gBiosVideoComponentName,\r
3234 &gBiosVideoComponentName2\r
3235 );\r
3236 ASSERT_EFI_ERROR (Status);\r
3237\r
3238 //\r
3239 // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver\r
3240 //\r
3241 return gBS->InstallMultipleProtocolInterfaces (\r
3242 &ImageHandle,\r
3243 &gEfiLegacyBiosGuid,\r
3244 NULL,\r
3245 NULL\r
3246 );\r
3247}\r
3248\r