Skip to content

Commit 29919c4

Browse files
committed
Initial OpROM based VGA support
Signed-off-by: Jiaxun Yang <[email protected]>
1 parent abfaa3d commit 29919c4

File tree

3 files changed

+264
-29
lines changed

3 files changed

+264
-29
lines changed

src/csmwrap.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
// Generated by: xxd -i Csm16.bin >> Csm16.h
88
#include "bins/Csm16.h"
99

10-
// Generated by: xxd -i vgabios.bin >> vgabios.h
11-
#include "bins/vgabios.h"
1210

1311
#ifndef BUILD_VERSION
1412
#define BUILD_VERSION "Unknown"
@@ -23,7 +21,6 @@ EFI_BOOT_SERVICES *gBS;
2321

2422
struct csmwrap_priv priv = {
2523
.csm_bin = Csm16_bin,
26-
.vgabios_bin = vgabios_bin
2724
};
2825

2926
static void *find_table(uint32_t signature, uint8_t *csm_bin_base, size_t size)
@@ -150,9 +147,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
150147
copy_rsdt(&priv);
151148

152149
Status = csmwrap_video_init(&priv);
153-
if (Status != EFI_SUCCESS) {
154-
csmwrap_video_fallback(&priv);
155-
}
156150

157151
HiPmm = 0xffffffff;
158152
if (gBS->AllocatePages(AllocateMaxAddress, EfiRuntimeServicesData, HIPMM_SIZE / EFI_PAGE_SIZE, &HiPmm) != EFI_SUCCESS) {
@@ -230,7 +224,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
230224

231225
/* Copy ROM to location, as late as possible */
232226
memcpy((void*)csm_bin_base, Csm16_bin, sizeof(Csm16_bin));
233-
memcpy((void*)VGABIOS_START, vgabios_bin, sizeof(vgabios_bin));
234227

235228
memset(&Regs, 0, sizeof(EFI_IA32_REGISTER_SET));
236229
Regs.X.AX = Legacy16InitializeYourself;

src/csmwrap.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ extern EFI_BOOT_SERVICES *gBS;
1515

1616
struct csmwrap_priv {
1717
uint8_t *csm_bin;
18-
uint8_t *vgabios_bin;
1918

2019
EFI_COMPATIBILITY16_TABLE *csm_efi_table;
2120
uintptr_t csm_bin_base;
@@ -30,8 +29,7 @@ struct csmwrap_priv {
3029
};
3130

3231
extern int unlock_bios_region();
33-
extern int csmwrap_video_init(struct csmwrap_priv *priv);
34-
extern int csmwrap_video_fallback(struct csmwrap_priv *priv);
32+
extern EFI_STATUS csmwrap_video_init(struct csmwrap_priv *priv);
3533
extern int build_coreboot_table(struct csmwrap_priv *priv);
3634
extern int copy_rsdt(struct csmwrap_priv *priv);
3735
int build_e820_map(struct csmwrap_priv *priv);

src/video.c

Lines changed: 263 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#include "csmwrap.h"
33
#include "io.h"
44

5-
EFI_STATUS FindGopPciDevice(struct csmwrap_priv *priv)
5+
// Generated by: xxd -i vgabios.bin >> vgabios.h
6+
#include "bins/vgabios.h"
7+
8+
static EFI_STATUS FindGopPciDevice(struct csmwrap_priv *priv)
69
{
710
EFI_STATUS Status = EFI_SUCCESS;
811
EFI_HANDLE *HandleBuffer;
@@ -125,7 +128,171 @@ EFI_STATUS FindGopPciDevice(struct csmwrap_priv *priv)
125128
return Status;
126129
}
127130

128-
static int csmwrap_pci_vgaarb(struct csmwrap_priv *priv)
131+
static EFI_STATUS
132+
GetPciLegacyRom (
133+
IN UINT16 Csm16Revision,
134+
IN UINT16 VendorId,
135+
IN UINT16 DeviceId,
136+
IN OUT VOID **Rom,
137+
IN OUT UINTN *ImageSize,
138+
OUT UINTN *MaxRuntimeImageLength, OPTIONAL
139+
OUT UINT8 *OpRomRevision, OPTIONAL
140+
OUT VOID **ConfigUtilityCodeHeader OPTIONAL
141+
)
142+
{
143+
BOOLEAN Match;
144+
UINT16 *DeviceIdList;
145+
EFI_PCI_ROM_HEADER RomHeader;
146+
PCI_3_0_DATA_STRUCTURE *Pcir;
147+
VOID *BackupImage;
148+
VOID *BestImage;
149+
150+
151+
if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) {
152+
return EFI_NOT_FOUND;
153+
}
154+
155+
BestImage = NULL;
156+
BackupImage = NULL;
157+
RomHeader.Raw = *Rom;
158+
while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
159+
if (RomHeader.Generic->PcirOffset == 0 ||
160+
(RomHeader.Generic->PcirOffset & 3) !=0 ||
161+
*ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) {
162+
break;
163+
}
164+
165+
Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
166+
//
167+
// Check signature in the PCI Data Structure.
168+
//
169+
if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
170+
break;
171+
}
172+
173+
if (((UINTN)RomHeader.Raw - (UINTN)*Rom) + Pcir->ImageLength * 512 > *ImageSize) {
174+
break;
175+
}
176+
177+
if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
178+
Match = FALSE;
179+
if (Pcir->VendorId == VendorId) {
180+
if (Pcir->DeviceId == DeviceId) {
181+
Match = TRUE;
182+
} else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) {
183+
DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset);
184+
//
185+
// Checking the device list
186+
//
187+
while (*DeviceIdList != 0) {
188+
if (*DeviceIdList == DeviceId) {
189+
Match = TRUE;
190+
break;
191+
}
192+
DeviceIdList ++;
193+
}
194+
}
195+
}
196+
197+
if (Match) {
198+
if (Csm16Revision >= 0x0300) {
199+
//
200+
// Case 1: CSM16 3.0
201+
//
202+
if (Pcir->Revision >= 3) {
203+
//
204+
// case 1.1: meets OpRom 3.0
205+
// Perfect!!!
206+
//
207+
BestImage = RomHeader.Raw;
208+
break;
209+
} else {
210+
//
211+
// case 1.2: meets OpRom 2.x
212+
// Store it and try to find the OpRom 3.0
213+
//
214+
BackupImage = RomHeader.Raw;
215+
}
216+
} else {
217+
//
218+
// Case 2: CSM16 2.x
219+
//
220+
if (Pcir->Revision >= 3) {
221+
//
222+
// case 2.1: meets OpRom 3.0
223+
// Store it and try to find the OpRom 2.x
224+
//
225+
BackupImage = RomHeader.Raw;
226+
} else {
227+
//
228+
// case 2.2: meets OpRom 2.x
229+
// Perfect!!!
230+
//
231+
BestImage = RomHeader.Raw;
232+
break;
233+
}
234+
}
235+
} else {
236+
DEBUG ((DEBUG_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId));
237+
}
238+
}
239+
240+
if ((Pcir->Indicator & 0x80) == 0x80) {
241+
break;
242+
} else {
243+
RomHeader.Raw += 512 * Pcir->ImageLength;
244+
}
245+
}
246+
247+
if (BestImage == NULL) {
248+
if (BackupImage == NULL) {
249+
return EFI_NOT_FOUND;
250+
}
251+
//
252+
// The versions of CSM16 and OpRom don't match exactly
253+
//
254+
BestImage = BackupImage;
255+
}
256+
RomHeader.Raw = BestImage;
257+
Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
258+
*Rom = BestImage;
259+
*ImageSize = Pcir->ImageLength * 512;
260+
261+
if (MaxRuntimeImageLength != NULL) {
262+
if (Pcir->Revision < 3) {
263+
*MaxRuntimeImageLength = 0;
264+
} else {
265+
*MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;
266+
}
267+
}
268+
269+
if (OpRomRevision != NULL) {
270+
//
271+
// Optional return PCI Data Structure revision
272+
//
273+
if (Pcir->Length >= 0x1C) {
274+
*OpRomRevision = Pcir->Revision;
275+
} else {
276+
*OpRomRevision = 0;
277+
}
278+
}
279+
280+
if (ConfigUtilityCodeHeader != NULL) {
281+
//
282+
// Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM
283+
//
284+
if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) {
285+
*ConfigUtilityCodeHeader = NULL;
286+
} else {
287+
*ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset;
288+
}
289+
}
290+
291+
return EFI_SUCCESS;
292+
}
293+
294+
295+
static EFI_STATUS csmwrap_pci_vgaarb(struct csmwrap_priv *priv)
129296
{
130297
EFI_STATUS Status;
131298
EFI_PCI_IO_PROTOCOL *PciIo = priv->vga_pci_io;
@@ -178,26 +345,61 @@ static int csmwrap_pci_vgaarb(struct csmwrap_priv *priv)
178345
return 0;
179346
}
180347

