[PATCH] wineboot: More accurate reporting of AMD and Intel processors.

Hans Leidekker hans at codeweavers.com
Mon Jan 28 08:37:26 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 programs/wineboot/wineboot.c | 190 ++++++++++++++++++++++++++++-------
 1 file changed, 151 insertions(+), 39 deletions(-)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 075b4c8b08..32e4225491 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -163,11 +163,112 @@ static DWORD set_reg_value( HKEY hkey, const WCHAR *name, const WCHAR *value )
     return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, (strlenW(value) + 1) * sizeof(WCHAR) );
 }
 
+extern void do_cpuid( unsigned int ax, unsigned int *p );
+#if defined(_MSC_VER)
+void do_cpuid( unsigned int ax, unsigned int *p )
+{
+    __cpuid( p, ax );
+}
+#elif defined(__i386__)
+__ASM_GLOBAL_FUNC( do_cpuid,
+                   "pushl %esi\n\t"
+                   "pushl %ebx\n\t"
+                   "movl 12(%esp),%eax\n\t"
+                   "movl 16(%esp),%esi\n\t"
+                   "cpuid\n\t"
+                   "movl %eax,(%esi)\n\t"
+                   "movl %ebx,4(%esi)\n\t"
+                   "movl %ecx,8(%esi)\n\t"
+                   "movl %edx,12(%esi)\n\t"
+                   "popl %ebx\n\t"
+                   "popl %esi\n\t"
+                   "ret" )
+#elif defined(__x86_64__)
+__ASM_GLOBAL_FUNC( do_cpuid,
+                   "pushq %rbx\n\t"
+                   "movl %edi,%eax\n\t"
+                   "cpuid\n\t"
+                   "movl %eax,(%rsi)\n\t"
+                   "movl %ebx,4(%rsi)\n\t"
+                   "movl %ecx,8(%rsi)\n\t"
+                   "movl %edx,12(%rsi)\n\t"
+                   "popq %rbx\n\t"
+                   "ret" )
+#else
+void do_cpuid( unsigned int ax, unsigned int *p )
+{
+    FIXME("\n");
+}
+#endif
+
+static void regs_to_str( unsigned int *regs, unsigned int len, WCHAR *buffer )
+{
+    unsigned int i;
+    unsigned char *p = (unsigned char *)regs;
+
+    for (i = 0; i < len; i++) { buffer[i] = *p++; }
+    buffer[i] = 0;
+}
+
+static unsigned int get_model( unsigned int reg0, unsigned int *stepping, unsigned int *family )
+{
+    unsigned int model, family_id = (reg0 & (0x0f << 8)) >> 8;
+
+    model = (reg0 & (0x0f << 4)) >> 4;
+    if (family_id == 6 || family_id == 15) model |= (reg0 & (0x0f << 16)) >> 12;
+
+    *family = family_id;
+    if (family_id == 15) *family += (reg0 & (0xff << 20)) >> 20;
+
+    *stepping = reg0 & 0x0f;
+    return model;
+}
+
+static void get_identifier( WCHAR *buf, const WCHAR *arch )
+{
+    static const WCHAR fmtW[] = {'%','s',' ','F','a','m','i','l','y',' ','%','u',' ','M','o','d','e','l',
+                                 ' ','%','u',' ','S','t','e','p','p','i','n','g',' ','%','u',0};
+    unsigned int regs[4] = {0, 0, 0, 0}, family, model, stepping;
+
+    do_cpuid( 1, regs );
+    model = get_model( regs[0], &stepping, &family );
+    sprintfW( buf, fmtW, arch, family, model, stepping );
+}
+
+static void get_vendorid( WCHAR *buf )
+{
+    unsigned int tmp, regs[4] = {0, 0, 0, 0};
+
+    do_cpuid( 0, regs );
+    tmp = regs[2];      /* swap edx and ecx */
+    regs[2] = regs[3];
+    regs[3] = tmp;
+
+    regs_to_str( regs + 1, 12, buf );
+}
+
+static void get_namestring( WCHAR *buf )
+{
+    unsigned int regs[4] = {0, 0, 0, 0};
+    int i;
+
+    do_cpuid( 0x80000000, regs );
+    if (regs[0] >= 0x80000004)
+    {
+        do_cpuid( 0x80000002, regs );
+        regs_to_str( regs, 16, buf );
+        do_cpuid( 0x80000003, regs );
+        regs_to_str( regs, 16, buf + 16 );
+        do_cpuid( 0x80000004, regs );
+        regs_to_str( regs, 16, buf + 32 );
+    }
+    for (i = strlenW(buf) - 1; i >= 0 && buf[i] == ' '; i--) buf[i] = 0;
+}
+
 /* create the volatile hardware registry keys */
 static void create_hardware_registry_keys(void)
 {
-    static const WCHAR SystemW[] = {'H','a','r','d','w','a','r','e','\\',
-                                    'D','e','s','c','r','i','p','t','i','o','n','\\',
+    static const WCHAR SystemW[] = {'H','a','r','d','w','a','r','e','\\','D','e','s','c','r','i','p','t','i','o','n','\\',
                                     'S','y','s','t','e','m',0};
     static const WCHAR fpuW[] = {'F','l','o','a','t','i','n','g','P','o','i','n','t','P','r','o','c','e','s','s','o','r',0};
     static const WCHAR cpuW[] = {'C','e','n','t','r','a','l','P','r','o','c','e','s','s','o','r',0};
@@ -178,22 +279,22 @@ static void create_hardware_registry_keys(void)
     static const WCHAR ARMSysidW[] = {'A','R','M',' ','p','r','o','c','e','s','s','o','r',' ','f','a','m','i','l','y',0};
     static const WCHAR mhzKeyW[] = {'~','M','H','z',0};
     static const WCHAR VendorIdentifierW[] = {'V','e','n','d','o','r','I','d','e','n','t','i','f','i','e','r',0};
-    static const WCHAR VenidIntelW[] = {'G','e','n','u','i','n','e','I','n','t','e','l',0};
-    /* static const WCHAR VenidAMDW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0}; */
     static const WCHAR PercentDW[] = {'%','d',0};
-    static const WCHAR IntelCpuDescrW[] = {'x','8','6',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d',
-                                           ' ','S','t','e','p','p','i','n','g',' ','%','d',0};
     static const WCHAR ARMCpuDescrW[]  = {'A','R','M',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d',
-                                            ' ','R','e','v','i','s','i','o','n',' ','%','d',0};
-    static const WCHAR IntelCpuStringW[] = {'I','n','t','e','l','(','R',')',' ','P','e','n','t','i','u','m','(','R',')',' ','4',' ',
-                                            'C','P','U',' ','2','.','4','0','G','H','z',0};
+                                          ' ','R','e','v','i','s','i','o','n',' ','%','d',0};
+    static const WCHAR x86W[] = {'x','8','6',0};
+    static const WCHAR intel64W[] = {'I','n','t','e','l','6','4',0};
+    static const WCHAR amd64W[] = {'A','M','D','6','4',0};
+    static const WCHAR authenticamdW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0};
     unsigned int i;
     HKEY hkey, system_key, cpu_key, fpu_key;
     SYSTEM_CPU_INFORMATION sci;
     PROCESSOR_POWER_INFORMATION* power_info;
     ULONG sizeof_power_info = sizeof(PROCESSOR_POWER_INFORMATION) * NtCurrentTeb()->Peb->NumberOfProcessors;
