@@ -302,6 +302,282 @@ GenFbVmpGetHwInitDataSize(
302302 return SIZE_OF_WXP_VIDEO_HW_INITIALIZATION_DATA ; // Vista?
303303}
304304
305+ /*
306+ * From a (VIDEO|MONITOR)_HARDWARE_CONFIGURATION_DATA structure, retrieve
307+ * where the actual legacy data starts from. Based from the fact that the
308+ * first two fields, InterfaceType and BusNumber, are common with the
309+ * CM_FULL_RESOURCE_DESCRIPTOR header, and the actual data starts where
310+ * the CM_FULL_RESOURCE_DESCRIPTOR::PartialResourceList member would start.
311+ */
312+ #define GET_LEGACY_DATA (fullConfigData ) \
313+ ((PVOID)&(((PCM_FULL_RESOURCE_DESCRIPTOR)fullConfigData)->PartialResourceList))
314+
315+ #define GET_LEGACY_DATA_LEN (fullConfigDataLen ) \
316+ ((fullConfigDataLen >= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList)) \
317+ ? (fullConfigDataLen - FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList)) \
318+ : 0)
319+
320+ typedef struct _DISPLAY_CONTEXT
321+ {
322+ /* Input parameters */
323+ CONFIGURATION_TYPE DeviceType ; // Which device type to search for.
324+
325+ /* Output data */
326+ PHYSICAL_ADDRESS BaseAddress ;
327+ ULONG BufferSize ;
328+ INTERFACE_TYPE Interface ;
329+ ULONG BusNumber ;
330+
331+ /* In input, contain pointers to the structures.
332+ * These are initialized on output. */
333+ PCM_FRAMEBUF_DEVICE_DATA VideoConfigData ;
334+ PCM_MONITOR_DEVICE_DATA MonitorConfigData ;
335+ } DISPLAY_CONTEXT , * PDISPLAY_CONTEXT ;
336+
337+ /**
338+ * @brief
339+ * A PIO_QUERY_DEVICE_ROUTINE callback for IoQueryDeviceDescription()
340+ * to return success when an enumerated display controller has been found.
341+ **/
342+ static NTSTATUS
343+ NTAPI
344+ pEnumDisplayControllerCallback (
345+ _In_ PVOID Context ,
346+ _In_ PUNICODE_STRING PathName ,
347+ _In_ INTERFACE_TYPE BusType ,
348+ _In_ ULONG BusNumber ,
349+ _In_ PKEY_VALUE_FULL_INFORMATION * BusInformation ,
350+ _In_ CONFIGURATION_TYPE ControllerType ,
351+ _In_ ULONG ControllerNumber ,
352+ _In_ PKEY_VALUE_FULL_INFORMATION * ControllerInformation ,
353+ _In_ CONFIGURATION_TYPE PeripheralType ,
354+ _In_ ULONG PeripheralNumber ,
355+ _In_ PKEY_VALUE_FULL_INFORMATION * PeripheralInformation )
356+ {
357+ #define GetDeviceInfoData (info ) \
358+ ((info) ? (PVOID)((ULONG_PTR)(info) + (info)->DataOffset) : NULL)
359+
360+ #define GetDeviceInfoLength (info ) \
361+ ((info) ? (info)->DataLength : 0)
362+
363+ NTSTATUS Status ;
364+ PDISPLAY_CONTEXT DisplayContext = Context ;
365+ PKEY_VALUE_FULL_INFORMATION * DeviceInformation ;
366+ PWCHAR Identifier ;
367+ ULONG IdentifierLength ;
368+ PVOID ConfigurationData ;
369+ ULONG ConfigurationDataLength ;
370+ PCM_COMPONENT_INFORMATION CompInfo ;
371+ ULONG CompInfoLength ;
372+
373+ UNREFERENCED_PARAMETER (PathName );
374+ UNREFERENCED_PARAMETER (BusInformation );
375+ UNREFERENCED_PARAMETER (ControllerType );
376+ UNREFERENCED_PARAMETER (ControllerNumber );
377+ UNREFERENCED_PARAMETER (PeripheralType );
378+ UNREFERENCED_PARAMETER (PeripheralNumber );
379+
380+ /* The display controller has been found */
381+ DPRINT1 ("pEnumDisplayControllerCallback():\n"
382+ " PathName: '%wZ'\n"
383+ " BusType: %lu\n"
384+ " BusNumber: %lu\n"
385+ " CtrlType: %lu\n"
386+ " CtrlNumber: %lu\n"
387+ " PeriType: %lu\n"
388+ " PeriNumber: %lu\n"
389+ "\n" ,
390+ PathName , BusType , BusNumber ,
391+ ControllerType , ControllerNumber ,
392+ PeripheralType , PeripheralNumber );
393+
394+ /* Capture information and return it via Context */
395+
396+ switch (DisplayContext -> DeviceType )
397+ {
398+ case DisplayController :
399+ {
400+ ASSERT (ControllerInformation );
401+
402+ /* Retrieve the pointers */
403+ DeviceInformation = ControllerInformation ;
404+ ConfigurationData =
405+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceConfigurationData ]);
406+ ConfigurationDataLength =
407+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceConfigurationData ]);
408+
409+ CompInfo =
410+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceComponentInformation ]);
411+ CompInfoLength =
412+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceComponentInformation ]);
413+
414+ Identifier =
415+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceIdentifier ]);
416+ IdentifierLength =
417+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceIdentifier ]);
418+
419+ DPRINT1 ("Display: '%.*ws'\n" ,
420+ IdentifierLength /sizeof (WCHAR ), Identifier );
421+
422+ if (CompInfo && (CompInfoLength == sizeof (CM_COMPONENT_INFORMATION )) &&
423+ !(CompInfo -> Flags .Output && CompInfo -> Flags .ConsoleOut ))
424+ {
425+ DPRINT1 ("Weird: this DisplayController has flags %lu\n" , CompInfo -> Flags );
426+
427+ /* Ignore */
428+ return STATUS_SUCCESS ;
429+ }
430+
431+ ASSERT (DisplayContext -> VideoConfigData );
432+
433+ Status = GetFramebufferVideoData (& DisplayContext -> BaseAddress ,
434+ & DisplayContext -> BufferSize ,
435+ DisplayContext -> VideoConfigData ,
436+ GET_LEGACY_DATA (ConfigurationData ),
437+ GET_LEGACY_DATA_LEN (ConfigurationDataLength ));
438+
439+ DisplayContext -> Interface = BusType ;
440+ DisplayContext -> BusNumber = BusNumber ;
441+ break ;
442+ }
443+
444+ case MonitorPeripheral :
445+ {
446+ ASSERT (ControllerInformation );
447+ ASSERT (PeripheralInformation );
448+
449+ /* Retrieve the pointers */
450+ DeviceInformation = PeripheralInformation ;
451+ ConfigurationData =
452+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceConfigurationData ]);
453+ ConfigurationDataLength =
454+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceConfigurationData ]);
455+
456+ CompInfo =
457+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceComponentInformation ]);
458+ CompInfoLength =
459+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceComponentInformation ]);
460+
461+ Identifier =
462+ GetDeviceInfoData (DeviceInformation [IoQueryDeviceIdentifier ]);
463+ IdentifierLength =
464+ GetDeviceInfoLength (DeviceInformation [IoQueryDeviceIdentifier ]);
465+
466+ DPRINT1 ("Monitor: '%.*ws'\n" ,
467+ IdentifierLength /sizeof (WCHAR ), Identifier );
468+
469+ if (CompInfo && (CompInfoLength == sizeof (CM_COMPONENT_INFORMATION )) &&
470+ !(CompInfo -> Flags .Output && CompInfo -> Flags .ConsoleOut ))
471+ {
472+ DPRINT1 ("Weird: this MonitorPeripheral has flags %lu\n" , CompInfo -> Flags );
473+
474+ /* Ignore */
475+ return STATUS_SUCCESS ;
476+ }
477+
478+ ASSERT (DisplayContext -> MonitorConfigData );
479+
480+ Status = GetFramebufferMonitorData (DisplayContext -> MonitorConfigData ,
481+ GET_LEGACY_DATA (ConfigurationData ),
482+ GET_LEGACY_DATA_LEN (ConfigurationDataLength ));
483+ if (!NT_SUCCESS (Status ))
484+ {
485+ DPRINT1 ("Invalid monitor data, ignoring.\n" );
486+ Status = STATUS_SUCCESS ;
487+ }
488+
489+ break ;
490+ }
491+
492+ default :
493+ ASSERT (FALSE); // We should never be called there.
494+ return STATUS_INVALID_PARAMETER ;
495+ }
496+
497+ DPRINT1 ("Returning STATUS_SUCCESS\n" );
498+
499+ return STATUS_SUCCESS ;
500+
501+ #undef GetDeviceInfoLength
502+ #undef GetDeviceInfoData
503+ }
504+
505+ static
506+ NTSTATUS
507+ FindBootDisplayFromCachedConfigTree (
508+ _Out_ PPHYSICAL_ADDRESS BaseAddress , // Start // FrameBuffer
509+ _Out_ PULONG BufferSize , // Length
510+ _Out_ PCM_FRAMEBUF_DEVICE_DATA VideoConfigData ,
511+ _Out_opt_ PCM_MONITOR_DEVICE_DATA MonitorConfigData ,
512+ _Out_ PINTERFACE_TYPE Interface , // FIXME: Make it opt?
513+ _Out_ PULONG BusNumber )
514+ {
515+ NTSTATUS Status ;
516+ INTERFACE_TYPE InterfaceType ;
517+ CONFIGURATION_TYPE ControllerType = DisplayController ;
518+ CONFIGURATION_TYPE PeripheralType = MonitorPeripheral ;
519+ ULONG ControllerNumber = 0 ;
520+
521+ DISPLAY_CONTEXT DisplayContext = {0 };
522+
523+ /* Find the first DisplayController available on any bus in the system */
524+ DisplayContext .DeviceType = ControllerType ;
525+ DisplayContext .VideoConfigData = VideoConfigData ;
526+ for (InterfaceType = 0 ; InterfaceType < MaximumInterfaceType ; ++ InterfaceType )
527+ {
528+ Status = IoQueryDeviceDescription (& InterfaceType ,
529+ NULL ,
530+ & ControllerType ,
531+ & ControllerNumber , // Should we specify that thing?
532+ NULL ,
533+ NULL ,
534+ pEnumDisplayControllerCallback ,
535+ & DisplayContext );
536+ /*
537+ * It seems that Windows Vista at least returns STATUS_OBJECT_NAME_NOT_FOUND regardless of anything,
538+ * but passes through the video parameters anyway.
539+ * Instead of using Status, we check to see if BaseAddress.QuadPart != 0.
540+ */
541+ if (DisplayContext .BaseAddress .QuadPart != 0 )
542+ break ;
543+ }
544+
545+ if (DisplayContext .BaseAddress .QuadPart == 0 ) // || (InterfaceType >= MaximumInterfaceType)
546+ {
547+ DPRINT1 ("Boot console not found. DisplayContext.BaseAddress = %X\n" , DisplayContext .BaseAddress );
548+ return Status ;
549+ }
550+
551+ * BaseAddress = DisplayContext .BaseAddress ;
552+ * BufferSize = DisplayContext .BufferSize ;
553+
554+ * Interface = DisplayContext .Interface ;
555+ * BusNumber = DisplayContext .BusNumber ;
556+
557+ // ASSERT(InterfaceType == DisplayContext.Interface);
558+
559+ /* If no monitor data to retrieve, just return success */
560+ if (!MonitorConfigData )
561+ return STATUS_SUCCESS ;
562+
563+ /* Now find the optional MonitorPeripheral on this controller */
564+ DisplayContext .DeviceType = PeripheralType ;
565+ DisplayContext .MonitorConfigData = MonitorConfigData ;
566+ Status = IoQueryDeviceDescription (& InterfaceType ,
567+ & DisplayContext .BusNumber ,
568+ & ControllerType ,
569+ & ControllerNumber ,
570+ & PeripheralType ,
571+ NULL , // In principle we should retrieve the 1st monitor.
572+ pEnumDisplayControllerCallback ,
573+ & DisplayContext );
574+ if (!NT_SUCCESS (Status ))
575+ {
576+ /* The optional monitor was not found, just ignore */
577+ }
578+
579+ return STATUS_SUCCESS ;
580+ }
305581
306582/*********************************** Public ***********************************/
307583
@@ -398,7 +674,7 @@ GenFbVmpFindAdapter(
398674 * Instead look at specific buses and enumerate the internal ARC
399675 * device tree set up by the bootloader.
400676 */
401- Status = FindBootDisplay (& DisplayInfo -> BaseAddress ,
677+ Status = FindBootDisplayFromCachedConfigTree (& DisplayInfo -> BaseAddress ,
402678 & DisplayInfo -> BufferSize ,
403679 & DisplayInfo -> VideoConfigData ,
404680 & DisplayInfo -> MonitorConfigData ,
0 commit comments