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