-    WCHAR idW[60];
+    WCHAR id[60], namestr[49], vendorid[13];
 
+    get_namestring( namestr );
+    get_vendorid( vendorid );
     NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL );
 
     power_info = HeapAlloc( GetProcessHeap(), 0, sizeof_power_info );
@@ -202,16 +303,20 @@ static void create_hardware_registry_keys(void)
     if (NtPowerInformation( ProcessorInformation, NULL, 0, power_info, sizeof_power_info ))
         memset( power_info, 0, sizeof_power_info );
 
-    /*TODO: report 64bit processors properly*/
-    switch(sci.Architecture)
+    switch (sci.Architecture)
     {
     case PROCESSOR_ARCHITECTURE_ARM:
     case PROCESSOR_ARCHITECTURE_ARM64:
-        sprintfW( idW, ARMCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
+        sprintfW( id, ARMCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
         break;
-    default:
+
+    case PROCESSOR_ARCHITECTURE_AMD64:
+        get_identifier( id, !strcmpW(vendorid, authenticamdW) ? amd64W : intel64W );
+        break;
+
     case PROCESSOR_ARCHITECTURE_INTEL:
-        sprintfW( idW, IntelCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
+    default:
+        get_identifier( id, x86W );
         break;
     }
 
@@ -222,14 +327,16 @@ static void create_hardware_registry_keys(void)
         return;
     }
 
-    switch(sci.Architecture)
+    switch (sci.Architecture)
     {
     case PROCESSOR_ARCHITECTURE_ARM:
     case PROCESSOR_ARCHITECTURE_ARM64:
         set_reg_value( system_key, IdentifierW, ARMSysidW );
         break;
-    default:
+
     case PROCESSOR_ARCHITECTURE_INTEL:
+    case PROCESSOR_ARCHITECTURE_AMD64:
+    default:
         set_reg_value( system_key, IdentifierW, SysidW );
         break;
     }
@@ -252,10 +359,10 @@ static void create_hardware_registry_keys(void)
                               KEY_ALL_ACCESS, NULL, &hkey, NULL ))
         {
             RegSetValueExW( hkey, FeatureSetW, 0, REG_DWORD, (BYTE *)&sci.FeatureSet, sizeof(DWORD) );
-            set_reg_value( hkey, IdentifierW, idW );
-            /*TODO; report ARM and AMD properly*/
-            set_reg_value( hkey, ProcessorNameStringW, IntelCpuStringW );
-            set_reg_value( hkey, VendorIdentifierW, VenidIntelW );
+            set_reg_value( hkey, IdentifierW, id );
+            /* TODO: report ARM properly */
+            set_reg_value( hkey, ProcessorNameStringW, namestr );
+            set_reg_value( hkey, VendorIdentifierW, vendorid );
             RegSetValueExW( hkey, mhzKeyW, 0, REG_DWORD, (BYTE *)&power_info[i].MaxMhz, sizeof(DWORD) );
             RegCloseKey( hkey );
         }
