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