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