181-
int csmwrap_video_init(struct csmwrap_priv *priv)
348+
EFI_STATUS csmwrap_video_oprom_init(struct csmwrap_priv *priv)
349+
{
350+
EFI_STATUS Status;
351+
PCI_TYPE00 PciConfigHeader;
352+
EFI_PCI_IO_PROTOCOL *PciIo = priv->vga_pci_io;
353+
UINTN LocalRomSize;
354+
VOID *LocalRomImage;
355+
356+
if (!PciIo || !PciIo->RomImage || !PciIo->RomSize) {
357+
DEBUG((DEBUG_ERROR, "No PCI I/O protocol or RomImage function\n"));
358+
return EFI_UNSUPPORTED;
359+
}
360+
361+
LocalRomSize = (UINTN) PciIo->RomSize;
362+
LocalRomImage = PciIo->RomImage;
363+
364+
PciIo->Pci.Read (
365+
PciIo,
366+
EfiPciIoWidthUint32,
367+
0,
368+
sizeof (PciConfigHeader) / sizeof (UINT32),
369+
&PciConfigHeader
370+
);
371+
372+
Status = GetPciLegacyRom (
373+
3, // ???
374+
PciConfigHeader.Hdr.VendorId,
375+
PciConfigHeader.Hdr.DeviceId,
376+
&LocalRomImage,
377+
&LocalRomSize,
378+
NULL /* RuntimeImageLength */,
379+
NULL /* OpromRevision */,
380+
NULL /* &LocalConfigUtilityCodeHeader */
381+
);
382+
383+
if (EFI_ERROR(Status)) {
384+
DEBUG((DEBUG_ERROR, "GetPciLegacyRom failed: %r\n", Status));
385+
return Status;
386+
}
387+
388+
memcpy((void*)VGABIOS_START, LocalRomImage, LocalRomSize);
389+
390+
printf("Video Initialisation Succeed with OpROM\n");
391+
392+
return 0;
393+
}
394+
395+
EFI_STATUS csmwrap_video_seavgabios_init(struct csmwrap_priv *priv)
182396
{
183397
struct cb_framebuffer *cb_fb = &priv->cb_fb;
184398
EFI_STATUS status;
185399
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
186400
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info = NULL;
187401
UINTN isiz = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), currentMode;
188402

