]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BiosVideoThunkDxe/BiosVideo.c
Final boot image just need combination, no need to create directory
[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
d0c94e59 602 IA32_REGISTER_SET Regs;\r
0d92cdc2 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
d0c94e59 1034 IA32_REGISTER_SET Regs;\r
0d92cdc2 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
a39d85f6 1091 // INT 10 - VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION\r
1092 //\r
1093 // AX = 4F00h\r
1094 // ES:DI -> buffer for SuperVGA information (see #00077)\r
1095 // Return: AL = 4Fh if function supported\r
1096 // AH = status\r
1097 // 00h successful\r
1098 // ES:DI buffer filled\r
1099 // 01h failed\r
1100 // ---VBE v2.0---\r
1101 // 02h function not supported by current hardware configuration\r
1102 // 03h function invalid in current video mode\r
1103 // Desc: determine whether VESA BIOS extensions are present and the capabilities\r
1104 // supported by the display adapter\r
1105 //\r
7da78b1f 1106 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1107 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;\r
1108 gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);\r
1109 BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;\r
d0c94e59 1110 Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
0d92cdc2 1111 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);\r
7da78b1f 1112\r
0d92cdc2 1113 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
237bb9d0 1114 \r
7da78b1f 1115 Status = EFI_DEVICE_ERROR;\r
1116\r
1117 //\r
1118 // See if the VESA call succeeded\r
1119 //\r
1120 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1121 return Status;\r
1122 }\r
1123 //\r
1124 // Check for 'VESA' signature\r
1125 //\r
1126 if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {\r
1127 return Status;\r
1128 }\r
1129 //\r
1130 // Check to see if this is VBE 2.0 or higher\r
1131 //\r
1132 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {\r
1133 return Status;\r
1134 }\r
0d92cdc2 1135\r
1136 //\r
1137 // Read EDID information\r
1138 //\r
a39d85f6 1139 // INT 10 - VESA VBE/DC (Display Data Channel) - READ EDID\r
1140 //\r
1141 // AX = 4F15h\r
1142 // BL = 01h\r
1143 // CX = 0000h\r
1144 // DX = 0000h\r
1145 // ES:DI -> 128-byte buffer for EDID record (see #00127)\r
1146 // Return: AL = 4Fh if function supported\r
1147 // AH = status\r
1148 // 00h successful\r
1149 // ES:DI buffer filled\r
1150 // 01h failed (e.g. non-DDC monitor)\r
1151 //\r
0d92cdc2 1152 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1153 Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;\r
1154 Regs.X.BX = 1;\r
1155 Regs.X.CX = 0;\r
1156 Regs.X.DX = 0;\r
d0c94e59 1157 Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
0d92cdc2 1158 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);\r
1159\r
1160 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1161 \r
1162 //\r
1163 // See if the VESA call succeeded\r
1164 //\r
1165 EdidFound = FALSE;\r
1166 if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1167 //\r
1168 // Parse EDID data structure to retrieve modes supported by monitor\r
1169 //\r
1170 if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {\r
1171 EdidFound = TRUE;\r
1172\r
1173 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1174 Status = gBS->AllocatePool (\r
1175 EfiBootServicesData,\r
1176 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
fe74f173 1177 (VOID**) &BiosVideoPrivate->EdidDiscovered.Edid\r
0d92cdc2 1178 );\r
1179 if (EFI_ERROR (Status)) {\r
1180 goto Done;\r
1181 }\r
1182 gBS->CopyMem (\r
1183 BiosVideoPrivate->EdidDiscovered.Edid,\r
1184 BiosVideoPrivate->VbeEdidDataBlock,\r
1185 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1186 );\r
1187\r
1188 BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;\r
1189 Status = gBS->AllocatePool (\r
1190 EfiBootServicesData,\r
1191 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,\r
fe74f173 1192 (VOID**)&BiosVideoPrivate->EdidActive.Edid\r
0d92cdc2 1193 );\r
1194 if (EFI_ERROR (Status)) {\r
1195 goto Done;\r
1196 }\r
1197 gBS->CopyMem (\r
1198 BiosVideoPrivate->EdidActive.Edid,\r
1199 BiosVideoPrivate->VbeEdidDataBlock,\r
1200 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE\r
1201 );\r
1202 } else {\r
1203 BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;\r
1204 BiosVideoPrivate->EdidDiscovered.Edid = NULL;\r
1205\r
1206 BiosVideoPrivate->EdidActive.SizeOfEdid = 0;\r
1207 BiosVideoPrivate->EdidActive.Edid = NULL;\r
1208 }\r
1209 }\r
1210\r
7da78b1f 1211 //\r
0d92cdc2 1212 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode\r
7da78b1f 1213 //\r
1214 ModeNumberPtr = (UINT16 *)\r
1215 (\r
1216 (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |\r
1217 ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)\r
1218 );\r
0d92cdc2 1219\r
1220 PreferMode = 0;\r
1221 ModeNumber = 0;\r
1222\r
7da78b1f 1223 for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {\r
1224 //\r
1225 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.\r
1226 //\r
1227 if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {\r
1228 continue;\r
1229 }\r
1230 //\r
1231 // Get the information about the mode\r
1232 //\r
a39d85f6 1233 // INT 10 - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION\r
1234 //\r
1235 // AX = 4F01h\r
1236 // CX = SuperVGA video mode (see #04082 for bitfields)\r
1237 // ES:DI -> 256-byte buffer for mode information (see #00079)\r
1238 // Return: AL = 4Fh if function supported\r
1239 // AH = status\r
1240 // 00h successful\r
1241 // ES:DI buffer filled\r
1242 // 01h failed\r
1243 // Desc: determine the attributes of the specified video mode\r
1244 //\r
7da78b1f 1245 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
1246 Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;\r
1247 Regs.X.CX = *ModeNumberPtr;\r
1248 gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);\r
d0c94e59 1249 Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
0d92cdc2 1250 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);\r
7da78b1f 1251\r
0d92cdc2 1252 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1253 \r
7da78b1f 1254 //\r
1255 // See if the call succeeded. If it didn't, then try the next mode.\r
1256 //\r
1257 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1258 continue;\r
1259 }\r
1260 //\r
1261 // See if the mode supports color. If it doesn't then try the next mode.\r
1262 //\r
1263 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {\r
1264 continue;\r
1265 }\r
1266 //\r
1267 // See if the mode supports graphics. If it doesn't then try the next mode.\r
1268 //\r
1269 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {\r
1270 continue;\r
1271 }\r
1272 //\r
1273 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.\r
1274 //\r
1275 if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {\r
1276 continue;\r
1277 }\r
1278 //\r
1279 // See if the mode supports 32 bit color. If it doesn't then try the next mode.\r
1280 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the\r
1281 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel\r
1282 //\r
1283 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {\r
1284 continue;\r
1285 }\r
1286\r
1287 if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {\r
1288 continue;\r
1289 }\r
1290\r
1291 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {\r
1292 continue;\r
1293 }\r
1294 //\r
1295 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.\r
1296 //\r
1297 if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {\r
1298 continue;\r
1299 }\r
0d92cdc2 1300\r
1301 if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {\r
1302 //\r
1303 // EDID exist, check whether this mode match with any mode in EDID\r
1304 //\r
1305 Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1306 Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
1307 if (SearchEdidTiming (&ValidEdidTiming, &Timing) == FALSE) {\r
1308 continue;\r
1309 }\r
1310 }\r
1311\r
7da78b1f 1312 //\r
0d92cdc2 1313 // Select a reasonable mode to be set for current display mode\r
7da78b1f 1314 //\r
1315 ModeFound = FALSE;\r
0d92cdc2 1316\r
7da78b1f 1317 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&\r
1318 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768\r
1319 ) {\r
1320 ModeFound = TRUE;\r
1321 }\r
7da78b1f 1322 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&\r
1323 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600\r
1324 ) {\r
1325 ModeFound = TRUE;\r
0d92cdc2 1326 PreferMode = ModeNumber;\r
7da78b1f 1327 }\r
7da78b1f 1328 if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&\r
1329 BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480\r
1330 ) {\r
1331 ModeFound = TRUE;\r
1332 }\r
0d92cdc2 1333 if ((!EdidFound) && (!ModeFound)) {\r
1334 //\r
1335 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480\r
1336 //\r
7da78b1f 1337 continue;\r
1338 }\r
0d92cdc2 1339\r
7da78b1f 1340 //\r
1341 // Add mode to the list of available modes\r
1342 //\r
0d92cdc2 1343 ModeNumber ++;\r
7da78b1f 1344 Status = gBS->AllocatePool (\r
1345 EfiBootServicesData,\r
0d92cdc2 1346 ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1347 (VOID **) &ModeBuffer\r
1348 );\r
1349 if (EFI_ERROR (Status)) {\r
1350 goto Done;\r
1351 }\r
1352\r
0d92cdc2 1353 if (ModeNumber > 1) {\r
7da78b1f 1354 gBS->CopyMem (\r
1355 ModeBuffer,\r
1356 BiosVideoPrivate->ModeData,\r
0d92cdc2 1357 (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)\r
7da78b1f 1358 );\r
1359 }\r
1360\r
1361 if (BiosVideoPrivate->ModeData != NULL) {\r
1362 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1363 }\r
1364\r
0d92cdc2 1365 CurrentModeData = &ModeBuffer[ModeNumber - 1];\r
1366 CurrentModeData->VbeModeNumber = *ModeNumberPtr;\r
7da78b1f 1367 if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {\r
0d92cdc2 1368 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;\r
1369 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;\r
1370 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);\r
1371 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;\r
1372 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);\r
1373 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;\r
1374 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);\r
1375 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;\r
1376 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);\r
7da78b1f 1377 } else {\r
0d92cdc2 1378 CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;\r
1379 CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;\r
1380 CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);\r
1381 CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;\r
1382 CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);\r
1383 CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;\r
1384 CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);\r
1385 CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;\r
1386 CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);\r
7da78b1f 1387 }\r
0d92cdc2 1388 CurrentModeData->PixelFormat = PixelBitMask;\r
1389 if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&\r
1390 (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {\r
1391 if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {\r
1392 CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
1393 } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {\r
1394 CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
1395 }\r
7da78b1f 1396 }\r
0d92cdc2 1397 CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;\r
1398 CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;\r
1399 CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;\r
1400 CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;\r
7da78b1f 1401\r
0d92cdc2 1402 CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;\r
1403 CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;\r
1404 CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;\r
1405 CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;\r
7da78b1f 1406\r
0d92cdc2 1407 CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;\r
7da78b1f 1408\r
1409 BiosVideoPrivate->ModeData = ModeBuffer;\r
1410 }\r
1411 //\r
0d92cdc2 1412 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT\r
7da78b1f 1413 //\r
0d92cdc2 1414 if (ModeNumber == 0) {\r
7da78b1f 1415 Status = EFI_DEVICE_ERROR;\r
1416 goto Done;\r
1417 }\r
0d92cdc2 1418\r
1419 //\r
1420 // Allocate buffer for Graphics Output Protocol mode information\r
1421 //\r
1422 Status = gBS->AllocatePool (\r
1423 EfiBootServicesData,\r
1424 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1425 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1426 );\r
1427 if (EFI_ERROR (Status)) {\r
1428 goto Done;\r
1429 }\r
1430 GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;\r
1431 Status = gBS->AllocatePool (\r
1432 EfiBootServicesData,\r
1433 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1434 (VOID **) &GraphicsOutputMode->Info\r
1435 );\r
1436 if (EFI_ERROR (Status)) {\r
1437 goto Done;\r
1438 }\r
1439\r
1440 GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;\r
1441 //\r
1442 // Current mode is unknow till now, set it to an invalid mode.\r
1443 //\r
1444 GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1445\r
7da78b1f 1446 //\r
1447 // Find the best mode to initialize\r
1448 //\r
0d92cdc2 1449 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);\r
7da78b1f 1450 if (EFI_ERROR (Status)) {\r
0d92cdc2 1451 for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {\r
1452 Status = BiosVideoGraphicsOutputSetMode (\r
1453 &BiosVideoPrivate->GraphicsOutput,\r
1454 (UINT32) PreferMode\r
1455 );\r
1456 if (!EFI_ERROR (Status)) {\r
1457 break;\r
7da78b1f 1458 }\r
1459 }\r
0d92cdc2 1460 if (PreferMode == ModeNumber) {\r
1461 //\r
1462 // None mode is set successfully.\r
1463 //\r
1464 goto Done;\r
1465 }\r
7da78b1f 1466 }\r
1467\r
1468Done:\r
1469 //\r
1470 // If there was an error, then free the mode structure\r
1471 //\r
1472 if (EFI_ERROR (Status)) {\r
1473 if (BiosVideoPrivate->ModeData != NULL) {\r
1474 gBS->FreePool (BiosVideoPrivate->ModeData);\r
0d92cdc2 1475 }\r
1476 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1477 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1478 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1479 }\r
1480 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
7da78b1f 1481 }\r
1482 }\r
1483\r
1484 return Status;\r
1485}\r
1486\r
f1294e4a 1487/**\r
1488 Check for VGA device\r
1489\r
1490 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure\r
1491\r
1492 @retval EFI_SUCCESS Standard VGA device found\r
1493**/\r
7da78b1f 1494EFI_STATUS\r
0d92cdc2 1495EFIAPI\r
7da78b1f 1496BiosVideoCheckForVga (\r
0d92cdc2 1497 IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate\r
7da78b1f 1498 )\r
7da78b1f 1499{\r
1500 EFI_STATUS Status;\r
1501 BIOS_VIDEO_MODE_DATA *ModeBuffer;\r
0d92cdc2 1502 \r
1503 //\r
1504 // Fill in the Graphics Output Protocol\r
1505 //\r
1506 BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;\r
1507 BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;\r
1508 BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt;\r
7da78b1f 1509\r
1510 //\r
0d92cdc2 1511 // Allocate buffer for Graphics Output Protocol mode information\r
7da78b1f 1512 //\r
0d92cdc2 1513 Status = gBS->AllocatePool (\r
1514 EfiBootServicesData,\r
1515 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
1516 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode\r
1517 );\r
1518 if (EFI_ERROR (Status)) {\r
1519 goto Done;\r
1520 }\r
1521 Status = gBS->AllocatePool (\r
1522 EfiBootServicesData,\r
1523 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
1524 (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info\r
1525 );\r
1526 if (EFI_ERROR (Status)) {\r
1527 goto Done;\r
1528 }\r
7da78b1f 1529\r
1530 //\r
1531 // Add mode to the list of available modes\r
1532 //\r
0d92cdc2 1533 BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;\r
1534\r
7da78b1f 1535 Status = gBS->AllocatePool (\r
1536 EfiBootServicesData,\r
0d92cdc2 1537 sizeof (BIOS_VIDEO_MODE_DATA),\r
7da78b1f 1538 (VOID **) &ModeBuffer\r
1539 );\r
1540 if (EFI_ERROR (Status)) {\r
0d92cdc2 1541 goto Done;\r
7da78b1f 1542 }\r
1543\r
0d92cdc2 1544 ModeBuffer->VbeModeNumber = 0x0012;\r
1545 ModeBuffer->BytesPerScanLine = 640;\r
1546 ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000);\r
1547 ModeBuffer->FrameBufferSize = 0;\r
1548 ModeBuffer->HorizontalResolution = 640;\r
1549 ModeBuffer->VerticalResolution = 480;\r
1550 ModeBuffer->BitsPerPixel = 8; \r
1551 ModeBuffer->PixelFormat = PixelBltOnly;\r
7da78b1f 1552\r
1553 BiosVideoPrivate->ModeData = ModeBuffer;\r
1554\r
1555 //\r
1556 // Test to see if the Video Adapter support the 640x480 16 color mode\r
1557 //\r
0d92cdc2 1558 BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
1559 Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);\r
7da78b1f 1560\r
0d92cdc2 1561Done:\r
7da78b1f 1562 //\r
1563 // If there was an error, then free the mode structure\r
1564 //\r
1565 if (EFI_ERROR (Status)) {\r
7da78b1f 1566 if (BiosVideoPrivate->ModeData != NULL) {\r
1567 gBS->FreePool (BiosVideoPrivate->ModeData);\r
1568 }\r
0d92cdc2 1569 if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {\r
1570 if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {\r
1571 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);\r
1572 }\r
1573 gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);\r
1574 }\r
7da78b1f 1575 }\r
7da78b1f 1576 return Status;\r
1577}\r
1578//\r
0d92cdc2 1579// Graphics Output Protocol Member Functions for VESA BIOS Extensions\r
7da78b1f 1580//\r
f1294e4a 1581/**\r
1582\r
1583 Graphics Output protocol interface to get video mode\r
1584\r
1585\r
1586 @param This - Protocol instance pointer.\r
1587 @param ModeNumber - The mode number to return information on.\r
1588 @param SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
1589 @param Info - Caller allocated buffer that returns information about ModeNumber.\r
1590\r
1591 @return EFI_SUCCESS - Mode information returned.\r
1592 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
1593 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
1594 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
1595\r
1596**/\r
7da78b1f 1597EFI_STATUS\r
1598EFIAPI\r
0d92cdc2 1599BiosVideoGraphicsOutputQueryMode (\r
1600 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1601 IN UINT32 ModeNumber,\r
1602 OUT UINTN *SizeOfInfo,\r
1603 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
7da78b1f 1604 )\r
7da78b1f 1605{\r
0d92cdc2 1606 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1607 EFI_STATUS Status;\r
1608 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1609\r
0d92cdc2 1610 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1611\r
1612 if (BiosVideoPrivate->HardwareNeedsStarting) {\r
0d92cdc2 1613 return EFI_NOT_STARTED;\r
7da78b1f 1614 }\r
1615\r
0d92cdc2 1616 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
7da78b1f 1617 return EFI_INVALID_PARAMETER;\r
1618 }\r
1619\r
0d92cdc2 1620 Status = gBS->AllocatePool (\r
1621 EfiBootServicesData,\r
1622 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
fe74f173 1623 (VOID**) Info\r
0d92cdc2 1624 );\r
1625 if (EFI_ERROR (Status)) {\r
1626 return Status;\r
1627 }\r
1628\r
1629 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
1630\r
1631 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
1632 (*Info)->Version = 0;\r
1633 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
1634 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
1635 (*Info)->PixelFormat = ModeData->PixelFormat;\r
1636 (*Info)->PixelInformation = ModeData->PixelBitMask;\r
1637\r
1638 (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
7da78b1f 1639\r
1640 return EFI_SUCCESS;\r
1641}\r
1642\r
f1294e4a 1643/**\r
1644\r
1645 Graphics Output protocol interface to set video mode\r
1646\r
1647\r
1648 @param This - Protocol instance pointer.\r
1649 @param ModeNumber - The mode number to be set.\r
1650\r
1651 @return EFI_SUCCESS - Graphics mode was changed.\r
1652 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
1653 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
1654\r
1655**/\r
7da78b1f 1656EFI_STATUS\r
1657EFIAPI\r
0d92cdc2 1658BiosVideoGraphicsOutputSetMode (\r
1659 IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,\r
1660 IN UINT32 ModeNumber\r
7da78b1f 1661 )\r
7da78b1f 1662{\r
0d92cdc2 1663 EFI_STATUS Status;\r
1664 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
d0c94e59 1665 IA32_REGISTER_SET Regs;\r
0d92cdc2 1666 BIOS_VIDEO_MODE_DATA *ModeData;\r
7da78b1f 1667\r
0d92cdc2 1668 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 1669\r
0d92cdc2 1670 if (This == NULL) {\r
1671 return EFI_INVALID_PARAMETER;\r
1672 }\r
7da78b1f 1673\r
0d92cdc2 1674 if (ModeNumber >= This->Mode->MaxMode) {\r
1675 return EFI_UNSUPPORTED;\r
1676 }\r
7da78b1f 1677\r
0d92cdc2 1678 if (ModeNumber == This->Mode->Mode) {\r
1679 return EFI_SUCCESS;\r
1680 }\r
7da78b1f 1681\r
0d92cdc2 1682 ModeData = &BiosVideoPrivate->ModeData[ModeNumber];\r
7da78b1f 1683\r
0d92cdc2 1684 if (BiosVideoPrivate->LineBuffer) {\r
1685 gBS->FreePool (BiosVideoPrivate->LineBuffer);\r
1686 }\r
7da78b1f 1687\r
0d92cdc2 1688 if (BiosVideoPrivate->VgaFrameBuffer) {\r
1689 gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);\r
1690 }\r
7da78b1f 1691\r
0d92cdc2 1692 if (BiosVideoPrivate->VbeFrameBuffer) {\r
1693 gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);\r
1694 }\r
7da78b1f 1695\r
0d92cdc2 1696 BiosVideoPrivate->LineBuffer = NULL;\r
1697 Status = gBS->AllocatePool (\r
1698 EfiBootServicesData,\r
1699 ModeData->BytesPerScanLine,\r
fe74f173 1700 (VOID**) &BiosVideoPrivate->LineBuffer\r
0d92cdc2 1701 );\r
1702 if (EFI_ERROR (Status)) {\r
1703 return Status;\r
1704 }\r
1705 //\r
1706 // Clear all registers\r
1707 //\r
1708 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
7da78b1f 1709\r
0d92cdc2 1710 if (ModeData->VbeModeNumber < 0x100) {\r
1711 //\r
1712 // Allocate a working buffer for BLT operations to the VGA frame buffer\r
1713 //\r
1714 BiosVideoPrivate->VgaFrameBuffer = NULL;\r
7da78b1f 1715 Status = gBS->AllocatePool (\r
1716 EfiBootServicesData,\r
0d92cdc2 1717 4 * 480 * 80,\r
fe74f173 1718 (VOID**) &BiosVideoPrivate->VgaFrameBuffer\r
7da78b1f 1719 );\r
1720 if (EFI_ERROR (Status)) {\r
1721 return Status;\r
1722 }\r
1723 //\r
0d92cdc2 1724 // Set VGA Mode\r
7da78b1f 1725 //\r
2776527d 1726 Regs.X.AX = ModeData->VbeModeNumber;\r
0d92cdc2 1727 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 1728\r
0d92cdc2 1729 } else {\r
1730 //\r
1731 // Allocate a working buffer for BLT operations to the VBE frame buffer\r
1732 //\r
1733 BiosVideoPrivate->VbeFrameBuffer = NULL;\r
1734 Status = gBS->AllocatePool (\r
1735 EfiBootServicesData,\r
1736 ModeData->BytesPerScanLine * ModeData->VerticalResolution,\r
fe74f173 1737 (VOID**) &BiosVideoPrivate->VbeFrameBuffer\r
0d92cdc2 1738 );\r
1739 if (EFI_ERROR (Status)) {\r
1740 return Status;\r
1741 }\r
1742 //\r
1743 // Set VBE mode\r
1744 //\r
1745 Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;\r
1746 Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);\r
1747 gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);\r
d0c94e59 1748 Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
0d92cdc2 1749 Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);\r
49de9dd4 1750 \r
0d92cdc2 1751 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
1752 \r
1753 //\r
1754 // Check to see if the call succeeded\r
1755 //\r
1756 if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {\r
1757 return EFI_DEVICE_ERROR;\r
1758 }\r
1759 //\r
1760 // Initialize the state of the VbeFrameBuffer\r
1761 //\r
1762 Status = BiosVideoPrivate->PciIo->Mem.Read (\r
1763 BiosVideoPrivate->PciIo,\r
1764 EfiPciIoWidthUint32,\r
1765 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1766 (UINT64) (UINTN) ModeData->LinearFrameBuffer,\r
1767 (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,\r
1768 BiosVideoPrivate->VbeFrameBuffer\r
1769 );\r
1770 if (EFI_ERROR (Status)) {\r
1771 return Status;\r
7da78b1f 1772 }\r
0d92cdc2 1773 }\r
7da78b1f 1774\r
0d92cdc2 1775 This->Mode->Mode = ModeNumber;\r
1776 This->Mode->Info->Version = 0;\r
1777 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
1778 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
1779 This->Mode->Info->PixelFormat = ModeData->PixelFormat;\r
1780 This->Mode->Info->PixelInformation = ModeData->PixelBitMask;\r
1781 This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;\r
1782 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
7da78b1f 1783\r
0d92cdc2 1784 //\r
1785 // Frame BufferSize remain unchanged\r
1786 //\r
fe74f173 1787 This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ModeData->LinearFrameBuffer;\r
0d92cdc2 1788 This->Mode->FrameBufferSize = ModeData->FrameBufferSize;\r
7da78b1f 1789\r
0d92cdc2 1790 BiosVideoPrivate->HardwareNeedsStarting = FALSE;\r
7da78b1f 1791\r
0d92cdc2 1792 return EFI_SUCCESS;\r
7da78b1f 1793}\r
1794\r
f1294e4a 1795/**\r
1796\r
1797 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.\r
1798\r
1799\r
1800 @param PciIo - The pointer of EFI_PCI_IO_PROTOCOL\r
1801 @param VbeBuffer - The data to transfer to screen\r
1802 @param MemAddress - Physical frame buffer base address\r
1803 @param DestinationX - The X coordinate of the destination for BltOperation\r
1804 @param DestinationY - The Y coordinate of the destination for BltOperation\r
1805 @param TotalBytes - The total bytes of copy\r
1806 @param VbePixelWidth - Bytes per pixel\r
1807 @param BytesPerScanLine - Bytes per scan line\r
1808\r
1809 @return None.\r
1810\r
1811**/\r
7da78b1f 1812VOID\r
1813CopyVideoBuffer (\r
1814 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1815 IN UINT8 *VbeBuffer,\r
1816 IN VOID *MemAddress,\r
1817 IN UINTN DestinationX,\r
1818 IN UINTN DestinationY,\r
1819 IN UINTN TotalBytes,\r
1820 IN UINT32 VbePixelWidth,\r
1821 IN UINTN BytesPerScanLine\r
1822 )\r
7da78b1f 1823{\r
1824 UINTN FrameBufferAddr;\r
1825 UINTN CopyBlockNum;\r
1826 UINTN RemainingBytes;\r
1827 UINTN UnalignedBytes;\r
1828 EFI_STATUS Status;\r
1829\r
1830 FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;\r
1831\r
1832 //\r
1833 // If TotalBytes is less than 4 bytes, only start byte copy.\r
1834 //\r
1835 if (TotalBytes < 4) {\r
1836 Status = PciIo->Mem.Write (\r
1837 PciIo,\r
1838 EfiPciIoWidthUint8,\r
1839 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1840 (UINT64) FrameBufferAddr,\r
1841 TotalBytes,\r
1842 VbeBuffer\r
1843 );\r
1844 ASSERT_EFI_ERROR (Status);\r
1845 return;\r
1846 }\r
1847\r
1848 //\r
1849 // If VbeBuffer is not 4-byte aligned, start byte copy.\r
1850 //\r
1851 UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;\r
1852\r
1853 if (UnalignedBytes != 0) {\r
1854 Status = PciIo->Mem.Write (\r
1855 PciIo,\r
1856 EfiPciIoWidthUint8,\r
1857 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1858 (UINT64) FrameBufferAddr,\r
1859 UnalignedBytes,\r
1860 VbeBuffer\r
1861 );\r
1862 ASSERT_EFI_ERROR (Status);\r
1863 FrameBufferAddr += UnalignedBytes;\r
1864 VbeBuffer += UnalignedBytes;\r
1865 }\r
1866\r
1867 //\r
1868 // Calculate 4-byte block count and remaining bytes.\r
1869 //\r
1870 CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;\r
1871 RemainingBytes = (TotalBytes - UnalignedBytes) & 3;\r
1872\r
1873 //\r
1874 // Copy 4-byte block and remaining bytes to physical frame buffer.\r
1875 //\r
1876 if (CopyBlockNum != 0) {\r
1877 Status = PciIo->Mem.Write (\r
1878 PciIo,\r
1879 EfiPciIoWidthUint32,\r
1880 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1881 (UINT64) FrameBufferAddr,\r
1882 CopyBlockNum,\r
1883 VbeBuffer\r
1884 );\r
1885 ASSERT_EFI_ERROR (Status);\r
1886 }\r
1887\r
1888 if (RemainingBytes != 0) {\r
1889 FrameBufferAddr += (CopyBlockNum << 2);\r
1890 VbeBuffer += (CopyBlockNum << 2);\r
1891 Status = PciIo->Mem.Write (\r
1892 PciIo,\r
1893 EfiPciIoWidthUint8,\r
1894 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1895 (UINT64) FrameBufferAddr,\r
1896 RemainingBytes,\r
1897 VbeBuffer\r
1898 );\r
1899 ASSERT_EFI_ERROR (Status);\r
1900 }\r
1901}\r
1902\r
1903//\r
1904// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes\r
1905//\r
f1294e4a 1906/**\r
1907\r
1908 Graphics Output protocol instance to block transfer for VBE device\r
1909\r
1910\r
1911 @param This - Pointer to Graphics Output protocol instance\r
1912 @param BltBuffer - The data to transfer to screen\r
1913 @param BltOperation - The operation to perform\r
1914 @param SourceX - The X coordinate of the source for BltOperation\r
1915 @param SourceY - The Y coordinate of the source for BltOperation\r
1916 @param DestinationX - The X coordinate of the destination for BltOperation\r
1917 @param DestinationY - The Y coordinate of the destination for BltOperation\r
1918 @param Width - The width of a rectangle in the blt rectangle in pixels\r
1919 @param Height - The height of a rectangle in the blt rectangle in pixels\r
1920 @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
1921 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
1922 If a subrectangle of the BltBuffer is used, then Delta represents\r
1923 the number of bytes in a row of the BltBuffer.\r
1924\r
1925 @return EFI_INVALID_PARAMETER - Invalid parameter passed in\r
1926 EFI_SUCCESS - Blt operation success\r
1927\r
1928**/\r
7da78b1f 1929EFI_STATUS\r
1930EFIAPI\r
0d92cdc2 1931BiosVideoGraphicsOutputVbeBlt (\r
1932 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
1933 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
1934 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
1935 IN UINTN SourceX,\r
1936 IN UINTN SourceY,\r
1937 IN UINTN DestinationX,\r
1938 IN UINTN DestinationY,\r
1939 IN UINTN Width,\r
1940 IN UINTN Height,\r
1941 IN UINTN Delta\r
7da78b1f 1942 )\r
7da78b1f 1943{\r
0d92cdc2 1944 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
1945 BIOS_VIDEO_MODE_DATA *Mode;\r
1946 EFI_PCI_IO_PROTOCOL *PciIo;\r
1947 EFI_TPL OriginalTPL;\r
1948 UINTN DstY;\r
1949 UINTN SrcY;\r
1950 UINTN DstX;\r
1951 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
1952 VOID *MemAddress;\r
1953 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;\r
1954 UINTN BytesPerScanLine;\r
1955 UINTN Index;\r
1956 UINT8 *VbeBuffer;\r
1957 UINT8 *VbeBuffer1;\r
1958 UINT8 *BltUint8;\r
1959 UINT32 VbePixelWidth;\r
1960 UINT32 Pixel;\r
1961 UINTN TotalBytes;\r
1962\r
1963 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
1964 Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode];\r
7da78b1f 1965 PciIo = BiosVideoPrivate->PciIo;\r
1966\r
1967 VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer;\r
1968 MemAddress = Mode->LinearFrameBuffer;\r
1969 BytesPerScanLine = Mode->BytesPerScanLine;\r
1970 VbePixelWidth = Mode->BitsPerPixel / 8;\r
1971 BltUint8 = (UINT8 *) BltBuffer;\r
1972 TotalBytes = Width * VbePixelWidth;\r
1973\r
0d92cdc2 1974 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 1975 return EFI_INVALID_PARAMETER;\r
1976 }\r
1977\r
1978 if (Width == 0 || Height == 0) {\r
1979 return EFI_INVALID_PARAMETER;\r
1980 }\r
1981 //\r
1982 // We need to fill the Virtual Screen buffer with the blt data.\r
1983 // The virtual screen is upside down, as the first row is the bootom row of\r
1984 // the image.\r
1985 //\r
0d92cdc2 1986 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 1987 //\r
1988 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
1989 //\r
1990 if (SourceY + Height > Mode->VerticalResolution) {\r
1991 return EFI_INVALID_PARAMETER;\r
1992 }\r
1993\r
1994 if (SourceX + Width > Mode->HorizontalResolution) {\r
1995 return EFI_INVALID_PARAMETER;\r
1996 }\r
1997 } else {\r
1998 //\r
1999 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2000 //\r
2001 if (DestinationY + Height > Mode->VerticalResolution) {\r
2002 return EFI_INVALID_PARAMETER;\r
2003 }\r
2004\r
2005 if (DestinationX + Width > Mode->HorizontalResolution) {\r
2006 return EFI_INVALID_PARAMETER;\r
2007 }\r
2008 }\r
2009 //\r
2010 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2011 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2012 // the number of bytes in each row can be computed.\r
2013 //\r
2014 if (Delta == 0) {\r
0d92cdc2 2015 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 2016 }\r
2017 //\r
2018 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2019 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2020 // doing this operation.\r
2021 //\r
2022 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2023\r
2024 switch (BltOperation) {\r
0d92cdc2 2025 case EfiBltVideoToBltBuffer:\r
7da78b1f 2026 for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {\r
0d92cdc2 2027 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 2028 //\r
0d92cdc2 2029 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL\r
7da78b1f 2030 //\r
2031 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));\r
2032 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2033 Pixel = *(UINT32 *) (VbeBuffer);\r
2034 Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);\r
2035 Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);\r
2036 Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);\r
2037 Blt->Reserved = 0;\r
2038 Blt++;\r
2039 VbeBuffer += VbePixelWidth;\r
2040 }\r
2041\r
2042 }\r
2043 break;\r
2044\r
0d92cdc2 2045 case EfiBltVideoToVideo:\r
7da78b1f 2046 for (Index = 0; Index < Height; Index++) {\r
2047 if (DestinationY <= SourceY) {\r
2048 SrcY = SourceY + Index;\r
2049 DstY = DestinationY + Index;\r
2050 } else {\r
2051 SrcY = SourceY + Height - Index - 1;\r
2052 DstY = DestinationY + Height - Index - 1;\r
2053 }\r
2054\r
2055 VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);\r
2056 VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);\r
2057\r
2058 gBS->CopyMem (\r
2059 VbeBuffer,\r
2060 VbeBuffer1,\r
2061 TotalBytes\r
2062 );\r
2063\r
2064 //\r
2065 // Update physical frame buffer.\r
2066 //\r
2067 CopyVideoBuffer (\r
2068 PciIo,\r
2069 VbeBuffer,\r
2070 MemAddress,\r
2071 DestinationX,\r
2072 DstY,\r
2073 TotalBytes,\r
2074 VbePixelWidth,\r
2075 BytesPerScanLine\r
2076 );\r
2077 }\r
2078 break;\r
2079\r
0d92cdc2 2080 case EfiBltVideoFill:\r
7da78b1f 2081 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
0d92cdc2 2082 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;\r
7da78b1f 2083 //\r
0d92cdc2 2084 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2085 //\r
2086 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2087 (\r
2088 (Blt->Green & Mode->Green.Mask) <<\r
2089 Mode->Green.Position\r
2090 ) |\r
2091 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2092\r
2093 for (Index = 0; Index < Width; Index++) {\r
2094 gBS->CopyMem (\r
2095 VbeBuffer,\r
2096 &Pixel,\r
2097 VbePixelWidth\r
2098 );\r
2099 VbeBuffer += VbePixelWidth;\r
2100 }\r
2101\r
2102 VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);\r
2103 for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {\r
2104 gBS->CopyMem (\r
2105 (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),\r
2106 VbeBuffer,\r
2107 TotalBytes\r
2108 );\r
2109 }\r
2110 for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {\r
2111 //\r
2112 // Update physical frame buffer.\r
2113 //\r
2114 CopyVideoBuffer (\r
2115 PciIo,\r
2116 VbeBuffer,\r
2117 MemAddress,\r
2118 DestinationX,\r
2119 DstY,\r
2120 TotalBytes,\r
2121 VbePixelWidth,\r
2122 BytesPerScanLine\r
2123 );\r
2124 }\r
7da78b1f 2125 break;\r
2126\r
0d92cdc2 2127 case EfiBltBufferToVideo:\r
7da78b1f 2128 for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {\r
0d92cdc2 2129 Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
7da78b1f 2130 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2131 for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {\r
2132 //\r
0d92cdc2 2133 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer\r
7da78b1f 2134 //\r
2135 Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |\r
2136 ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |\r
2137 ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);\r
2138 gBS->CopyMem (\r
2139 VbeBuffer,\r
2140 &Pixel,\r
2141 VbePixelWidth\r
2142 );\r
2143 Blt++;\r
2144 VbeBuffer += VbePixelWidth;\r
2145 }\r
2146\r
2147 VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));\r
2148\r
2149 //\r
2150 // Update physical frame buffer.\r
2151 //\r
2152 CopyVideoBuffer (\r
2153 PciIo,\r
2154 VbeBuffer,\r
2155 MemAddress,\r
2156 DestinationX,\r
2157 DstY,\r
2158 TotalBytes,\r
2159 VbePixelWidth,\r
2160 BytesPerScanLine\r
2161 );\r
2162 }\r
2163 break;\r
fe74f173 2164 default:\r
2165 break;\r
7da78b1f 2166 }\r
2167\r
2168 gBS->RestoreTPL (OriginalTPL);\r
2169\r
2170 return EFI_SUCCESS;\r
2171}\r
2172\r
f1294e4a 2173/**\r
2174\r
2175 Write graphics controller registers\r
2176\r
2177\r
2178 @param PciIo - Pointer to PciIo protocol instance of the controller\r
2179 @param Address - Register address\r
2180 @param Data - Data to be written to register\r
2181\r
2182 @return None\r
2183\r
2184**/\r
7da78b1f 2185STATIC\r
2186VOID\r
2187WriteGraphicsController (\r
2188 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2189 IN UINTN Address,\r
2190 IN UINTN Data\r
2191 )\r
7da78b1f 2192{\r
2193 Address = Address | (Data << 8);\r
2194 PciIo->Io.Write (\r
2195 PciIo,\r
2196 EfiPciIoWidthUint16,\r
2197 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2198 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,\r
2199 1,\r
2200 &Address\r
2201 );\r
2202}\r
2203\r
f1294e4a 2204/**\r
2205\r
2206 Read the four bit plane of VGA frame buffer\r
2207\r
2208\r
2209 @param PciIo - Pointer to PciIo protocol instance of the controller\r
2210 @param HardwareBuffer - Hardware VGA frame buffer address\r
2211 @param MemoryBuffer - Memory buffer address\r
2212 @param WidthInBytes - Number of bytes in a line to read\r
2213 @param Height - Height of the area to read\r
2214\r
2215 @return None\r
2216\r
2217**/\r
7da78b1f 2218VOID\r
2219VgaReadBitPlanes (\r
2220 EFI_PCI_IO_PROTOCOL *PciIo,\r
2221 UINT8 *HardwareBuffer,\r
2222 UINT8 *MemoryBuffer,\r
2223 UINTN WidthInBytes,\r
2224 UINTN Height\r
2225 )\r
7da78b1f 2226{\r
2227 UINTN BitPlane;\r
2228 UINTN Rows;\r
2229 UINTN FrameBufferOffset;\r
2230 UINT8 *Source;\r
2231 UINT8 *Destination;\r
2232\r
2233 //\r
2234 // Program the Mode Register Write mode 0, Read mode 0\r
2235 //\r
2236 WriteGraphicsController (\r
2237 PciIo,\r
2238 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2239 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0\r
2240 );\r
2241\r
2242 for (BitPlane = 0, FrameBufferOffset = 0;\r
2243 BitPlane < VGA_NUMBER_OF_BIT_PLANES;\r
2244 BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE\r
2245 ) {\r
2246 //\r
2247 // Program the Read Map Select Register to select the correct bit plane\r
2248 //\r
2249 WriteGraphicsController (\r
2250 PciIo,\r
2251 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,\r
2252 BitPlane\r
2253 );\r
2254\r
2255 Source = HardwareBuffer;\r
2256 Destination = MemoryBuffer + FrameBufferOffset;\r
2257\r
2258 for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {\r
2259 PciIo->Mem.Read (\r
2260 PciIo,\r
2261 EfiPciIoWidthUint8,\r
fe74f173 2262 (UINT8) EFI_PCI_IO_PASS_THROUGH_BAR,\r
2263 (UINT64)(UINTN) Source,\r
7da78b1f 2264 WidthInBytes,\r
2265 (VOID *) Destination\r
2266 );\r
2267 }\r
2268 }\r
2269}\r
2270\r
f1294e4a 2271/**\r
2272\r
2273 Internal routine to convert VGA color to Grahpics Output color\r
2274\r
2275\r
2276 @param MemoryBuffer - Buffer containing VGA color\r
2277 @param X - The X coordinate of pixel on screen\r
2278 @param Y - The Y coordinate of pixel on screen\r
2279 @param BltBuffer - Buffer to contain converted Grahpics Output color\r
2280\r
2281 @return None\r
2282\r
2283**/\r
7da78b1f 2284VOID\r
0d92cdc2 2285VgaConvertToGraphicsOutputColor (\r
2286 UINT8 *MemoryBuffer,\r
2287 UINTN X,\r
2288 UINTN Y,\r
2289 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
7da78b1f 2290 )\r
7da78b1f 2291{\r
2292 UINTN Mask;\r
2293 UINTN Bit;\r
2294 UINTN Color;\r
2295\r
2296 MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));\r
2297 Mask = mVgaBitMaskTable[X & 0x07];\r
2298 for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {\r
2299 if (*MemoryBuffer & Mask) {\r
2300 Color |= Bit;\r
2301 }\r
2302 }\r
2303\r
0d92cdc2 2304 *BltBuffer = mVgaColorToGraphicsOutputColor[Color];\r
7da78b1f 2305}\r
2306\r
f1294e4a 2307/**\r
7da78b1f 2308\r
0d92cdc2 2309 Internal routine to convert Grahpics Output color to VGA color\r
7da78b1f 2310\r
7da78b1f 2311\r
f1294e4a 2312 @param BltBuffer - buffer containing Grahpics Output color\r
7da78b1f 2313\r
f1294e4a 2314 @return Converted VGA color\r
7da78b1f 2315\r
f1294e4a 2316**/\r
2317UINT8\r
2318VgaConvertColor (\r
2319 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer\r
2320 )\r
7da78b1f 2321{\r
2322 UINT8 Color;\r
2323\r
2324 Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));\r
2325 if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {\r
2326 Color |= 0x08;\r
2327 }\r
2328\r
2329 return Color;\r
2330}\r
2331\r
f1294e4a 2332/**\r
2333 Grahpics Output protocol instance to block transfer for VGA device\r
2334\r
2335 @param This Pointer to Grahpics Output protocol instance\r
2336 @param BltBuffer The data to transfer to screen\r
2337 @param BltOperation The operation to perform\r
2338 @param SourceX The X coordinate of the source for BltOperation\r
2339 @param SourceY The Y coordinate of the source for BltOperation\r
2340 @param DestinationX The X coordinate of the destination for BltOperation\r
2341 @param DestinationY The Y coordinate of the destination for BltOperation\r
2342 @param Width The width of a rectangle in the blt rectangle in pixels\r
2343 @param Height The height of a rectangle in the blt rectangle in pixels\r
2344 @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
2345 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
2346 If a subrectangle of the BltBuffer is used, then Delta represents\r
2347 the number of bytes in a row of the BltBuffer.\r
2348\r
2349 @retval EFI_INVALID_PARAMETER Invalid parameter passed in\r
2350 @retval EFI_SUCCESS Blt operation success\r
2351\r
2352**/\r
7da78b1f 2353EFI_STATUS\r
2354EFIAPI\r
0d92cdc2 2355BiosVideoGraphicsOutputVgaBlt (\r
2356 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
2357 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
2358 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
2359 IN UINTN SourceX,\r
2360 IN UINTN SourceY,\r
2361 IN UINTN DestinationX,\r
2362 IN UINTN DestinationY,\r
2363 IN UINTN Width,\r
2364 IN UINTN Height,\r
2365 IN UINTN Delta\r
7da78b1f 2366 )\r
7da78b1f 2367{\r
2368 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
2369 EFI_TPL OriginalTPL;\r
2370 UINT8 *MemAddress;\r
2371 UINTN BytesPerScanLine;\r
49de9dd4 2372 //UINTN BytesPerBitPlane;\r
7da78b1f 2373 UINTN Bit;\r
2374 UINTN Index;\r
2375 UINTN Index1;\r
2376 UINTN StartAddress;\r
2377 UINTN Bytes;\r
2378 UINTN Offset;\r
2379 UINT8 LeftMask;\r
2380 UINT8 RightMask;\r
2381 UINTN Address;\r
2382 UINTN AddressFix;\r
2383 UINT8 *Address1;\r
2384 UINT8 *SourceAddress;\r
2385 UINT8 *DestinationAddress;\r
2386 EFI_PCI_IO_PROTOCOL *PciIo;\r
2387 UINT8 Data;\r
2388 UINT8 PixelColor;\r
2389 UINT8 *VgaFrameBuffer;\r
2390 UINTN SourceOffset;\r
2391 UINTN SourceWidth;\r
2392 UINTN Rows;\r
2393 UINTN Columns;\r
2394 UINTN X;\r
2395 UINTN Y;\r
0d92cdc2 2396 UINTN CurrentMode;\r
7da78b1f 2397\r
0d92cdc2 2398 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);\r
7da78b1f 2399\r
0d92cdc2 2400 CurrentMode = This->Mode->Mode;\r
7da78b1f 2401 PciIo = BiosVideoPrivate->PciIo;\r
0d92cdc2 2402 MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;\r
2403 BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;\r
49de9dd4 2404 //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;\r
7da78b1f 2405 VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer;\r
2406\r
0d92cdc2 2407 if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {\r
7da78b1f 2408 return EFI_INVALID_PARAMETER;\r
2409 }\r
2410\r
2411 if (Width == 0 || Height == 0) {\r
2412 return EFI_INVALID_PARAMETER;\r
2413 }\r
2414 //\r
2415 // We need to fill the Virtual Screen buffer with the blt data.\r
2416 // The virtual screen is upside down, as the first row is the bootom row of\r
2417 // the image.\r
2418 //\r
0d92cdc2 2419 if (BltOperation == EfiBltVideoToBltBuffer) {\r
7da78b1f 2420 //\r
2421 // Video to BltBuffer: Source is Video, destination is BltBuffer\r
2422 //\r
0d92cdc2 2423 if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2424 return EFI_INVALID_PARAMETER;\r
2425 }\r
2426\r
0d92cdc2 2427 if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2428 return EFI_INVALID_PARAMETER;\r
2429 }\r
2430 } else {\r
2431 //\r
2432 // BltBuffer to Video: Source is BltBuffer, destination is Video\r
2433 //\r
0d92cdc2 2434 if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {\r
7da78b1f 2435 return EFI_INVALID_PARAMETER;\r
2436 }\r
2437\r
0d92cdc2 2438 if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {\r
7da78b1f 2439 return EFI_INVALID_PARAMETER;\r
2440 }\r
2441 }\r
2442 //\r
2443 // If Delta is zero, then the entire BltBuffer is being used, so Delta\r
2444 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,\r
2445 // the number of bytes in each row can be computed.\r
2446 //\r
2447 if (Delta == 0) {\r
0d92cdc2 2448 Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
7da78b1f 2449 }\r
2450 //\r
2451 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
2452 // We would not want a timer based event (Cursor, ...) to come in while we are\r
2453 // doing this operation.\r
2454 //\r
2455 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
2456\r
2457 //\r
2458 // Compute some values we need for VGA\r
2459 //\r
2460 switch (BltOperation) {\r
0d92cdc2 2461 case EfiBltVideoToBltBuffer:\r
7da78b1f 2462\r
2463 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2464 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2465\r
2466 //\r
2467 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2468 //\r
2469 VgaReadBitPlanes (\r
2470 PciIo,\r
2471 MemAddress + SourceOffset,\r
2472 VgaFrameBuffer + SourceOffset,\r
2473 SourceWidth,\r
2474 Height\r
2475 );\r
2476\r
2477 //\r
0d92cdc2 2478 // Convert VGA Bit Planes to a Graphics Output 32-bit color value\r
7da78b1f 2479 //\r
2480 BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);\r
2481 for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {\r
2482 for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {\r
0d92cdc2 2483 VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer);\r
7da78b1f 2484 }\r
2485\r
2486 BltBuffer -= Width;\r
2487 }\r
2488\r
2489 break;\r
2490\r
0d92cdc2 2491 case EfiBltVideoToVideo:\r
7da78b1f 2492 //\r
2493 // Check for an aligned Video to Video operation\r
2494 //\r
2495 if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {\r
2496 //\r
2497 // Program the Mode Register Write mode 1, Read mode 0\r
2498 //\r
2499 WriteGraphicsController (\r
0d92cdc2 2500 PciIo,\r
7da78b1f 2501 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2502 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1\r
2503 );\r
2504\r
2505 SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));\r
2506 DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2507 Bytes = Width >> 3;\r
2508 for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {\r
2509 PciIo->CopyMem (\r
2510 PciIo,\r
2511 EfiPciIoWidthUint8,\r
2512 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2513 (UINT64) ((UINTN)DestinationAddress + Offset),\r
7da78b1f 2514 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2515 (UINT64) ((UINTN)SourceAddress + Offset),\r
7da78b1f 2516 Bytes\r
2517 );\r
2518 }\r
2519 } else {\r
2520 SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);\r
2521 SourceWidth = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;\r
2522\r
2523 //\r
2524 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer\r
2525 //\r
2526 VgaReadBitPlanes (\r
2527 PciIo,\r
2528 MemAddress + SourceOffset,\r
2529 VgaFrameBuffer + SourceOffset,\r
2530 SourceWidth,\r
2531 Height\r
2532 );\r
2533 }\r
2534\r
2535 break;\r
2536\r
0d92cdc2 2537 case EfiBltVideoFill:\r
7da78b1f 2538 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2539 Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);\r
2540 LeftMask = mVgaLeftMaskTable[DestinationX & 0x07];\r
2541 RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];\r
2542 if (Bytes == 0) {\r
49de9dd4 2543 LeftMask = (UINT8) (LeftMask & RightMask);\r
7da78b1f 2544 RightMask = 0;\r
2545 }\r
2546\r
2547 if (LeftMask == 0xff) {\r
2548 StartAddress--;\r
2549 Bytes++;\r
2550 LeftMask = 0;\r
2551 }\r
2552\r
2553 if (RightMask == 0xff) {\r
2554 Bytes++;\r
2555 RightMask = 0;\r
2556 }\r
2557\r
2558 PixelColor = VgaConvertColor (BltBuffer);\r
2559\r
2560 //\r
2561 // Program the Mode Register Write mode 2, Read mode 0\r
2562 //\r
2563 WriteGraphicsController (\r
0d92cdc2 2564 PciIo,\r
7da78b1f 2565 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2566 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2567 );\r
2568\r
2569 //\r
2570 // Program the Data Rotate/Function Select Register to replace\r
2571 //\r
2572 WriteGraphicsController (\r
0d92cdc2 2573 PciIo,\r
7da78b1f 2574 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2575 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2576 );\r
2577\r
2578 if (LeftMask != 0) {\r
2579 //\r
2580 // Program the BitMask register with the Left column mask\r
2581 //\r
2582 WriteGraphicsController (\r
0d92cdc2 2583 PciIo,\r
7da78b1f 2584 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2585 LeftMask\r
2586 );\r
2587\r
2588 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2589 //\r
2590 // Read data from the bit planes into the latches\r
2591 //\r
2592 PciIo->Mem.Read (\r
2593 PciIo,\r
2594 EfiPciIoWidthUint8,\r
2595 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2596 (UINT64) Address,\r
2597 1,\r
2598 &Data\r
2599 );\r
2600 //\r
2601 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2602 //\r
2603 PciIo->Mem.Write (\r
2604 PciIo,\r
2605 EfiPciIoWidthUint8,\r
2606 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2607 (UINT64) Address,\r
2608 1,\r
2609 &PixelColor\r
2610 );\r
2611 }\r
2612 }\r
2613\r
2614 if (Bytes > 1) {\r
2615 //\r
2616 // Program the BitMask register with the middle column mask of 0xff\r
2617 //\r
2618 WriteGraphicsController (\r
0d92cdc2 2619 PciIo,\r
7da78b1f 2620 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2621 0xff\r
2622 );\r
2623\r
2624 for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {\r
2625 PciIo->Mem.Write (\r
2626 PciIo,\r
2627 EfiPciIoWidthFillUint8,\r
2628 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2629 (UINT64) Address,\r
2630 Bytes - 1,\r
2631 &PixelColor\r
2632 );\r
2633 }\r
2634 }\r
2635\r
2636 if (RightMask != 0) {\r
2637 //\r
2638 // Program the BitMask register with the Right column mask\r
2639 //\r
2640 WriteGraphicsController (\r
0d92cdc2 2641 PciIo,\r
7da78b1f 2642 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2643 RightMask\r
2644 );\r
2645\r
2646 for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {\r
2647 //\r
2648 // Read data from the bit planes into the latches\r
2649 //\r
2650 PciIo->Mem.Read (\r
2651 PciIo,\r
2652 EfiPciIoWidthUint8,\r
2653 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2654 (UINT64) Address,\r
2655 1,\r
2656 &Data\r
2657 );\r
2658 //\r
2659 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask\r
2660 //\r
2661 PciIo->Mem.Write (\r
2662 PciIo,\r
2663 EfiPciIoWidthUint8,\r
2664 EFI_PCI_IO_PASS_THROUGH_BAR,\r
2665 (UINT64) Address,\r
2666 1,\r
2667 &PixelColor\r
2668 );\r
2669 }\r
2670 }\r
2671 break;\r
2672\r
0d92cdc2 2673 case EfiBltBufferToVideo:\r
7da78b1f 2674 StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));\r
2675 LeftMask = mVgaBitMaskTable[DestinationX & 0x07];\r
2676\r
2677 //\r
2678 // Program the Mode Register Write mode 2, Read mode 0\r
2679 //\r
2680 WriteGraphicsController (\r
0d92cdc2 2681 PciIo,\r
7da78b1f 2682 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,\r
2683 VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2\r
2684 );\r
2685\r
2686 //\r
2687 // Program the Data Rotate/Function Select Register to replace\r
2688 //\r
2689 WriteGraphicsController (\r
0d92cdc2 2690 PciIo,\r
7da78b1f 2691 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,\r
2692 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE\r
2693 );\r
2694\r
2695 for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {\r
2696 for (Index1 = 0; Index1 < Width; Index1++) {\r
2697 BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);\r
2698 }\r
2699 AddressFix = Address;\r
2700\r
2701 for (Bit = 0; Bit < 8; Bit++) {\r
2702 //\r
2703 // Program the BitMask register with the Left column mask\r
2704 //\r
2705 WriteGraphicsController (\r
0d92cdc2 2706 PciIo,\r
7da78b1f 2707 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,\r
2708 LeftMask\r
2709 );\r
2710\r
2711 for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {\r
2712 //\r
2713 // Read data from the bit planes into the latches\r
2714 //\r
2715 PciIo->Mem.Read (\r
2716 PciIo,\r
2717 EfiPciIoWidthUint8,\r
2718 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2719 (UINT64)(UINTN) Address1,\r
7da78b1f 2720 1,\r
2721 &Data\r
2722 );\r
2723\r
2724 PciIo->Mem.Write (\r
2725 PciIo,\r
2726 EfiPciIoWidthUint8,\r
2727 EFI_PCI_IO_PASS_THROUGH_BAR,\r
fe74f173 2728 (UINT64)(UINTN) Address1,\r
7da78b1f 2729 1,\r
2730 &BiosVideoPrivate->LineBuffer[Index1]\r
2731 );\r
2732 }\r
2733\r
2734 LeftMask = (UINT8) (LeftMask >> 1);\r
2735 if (LeftMask == 0) {\r
2736 LeftMask = 0x80;\r
2737 AddressFix++;\r
2738 }\r
2739 }\r
2740 }\r
2741\r
fe74f173 2742 break;\r
2743 default:\r
7da78b1f 2744 break;\r
2745 }\r
2746\r
2747 gBS->RestoreTPL (OriginalTPL);\r
2748\r
2749 return EFI_SUCCESS;\r
2750}\r
2751//\r
2752// VGA Mini Port Protocol Functions\r
2753//\r
f1294e4a 2754/**\r
2755 VgaMiniPort protocol interface to set mode\r
2756\r
2757 @param This Pointer to VgaMiniPort protocol instance\r
2758 @param ModeNumber The index of the mode\r
2759\r
2760 @retval EFI_UNSUPPORTED The requested mode is not supported\r
2761 @retval EFI_SUCCESS The requested mode is set successfully\r
2762\r
2763**/\r
7da78b1f 2764EFI_STATUS\r
2765EFIAPI\r
2766BiosVideoVgaMiniPortSetMode (\r
2767 IN EFI_VGA_MINI_PORT_PROTOCOL *This,\r
2768 IN UINTN ModeNumber\r
2769 )\r
7da78b1f 2770{\r
2771 BIOS_VIDEO_DEV *BiosVideoPrivate;\r
d0c94e59 2772 IA32_REGISTER_SET Regs;\r
7da78b1f 2773\r
0d92cdc2 2774 if (This == NULL) {\r
2775 return EFI_INVALID_PARAMETER;\r
2776 }\r
2777\r
7da78b1f 2778 //\r
2779 // Make sure the ModeNumber is a valid value\r
2780 //\r
2781 if (ModeNumber >= This->MaxMode) {\r
2782 return EFI_UNSUPPORTED;\r
2783 }\r
2784 //\r
2785 // Get the device structure for this device\r
2786 //\r
2787 BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);\r
0d92cdc2 2788 \r
7da78b1f 2789 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
2790\r
2791 switch (ModeNumber) {\r
2792 case 0:\r
2793 //\r
2794 // Set the 80x25 Text VGA Mode\r
2795 //\r
2796 Regs.H.AH = 0x00;\r
2797 Regs.H.AL = 0x83;\r
0d92cdc2 2798 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2799 \r
7da78b1f 2800 Regs.H.AH = 0x11;\r
2801 Regs.H.AL = 0x14;\r
2802 Regs.H.BL = 0;\r
0d92cdc2 2803 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2804 \r
7da78b1f 2805 break;\r
2806\r
2807 case 1:\r
2808 //\r
2809 // Set the 80x50 Text VGA Mode\r
2810 //\r
2811 Regs.H.AH = 0x00;\r
2812 Regs.H.AL = 0x83;\r
0d92cdc2 2813 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
2814 \r
7da78b1f 2815 Regs.H.AH = 0x11;\r
2816 Regs.H.AL = 0x12;\r
2817 Regs.H.BL = 0;\r
0d92cdc2 2818 LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);\r
7da78b1f 2819 break;\r
2820\r
2821 default:\r
2822 return EFI_UNSUPPORTED;\r
2823 }\r
2824\r
2825 return EFI_SUCCESS;\r
2826}\r