VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuVideoDxe/Initialize.c@ 105681

最後變更 在這個檔案從105681是 101291,由 vboxsync 提交於 18 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 12.8 KB
 
1/** @file
2 Graphics Output Protocol functions for the QEMU video controller.
3
4 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "Qemu.h"
11
12///
13/// Generic Attribute Controller Register Settings
14///
15UINT8 AttributeController[21] = {
16 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
17 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
18 0x41, 0x00, 0x0F, 0x00, 0x00
19};
20
21///
22/// Generic Graphics Controller Register Settings
23///
24UINT8 GraphicsController[9] = {
25 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
26};
27
28//
29// 640 x 480 x 256 color @ 60 Hertz
30//
31UINT8 Crtc_640_480_256_60[28] = {
32 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
33 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
35 0xff, 0x00, 0x00, 0x22
36};
37
38UINT8 Crtc_640_480_32bpp_60[28] = {
39 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
40 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,
42 0xff, 0x00, 0x00, 0x32
43};
44
45UINT16 Seq_640_480_256_60[15] = {
46 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
47 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
48};
49
50UINT16 Seq_640_480_32bpp_60[15] = {
51 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
52 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
53};
54
55//
56// 800 x 600 x 256 color @ 60 Hertz
57//
58UINT8 Crtc_800_600_256_60[28] = {
59 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
60 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
62 0xFF, 0x00, 0x00, 0x22
63};
64
65UINT8 Crtc_800_600_32bpp_60[28] = {
66 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
67 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,
69 0xFF, 0x00, 0x00, 0x32
70};
71
72UINT16 Seq_800_600_256_60[15] = {
73 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
74 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
75};
76
77UINT16 Seq_800_600_32bpp_60[15] = {
78 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
79 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
80};
81
82UINT8 Crtc_960_720_32bpp_60[28] = {
83 0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
84 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
86 0xFF, 0x4A, 0x00, 0x32
87};
88
89UINT16 Seq_960_720_32bpp_60[15] = {
90 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
91 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
92};
93
94//
95// 1024 x 768 x 256 color @ 60 Hertz
96//
97UINT8 Crtc_1024_768_256_60[28] = {
98 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
99 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
101 0xFF, 0x4A, 0x00, 0x22
102};
103
104UINT16 Seq_1024_768_256_60[15] = {
105 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
106 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
107};
108
109//
110// 1024 x 768 x 24-bit color @ 60 Hertz
111//
112UINT8 Crtc_1024_768_24bpp_60[28] = {
113 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
114 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
116 0xFF, 0x4A, 0x00, 0x32
117};
118
119UINT16 Seq_1024_768_24bpp_60[15] = {
120 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,
121 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
122};
123
124UINT8 Crtc_1024_768_32bpp_60[28] = {
125 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
126 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
128 0xFF, 0x4A, 0x00, 0x32
129};
130
131UINT16 Seq_1024_768_32bpp_60[15] = {
132 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
133 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
134};
135
136///
137/// Table of supported video modes
138///
139QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[] = {
140 // { 640, 480, 8, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 },
141 // { 800, 600, 8, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef },
142 { 640, 480, 32, Crtc_640_480_32bpp_60, Seq_640_480_32bpp_60, 0xef },
143 { 800, 600, 32, Crtc_800_600_32bpp_60, Seq_800_600_32bpp_60, 0xef },
144 // { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
145 { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }
146 // { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
147 // { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
148};
149
150#define QEMU_VIDEO_CIRRUS_MODE_COUNT \
151 (ARRAY_SIZE (QemuVideoCirrusModes))
152
153/**
154 Construct the valid video modes for QemuVideo.
155
156**/
157EFI_STATUS
158QemuVideoCirrusModeSetup (
159 QEMU_VIDEO_PRIVATE_DATA *Private
160 )
161{
162 UINT32 Index;
163 QEMU_VIDEO_MODE_DATA *ModeData;
164 QEMU_VIDEO_CIRRUS_MODES *VideoMode;
165
166 //
167 // Setup Video Modes
168 //
169 Private->ModeData = AllocatePool (
170 sizeof (Private->ModeData[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT
171 );
172 if (Private->ModeData == NULL) {
173 return EFI_OUT_OF_RESOURCES;
174 }
175
176 ModeData = Private->ModeData;
177 VideoMode = &QemuVideoCirrusModes[0];
178 for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index++) {
179 ModeData->InternalModeIndex = Index;
180 ModeData->HorizontalResolution = VideoMode->Width;
181 ModeData->VerticalResolution = VideoMode->Height;
182 ModeData->ColorDepth = VideoMode->ColorDepth;
183 DEBUG ((
184 DEBUG_INFO,
185 "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",
186 (INT32)(ModeData - Private->ModeData),
187 ModeData->InternalModeIndex,
188 ModeData->HorizontalResolution,
189 ModeData->VerticalResolution,
190 ModeData->ColorDepth
191 ));
192
193 ModeData++;
194 VideoMode++;
195 }
196
197 Private->MaxMode = ModeData - Private->ModeData;
198
199 return EFI_SUCCESS;
200}
201
202///
203/// Table of supported video modes
204///
205STATIC QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = {
206 { 640, 480 },
207 { 800, 480 },
208 { 800, 600 },
209 { 832, 624 },
210 { 960, 640 },
211 { 1024, 600 },
212 { 1024, 768 },
213 { 1152, 864 },
214 { 1152, 870 },
215 { 1280, 720 },
216 { 1280, 760 },
217 { 1280, 768 },
218 { 1280, 800 },
219 { 1280, 960 },
220 { 1280, 1024 },
221 { 1360, 768 },
222 { 1366, 768 },
223 { 1400, 1050 },
224 { 1440, 900 },
225 { 1600, 900 },
226 { 1600, 1200 },
227 { 1680, 1050 },
228 { 1920, 1080 },
229 { 1920, 1200 },
230 { 1920, 1440 },
231 { 2000, 2000 },
232 { 2048, 1536 },
233 { 2048, 2048 },
234 { 2560, 1440 },
235 { 2560, 1600 },
236 { 2560, 2048 },
237 { 2800, 2100 },
238 { 3200, 2400 },
239 { 3840, 2160 },
240 { 4096, 2160 },
241 { 7680, 4320 },
242 { 8192, 4320 }
243};
244
245#define QEMU_VIDEO_BOCHS_MODE_COUNT \
246 (ARRAY_SIZE (QemuVideoBochsModes))
247
248STATIC
249VOID
250QemuVideoBochsAddMode (
251 QEMU_VIDEO_PRIVATE_DATA *Private,
252 UINT32 AvailableFbSize,
253 UINT32 Width,
254 UINT32 Height
255 )
256{
257 QEMU_VIDEO_MODE_DATA *ModeData = Private->ModeData + Private->MaxMode;
258 UINTN RequiredFbSize;
259
260 RequiredFbSize = (UINTN)Width * Height * 4;
261 if (RequiredFbSize > AvailableFbSize) {
262 DEBUG ((
263 DEBUG_INFO,
264 "Skipping Bochs Mode %dx%d, 32-bit (not enough vram)\n",
265 Width,
266 Height
267 ));
268 return;
269 }
270
271 ModeData->InternalModeIndex = (UINT32)Private->MaxMode;
272 ModeData->HorizontalResolution = Width;
273 ModeData->VerticalResolution = Height;
274 ModeData->ColorDepth = 32;
275 DEBUG ((
276 DEBUG_INFO,
277 "Adding Bochs Internal Mode %d: %dx%d, %d-bit\n",
278 ModeData->InternalModeIndex,
279 ModeData->HorizontalResolution,
280 ModeData->VerticalResolution,
281 ModeData->ColorDepth
282 ));
283
284 Private->MaxMode++;
285}
286
287STATIC
288VOID
289QemuVideoBochsEdid (
290 QEMU_VIDEO_PRIVATE_DATA *Private,
291 UINT32 *XRes,
292 UINT32 *YRes
293 )
294{
295 EFI_STATUS Status;
296
297 if (Private->Variant != QEMU_VIDEO_BOCHS_MMIO) {
298 return;
299 }
300
301 Status = Private->PciIo->Mem.Read (
302 Private->PciIo,
303 EfiPciIoWidthUint8,
304 PCI_BAR_IDX2,
305 0,
306 sizeof (Private->Edid),
307 Private->Edid
308 );
309 if (Status != EFI_SUCCESS) {
310 DEBUG ((
311 DEBUG_INFO,
312 "%a: mmio read failed\n",
313 __func__
314 ));
315 return;
316 }
317
318 if ((Private->Edid[0] != 0x00) ||
319 (Private->Edid[1] != 0xff))
320 {
321 DEBUG ((
322 DEBUG_INFO,
323 "%a: magic check failed\n",
324 __func__
325 ));
326 return;
327 }
328
329 DEBUG ((
330 DEBUG_INFO,
331 "%a: blob found (extensions: %d)\n",
332 __func__,
333 Private->Edid[126]
334 ));
335
336 if ((Private->Edid[54] == 0x00) &&
337 (Private->Edid[55] == 0x00))
338 {
339 DEBUG ((
340 DEBUG_INFO,
341 "%a: no detailed timing descriptor\n",
342 __func__
343 ));
344 return;
345 }
346
347 *XRes = Private->Edid[56] | ((Private->Edid[58] & 0xf0) << 4);
348 *YRes = Private->Edid[59] | ((Private->Edid[61] & 0xf0) << 4);
349 DEBUG ((
350 DEBUG_INFO,
351 "%a: default resolution: %dx%d\n",
352 __func__,
353 *XRes,
354 *YRes
355 ));
356
357 if (PcdGet8 (PcdVideoResolutionSource) == 0) {
358 Status = PcdSet32S (PcdVideoHorizontalResolution, *XRes);
359 ASSERT_RETURN_ERROR (Status);
360 Status = PcdSet32S (PcdVideoVerticalResolution, *YRes);
361 ASSERT_RETURN_ERROR (Status);
362 Status = PcdSet8S (PcdVideoResolutionSource, 2);
363 ASSERT_RETURN_ERROR (Status);
364 }
365
366 // TODO: register edid as gEfiEdidDiscoveredProtocolGuid ?
367}
368
369EFI_STATUS
370QemuVideoBochsModeSetup (
371 QEMU_VIDEO_PRIVATE_DATA *Private,
372 BOOLEAN IsQxl
373 )
374{
375 UINT32 AvailableFbSize;
376 UINT32 Index, XRes = 0, YRes = 0;
377
378 //
379 // Fetch the available framebuffer size.
380 //
381 // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the
382 // drawable framebuffer. Up to and including qemu-2.1 however it used to
383 // return the size of PCI BAR 0 (ie. the full video RAM size).
384 //
385 // On stdvga the two concepts coincide with each other; the full memory size
386 // is usable for drawing.
387 //
388 // On QXL however, only a leading segment, "surface 0", can be used for
389 // drawing; the rest of the video memory is used for the QXL guest-host
390 // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of
391 // "surface 0", but since it doesn't (up to and including qemu-2.1), we
392 // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
393 // where it is also available.
394 //
395 if (IsQxl) {
396 UINT32 Signature;
397 UINT32 DrawStart;
398
399 Signature = 0;
400 DrawStart = 0xFFFFFFFF;
401 AvailableFbSize = 0;
402 if (EFI_ERROR (
403 Private->PciIo->Mem.Read (
404 Private->PciIo,
405 EfiPciIoWidthUint32,
406 PCI_BAR_IDX2,
407 0,
408 1,
409 &Signature
410 )
411 ) ||
412 (Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O')) ||
413 EFI_ERROR (
414 Private->PciIo->Mem.Read (
415 Private->PciIo,
416 EfiPciIoWidthUint32,
417 PCI_BAR_IDX2,
418 36,
419 1,
420 &DrawStart
421 )
422 ) ||
423 (DrawStart != 0) ||
424 EFI_ERROR (
425 Private->PciIo->Mem.Read (
426 Private->PciIo,
427 EfiPciIoWidthUint32,
428 PCI_BAR_IDX2,
429 40,
430 1,
431 &AvailableFbSize
432 )
433 ))
434 {
435 DEBUG ((
436 DEBUG_ERROR,
437 "%a: can't read size of drawable buffer from QXL "
438 "ROM\n",
439 __func__
440 ));
441 return EFI_NOT_FOUND;
442 }
443 } else {
444 AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
445 AvailableFbSize *= SIZE_64KB;
446 }
447
448 DEBUG ((
449 DEBUG_INFO,
450 "%a: AvailableFbSize=0x%x\n",
451 __func__,
452 AvailableFbSize
453 ));
454
455 //
456 // Setup Video Modes
457 //
458 Private->ModeData = AllocatePool (
459 sizeof (Private->ModeData[0]) * (QEMU_VIDEO_BOCHS_MODE_COUNT+1)
460 );
461 if (Private->ModeData == NULL) {
462 return EFI_OUT_OF_RESOURCES;
463 }
464
465 QemuVideoBochsEdid (Private, &XRes, &YRes);
466 if (XRes && YRes) {
467 QemuVideoBochsAddMode (
468 Private,
469 AvailableFbSize,
470 XRes,
471 YRes
472 );
473 }
474
475 for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index++) {
476 if ((QemuVideoBochsModes[Index].Width == XRes) &&
477 (QemuVideoBochsModes[Index].Height == YRes))
478 {
479 continue; // duplicate with edid resolution
480 }
481
482 QemuVideoBochsAddMode (
483 Private,
484 AvailableFbSize,
485 QemuVideoBochsModes[Index].Width,
486 QemuVideoBochsModes[Index].Height
487 );
488 }
489
490 return EFI_SUCCESS;
491}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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