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