189-
status = FindGopPciDevice(priv);
190-
gop = priv->gop;
191-
192-
if (EFI_ERROR(status) && !gop) {
193-
printf("Unable to get GOP service\n");
194-
return -1;
195-
}
196-
197-
if (priv->vga_pci_io) {
198-
status = csmwrap_pci_vgaarb(priv);
199-
}
200-
201403
/* FIXME: What if it's not a VBE mode? */
202404
currentMode = gop->Mode ? gop->Mode->Mode : 0;
203405

@@ -227,12 +429,12 @@ int csmwrap_video_init(struct csmwrap_priv *priv)
227429

228430
if (!cb_fb->physical_address) {
229431
printf("Framebuffer invalid.\n");
230-
return -1;
432+
return EFI_UNSUPPORTED;
231433
}
232434

233435
if (gop->Mode->FrameBufferBase > 0xffffffff) {
234436
printf("Framebuffer is too high, try Disabling Above 4G \n");
235-
return -1;
437+
return EFI_UNSUPPORTED;
236438
}
237439

238440
cb_fb->x_resolution = info->HorizontalResolution;
@@ -277,13 +479,19 @@ int csmwrap_video_init(struct csmwrap_priv *priv)
277479
break;
278480
default:
279481
printf("Unsupported pixel format: %d\n", info->PixelFormat);
280-
return -1;
482+
return EFI_UNSUPPORTED;
281483
}
282484

485+
/* Copy VGA BIOS to location */
486+
memcpy((void*)VGABIOS_START, vgabios_bin, sizeof(vgabios_bin));
487+
488+
printf("Video Initialisation Succeed with SeaVGABIOS GOP\n");
489+
283490
return 0;
491+
284492
}
285493

286-
int csmwrap_video_fallback(struct csmwrap_priv *priv)
494+
EFI_STATUS csmwrap_video_fallback(struct csmwrap_priv *priv)
287495
{
288496
struct cb_framebuffer *cb_fb = &priv->cb_fb;
289497

@@ -301,9 +509,45 @@ int csmwrap_video_fallback(struct csmwrap_priv *priv)
301509
cb_fb->reserved_mask_pos = 24;
302510
cb_fb->reserved_mask_size = 8;
303511

512+
/* Copy VGA BIOS to location */
513+
memcpy((void*)VGABIOS_START, vgabios_bin, sizeof(vgabios_bin));
514+
304515
printf("WARNING: Using fallback Video, you wont't be able to get display!\n");
305516

306517
return 0;
307518
}
308519

520+
EFI_STATUS csmwrap_video_init(struct csmwrap_priv *priv)
521+
{
522+
EFI_STATUS status;
523+
524+
status = FindGopPciDevice(priv);
525+
526+
if (EFI_ERROR(status) && !priv->gop) {
527+
printf("Unable to get GOP service\n");
528+
return -1;
529+
}
530+
531+
if (priv->vga_pci_io) {
532+
/* Some boards will fail on this stage, no worries */
533+
status = csmwrap_pci_vgaarb(priv);
534+
}
535+
536+
status = csmwrap_video_oprom_init(priv);
537+
if (status == EFI_SUCCESS) {
538+
return 0;
539+
}
540+
541+
status = csmwrap_video_seavgabios_init(priv);
542+
if (status == EFI_SUCCESS) {
543+
return 0;
544+
}
545+
546+
status = csmwrap_video_fallback(priv);
547+
if (status == EFI_SUCCESS) {
548+
return 0;
549+
}
550+
551+
return EFI_UNSUPPORTED;
552+
}
309553

0 commit comments

Comments
 (0)