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