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