]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BiosVideoThunkDxe/BiosVideo.c
Remove debug message code.
[mirror_edk2.git] / DuetPkg / BiosVideoThunkDxe / BiosVideo.c
CommitLineData
f1294e4a 1/** @file\r
2\r
3 BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom.\r
7da78b1f 4\r
5Copyright (c) 2006 - 2008, Intel Corporation \r
6All rights reserved. This 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
f1294e4a 14**/\r
7da78b1f 15\r
16#include "BiosVideo.h"\r
17\r
7da78b1f 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
f1294e4a 33UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };\r
34\r
35UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };\r
7da78b1f 36\r
f1294e4a 37UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };\r
7da78b1f 38\r
f1294e4a 39EFI_LEGACY_8259_PROTOCOL *mLegacy8259 = NULL;\r
40THUNK_CONTEXT mThunkContext;\r
7da78b1f 41\r
0d92cdc2 42EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = {\r
f1294e4a 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
7da78b1f 62};\r
63\r
0d92cdc2 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
f1294e4a 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
0d92cdc2 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
f1294e4a 117 IN THUNK_CONTEXT *ThunkContext,\r
0d92cdc2 118 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
119 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
120 )\r
121;\r
122\r
f1294e4a 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
0d92cdc2 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
f1294e4a 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
7da78b1f 148VOID\r
0d92cdc2 149BiosVideoDeviceReleaseResource (\r
150 BIOS_VIDEO_DEV *BiosVideoPrivate\r
151 )\r
152;\r
153\r
f1294e4a 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
7da78b1f 162EFI_STATUS\r
163EFIAPI\r
164BiosVideoDriverEntryPoint (\r
165 IN EFI_HANDLE ImageHandle,\r
166 IN EFI_SYSTEM_TABLE *SystemTable\r
167 )\r
7da78b1f 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
0d92cdc2 179 \r
7da78b1f 180 return Status;\r
181}\r
182\r
f1294e4a 183/**\r
184 Test to see if Bios Video could be supported on the Controller.\r
7da78b1f 185\r
f1294e4a 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
7da78b1f 189\r
f1294e4a 190 @retval EFI_SUCCESS This driver supports this device.\r
191 @retval other This driver does not support this device.\r
7da78b1f 192\r
f1294e4a 193**/\r
7da78b1f 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
7da78b1f 201{\r
0d92cdc2 202 EFI_STATUS Status;\r
203 EFI_LEGACY_8259_PROTOCOL *LegacyBios;\r
204 EFI_PCI_IO_PROTOCOL *PciIo;\r
7da78b1f 205\r
206 //\r
0d92cdc2 207 // See if the Legacy 8259 Protocol is available\r
7da78b1f 208 //\r
0d92cdc2 209 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &LegacyBios);\r
7da78b1f 210 if (EFI_ERROR (Status)) {\r
211 return Status;\r
212 }\r
0d92cdc2 213 \r
7da78b1f 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
7da78b1f 226 return Status;\r
227 }\r
0d92cdc2 228\r
7da78b1f 229 if (!BiosVideoIsVga (PciIo)) {\r
7da78b1f 230 Status = EFI_UNSUPPORTED;\r
231 }\r
232\r
233 gBS->CloseProtocol (\r
0d92cdc2 234 Controller,\r
235 &gEfiPciIoProtocolGuid,\r
236 This->DriverBindingHandle,\r
237 Controller\r
238 );\r
7da78b1f 239\r
240 return Status;\r
241}\r
242\r
f1294e4a 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
7da78b1f 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
7da78b1f 260{\r
0d92cdc2 261 EFI_STATUS Status;\r
262 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
263 EFI_PCI_IO_PROTOCOL *PciIo;\r
7da78b1f 264\r
0d92cdc2 265 PciIo = NULL;\r
7da78b1f 266 //\r
0d92cdc2 267 // Prepare for status code\r
7da78b1f 268 //\r
0d92cdc2 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
7da78b1f 277\r
278 //\r
0d92cdc2 279 // Open the IO Abstraction(s) needed\r
7da78b1f 280 //\r
0d92cdc2 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
7da78b1f 288 );\r
289 if (EFI_ERROR (Status)) {\r
290 goto Done;\r
291 }\r
292\r
7da78b1f 293 //\r
f1294e4a 294 // Establish legacy environment for thunk call for all children handle.\r
7da78b1f 295 //\r
f1294e4a 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
7da78b1f 304 }\r
0d92cdc2 305\r
7da78b1f 306 //\r
0d92cdc2 307 // Create child handle and install GraphicsOutputProtocol on it\r
7da78b1f 308 //\r
0d92cdc2 309 Status = BiosVideoChildHandleInstall (\r
310 This,\r
311 Controller,\r
312 PciIo,\r
f1294e4a 313 mLegacy8259,\r
314 &mThunkContext,\r
0d92cdc2 315 ParentDevicePath,\r
316 RemainingDevicePath\r
317 );\r
318\r
319Done:\r
7da78b1f 320 if (EFI_ERROR (Status)) {\r
0d92cdc2 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
7da78b1f 332 }\r
0d92cdc2 333\r
334 return Status;\r
335}\r
336\r
f1294e4a 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
0d92cdc2 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
0d92cdc2 358{\r
359 EFI_STATUS Status;\r
0d92cdc2 360 BOOLEAN AllChildrenStopped;\r
361 UINTN Index;\r
362\r
0d92cdc2 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
f1294e4a 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
0d92cdc2 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
f1294e4a 414 IN THUNK_CONTEXT *ParentThunkContext,\r
0d92cdc2 415 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
416 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
417 )\r
0d92cdc2 418{\r
419 EFI_STATUS Status;\r
420 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
421 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
422\r
7da78b1f 423 //\r
0d92cdc2 424 // Allocate the private device structure for video device\r
7da78b1f 425 //\r
0d92cdc2 426 Status = gBS->AllocatePool (\r
427 EfiBootServicesData,\r
428 sizeof (BIOS_VIDEO_DEV),\r
fe74f173 429 (VOID**) &BiosVideoPrivate\r
7da78b1f 430 );\r
431 if (EFI_ERROR (Status)) {\r
432 goto Done;\r
433 }\r
0d92cdc2 434\r
435 ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));\r
436\r
437 if (!BiosVideoIsVga (ParentPciIo)) {\r
7da78b1f 438 Status = EFI_UNSUPPORTED;\r
439 goto Done;\r
440 }\r
441 \r
0d92cdc2 442 BiosVideoPrivate->VgaCompatible = TRUE;\r
443\r
7da78b1f 444 //\r
0d92cdc2 445 // Initialize the child private structure\r
7da78b1f 446 //\r
447 BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;\r
f1294e4a 448 BiosVideoPrivate->Handle = NULL;\r
449\r
7da78b1f 450 //\r
0d92cdc2 451 // Fill in Graphics Output specific mode structures\r
7da78b1f 452 //\r
453 BiosVideoPrivate->HardwareNeedsStarting = TRUE;\r
7da78b1f 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
0d92cdc2 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
7da78b1f 477 //\r
f1294e4a 478 BiosVideoPrivate->Legacy8259 = ParentLegacy8259;\r
479 BiosVideoPrivate->ThunkContext = ParentThunkContext;\r
480 \r
7da78b1f 481 //\r
0d92cdc2 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
0d92cdc2 486 //\r
487 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output\r
7da78b1f 488 //\r
7da78b1f 489 Status = BiosVideoCheckForVbe (BiosVideoPrivate);\r
7da78b1f 490 if (EFI_ERROR (Status)) {\r
7da78b1f 491 //\r
0d92cdc2 492 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support\r
7da78b1f 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
0d92cdc2 502 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.\r
7da78b1f 503 //\r
0d92cdc2 504 BiosVideoPrivate->ProduceGraphicsOutput = FALSE;\r
7da78b1f 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
0d92cdc2 513 if (BiosVideoPrivate->ProduceGraphicsOutput) {\r
514 if (RemainingDevicePath == NULL) {\r
515 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
f1294e4a 516 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
0d92cdc2 517 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
f1294e4a 518 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
0d92cdc2 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
7da78b1f 529 //\r
0d92cdc2 530 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol\r
7da78b1f 531 //\r
532 Status = gBS->InstallMultipleProtocolInterfaces (\r
0d92cdc2 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
7da78b1f 542 NULL\r
543 );\r
0d92cdc2 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
7da78b1f 561 } else {\r
562 //\r
563 // Install VGA Mini Port Protocol\r
564 //\r
565 Status = gBS->InstallMultipleProtocolInterfaces (\r
0d92cdc2 566 &BiosVideoPrivate->Handle,\r
7da78b1f 567 &gEfiVgaMiniPortProtocolGuid,\r
568 &BiosVideoPrivate->VgaMiniPort,\r
569 NULL\r
570 );\r
571 }\r
572\r
573Done:\r
574 if (EFI_ERROR (Status)) {\r
0d92cdc2 575 //\r
576 // Free private data structure\r
577 //\r
578 BiosVideoDeviceReleaseResource (BiosVideoPrivate);\r
7da78b1f 579 }\r
580\r
581 return Status;\r
582}\r
583\r
f1294e4a 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
7da78b1f 594EFI_STATUS\r
0d92cdc2 595BiosVideoChildHandleUninstall (\r
596 EFI_DRIVER_BINDING_PROTOCOL *This,\r
597 EFI_HANDLE Controller,\r
598 EFI_HANDLE Handle\r
7da78b1f 599 )\r
7da78b1f 600{\r
0d92cdc2 601 EFI_STATUS Status;\r
602 EFI_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
7da78b1f 607\r
608 BiosVideoPrivate = NULL;\r
609\r
610 Status = gBS->OpenProtocol (\r
0d92cdc2 611 Handle,\r
612 &gEfiGraphicsOutputProtocolGuid,\r
613 (VOID **) &GraphicsOutput,\r
7da78b1f 614 This->DriverBindingHandle,\r
0d92cdc2 615 Handle,\r
7da78b1f 616 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
617 );\r
618 if (!EFI_ERROR (Status)) {\r
0d92cdc2 619 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
7da78b1f 620 }\r
621\r
622 Status = gBS->OpenProtocol (\r
0d92cdc2 623 Handle,\r
7da78b1f 624 &gEfiVgaMiniPortProtocolGuid,\r
625 (VOID **) &VgaMiniPort,\r
626 This->DriverBindingHandle,\r
0d92cdc2 627 Handle,\r
7da78b1f 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
0d92cdc2 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
7da78b1f 652 Status = gBS->UninstallMultipleProtocolInterfaces (\r
0d92cdc2 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
7da78b1f 662 NULL\r
663 );\r
664 } else {\r
665 Status = gBS->UninstallMultipleProtocolInterfaces (\r
0d92cdc2 666 BiosVideoPrivate->Handle,\r
7da78b1f 667 &gEfiVgaMiniPortProtocolGuid,\r
668 &BiosVideoPrivate->VgaMiniPort,\r
669 NULL\r
670 );\r
671 }\r
7da78b1f 672 if (EFI_ERROR (Status)) {\r
0d92cdc2 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
7da78b1f 681 return Status;\r
682 }\r
0d92cdc2 683\r
684 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
685\r
7da78b1f 686 //\r
687 // Set the 80x25 Text VGA Mode\r
688 //\r
689 Regs.H.AH = 0x00;\r
690 Regs.H.AL = 0x03;\r
0d92cdc2 691 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
692 \r
7da78b1f 693 Regs.H.AH = 0x11;\r
694 Regs.H.AL = 0x14;\r
695 Regs.H.BL = 0;\r
0d92cdc2 696 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
697 \r
7da78b1f 698 //\r
699 // Do not disable IO/memory decode since that would prevent legacy ROM from working\r
700 //\r
0d92cdc2 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
f1294e4a 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
0d92cdc2 716VOID\r
717BiosVideoDeviceReleaseResource (\r
718 BIOS_VIDEO_DEV *BiosVideoPrivate\r
719 )\r
0d92cdc2 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
7da78b1f 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
0d92cdc2 764 // Free graphics output protocol occupied resource\r
7da78b1f 765 //\r
0d92cdc2 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
7da78b1f 788\r
0d92cdc2 789 gBS->FreePool (BiosVideoPrivate);\r
790\r
791 return ;\r
792}\r
793\r
f1294e4a 794/**\r
0d92cdc2 795\r
796 Generate a search key for a specified timing data.\r
797\r
0d92cdc2 798\r
f1294e4a 799 @param EdidTiming - Pointer to EDID timing\r
0d92cdc2 800\r
f1294e4a 801 @return The 32 bit unique key for search.\r
0d92cdc2 802\r
f1294e4a 803**/\r
804STATIC\r
805UINT32\r
806CalculateEdidKey (\r
807 VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming\r
808 )\r
0d92cdc2 809{\r
810 UINT32 Key;\r
7da78b1f 811\r
812 //\r
0d92cdc2 813 // Be sure no conflicts for all standard timing defined by VESA.\r
7da78b1f 814 //\r
0d92cdc2 815 Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;\r
816 return Key;\r
817}\r
7da78b1f 818\r
f1294e4a 819/**\r
0d92cdc2 820\r
821 Parse the Established Timing and Standard Timing in EDID data block.\r
822\r
0d92cdc2 823\r
f1294e4a 824 @param EdidBuffer - Pointer to EDID data block\r
825 @param ValidEdidTiming - Valid EDID timing information\r
0d92cdc2 826\r
f1294e4a 827 @return TRUE - The EDID data is valid.\r
828 FALSE - The EDID data is invalid.\r
0d92cdc2 829\r
f1294e4a 830**/\r
831STATIC\r
832BOOLEAN\r
833ParseEdidData (\r
834 UINT8 *EdidBuffer,\r
835 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming\r
836 )\r
0d92cdc2 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
49de9dd4 857 CheckSum = (UINT8)(CheckSum + EdidBuffer[Index]);\r
0d92cdc2 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
49de9dd4 893 HorizontalResolution = (UINT8) (BufferIndex[0] * 8 + 248);\r
894 AspectRatio = (UINT8) (BufferIndex[1] >> 6);\r
0d92cdc2 895 switch (AspectRatio) {\r
896 case 0:\r
49de9dd4 897 VerticalResolution = (UINT8) (HorizontalResolution / 16 * 10);\r
0d92cdc2 898 break;\r
899 case 1:\r
49de9dd4 900 VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);\r
0d92cdc2 901 break;\r
902 case 2:\r
49de9dd4 903 VerticalResolution = (UINT8) (HorizontalResolution / 5 * 4);\r
0d92cdc2 904 break;\r
905 case 3:\r
49de9dd4 906 VerticalResolution = (UINT8) (HorizontalResolution / 16 * 9);\r
0d92cdc2 907 break;\r
908 default:\r
49de9dd4 909 VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);\r
0d92cdc2 910 break;\r
911 }\r
49de9dd4 912 RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);\r
0d92cdc2 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
f1294e4a 927/**\r
0d92cdc2 928\r
929 Search a specified Timing in all the valid EDID timings.\r
930\r
0d92cdc2 931\r
f1294e4a 932 @param ValidEdidTiming - All valid EDID timing information.\r
933 @param EdidTiming - The Timing to search for.\r
0d92cdc2 934\r
f1294e4a 935 @return TRUE - Found.\r
936 FALSE - Not found.\r
0d92cdc2 937\r
f1294e4a 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
0d92cdc2 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
7da78b1f 958}\r
959\r
960#define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)\r
961\r
962\r
f1294e4a 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
7da78b1f 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
f1294e4a 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
7da78b1f 1027EFI_STATUS\r
0d92cdc2 1028EFIAPI\r
7da78b1f 1029BiosVideoCheckForVbe (\r
0d92cdc2 1030 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
7da78b1f 1031 )\r
7da78b1f 1032{\r
0d92cdc2 1033 EFI_STATUS Status;\r
1034 EFI_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
7da78b1f 1045\r
1046 //\r
1047 // Allocate buffer under 1MB for VBE data structures\r
1048 //\r
1049 BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (\r
0d92cdc2 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
7da78b1f 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
0d92cdc2 1067\r
1068 ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));\r
1069\r
7da78b1f 1070 //\r
0d92cdc2 1071 // Fill in the Graphics Output Protocol\r
7da78b1f 1072 //\r
0d92cdc2 1073 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
1074 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
1075 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt;\r
1076 BiosVideoPrivate->GraphicsOutput.Mode = NULL;\r
7da78b1f 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
0d92cdc2 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
7da78b1f 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 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1092 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
1093 gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
1094 BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
0d92cdc2 1095 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
1096 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
7da78b1f 1097\r
0d92cdc2 1098 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
237bb9d0 1099 \r
7da78b1f 1100 Status = EFI_DEVICE_ERROR;\r
1101\r
1102 //\r
1103 // See if the VESA call succeeded\r
1104 //\r
1105 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1106 return Status;\r
1107 }\r
1108 //\r
1109 // Check for 'VESA' signature\r
1110 //\r
1111 if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
1112 return Status;\r
1113 }\r
1114 //\r
1115 // Check to see if this is VBE 2.0 or higher\r
1116 //\r
1117 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
1118 return Status;\r
1119 }\r
0d92cdc2 1120\r
1121 //\r
1122 // Read EDID information\r
1123 //\r
1124 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1125 Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
1126 Regs.X.BX = 1;\r
1127 Regs.X.CX = 0;\r
1128 Regs.X.DX = 0;\r
1129 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1130 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1131\r
1132 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1133 \r
1134 //\r
1135 // See if the VESA call succeeded\r
1136 //\r
1137 EdidFound = FALSE;\r
1138 if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1139 //\r
1140 // Parse EDID data structure to retrieve modes supported by monitor\r
1141 //\r
1142 if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {\r
1143 EdidFound = TRUE;\r
1144\r
1145 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1146 Status = gBS->AllocatePool (\r
1147 EfiBootServicesData,\r
1148 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
fe74f173 1149 (VOID**) &BiosVideoPrivate->EdidDiscovered.Edid\r
0d92cdc2 1150 );\r
1151 if (EFI_ERROR (Status)) {\r
1152 goto Done;\r
1153 }\r
1154 gBS->CopyMem (\r
1155 BiosVideoPrivate->EdidDiscovered.Edid,\r
1156 BiosVideoPrivate->VbeEdidDataBlock,\r
1157 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1158 );\r
1159\r
1160 BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1161 Status = gBS->AllocatePool (\r
1162 EfiBootServicesData,\r
1163 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
fe74f173 1164 (VOID**)&BiosVideoPrivate->EdidActive.Edid\r
0d92cdc2 1165 );\r
1166 if (EFI_ERROR (Status)) {\r
1167 goto Done;\r
1168 }\r
1169 gBS->CopyMem (\r
1170 BiosVideoPrivate->EdidActive.Edid,\r
1171 BiosVideoPrivate->VbeEdidDataBlock,\r
1172 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1173 );\r
1174 } else {\r
1175 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;\r
1176 BiosVideoPrivate->EdidDiscovered.Edid = NULL;\r
1177\r
1178 BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
1179 BiosVideoPrivate->EdidActive.Edid = NULL;\r
1180 }\r
1181 }\r
1182\r
7da78b1f 1183 //\r
0d92cdc2 1184 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
7da78b1f 1185 //\r
1186 ModeNumberPtr = (UINT16 *)\r
1187 (\r
1188 (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
1189 ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
1190 );\r
0d92cdc2 1191\r
1192 PreferMode = 0;\r
1193 ModeNumber = 0;\r
1194\r
7da78b1f 1195 for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
1196 //\r
1197 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
1198 //\r
1199 if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
1200 continue;\r
1201 }\r
1202 //\r
1203 // Get the information about the mode\r
1204 //\r
1205 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1206 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
1207 Regs.X.CX = *ModeNumberPtr;\r
1208 gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
0d92cdc2 1209 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
1210 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
7da78b1f 1211\r
0d92cdc2 1212 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1213 \r
7da78b1f 1214 //\r
1215 // See if the call succeeded. If it didn't, then try the next mode.\r
1216 //\r
1217 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1218 continue;\r
1219 }\r
1220 //\r
1221 // See if the mode supports color. If it doesn't then try the next mode.\r
1222 //\r
1223 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
1224 continue;\r
1225 }\r
1226 //\r
1227 // See if the mode supports graphics. If it doesn't then try the next mode.\r
1228 //\r
1229 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
1230 continue;\r
1231 }\r
1232 //\r
1233 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
1234 //\r
1235 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
1236 continue;\r
1237 }\r
1238 //\r
1239 // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
1240 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
1241 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
1242 //\r
1243 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
1244 continue;\r
1245 }\r
1246\r
1247 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
1248 continue;\r
1249 }\r
1250\r
1251 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
1252 continue;\r
1253 }\r
1254 //\r
1255 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
1256 //\r
1257 if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
1258 continue;\r
1259 }\r
0d92cdc2 1260\r
1261 if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
1262 //\r
1263 // EDID exist, check whether this mode match with any mode in EDID\r
1264 //\r
1265 Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1266 Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1267 if (SearchEdidTiming (&ValidEdidTiming, &Timing) == FALSE) {\r
1268 continue;\r
1269 }\r
1270 }\r
1271\r
7da78b1f 1272 //\r
0d92cdc2 1273 // Select a reasonable mode to be set for current display mode\r
7da78b1f 1274 //\r
1275 ModeFound = FALSE;\r
0d92cdc2 1276\r
7da78b1f 1277 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
1278 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
1279 ) {\r
1280 ModeFound = TRUE;\r
1281 }\r
7da78b1f 1282 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
1283 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
1284 ) {\r
1285 ModeFound = TRUE;\r
0d92cdc2 1286 PreferMode = ModeNumber;\r
7da78b1f 1287 }\r
7da78b1f 1288 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
1289 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
1290 ) {\r
1291 ModeFound = TRUE;\r
1292 }\r
0d92cdc2 1293 if ((!EdidFound) && (!ModeFound)) {\r
1294 //\r
1295 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
1296 //\r
7da78b1f 1297 continue;\r
1298 }\r
0d92cdc2 1299\r
7da78b1f 1300 //\r
1301 // Add mode to the list of available modes\r
1302 //\r
0d92cdc2 1303 ModeNumber ++;\r
7da78b1f 1304 Status = gBS->AllocatePool (\r
1305 EfiBootServicesData,\r
0d92cdc2 1306 ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1307 (VOID **) &ModeBuffer\r
1308 );\r
1309 if (EFI_ERROR (Status)) {\r
1310 goto Done;\r
1311 }\r
1312\r
0d92cdc2 1313 if (ModeNumber > 1) {\r
7da78b1f 1314 gBS->CopyMem (\r
1315 ModeBuffer,\r
1316 BiosVideoPrivate->ModeData,\r
0d92cdc2 1317 (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
7da78b1f 1318 );\r
1319 }\r
1320\r
1321 if (BiosVideoPrivate->ModeData != NULL) {\r
1322 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1323 }\r
1324\r
0d92cdc2 1325 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
1326 CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
7da78b1f 1327 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
0d92cdc2 1328 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
1329 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
1330 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
1331 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
1332 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
1333 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
1334 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
1335 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
1336 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
7da78b1f 1337 } else {\r
0d92cdc2 1338 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
1339 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
1340 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
1341 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
1342 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
1343 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
1344 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
1345 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
1346 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
7da78b1f 1347 }\r
0d92cdc2 1348 CurrentModeData->PixelFormat = PixelBitMask;\r
1349 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
1350 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
1351 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
1352 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
1353 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
1354 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
1355 }\r
7da78b1f 1356 }\r
0d92cdc2 1357 CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
1358 CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
1359 CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
1360 CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
7da78b1f 1361\r
0d92cdc2 1362 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
1363 CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
1364 CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1365 CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
7da78b1f 1366\r
0d92cdc2 1367 CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
7da78b1f 1368\r
1369 BiosVideoPrivate->ModeData = ModeBuffer;\r
1370 }\r
1371 //\r
0d92cdc2 1372 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
7da78b1f 1373 //\r
0d92cdc2 1374 if (ModeNumber == 0) {\r
7da78b1f 1375 Status = EFI_DEVICE_ERROR;\r
1376 goto Done;\r
1377 }\r
0d92cdc2 1378\r
1379 //\r
1380 // Allocate buffer for Graphics Output Protocol mode information\r
1381 //\r
1382 Status = gBS->AllocatePool (\r
1383 EfiBootServicesData,\r
1384 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1385 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1386 );\r
1387 if (EFI_ERROR (Status)) {\r
1388 goto Done;\r
1389 }\r
1390 GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;\r
1391 Status = gBS->AllocatePool (\r
1392 EfiBootServicesData,\r
1393 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1394 (VOID **) &GraphicsOutputMode->Info\r
1395 );\r
1396 if (EFI_ERROR (Status)) {\r
1397 goto Done;\r
1398 }\r
1399\r
1400 GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;\r
1401 //\r
1402 // Current mode is unknow till now, set it to an invalid mode.\r
1403 //\r
1404 GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1405\r
7da78b1f 1406 //\r
1407 // Find the best mode to initialize\r
1408 //\r
0d92cdc2 1409 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
7da78b1f 1410 if (EFI_ERROR (Status)) {\r
0d92cdc2 1411 for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
1412 Status = BiosVideoGraphicsOutputSetMode (\r
1413 &BiosVideoPrivate->GraphicsOutput,\r
1414 (UINT32) PreferMode\r
1415 );\r
1416 if (!EFI_ERROR (Status)) {\r
1417 break;\r
7da78b1f 1418 }\r
1419 }\r
0d92cdc2 1420 if (PreferMode == ModeNumber) {\r
1421 //\r
1422 // None mode is set successfully.\r
1423 //\r
1424 goto Done;\r
1425 }\r
7da78b1f 1426 }\r
1427\r
1428Done:\r
1429 //\r
1430 // If there was an error, then free the mode structure\r
1431 //\r
1432 if (EFI_ERROR (Status)) {\r
1433 if (BiosVideoPrivate->ModeData != NULL) {\r
1434 gBS->FreePool (BiosVideoPrivate->ModeData);\r
0d92cdc2 1435 }\r
1436 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1437 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1438 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1439 }\r
1440 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
7da78b1f 1441 }\r
1442 }\r
1443\r
1444 return Status;\r
1445}\r
1446\r
f1294e4a 1447/**\r
1448 Check for VGA device\r
1449\r
1450 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
1451\r
1452 @retval EFI_SUCCESS Standard VGA device found\r
1453**/\r
7da78b1f 1454EFI_STATUS\r
0d92cdc2 1455EFIAPI\r
7da78b1f 1456BiosVideoCheckForVga (\r
0d92cdc2 1457 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
7da78b1f 1458 )\r
7da78b1f 1459{\r
1460 EFI_STATUS Status;\r
1461 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
0d92cdc2 1462 \r
1463 //\r
1464 // Fill in the Graphics Output Protocol\r
1465 //\r
1466 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
1467 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
1468 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
7da78b1f 1469\r
1470 //\r
0d92cdc2 1471 // Allocate buffer for Graphics Output Protocol mode information\r
7da78b1f 1472 //\r
0d92cdc2 1473 Status = gBS->AllocatePool (\r
1474 EfiBootServicesData,\r
1475 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1476 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1477 );\r
1478 if (EFI_ERROR (Status)) {\r
1479 goto Done;\r
1480 }\r
1481 Status = gBS->AllocatePool (\r
1482 EfiBootServicesData,\r
1483 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1484 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info\r
1485 );\r
1486 if (EFI_ERROR (Status)) {\r
1487 goto Done;\r
1488 }\r
7da78b1f 1489\r
1490 //\r
1491 // Add mode to the list of available modes\r
1492 //\r
0d92cdc2 1493 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
1494\r
7da78b1f 1495 Status = gBS->AllocatePool (\r
1496 EfiBootServicesData,\r
0d92cdc2 1497 sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1498 (VOID **) &ModeBuffer\r
1499 );\r
1500 if (EFI_ERROR (Status)) {\r
0d92cdc2 1501 goto Done;\r
7da78b1f 1502 }\r
1503\r
0d92cdc2 1504 ModeBuffer->VbeModeNumber = 0x0012;\r
1505 ModeBuffer->BytesPerScanLine = 640;\r
1506 ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
1507 ModeBuffer->FrameBufferSize = 0;\r
1508 ModeBuffer->HorizontalResolution = 640;\r
1509 ModeBuffer->VerticalResolution = 480;\r
1510 ModeBuffer->BitsPerPixel = 8; \r
1511 ModeBuffer->PixelFormat = PixelBltOnly;\r
7da78b1f 1512\r
1513 BiosVideoPrivate->ModeData = ModeBuffer;\r
1514\r
1515 //\r
1516 // Test to see if the Video Adapter support the 640x480 16 color mode\r
1517 //\r
0d92cdc2 1518 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1519 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
7da78b1f 1520\r
0d92cdc2 1521Done:\r
7da78b1f 1522 //\r
1523 // If there was an error, then free the mode structure\r
1524 //\r
1525 if (EFI_ERROR (Status)) {\r
7da78b1f 1526 if (BiosVideoPrivate->ModeData != NULL) {\r
1527 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1528 }\r
0d92cdc2 1529 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1530 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1531 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1532 }\r
1533 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1534 }\r
7da78b1f 1535 }\r
7da78b1f 1536 return Status;\r
1537}\r
1538//\r
0d92cdc2 1539// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
7da78b1f 1540//\r
f1294e4a 1541/**\r
1542\r
1543 Graphics Output protocol interface to get video mode\r
1544\r
1545\r
1546 @param This - Protocol instance pointer.\r
1547 @param ModeNumber - The mode number to return information on.\r
1548 @param SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
1549 @param Info - Caller allocated buffer that returns information about ModeNumber.\r
1550\r
1551 @return EFI_SUCCESS - Mode information returned.\r
1552 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
1553 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
1554 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
1555\r
1556**/\r
7da78b1f 1557EFI_STATUS\r
1558EFIAPI\r
0d92cdc2 1559BiosVideoGraphicsOutputQueryMode (\r
1560 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1561 IN UINT32 ModeNumber,\r
1562 OUT UINTN *SizeOfInfo,\r
1563 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
7da78b1f 1564 )\r
7da78b1f 1565{\r
0d92cdc2 1566 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1567 EFI_STATUS Status;\r
1568 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1569\r
0d92cdc2 1570 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1571\r
1572 if (BiosVideoPrivate->HardwareNeedsStarting) {\r
0d92cdc2 1573 return EFI_NOT_STARTED;\r
7da78b1f 1574 }\r
1575\r
0d92cdc2 1576 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
7da78b1f 1577 return EFI_INVALID_PARAMETER;\r
1578 }\r
1579\r
0d92cdc2 1580 Status = gBS->AllocatePool (\r
1581 EfiBootServicesData,\r
1582 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
fe74f173 1583 (VOID**) Info\r
0d92cdc2 1584 );\r
1585 if (EFI_ERROR (Status)) {\r
1586 return Status;\r
1587 }\r
1588\r
1589 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1590\r
1591 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1592 (*Info)->Version = 0;\r
1593 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
1594 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
1595 (*Info)->PixelFormat = ModeData->PixelFormat;\r
1596 (*Info)->PixelInformation = ModeData->PixelBitMask;\r
1597\r
1598 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
7da78b1f 1599\r
1600 return EFI_SUCCESS;\r
1601}\r
1602\r
f1294e4a 1603/**\r
1604\r
1605 Graphics Output protocol interface to set video mode\r
1606\r
1607\r
1608 @param This - Protocol instance pointer.\r
1609 @param ModeNumber - The mode number to be set.\r
1610\r
1611 @return EFI_SUCCESS - Graphics mode was changed.\r
1612 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
1613 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
1614\r
1615**/\r
7da78b1f 1616EFI_STATUS\r
1617EFIAPI\r
0d92cdc2 1618BiosVideoGraphicsOutputSetMode (\r
1619 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1620 IN UINT32 ModeNumber\r
7da78b1f 1621 )\r
7da78b1f 1622{\r
0d92cdc2 1623 EFI_STATUS Status;\r
1624 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1625 EFI_IA32_REGISTER_SET Regs;\r
1626 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1627\r
0d92cdc2 1628 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1629\r
0d92cdc2 1630 if (This == NULL) {\r
1631 return EFI_INVALID_PARAMETER;\r
1632 }\r
7da78b1f 1633\r
0d92cdc2 1634 if (ModeNumber >= This->Mode->MaxMode) {\r
1635 return EFI_UNSUPPORTED;\r
1636 }\r
7da78b1f 1637\r
0d92cdc2 1638 if (ModeNumber == This->Mode->Mode) {\r
1639 return EFI_SUCCESS;\r
1640 }\r
7da78b1f 1641\r
0d92cdc2 1642 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
7da78b1f 1643\r
0d92cdc2 1644 if (BiosVideoPrivate->LineBuffer) {\r
1645 gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
1646 }\r
7da78b1f 1647\r
0d92cdc2 1648 if (BiosVideoPrivate->VgaFrameBuffer) {\r
1649 gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
1650 }\r
7da78b1f 1651\r
0d92cdc2 1652 if (BiosVideoPrivate->VbeFrameBuffer) {\r
1653 gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
1654 }\r
7da78b1f 1655\r
0d92cdc2 1656 BiosVideoPrivate->LineBuffer = NULL;\r
1657 Status = gBS->AllocatePool (\r
1658 EfiBootServicesData,\r
1659 ModeData->BytesPerScanLine,\r
fe74f173 1660 (VOID**) &BiosVideoPrivate->LineBuffer\r
0d92cdc2 1661 );\r
1662 if (EFI_ERROR (Status)) {\r
1663 return Status;\r
1664 }\r
1665 //\r
1666 // Clear all registers\r
1667 //\r
1668 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
7da78b1f 1669\r
0d92cdc2 1670 if (ModeData->VbeModeNumber < 0x100) {\r
1671 //\r
1672 // Allocate a working buffer for BLT operations to the VGA frame buffer\r
1673 //\r
1674 BiosVideoPrivate->VgaFrameBuffer = NULL;\r
7da78b1f 1675 Status = gBS->AllocatePool (\r
1676 EfiBootServicesData,\r
0d92cdc2 1677 4 * 480 * 80,\r
fe74f173 1678 (VOID**) &BiosVideoPrivate->VgaFrameBuffer\r
7da78b1f 1679 );\r
1680 if (EFI_ERROR (Status)) {\r
1681 return Status;\r
1682 }\r
1683 //\r
0d92cdc2 1684 // Set VGA Mode\r
7da78b1f 1685 //\r
2776527d 1686 Regs.X.AX = ModeData->VbeModeNumber;\r
0d92cdc2 1687 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 1688\r
0d92cdc2 1689 } else {\r
1690 //\r
1691 // Allocate a working buffer for BLT operations to the VBE frame buffer\r
1692 //\r
1693 BiosVideoPrivate->VbeFrameBuffer = NULL;\r
1694 Status = gBS->AllocatePool (\r
1695 EfiBootServicesData,\r
1696 ModeData->BytesPerScanLine * ModeData->VerticalResolution,\r
fe74f173 1697 (VOID**) &BiosVideoPrivate->VbeFrameBuffer\r
0d92cdc2 1698 );\r
1699 if (EFI_ERROR (Status)) {\r
1700 return Status;\r
1701 }\r
1702 //\r
1703 // Set VBE mode\r
1704 //\r
1705 Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
1706 Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
1707 gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);\r
1708 Regs.X.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
1709 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
49de9dd4 1710 \r
0d92cdc2 1711 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1712 \r
1713 //\r
1714 // Check to see if the call succeeded\r
1715 //\r
1716 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1717 return EFI_DEVICE_ERROR;\r
1718 }\r
1719 //\r
1720 // Initialize the state of the VbeFrameBuffer\r
1721 //\r
1722 Status = BiosVideoPrivate->PciIo->Mem.Read (\r
1723 BiosVideoPrivate->PciIo,\r
1724 EfiPciIoWidthUint32,\r
1725 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1726 (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
1727 (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
1728 BiosVideoPrivate->VbeFrameBuffer\r
1729 );\r
1730 if (EFI_ERROR (Status)) {\r
1731 return Status;\r
7da78b1f 1732 }\r
0d92cdc2 1733 }\r
7da78b1f 1734\r
0d92cdc2 1735 This->Mode->Mode = ModeNumber;\r
1736 This->Mode->Info->Version = 0;\r
1737 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
1738 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
1739 This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
1740 This->Mode->Info->PixelInformation = ModeData->PixelBitMask;\r
1741 This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1742 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
7da78b1f 1743\r
0d92cdc2 1744 //\r
1745 // Frame BufferSize remain unchanged\r
1746 //\r
fe74f173 1747 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ModeData->LinearFrameBuffer;\r
0d92cdc2 1748 This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
7da78b1f 1749\r
0d92cdc2 1750 BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
7da78b1f 1751\r
0d92cdc2 1752 return EFI_SUCCESS;\r
7da78b1f 1753}\r
1754\r
f1294e4a 1755/**\r
1756\r
1757 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1758\r
1759\r
1760 @param PciIo - The pointer of EFI_PCI_IO_PROTOCOL\r
1761 @param VbeBuffer - The data to transfer to screen\r
1762 @param MemAddress - Physical frame buffer base address\r
1763 @param DestinationX - The X coordinate of the destination for BltOperation\r
1764 @param DestinationY - The Y coordinate of the destination for BltOperation\r
1765 @param TotalBytes - The total bytes of copy\r
1766 @param VbePixelWidth - Bytes per pixel\r
1767 @param BytesPerScanLine - Bytes per scan line\r
1768\r
1769 @return None.\r
1770\r
1771**/\r
7da78b1f 1772VOID\r
1773CopyVideoBuffer (\r
1774 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1775 IN UINT8 *VbeBuffer,\r
1776 IN VOID *MemAddress,\r
1777 IN UINTN DestinationX,\r
1778 IN UINTN DestinationY,\r
1779 IN UINTN TotalBytes,\r
1780 IN UINT32 VbePixelWidth,\r
1781 IN UINTN BytesPerScanLine\r
1782 )\r
7da78b1f 1783{\r
1784 UINTN FrameBufferAddr;\r
1785 UINTN CopyBlockNum;\r
1786 UINTN RemainingBytes;\r
1787 UINTN UnalignedBytes;\r
1788 EFI_STATUS Status;\r
1789\r
1790 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
1791\r
1792 //\r
1793 // If TotalBytes is less than 4 bytes, only start byte copy.\r
1794 //\r
1795 if (TotalBytes < 4) {\r
1796 Status = PciIo->Mem.Write (\r
1797 PciIo,\r
1798 EfiPciIoWidthUint8,\r
1799 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1800 (UINT64) FrameBufferAddr,\r
1801 TotalBytes,\r
1802 VbeBuffer\r
1803 );\r
1804 ASSERT_EFI_ERROR (Status);\r
1805 return;\r
1806 }\r
1807\r
1808 //\r
1809 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
1810 //\r
1811 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
1812\r
1813 if (UnalignedBytes != 0) {\r
1814 Status = PciIo->Mem.Write (\r
1815 PciIo,\r
1816 EfiPciIoWidthUint8,\r
1817 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1818 (UINT64) FrameBufferAddr,\r
1819 UnalignedBytes,\r
1820 VbeBuffer\r
1821 );\r
1822 ASSERT_EFI_ERROR (Status);\r
1823 FrameBufferAddr += UnalignedBytes;\r
1824 VbeBuffer += UnalignedBytes;\r
1825 }\r
1826\r
1827 //\r
1828 // Calculate 4-byte block count and remaining bytes.\r
1829 //\r
1830 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
1831 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
1832\r
1833 //\r
1834 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
1835 //\r
1836 if (CopyBlockNum != 0) {\r
1837 Status = PciIo->Mem.Write (\r
1838 PciIo,\r
1839 EfiPciIoWidthUint32,\r
1840 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1841 (UINT64) FrameBufferAddr,\r
1842 CopyBlockNum,\r
1843 VbeBuffer\r
1844 );\r
1845 ASSERT_EFI_ERROR (Status);\r
1846 }\r
1847\r
1848 if (RemainingBytes != 0) {\r
1849 FrameBufferAddr += (CopyBlockNum << 2);\r
1850 VbeBuffer += (CopyBlockNum << 2);\r
1851 Status = PciIo->Mem.Write (\r
1852 PciIo,\r
1853 EfiPciIoWidthUint8,\r
1854 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1855 (UINT64) FrameBufferAddr,\r
1856 RemainingBytes,\r
1857 VbeBuffer\r
1858 );\r
1859 ASSERT_EFI_ERROR (Status);\r
1860 }\r
1861}\r
1862\r
1863//\r
1864// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes\r
1865//\r
f1294e4a 1866/**\r
1867\r
1868 Graphics Output protocol instance to block transfer for VBE device\r
1869\r
1870\r
1871 @param This - Pointer to Graphics Output protocol instance\r
1872 @param BltBuffer - The data to transfer to screen\r
1873 @param BltOperation - The operation to perform\r
1874 @param SourceX - The X coordinate of the source for BltOperation\r
1875 @param SourceY - The Y coordinate of the source for BltOperation\r
1876 @param DestinationX - The X coordinate of the destination for BltOperation\r
1877 @param DestinationY - The Y coordinate of the destination for BltOperation\r
1878 @param Width - The width of a rectangle in the blt rectangle in pixels\r
1879 @param Height - The height of a rectangle in the blt rectangle in pixels\r
1880 @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
1881 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
1882 If a subrectangle of the BltBuffer is used, then Delta represents\r
1883 the number of bytes in a row of the BltBuffer.\r
1884\r
1885 @return EFI_INVALID_PARAMETER - Invalid parameter passed in\r
1886 EFI_SUCCESS - Blt operation success\r
1887\r
1888**/\r
7da78b1f 1889EFI_STATUS\r
1890EFIAPI\r
0d92cdc2 1891BiosVideoGraphicsOutputVbeBlt (\r
1892 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1893 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1894 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1895 IN UINTN SourceX,\r
1896 IN UINTN SourceY,\r
1897 IN UINTN DestinationX,\r
1898 IN UINTN DestinationY,\r
1899 IN UINTN Width,\r
1900 IN UINTN Height,\r
1901 IN UINTN Delta\r
7da78b1f 1902 )\r
7da78b1f 1903{\r
0d92cdc2 1904 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1905 BIOS_VIDEO_MODE_DATA *Mode;\r
1906 EFI_PCI_IO_PROTOCOL *PciIo;\r
1907 EFI_TPL OriginalTPL;\r
1908 UINTN DstY;\r
1909 UINTN SrcY;\r
1910 UINTN DstX;\r
1911 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
1912 VOID *MemAddress;\r
1913 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
1914 UINTN BytesPerScanLine;\r
1915 UINTN Index;\r
1916 UINT8 *VbeBuffer;\r
1917 UINT8 *VbeBuffer1;\r
1918 UINT8 *BltUint8;\r
1919 UINT32 VbePixelWidth;\r
1920 UINT32 Pixel;\r
1921 UINTN TotalBytes;\r
1922\r
1923 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1924 Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
7da78b1f 1925 PciIo = BiosVideoPrivate->PciIo;\r
1926\r
1927 VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
1928 MemAddress = Mode->LinearFrameBuffer;\r
1929 BytesPerScanLine = Mode->BytesPerScanLine;\r
1930 VbePixelWidth = Mode->BitsPerPixel / 8;\r
1931 BltUint8 = (UINT8 *) BltBuffer;\r
1932 TotalBytes = Width * VbePixelWidth;\r
1933\r
0d92cdc2 1934 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 1935 return EFI_INVALID_PARAMETER;\r
1936 }\r
1937\r
1938 if (Width == 0 || Height == 0) {\r
1939 return EFI_INVALID_PARAMETER;\r
1940 }\r
1941 //\r
1942 // We need to fill the Virtual Screen buffer with the blt data.\r
1943 // The virtual screen is upside down, as the first row is the bootom row of\r
1944 // the image.\r
1945 //\r
0d92cdc2 1946 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 1947 //\r
1948 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
1949 //\r
1950 if (SourceY + Height > Mode->VerticalResolution) {\r
1951 return EFI_INVALID_PARAMETER;\r
1952 }\r
1953\r
1954 if (SourceX + Width > Mode->HorizontalResolution) {\r
1955 return EFI_INVALID_PARAMETER;\r
1956 }\r
1957 } else {\r
1958 //\r
1959 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
1960 //\r
1961 if (DestinationY + Height > Mode->VerticalResolution) {\r
1962 return EFI_INVALID_PARAMETER;\r
1963 }\r
1964\r
1965 if (DestinationX + Width > Mode->HorizontalResolution) {\r
1966 return EFI_INVALID_PARAMETER;\r
1967 }\r
1968 }\r
1969 //\r
1970 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
1971 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
1972 // the number of bytes in each row can be computed.\r
1973 //\r
1974 if (Delta == 0) {\r
0d92cdc2 1975 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 1976 }\r
1977 //\r
1978 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
1979 // We would not want a timer based event (Cursor, ...) to come in while we are\r
1980 // doing this operation.\r
1981 //\r
1982 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
1983\r
1984 switch (BltOperation) {\r
0d92cdc2 1985 case EfiBltVideoToBltBuffer:\r
7da78b1f 1986 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
0d92cdc2 1987 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 1988 //\r
0d92cdc2 1989 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
7da78b1f 1990 //\r
1991 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
1992 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
1993 Pixel = *(UINT32 *) (VbeBuffer);\r
1994 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
1995 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
1996 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
1997 Blt->Reserved = 0;\r
1998 Blt++;\r
1999 VbeBuffer += VbePixelWidth;\r
2000 }\r
2001\r
2002 }\r
2003 break;\r
2004\r
0d92cdc2 2005 case EfiBltVideoToVideo:\r
7da78b1f 2006 for (Index = 0; Index < Height; Index++) {\r
2007 if (DestinationY <= SourceY) {\r
2008 SrcY = SourceY + Index;\r
2009 DstY = DestinationY + Index;\r
2010 } else {\r
2011 SrcY = SourceY + Height - Index - 1;\r
2012 DstY = DestinationY + Height - Index - 1;\r
2013 }\r
2014\r
2015 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
2016 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
2017\r
2018 gBS->CopyMem (\r
2019 VbeBuffer,\r
2020 VbeBuffer1,\r
2021 TotalBytes\r
2022 );\r
2023\r
2024 //\r
2025 // Update physical frame buffer.\r
2026 //\r
2027 CopyVideoBuffer (\r
2028 PciIo,\r
2029 VbeBuffer,\r
2030 MemAddress,\r
2031 DestinationX,\r
2032 DstY,\r
2033 TotalBytes,\r
2034 VbePixelWidth,\r
2035 BytesPerScanLine\r
2036 );\r
2037 }\r
2038 break;\r
2039\r
0d92cdc2 2040 case EfiBltVideoFill:\r
7da78b1f 2041 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
0d92cdc2 2042 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
7da78b1f 2043 //\r
0d92cdc2 2044 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2045 //\r
2046 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2047 (\r
2048 (Blt->Green & Mode->Green.Mask) <<\r
2049 Mode->Green.Position\r
2050 ) |\r
2051 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2052\r
2053 for (Index = 0; Index < Width; Index++) {\r
2054 gBS->CopyMem (\r
2055 VbeBuffer,\r
2056 &Pixel,\r
2057 VbePixelWidth\r
2058 );\r
2059 VbeBuffer += VbePixelWidth;\r
2060 }\r
2061\r
2062 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2063 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
2064 gBS->CopyMem (\r
2065 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
2066 VbeBuffer,\r
2067 TotalBytes\r
2068 );\r
2069 }\r
2070 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
2071 //\r
2072 // Update physical frame buffer.\r
2073 //\r
2074 CopyVideoBuffer (\r
2075 PciIo,\r
2076 VbeBuffer,\r
2077 MemAddress,\r
2078 DestinationX,\r
2079 DstY,\r
2080 TotalBytes,\r
2081 VbePixelWidth,\r
2082 BytesPerScanLine\r
2083 );\r
2084 }\r
7da78b1f 2085 break;\r
2086\r
0d92cdc2 2087 case EfiBltBufferToVideo:\r
7da78b1f 2088 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
0d92cdc2 2089 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 2090 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2091 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2092 //\r
0d92cdc2 2093 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2094 //\r
2095 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2096 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
2097 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2098 gBS->CopyMem (\r
2099 VbeBuffer,\r
2100 &Pixel,\r
2101 VbePixelWidth\r
2102 );\r
2103 Blt++;\r
2104 VbeBuffer += VbePixelWidth;\r
2105 }\r
2106\r
2107 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2108\r
2109 //\r
2110 // Update physical frame buffer.\r
2111 //\r
2112 CopyVideoBuffer (\r
2113 PciIo,\r
2114 VbeBuffer,\r
2115 MemAddress,\r
2116 DestinationX,\r
2117 DstY,\r
2118 TotalBytes,\r
2119 VbePixelWidth,\r
2120 BytesPerScanLine\r
2121 );\r
2122 }\r
2123 break;\r
fe74f173 2124 default:\r
2125 break;\r
7da78b1f 2126 }\r
2127\r
2128 gBS->RestoreTPL (OriginalTPL);\r
2129\r
2130 return EFI_SUCCESS;\r
2131}\r
2132\r
f1294e4a 2133/**\r
2134\r
2135 Write graphics controller registers\r
2136\r
2137\r
2138 @param PciIo - Pointer to PciIo protocol instance of the controller\r
2139 @param Address - Register address\r
2140 @param Data - Data to be written to register\r
2141\r
2142 @return None\r
2143\r
2144**/\r
7da78b1f 2145STATIC\r
2146VOID\r
2147WriteGraphicsController (\r
2148 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2149 IN UINTN Address,\r
2150 IN UINTN Data\r
2151 )\r
7da78b1f 2152{\r
2153 Address = Address | (Data << 8);\r
2154 PciIo->Io.Write (\r
2155 PciIo,\r
2156 EfiPciIoWidthUint16,\r
2157 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2158 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
2159 1,\r
2160 &Address\r
2161 );\r
2162}\r
2163\r
f1294e4a 2164/**\r
2165\r
2166 Read the four bit plane of VGA frame buffer\r
2167\r
2168\r
2169 @param PciIo - Pointer to PciIo protocol instance of the controller\r
2170 @param HardwareBuffer - Hardware VGA frame buffer address\r
2171 @param MemoryBuffer - Memory buffer address\r
2172 @param WidthInBytes - Number of bytes in a line to read\r
2173 @param Height - Height of the area to read\r
2174\r
2175 @return None\r
2176\r
2177**/\r
7da78b1f 2178VOID\r
2179VgaReadBitPlanes (\r
2180 EFI_PCI_IO_PROTOCOL *PciIo,\r
2181 UINT8 *HardwareBuffer,\r
2182 UINT8 *MemoryBuffer,\r
2183 UINTN WidthInBytes,\r
2184 UINTN Height\r
2185 )\r
7da78b1f 2186{\r
2187 UINTN BitPlane;\r
2188 UINTN Rows;\r
2189 UINTN FrameBufferOffset;\r
2190 UINT8 *Source;\r
2191 UINT8 *Destination;\r
2192\r
2193 //\r
2194 // Program the Mode Register Write mode 0, Read mode 0\r
2195 //\r
2196 WriteGraphicsController (\r
2197 PciIo,\r
2198 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2199 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
2200 );\r
2201\r
2202 for (BitPlane = 0, FrameBufferOffset = 0;\r
2203 BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
2204 BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
2205 ) {\r
2206 //\r
2207 // Program the Read Map Select Register to select the correct bit plane\r
2208 //\r
2209 WriteGraphicsController (\r
2210 PciIo,\r
2211 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
2212 BitPlane\r
2213 );\r
2214\r
2215 Source = HardwareBuffer;\r
2216 Destination = MemoryBuffer + FrameBufferOffset;\r
2217\r
2218 for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
2219 PciIo->Mem.Read (\r
2220 PciIo,\r
2221 EfiPciIoWidthUint8,\r
fe74f173 2222 (UINT8) EFI_PCI_IO_PASS_THROUGH_BAR,\r
2223 (UINT64)(UINTN) Source,\r
7da78b1f 2224 WidthInBytes,\r
2225 (VOID *) Destination\r
2226 );\r
2227 }\r
2228 }\r
2229}\r
2230\r
f1294e4a 2231/**\r
2232\r
2233 Internal routine to convert VGA color to Grahpics Output color\r
2234\r
2235\r
2236 @param MemoryBuffer - Buffer containing VGA color\r
2237 @param X - The X coordinate of pixel on screen\r
2238 @param Y - The Y coordinate of pixel on screen\r
2239 @param BltBuffer - Buffer to contain converted Grahpics Output color\r
2240\r
2241 @return None\r
2242\r
2243**/\r
7da78b1f 2244VOID\r
0d92cdc2 2245VgaConvertToGraphicsOutputColor (\r
2246 UINT8 *MemoryBuffer,\r
2247 UINTN X,\r
2248 UINTN Y,\r
2249 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
7da78b1f 2250 )\r
7da78b1f 2251{\r
2252 UINTN Mask;\r
2253 UINTN Bit;\r
2254 UINTN Color;\r
2255\r
2256 MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));\r
2257 Mask = mVgaBitMaskTable[X & 0x07];\r
2258 for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
2259 if (*MemoryBuffer & Mask) {\r
2260 Color |= Bit;\r
2261 }\r
2262 }\r
2263\r
0d92cdc2 2264 *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
7da78b1f 2265}\r
2266\r
f1294e4a 2267/**\r
7da78b1f 2268\r
0d92cdc2 2269 Internal routine to convert Grahpics Output color to VGA color\r
7da78b1f 2270\r
7da78b1f 2271\r
f1294e4a 2272 @param BltBuffer - buffer containing Grahpics Output color\r
7da78b1f 2273\r
f1294e4a 2274 @return Converted VGA color\r
7da78b1f 2275\r
f1294e4a 2276**/\r
2277UINT8\r
2278VgaConvertColor (\r
2279 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2280 )\r
7da78b1f 2281{\r
2282 UINT8 Color;\r
2283\r
2284 Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
2285 if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
2286 Color |= 0x08;\r
2287 }\r
2288\r
2289 return Color;\r
2290}\r
2291\r
f1294e4a 2292/**\r
2293 Grahpics Output protocol instance to block transfer for VGA device\r
2294\r
2295 @param This Pointer to Grahpics Output protocol instance\r
2296 @param BltBuffer The data to transfer to screen\r
2297 @param BltOperation The operation to perform\r
2298 @param SourceX The X coordinate of the source for BltOperation\r
2299 @param SourceY The Y coordinate of the source for BltOperation\r
2300 @param DestinationX The X coordinate of the destination for BltOperation\r
2301 @param DestinationY The Y coordinate of the destination for BltOperation\r
2302 @param Width The width of a rectangle in the blt rectangle in pixels\r
2303 @param Height The height of a rectangle in the blt rectangle in pixels\r
2304 @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
2305 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
2306 If a subrectangle of the BltBuffer is used, then Delta represents\r
2307 the number of bytes in a row of the BltBuffer.\r
2308\r
2309 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2310 @retval EFI_SUCCESS Blt operation success\r
2311\r
2312**/\r
7da78b1f 2313EFI_STATUS\r
2314EFIAPI\r
0d92cdc2 2315BiosVideoGraphicsOutputVgaBlt (\r
2316 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2317 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2318 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2319 IN UINTN SourceX,\r
2320 IN UINTN SourceY,\r
2321 IN UINTN DestinationX,\r
2322 IN UINTN DestinationY,\r
2323 IN UINTN Width,\r
2324 IN UINTN Height,\r
2325 IN UINTN Delta\r
7da78b1f 2326 )\r
7da78b1f 2327{\r
2328 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2329 EFI_TPL OriginalTPL;\r
2330 UINT8 *MemAddress;\r
2331 UINTN BytesPerScanLine;\r
49de9dd4 2332 //UINTN BytesPerBitPlane;\r
7da78b1f 2333 UINTN Bit;\r
2334 UINTN Index;\r
2335 UINTN Index1;\r
2336 UINTN StartAddress;\r
2337 UINTN Bytes;\r
2338 UINTN Offset;\r
2339 UINT8 LeftMask;\r
2340 UINT8 RightMask;\r
2341 UINTN Address;\r
2342 UINTN AddressFix;\r
2343 UINT8 *Address1;\r
2344 UINT8 *SourceAddress;\r
2345 UINT8 *DestinationAddress;\r
2346 EFI_PCI_IO_PROTOCOL *PciIo;\r
2347 UINT8 Data;\r
2348 UINT8 PixelColor;\r
2349 UINT8 *VgaFrameBuffer;\r
2350 UINTN SourceOffset;\r
2351 UINTN SourceWidth;\r
2352 UINTN Rows;\r
2353 UINTN Columns;\r
2354 UINTN X;\r
2355 UINTN Y;\r
0d92cdc2 2356 UINTN CurrentMode;\r
7da78b1f 2357\r
0d92cdc2 2358 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 2359\r
0d92cdc2 2360 CurrentMode = This->Mode->Mode;\r
7da78b1f 2361 PciIo = BiosVideoPrivate->PciIo;\r
0d92cdc2 2362 MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
2363 BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
49de9dd4 2364 //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;\r
7da78b1f 2365 VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
2366\r
0d92cdc2 2367 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 2368 return EFI_INVALID_PARAMETER;\r
2369 }\r
2370\r
2371 if (Width == 0 || Height == 0) {\r
2372 return EFI_INVALID_PARAMETER;\r
2373 }\r
2374 //\r
2375 // We need to fill the Virtual Screen buffer with the blt data.\r
2376 // The virtual screen is upside down, as the first row is the bootom row of\r
2377 // the image.\r
2378 //\r
0d92cdc2 2379 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 2380 //\r
2381 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2382 //\r
0d92cdc2 2383 if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2384 return EFI_INVALID_PARAMETER;\r
2385 }\r
2386\r
0d92cdc2 2387 if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2388 return EFI_INVALID_PARAMETER;\r
2389 }\r
2390 } else {\r
2391 //\r
2392 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2393 //\r
0d92cdc2 2394 if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2395 return EFI_INVALID_PARAMETER;\r
2396 }\r
2397\r
0d92cdc2 2398 if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2399 return EFI_INVALID_PARAMETER;\r
2400 }\r
2401 }\r
2402 //\r
2403 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2404 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2405 // the number of bytes in each row can be computed.\r
2406 //\r
2407 if (Delta == 0) {\r
0d92cdc2 2408 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 2409 }\r
2410 //\r
2411 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2412 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2413 // doing this operation.\r
2414 //\r
2415 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2416\r
2417 //\r
2418 // Compute some values we need for VGA\r
2419 //\r
2420 switch (BltOperation) {\r
0d92cdc2 2421 case EfiBltVideoToBltBuffer:\r
7da78b1f 2422\r
2423 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2424 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2425\r
2426 //\r
2427 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2428 //\r
2429 VgaReadBitPlanes (\r
2430 PciIo,\r
2431 MemAddress + SourceOffset,\r
2432 VgaFrameBuffer + SourceOffset,\r
2433 SourceWidth,\r
2434 Height\r
2435 );\r
2436\r
2437 //\r
0d92cdc2 2438 // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
7da78b1f 2439 //\r
2440 BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
2441 for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {\r
2442 for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {\r
0d92cdc2 2443 VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer);\r
7da78b1f 2444 }\r
2445\r
2446 BltBuffer -= Width;\r
2447 }\r
2448\r
2449 break;\r
2450\r
0d92cdc2 2451 case EfiBltVideoToVideo:\r
7da78b1f 2452 //\r
2453 // Check for an aligned Video to Video operation\r
2454 //\r
2455 if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
2456 //\r
2457 // Program the Mode Register Write mode 1, Read mode 0\r
2458 //\r
2459 WriteGraphicsController (\r
0d92cdc2 2460 PciIo,\r
7da78b1f 2461 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2462 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
2463 );\r
2464\r
2465 SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
2466 DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2467 Bytes = Width >> 3;\r
2468 for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
2469 PciIo->CopyMem (\r
2470 PciIo,\r
2471 EfiPciIoWidthUint8,\r
2472 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2473 (UINT64) ((UINTN)DestinationAddress + Offset),\r
7da78b1f 2474 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2475 (UINT64) ((UINTN)SourceAddress + Offset),\r
7da78b1f 2476 Bytes\r
2477 );\r
2478 }\r
2479 } else {\r
2480 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2481 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2482\r
2483 //\r
2484 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2485 //\r
2486 VgaReadBitPlanes (\r
2487 PciIo,\r
2488 MemAddress + SourceOffset,\r
2489 VgaFrameBuffer + SourceOffset,\r
2490 SourceWidth,\r
2491 Height\r
2492 );\r
2493 }\r
2494\r
2495 break;\r
2496\r
0d92cdc2 2497 case EfiBltVideoFill:\r
7da78b1f 2498 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2499 Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
2500 LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
2501 RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
2502 if (Bytes == 0) {\r
49de9dd4 2503 LeftMask = (UINT8) (LeftMask & RightMask);\r
7da78b1f 2504 RightMask = 0;\r
2505 }\r
2506\r
2507 if (LeftMask == 0xff) {\r
2508 StartAddress--;\r
2509 Bytes++;\r
2510 LeftMask = 0;\r
2511 }\r
2512\r
2513 if (RightMask == 0xff) {\r
2514 Bytes++;\r
2515 RightMask = 0;\r
2516 }\r
2517\r
2518 PixelColor = VgaConvertColor (BltBuffer);\r
2519\r
2520 //\r
2521 // Program the Mode Register Write mode 2, Read mode 0\r
2522 //\r
2523 WriteGraphicsController (\r
0d92cdc2 2524 PciIo,\r
7da78b1f 2525 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2526 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2527 );\r
2528\r
2529 //\r
2530 // Program the Data Rotate/Function Select Register to replace\r
2531 //\r
2532 WriteGraphicsController (\r
0d92cdc2 2533 PciIo,\r
7da78b1f 2534 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2535 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2536 );\r
2537\r
2538 if (LeftMask != 0) {\r
2539 //\r
2540 // Program the BitMask register with the Left column mask\r
2541 //\r
2542 WriteGraphicsController (\r
0d92cdc2 2543 PciIo,\r
7da78b1f 2544 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2545 LeftMask\r
2546 );\r
2547\r
2548 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2549 //\r
2550 // Read data from the bit planes into the latches\r
2551 //\r
2552 PciIo->Mem.Read (\r
2553 PciIo,\r
2554 EfiPciIoWidthUint8,\r
2555 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2556 (UINT64) Address,\r
2557 1,\r
2558 &Data\r
2559 );\r
2560 //\r
2561 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2562 //\r
2563 PciIo->Mem.Write (\r
2564 PciIo,\r
2565 EfiPciIoWidthUint8,\r
2566 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2567 (UINT64) Address,\r
2568 1,\r
2569 &PixelColor\r
2570 );\r
2571 }\r
2572 }\r
2573\r
2574 if (Bytes > 1) {\r
2575 //\r
2576 // Program the BitMask register with the middle column mask of 0xff\r
2577 //\r
2578 WriteGraphicsController (\r
0d92cdc2 2579 PciIo,\r
7da78b1f 2580 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2581 0xff\r
2582 );\r
2583\r
2584 for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
2585 PciIo->Mem.Write (\r
2586 PciIo,\r
2587 EfiPciIoWidthFillUint8,\r
2588 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2589 (UINT64) Address,\r
2590 Bytes - 1,\r
2591 &PixelColor\r
2592 );\r
2593 }\r
2594 }\r
2595\r
2596 if (RightMask != 0) {\r
2597 //\r
2598 // Program the BitMask register with the Right column mask\r
2599 //\r
2600 WriteGraphicsController (\r
0d92cdc2 2601 PciIo,\r
7da78b1f 2602 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2603 RightMask\r
2604 );\r
2605\r
2606 for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
2607 //\r
2608 // Read data from the bit planes into the latches\r
2609 //\r
2610 PciIo->Mem.Read (\r
2611 PciIo,\r
2612 EfiPciIoWidthUint8,\r
2613 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2614 (UINT64) Address,\r
2615 1,\r
2616 &Data\r
2617 );\r
2618 //\r
2619 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2620 //\r
2621 PciIo->Mem.Write (\r
2622 PciIo,\r
2623 EfiPciIoWidthUint8,\r
2624 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2625 (UINT64) Address,\r
2626 1,\r
2627 &PixelColor\r
2628 );\r
2629 }\r
2630 }\r
2631 break;\r
2632\r
0d92cdc2 2633 case EfiBltBufferToVideo:\r
7da78b1f 2634 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2635 LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
2636\r
2637 //\r
2638 // Program the Mode Register Write mode 2, Read mode 0\r
2639 //\r
2640 WriteGraphicsController (\r
0d92cdc2 2641 PciIo,\r
7da78b1f 2642 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2643 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2644 );\r
2645\r
2646 //\r
2647 // Program the Data Rotate/Function Select Register to replace\r
2648 //\r
2649 WriteGraphicsController (\r
0d92cdc2 2650 PciIo,\r
7da78b1f 2651 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2652 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2653 );\r
2654\r
2655 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2656 for (Index1 = 0; Index1 < Width; Index1++) {\r
2657 BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
2658 }\r
2659 AddressFix = Address;\r
2660\r
2661 for (Bit = 0; Bit < 8; Bit++) {\r
2662 //\r
2663 // Program the BitMask register with the Left column mask\r
2664 //\r
2665 WriteGraphicsController (\r
0d92cdc2 2666 PciIo,\r
7da78b1f 2667 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2668 LeftMask\r
2669 );\r
2670\r
2671 for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
2672 //\r
2673 // Read data from the bit planes into the latches\r
2674 //\r
2675 PciIo->Mem.Read (\r
2676 PciIo,\r
2677 EfiPciIoWidthUint8,\r
2678 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2679 (UINT64)(UINTN) Address1,\r
7da78b1f 2680 1,\r
2681 &Data\r
2682 );\r
2683\r
2684 PciIo->Mem.Write (\r
2685 PciIo,\r
2686 EfiPciIoWidthUint8,\r
2687 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2688 (UINT64)(UINTN) Address1,\r
7da78b1f 2689 1,\r
2690 &BiosVideoPrivate->LineBuffer[Index1]\r
2691 );\r
2692 }\r
2693\r
2694 LeftMask = (UINT8) (LeftMask >> 1);\r
2695 if (LeftMask == 0) {\r
2696 LeftMask = 0x80;\r
2697 AddressFix++;\r
2698 }\r
2699 }\r
2700 }\r
2701\r
fe74f173 2702 break;\r
2703 default:\r
7da78b1f 2704 break;\r
2705 }\r
2706\r
2707 gBS->RestoreTPL (OriginalTPL);\r
2708\r
2709 return EFI_SUCCESS;\r
2710}\r
2711//\r
2712// VGA Mini Port Protocol Functions\r
2713//\r
f1294e4a 2714/**\r
2715 VgaMiniPort protocol interface to set mode\r
2716\r
2717 @param This Pointer to VgaMiniPort protocol instance\r
2718 @param ModeNumber The index of the mode\r
2719\r
2720 @retval EFI_UNSUPPORTED The requested mode is not supported\r
2721 @retval EFI_SUCCESS The requested mode is set successfully\r
2722\r
2723**/\r
7da78b1f 2724EFI_STATUS\r
2725EFIAPI\r
2726BiosVideoVgaMiniPortSetMode (\r
2727 IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
2728 IN UINTN ModeNumber\r
2729 )\r
7da78b1f 2730{\r
2731 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2732 EFI_IA32_REGISTER_SET Regs;\r
2733\r
0d92cdc2 2734 if (This == NULL) {\r
2735 return EFI_INVALID_PARAMETER;\r
2736 }\r
2737\r
7da78b1f 2738 //\r
2739 // Make sure the ModeNumber is a valid value\r
2740 //\r
2741 if (ModeNumber >= This->MaxMode) {\r
2742 return EFI_UNSUPPORTED;\r
2743 }\r
2744 //\r
2745 // Get the device structure for this device\r
2746 //\r
2747 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
0d92cdc2 2748 \r
7da78b1f 2749 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
2750\r
2751 switch (ModeNumber) {\r
2752 case 0:\r
2753 //\r
2754 // Set the 80x25 Text VGA Mode\r
2755 //\r
2756 Regs.H.AH = 0x00;\r
2757 Regs.H.AL = 0x83;\r
0d92cdc2 2758 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2759 \r
7da78b1f 2760 Regs.H.AH = 0x11;\r
2761 Regs.H.AL = 0x14;\r
2762 Regs.H.BL = 0;\r
0d92cdc2 2763 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2764 \r
7da78b1f 2765 break;\r
2766\r
2767 case 1:\r
2768 //\r
2769 // Set the 80x50 Text VGA Mode\r
2770 //\r
2771 Regs.H.AH = 0x00;\r
2772 Regs.H.AL = 0x83;\r
0d92cdc2 2773 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2774 \r
7da78b1f 2775 Regs.H.AH = 0x11;\r
2776 Regs.H.AL = 0x12;\r
2777 Regs.H.BL = 0;\r
0d92cdc2 2778 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 2779 break;\r
2780\r
2781 default:\r
2782 return EFI_UNSUPPORTED;\r
2783 }\r
2784\r
2785 return EFI_SUCCESS;\r
2786}\r