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