VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxVgaDxe/VBoxVga.c@ 67356

Last change on this file since 67356 was 67352, checked in by vboxsync, 8 years ago

EFI/Firmware: big VGA graphics init cleanup. Eliminate need to adjust array size manually when resolutions are added. By default use VBE for setting up graphics mode, but keep standard VGA code. Standard VGA code uses now more defaults (for the sequencer init), as in a virtualized VGA card there is no need to be super precise like with real hardware. Add lots of resolutions to the list of video modes (biggest resolution still fits into 128MB). Automatically remove resolutions which don't fit into the VRAM size. Remove incorrect references to Cirrus Logic. Thinned out the commented out CRTC register values (were mostly bogus) and attempted to fix the values for 800x600. Lots of whitespace/indentation fixing to make the code more readable.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.2 KB
Line 
1/* $Id: VBoxVga.c 67352 2017-06-12 18:02:10Z vboxsync $ */
2/** @file
3 * VBoxVga.c
4 */
5
6/*
7 * Copyright (C) 2009-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 This code is based on:
29
30 Cirrus Logic 5430 Controller Driver.
31 This driver is a sample implementation of the UGA Draw and Graphics Output
32 Protocols for the Cirrus Logic 5430 family of PCI video controllers.
33 This driver is only usable in the EFI pre-boot environment.
34 This sample is intended to show how the UGA Draw and Graphics output Protocol
35 is able to function.
36 The UGA I/O Protocol is not implemented in this sample.
37 A fully compliant EFI UGA driver requires both
38 the UGA Draw and the UGA I/O Protocol. Please refer to Microsoft's
39 documentation on UGA for details on how to write a UGA driver that is able
40 to function both in the EFI pre-boot environment and from the OS runtime.
41
42 Copyright (c) 2006 - 2009, Intel Corporation
43 All rights reserved. This program and the accompanying materials
44 are licensed and made available under the terms and conditions of the BSD License
45 which accompanies this distribution. The full text of the license may be found at
46 http://opensource.org/licenses/bsd-license.php
47
48 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
49 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
50
51*/
52
53//
54// VirtualBox VGA Controller Driver
55//
56#include "VBoxVga.h"
57#include <IndustryStandard/Acpi.h>
58#include "iprt/asm.h"
59
60
61#define BOUTB(storage, count, aport, dport) \
62 do { \
63 for (i = 0 ; i < (count); ++i) \
64 if ((dport) == (aport) + 1) \
65 ASMOutU16((aport), ((UINT16)storage[i] << 8) | (UINT8)i); \
66 else { \
67 ASMOutU8((aport), (UINT8)i); \
68 ASMOutU8((dport), storage[i]); \
69 } \
70 } while (0)
71
72
73
74EFI_DRIVER_BINDING_PROTOCOL gVBoxVgaDriverBinding = {
75 VBoxVgaControllerDriverSupported,
76 VBoxVgaControllerDriverStart,
77 VBoxVgaControllerDriverStop,
78 0x10,
79 NULL,
80 NULL
81};
82
83///
84/// Generic Attribute Controller Register Settings
85///
86UINT8 AttributeController[21] = {
87 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
88 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
89 0x41, 0x00, 0x0F, 0x00, 0x00
90};
91
92///
93/// Generic Graphics Controller Register Settings
94///
95UINT8 GraphicsController[9] = {
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xff
97};
98
99///
100/// Generic Graphics Controller Sequencer Register Settings
101///
102UINT8 Seq_Default[5] = {
103 0x01, 0x01, 0x0f, 0x00, 0x0a
104};
105
106#if 0 // CRTC tables not used (and not checked for correctness), as VBE is much simpler
107//
108// 640 x 480 x 256 color @ 60 Hertz
109//
110UINT8 Crtc_640_480_256_60[25] = {
111 /* r0 = */0x5f, /* r1 = */0x4f, /* r2 = */0x50, /* r3 = */0x82,
112 /* r4 = */0x54, /* r5 = */0x80, /* r6 = */0x0b, /* r7 = */0x3e,
113 /* r8 = */0x00, /* r9 = */0x40, /* r10 = */0x00, /* r11 = */0x00,
114 /* r12 = */0x00, /* r13 = */0x00, /* r14 = */0x00, /* r15 = */0x00,
115 /* r16 = */0xea, /* r17 = */0x0c, /* r18 = */0xdf, /* r19 = */0x28,
116 /* r20 = */0x4f, /* r21 = */0xe7, /* r22 = */0x04, /* r23 = */0xe3,
117 /* r24 = */0xff
118};
119
120//
121// 800 x 600 x 256 color @ 60 Hertz
122//
123UINT8 Crtc_800_600_256_60[25] = {
124 /* r0 = */0x7f, /* r1 = */0x63, /* r2 = */0x64, /* r3 = */0x82,
125 /* r4 = */0x6b, /* r5 = */0x80, /* r6 = */0x0b, /* r7 = */0x3e,
126 /* r8 = */0x00, /* r9 = */0x60, /* r10 = */0x00, /* r11 = */0x00,
127 /* r12 = */0x00, /* r13 = */0x00, /* r14 = */0x00, /* r15 = */0x00,
128 /* r16 = */0xea, /* r17 = */0x0c, /* r18 = */0xdf, /* r19 = */0x28,
129 /* r20 = */0x4f, /* r21 = */0xe7, /* r22 = */0x04, /* r23 = */0xe3,
130 /* r24 = */0xff
131
132};
133
134//
135// 1024 x 768 x 256 color @ 60 Hertz
136//
137UINT8 Crtc_1024_768_256_60[25] = {
138 /* r0 = */0xa3, /* r1 = */0x7f, /* r2 = */0x81, /* r3 = */0x90,
139 /* r4 = */0x88, /* r5 = */0x05, /* r6 = */0x28, /* r7 = */0xfd,
140 /* r8 = */0x00, /* r9 = */0x60, /* r10 = */0x00, /* r11 = */0x00,
141 /* r12 = */0x00, /* r13 = */0x00, /* r14 = */0x00, /* r15 = */0x00,
142 /* r16 = */0x06, /* r17 = */0x0f, /* r18 = */0xff, /* r19 = */0x40,
143 /* r20 = */0x4f, /* r21 = */0x05, /* r22 = */0x1a, /* r23 = */0xe3,
144 /* r24 = */0xff
145};
146#endif
147
148///
149/// Table of supported video modes (sorted by pixel count!)
150///
151VBOX_VGA_VIDEO_MODES VBoxVgaVideoModes[] =
152{
153 { 640, 480, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // VGA 4:3
154 { 800, 600, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // SVGA 4:3
155 { 1024, 768, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // XGA 4:3
156 { 1280, 720, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // HD 16:9
157 { 1152, 864, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // XGA+ 4:3
158 { 1280, 800, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WXGA 16:10
159 { 1440, 900, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WXGA+ 16:10
160 { 1280, 1024, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // SXGA 5:4
161 { 1400, 1050, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // SXGA+ 4:3
162 { 1600, 900, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // HD+ 16:9
163 { 1680, 1050, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WSXGA+ 16:10
164 { 1600, 1200, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // UXGA 4:3
165 { 1920, 1080, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // FHD 16:9
166 { 2048, 1080, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // DCI_2K 19:10
167 { 1920, 1200, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WUXGA 16:10
168 { 2160, 1440, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // FHD+ 3:2
169 { 2304, 1440, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // unnamed 16:10
170 { 2560, 1440, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // QHD 16:9
171 { 2560, 1600, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WQXGA 16:10
172 { 2880, 1800, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // QWXGA+ 16:10
173 { 3200, 1800, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // QHD+ 16:9
174 { 3200, 2048, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WQSXGA 16:10
175 { 3840, 2160, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // 4K_UHD 16:9
176 { 4096, 2160, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // DCI_4K 19:10
177 { 3840, 2400, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WQUXGA 16:10
178 { 4096, 3072, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // HXGA 4:3
179 { 5120, 2880, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // UHD+ 16:9
180 { 5120, 3200, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WHXGA 16:10
181 { 6400, 4096, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // WHSXGA 16:10
182 { 6400, 4800, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // HUXGA 4:3
183 { 7680, 4320, 32, 60, NULL /* crtc */, NULL /* sequencer */, 0x01 }, // 8K_UHD2 16:9
184};
185
186const UINT32 VBoxVgaVideoModeCount = sizeof(VBoxVgaVideoModes) / sizeof(VBoxVgaVideoModes[0]);
187
188typedef struct _APPLE_FRAMEBUFFERINFO_PROTOCOL APPLE_FRAMEBUFFERINFO_PROTOCOL;
189
190typedef
191EFI_STATUS
192(EFIAPI *APPLE_FRAMEBUFFERINFO_PROTOCOL_GET_INFO) (
193 IN APPLE_FRAMEBUFFERINFO_PROTOCOL *This,
194 OUT UINT32 *BaseAddr,
195 OUT UINT32 *Something,
196 OUT UINT32 *RowBytes,
197 OUT UINT32 *Width,
198 OUT UINT32 *Height,
199 OUT UINT32 *Depth);
200
201struct _APPLE_FRAMEBUFFERINFO_PROTOCOL {
202 APPLE_FRAMEBUFFERINFO_PROTOCOL_GET_INFO GetInfo;
203 VBOX_VGA_PRIVATE_DATA *Private;
204};
205
206EFI_STATUS EFIAPI
207GetFrameBufferInfo(IN APPLE_FRAMEBUFFERINFO_PROTOCOL *This,
208 OUT UINT32 *BaseAddr,
209 OUT UINT32 *Something,
210 OUT UINT32 *RowBytes,
211 OUT UINT32 *Width,
212 OUT UINT32 *Height,
213 OUT UINT32 *Depth);
214
215static APPLE_FRAMEBUFFERINFO_PROTOCOL gAppleFrameBufferInfo =
216{
217 GetFrameBufferInfo,
218 NULL
219};
220
221
222/*
223 * @todo move this function to the library.
224 */
225UINT32 VBoxVgaGetVmVariable(UINT32 Variable, CHAR8* Buffer, UINT32 Size)
226{
227 UINT32 VarLen, i;
228
229 ASMOutU32(EFI_INFO_PORT, Variable);
230 VarLen = ASMInU32(EFI_INFO_PORT);
231
232 for (i = 0; i < VarLen && i < Size; i++)
233 Buffer[i] = ASMInU8(EFI_INFO_PORT);
234
235 return VarLen;
236}
237
238
239/**
240 VBoxVgaControllerDriverSupported
241
242 TODO: This - add argument and description to function comment
243 TODO: Controller - add argument and description to function comment
244 TODO: RemainingDevicePath - add argument and description to function comment
245**/
246EFI_STATUS
247EFIAPI
248VBoxVgaControllerDriverSupported (
249 IN EFI_DRIVER_BINDING_PROTOCOL *This,
250 IN EFI_HANDLE Controller,
251 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
252 )
253{
254 EFI_STATUS Status;
255 EFI_PCI_IO_PROTOCOL *PciIo;
256 PCI_TYPE00 Pci;
257 EFI_DEV_PATH *Node;
258
259 //
260 // Open the PCI I/O Protocol
261 //
262 Status = gBS->OpenProtocol (
263 Controller,
264 &gEfiPciIoProtocolGuid,
265 (VOID **) &PciIo,
266 This->DriverBindingHandle,
267 Controller,
268 EFI_OPEN_PROTOCOL_BY_DRIVER
269 );
270 if (EFI_ERROR (Status)) {
271 DEBUG((DEBUG_INFO, "%a:%d status:%r\n", __FILE__, __LINE__, Status));
272 return Status;
273 }
274
275 //
276 // Read the PCI Configuration Header from the PCI Device
277 //
278 Status = PciIo->Pci.Read (
279 PciIo,
280 EfiPciIoWidthUint32,
281 0,
282 sizeof (Pci) / sizeof (UINT32),
283 &Pci
284 );
285 if (EFI_ERROR (Status)) {
286 DEBUG((DEBUG_INFO, "%a:%d status:%r\n", __FILE__, __LINE__, Status));
287 goto Done;
288 }
289
290 Status = EFI_UNSUPPORTED;
291 //
292 // See if the I/O enable is on. Most systems only allow one VGA device to be turned on
293 // at a time, so see if this is one that is turned on.
294 //
295 // if (((Pci.Hdr.Command & 0x01) == 0x01)) {
296 //
297 // See if this is a VirtualBox VGA PCI controller
298 //
299 if (Pci.Hdr.VendorId == VBOX_VENDOR_ID) {
300 if (Pci.Hdr.DeviceId == VBOX_VGA_DEVICE_ID) {
301
302 Status = EFI_SUCCESS;
303 if (RemainingDevicePath != NULL) {
304 Node = (EFI_DEV_PATH *) RemainingDevicePath;
305 //
306 // Check if RemainingDevicePath is the End of Device Path Node,
307 // if yes, return EFI_SUCCESS
308 //
309 if (!IsDevicePathEnd (Node)) {
310 //
311 // If RemainingDevicePath isn't the End of Device Path Node,
312 // check its validation
313 //
314 if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
315 Node->DevPath.SubType != ACPI_ADR_DP ||
316 DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {
317 DEBUG((DEBUG_INFO, "%a:%d status:%r\n", __FILE__, __LINE__, Status));
318 Status = EFI_UNSUPPORTED;
319 }
320 }
321 }
322 }
323 }
324
325Done:
326 //
327 // Close the PCI I/O Protocol
328 //
329 gBS->CloseProtocol (
330 Controller,
331 &gEfiPciIoProtocolGuid,
332 This->DriverBindingHandle,
333 Controller
334 );
335
336 DEBUG((DEBUG_INFO, "%a:%d status:%r\n", __FILE__, __LINE__, Status));
337 return Status;
338}
339
340/**
341 VBoxVgaControllerDriverStart
342
343 TODO: This - add argument and description to function comment
344 TODO: Controller - add argument and description to function comment
345 TODO: RemainingDevicePath - add argument and description to function comment
346**/
347EFI_STATUS
348EFIAPI
349VBoxVgaControllerDriverStart (
350 IN EFI_DRIVER_BINDING_PROTOCOL *This,
351 IN EFI_HANDLE Controller,
352 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
353 )
354{
355 EFI_STATUS Status;
356 VBOX_VGA_PRIVATE_DATA *Private;
357 BOOLEAN PciAttributesSaved;
358 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
359 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
360
361 PciAttributesSaved = FALSE;
362 //
363 // Allocate Private context data for UGA Draw interface.
364 //
365 Private = AllocateZeroPool (sizeof (VBOX_VGA_PRIVATE_DATA));
366 if (Private == NULL) {
367 Status = EFI_OUT_OF_RESOURCES;
368 goto Error;
369 }
370 gAppleFrameBufferInfo.Private = Private;
371 //
372 // Set up context record
373 //
374 Private->Signature = VBOX_VGA_PRIVATE_DATA_SIGNATURE;
375 Private->Handle = NULL;
376
377 //
378 // Open PCI I/O Protocol
379 //
380 Status = gBS->OpenProtocol (
381 Controller,
382 &gEfiPciIoProtocolGuid,
383 (VOID **) &Private->PciIo,
384 This->DriverBindingHandle,
385 Controller,
386 EFI_OPEN_PROTOCOL_BY_DRIVER
387 );
388 if (EFI_ERROR (Status)) {
389 goto Error;
390 }
391
392 //
393 // Save original PCI attributes
394 //
395 Status = Private->PciIo->Attributes (
396 Private->PciIo,
397 EfiPciIoAttributeOperationGet,
398 0,
399 &Private->OriginalPciAttributes
400 );
401
402 if (EFI_ERROR (Status)) {
403 goto Error;
404 }
405 PciAttributesSaved = TRUE;
406
407 Status = Private->PciIo->Attributes (
408 Private->PciIo,
409 EfiPciIoAttributeOperationEnable,
410 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
411 NULL
412 );
413 if (EFI_ERROR (Status)) {
414 goto Error;
415 }
416
417 //
418 // Get ParentDevicePath
419 //
420 Status = gBS->HandleProtocol (
421 Controller,
422 &gEfiDevicePathProtocolGuid,
423 (VOID **) &ParentDevicePath
424 );
425 if (EFI_ERROR (Status)) {
426 goto Error;
427 }
428
429 if (FeaturePcdGet (PcdSupportGop)) {
430 //
431 // Set Gop Device Path
432 //
433 if (RemainingDevicePath == NULL) {
434 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
435 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
436 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
437 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
438 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
439
440 Private->GopDevicePath = AppendDevicePathNode (
441 ParentDevicePath,
442 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
443 );
444 } else if (!IsDevicePathEnd (RemainingDevicePath)) {
445 //
446 // If RemainingDevicePath isn't the End of Device Path Node,
447 // only scan the specified device by RemainingDevicePath
448 //
449 Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
450 } else {
451 //
452 // If RemainingDevicePath is the End of Device Path Node,
453 // don't create child device and return EFI_SUCCESS
454 //
455 Private->GopDevicePath = NULL;
456 }
457
458 if (Private->GopDevicePath != NULL) {
459 //
460 // Create child handle and device path protocol first
461 //
462 Private->Handle = NULL;
463 Status = gBS->InstallMultipleProtocolInterfaces (
464 &Private->Handle,
465 &gEfiDevicePathProtocolGuid,
466 Private->GopDevicePath,
467 NULL
468 );
469 }
470 }
471
472 //
473 // Get VRAM size, needed for constructing a correct video mode list
474 //
475 Private->VRAMSize = ASMInU32(VBE_DISPI_IOPORT_DATA);
476
477 //
478 // Construct video mode list
479 //
480 Status = VBoxVgaVideoModeSetup (Private);
481 if (EFI_ERROR (Status)) {
482 goto Error;
483 }
484
485 if (FeaturePcdGet (PcdSupportUga)) {
486 //
487 // Start the UGA Draw software stack.
488 //
489 Status = VBoxVgaUgaDrawConstructor (Private);
490 ASSERT_EFI_ERROR (Status);
491
492 Private->UgaDevicePath = ParentDevicePath;
493 Status = gBS->InstallMultipleProtocolInterfaces (
494 &Controller,
495 //&gEfiUgaDrawProtocolGuid,
496 //&Private->UgaDraw,
497 &gEfiDevicePathProtocolGuid,
498 Private->UgaDevicePath,
499 NULL
500 );
501 Status = gBS->InstallMultipleProtocolInterfaces (
502 &Controller,
503 &gEfiUgaDrawProtocolGuid,
504 &Private->UgaDraw,
505 NULL
506 );
507
508 } else if (FeaturePcdGet (PcdSupportGop)) {
509 if (Private->GopDevicePath == NULL) {
510 //
511 // If RemainingDevicePath is the End of Device Path Node,
512 // don't create child device and return EFI_SUCCESS
513 //
514 Status = EFI_SUCCESS;
515 } else {
516
517 //
518 // Start the GOP software stack.
519 //
520 Status = VBoxVgaGraphicsOutputConstructor (Private);
521 ASSERT_EFI_ERROR (Status);
522
523 Status = gBS->InstallMultipleProtocolInterfaces (
524 &Private->Handle,
525 &gEfiGraphicsOutputProtocolGuid,
526 &Private->GraphicsOutput,
527 &gEfiEdidDiscoveredProtocolGuid,
528 &Private->EdidDiscovered,
529 &gEfiEdidActiveProtocolGuid,
530 &Private->EdidActive,
531 NULL
532 );
533 }
534 } else {
535 //
536 // This driver must support eithor GOP or UGA or both.
537 //
538 ASSERT (FALSE);
539 Status = EFI_UNSUPPORTED;
540 }
541
542Error:
543 if (EFI_ERROR (Status)) {
544 if (Private) {
545 if (Private->PciIo) {
546 if (PciAttributesSaved == TRUE) {
547 //
548 // Restore original PCI attributes
549 //
550 Private->PciIo->Attributes (
551 Private->PciIo,
552 EfiPciIoAttributeOperationSet,
553 Private->OriginalPciAttributes,
554 NULL
555 );
556 }
557 //
558 // Close the PCI I/O Protocol
559 //
560 gBS->CloseProtocol (
561 Private->Handle,
562 &gEfiPciIoProtocolGuid,
563 This->DriverBindingHandle,
564 Private->Handle
565 );
566 }
567
568 gBS->FreePool (Private);
569 }
570 }
571
572 return Status;
573}
574
575/**
576 VBoxVgaControllerDriverStop
577
578 TODO: This - add argument and description to function comment
579 TODO: Controller - add argument and description to function comment
580 TODO: NumberOfChildren - add argument and description to function comment
581 TODO: ChildHandleBuffer - add argument and description to function comment
582 TODO: EFI_SUCCESS - add return value to function comment
583**/
584EFI_STATUS
585EFIAPI
586VBoxVgaControllerDriverStop (
587 IN EFI_DRIVER_BINDING_PROTOCOL *This,
588 IN EFI_HANDLE Controller,
589 IN UINTN NumberOfChildren,
590 IN EFI_HANDLE *ChildHandleBuffer
591 )
592{
593 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
594 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
595
596 EFI_STATUS Status;
597 VBOX_VGA_PRIVATE_DATA *Private;
598
599 if (FeaturePcdGet (PcdSupportUga)) {
600 Status = gBS->OpenProtocol (
601 Controller,
602 &gEfiUgaDrawProtocolGuid,
603 (VOID **) &UgaDraw,
604 This->DriverBindingHandle,
605 Controller,
606 EFI_OPEN_PROTOCOL_GET_PROTOCOL
607 );
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611
612 //
613 // Get our private context information
614 //
615 Private = VBOX_VGA_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw);
616 VBoxVgaUgaDrawDestructor (Private);
617
618 if (FeaturePcdGet (PcdSupportGop)) {
619 VBoxVgaGraphicsOutputDestructor (Private);
620 //
621 // Remove the UGA and GOP protocol interface from the system
622 //
623 Status = gBS->UninstallMultipleProtocolInterfaces (
624 Private->Handle,
625 &gEfiUgaDrawProtocolGuid,
626 &Private->UgaDraw,
627 &gEfiGraphicsOutputProtocolGuid,
628 &Private->GraphicsOutput,
629 NULL
630 );
631 } else {
632 //
633 // Remove the UGA Draw interface from the system
634 //
635 Status = gBS->UninstallMultipleProtocolInterfaces (
636 Private->Handle,
637 &gEfiUgaDrawProtocolGuid,
638 &Private->UgaDraw,
639 NULL
640 );
641 }
642 } else {
643 Status = gBS->OpenProtocol (
644 Controller,
645 &gEfiGraphicsOutputProtocolGuid,
646 (VOID **) &GraphicsOutput,
647 This->DriverBindingHandle,
648 Controller,
649 EFI_OPEN_PROTOCOL_GET_PROTOCOL
650 );
651 if (EFI_ERROR (Status)) {
652 return Status;
653 }
654
655 //
656 // Get our private context information
657 //
658 Private = VBOX_VGA_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
659
660 VBoxVgaGraphicsOutputDestructor (Private);
661 //
662 // Remove the GOP protocol interface from the system
663 //
664 Status = gBS->UninstallMultipleProtocolInterfaces (
665 Private->Handle,
666 &gEfiGraphicsOutputProtocolGuid,
667 &Private->GraphicsOutput,
668 NULL
669 );
670 }
671
672 if (EFI_ERROR (Status)) {
673 return Status;
674 }
675
676 if (Private->ModeData) {
677 FreePool(Private->ModeData);
678 Private->ModeData = NULL;
679 }
680
681 //
682 // Restore original PCI attributes
683 //
684 Private->PciIo->Attributes (
685 Private->PciIo,
686 EfiPciIoAttributeOperationSet,
687 Private->OriginalPciAttributes,
688 NULL
689 );
690
691 //
692 // Close the PCI I/O Protocol
693 //
694 gBS->CloseProtocol (
695 Controller,
696 &gEfiPciIoProtocolGuid,
697 This->DriverBindingHandle,
698 Controller
699 );
700
701 //
702 // Free our instance data
703 //
704 gBS->FreePool (Private);
705
706 return EFI_SUCCESS;
707}
708
709/**
710 VBoxVgaUgaDrawDestructor
711
712 TODO: Private - add argument and description to function comment
713 TODO: EFI_SUCCESS - add return value to function comment
714**/
715EFI_STATUS
716VBoxVgaUgaDrawDestructor (
717 VBOX_VGA_PRIVATE_DATA *Private
718 )
719{
720 return EFI_SUCCESS;
721}
722
723/**
724 TODO: Add function description
725
726 @param Private TODO: add argument description
727 @param Index TODO: add argument description
728 @param Red TODO: add argument description
729 @param Green TODO: add argument description
730 @param Blue TODO: add argument description
731
732 TODO: add return values
733
734**/
735VOID
736SetPaletteColor (
737 VBOX_VGA_PRIVATE_DATA *Private,
738 UINTN Index,
739 UINT8 Red,
740 UINT8 Green,
741 UINT8 Blue
742 )
743{
744 ASMOutU8(PALETTE_INDEX_REGISTER, (UINT8) Index);
745 ASMOutU8(PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
746 ASMOutU8(PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
747 ASMOutU8(PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
748}
749
750/**
751 TODO: Add function description
752
753 @param Private TODO: add argument description
754
755 TODO: add return values
756
757**/
758VOID
759SetDefaultPalette (
760 VBOX_VGA_PRIVATE_DATA *Private
761 )
762{
763#if 1
764 UINTN Index;
765 UINTN RedIndex;
766 UINTN GreenIndex;
767 UINTN BlueIndex;
768 Index = 0;
769 for (RedIndex = 0; RedIndex < 8; RedIndex++) {
770 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
771 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
772 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
773 Index++;
774 }
775 }
776 }
777#else
778 {
779 int i;
780 static const UINT8 s_a3bVgaDac[64*3] =
781 {
782 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x2A,
784 0x00, 0x2A, 0x00,
785 0x00, 0x2A, 0x2A,
786 0x2A, 0x00, 0x00,
787 0x2A, 0x00, 0x2A,
788 0x2A, 0x2A, 0x00,
789 0x2A, 0x2A, 0x2A,
790 0x00, 0x00, 0x15,
791 0x00, 0x00, 0x3F,
792 0x00, 0x2A, 0x15,
793 0x00, 0x2A, 0x3F,
794 0x2A, 0x00, 0x15,
795 0x2A, 0x00, 0x3F,
796 0x2A, 0x2A, 0x15,
797 0x2A, 0x2A, 0x3F,
798 0x00, 0x15, 0x00,
799 0x00, 0x15, 0x2A,
800 0x00, 0x3F, 0x00,
801 0x00, 0x3F, 0x2A,
802 0x2A, 0x15, 0x00,
803 0x2A, 0x15, 0x2A,
804 0x2A, 0x3F, 0x00,
805 0x2A, 0x3F, 0x2A,
806 0x00, 0x15, 0x15,
807 0x00, 0x15, 0x3F,
808 0x00, 0x3F, 0x15,
809 0x00, 0x3F, 0x3F,
810 0x2A, 0x15, 0x15,
811 0x2A, 0x15, 0x3F,
812 0x2A, 0x3F, 0x15,
813 0x2A, 0x3F, 0x3F,
814 0x15, 0x00, 0x00,
815 0x15, 0x00, 0x2A,
816 0x15, 0x2A, 0x00,
817 0x15, 0x2A, 0x2A,
818 0x3F, 0x00, 0x00,
819 0x3F, 0x00, 0x2A,
820 0x3F, 0x2A, 0x00,
821 0x3F, 0x2A, 0x2A,
822 0x15, 0x00, 0x15,
823 0x15, 0x00, 0x3F,
824 0x15, 0x2A, 0x15,
825 0x15, 0x2A, 0x3F,
826 0x3F, 0x00, 0x15,
827 0x3F, 0x00, 0x3F,
828 0x3F, 0x2A, 0x15,
829 0x3F, 0x2A, 0x3F,
830 0x15, 0x15, 0x00,
831 0x15, 0x15, 0x2A,
832 0x15, 0x3F, 0x00,
833 0x15, 0x3F, 0x2A,
834 0x3F, 0x15, 0x00,
835 0x3F, 0x15, 0x2A,
836 0x3F, 0x3F, 0x00,
837 0x3F, 0x3F, 0x2A,
838 0x15, 0x15, 0x15,
839 0x15, 0x15, 0x3F,
840 0x15, 0x3F, 0x15,
841 0x15, 0x3F, 0x3F,
842 0x3F, 0x15, 0x15,
843 0x3F, 0x15, 0x3F,
844 0x3F, 0x3F, 0x15,
845 0x3F, 0x3F, 0x3F
846 };
847
848 for (i = 0; i < 64; ++i)
849 {
850 ASMOutU8(PALETTE_INDEX_REGISTER, (UINT8)i);
851 ASMOutU8(PALETTE_DATA_REGISTER, s_a3bVgaDac[i*3 + 0]);
852 ASMOutU8(PALETTE_DATA_REGISTER, s_a3bVgaDac[i*3 + 1]);
853 ASMOutU8(PALETTE_DATA_REGISTER, s_a3bVgaDac[i*3 + 2]);
854 }
855 }
856
857#endif
858}
859
860/**
861 TODO: Add function description
862
863 @param Private TODO: add argument description
864
865 TODO: add return values
866
867**/
868VOID
869ClearScreen (
870 VBOX_VGA_PRIVATE_DATA *Private
871 )
872{
873 EFI_GRAPHICS_OUTPUT_BLT_PIXEL blt;
874 blt.Blue = 0;
875 blt.Green = 0;
876 blt.Red = 0;
877 blt.Reserved = 0;
878 Private->PciIo->Mem.Write (
879 Private->PciIo,
880 EfiPciIoWidthFillUint32,
881 0,
882 0,
883 Private->ModeData[Private->CurrentMode].HorizontalResolution
884 * Private->ModeData[Private->CurrentMode].VerticalResolution,
885 &blt
886 );
887}
888
889/**
890 TODO: Add function description
891
892 @param Private TODO: add argument description
893
894 TODO: add return values
895
896**/
897VOID
898DrawLogo (
899 VBOX_VGA_PRIVATE_DATA *Private,
900 UINTN ScreenWidth,
901 UINTN ScreenHeight
902 )
903{
904 DEBUG((DEBUG_INFO, "UGA is %a GOP is %a\n",
905 FeaturePcdGet(PcdSupportUga) ? "on" : "off",
906 FeaturePcdGet(PcdSupportGop) ? "on" : "off"
907 ));
908}
909
910/**
911 TODO: Add function description
912
913 @param Private TODO: add argument description
914 @param ModeData TODO: add argument description
915
916 TODO: add return values
917
918**/
919VOID
920InitializeGraphicsMode (
921 VBOX_VGA_PRIVATE_DATA *Private,
922 VBOX_VGA_VIDEO_MODES *ModeData
923 )
924{
925 UINT16 DeviceId;
926 EFI_STATUS Status;
927 int i;
928
929 //
930 // Read the PCI ID from the PCI Device (dummy)
931 //
932 Status = Private->PciIo->Pci.Read (
933 Private->PciIo,
934 EfiPciIoWidthUint16,
935 PCI_DEVICE_ID_OFFSET,
936 1,
937 &DeviceId
938 );
939 ASSERT_EFI_ERROR(Status);
940
941 ASMOutU8(MISC_OUTPUT_REGISTER, 0xc3);
942 ASMOutU16(SEQ_ADDRESS_REGISTER, 0x0204);
943
944 ASMInU8(INPUT_STATUS_1_REGISTER); // reset attribute address/data flip-flop
945 ASMOutU8(ATT_ADDRESS_REGISTER, 0); // blank screen using the attribute address register
946
947 ASMOutU16(CRTC_ADDRESS_REGISTER, 0x0011);
948
949 ASMOutU16(SEQ_ADDRESS_REGISTER, 0x0100);
950
951 if (!ModeData->CrtcSettings)
952 {
953 // No CRTC settings, use VBE
954 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x00); ASMOutU16(VBE_DISPI_IOPORT_DATA, 0xb0c0); // ID
955 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x04); ASMOutU16(VBE_DISPI_IOPORT_DATA, 0); // ENABLE
956 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x01); ASMOutU16(VBE_DISPI_IOPORT_DATA, (UINT16)ModeData->Width); // XRES
957 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x02); ASMOutU16(VBE_DISPI_IOPORT_DATA, (UINT16)ModeData->Height); // YRES
958 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x03); ASMOutU16(VBE_DISPI_IOPORT_DATA, (UINT16)ModeData->ColorDepth); // BPP
959 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x05); ASMOutU16(VBE_DISPI_IOPORT_DATA, 0); // BANK
960 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x06); ASMOutU16(VBE_DISPI_IOPORT_DATA, (UINT16)ModeData->Width); // VIRT_WIDTH
961 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x07); ASMOutU16(VBE_DISPI_IOPORT_DATA, (UINT16)ModeData->Height); // VIRT_HEIGHT
962 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x08); ASMOutU16(VBE_DISPI_IOPORT_DATA, 0); // X_OFFSET
963 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x09); ASMOutU16(VBE_DISPI_IOPORT_DATA, 0); // Y_OFFSET
964 ASMOutU16(VBE_DISPI_IOPORT_INDEX, 0x04); ASMOutU16(VBE_DISPI_IOPORT_DATA, 1); // ENABLE
965 }
966 else
967 {
968 BOUTB(ModeData->CrtcSettings, 25, CRTC_ADDRESS_REGISTER, CRTC_DATA_REGISTER);
969 }
970
971 ASMOutU8(MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
972
973 if (ModeData->SeqSettings)
974 BOUTB(ModeData->SeqSettings, 5, SEQ_ADDRESS_REGISTER, SEQ_DATA_REGISTER);
975 else
976 BOUTB(Seq_Default, 5, SEQ_ADDRESS_REGISTER, SEQ_DATA_REGISTER);
977
978 ASMOutU16(SEQ_ADDRESS_REGISTER, 0x0300);
979
980 BOUTB(GraphicsController, 9, GRAPH_ADDRESS_REGISTER, GRAPH_DATA_REGISTER);
981
982 ASMInU8(INPUT_STATUS_1_REGISTER); // reset attribute address/data flip-flop
983 // attribute controller is weird: data writes to the address register
984 BOUTB(AttributeController, 21, ATT_ADDRESS_REGISTER, ATT_ADDRESS_REGISTER);
985 ASMOutU8(ATT_ADDRESS_REGISTER, 0x20);
986
987 if (ModeData->ColorDepth <= 8)
988 {
989 ASMOutU8(DAC_PIXEL_MASK_REGISTER, 0xff);
990 SetDefaultPalette(Private);
991 }
992
993 ClearScreen(Private);
994}
995
996/** Aka know as AppleGraphInfoProtocolGuid in other sources. */
997#define EFI_UNKNOWN_2_PROTOCOL_GUID \
998 { 0xE316E100, 0x0751, 0x4C49, {0x90, 0x56, 0x48, 0x6C, 0x7E, 0x47, 0x29, 0x03} }
999
1000EFI_GUID gEfiAppleFrameBufferInfoGuid = EFI_UNKNOWN_2_PROTOCOL_GUID;
1001
1002EFI_STATUS EFIAPI
1003GetFrameBufferInfo(IN APPLE_FRAMEBUFFERINFO_PROTOCOL *This,
1004 OUT UINT32 *BaseAddr,
1005 OUT UINT32 *Something,
1006 OUT UINT32 *RowBytes,
1007 OUT UINT32 *Width,
1008 OUT UINT32 *Height,
1009 OUT UINT32 *Depth)
1010{
1011 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
1012 UINT32 W, H, BPP;
1013 VBOX_VGA_PRIVATE_DATA *Private = This->Private;
1014 UINTN CurrentModeNumber = Private->CurrentMode;
1015 VBOX_VGA_MODE_DATA const *pCurrentMode = &Private->ModeData[CurrentModeNumber];
1016
1017 W = pCurrentMode->HorizontalResolution;
1018 H = pCurrentMode->VerticalResolution;
1019 BPP = pCurrentMode->ColorDepth;
1020 DEBUG((DEBUG_INFO, "%a:%d GetFrameBufferInfo: %dx%d bpp:%d\n", __FILE__, __LINE__, W, H, BPP));
1021
1022 Private->PciIo->GetBarAttributes (
1023 Private->PciIo,
1024 0,
1025 NULL,
1026 (VOID**) &FrameBufDesc
1027 );
1028
1029
1030 /* EFI firmware remaps it here */
1031 *BaseAddr = (UINT32)FrameBufDesc->AddrRangeMin;
1032 *RowBytes = W * BPP / 8;
1033 *Width = W;
1034 *Height = H;
1035 *Depth = BPP;
1036 // what *Something shall be?
1037
1038 return EFI_SUCCESS;
1039}
1040
1041EFI_STATUS
1042EFIAPI
1043InitializeVBoxVga (
1044 IN EFI_HANDLE ImageHandle,
1045 IN EFI_SYSTEM_TABLE *SystemTable
1046 )
1047{
1048 EFI_STATUS Status;
1049
1050 Status = EfiLibInstallDriverBindingComponentName2 (
1051 ImageHandle,
1052 SystemTable,
1053 &gVBoxVgaDriverBinding,
1054 ImageHandle,
1055 &gVBoxVgaComponentName,
1056 &gVBoxVgaComponentName2
1057 );
1058 ASSERT_EFI_ERROR (Status);
1059
1060 //
1061 // Install EFI Driver Supported EFI Version Protocol required for
1062 // EFI drivers that are on PCI and other plug in cards.
1063 //
1064 gVBoxVgaDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);
1065 Status = gBS->InstallMultipleProtocolInterfaces (
1066 &ImageHandle,
1067 &gEfiDriverSupportedEfiVersionProtocolGuid,
1068 &gVBoxVgaDriverSupportedEfiVersion,
1069 &gEfiAppleFrameBufferInfoGuid,
1070 &gAppleFrameBufferInfo,
1071 NULL
1072 );
1073 ASSERT_EFI_ERROR (Status);
1074
1075 return Status;
1076}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette