This patch super-seeds my previous attempt ID 91173. This time I used
do_cpuid from ntdll / wbemprox. If cpuid is not available, the default
"Intel Pentium 4" string is used. I modified get_processor_name to
remove leading white-spaces. I also updated the code for Identifier
REG_SZ. This applies to 64bit wine only, as 32bit still reports x86.From b2d44473592cfe2840912b30fb345a513bd58f7d Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <s...@das-labor.org>
Date: Mon, 22 Oct 2012 20:46:58 +0200
Subject: wineboot: detect correct processor name and vendorID, using cpuid
---
programs/wineboot/wineboot.c | 160 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 145 insertions(+), 15 deletions(-)
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 0be773b..ae67516 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -159,6 +159,112 @@ done:
return ret;
}
+/* TODO: move do_cpuid and have_cpuid to a common header */
+static inline void do_cpuid( unsigned int ax, unsigned int *p )
+{
+#ifdef __i386__
+ __asm__("pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "movl %%ebx, %%esi\n\t"
+ "popl %%ebx"
+ : "=a" (p[0]), "=S" (p[1]), "=c" (p[2]), "=d" (p[3])
+ : "0" (ax));
+#endif
+}
+
+/* From xf86info havecpuid.c 1.11 */
+static inline int have_cpuid(void)
+{
+#ifdef __i386__
+ unsigned int f1, f2;
+ __asm__("pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl"
+ : "=&r" (f1), "=&r" (f2)
+ : "ir" (0x00200000));
+ return ((f1^f2) & 0x00200000) != 0;
+#else
+ return 0;
+#endif
+}
+
+/* helper for get_processor_* */
+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 void get_processor_manufacturer( WCHAR *manufacturer )
+{
+#ifdef __i386__
+ unsigned int tmp, regs[4] = {0, 0, 0, 0};
+ static const WCHAR VenidIntelW[] = {'G','e','n','u','i','n','e','I','n','t','e','l',0};
+
+ if (!have_cpuid())
+ {
+ memcpy(manufacturer, VenidIntelW, sizeof(VenidIntelW));
+ return;
+ }
+
+ do_cpuid( 0, regs );
+ tmp = regs[2]; /* swap edx and ecx */
+ regs[2] = regs[3];
+ regs[3] = tmp;
+
+ regs_to_str( regs + 1, 12, manufacturer );
+#else
+ WINE_FIXME("non i386 CPUs aren't supported yet\n");
+#endif
+}
+
+static void get_processor_name( WCHAR *name )
+{
+#ifdef __i386__
+ unsigned int tmp, regs[4] = {0, 0, 0, 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',' ','G','H','z',0};
+ if (!have_cpuid())
+ {
+ memcpy(name, IntelCpuStringW, sizeof(IntelCpuStringW));
+ return;
+ }
+
+ do_cpuid( 0x80000000, regs );
+ if (regs[0] >= 0x80000004)
+ {
+ do_cpuid( 0x80000002, regs );
+ regs_to_str( regs, 16, name );
+ do_cpuid( 0x80000003, regs );
+ regs_to_str( regs, 16, name + 16 );
+ do_cpuid( 0x80000004, regs );
+ regs_to_str( regs, 16, name + 32 );
+
+ /* cut leading whitespace */
+ tmp = 0;
+ while(*(name+tmp) == (WCHAR)' ')
+ tmp++;
+ if(tmp < 48)
+ memmove(name,name+tmp,48-tmp);
+ }
+#else
+ WINE_FIXME("non i386 CPUs aren't supported yet\n");
+#endif
+}
+
/* wrapper for RegSetValueExW */
static DWORD set_reg_value( HKEY hkey, const WCHAR *name, const WCHAR *value )
{
@@ -179,19 +285,22 @@ static void create_hardware_registry_keys(void)
static const WCHAR SysidW[] = {'A','T',' ','c','o','m','p','a','t','i','b','l','e',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',
+ static const WCHAR CommonCpuDescrW[] = {'%','s',' ','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 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};
+ 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 IntelW[] = {'I','n','t','e','l',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];
+ const WCHAR *arch;
NtQuerySystemInformation( SystemCpuInformation, &sci, sizeof(sci), NULL );
@@ -201,9 +310,6 @@ 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*/
- sprintfW( idW, IntelCpuDescrW, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
-
if (RegCreateKeyExW( HKEY_LOCAL_MACHINE, SystemW, 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &system_key, NULL ))
{
@@ -222,21 +328,45 @@ static void create_hardware_registry_keys(void)
for (i = 0; i < NtCurrentTeb()->Peb->NumberOfProcessors; i++)
{
- WCHAR numW[10];
+ /* ProcessorNameStringW has a maximum size of 48 */
+ WCHAR regvalW[48];
- sprintfW( numW, PercentDW, i );
- if (!RegCreateKeyExW( cpu_key, numW, 0, NULL, REG_OPTION_VOLATILE,
+ sprintfW( regvalW, PercentDW, i );
+ if (!RegCreateKeyExW( cpu_key, regvalW, 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
RegSetValueExW( hkey, FeatureSetW, 0, REG_DWORD, (BYTE *)&sci.FeatureSet, sizeof(DWORD) );
+
+ get_processor_name( regvalW );
+ set_reg_value( hkey, ProcessorNameStringW, regvalW );
+
+ get_processor_manufacturer( regvalW );
+ set_reg_value( hkey, VendorIdentifierW, regvalW );
+
+ /* fill the Identifier REG_SZ with correct data */
+ switch(sci.Architecture)
+ {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ if(strstrW(regvalW,IntelW))
+ arch = Intel64W;
+ else
+ arch = AMD64W;
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64: arch = Intel64W; break;
+
+ default:
+ case PROCESSOR_ARCHITECTURE_INTEL: arch = x86W; break;
+ }
+
+ sprintfW( idW, CommonCpuDescrW, arch, sci.Level, HIBYTE(sci.Revision), LOBYTE(sci.Revision) );
+
set_reg_value( hkey, IdentifierW, idW );
- /*TODO; report amd's properly*/
- set_reg_value( hkey, ProcessorNameStringW, IntelCpuStringW );
- set_reg_value( hkey, VendorIdentifierW, VenidIntelW );
+
RegSetValueExW( hkey, mhzKeyW, 0, REG_DWORD, (BYTE *)&power_info[i].MaxMhz, sizeof(DWORD) );
RegCloseKey( hkey );
}
- if (!RegCreateKeyExW( fpu_key, numW, 0, NULL, REG_OPTION_VOLATILE,
+ sprintfW( regvalW, PercentDW, i );
+ if (!RegCreateKeyExW( fpu_key, regvalW, 0, NULL, REG_OPTION_VOLATILE,
KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
set_reg_value( hkey, IdentifierW, idW );
--
1.7.10.4