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