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