@@ -264,7 +371,7 @@ static void create_hardware_registry_keys(void)
             !RegCreateKeyExW( fpu_key, numW, 0, NULL, REG_OPTION_VOLATILE,
                               KEY_ALL_ACCESS, NULL, &hkey, NULL ))
         {
-            set_reg_value( hkey, IdentifierW, idW );
+            set_reg_value( hkey, IdentifierW, id );
             RegCloseKey( hkey );
         }
     }
@@ -301,50 +408,56 @@ static void create_environment_registry_keys( void )
     static const WCHAR NumProcW[]  = {'N','U','M','B','E','R','_','O','F','_','P','R','O','C','E','S','S','O','R','S',0};
     static const WCHAR ProcArchW[] = {'P','R','O','C','E','S','S','O','R','_','A','R','C','H','I','T','E','C','T','U','R','E',0};
     static const WCHAR x86W[]      = {'x','8','6',0};
-    static const WCHAR armW[]      = {'A','R','M',0};
-    static const WCHAR arm64W[]    = {'A','R','M','6','4',0};
-    static const WCHAR AMD64W[]    = {'A','M','D','6','4',0};
+    static const WCHAR intel64W[]  = {'I','n','t','e','l','6','4',0};
+    static const WCHAR amd64W[]    = {'A','M','D','6','4',0};
+    static const WCHAR authenticamdW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0};
+    static const WCHAR commaW[]    = {',',' ',0};
     static const WCHAR ProcIdW[]   = {'P','R','O','C','E','S','S','O','R','_','I','D','E','N','T','I','F','I','E','R',0};
     static const WCHAR ProcLvlW[]  = {'P','R','O','C','E','S','S','O','R','_','L','E','V','E','L',0};
     static const WCHAR ProcRevW[]  = {'P','R','O','C','E','S','S','O','R','_','R','E','V','I','S','I','O','N',0};
     static const WCHAR PercentDW[] = {'%','d',0};
     static const WCHAR Percent04XW[] = {'%','0','4','x',0};
