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