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