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