-    static const WCHAR IntelCpuDescrW[]  = {'%','s',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d',
-                                            ' ','S','t','e','p','p','i','n','g',' ','%','d',',',' ','G','e','n','u','i','n','e','I','n','t','e','l',0};
     static const WCHAR ARMCpuDescrW[]  = {'A','R','M',' ','F','a','m','i','l','y',' ','%','d',' ','M','o','d','e','l',' ','%','d',
-                                            ' ','R','e','v','i','s','i','o','n',' ','%','d',0};
-
+                                          ' ','R','e','v','i','s','i','o','n',' ','%','d',0};
     HKEY env_key;
     SYSTEM_CPU_INFORMATION sci;
-    WCHAR buffer[60];
+    WCHAR buffer[60], vendorid[13];
     const WCHAR *arch;
 
     if (RegCreateKeyW( HKEY_LOCAL_MACHINE, EnvironW, &env_key )) return;
 
+    get_vendorid( vendorid );
     NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL );
 
     sprintfW( buffer, PercentDW, NtCurrentTeb()->Peb->NumberOfProcessors );
     set_reg_value( env_key, NumProcW, buffer );
 
-    switch(sci.Architecture)
+    switch (sci.Architecture)
     {
-    case PROCESSOR_ARCHITECTURE_AMD64: arch = AMD64W; break;
-    case PROCESSOR_ARCHITECTURE_ARM:   arch = armW; break;
-    case PROCESSOR_ARCHITECTURE_ARM64: arch = arm64W; break;
+    case PROCESSOR_ARCHITECTURE_AMD64:
+        arch = !strcmpW(vendorid, authenticamdW) ? amd64W : intel64W;
+        break;
+
+    case PROCESSOR_ARCHITECTURE_INTEL:
     default:
-    case PROCESSOR_ARCHITECTURE_INTEL: arch = x86W; break;
+        arch = x86W;
+        break;
     }
     set_reg_value( env_key, ProcArchW, arch );
 
-    switch(sci.Architecture)
+    switch (sci.Architecture)
     {
     case PROCESSOR_ARCHITECTURE_ARM:
     case PROCESSOR_ARCHITECTURE_ARM64:
         sprintfW( buffer, ARMCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
         break;
-    default:
+
+    case PROCESSOR_ARCHITECTURE_AMD64:
     case PROCESSOR_ARCHITECTURE_INTEL:
-        sprintfW( buffer, IntelCpuDescrW, arch, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
+    default:
+        get_identifier( buffer, arch );
+        strcatW( buffer, commaW );
+        strcatW( buffer, vendorid );
         break;
     }
     set_reg_value( env_key, ProcIdW, buffer );
@@ -352,7 +465,6 @@ static void create_environment_registry_keys( void )
     sprintfW( buffer, PercentDW, sci.Level );
     set_reg_value( env_key, ProcLvlW, buffer );
 
-    /* Properly report model/stepping */
     sprintfW( buffer, Percent04XW, sci.Revision );
     set_reg_value( env_key, ProcRevW, buffer );
 
-- 
2.20.1




More information about the wine-devel mailing list