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