diff --git a/.gitignore b/.gitignore index 189b414f..cc6cfdb1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -/build +/build* /CMakeLists.txt.user +/vs/*/ +*.opensdf +*.sdf diff --git a/README.md b/README.md index acaf178f..5494dc0b 100644 --- a/README.md +++ b/README.md @@ -1,133 +1,25 @@ -# XMRig - -:warning: **You must update miners to version 2.5 before March 28 due [Monero PoW change](https://getmonero.org/2018/02/11/PoW-change-and-key-reuse.html).** - -[![Github All Releases](https://img.shields.io/github/downloads/xmrig/xmrig/total.svg)](https://github.com/xmrig/xmrig/releases) -[![GitHub release](https://img.shields.io/github/release/xmrig/xmrig/all.svg)](https://github.com/xmrig/xmrig/releases) -[![GitHub Release Date](https://img.shields.io/github/release-date-pre/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/releases) -[![GitHub license](https://img.shields.io/github/license/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/blob/master/LICENSE) -[![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/network) +# XMRig (enWILLYado version) +[XMRig](https://github.com/xmrig) is a team that has some high performance Monero (XMR) miners, with official support for Windows. +This fork is originally based on the [CPU-mining](https://github.com/xmrig/xmrig) version with some optimizations/rewrites, interesting features for final users and a little code refactors. XMRig is a high performance Monero (XMR) CPU miner, with official support for Windows. Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 completely rewritten from scratch on C++. +* This software is like the [CPU-mining](https://github.com/xmrig/xmrig) version; but there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia) and [AMD GPU version]( https://github.com/xmrig/xmrig-amd). * This is the **CPU-mining** version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia) and [AMD GPU version]( https://github.com/xmrig/xmrig-amd). -* [Roadmap](https://github.com/xmrig/xmrig/issues/106) for next releases. - +## Own features -#### Table of contents -* [Features](#features) -* [Download](#download) -* [Usage](#usage) -* [Algorithm variations](#algorithm-variations) -* [Build](https://github.com/xmrig/xmrig/wiki/Build) -* [Common Issues](#common-issues) -* [Other information](#other-information) -* [Donations](#donations) -* [Release checksums](#release-checksums) -* [Contacts](#contacts) - -## Features -* High performance. -* Official Windows support. -* Small Windows executable, without dependencies. -* x86/x64 support. -* Support for backup (failover) mining server. -* keepalived support. -* Command line options compatible with cpuminer. -* CryptoNight-Lite support for AEON. -* Smart automatic [CPU configuration](https://github.com/xmrig/xmrig/wiki/Threads). -* Nicehash support -* It's open source software. - -## Download -* Binary releases: https://github.com/xmrig/xmrig/releases -* Git tree: https://github.com/xmrig/xmrig.git - * Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build). - -## Usage -Use [config.xmrig.com](https://config.xmrig.com/xmrig) to generate, edit or share configurations. - -### Options -``` - -a, --algo=ALGO cryptonight (default) or cryptonight-lite - -o, --url=URL URL of mining server - -O, --userpass=U:P username:password pair for mining server - -u, --user=USERNAME username for mining server - -p, --pass=PASSWORD password for mining server - -t, --threads=N number of miner threads - -v, --av=N algorithm variation, 0 auto select - -k, --keepalive send keepalived for prevent timeout (need pool support) - -r, --retries=N number of times to retry before switch to backup server (default: 5) - -R, --retry-pause=N time to pause between retries (default: 5) - --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1 - --cpu-priority set process priority (0 idle, 2 normal to 5 highest) - --no-huge-pages disable huge pages support - --no-color disable colored output - --donate-level=N donate level, default 5% (5 minutes in 100 minutes) - --user-agent set custom user-agent string for pool - -B, --background run the miner in the background - -c, --config=FILE load a JSON-format configuration file - -l, --log-file=FILE log all output to a file - --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75) - --safe safe adjust threads and av settings for current CPU - --nicehash enable nicehash/xmrig-proxy support - --print-time=N print hashrate report every N seconds - --api-port=N port for the miner API - --api-access-token=T access token for API - --api-worker-id=ID custom worker-id for API - -h, --help display this help and exit - -V, --version output version information and exit -``` - -Also you can use configuration via config file, default **config.json**. You can load multiple config files and combine it with command line options. - -## Algorithm variations -Since version 0.8.0. -* `--av=1` For CPUs with hardware AES. -* `--av=2` Lower power mode (double hash) of `1`. -* `--av=3` Software AES implementation. -* `--av=4` Lower power mode (double hash) of `3`. - -## Common Issues -### HUGE PAGES unavailable -* Run XMRig as Administrator. -* Since version 0.8.0 XMRig automatically enables SeLockMemoryPrivilege for current user, but reboot or sign out still required. [Manual instruction](https://msdn.microsoft.com/en-gb/library/ms190730.aspx). - -## Other information -* No HTTP support, only stratum protocol support. -* No TLS support. -* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via command line option `--donate-level`. - - -### CPU mining performance -* **Intel i7-7700** - 307 H/s (4 threads) -* **AMD Ryzen 7 1700X** - 560 H/s (8 threads) - -Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache. - -### Maximum performance checklist -* Idle operating system. -* Do not exceed optimal thread count. -* Use modern CPUs with AES-NI instruction set. -* Try setup optimal cpu affinity. -* Enable fast memory (Large/Huge pages). +* Connect to pool or proxies over HTTP PROXY. +* Include basic encrypted communications. ## Donations -* XMR: `48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD` -* BTC: `1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT` - -## Release checksums -### SHA-256 -``` -232ea929f7219c8de81c7e6fcae7437d40d8128cf55b597a6e1fca0cd77f9f5b xmrig-2.5.0-xenial-amd64.tar.gz/xmrig-2.5.0/xmrig -6149ffed21e740cac12aa61b2fdd17248cbd3e51bab2289d2766aad1d29df910 xmrig-2.5.0-gcc-win32.zip/xmrig.exe -9c89f80e21db906439a7a1b333b8215dbe07d8e42f98a63f6c10c954288a7108 xmrig-2.5.0-gcc-win64.zip/xmrig.exe -b50773c5a74ca9921597a1152e2469ec266cc89eb9765038db7e876f0bcece73 xmrig-2.5.0-msvc-win64.zip/xmrig.exe -``` +* XMR: `433hhduFBtwVXtQiTTTeqyZsB36XaBLJB6bcQfnqqMs5RJitdpi8xBN21hWiEfuPp2hytmf1cshgK5Grgo6QUvLZCP2QSMi` +* BTC: `13MTEjDv8JmS4suaRx6CcWNthR1vwPr7Ce` +* DOGE: `DHif8RTy8E6K4b71u3fXXSk7AEyiuN2sUi` ## Contacts -* support@xmrig.com -* [reddit](https://www.reddit.com/user/XMRig/) +* xmrig@enwillyado.com +* [telegram](https://telegram.me/enWILLYado) + +¡Se habla español! diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 488f1236..69706436 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -8,11 +8,11 @@ endif() if (CMAKE_CXX_COMPILER_ID MATCHES GNU) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -DFOUR_WAY -fomit-frame-pointer -Wno-strict-aliasing -msse -msse2 -msse3 -mmmx -m3dnow") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -ffast-math -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fpermissive -DFOUR_WAY -fomit-frame-pointer -Wno-strict-aliasing -msse -msse2 -msse3 -mmmx -m3dnow") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -ffast-math -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") if (XMRIG_ARMv8) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+crypto") @@ -21,20 +21,20 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -flax-vector-conversions") else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -maes") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -maes") endif() if (WIN32) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -flto") else() - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -flto") endif() add_definitions(/D_GNU_SOURCE) if (${CMAKE_VERSION} VERSION_LESS "3.1.0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") endif() #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2") diff --git a/src/3rdparty/align.h b/src/3rdparty/align.h new file mode 100644 index 00000000..b61179b9 --- /dev/null +++ b/src/3rdparty/align.h @@ -0,0 +1,33 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ALIGN_H__ +#define __ALIGN_H__ + +#ifdef _MSC_VER +# define VAR_ALIGN(x, decl) __declspec(align(x)) decl +#else +# define VAR_ALIGN(x, decl) decl __attribute__ ((aligned(x))) +#endif + +#endif /* __ALIGN_H__ */ diff --git a/src/3rdparty/libcpuid/cpuid_main.c b/src/3rdparty/libcpuid/cpuid_main.c index 9027b6f6..1005cef7 100644 --- a/src/3rdparty/libcpuid/cpuid_main.c +++ b/src/3rdparty/libcpuid/cpuid_main.c @@ -36,6 +36,10 @@ #include #include +#ifndef VERSION +#define VERSION "7.10" +#endif + /* Implementation: */ static int _libcpiud_errno = ERR_OK; @@ -46,6 +50,11 @@ int set_error(cpu_error_t err) return (int) err; } +static void raw_data_t_constructor(struct cpu_raw_data_t* raw) +{ + memset(raw, 0, sizeof(struct cpu_raw_data_t)); +} + static void cpu_id_t_constructor(struct cpu_id_t* id) { memset(id, 0, sizeof(struct cpu_id_t)); @@ -55,6 +64,37 @@ static void cpu_id_t_constructor(struct cpu_id_t* id) id->sse_size = -1; } +static int parse_token(const char* expected_token, const char* token, + const char* value, uint32_t array[][4], int limit, int* recognized) +{ + char format[32]; + int veax, vebx, vecx, vedx; + int index; + + if(*recognized) + { + return 1; /* already recognized */ + } + if(strncmp(token, expected_token, strlen(expected_token))) + { + return 1; /* not what we search for */ + } + sprintf(format, "%s[%%d]", expected_token); + *recognized = 1; + if(1 == sscanf(token, format, &index) && index >= 0 && index < limit) + { + if(4 == sscanf(value, "%x%x%x%x", &veax, &vebx, &vecx, &vedx)) + { + array[index][0] = veax; + array[index][1] = vebx; + array[index][2] = vecx; + array[index][3] = vedx; + return 1; + } + } + return 0; +} + /* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */ #ifdef __APPLE__ #include @@ -328,6 +368,31 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat return set_error(ERR_OK); } +static void make_list_from_string(const char* csv, struct cpu_list_t* list) +{ + int i, n, l, last; + l = (int) strlen(csv); + n = 0; + for(i = 0; i < l; i++) if(csv[i] == ',') + { + n++; + } + n++; + list->num_entries = n; + list->names = (char**) malloc(sizeof(char*) * n); + last = -1; + n = 0; + for(i = 0; i <= l; i++) if(i == l || csv[i] == ',') + { + list->names[n] = (char*) malloc(i - last); + memcpy(list->names[n], &csv[last + 1], i - last - 1); + list->names[n][i - last - 1] = '\0'; + n++; + last = i; + } +} + + /* Interface: */ int cpuid_get_total_cpus(void) @@ -398,6 +463,140 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data) return set_error(ERR_OK); } +int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename) +{ + int i; + FILE* f; + + if(!strcmp(filename, "")) + { + f = stdout; + } + else + { + f = fopen(filename, "wt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + + fprintf(f, "version=%s\n", VERSION); + for(i = 0; i < MAX_CPUID_LEVEL; i++) + fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i, + data->basic_cpuid[i][0], data->basic_cpuid[i][1], + data->basic_cpuid[i][2], data->basic_cpuid[i][3]); + for(i = 0; i < MAX_EXT_CPUID_LEVEL; i++) + fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i, + data->ext_cpuid[i][0], data->ext_cpuid[i][1], + data->ext_cpuid[i][2], data->ext_cpuid[i][3]); + for(i = 0; i < MAX_INTELFN4_LEVEL; i++) + fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn4[i][0], data->intel_fn4[i][1], + data->intel_fn4[i][2], data->intel_fn4[i][3]); + for(i = 0; i < MAX_INTELFN11_LEVEL; i++) + fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn11[i][0], data->intel_fn11[i][1], + data->intel_fn11[i][2], data->intel_fn11[i][3]); + for(i = 0; i < MAX_INTELFN12H_LEVEL; i++) + fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn12h[i][0], data->intel_fn12h[i][1], + data->intel_fn12h[i][2], data->intel_fn12h[i][3]); + for(i = 0; i < MAX_INTELFN14H_LEVEL; i++) + fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn14h[i][0], data->intel_fn14h[i][1], + data->intel_fn14h[i][2], data->intel_fn14h[i][3]); + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + +int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename) +{ + int i, len; + char line[100]; + char token[100]; + char* value; + int syntax; + int cur_line = 0; + int recognized; + FILE* f; + + raw_data_t_constructor(data); + + if(!strcmp(filename, "")) + { + f = stdin; + } + else + { + f = fopen(filename, "rt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + while(fgets(line, sizeof(line), f)) + { + ++cur_line; + len = (int) strlen(line); + if(len < 2) + { + continue; + } + if(line[len - 1] == '\n') + { + line[--len] = '\0'; + } + for(i = 0; i < len && line[i] != '='; i++) + if(i >= len && i < 1 && len - i - 1 <= 0) + { + fclose(f); + return set_error(ERR_BADFMT); + } + strncpy(token, line, i); + token[i] = '\0'; + value = &line[i + 1]; + /* try to recognize the line */ + recognized = 0; + if(!strcmp(token, "version") || !strcmp(token, "build_date")) + { + recognized = 1; + } + syntax = 1; + syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &recognized); + syntax = syntax && + parse_token("ext_cpuid", token, value, data->ext_cpuid, MAX_EXT_CPUID_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn4", token, value, data->intel_fn4, MAX_INTELFN4_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn12h", token, value, data->intel_fn12h, MAX_INTELFN12H_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn14h", token, value, data->intel_fn14h, MAX_INTELFN14H_LEVEL, &recognized); + if(!syntax) + { + warnf("Error: %s:%d: Syntax error\n", filename, cur_line); + fclose(f); + return set_error(ERR_BADFMT); + } + if(!recognized) + { + warnf("Warning: %s:%d not understood!\n", filename, cur_line); + } + } + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal) { int r; @@ -435,7 +634,264 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) return cpu_ident_internal(raw, data, &throwaway); } +const char* cpu_feature_str(cpu_feature_t feature) +{ + const struct + { + cpu_feature_t feature; + const char* name; + } + matchtable[] = + { + { CPU_FEATURE_FPU, "fpu" }, + { CPU_FEATURE_VME, "vme" }, + { CPU_FEATURE_DE, "de" }, + { CPU_FEATURE_PSE, "pse" }, + { CPU_FEATURE_TSC, "tsc" }, + { CPU_FEATURE_MSR, "msr" }, + { CPU_FEATURE_PAE, "pae" }, + { CPU_FEATURE_MCE, "mce" }, + { CPU_FEATURE_CX8, "cx8" }, + { CPU_FEATURE_APIC, "apic" }, + { CPU_FEATURE_MTRR, "mtrr" }, + { CPU_FEATURE_SEP, "sep" }, + { CPU_FEATURE_PGE, "pge" }, + { CPU_FEATURE_MCA, "mca" }, + { CPU_FEATURE_CMOV, "cmov" }, + { CPU_FEATURE_PAT, "pat" }, + { CPU_FEATURE_PSE36, "pse36" }, + { CPU_FEATURE_PN, "pn" }, + { CPU_FEATURE_CLFLUSH, "clflush" }, + { CPU_FEATURE_DTS, "dts" }, + { CPU_FEATURE_ACPI, "acpi" }, + { CPU_FEATURE_MMX, "mmx" }, + { CPU_FEATURE_FXSR, "fxsr" }, + { CPU_FEATURE_SSE, "sse" }, + { CPU_FEATURE_SSE2, "sse2" }, + { CPU_FEATURE_SS, "ss" }, + { CPU_FEATURE_HT, "ht" }, + { CPU_FEATURE_TM, "tm" }, + { CPU_FEATURE_IA64, "ia64" }, + { CPU_FEATURE_PBE, "pbe" }, + { CPU_FEATURE_PNI, "pni" }, + { CPU_FEATURE_PCLMUL, "pclmul" }, + { CPU_FEATURE_DTS64, "dts64" }, + { CPU_FEATURE_MONITOR, "monitor" }, + { CPU_FEATURE_DS_CPL, "ds_cpl" }, + { CPU_FEATURE_VMX, "vmx" }, + { CPU_FEATURE_SMX, "smx" }, + { CPU_FEATURE_EST, "est" }, + { CPU_FEATURE_TM2, "tm2" }, + { CPU_FEATURE_SSSE3, "ssse3" }, + { CPU_FEATURE_CID, "cid" }, + { CPU_FEATURE_CX16, "cx16" }, + { CPU_FEATURE_XTPR, "xtpr" }, + { CPU_FEATURE_PDCM, "pdcm" }, + { CPU_FEATURE_DCA, "dca" }, + { CPU_FEATURE_SSE4_1, "sse4_1" }, + { CPU_FEATURE_SSE4_2, "sse4_2" }, + { CPU_FEATURE_SYSCALL, "syscall" }, + { CPU_FEATURE_XD, "xd" }, + { CPU_FEATURE_X2APIC, "x2apic"}, + { CPU_FEATURE_MOVBE, "movbe" }, + { CPU_FEATURE_POPCNT, "popcnt" }, + { CPU_FEATURE_AES, "aes" }, + { CPU_FEATURE_XSAVE, "xsave" }, + { CPU_FEATURE_OSXSAVE, "osxsave" }, + { CPU_FEATURE_AVX, "avx" }, + { CPU_FEATURE_MMXEXT, "mmxext" }, + { CPU_FEATURE_3DNOW, "3dnow" }, + { CPU_FEATURE_3DNOWEXT, "3dnowext" }, + { CPU_FEATURE_NX, "nx" }, + { CPU_FEATURE_FXSR_OPT, "fxsr_opt" }, + { CPU_FEATURE_RDTSCP, "rdtscp" }, + { CPU_FEATURE_LM, "lm" }, + { CPU_FEATURE_LAHF_LM, "lahf_lm" }, + { CPU_FEATURE_CMP_LEGACY, "cmp_legacy" }, + { CPU_FEATURE_SVM, "svm" }, + { CPU_FEATURE_SSE4A, "sse4a" }, + { CPU_FEATURE_MISALIGNSSE, "misalignsse" }, + { CPU_FEATURE_ABM, "abm" }, + { CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" }, + { CPU_FEATURE_OSVW, "osvw" }, + { CPU_FEATURE_IBS, "ibs" }, + { CPU_FEATURE_SSE5, "sse5" }, + { CPU_FEATURE_SKINIT, "skinit" }, + { CPU_FEATURE_WDT, "wdt" }, + { CPU_FEATURE_TS, "ts" }, + { CPU_FEATURE_FID, "fid" }, + { CPU_FEATURE_VID, "vid" }, + { CPU_FEATURE_TTP, "ttp" }, + { CPU_FEATURE_TM_AMD, "tm_amd" }, + { CPU_FEATURE_STC, "stc" }, + { CPU_FEATURE_100MHZSTEPS, "100mhzsteps" }, + { CPU_FEATURE_HWPSTATE, "hwpstate" }, + { CPU_FEATURE_CONSTANT_TSC, "constant_tsc" }, + { CPU_FEATURE_XOP, "xop" }, + { CPU_FEATURE_FMA3, "fma3" }, + { CPU_FEATURE_FMA4, "fma4" }, + { CPU_FEATURE_TBM, "tbm" }, + { CPU_FEATURE_F16C, "f16c" }, + { CPU_FEATURE_RDRAND, "rdrand" }, + { CPU_FEATURE_CPB, "cpb" }, + { CPU_FEATURE_APERFMPERF, "aperfmperf" }, + { CPU_FEATURE_PFI, "pfi" }, + { CPU_FEATURE_PA, "pa" }, + { CPU_FEATURE_AVX2, "avx2" }, + { CPU_FEATURE_BMI1, "bmi1" }, + { CPU_FEATURE_BMI2, "bmi2" }, + { CPU_FEATURE_HLE, "hle" }, + { CPU_FEATURE_RTM, "rtm" }, + { CPU_FEATURE_AVX512F, "avx512f" }, + { CPU_FEATURE_AVX512DQ, "avx512dq" }, + { CPU_FEATURE_AVX512PF, "avx512pf" }, + { CPU_FEATURE_AVX512ER, "avx512er" }, + { CPU_FEATURE_AVX512CD, "avx512cd" }, + { CPU_FEATURE_SHA_NI, "sha_ni" }, + { CPU_FEATURE_AVX512BW, "avx512bw" }, + { CPU_FEATURE_AVX512VL, "avx512vl" }, + { CPU_FEATURE_SGX, "sgx" }, + { CPU_FEATURE_RDSEED, "rdseed" }, + { CPU_FEATURE_ADX, "adx" }, + }; + unsigned i, n = COUNT_OF(matchtable); + if(n != NUM_CPU_FEATURES) + { + warnf("Warning: incomplete library, feature matchtable size differs from the actual number of features.\n"); + } + for(i = 0; i < n; i++) + if(matchtable[i].feature == feature) + { + return matchtable[i].name; + } + return ""; +} + +const char* cpuid_error(void) +{ + const struct + { + cpu_error_t error; + const char* description; + } + matchtable[] = + { + { ERR_OK , "No error"}, + { ERR_NO_CPUID , "CPUID instruction is not supported"}, + { ERR_NO_RDTSC , "RDTSC instruction is not supported"}, + { ERR_NO_MEM , "Memory allocation failed"}, + { ERR_OPEN , "File open operation failed"}, + { ERR_BADFMT , "Bad file format"}, + { ERR_NOT_IMP , "Not implemented"}, + { ERR_CPU_UNKN , "Unsupported processor"}, + { ERR_NO_RDMSR , "RDMSR instruction is not supported"}, + { ERR_NO_DRIVER, "RDMSR driver error (generic)"}, + { ERR_NO_PERMS , "No permissions to install RDMSR driver"}, + { ERR_EXTRACT , "Cannot extract RDMSR driver (read only media?)"}, + { ERR_HANDLE , "Bad handle"}, + { ERR_INVMSR , "Invalid MSR"}, + { ERR_INVCNB , "Invalid core number"}, + { ERR_HANDLE_R , "Error on handle read"}, + { ERR_INVRANGE , "Invalid given range"}, + }; + unsigned i; + for(i = 0; i < COUNT_OF(matchtable); i++) + if(_libcpiud_errno == matchtable[i].error) + { + return matchtable[i].description; + } + return "Unknown error"; +} + + const char* cpuid_lib_version(void) { return VERSION; } + +libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn) +{ + libcpuid_warn_fn_t ret = _warn_fun; + _warn_fun = new_fn; + return ret; +} + +void cpuid_set_verbosiness_level(int level) +{ + _current_verboselevel = level; +} + +cpu_vendor_t cpuid_get_vendor(void) +{ + static cpu_vendor_t vendor = VENDOR_UNKNOWN; + uint32_t raw_vendor[4]; + char vendor_str[VENDOR_STR_MAX]; + + if(vendor == VENDOR_UNKNOWN) + { + if(!cpuid_present()) + { + set_error(ERR_NO_CPUID); + } + else + { + cpu_exec_cpuid(0, raw_vendor); + vendor = cpuid_vendor_identify(raw_vendor, vendor_str); + } + } + return vendor; +} + +void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list) +{ + switch(vendor) + { + case VENDOR_INTEL: + cpuid_get_list_intel(list); + break; + case VENDOR_AMD: + cpuid_get_list_amd(list); + break; + case VENDOR_CYRIX: + make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list); + break; + case VENDOR_NEXGEN: + make_list_from_string("Nx586", list); + break; + case VENDOR_TRANSMETA: + make_list_from_string("Crusoe,Efficeon", list); + break; + case VENDOR_UMC: + make_list_from_string("UMC x86 CPU", list); + break; + case VENDOR_CENTAUR: + make_list_from_string("VIA C3,VIA C7,VIA Nano", list); + break; + case VENDOR_RISE: + make_list_from_string("Rise mP6", list); + break; + case VENDOR_SIS: + make_list_from_string("SiS mP6", list); + break; + case VENDOR_NSC: + make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list); + break; + default: + warnf("Unknown vendor passed to cpuid_get_cpu_list()\n"); + break; + } +} + +void cpuid_free_cpu_list(struct cpu_list_t* list) +{ + int i; + if(list->num_entries <= 0) + { + return; + } + for(i = 0; i < list->num_entries; i++) + { + free(list->names[i]); + } + free(list->names); +} diff --git a/src/3rdparty/libcpuid/libcpuid.h b/src/3rdparty/libcpuid/libcpuid.h index 00c39322..88ec5721 100644 --- a/src/3rdparty/libcpuid/libcpuid.h +++ b/src/3rdparty/libcpuid/libcpuid.h @@ -85,7 +85,11 @@ @{ */ /* Include some integer type specifications: */ +#ifdef _WIN32 #include "libcpuid_types.h" +#else +# include +#endif /* Some limits and other constants */ #include "libcpuid_constants.h" @@ -619,6 +623,39 @@ void cpu_exec_cpuid_ext(uint32_t* regs); */ int cpuid_get_raw_data(struct cpu_raw_data_t* data); +/** + * @brief Writes the raw CPUID data to a text file + * @param data - a pointer to cpu_raw_data_t structure + * @param filename - the path of the file, where the serialized data should be + * written. If empty, stdout will be used. + * @note This is intended primarily for debugging. On some processor, which is + * not currently supported or not completely recognized by cpu_identify, + * one can still successfully get the raw data and write it to a file. + * libcpuid developers can later import this file and debug the detection + * code as if running on the actual hardware. + * The file is simple text format of "something=value" pairs. Version info + * is also written, but the format is not intended to be neither backward- + * nor forward compatible. + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename); + +/** + * @brief Reads raw CPUID data from file + * @param data - a pointer to cpu_raw_data_t structure. The deserialized data will + * be written here. + * @param filename - the path of the file, containing the serialized raw data. + * If empty, stdin will be used. + * @note This function may fail, if the file is created by different version of + * the library. Also, see the notes on cpuid_serialize_raw_data. + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t +*/ +int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename); + /** * @brief Identifies the CPU * @param raw - Input - a pointer to the raw CPUID data, which is obtained @@ -644,6 +681,222 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data); */ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data); +/** + * @brief Returns the short textual representation of a CPU flag + * @param feature - the feature, whose textual representation is wanted. + * @returns a constant string like "fpu", "tsc", "sse2", etc. + * @note the names of the returned flags are compatible with those from + * /proc/cpuinfo in Linux, with the exception of `tm_amd' + */ +const char* cpu_feature_str(cpu_feature_t feature); + +/** + * @brief Returns textual description of the last error + * + * libcpuid stores an `errno'-style error status, whose description + * can be obtained with this function. + * @note This function is not thread-safe + * @see cpu_error_t + */ +const char* cpuid_error(void); + +/** + * @brief Executes RDTSC + * + * The RDTSC (ReaD Time Stamp Counter) instruction gives access to an + * internal 64-bit counter, which usually increments at each clock cycle. + * This can be used for various timing routines, and as a very precise + * clock source. It is set to zero on system startup. Beware that may not + * increment at the same frequency as the CPU. Consecutive calls of RDTSC + * are, however, guaranteed to return monotonically-increasing values. + * + * @param result - a pointer to a 64-bit unsigned integer, where the TSC value + * will be stored + * + * @note If 100% compatibility is a concern, you must first check if the + * RDTSC instruction is present (if it is not, your program will crash + * with "invalid opcode" exception). Only some very old processors (i486, + * early AMD K5 and some Cyrix CPUs) lack that instruction - they should + * have become exceedingly rare these days. To verify RDTSC presence, + * run cpu_identify() and check flags[CPU_FEATURE_TSC]. + * + * @note The monotonically increasing nature of the TSC may be violated + * on SMP systems, if their TSC clocks run at different rate. If the OS + * doesn't account for that, the TSC drift may become arbitrary large. + */ +void cpu_rdtsc(uint64_t* result); + +/** + * @brief Store TSC and timing info + * + * This function stores the current TSC value and current + * time info from a precise OS-specific clock source in the cpu_mark_t + * structure. The sys_clock field contains time with microsecond resolution. + * The values can later be used to measure time intervals, number of clocks, + * FPU frequency, etc. + * @see cpu_rdtsc + * + * @param mark [out] - a pointer to a cpu_mark_t structure + */ +void cpu_tsc_mark(struct cpu_mark_t* mark); + +/** + * @brief Calculate TSC and timing difference + * + * @param mark - input/output: a pointer to a cpu_mark_t sturcture, which has + * already been initialized by cpu_tsc_mark. The difference in + * TSC and time will be written here. + * + * This function calculates the TSC and time difference, by obtaining the + * current TSC and timing values and subtracting the contents of the `mark' + * structure from them. Results are written in the same structure. + * + * Example: + * @code + * ... + * struct cpu_mark_t mark; + * cpu_tsc_mark(&mark); + * foo(); + * cpu_tsc_unmark(&mark); + * printf("Foo finished. Executed in %llu cycles and %llu usecs\n", + * mark.tsc, mark.sys_clock); + * ... + * @endcode + */ +void cpu_tsc_unmark(struct cpu_mark_t* mark); + +/** + * @brief Calculates the CPU clock + * + * @param mark - pointer to a cpu_mark_t structure, which has been initialized + * with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark. + * + * @note For reliable results, the marked time interval should be at least about + * 10 ms. + * + * @returns the CPU clock frequency, in MHz. Due to measurement error, it will + * differ from the true value in a few least-significant bits. Accuracy depends + * on the timing interval - the more, the better. If the timing interval is + * insufficient, the result is -1. Also, see the comment on cpu_clock_measure + * for additional issues and pitfalls in using RDTSC for CPU frequency + * measurements. + */ +int cpu_clock_by_mark(struct cpu_mark_t* mark); + +/** + * @brief Returns the CPU clock, as reported by the OS + * + * This function uses OS-specific functions to obtain the CPU clock. It may + * differ from the true clock for several reasons:

+ * + * i) The CPU might be in some power saving state, while the OS reports its + * full-power frequency, or vice-versa.
+ * ii) In some cases you can raise or lower the CPU frequency with overclocking + * utilities and the OS will not notice. + * + * @returns the CPU clock frequency in MHz. If the OS is not (yet) supported + * or lacks the necessary reporting machinery, the return value is -1 + */ +int cpu_clock_by_os(void); + +/** + * @brief Measure the CPU clock frequency + * + * @param millis - How much time to waste in the busy-wait cycle. In millisecs. + * Useful values 10 - 1000 + * @param quad_check - Do a more thorough measurement if nonzero + * (see the explanation). + * + * The function performs a busy-wait cycle for the given time and calculates + * the CPU frequency by the difference of the TSC values. The accuracy of the + * calculation depends on the length of the busy-wait cycle: more is better, + * but 100ms should be enough for most purposes. + * + * While this will calculate the CPU frequency correctly in most cases, there are + * several reasons why it might be incorrect:
+ * + * i) RDTSC doesn't guarantee it will run at the same clock as the CPU. + * Apparently there aren't CPUs at the moment, but still, there's no + * guarantee.
+ * ii) The CPU might be in a low-frequency power saving mode, and the CPU + * might be switched to higher frequency at any time. If this happens + * during the measurement, the result can be anywhere between the + * low and high frequencies. Also, if you're interested in the + * high frequency value only, this function might return the low one + * instead.
+ * iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc) + * + * the quad_check option will run four consecutive measurements and + * then return the average of the two most-consistent results. The total + * runtime of the function will still be `millis' - consider using + * a bit more time for the timing interval. + * + * Finally, for benchmarking / CPU intensive applications, the best strategy is + * to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method. + * Begin by mark()-ing about one second after application startup (allowing the + * power-saving manager to kick in and rise the frequency during that time), + * then unmark() just before application finishing. The result will most + * acurately represent at what frequency your app was running. + * + * @returns the CPU clock frequency in MHz (within some measurement error + * margin). If RDTSC is not supported, the result is -1. + */ +int cpu_clock_measure(int millis, int quad_check); + +/** + * @brief Measure the CPU clock frequency using instruction-counting + * + * @param millis - how much time to allocate for each run, in milliseconds + * @param runs - how many runs to perform + * + * The function performs a busy-wait cycle using a known number of "heavy" (SSE) + * instructions. These instructions run at (more or less guaranteed) 1 IPC rate, + * so by running a busy loop for a fixed amount of time, and measuring the + * amount of instructions done, the CPU clock is accurately measured. + * + * Of course, this function is still affected by the power-saving schemes, so + * the warnings as of cpu_clock_measure() still apply. However, this function is + * immune to problems with detection, related to the Intel Nehalem's "Turbo" + * mode, where the internal clock is raised, but the RDTSC rate is unaffected. + * + * The function will run for about (millis * runs) milliseconds. + * You can make only a single busy-wait run (runs == 1); however, this can + * be affected by task scheduling (which will break the counting), so allowing + * more than one run is recommended. As run length is not imperative for + * accurate readings (e.g., 50ms is sufficient), you can afford a lot of short + * runs, e.g. 10 runs of 50ms or 20 runs of 25ms. + * + * Recommended values - millis = 50, runs = 4. For more robustness, + * increase the number of runs. + * + * NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus + * the results are skewed. This is corrected internally by dividing the resulting + * value by 1.4. + * However, this only occurs if the thread is executed on a single CMT + * module - if there are other threads competing for resources, the results are + * unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from + * competing threads, or if there are such threads, they shouldn't exceed the + * number of modules. On a Bulldozer X8, that means 4 threads. + * + * @returns the CPU clock frequency in MHz (within some measurement error + * margin). If SSE is not supported, the result is -1. If the input parameters + * are incorrect, or some other internal fault is detected, the result is -2. + */ +int cpu_clock_by_ic(int millis, int runs); + +/** + * @brief Get the CPU clock frequency (all-in-one method) + * + * This is an all-in-one method for getting the CPU clock frequency. + * It tries to use the OS for that. If the OS doesn't have this info, it + * uses cpu_clock_measure with 200ms time interval and quadruple checking. + * + * @returns the CPU clock frequency in MHz. If every possible method fails, + * the result is -1. + */ +int cpu_clock(void); + + /** * @brief The return value of cpuid_get_epc(). * @details @@ -677,6 +930,232 @@ struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw); */ const char* cpuid_lib_version(void); +typedef void (*libcpuid_warn_fn_t)(const char* msg); +/** + * @brief Sets the warning print function + * + * In some cases, the internal libcpuid machinery would like to emit useful + * debug warnings. By default, these warnings are written to stderr. However, + * you can set a custom function that will receive those warnings. + * + * @param warn_fun - the warning function you want to set. If NULL, warnings + * are disabled. The function takes const char* argument. + * + * @returns the current warning function. You can use the return value to + * keep the previous warning function and restore it at your discretion. + */ +libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun); + +/** + * @brief Sets the verbosiness level + * + * When the verbosiness level is above zero, some functions might print + * diagnostic information about what are they doing. The higher the level is, + * the more detail is printed. Level zero is guaranteed to omit all such + * output. The output is written using the same machinery as the warnings, + * @see cpuid_set_warn_function() + * + * @param level the desired verbosiness level. Useful values 0..2 inclusive + */ +void cpuid_set_verbosiness_level(int level); + + +/** + * @brief Obtains the CPU vendor from CPUID from the current CPU + * @note The result is cached. + * @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type. + * @see cpu_vendor_t + */ +cpu_vendor_t cpuid_get_vendor(void); + +/** + * @brief a structure that holds a list of processor names + */ +struct cpu_list_t +{ + /** Number of entries in the list */ + int num_entries; + /** Pointers to names. There will be num_entries of them */ + char** names; +}; + +/** + * @brief Gets a list of all known CPU names from a specific vendor. + * + * This function compiles a list of all known CPU (code)names + * (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor. + * + * There are about 100 entries for Intel and AMD, and a few for the other + * vendors. The list is written out in approximate chronological introduction + * order of the parts. + * + * @param vendor the vendor to be queried + * @param list [out] the resulting list will be written here. + * NOTE: As the memory is dynamically allocated, be sure to call + * cpuid_free_cpu_list() after you're done with the data + * @see cpu_list_t + */ +void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list); + +/** + * @brief Frees a CPU list + * + * This function deletes all the memory associated with a CPU list, as obtained + * by cpuid_get_cpu_list() + * + * @param list - the list to be free()'d. + */ +void cpuid_free_cpu_list(struct cpu_list_t* list); + +struct msr_driver_t; +/** + * @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers) + * + * On systems that support it, this function will create a temporary + * system driver, that has privileges to execute the RDMSR instruction. + * After the driver is created, you can read MSRs by calling \ref cpu_rdmsr + * + * @returns a handle to the driver on success, and NULL on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +struct msr_driver_t* cpu_msr_driver_open(void); + +/** + * @brief Similar to \ref cpu_msr_driver_open, but accept one parameter + * + * This function works on certain operating systems (GNU/Linux, FreeBSD) + * + * @param core_num specify the core number for MSR. + * The first core number is 0. + * The last core number is \ref cpuid_get_total_cpus - 1. + * + * @returns a handle to the driver on success, and NULL on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num); + +/** + * @brief Reads a Model-Specific Register (MSR) + * + * If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can + * read a MSR with the given index by calling this function. + * + * There are several prerequisites you must do before reading MSRs: + * 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag + * in cpu_id_t::flags + * 2) You must ensure that the CPU implements the specific MSR you intend to + * read. + * 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and + * needs ring-0 access in order to work. This temporary driver is created + * by calling \ref cpu_msr_driver_open + * + * @param handle - a handle to the MSR reader driver, as created by + * cpu_msr_driver_open + * @param msr_index - the numeric ID of the MSR you want to read + * @param result - a pointer to a 64-bit integer, where the MSR value is stored + * + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result); + + +typedef enum +{ + INFO_MPERF, /*!< Maximum performance frequency clock. This + is a counter, which increments as a + proportion of the actual processor speed. */ + INFO_APERF, /*!< Actual performance frequency clock. This + accumulates the core clock counts when the + core is active. */ + INFO_MIN_MULTIPLIER, /*!< Minimum CPU:FSB ratio for this CPU, + multiplied by 100. */ + INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100. + e.g., a CPU:FSB value of 18.5 reads as + "1850". */ + INFO_MAX_MULTIPLIER, /*!< Maximum CPU:FSB ratio for this CPU, + multiplied by 100. */ + INFO_TEMPERATURE, /*!< The current core temperature in Celsius. */ + INFO_THROTTLING, /*!< 1 if the current logical processor is + throttling. 0 if it is running normally. */ + INFO_VOLTAGE, /*!< The current core voltage in Volt, + multiplied by 100. */ + INFO_BCLK, /*!< See \ref INFO_BUS_CLOCK. */ + INFO_BUS_CLOCK, /*!< The main bus clock in MHz, + e.g., FSB/QPI/DMI/HT base clock, + multiplied by 100. */ +} cpu_msrinfo_request_t; + +/** + * @brief Similar to \ref cpu_rdmsr, but extract a range of bits + * + * @param handle - a handle to the MSR reader driver, as created by + * cpu_msr_driver_open + * @param msr_index - the numeric ID of the MSR you want to read + * @param highbit - the high bit in range, must be inferior to 64 + * @param lowbit - the low bit in range, must be equal or superior to 0 + * @param result - a pointer to a 64-bit integer, where the MSR value is stored + * + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, + uint8_t lowbit, uint64_t* result); + +/** + * @brief Reads extended CPU information from Model-Specific Registers. + * @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open + * @param which - which info field should be returned. A list of + * available information entities is listed in the + * cpu_msrinfo_request_t enum. + * @retval - if the requested information is available for the current + * processor model, the respective value is returned. + * if no information is available, or the CPU doesn't support + * the query, the special value CPU_INVALID_VALUE is returned + * @note This function is not MT-safe. If you intend to call it from multiple + * threads, guard it through a mutex or a similar primitive. + */ +int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which); +#define CPU_INVALID_VALUE 0x3fffffff + +/** + * @brief Writes the raw MSR data to a text file + * @param data - a pointer to msr_driver_t structure + * @param filename - the path of the file, where the serialized data should be + * written. If empty, stdout will be used. + * @note This is intended primarily for debugging. On some processor, which is + * not currently supported or not completely recognized by cpu_identify, + * one can still successfully get the raw data and write it to a file. + * libcpuid developers can later import this file and debug the detection + * code as if running on the actual hardware. + * The file is simple text format of "something=value" pairs. Version info + * is also written, but the format is not intended to be neither backward- + * nor forward compatible. + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename); + +/** + * @brief Closes an open MSR driver + * + * This function unloads the MSR driver opened by cpu_msr_driver_open and + * frees any resources associated with it. + * + * @param handle - a handle to the MSR reader driver, as created by + * cpu_msr_driver_open + * + * @returns zero if successful, and some negative number on error. + * The error message can be obtained by calling \ref cpuid_error. + * @see cpu_error_t + */ +int cpu_msr_driver_close(struct msr_driver_t* handle); + #ifdef __cplusplus }; /* extern "C" */ #endif diff --git a/src/3rdparty/libcpuid/libcpuid_types.h b/src/3rdparty/libcpuid/libcpuid_types.h index 9e897275..b0923cc6 100644 --- a/src/3rdparty/libcpuid/libcpuid_types.h +++ b/src/3rdparty/libcpuid/libcpuid_types.h @@ -32,6 +32,36 @@ #ifndef __LIBCPUID_TYPES_H__ #define __LIBCPUID_TYPES_H__ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(HAVE_STDINT_H) +# include +#else +/* we have to provide our own: */ +# if !defined(HAVE_INT32_T) && !defined(__int32_t_defined) +typedef int int32_t; +# endif + +# if !defined(HAVE_UINT32_T) && !defined(__uint32_t_defined) +typedef unsigned uint32_t; +# endif + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +#if (defined _MSC_VER) && (_MSC_VER <= 1300) +/* MSVC 6.0: no long longs ... */ +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* all other sane compilers: */ +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#endif #endif /* __LIBCPUID_TYPES_H__ */ diff --git a/src/3rdparty/libcpuid/libcpuid_util.c b/src/3rdparty/libcpuid/libcpuid_util.c index 90ac5125..8d4ca03d 100644 --- a/src/3rdparty/libcpuid/libcpuid_util.c +++ b/src/3rdparty/libcpuid/libcpuid_util.c @@ -32,6 +32,8 @@ #include "libcpuid.h" #include "libcpuid_util.h" +int _current_verboselevel; + void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data) { int i; @@ -42,6 +44,165 @@ void match_features(const struct feature_map_t* matchtable, int count, uint32_t } } +static void default_warn(const char* msg) +{ + fprintf(stderr, "%s", msg); +} + +libcpuid_warn_fn_t _warn_fun = default_warn; + +#if defined(_MSC_VER) +# define vsnprintf _vsnprintf +#endif +void warnf(const char* format, ...) +{ + char buff[1024]; + va_list va; + if(!_warn_fun) + { + return; + } + va_start(va, format); + vsnprintf(buff, sizeof(buff), format, va); + va_end(va); + _warn_fun(buff); +} + +void debugf(int verboselevel, const char* format, ...) +{ + char buff[1024]; + va_list va; + if(verboselevel > _current_verboselevel) + { + return; + } + va_start(va, format); + vsnprintf(buff, sizeof(buff), format, va); + va_end(va); + _warn_fun(buff); +} + +static int popcount64(uint64_t mask) +{ + int num_set_bits = 0; + + while(mask) + { + mask &= mask - 1; + num_set_bits++; + } + + return num_set_bits; +} + +static int score(const struct match_entry_t* entry, const struct cpu_id_t* data, + int brand_code, uint64_t bits, int model_code) +{ + int res = 0; + if(entry->family == data->family) + { + res += 2; + } + if(entry->model == data->model) + { + res += 2; + } + if(entry->stepping == data->stepping) + { + res += 2; + } + if(entry->ext_family == data->ext_family) + { + res += 2; + } + if(entry->ext_model == data->ext_model) + { + res += 2; + } + if(entry->ncores == data->num_cores) + { + res += 2; + } + if(entry->l2cache == data->l2_cache) + { + res += 1; + } + if(entry->l3cache == data->l3_cache) + { + res += 1; + } + if(entry->brand_code == brand_code) + { + res += 2; + } + if(entry->model_code == model_code) + { + res += 2; + } + + res += popcount64(entry->model_bits & bits) * 2; + return res; +} + +int match_cpu_codename(const struct match_entry_t* matchtable, int count, + struct cpu_id_t* data, int brand_code, uint64_t bits, + int model_code) +{ + int bestscore = -1; + int bestindex = 0; + int i, t; + + debugf(3, "Matching cpu f:%d, m:%d, s:%d, xf:%d, xm:%d, ncore:%d, l2:%d, bcode:%d, bits:%I64u, code:%d\n", + data->family, data->model, data->stepping, data->ext_family, + data->ext_model, data->num_cores, data->l2_cache, brand_code, (unsigned long long) bits, model_code); + + for(i = 0; i < count; i++) + { + t = score(&matchtable[i], data, brand_code, bits, model_code); + debugf(3, "Entry %d, `%s', score %d\n", i, matchtable[i].name, t); + if(t > bestscore) + { + debugf(2, "Entry `%s' selected - best score so far (%d)\n", matchtable[i].name, t); + bestscore = t; + bestindex = i; + } + } + strcpy(data->cpu_codename, matchtable[bestindex].name); + return bestscore; +} + +void generic_get_cpu_list(const struct match_entry_t* matchtable, int count, + struct cpu_list_t* list) +{ + int i, j, n, good; + n = 0; + list->names = (char**) malloc(sizeof(char*) * count); + for(i = 0; i < count; i++) + { + if(strstr(matchtable[i].name, "Unknown")) + { + continue; + } + good = 1; + for(j = n - 1; j >= 0; j--) + if(!strcmp(list->names[j], matchtable[i].name)) + { + good = 0; + break; + } + if(!good) + { + continue; + } +#if defined(_MSC_VER) + list->names[n++] = _strdup(matchtable[i].name); +#else + list->names[n++] = strdup(matchtable[i].name); +#endif + } + list->num_entries = n; +} + static int xmatch_entry(char c, const char* p) { int i, j; @@ -126,3 +287,21 @@ int match_all(uint64_t bits, uint64_t mask) { return (bits & mask) == mask; } + +void debug_print_lbits(int debuglevel, uint64_t mask) +{ + int i, first = 0; + for(i = 0; i < 64; i++) if(mask & (((uint64_t) 1) << i)) + { + if(first) + { + first = 0; + } + else + { + debugf(2, " + "); + } + debugf(2, "LBIT(%d)", i); + } + debugf(2, "\n"); +} diff --git a/src/3rdparty/libcpuid/libcpuid_util.h b/src/3rdparty/libcpuid/libcpuid_util.h index eaff1430..9c75435e 100644 --- a/src/3rdparty/libcpuid/libcpuid_util.h +++ b/src/3rdparty/libcpuid/libcpuid_util.h @@ -50,6 +50,20 @@ struct match_entry_t int match_cpu_codename(const struct match_entry_t* matchtable, int count, struct cpu_id_t* data, int brand_code, uint64_t bits, int model_code); + +void warnf(const char* format, ...) +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +; +void debugf(int verboselevel, const char* format, ...) +#ifdef __GNUC__ +__attribute__((format(printf, 2, 3))) +#endif +; +void generic_get_cpu_list(const struct match_entry_t* matchtable, int count, + struct cpu_list_t* list); + /* * Seek for a pattern in `haystack'. * Pattern may be an fixed string, or contain the special metacharacters @@ -72,9 +86,15 @@ struct cpu_id_t* get_cached_cpuid(void); /* returns true if all bits of mask are present in `bits'. */ int match_all(uint64_t bits, uint64_t mask); +/* print what bits a mask consists of */ +void debug_print_lbits(int debuglevel, uint64_t mask); + /* * Sets the current errno */ int set_error(cpu_error_t err); +extern libcpuid_warn_fn_t _warn_fun; +extern int _current_verboselevel; + #endif /* __LIBCPUID_UTIL_H__ */ diff --git a/src/3rdparty/libcpuid/msrdriver.c b/src/3rdparty/libcpuid/msrdriver.c new file mode 100644 index 00000000..9dc42bdd --- /dev/null +++ b/src/3rdparty/libcpuid/msrdriver.c @@ -0,0 +1,595 @@ +/* + * Copyright 2009 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @File msrdriver.c + * @Brief Contains the binary images of the x86 and x64 MSR drivers for Windows + * @Date 2009-09-29 + * + * The driver is courtesy of Nick 'Bombera' Gabareff, and its source is actually + * available, see the contrib/ dir. + * + * However, for simplicity, here we just include the images of the compiled .SYS + * files. + * They are extracted to the filesystem on demand and loaded in the kernel + * by the cpu_msr_driver_open() function + */ +#ifdef _WIN32 +#include "asm-bits.h" +//begin { +int cc_x86driver_code_size = 4608; +uint8_t cc_x86driver_code[4608] = +{ + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, + 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, + 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, + 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9f, 0x99, 0x48, 0xdf, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c, + 0xdb, 0xf8, 0x27, 0x8c, 0xdd, 0xf8, 0x26, 0x8c, 0x21, 0xdb, 0x3f, 0x8c, 0xd8, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, + 0x57, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5a, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5e, 0x8c, + 0xda, 0xf8, 0x26, 0x8c, 0x52, 0x69, 0x63, 0x68, 0xdb, 0xf8, 0x26, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x07, 0x00, 0x12, 0x9b, 0x9b, 0x4a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x21, 0x0b, 0x01, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0xa9, 0xd1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, + 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46, + 0x8c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54, + 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2, + 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x42, 0x2e, 0x72, 0x65, 0x6c, 0x6f, 0x63, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c, + 0x24, 0x08, 0x83, 0x61, 0x18, 0x00, 0x83, 0x61, 0x1c, 0x00, 0x32, 0xd2, 0xff, 0x15, 0x08, 0x20, 0x01, 0x00, + 0x33, 0xc0, 0xc2, 0x08, 0x00, 0x56, 0x8b, 0x74, 0x24, 0x0c, 0x8b, 0x46, 0x60, 0x81, 0x78, 0x0c, 0x0c, 0xe0, + 0x22, 0x00, 0x57, 0x75, 0x3c, 0x83, 0x78, 0x04, 0x08, 0x72, 0x36, 0x83, 0x78, 0x08, 0x04, 0x75, 0x07, 0x8b, + 0x46, 0x0c, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01, 0x00, 0x00, 0x8b, 0x7e, 0x0c, 0x0f, 0x32, 0x89, 0x07, + 0x89, 0x57, 0x04, 0xc7, 0x46, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x33, 0xff, 0x32, 0xd2, 0x8b, 0xce, 0xff, 0x15, + 0x08, 0x20, 0x01, 0x00, 0x8b, 0xc7, 0x5f, 0x5e, 0xc2, 0x08, 0x00, 0x83, 0x66, 0x1c, 0x00, 0xbf, 0x01, 0x00, + 0x00, 0xc0, 0x89, 0x7e, 0x18, 0xeb, 0xe1, 0x55, 0x8b, 0xec, 0x51, 0x51, 0x8b, 0x45, 0x08, 0xff, 0x70, 0x04, + 0xff, 0x15, 0x04, 0x20, 0x01, 0x00, 0x68, 0x3c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x00, + 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x14, 0x20, 0x01, 0x00, 0xc9, 0xc2, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50, 0x00, 0x00, + 0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, + 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00, + 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, + 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x8b, 0xec, 0x83, + 0xec, 0x14, 0x56, 0x8b, 0x35, 0x00, 0x20, 0x01, 0x00, 0x57, 0x68, 0x1c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf4, + 0x50, 0xff, 0xd6, 0x8b, 0x7d, 0x08, 0x8d, 0x45, 0xfc, 0x50, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x22, 0x8d, 0x45, + 0xf4, 0x50, 0x6a, 0x04, 0x57, 0xff, 0x15, 0x10, 0x20, 0x01, 0x00, 0x85, 0xc0, 0x75, 0x4f, 0x68, 0x3c, 0x20, + 0x01, 0x00, 0x8d, 0x45, 0xec, 0x50, 0xff, 0xd6, 0x8d, 0x45, 0xf4, 0x50, 0x8d, 0x45, 0xec, 0x50, 0xff, 0x15, + 0x0c, 0x20, 0x01, 0x00, 0x8b, 0xf0, 0x85, 0xf6, 0x74, 0x0d, 0xff, 0x75, 0xfc, 0xff, 0x15, 0x04, 0x20, 0x01, + 0x00, 0x8b, 0xc6, 0xeb, 0x23, 0x8b, 0x45, 0xfc, 0xa3, 0x00, 0x30, 0x01, 0x00, 0xb8, 0x00, 0x10, 0x01, 0x00, + 0x89, 0x47, 0x38, 0x89, 0x47, 0x40, 0xc7, 0x47, 0x34, 0x75, 0x10, 0x01, 0x00, 0xc7, 0x47, 0x70, 0x19, 0x10, + 0x01, 0x00, 0x33, 0xc0, 0x5f, 0x5e, 0xc9, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x50, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50, + 0x00, 0x00, 0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4b, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, + 0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x0b, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69, + 0x63, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x49, 0x01, 0x49, 0x6f, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0xda, 0x01, 0x49, 0x6f, 0x66, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x41, 0x01, + 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, + 0x6e, 0x6b, 0x00, 0x00, 0x38, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x00, 0x00, 0x6e, 0x74, 0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x5c, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, + 0x53, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xba, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, + 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00, + 0x34, 0x00, 0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x6d, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00, + 0x52, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x65, 0x00, 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, + 0x20, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, + 0x75, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, + 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00, + 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00, + 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, + 0x6c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, + 0x62, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, + 0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x52, 0x00, + 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00, 0x01, 0x00, + 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, + 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, + 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x30, 0x5c, 0x30, 0x82, 0x30, 0x87, 0x30, 0x91, 0x30, 0x9b, 0x30, 0x00, 0x40, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x09, 0x30, 0x0f, 0x30, 0x2f, 0x30, 0x38, 0x30, 0x4c, 0x30, 0x5b, 0x30, 0x67, 0x30, 0x6c, 0x30, + 0x79, 0x30, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +int cc_x64driver_code_size = 5120; +uint8_t cc_x64driver_code[5120] = +{ + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, + 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, + 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, + 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb7, 0x04, 0xa8, 0xc2, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91, + 0xf3, 0x65, 0xc7, 0x91, 0xf4, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbd, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x85, 0xf8, + 0xab, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x30, 0x6a, 0x98, 0x91, 0xf2, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbe, 0x91, + 0xf2, 0x65, 0xc6, 0x91, 0x52, 0x69, 0x63, 0x68, 0xf3, 0x65, 0xc6, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x07, 0x00, + 0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x22, 0x00, 0x0b, 0x02, + 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x60, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x79, 0x44, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x60, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, + 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x2e, 0x70, + 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x48, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2, 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, + 0xc0, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x28, + 0x33, 0xc9, 0x48, 0x8b, 0xc2, 0x89, 0x4a, 0x30, 0x48, 0x89, 0x4a, 0x38, 0x33, 0xd2, 0x48, 0x8b, 0xc8, 0xff, + 0x15, 0xfd, 0x0f, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x82, 0xb8, 0x00, 0x00, + 0x00, 0x4c, 0x8b, 0xca, 0x81, 0x78, 0x18, 0x0c, 0xe0, 0x22, 0x00, 0x75, 0x43, 0x83, 0x78, 0x08, 0x08, 0x72, + 0x3d, 0x83, 0x78, 0x10, 0x04, 0x75, 0x08, 0x48, 0x8b, 0x42, 0x18, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01, + 0x00, 0x00, 0x4c, 0x8b, 0x42, 0x18, 0x0f, 0x32, 0x48, 0xc1, 0xe2, 0x20, 0x49, 0x8b, 0xc9, 0x48, 0x0b, 0xc2, + 0x33, 0xd2, 0x49, 0x89, 0x00, 0x49, 0xc7, 0x41, 0x38, 0x08, 0x00, 0x00, 0x00, 0xff, 0x15, 0x95, 0x0f, 0x00, + 0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xc7, 0x42, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x48, 0xc7, 0x42, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xc9, 0x33, 0xd2, 0xff, 0x15, 0x74, 0x0f, 0x00, 0x00, 0xb8, 0x01, + 0x00, 0x00, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x38, 0x48, 0x8b, 0x49, 0x08, 0xff, 0x15, + 0x32, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x1b, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15, + 0x18, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15, 0x05, 0x0f, 0x00, 0x00, 0x48, 0x83, 0xc4, + 0x38, 0xc3, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x5c, 0x20, 0x00, 0x00, 0x5c, 0x06, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, 0xd9, 0x5e, 0xab, 0x47, 0xc4, 0xf2, + 0x4f, 0x40, 0xaa, 0xe9, 0x90, 0x47, 0x67, 0x30, 0xa5, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x44, 0x3a, 0x5c, 0x74, + 0x6d, 0x70, 0x5c, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5c, 0x6f, 0x62, 0x6a, 0x66, 0x72, 0x65, 0x5f, 0x77, + 0x6e, 0x65, 0x74, 0x5f, 0x41, 0x4d, 0x44, 0x36, 0x34, 0x5c, 0x61, 0x6d, 0x64, 0x36, 0x34, 0x5c, 0x54, 0x6d, + 0x70, 0x52, 0x64, 0x72, 0x2e, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, + 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x21, 0x08, + 0x02, 0x00, 0x08, 0x74, 0x13, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, + 0x01, 0x0c, 0x03, 0x00, 0x0c, 0x34, 0x12, 0x00, 0x04, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x5d, 0x20, 0xd2, 0x66, 0xd4, 0xff, 0xff, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x00, 0x40, 0x10, + 0x00, 0x00, 0xbe, 0x10, 0x00, 0x00, 0xb0, 0x20, 0x00, 0x00, 0xd0, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, + 0xb8, 0x20, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x74, 0x50, + 0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xd0, 0x20, 0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xf5, 0x50, 0x00, 0x00, + 0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x78, 0x48, 0x89, 0x9c, 0x24, + 0x90, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8d, 0x15, 0x0a, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, + 0x48, 0xff, 0x15, 0xd7, 0xcf, 0xff, 0xff, 0x41, 0xb9, 0x22, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x5c, 0x24, 0x40, + 0x4c, 0x89, 0x5c, 0x24, 0x30, 0x4c, 0x8d, 0x44, 0x24, 0x48, 0x41, 0x8d, 0x51, 0xe6, 0x48, 0x8b, 0xcb, 0xc6, + 0x44, 0x24, 0x28, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0xc0, 0xcf, 0xff, 0xff, + 0x85, 0xc0, 0x0f, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x91, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c, + 0x24, 0x58, 0x48, 0x89, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x48, 0x8d, + 0x54, 0x24, 0x48, 0x48, 0x8d, 0x4c, 0x24, 0x58, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x85, 0xc0, 0x8b, 0xf8, + 0x74, 0x0f, 0x48, 0x8b, 0x4c, 0x24, 0x40, 0xff, 0x15, 0x6d, 0xcf, 0xff, 0xff, 0x8b, 0xc7, 0xeb, 0x39, 0x48, + 0x8b, 0x44, 0x24, 0x40, 0x48, 0x89, 0x05, 0x5d, 0xe0, 0xff, 0xff, 0x48, 0x8d, 0x05, 0x16, 0xc0, 0xff, 0xff, + 0x48, 0x89, 0x43, 0x68, 0x48, 0x8d, 0x05, 0x4b, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x43, 0x70, 0x48, 0x89, 0x83, + 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x69, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x83, 0xe0, 0x00, 0x00, 0x00, + 0x33, 0xc0, 0x48, 0x8b, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x9c, 0x24, 0x90, 0x00, 0x00, 0x00, + 0x48, 0x83, 0xc4, 0x78, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00, + 0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x05, 0xf1, 0xd0, 0xff, 0xff, 0x49, 0xb9, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x48, + 0x85, 0xc0, 0x74, 0x05, 0x49, 0x3b, 0xc1, 0x75, 0x2f, 0x4c, 0x8d, 0x05, 0xd6, 0xd0, 0xff, 0xff, 0x48, 0xb8, + 0x20, 0x03, 0x00, 0x00, 0x80, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x49, 0x33, 0xc0, 0x49, 0xb8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x49, 0x23, 0xc0, 0x49, 0x0f, 0x44, 0xc1, 0x48, 0x89, 0x05, 0xae, 0xd0, + 0xff, 0xff, 0x48, 0xf7, 0xd0, 0x48, 0x89, 0x05, 0x9c, 0xd0, 0xff, 0xff, 0xe9, 0xa7, 0xef, 0xff, 0xff, 0xcc, + 0xcc, 0xcc, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x61, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x01, 0x49, 0x6f, 0x66, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x61, 0x01, + 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, + 0x6e, 0x6b, 0x00, 0x00, 0x3e, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69, 0x63, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x5f, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x55, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x4c, 0x01, + 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x6e, 0x74, + 0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x70, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, + 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbe, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, + 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00, 0x34, 0x00, + 0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x52, 0x00, + 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x36, 0x00, + 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00, 0x65, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x36, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, + 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6c, 0x00, + 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, + 0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, 0x62, 0x00, + 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00, 0x69, 0x00, + 0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, + 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, + 0x64, 0x00, 0x72, 0x00, 0x36, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, + 0x63, 0x00, 0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, + 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, + 0x52, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00, + 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, + 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +//} end +#endif // _WIN32 + +int msrdriver_dummy; // a dummy to avoid a linker warning on OS X. diff --git a/src/3rdparty/libcpuid/rdmsr.c b/src/3rdparty/libcpuid/rdmsr.c new file mode 100644 index 00000000..60a75600 --- /dev/null +++ b/src/3rdparty/libcpuid/rdmsr.c @@ -0,0 +1,1291 @@ +/* + * Copyright 2009 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "libcpuid.h" +#include "asm-bits.h" +#include "libcpuid_util.h" +#include "libcpuid_internal.h" +#include "rdtsc.h" + +#if defined (__linux__) || defined (__gnu_linux__) +/* Assuming linux with /dev/cpu/x/msr: */ +#include +#include +#include +#include +#include +#include +struct msr_driver_t +{ + int fd; +}; +static int rdmsr_supported(void); +static int load_driver(char* msr_path) +{ + const int file_exists = !access(msr_path, F_OK); + const int file_readable = !access(msr_path, R_OK); + + if(file_exists && file_readable) + { + return 1; + } + else if(file_exists && !file_readable) + { + return 0; + } + else if(getuid() != 0) + { + return 0; + } + else + { + return !system("modprobe msr 2> /dev/null"); + } +} + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + return cpu_msr_driver_open_core(0); +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + char msr[32]; + struct msr_driver_t* handle; + if(core_num >= cpuid_get_total_cpus()) + { + set_error(ERR_INVCNB); + return NULL; + } + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + sprintf(msr, "/dev/cpu/%u/msr", core_num); + if(!load_driver(msr)) + { + set_error(ERR_NO_DRIVER); + return NULL; + } + int fd = open(msr, O_RDONLY); + if(fd < 0) + { + if(errno == EIO) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + set_error(ERR_NO_DRIVER); + return NULL; + } + handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + handle->fd = fd; + return handle; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + ssize_t ret; + + if(!driver || driver->fd < 0) + { + return set_error(ERR_HANDLE); + } + ret = pread(driver->fd, result, 8, msr_index); + if(ret != 8) + { + return set_error(ERR_INVMSR); + } + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + if(drv && drv->fd >= 0) + { + close(drv->fd); + free(drv); + } + return 0; +} + +/* #endif defined (__linux__) || defined (__gnu_linux__) */ + +#elif defined (__FreeBSD__) || defined (__DragonFly__) +/* Assuming FreeBSD with /dev/cpuctlX */ +#include +#include +#include +#include +#include + +struct msr_driver_t +{ + int fd; +}; +static int rdmsr_supported(void); +static int load_driver(char* msr_path) +{ + const int file_exists = !access(msr_path, F_OK); + const int file_readable = !access(msr_path, R_OK); + + if(file_exists && file_readable) + { + return 1; + } + else if(file_exists && !file_readable) + { + return 0; + } + else if(getuid() != 0) + { + return 0; + } + else + { + return !system("kldload -n cpuctl 2> /dev/null"); + } +} + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + return cpu_msr_driver_open_core(0); +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + char msr[32]; + struct msr_driver_t* handle; + if(core_num >= cpuid_get_total_cpus()) + { + set_error(ERR_INVCNB); + return NULL; + } + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + sprintf(msr, "/dev/cpuctl%u", core_num); + if(!load_driver(msr)) + { + set_error(ERR_NO_DRIVER); + return NULL; + } + int fd = open(msr, O_RDONLY); + if(fd < 0) + { + if(errno == EIO) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + set_error(ERR_NO_DRIVER); + return NULL; + } + handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + handle->fd = fd; + return handle; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + cpuctl_msr_args_t args; + args.msr = msr_index; + + if(!driver || driver->fd < 0) + { + return set_error(ERR_HANDLE); + } + + if(ioctl(driver->fd, CPUCTL_RDMSR, &args)) + { + return set_error(ERR_INVMSR); + } + + *result = args.data; + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + if(drv && drv->fd >= 0) + { + close(drv->fd); + free(drv); + } + return 0; +} + +/* #endif defined (__FreeBSD__) || defined (__DragonFly__) */ + +#elif defined (_WIN32) +#include +#include +#include + +extern uint8_t cc_x86driver_code[]; +extern int cc_x86driver_code_size; +extern uint8_t cc_x64driver_code[]; +extern int cc_x64driver_code_size; + +struct msr_driver_t +{ + char driver_path[MAX_PATH + 1]; + SC_HANDLE scManager; + volatile SC_HANDLE scDriver; + HANDLE hhDriver; + OVERLAPPED ovl; + int errorcode; +}; + +static int rdmsr_supported(void); +static int extract_driver(struct msr_driver_t* driver); +static int load_driver(struct msr_driver_t* driver); + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + struct msr_driver_t* drv; + int status; + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + + drv = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + if(!drv) + { + set_error(ERR_NO_MEM); + return NULL; + } + memset(drv, 0, sizeof(struct msr_driver_t)); + + if(!extract_driver(drv)) + { + free(drv); + set_error(ERR_EXTRACT); + return NULL; + } + + status = load_driver(drv); + if(!DeleteFile(drv->driver_path)) + { + debugf(1, "Deleting temporary driver file failed.\n"); + } + if(!status) + { + set_error(drv->errorcode ? drv->errorcode : ERR_NO_DRIVER); + free(drv); + return NULL; + } + return drv; +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + warnf("cpu_msr_driver_open_core(): parameter ignored (function is the same as cpu_msr_driver_open)\n"); + return cpu_msr_driver_open(); +} + +typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); +static BOOL is_running_x64(void) +{ + BOOL bIsWow64 = FALSE; + + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(__TEXT("kernel32")), + "IsWow64Process"); + if(NULL != fnIsWow64Process) + { + fnIsWow64Process(GetCurrentProcess(), &bIsWow64); + } + return bIsWow64; +} + + +static int extract_driver(struct msr_driver_t* driver) +{ + FILE* f; + if(!GetTempPath(sizeof(driver->driver_path), driver->driver_path)) + { + return 0; + } + strcat(driver->driver_path, "TmpRdr.sys"); + + f = fopen(driver->driver_path, "wb"); + if(!f) + { + return 0; + } + if(is_running_x64()) + { + fwrite(cc_x64driver_code, 1, cc_x64driver_code_size, f); + } + else + { + fwrite(cc_x86driver_code, 1, cc_x86driver_code_size, f); + } + fclose(f); + return 1; +} + +static BOOL wait_for_service_state(SC_HANDLE hService, DWORD dwDesiredState, SERVICE_STATUS* lpsrvStatus) +{ + BOOL fOK = FALSE; + DWORD dwWaitHint; + + if(hService != NULL) + { + while(TRUE) + { + fOK = QueryServiceStatus(hService, lpsrvStatus); + if(!fOK) + { + break; + } + if(lpsrvStatus->dwCurrentState == dwDesiredState) + { + break; + } + + dwWaitHint = lpsrvStatus->dwWaitHint / 10; // Poll 1/10 of the wait hint + if(dwWaitHint < 1000) + { + dwWaitHint = 1000; // At most once per second + } + if(dwWaitHint > 10000) + { + dwWaitHint = 10000; // At least every 10 seconds + } + Sleep(dwWaitHint); + } + } + + return fOK; +} + +static int load_driver(struct msr_driver_t* drv) +{ + LPTSTR lpszInfo = __TEXT("RDMSR Executor Driver"); + USHORT uLen = 0; + SERVICE_STATUS srvStatus = {0}; + BOOL fRunning = FALSE; + DWORD dwLastError; + LPTSTR lpszDriverServiceName = __TEXT("TmpRdr"); + TCHAR lpszDriverName[] = __TEXT("\\\\.\\Global\\TmpRdr"); + + if((LPVOID)(drv->scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) != NULL) + { + drv->scDriver = CreateService(drv->scManager, lpszDriverServiceName, lpszInfo, SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + drv->driver_path, NULL, NULL, NULL, NULL, NULL); + if(drv->scDriver == NULL) + { + switch(dwLastError = GetLastError()) + { + case ERROR_SERVICE_EXISTS: + case ERROR_SERVICE_MARKED_FOR_DELETE: + { + LPQUERY_SERVICE_CONFIG lpqsc; + DWORD dwBytesNeeded; + + drv->scDriver = OpenService(drv->scManager, lpszDriverServiceName, SERVICE_ALL_ACCESS); + if(drv->scDriver == NULL) + { + debugf(1, "Error opening service: %d\n", GetLastError()); + break; + } + + QueryServiceConfig(drv->scDriver, NULL, 0, &dwBytesNeeded); + if((dwLastError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) + { + lpqsc = calloc(1, dwBytesNeeded); + if(!QueryServiceConfig(drv->scDriver, lpqsc, dwBytesNeeded, &dwBytesNeeded)) + { + free(lpqsc); + debugf(1, "Error query service config(adjusted buffer): %d\n", GetLastError()); + goto clean_up; + } + else + { + free(lpqsc); + } + } + else + { + debugf(1, "Error query service config: %d\n", dwLastError); + goto clean_up; + } + + break; + } + case ERROR_ACCESS_DENIED: + drv->errorcode = ERR_NO_PERMS; + break; + default: + debugf(1, "Create driver service failed: %d\n", dwLastError); + break; + } + } + if(drv->scDriver != NULL) + { + if(StartService(drv->scDriver, 0, NULL)) + { + if(!wait_for_service_state(drv->scDriver, SERVICE_RUNNING, &srvStatus)) + { + debugf(1, "Driver load failed.\n"); + DeleteService(drv->scDriver); + CloseServiceHandle(drv->scManager); + drv->scDriver = NULL; + goto clean_up; + } + else + { + fRunning = TRUE; + } + } + else + { + if((dwLastError = GetLastError()) == ERROR_SERVICE_ALREADY_RUNNING) + { + fRunning = TRUE; + } + else + { + debugf(1, "Driver start failed.\n"); + DeleteService(drv->scDriver); + CloseServiceHandle(drv->scManager); + drv->scDriver = NULL; + goto clean_up; + } + + } + if(fRunning) + { + debugf(1, "Driver already running.\n"); + } + else + { + debugf(1, "Driver loaded.\n"); + } + CloseServiceHandle(drv->scManager); + drv->hhDriver = CreateFile(lpszDriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + drv->ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + return 1; + } + } + else + { + debugf(1, "Open SCM failed: %d\n", GetLastError()); + } + +clean_up: + if(drv->scManager != NULL) + { + CloseServiceHandle(drv->scManager); + drv->scManager = 0; // pointless + } + if(drv->scDriver != NULL) + { + if(!DeleteService(drv->scDriver)) + { + debugf(1, "Delete driver service failed: %d\n", GetLastError()); + } + CloseServiceHandle(drv->scDriver); + drv->scDriver = 0; + } + + return 0; +} + +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN +#define IOCTL_PROCVIEW_RDMSR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + DWORD dwBytesReturned; + __int64 msrdata; + SERVICE_STATUS srvStatus = {0}; + + if(!driver) + { + return set_error(ERR_HANDLE); + } + DeviceIoControl(driver->hhDriver, IOCTL_PROCVIEW_RDMSR, &msr_index, sizeof(int), &msrdata, sizeof(__int64), + &dwBytesReturned, &driver->ovl); + GetOverlappedResult(driver->hhDriver, &driver->ovl, &dwBytesReturned, TRUE); + *result = msrdata; + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + SERVICE_STATUS srvStatus = {0}; + if(drv == NULL) + { + return 0; + } + if(drv->scDriver != NULL) + { + if(drv->hhDriver) + { + CancelIo(drv->hhDriver); + } + if(drv->ovl.hEvent != NULL) + { + CloseHandle(drv->ovl.hEvent); + } + if(drv->hhDriver) + { + CloseHandle(drv->hhDriver); + } + drv->hhDriver = NULL; + drv->ovl.hEvent = NULL; + if(ControlService(drv->scDriver, SERVICE_CONTROL_STOP, &srvStatus)) + { + if(wait_for_service_state(drv->scDriver, SERVICE_STOPPED, &srvStatus)) + { + DeleteService(drv->scDriver); + } + } + } + return 0; +} + +/* endif defined (_WIN32) */ + +#else /* Unsupported OS */ +/* On others OS (i.e., Darwin), we still do not support RDMSR, so supply dummy struct + and functions */ + +#define RDMSR_UNSUPPORTED_OS + +struct msr_driver_t +{ + int dummy; +}; +struct msr_driver_t* cpu_msr_driver_open(void) +{ + set_error(ERR_NOT_IMP); + return NULL; +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + set_error(ERR_NOT_IMP); + return NULL; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_msr_driver_close(struct msr_driver_t* driver) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, + uint8_t lowbit, uint64_t* result) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which) +{ + return set_error(ERR_NOT_IMP); +} + +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + return set_error(ERR_NOT_IMP); +} + +#endif /* Unsupported OS */ + +#ifndef RDMSR_UNSUPPORTED_OS + +/* Useful links for hackers: +- AMD MSRs: + AMD BIOS and Kernel Developer’s Guide (BKDG) + * AMD Family 10h Processors + http://support.amd.com/TechDocs/31116.pdf + * AMD Family 11h Processors + http://support.amd.com/TechDocs/41256.pdf + * AMD Family 12h Processors + http://support.amd.com/TechDocs/41131.pdf + * AMD Family 14h Processors + http://support.amd.com/TechDocs/43170_14h_Mod_00h-0Fh_BKDG.pdf + * AMD Family 15h Processors + http://support.amd.com/TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf + http://support.amd.com/TechDocs/42300_15h_Mod_10h-1Fh_BKDG.pdf + http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf + http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf + http://support.amd.com/TechDocs/55072_AMD_Family_15h_Models_70h-7Fh_BKDG.pdf + * AMD Family 16h Processors + http://support.amd.com/TechDocs/48751_16h_bkdg.pdf + http://support.amd.com/TechDocs/52740_16h_Models_30h-3Fh_BKDG.pdf + + AMD Processor Programming Reference (PPR) + * AMD Family 17h Processors + https://support.amd.com/TechDocs/54945_PPR_Family_17h_Models_00h-0Fh.pdf + +- Intel MSRs: + Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Volume 3 (3A, 3B, 3C & 3D): System Programming Guide + http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf +*/ + +/* AMD MSRs addresses */ +#define MSR_PSTATE_L 0xC0010061 +#define MSR_PSTATE_S 0xC0010063 +#define MSR_PSTATE_0 0xC0010064 +#define MSR_PSTATE_1 0xC0010065 +#define MSR_PSTATE_2 0xC0010066 +#define MSR_PSTATE_3 0xC0010067 +#define MSR_PSTATE_4 0xC0010068 +#define MSR_PSTATE_5 0xC0010069 +#define MSR_PSTATE_6 0xC001006A +#define MSR_PSTATE_7 0xC001006B +static const uint32_t amd_msr[] = +{ + MSR_PSTATE_L, + MSR_PSTATE_S, + MSR_PSTATE_0, + MSR_PSTATE_1, + MSR_PSTATE_2, + MSR_PSTATE_3, + MSR_PSTATE_4, + MSR_PSTATE_5, + MSR_PSTATE_6, + MSR_PSTATE_7, + CPU_INVALID_VALUE +}; + +/* Intel MSRs addresses */ +#define IA32_MPERF 0xE7 +#define IA32_APERF 0xE8 +#define IA32_PERF_STATUS 0x198 +#define IA32_THERM_STATUS 0x19C +#define MSR_EBL_CR_POWERON 0x2A +#define MSR_TURBO_RATIO_LIMIT 0x1AD +#define MSR_TEMPERATURE_TARGET 0x1A2 +#define MSR_PERF_STATUS 0x198 +#define MSR_PLATFORM_INFO 0xCE +static const uint32_t intel_msr[] = +{ + IA32_MPERF, + IA32_APERF, + IA32_PERF_STATUS, + IA32_THERM_STATUS, + MSR_EBL_CR_POWERON, + MSR_TURBO_RATIO_LIMIT, + MSR_TEMPERATURE_TARGET, + MSR_PERF_STATUS, + MSR_PLATFORM_INFO, + CPU_INVALID_VALUE +}; + +struct msr_info_t +{ + int cpu_clock; + struct msr_driver_t* handle; + struct cpu_id_t* id; + struct internal_id_info_t* internal; +}; + +static int rdmsr_supported(void) +{ + struct cpu_id_t* id = get_cached_cpuid(); + return id->flags[CPU_FEATURE_MSR]; +} + +static int perfmsr_measure(struct msr_driver_t* handle, int msr) +{ + int err; + uint64_t a, b; + uint64_t x, y; + err = cpu_rdmsr(handle, msr, &x); + if(err) + { + return CPU_INVALID_VALUE; + } + sys_precise_clock(&a); + busy_loop_delay(10); + cpu_rdmsr(handle, msr, &y); + sys_precise_clock(&b); + if(a >= b || x > y) + { + return CPU_INVALID_VALUE; + } + return (int)((y - x) / (b - a)); +} + +static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double* multiplier) +{ + int i, err; + uint64_t CpuFid, CpuDid, CpuDidLSD; + + /* Constant values needed for 12h family */ + const struct + { + uint64_t did; + double divisor; + } divisor_t[] = + { + { 0x0, 1 }, + { 0x1, 1.5 }, + { 0x2, 2 }, + { 0x3, 3 }, + { 0x4, 4 }, + { 0x5, 6 }, + { 0x6, 8 }, + { 0x7, 12 }, + { 0x8, 16 }, + }; + const int num_dids = (int) COUNT_OF(divisor_t); + + /* Constant values for common families */ + const int magic_constant = (info->id->ext_family == 0x11) ? 0x8 : 0x10; + const int is_apu = ((FUSION_C <= info->internal->code.amd) && (info->internal->code.amd <= FUSION_A)) || + (info->internal->bits & _APU_); + const double divisor = is_apu ? 1.0 : 2.0; + + /* Check if P-state is valid */ + if(pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate) + { + return 1; + } + + switch(info->id->ext_family) + { + case 0x12: + /* BKDG 12h, page 469 + MSRC001_00[6B:64][8:4] is CpuFid + MSRC001_00[6B:64][3:0] is CpuDid + CPU COF is (100MHz * (CpuFid + 10h) / (divisor specified by CpuDid)) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &CpuFid); + err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &CpuDid); + i = 0; + while(i < num_dids && divisor_t[i].did != CpuDid) + { + i++; + } + if(i < num_dids) + { + *multiplier = (double)((CpuFid + magic_constant) / divisor_t[i].divisor); + } + else + { + err++; + } + break; + case 0x14: + /* BKDG 14h, page 430 + MSRC001_00[6B:64][8:4] is CpuDidMSD + MSRC001_00[6B:64][3:0] is CpuDidLSD + PLL COF is (100 MHz * (D18F3xD4[MainPllOpFreqId] + 10h)) + Divisor is (CpuDidMSD + (CpuDidLSD * 0.25) + 1) + CPU COF is (main PLL frequency specified by D18F3xD4[MainPllOpFreqId]) / (core clock divisor specified by CpuDidMSD and CpuDidLSD) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &CpuDidLSD); + *multiplier = (double)(((info->cpu_clock + 5) / 100 + magic_constant) / (CpuDid + CpuDidLSD * 0.25 + 1)); + break; + case 0x10: + /* BKDG 10h, page 429 + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CPU COF is (100 MHz * (CpuFid + 10h) / (2^CpuDid)) + Note: This family contains only CPUs */ + case 0x11: + /* BKDG 11h, page 236 + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CPU COF is ((100 MHz * (CpuFid + 08h)) / (2^CpuDid)) + Note: This family contains only CPUs */ + case 0x15: + /* BKDG 15h, page 570/580/635/692 (00h-0Fh/10h-1Fh/30h-3Fh/60h-6Fh) + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) + Note: This family contains BOTH CPUs and APUs */ + case 0x16: + /* BKDG 16h, page 549/611 (00h-0Fh/30h-3Fh) + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 6, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 5, 0, &CpuFid); + *multiplier = (double)((CpuFid + magic_constant) / (1ull << CpuDid)) / divisor; + break; + case 0x17: + /* PPR 17h, pages 30 and 138-139 + MSRC001_00[6B:64][13:8] is CpuDfsId + MSRC001_00[6B:64][7:0] is CpuFid + CoreCOF is (Core::X86::Msr::PStateDef[CpuFid[7:0]] / Core::X86::Msr::PStateDef[CpuDfsId]) * 200 */ + err = cpu_rdmsr_range(info->handle, pstate, 13, 8, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 7, 0, &CpuFid); + *multiplier = (double)(CpuFid / CpuDid) * 2; + break; + default: + err = 1; + break; + } + + return err; +} + +static uint32_t get_amd_last_pstate_addr(struct msr_info_t* info) +{ + static uint32_t last_addr = 0x0; + uint64_t reg = 0x0; + + /* The result is cached, need to be computed once */ + if(last_addr != 0x0) + { + return last_addr; + } + + /* Refer links above + MSRC001_00[6B:64][63] is PstateEn + PstateEn indicates if the rest of the P-state information in the register is valid after a reset */ + last_addr = MSR_PSTATE_7 + 1; + while((reg == 0x0) && (last_addr > MSR_PSTATE_0)) + { + last_addr--; + cpu_rdmsr_range(info->handle, last_addr, 63, 63, ®); + } + return last_addr; +} + +static double get_info_min_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint32_t addr; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Coreâ„¢ Processors (based on Intel® microarchitecture code name Ivy Bridge) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) + Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_PLATFORM_INFO[47:40] is Maximum Efficiency Ratio + Maximum Efficiency Ratio is the minimum ratio that the processor can operates */ + err = cpu_rdmsr_range(info->handle, MSR_PLATFORM_INFO, 47, 40, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* N.B.: Find the last P-state + get_amd_last_pstate_addr() returns the last P-state, MSR_PSTATE_0 <= addr <= MSR_PSTATE_7 */ + addr = get_amd_last_pstate_addr(info); + err = get_amd_multipliers(info, addr, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_cur_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) + { + err = cpu_rdmsr(info->handle, MSR_EBL_CR_POWERON, ®); + if(!err) + { + return (double)((reg >> 22) & 0x1f); + } + } + else if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel != PENTIUM) + { + /* Refer links above + Table 35-2. IA-32 Architectural MSRs (Contd.) + IA32_PERF_STATUS[15:0] is Current performance State Value + [7:0] is 0x0, [15:8] looks like current ratio */ + err = cpu_rdmsr_range(info->handle, IA32_PERF_STATUS, 15, 8, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0063[2:0] is CurPstate */ + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, ®); + err += get_amd_multipliers(info, MSR_PSTATE_0 + (uint32_t) reg, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_max_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) + { + err = cpu_rdmsr(info->handle, IA32_PERF_STATUS, ®); + if(!err) + { + return (double)((reg >> 40) & 0x1f); + } + } + else if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel != PENTIUM) + { + /* Refer links above + Table 35-10. Specific MSRs Supported by Intel® Atomâ„¢ Processor C2000 Series with CPUID Signature 06_4DH + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture (Contd.) + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.) + Table 35-14. Additional MSRs in Intel® Xeon® Processor 5500 and 3400 Series + Table 35-16. Additional MSRs Supported by Intel Processors (Based on Intel® Microarchitecture Code Name Westmere) + Table 35-19. MSRs Supported by 2nd Generation Intel® Coreâ„¢ Processors (Intel® microarchitecture code name Sandy Bridge) + Table 35-21. Selected MSRs Supported by Intel® Xeon® Processors E5 Family (based on Sandy Bridge microarchitecture) + Table 35-28. MSRs Supported by 4th Generation Intel® Coreâ„¢ Processors (Haswell microarchitecture) (Contd.) + Table 35-30. Additional MSRs Supported by Intel® Xeon® Processor E5 v3 Family + Table 35-33. Additional MSRs Supported by Intel® Coreâ„¢ M Processors and 5th Generation Intel® Coreâ„¢ Processors + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-37. Additional MSRs Supported by 6th Generation Intel® Coreâ„¢ Processors Based on Skylake Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_TURBO_RATIO_LIMIT[7:0] is Maximum Ratio Limit for 1C */ + err = cpu_rdmsr_range(info->handle, MSR_TURBO_RATIO_LIMIT, 7, 0, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0064 is Pb0 + Pb0 is the highest-performance boosted P-state */ + err = get_amd_multipliers(info, MSR_PSTATE_0, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static int get_info_temperature(struct msr_info_t* info) +{ + int err; + uint64_t DigitalReadout, ReadingValid, TemperatureTarget; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-2. IA-32 Architectural MSRs + IA32_THERM_STATUS[22:16] is Digital Readout + IA32_THERM_STATUS[31] is Reading Valid + + Table 35-6. MSRs Common to the Silvermont Microarchitecture and Newer Microarchitectures for Intel® Atom + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.) + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) (Contd.) + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_TEMPERATURE_TARGET[23:16] is Temperature Target */ + err = cpu_rdmsr_range(info->handle, IA32_THERM_STATUS, 22, 16, &DigitalReadout); + err += cpu_rdmsr_range(info->handle, IA32_THERM_STATUS, 31, 31, &ReadingValid); + err += cpu_rdmsr_range(info->handle, MSR_TEMPERATURE_TARGET, 23, 16, &TemperatureTarget); + if(!err && ReadingValid) + { + return (int)(TemperatureTarget - DigitalReadout); + } + } + + return CPU_INVALID_VALUE; +} + +static double get_info_voltage(struct msr_info_t* info) +{ + int err; + double VIDStep; + uint64_t reg, CpuVid; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + MSR_PERF_STATUS[47:32] is Core Voltage + P-state core voltage can be computed by MSR_PERF_STATUS[37:32] * (float) 1/(2^13). */ + err = cpu_rdmsr_range(info->handle, MSR_PERF_STATUS, 47, 32, ®); + if(!err) + { + return (double) reg / (1 << 13); + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_00[6B:64][15:9] is CpuVid (Jaguar and before) + MSRC001_00[6B:64][21:14] is CpuVid (Zen) + MSRC001_0063[2:0] is P-state Status + BKDG 10h, page 49: voltage = 1.550V - 0.0125V * SviVid (SVI1) + BKDG 15h, page 50: Voltage = 1.5500 - 0.00625 * Vid[7:0] (SVI2) + SVI2 since Piledriver (Family 15h, 2nd-gen): Models 10h-1Fh Processors */ + VIDStep = ((info->id->ext_family < 0x15) || ((info->id->ext_family == 0x15) && + (info->id->ext_model < 0x10))) ? 0.0125 : 0.00625; + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, ®); + if(info->id->ext_family < 0x17) + { + err += cpu_rdmsr_range(info->handle, MSR_PSTATE_0 + (uint32_t) reg, 15, 9, &CpuVid); + } + else + { + err += cpu_rdmsr_range(info->handle, MSR_PSTATE_0 + (uint32_t) reg, 21, 14, &CpuVid); + } + if(!err && MSR_PSTATE_0 + (uint32_t) reg <= MSR_PSTATE_7) + { + return 1.550 - VIDStep * CpuVid; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_bus_clock(struct msr_info_t* info) +{ + int err; + double mult; + uint32_t addr; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Coreâ„¢ Processors (based on Intel® microarchitecture code name Ivy Bridge) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) + Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_PLATFORM_INFO[15:8] is Maximum Non-Turbo Ratio */ + err = cpu_rdmsr_range(info->handle, MSR_PLATFORM_INFO, 15, 8, ®); + if(!err) + { + return (double) info->cpu_clock / reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0061[6:4] is PstateMaxVal + PstateMaxVal is the the lowest-performance non-boosted P-state */ + addr = get_amd_last_pstate_addr(info); + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_L, 6, 4, ®); + err += get_amd_multipliers(info, addr - reg, &mult); + if(!err) + { + return (double) info->cpu_clock / mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, + uint8_t lowbit, uint64_t* result) +{ + int err; + const uint8_t bits = highbit - lowbit + 1; + + if(highbit > 63 || lowbit > highbit) + { + return set_error(ERR_INVRANGE); + } + + err = cpu_rdmsr(handle, msr_index, result); + + if(!err && bits < 64) + { + /* Show only part of register */ + *result >>= lowbit; + *result &= (1ULL << bits) - 1; + } + + return err; +} + +int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) +{ + static int err = 0, init = 0; + struct cpu_raw_data_t raw; + static struct cpu_id_t id; + static struct internal_id_info_t internal; + static struct msr_info_t info; + + if(handle == NULL) + { + set_error(ERR_HANDLE); + return CPU_INVALID_VALUE; + } + + info.handle = handle; + if(!init) + { + err = cpuid_get_raw_data(&raw); + err += cpu_ident_internal(&raw, &id, &internal); + info.cpu_clock = cpu_clock_measure(250, 1); + info.id = &id; + info.internal = &internal; + init = 1; + } + + if(err) + { + return CPU_INVALID_VALUE; + } + + switch(which) + { + case INFO_MPERF: + return perfmsr_measure(handle, IA32_MPERF); + case INFO_APERF: + return perfmsr_measure(handle, IA32_APERF); + case INFO_MIN_MULTIPLIER: + return (int)(get_info_min_multiplier(&info) * 100); + case INFO_CUR_MULTIPLIER: + return (int)(get_info_cur_multiplier(&info) * 100); + case INFO_MAX_MULTIPLIER: + return (int)(get_info_max_multiplier(&info) * 100); + case INFO_TEMPERATURE: + return get_info_temperature(&info); + case INFO_THROTTLING: + return CPU_INVALID_VALUE; + case INFO_VOLTAGE: + return (int)(get_info_voltage(&info) * 100); + case INFO_BCLK: + case INFO_BUS_CLOCK: + return (int)(get_info_bus_clock(&info) * 100); + default: + return CPU_INVALID_VALUE; + } +} + +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + int i, j; + FILE* f; + uint64_t reg; + const uint32_t* msr; + struct cpu_raw_data_t raw; + struct cpu_id_t id; + struct internal_id_info_t internal; + + if(handle == NULL) + { + return set_error(ERR_HANDLE); + } + + if(!strcmp(filename, "")) + { + f = stdout; + } + else + { + f = fopen(filename, "wt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + + if(cpuid_get_raw_data(&raw) || cpu_ident_internal(&raw, &id, &internal)) + { + return -1; + } + + fprintf(f, "CPU is %s %s, stock clock is %dMHz.\n", id.vendor_str, id.brand_str, cpu_clock_measure(250, 1)); + if(id.vendor == VENDOR_INTEL) + { + msr = intel_msr; + } + else if(id.vendor == VENDOR_AMD) + { + msr = amd_msr; + } + else + { + return set_error(ERR_CPU_UNKN); + } + + for(i = 0; msr[i] != CPU_INVALID_VALUE; i++) + { + cpu_rdmsr(handle, msr[i], ®); + fprintf(f, "msr[%#08x]=", msr[i]); + for(j = 56; j >= 0; j -= 8) + { + fprintf(f, "%02x ", (int)(reg >> j) & 0xff); + } + printf("\n"); + } + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + +#endif // RDMSR_UNSUPPORTED_OS diff --git a/src/3rdparty/libcpuid/rdtsc.c b/src/3rdparty/libcpuid/rdtsc.c new file mode 100644 index 00000000..4c810132 --- /dev/null +++ b/src/3rdparty/libcpuid/rdtsc.c @@ -0,0 +1,409 @@ +/* + * Copyright 2008 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "libcpuid.h" +#include "libcpuid_util.h" +#include "asm-bits.h" +#include "rdtsc.h" + +#ifdef _WIN32 +#include +void sys_precise_clock(uint64_t* result) +{ + double c, f; + LARGE_INTEGER freq, counter; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&freq); + c = (double) counter.QuadPart; + f = (double) freq.QuadPart; + *result = (uint64_t)(c * 1000000.0 / f); +} +#else +/* assuming Linux, Mac OS or other POSIX */ +#include +void sys_precise_clock(uint64_t* result) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + *result = (uint64_t) tv.tv_sec * (uint64_t) 1000000 + + (uint64_t) tv.tv_usec; +} +#endif /* _WIN32 */ + +/* out = a - b */ +static void mark_t_subtract(struct cpu_mark_t* a, struct cpu_mark_t* b, struct cpu_mark_t* out) +{ + out->tsc = a->tsc - b->tsc; + out->sys_clock = a->sys_clock - b->sys_clock; +} + +void cpu_tsc_mark(struct cpu_mark_t* mark) +{ + cpu_rdtsc(&mark->tsc); + sys_precise_clock(&mark->sys_clock); +} + +void cpu_tsc_unmark(struct cpu_mark_t* mark) +{ + struct cpu_mark_t temp; + cpu_tsc_mark(&temp); + mark_t_subtract(&temp, mark, mark); +} + + +int cpu_clock_by_mark(struct cpu_mark_t* mark) +{ + uint64_t result; + + /* Check if some subtraction resulted in a negative number: */ + if((mark->tsc >> 63) != 0 || (mark->sys_clock >> 63) != 0) + { + return -1; + } + + /* Divide-by-zero check: */ + if(mark->sys_clock == 0) + { + return -1; + } + + /* Check if the result fits in 32bits */ + result = mark->tsc / mark->sys_clock; + if(result > (uint64_t) 0x7fffffff) + { + return -1; + } + return (int) result; +} + +#ifdef _WIN32 +int cpu_clock_by_os(void) +{ + HKEY key; + DWORD result; + DWORD size = 4; + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ, + &key) != ERROR_SUCCESS) + { + return -1; + } + + if(RegQueryValueEx(key, TEXT("~MHz"), NULL, NULL, (LPBYTE) &result, (LPDWORD) &size) != ERROR_SUCCESS) + { + RegCloseKey(key); + return -1; + } + RegCloseKey(key); + + return (int)result; +} +#else +#ifdef __APPLE__ +#include +#include +/* Assuming Mac OS X with hw.cpufrequency sysctl */ +int cpu_clock_by_os(void) +{ + long long result = -1; + size_t size = sizeof(result); + if(sysctlbyname("hw.cpufrequency", &result, &size, NULL, 0)) + { + return -1; + } + return (int)(result / (long long) 1000000); +} +#else +/* Assuming Linux with /proc/cpuinfo */ +int cpu_clock_by_os(void) +{ + FILE* f; + char line[1024], *s; + int result; + + f = fopen("/proc/cpuinfo", "rt"); + if(!f) + { + return -1; + } + + while(fgets(line, sizeof(line), f)) + { + if(!strncmp(line, "cpu MHz", 7)) + { + s = strchr(line, ':'); + if(s && 1 == sscanf(s, ":%d.", &result)) + { + fclose(f); + return result; + } + } + } + fclose(f); + return -1; +} +#endif /* __APPLE__ */ +#endif /* _WIN32 */ + +/* Emulate doing useful CPU intensive work */ +static int busy_loop(int amount) +{ + int i, j, k, s = 0; + static volatile int data[42] = {32, 12, -1, 5, 23, 0 }; + for(i = 0; i < amount; i++) + for(j = 0; j < 65536; j++) + for(k = 0; k < 42; k++) + { + s += data[k]; + } + return s; +} + +int busy_loop_delay(int milliseconds) +{ + int cycles = 0, r = 0, first = 1; + uint64_t a, b, c; + sys_precise_clock(&a); + while(1) + { + sys_precise_clock(&c); + if((c - a) / 1000 > milliseconds) + { + return r; + } + r += busy_loop(cycles); + if(first) + { + first = 0; + } + else + { + if(c - b < 1000) + { + cycles *= 2; + } + if(c - b > 10000) + { + cycles /= 2; + } + } + b = c; + } +} + +int cpu_clock_measure(int millis, int quad_check) +{ + struct cpu_mark_t begin[4], end[4], temp, temp2; + int results[4], cycles, n, k, i, j, bi, bj, mdiff, diff, _zero = 0; + uint64_t tl; + + if(millis < 1) + { + return -1; + } + tl = millis * (uint64_t) 1000; + if(quad_check) + { + tl /= 4; + } + n = quad_check ? 4 : 1; + cycles = 1; + for(k = 0; k < n; k++) + { + cpu_tsc_mark(&begin[k]); + end[k] = begin[k]; + do + { + /* Run busy loop, and fool the compiler that we USE the garbishy + value it calculates */ + _zero |= (1 & busy_loop(cycles)); + cpu_tsc_mark(&temp); + mark_t_subtract(&temp, &end[k], &temp2); + /* If busy loop is too short, increase it */ + if(temp2.sys_clock < tl / 8) + { + cycles *= 2; + } + end[k] = temp; + } + while(end[k].sys_clock - begin[k].sys_clock < tl); + mark_t_subtract(&end[k], &begin[k], &temp); + results[k] = cpu_clock_by_mark(&temp); + } + if(n == 1) + { + return results[0]; + } + mdiff = 0x7fffffff; + bi = bj = -1; + for(i = 0; i < 4; i++) + { + for(j = i + 1; j < 4; j++) + { + diff = results[i] - results[j]; + if(diff < 0) + { + diff = -diff; + } + if(diff < mdiff) + { + mdiff = diff; + bi = i; + bj = j; + } + } + } + if(results[bi] == -1) + { + return -1; + } + return (results[bi] + results[bj] + _zero) / 2; +} + + +static void adjust_march_ic_multiplier(const struct cpu_id_t* id, int* numerator, int* denom) +{ + /* + * for cpu_clock_by_ic: we need to know how many clocks does a typical ADDPS instruction + * take, when issued in rapid succesion without dependencies. The whole idea of + * cpu_clock_by_ic was that this is easy to determine, at least it was back in 2010. Now + * it's getting progressively more hairy, but here are the current measurements: + * + * 1. For CPUs with 64-bit SSE units, ADDPS issue rate is 0.5 IPC (one insn in 2 clocks) + * 2. For CPUs with 128-bit SSE units, issue rate is exactly 1.0 IPC + * 3. For Bulldozer and later, it is 1.4 IPC (we multiply by 5/7) + * 4. For Skylake and later, it is 1.6 IPC (we multiply by 5/8) + */ + // + if(id->sse_size < 128) + { + debugf(1, "SSE execution path is 64-bit\n"); + // on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC; + // the resulting value must be multiplied by 2: + *numerator = 2; + } + else + { + debugf(1, "SSE execution path is 128-bit\n"); + } + // + // Bulldozer or later: assume 1.4 IPC + if(id->vendor == VENDOR_AMD && id->ext_family >= 21) + { + debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n"); + *numerator = 5; + *denom = 7; // multiply by 5/7, to divide by 1.4 + } + // + // Skylake or later: assume 1.6 IPC + if(id->vendor == VENDOR_INTEL && id->ext_model >= 94) + { + debugf(1, "cpu_clock_by_ic: Skylake (or later) detected, dividing result by 1.6\n"); + *numerator = 5; + *denom = 8; // to divide by 1.6, multiply by 5/8 + } +} + +int cpu_clock_by_ic(int millis, int runs) +{ + int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c; + struct cpu_id_t* id; + uint64_t t0, t1, tl, hz; + int multiplier_numerator = 1, multiplier_denom = 1; + if(millis <= 0 || runs <= 0) + { + return -2; + } + id = get_cached_cpuid(); + // if there aren't SSE instructions - we can't run the test at all + if(!id || !id->flags[CPU_FEATURE_SSE]) + { + return -1; + } + // + adjust_march_ic_multiplier(id, &multiplier_numerator, &multiplier_denom); + // + tl = millis * 125; // (*1000 / 8) + cycles_inner = 128; + cycles_outer = 1; + do + { + if(cycles_inner < 1000000000) + { + cycles_inner *= 2; + } + else + { + cycles_outer *= 2; + } + sys_precise_clock(&t0); + for(i = 0; i < cycles_outer; i++) + { + busy_sse_loop(cycles_inner); + } + sys_precise_clock(&t1); + } + while(t1 - t0 < tl); + debugf(2, "inner: %d, outer: %d\n", cycles_inner, cycles_outer); + for(ri = 0; ri < runs; ri++) + { + sys_precise_clock(&t0); + c = 0; + do + { + c++; + for(i = 0; i < cycles_outer; i++) + { + busy_sse_loop(cycles_inner); + } + sys_precise_clock(&t1); + } + while(t1 - t0 < tl * (uint64_t) 8); + // cpu_Hz = cycles_inner * cycles_outer * 256 / (t1 - t0) * 1000000 + debugf(2, "c = %d, td = %d\n", c, (int)(t1 - t0)); + hz = ((uint64_t) cycles_inner * (uint64_t) 256 + 12) * + (uint64_t) cycles_outer * (uint64_t) multiplier_numerator * (uint64_t) c * (uint64_t) 1000000 + / ((t1 - t0) * (uint64_t) multiplier_denom); + cur_value = (int)(hz / 1000000); + if(cur_value > max_value) + { + max_value = cur_value; + } + } + return max_value; +} + +int cpu_clock(void) +{ + int result; + result = cpu_clock_by_os(); + if(result <= 0) + { + result = cpu_clock_measure(200, 1); + } + return result; +} diff --git a/src/3rdparty/libcpuid/rdtsc.h b/src/3rdparty/libcpuid/rdtsc.h new file mode 100644 index 00000000..7a3307d9 --- /dev/null +++ b/src/3rdparty/libcpuid/rdtsc.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __RDTSC_H__ +#define __RDTSC_H__ + +void sys_precise_clock(uint64_t* result); +int busy_loop_delay(int milliseconds); + + +#endif /* __RDTSC_H__ */ diff --git a/src/3rdparty/libcpuid/recog_amd.c b/src/3rdparty/libcpuid/recog_amd.c index c7f48000..1c851901 100644 --- a/src/3rdparty/libcpuid/recog_amd.c +++ b/src/3rdparty/libcpuid/recog_amd.c @@ -58,6 +58,238 @@ enum _amd_model_codes_t _1600, }; + +const struct match_entry_t cpudb_amd[] = +{ + { -1, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD CPU" }, + + /* 486 and the likes */ + { 4, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 486" }, + { 4, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2" }, + { 4, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2WB" }, + { 4, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4" }, + { 4, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4WB" }, + + /* Pentia clones */ + { 5, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 586" }, + { 5, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" }, + { 5, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" }, + { 5, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" }, + { 5, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" }, + + /* The K6 */ + { 5, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" }, + { 5, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" }, + + { 5, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2" }, + { 5, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-III" }, + { 5, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" }, + { 5, 11, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" }, + { 5, 12, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" }, + { 5, 13, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2+" }, + + /* Athlon et al. */ + { 6, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" }, + { 6, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" }, + { 6, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Duron (Spitfire)" }, + { 6, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (ThunderBird)" }, + + { 6, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon (Palomino)" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Palomino)" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Palomino)" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP" }, + + { 6, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon XP" }, + { 6, 7, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Morgan)" }, + + { 6, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon XP (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Applebred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Thoroughbred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ , 0, "Mobile Athlon (T-Bred)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ | _LV_, 0, "Mobile Athlon (T-Bred)" }, + + { 6, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP (Barton)" }, + { 6, 10, -1, -1, -1, 1, 512, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Barton)" }, + { 6, 10, -1, -1, -1, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron (Barton)" }, + { 6, 10, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thorton)" }, + { 6, 10, -1, -1, -1, 1, 256, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Thorton)" }, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Barton)" }, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ , 0, "Mobile Athlon (Barton)" }, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ | _LV_, 0, "Mobile Athlon (Barton)" }, + + /* K8 Architecture */ + { 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown K8" }, + { 15, -1, -1, 16, -1, 1, -1, -1, NC, 0 , 0, "Unknown K9" }, + + { 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown A64" }, + { 15, -1, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" }, + { 15, -1, -1, 15, -1, 2, -1, -1, NC, OPTERON_ | _X2 , 0, "Opteron (Dual Core)" }, + { 15, 3, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" }, + { 15, 3, -1, 15, -1, 2, -1, -1, NC, OPTERON_ | _X2 , 0, "Opteron (Dual Core)" }, + { 15, -1, -1, 15, -1, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (512K)" }, + { 15, -1, -1, 15, -1, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (1024K)" }, + { 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_ | _FX , 0, "Athlon FX" }, + { 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_ | _64_ | _FX , 0, "Athlon 64 FX" }, + { 15, 3, -1, 15, 35, 2, -1, -1, NC, ATHLON_ | _64_ | _FX , 0, "Athlon 64 FX X2 (Toledo)" }, + { 15, -1, -1, 15, -1, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (512K)" }, + { 15, -1, -1, 15, -1, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (1024K)" }, + { 15, -1, -1, 15, -1, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (512K)" }, + { 15, -1, -1, 15, -1, 1, 1024, -1, NC, TURION_ | _64_ , 0, "Turion 64 (1024K)" }, + { 15, -1, -1, 15, -1, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion 64 X2 (512K)" }, + { 15, -1, -1, 15, -1, 2, 1024, -1, NC, TURION_ | _X2 , 0, "Turion 64 X2 (1024K)" }, + { 15, -1, -1, 15, -1, 1, 128, -1, NC, SEMPRON_ , 0, "A64 Sempron (128K)" }, + { 15, -1, -1, 15, -1, 1, 256, -1, NC, SEMPRON_ , 0, "A64 Sempron (256K)" }, + { 15, -1, -1, 15, -1, 1, 512, -1, NC, SEMPRON_ , 0, "A64 Sempron (512K)" }, + { 15, -1, -1, 15, 0x4f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/512K)" }, + { 15, -1, -1, 15, 0x5f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/512K)" }, + { 15, -1, -1, 15, 0x2f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Venice/512K)" }, + { 15, -1, -1, 15, 0x2c, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Venice/512K)" }, + { 15, -1, -1, 15, 0x1f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Winchester/512K)" }, + { 15, -1, -1, 15, 0x0c, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Newcastle/512K)" }, + { 15, -1, -1, 15, 0x27, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/512K)" }, + { 15, -1, -1, 15, 0x37, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/512K)" }, + { 15, -1, -1, 15, 0x04, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (ClawHammer/512K)" }, + + { 15, -1, -1, 15, 0x5f, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/1024K)" }, + { 15, -1, -1, 15, 0x27, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/1024K)" }, + { 15, -1, -1, 15, 0x04, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (ClawHammer/1024K)" }, + + { 15, -1, -1, 15, 0x4b, 2, 256, -1, NC, SEMPRON_ , 0, "Athlon 64 X2 (Windsor/256K)" }, + + { 15, -1, -1, 15, 0x23, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Toledo/512K)" }, + { 15, -1, -1, 15, 0x4b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/512K)" }, + { 15, -1, -1, 15, 0x43, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/512K)" }, + { 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Brisbane/512K)" }, + { 15, -1, -1, 15, 0x2b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Manchester/512K)"}, + + { 15, -1, -1, 15, 0x23, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Toledo/1024K)" }, + { 15, -1, -1, 15, 0x43, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/1024K)" }, + + { 15, -1, -1, 15, 0x08, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/128K)"}, + { 15, -1, -1, 15, 0x08, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/256K)"}, + { 15, -1, -1, 15, 0x0c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Paris)" }, + { 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" }, + { 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" }, + { 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/128K)"}, + { 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/256K)"}, + { 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" }, + { 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" }, + { 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Albany/128K)"}, + { 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Albany/256K)"}, + { 15, -1, -1, 15, 0x2f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" }, + { 15, -1, -1, 15, 0x2f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" }, + { 15, -1, -1, 15, 0x4f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" }, + { 15, -1, -1, 15, 0x4f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" }, + { 15, -1, -1, 15, 0x5f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" }, + { 15, -1, -1, 15, 0x5f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" }, + { 15, -1, -1, 15, 0x6b, 2, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/256K)"}, + { 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/512K)"}, + { 15, -1, -1, 15, 0x7f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/256K)" }, + { 15, -1, -1, 15, 0x7f, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/512K)" }, + { 15, -1, -1, 15, 0x4c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Keene/256K)"}, + { 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Keene/512K)"}, + { 15, -1, -1, 15, -1, 2, -1, -1, NC, SEMPRON_ , 0, "Sempron Dual Core" }, + + { 15, -1, -1, 15, 0x24, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Lancaster/512K)" }, + { 15, -1, -1, 15, 0x24, 1, 1024, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Lancaster/1024K)" }, + { 15, -1, -1, 15, 0x48, 2, 256, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Taylor)" }, + { 15, -1, -1, 15, 0x48, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Trinidad)" }, + { 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Richmond)" }, + { 15, -1, -1, 15, 0x68, 2, 256, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Tyler/256K)" }, + { 15, -1, -1, 15, 0x68, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Tyler/512K)" }, + { 15, -1, -1, 17, 3, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Griffin/512K)" }, + { 15, -1, -1, 17, 3, 2, 1024, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Griffin/1024K)" }, + + /* K10 Architecture (2007) */ + { 15, -1, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Unknown AMD Phenom" }, + { 15, 2, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Phenom" }, + { 15, 2, -1, 16, -1, 3, -1, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman)" }, + { 15, 2, -1, 16, -1, 4, -1, -1, PHENOM, 0 , 0, "Phenom X4 (Agena)" }, + { 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/256K)" }, + { 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/512K)" }, + { 15, 2, -1, 16, -1, 4, 128, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/128K)" }, + { 15, 2, -1, 16, -1, 4, 256, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/256K)" }, + { 15, 2, -1, 16, -1, 4, 512, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/512K)" }, + { 15, 2, -1, 16, -1, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon X2 (Kuma)" }, + /* Phenom II derivates: */ + { 15, 4, -1, 16, -1, 4, -1, -1, NC, 0 , 0, "Phenom (Deneb-based)" }, + { 15, 4, -1, 16, -1, 1, 1024, -1, NC, SEMPRON_ , 0, "Sempron (Sargas)" }, + { 15, 4, -1, 16, -1, 2, 512, -1, PHENOM2, 0 , 0, "Phenom II X2 (Callisto)" }, + { 15, 4, -1, 16, -1, 3, 512, -1, PHENOM2, 0 , 0, "Phenom II X3 (Heka)" }, + { 15, 4, -1, 16, -1, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4" }, + { 15, 4, -1, 16, 4, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" }, + { 15, 5, -1, 16, 5, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" }, + { 15, 4, -1, 16, 10, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Zosma)" }, + { 15, 4, -1, 16, 10, 6, 512, -1, PHENOM2, 0 , 0, "Phenom II X6 (Thuban)" }, + /* Athlon II derivates: */ + { 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_ | _X2 , 0, "Athlon II (Champlain)" }, + { 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon II X2 (Regor)" }, + { 15, 6, -1, 16, 6, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon II X2 (Regor)" }, + { 15, 5, -1, 16, 5, 3, 512, -1, NC, ATHLON_ | _64_ | _X3 , 0, "Athlon II X3 (Rana)" }, + { 15, 5, -1, 16, 5, 4, 512, -1, NC, ATHLON_ | _64_ | _X4 , 0, "Athlon II X4 (Propus)" }, + /* Llano APUs (2011): */ + { 15, 1, -1, 18, 1, 2, -1, -1, FUSION_EA, 0 , 0, "Llano X2" }, + { 15, 1, -1, 18, 1, 3, -1, -1, FUSION_EA, 0 , 0, "Llano X3" }, + { 15, 1, -1, 18, 1, 4, -1, -1, FUSION_EA, 0 , 0, "Llano X4" }, + + /* Family 14h: Bobcat Architecture (2011) */ + { 15, 2, -1, 20, -1, 1, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario" }, + { 15, 2, -1, 20, -1, 2, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario (Dual-core)" }, + { 15, 1, -1, 20, -1, 1, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate" }, + { 15, 1, -1, 20, -1, 2, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate (Dual-core)" }, + { 15, 2, -1, 20, -1, 2, -1, -1, FUSION_Z, 0 , 0, "Brazos Desna (Dual-core)" }, + + /* Family 15h: Bulldozer Architecture (2011) */ + { 15, -1, -1, 21, 0, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" }, + { 15, -1, -1, 21, 1, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" }, + { 15, -1, -1, 21, 1, 6, -1, -1, NC, 0 , 0, "Bulldozer X3" }, + { 15, -1, -1, 21, 1, 8, -1, -1, NC, 0 , 0, "Bulldozer X4" }, + /* 2nd-gen, Piledriver core (2012): */ + { 15, -1, -1, 21, 2, 4, -1, -1, NC, 0 , 0, "Vishera X2" }, + { 15, -1, -1, 21, 2, 6, -1, -1, NC, 0 , 0, "Vishera X3" }, + { 15, -1, -1, 21, 2, 8, -1, -1, NC, 0 , 0, "Vishera X4" }, + { 15, 0, -1, 21, 16, 2, -1, -1, FUSION_A, 0 , 0, "Trinity X2" }, + { 15, 0, -1, 21, 16, 4, -1, -1, FUSION_A, 0 , 0, "Trinity X4" }, + { 15, 3, -1, 21, 19, 2, -1, -1, FUSION_A, 0 , 0, "Richland X2" }, + { 15, 3, -1, 21, 19, 4, -1, -1, FUSION_A, 0 , 0, "Richland X4" }, + /* 3rd-gen, Steamroller core (2014): */ + { 15, 0, -1, 21, 48, 2, -1, -1, FUSION_A, 0 , 0, "Kaveri X2" }, + { 15, 0, -1, 21, 48, 4, -1, -1, FUSION_A, 0 , 0, "Kaveri X4" }, + { 15, 8, -1, 21, 56, 4, -1, -1, FUSION_A, 0 , 0, "Godavari X4" }, + /* 4th-gen, Excavator core (2015): */ + { 15, 1, -1, 21, 96, 2, -1, -1, FUSION_A, 0 , 0, "Carrizo X2" }, + { 15, 1, -1, 21, 96, 4, -1, -1, FUSION_A, 0 , 0, "Carrizo X4" }, + { 15, 5, -1, 21, 101, 2, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X2" }, + { 15, 5, -1, 21, 101, 4, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X4" }, + { 15, 0, -1, 21, 112, 2, -1, -1, FUSION_A, 0 , 0, "Stoney Ridge X2" }, + { 15, 0, -1, 21, 112, 2, -1, -1, FUSION_E, 0 , 0, "Stoney Ridge X2" }, + + /* Family 16h: Jaguar Architecture (2013) */ + { 15, 0, -1, 22, 0, 2, -1, -1, FUSION_A, 0 , 0, "Kabini X2" }, + { 15, 0, -1, 22, 0, 4, -1, -1, FUSION_A, 0 , 0, "Kabini X4" }, + /* 2nd-gen, Puma core (2013): */ + { 15, 0, -1, 22, 48, 2, -1, -1, FUSION_E, 0 , 0, "Mullins X2" }, + { 15, 0, -1, 22, 48, 4, -1, -1, FUSION_A, 0 , 0, "Mullins X4" }, + + /* Family 17h: Zen Architecture (2017) */ + { 15, -1, -1, 23, 1, 8, -1, -1, NC, 0 , 0, "Ryzen 7" }, + { 15, -1, -1, 23, 1, 6, -1, -1, NC, 0 , _1600, "Ryzen 5" }, + { 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1500, "Ryzen 5" }, + { 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1400, "Ryzen 5" }, + { 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Ryzen 3" }, + //{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Raven Ridge" }, //TBA + + /* Newer Opterons: */ + { 15, 9, -1, 22, 9, 8, -1, -1, NC, OPTERON_ , 0, "Magny-Cours Opteron" }, +}; + + static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { const struct feature_map_t matchtable_edx81[] = @@ -190,10 +422,217 @@ static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id } } +static int amd_has_turion_modelname(const char* bs) +{ + /* We search for something like TL-60. Ahh, I miss regexes...*/ + int i, l, k; + char code[3] = {0}; + const char* codes[] = { "ML", "MT", "MK", "TK", "TL", "RM", "ZM", "" }; + l = (int) strlen(bs); + for(i = 3; i < l - 2; i++) + { + if(bs[i] == '-' && + isupper(bs[i - 1]) && isupper(bs[i - 2]) && !isupper(bs[i - 3]) && + isdigit(bs[i + 1]) && isdigit(bs[i + 2]) && !isdigit(bs[i + 3])) + { + code[0] = bs[i - 2]; + code[1] = bs[i - 1]; + for(k = 0; codes[k][0]; k++) + if(!strcmp(codes[k], code)) + { + return 1; + } + } + } + return 0; +} + +static struct amd_code_and_bits_t decode_amd_codename_part1(const char* bs) +{ + amd_code_t code = NC; + uint64_t bits = 0; + struct amd_code_and_bits_t result; + + if(strstr(bs, "Dual Core") || + strstr(bs, "Dual-Core") || + strstr(bs, " X2 ")) + { + bits |= _X2; + } + if(strstr(bs, " X4 ")) + { + bits |= _X4; + } + if(strstr(bs, " X3 ")) + { + bits |= _X3; + } + if(strstr(bs, "Opteron")) + { + bits |= OPTERON_; + } + if(strstr(bs, "Phenom")) + { + code = (strstr(bs, "II")) ? PHENOM2 : PHENOM; + } + if(amd_has_turion_modelname(bs)) + { + bits |= TURION_; + } + if(strstr(bs, "Athlon(tm)")) + { + bits |= ATHLON_; + } + if(strstr(bs, "Sempron(tm)")) + { + bits |= SEMPRON_; + } + if(strstr(bs, "Duron")) + { + bits |= DURON_; + } + if(strstr(bs, " 64 ")) + { + bits |= _64_; + } + if(strstr(bs, " FX")) + { + bits |= _FX; + } + if(strstr(bs, " MP")) + { + bits |= _MP_; + } + if(strstr(bs, "Athlon(tm) 64") || strstr(bs, "Athlon(tm) II X") || match_pattern(bs, "Athlon(tm) X#")) + { + bits |= ATHLON_ | _64_; + } + if(strstr(bs, "Turion")) + { + bits |= TURION_; + } + + if(strstr(bs, "mobile") || strstr(bs, "Mobile")) + { + bits |= MOBILE_; + } + + if(strstr(bs, "XP")) + { + bits |= _XP_; + } + if(strstr(bs, "XP-M")) + { + bits |= _M_; + } + if(strstr(bs, "(LV)")) + { + bits |= _LV_; + } + if(strstr(bs, " APU ")) + { + bits |= _APU_; + } + + if(match_pattern(bs, "C-##")) + { + code = FUSION_C; + } + if(match_pattern(bs, "E-###")) + { + code = FUSION_E; + } + if(match_pattern(bs, "Z-##")) + { + code = FUSION_Z; + } + if(match_pattern(bs, "[EA]#-####")) + { + code = FUSION_EA; + } + + result.code = code; + result.bits = bits; + return result; +} + +static int decode_amd_ryzen_model_code(const char* bs) +{ + const struct + { + int model_code; + const char* match_str; + } patterns[] = + { + { _1600, "1600" }, + { _1500, "1500" }, + { _1400, "1400" }, + }; + int i; + + for(i = 0; i < COUNT_OF(patterns); i++) + if(strstr(bs, patterns[i].match_str)) + { + return patterns[i].model_code; + } + // + return 0; +} + +static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data, + struct internal_id_info_t* internal) +{ + struct amd_code_and_bits_t code_and_bits = decode_amd_codename_part1(data->brand_str); + int i = 0; + char* code_str = NULL; + int model_code; + + for(i = 0; i < COUNT_OF(amd_code_str); i++) + { + if(code_and_bits.code == amd_code_str[i].code) + { + code_str = amd_code_str[i].str; + break; + } + } + if(/*code == ATHLON_64_X2*/ match_all(code_and_bits.bits, ATHLON_ | _64_ | _X2) && data->l2_cache < 512) + { + code_and_bits.bits &= ~(ATHLON_ | _64_); + code_and_bits.bits |= SEMPRON_; + } + if(code_str) + { + debugf(2, "Detected AMD brand code: %d (%s)\n", code_and_bits.code, code_str); + } + else + { + debugf(2, "Detected AMD brand code: %d\n", code_and_bits.code); + } + + if(code_and_bits.bits) + { + debugf(2, "Detected AMD bits: "); + debug_print_lbits(2, code_and_bits.bits); + } + // is it Ryzen? if so, we need to detect discern between the four-core 1400/1500 (Ryzen 5) and the four-core Ryzen 3: + model_code = (data->ext_family == 23) ? decode_amd_ryzen_model_code(data->brand_str) : 0; + + internal->code.amd = code_and_bits.code; + internal->bits = code_and_bits.bits; + internal->score = match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code_and_bits.code, + code_and_bits.bits, model_code); +} + int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal) { load_amd_features(raw, data); decode_amd_cache_info(raw, data); decode_amd_number_of_cores(raw, data); + decode_amd_codename(raw, data, internal); return 0; } + +void cpuid_get_list_amd(struct cpu_list_t* list) +{ + generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list); +} diff --git a/src/3rdparty/libcpuid/recog_amd.h b/src/3rdparty/libcpuid/recog_amd.h index 19f839ba..34e89598 100644 --- a/src/3rdparty/libcpuid/recog_amd.h +++ b/src/3rdparty/libcpuid/recog_amd.h @@ -27,5 +27,6 @@ #define __RECOG_AMD_H__ int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal); +void cpuid_get_list_amd(struct cpu_list_t* list); #endif /* __RECOG_AMD_H__ */ diff --git a/src/3rdparty/libcpuid/recog_intel.c b/src/3rdparty/libcpuid/recog_intel.c index 850bbb56..3e4707ac 100644 --- a/src/3rdparty/libcpuid/recog_intel.c +++ b/src/3rdparty/libcpuid/recog_intel.c @@ -66,6 +66,298 @@ enum _intel_model_t }; typedef enum _intel_model_t intel_model_t; +const struct match_entry_t cpudb_intel[] = +{ + { -1, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Intel CPU" }, + + /* i486 */ + { 4, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown i486" }, + { 4, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX-25/33" }, + { 4, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX-50" }, + { 4, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SX" }, + { 4, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX2" }, + { 4, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SL" }, + { 4, 5, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SX2" }, + { 4, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX2 WriteBack" }, + { 4, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX4" }, + { 4, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX4 WriteBack" }, + + /* All Pentia: + Pentium 1 */ + { 5, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium" }, + { 5, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium A-Step" }, + { 5, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.8u)" }, + { 5, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" }, + { 5, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium OverDrive" }, + { 5, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" }, + { 5, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" }, + { 5, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium MMX (0.25u)" }, + + /* Pentium 2 / 3 / M / Conroe / whatsnext - all P6 based. */ + { 6, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown P6" }, + { 6, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium Pro" }, + { 6, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium Pro" }, + { 6, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium II (Klamath)" }, + { 6, 5, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium II (Deschutes)" }, + { 6, 5, -1, -1, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile Pentium II (Tonga)"}, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium II (Dixon)" }, + + { 6, 3, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Klamath)" }, + { 6, 5, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Drake)" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Dixon)" }, + + { 6, 5, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-II Celeron (Covington)" }, + { 6, 6, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-II Celeron (Mendocino)" }, + + /* -------------------------------------------------- */ + + { 6, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Katmai)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Coppermine)"}, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Coppermine)"}, + { 6, 11, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Tualatin)" }, + + { 6, 7, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Tanner)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Cascades)" }, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Cascades)" }, + { 6, 11, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Tualatin)" }, + + { 6, 7, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Katmai)" }, + { 6, 8, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Coppermine)" }, + { 6, 10, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Coppermine)" }, + { 6, 11, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Tualatin)" }, + + /* Netburst based (Pentium 4 and later) + classic P4s */ + { 15, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium 4" }, + { 15, -1, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "Unknown P-4 Celeron" }, + { 15, -1, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Unknown Xeon" }, + + { 15, 0, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Willamette)" }, + { 15, 1, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Willamette)" }, + { 15, 2, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Northwood)" }, + { 15, 3, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Prescott)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Prescott)" }, + { 15, 6, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Cedar Mill)" }, + { 15, 0, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Willamette)" }, + { 15, 1, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Willamette)" }, + { 15, 2, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Northwood)" }, + { 15, 3, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Prescott)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Prescott)" }, + { 15, 6, -1, 15, -1, 1, -1, -1, NC, MOBILE_ | PENTIUM_, 0, "Mobile P-4 (Cedar Mill)" }, + + /* server CPUs */ + { 15, 0, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Foster)" }, + { 15, 1, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Foster)" }, + { 15, 2, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Prestonia)" }, + { 15, 2, -1, 15, -1, 1, -1, -1, NC, XEON_ | _MP_ , 0, "Xeon (Gallatin)" }, + { 15, 3, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Nocona)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Nocona)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, IRWIN, XEON_ , 0, "Xeon (Irwindale)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, NC, XEON_ | _MP_ , 0, "Xeon (Cranford)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, POTOMAC, XEON_ , 0, "Xeon (Potomac)" }, + { 15, 6, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Dempsey)" }, + + /* Pentium Ds */ + { 15, 4, 4, 15, -1, 1, -1, -1, NC, 0 , 0, "Pentium D (SmithField)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, PENTIUM_D, 0 , 0, "Pentium D (SmithField)" }, + { 15, 4, 7, 15, -1, 1, -1, -1, NC, 0 , 0, "Pentium D (SmithField)" }, + { 15, 6, -1, 15, -1, 1, -1, -1, PENTIUM_D, 0 , 0, "Pentium D (Presler)" }, + + /* Celeron and Celeron Ds */ + { 15, 1, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron (Willamette)" }, + { 15, 2, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron (Northwood)" }, + { 15, 3, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Prescott)" }, + { 15, 4, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Prescott)" }, + { 15, 6, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Cedar Mill)" }, + + /* -------------------------------------------------- */ + /* Intel Core microarchitecture - P6-based */ + + { 6, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium M" }, + { 6, 9, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Unknown Pentium M" }, + { 6, 9, -1, -1, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium M (Banias)" }, + { 6, 9, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Pentium M (Banias)" }, + { 6, 9, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "Celeron M" }, + { 6, 13, -1, -1, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium M (Dothan)" }, + { 6, 13, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Pentium M (Dothan)" }, + { 6, 13, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "Celeron M" }, + + { 6, 12, -1, -1, -1, -1, -1, -1, NC, ATOM_ , 0, "Unknown Atom" }, + { 6, 12, -1, -1, -1, -1, -1, -1, DIAMONDVILLE, ATOM_, 0, "Atom (Diamondville)" }, + { 6, 12, -1, -1, -1, -1, -1, -1, SILVERTHORNE, ATOM_, 0, "Atom (Silverthorne)" }, + { 6, 12, -1, -1, -1, -1, -1, -1, CEDARVIEW, ATOM_ , 0, "Atom (Cedarview)" }, + { 6, 6, -1, -1, -1, -1, -1, -1, CEDARVIEW, ATOM_ , 0, "Atom (Cedarview)" }, + { 6, 12, -1, -1, -1, -1, -1, -1, PINEVIEW, ATOM_ , 0, "Atom (Pineview)" }, + + /* -------------------------------------------------- */ + + { 6, 14, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Yonah" }, + { 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, 0 , 0, "Yonah (Core Solo)" }, + { 6, 14, -1, -1, -1, 2, -1, -1, CORE_DUO, 0 , 0, "Yonah (Core Duo)" }, + { 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, MOBILE_, 0, "Yonah (Core Solo)" }, + { 6, 14, -1, -1, -1, 2, -1, -1, CORE_DUO , MOBILE_, 0, "Yonah (Core Duo)" }, + { 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, 0 , 0, "Yonah (Core Solo)" }, + + { 6, 15, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Core 2" }, + { 6, 15, -1, -1, -1, 2, 4096, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo)" }, + { 6, 15, -1, -1, -1, 2, 1024, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo) 1024K" }, + { 6, 15, -1, -1, -1, 2, 512, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo) 512K" }, + { 6, 15, -1, -1, -1, 4, -1, -1, QUAD_CORE, 0 , 0, "Kentsfield (Core 2 Quad)" }, + { 6, 15, -1, -1, -1, 4, 4096, -1, QUAD_CORE, 0 , 0, "Kentsfield (Core 2 Quad)" }, + { 6, 15, -1, -1, -1, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" }, + { 6, 15, -1, -1, -1, 2, 2048, -1, CORE_DUO, 0 , 0, "Allendale (Core 2 Duo)" }, + { 6, 15, -1, -1, -1, 2, -1, -1, MOBILE_CORE_DUO, 0, 0, "Merom (Core 2 Duo)" }, + { 6, 15, -1, -1, -1, 2, 2048, -1, MEROM, 0 , 0, "Merom (Core 2 Duo) 2048K" }, + { 6, 15, -1, -1, -1, 2, 4096, -1, MEROM, 0 , 0, "Merom (Core 2 Duo) 4096K" }, + + { 6, 15, -1, -1, 15, 1, -1, -1, NC, CELERON_ , 0, "Conroe-L (Celeron)" }, + { 6, 6, -1, -1, 22, 1, -1, -1, NC, CELERON_ , 0, "Conroe-L (Celeron)" }, + { 6, 15, -1, -1, 15, 2, -1, -1, NC, CELERON_ , 0, "Conroe-L (Allendale)" }, + { 6, 6, -1, -1, 22, 2, -1, -1, NC, CELERON_ , 0, "Conroe-L (Allendale)" }, + + + { 6, 6, -1, -1, 22, 1, -1, -1, NC, 0 , 0, "Unknown Core ?" }, + { 6, 7, -1, -1, 23, 1, -1, -1, NC, 0 , 0, "Unknown Core ?" }, + { 6, 6, -1, -1, 22, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" }, + { 6, 7, -1, -1, 23, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" }, + + { 6, 7, -1, -1, 23, 1, -1, -1, CORE_SOLO , 0, 0, "Unknown Core 45nm" }, + { 6, 7, -1, -1, 23, 1, -1, -1, CORE_DUO , 0, 0, "Unknown Core 45nm" }, + { 6, 7, -1, -1, 23, 2, 1024, -1, WOLFDALE , 0, 0, "Celeron Wolfdale 1M" }, + { 6, 7, -1, -1, 23, 2, 2048, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 2M" }, + { 6, 7, -1, -1, 23, 2, 3072, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 3M" }, + { 6, 7, -1, -1, 23, 2, 6144, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 6M" }, + { 6, 7, -1, -1, 23, 1, -1, -1, MOBILE_CORE_DUO , 0, 0, "Penryn (Core 2 Duo)" }, + { 6, 7, -1, -1, 23, 2, 1024, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo)" }, + { 6, 7, -1, -1, 23, 2, 3072, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo) 3M" }, + { 6, 7, -1, -1, 23, 2, 6144, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo) 6M" }, + { 6, 7, -1, -1, 23, 4, 2048, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 2M"}, + { 6, 7, -1, -1, 23, 4, 3072, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 3M"}, + { 6, 7, -1, -1, 23, 4, 6144, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 6M"}, + + /* Core microarchitecture-based Xeons: */ + { 6, 14, -1, -1, 14, 1, -1, -1, NC, XEON_ , 0, "Xeon LV" }, + { 6, 15, -1, -1, 15, 2, 4096, -1, NC, XEON_ , _5100, "Xeon (Woodcrest)" }, + { 6, 15, -1, -1, 15, 2, 2048, -1, NC, XEON_ , _3000, "Xeon (Conroe/2M)" }, + { 6, 15, -1, -1, 15, 2, 4096, -1, NC, XEON_ , _3000, "Xeon (Conroe/4M)" }, + { 6, 15, -1, -1, 15, 4, 4096, -1, NC, XEON_ , X3200, "Xeon (Kentsfield)" }, + { 6, 15, -1, -1, 15, 4, 4096, -1, NC, XEON_ , _5300, "Xeon (Clovertown)" }, + { 6, 7, -1, -1, 23, 2, 6144, -1, NC, XEON_ , _3100, "Xeon (Wolfdale)" }, + { 6, 7, -1, -1, 23, 2, 6144, -1, NC, XEON_ , _5200, "Xeon (Wolfdale DP)" }, + { 6, 7, -1, -1, 23, 4, 6144, -1, NC, XEON_ , _5400, "Xeon (Harpertown)" }, + { 6, 7, -1, -1, 23, 4, 3072, -1, NC, XEON_ , X3300, "Xeon (Yorkfield/3M)" }, + { 6, 7, -1, -1, 23, 4, 6144, -1, NC, XEON_ , X3300, "Xeon (Yorkfield/6M)" }, + + /* Nehalem CPUs (45nm): */ + { 6, 10, -1, -1, 26, 4, -1, -1, GAINESTOWN, XEON_ , 0, "Gainestown (Xeon)" }, + { 6, 10, -1, -1, 26, 4, -1, 4096, GAINESTOWN, XEON_ , 0, "Gainestown 4M (Xeon)" }, + { 6, 10, -1, -1, 26, 4, -1, 8192, GAINESTOWN, XEON_ , 0, "Gainestown 8M (Xeon)" }, + { 6, 10, -1, -1, 26, 4, -1, -1, NC, XEON_ | _7 , 0, "Bloomfield (Xeon)" }, + { 6, 10, -1, -1, 26, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Bloomfield (Core i7)" }, + { 6, 10, -1, -1, 30, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Lynnfield (Core i7)" }, + { 6, 5, -1, -1, 37, 4, -1, 8192, NC, CORE_ | _I_ | _5 , 0, "Lynnfield (Core i5)" }, + + /* Westmere CPUs (32nm): */ + { 6, 5, -1, -1, 37, 2, -1, -1, NC, 0 , 0, "Unknown Core i3/i5" }, + { 6, 12, -1, -1, 44, -1, -1, -1, WESTMERE, XEON_ , 0, "Westmere (Xeon)" }, + { 6, 12, -1, -1, 44, -1, -1, 12288, WESTMERE, XEON_ , 0, "Gulftown (Xeon)" }, + { 6, 12, -1, -1, 44, 4, -1, 12288, NC, CORE_ | _I_ | _7 , 0, "Gulftown (Core i7)" }, + { 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_ | _I_ | _5 , 0, "Clarkdale (Core i5)" }, + { 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_ | _I_ | _3 , 0, "Clarkdale (Core i3)" }, + { 6, 5, -1, -1, 37, 2, -1, -1, NC, PENTIUM_ , 0, "Arrandale" }, + { 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_ | _I_ | _7 , 0, "Arrandale (Core i7)" }, + { 6, 5, -1, -1, 37, 2, -1, 3072, NC, CORE_ | _I_ | _5 , 0, "Arrandale (Core i5)" }, + { 6, 5, -1, -1, 37, 2, -1, 3072, NC, CORE_ | _I_ | _3 , 0, "Arrandale (Core i3)" }, + + /* Sandy Bridge CPUs (32nm): */ + { 6, 10, -1, -1, 42, -1, -1, -1, NC, 0 , 0, "Unknown Sandy Bridge" }, + { 6, 10, -1, -1, 42, -1, -1, -1, NC, XEON_ , 0, "Sandy Bridge (Xeon)" }, + { 6, 10, -1, -1, 42, -1, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Sandy Bridge (Core i7)" }, + { 6, 10, -1, -1, 42, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Sandy Bridge (Core i7)" }, + { 6, 10, -1, -1, 42, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Sandy Bridge (Core i5)" }, + { 6, 10, -1, -1, 42, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Sandy Bridge (Core i3)" }, + { 6, 10, -1, -1, 42, 2, -1, -1, NC, PENTIUM_ , 0, "Sandy Bridge (Pentium)" }, + { 6, 10, -1, -1, 42, 1, -1, -1, NC, CELERON_ , 0, "Sandy Bridge (Celeron)" }, + { 6, 10, -1, -1, 42, 2, -1, -1, NC, CELERON_ , 0, "Sandy Bridge (Celeron)" }, + { 6, 13, -1, -1, 45, -1, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Sandy Bridge-E" }, + { 6, 13, -1, -1, 45, -1, -1, -1, NC, XEON_ , 0, "Sandy Bridge-E (Xeon)" }, + + /* Ivy Bridge CPUs (22nm): */ + { 6, 10, -1, -1, 58, -1, -1, -1, NC, XEON_ , 0, "Ivy Bridge (Xeon)" }, + { 6, 10, -1, -1, 58, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Ivy Bridge (Core i7)" }, + { 6, 10, -1, -1, 58, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Ivy Bridge (Core i5)" }, + { 6, 10, -1, -1, 58, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Ivy Bridge (Core i3)" }, + { 6, 10, -1, -1, 58, 2, -1, -1, NC, PENTIUM_ , 0, "Ivy Bridge (Pentium)" }, + { 6, 10, -1, -1, 58, 1, -1, -1, NC, CELERON_ , 0, "Ivy Bridge (Celeron)" }, + { 6, 10, -1, -1, 58, 2, -1, -1, NC, CELERON_ , 0, "Ivy Bridge (Celeron)" }, + { 6, 14, -1, -1, 62, -1, -1, -1, NC, 0 , 0, "Ivy Bridge-E" }, + + /* Haswell CPUs (22nm): */ + { 6, 12, -1, -1, 60, -1, -1, -1, NC, XEON_ , 0, "Haswell (Xeon)" }, + { 6, 12, -1, -1, 60, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Haswell (Core i7)" }, + { 6, 5, -1, -1, 69, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Haswell (Core i7)" }, + { 6, 6, -1, -1, 70, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Haswell (Core i7)" }, + { 6, 12, -1, -1, 60, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Haswell (Core i5)" }, + { 6, 5, -1, -1, 69, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Haswell (Core i5)" }, + { 6, 12, -1, -1, 60, 2, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Haswell (Core i5)" }, + { 6, 5, -1, -1, 69, 2, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Haswell (Core i5)" }, + { 6, 12, -1, -1, 60, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Haswell (Core i3)" }, + { 6, 5, -1, -1, 69, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Haswell (Core i3)" }, + { 6, 12, -1, -1, 60, 2, -1, -1, NC, PENTIUM_ , 0, "Haswell (Pentium)" }, + { 6, 12, -1, -1, 60, 2, -1, -1, NC, CELERON_ , 0, "Haswell (Celeron)" }, + { 6, 12, -1, -1, 60, 1, -1, -1, NC, CELERON_ , 0, "Haswell (Celeron)" }, + { 6, 15, -1, -1, 63, -1, -1, -1, NC, 0 , 0, "Haswell-E" }, + + /* Broadwell CPUs (14nm): */ + { 6, 7, -1, -1, 71, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Broadwell (Core i7)" }, + { 6, 7, -1, -1, 71, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Broadwell (Core i5)" }, + { 6, 13, -1, -1, 61, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Broadwell-U (Core i7)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Broadwell-U (Core i7)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Broadwell-U (Core i5)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Broadwell-U (Core i3)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NC, PENTIUM_ , 0, "Broadwell-U (Pentium)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NC, CELERON_ , 0, "Broadwell-U (Celeron)" }, + { 6, 13, -1, -1, 61, 2, -1, -1, NA, 0 , 0, "Broadwell-U (Core M)" }, + { 6, 15, -1, -1, 79, -1, -1, -1, NC, XEON_ , 0, "Broadwell-E (Xeon)" }, + { 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Broadwell-E (Core i3)" }, + { 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Broadwell-E (Core i5)" }, + { 6, 15, -1, -1, 79, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Broadwell-E (Core i5)" }, + { 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Broadwell-E (Core i7)" }, + { 6, 15, -1, -1, 79, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Broadwell-E (Core i7)" }, + + /* Skylake CPUs (14nm): */ + { 6, 14, -1, -1, 94, -1, -1, -1, NC, XEON_ , 0, "Skylake (Xeon)" }, + { 6, 14, -1, -1, 94, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Skylake (Core i7)" }, + { 6, 14, -1, -1, 94, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Skylake (Core i5)" }, + { 6, 14, -1, -1, 94, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Skylake (Core i3)" }, + { 6, 14, -1, -1, 94, 2, -1, -1, NC, PENTIUM_ , 0, "Skylake (Pentium)" }, + { 6, 14, -1, -1, 78, 2, -1, -1, NC, PENTIUM_ , 0, "Skylake (Pentium)" }, + { 6, 14, -1, -1, 94, 2, -1, -1, NC, CELERON_ , 0, "Skylake (Celeron)" }, + { 6, 14, -1, -1, 78, 2, -1, -1, NC, CELERON_ , 0, "Skylake (Celeron)" }, + { 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_ | _M_ | _7 , 0, "Skylake (Core m7)" }, + { 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_ | _M_ | _5 , 0, "Skylake (Core m5)" }, + { 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_ | _M_ | _3 , 0, "Skylake (Core m3)" }, + { 6, 5, -1, -1, 85, 8, -1, -1, NC, XEON_, 0, "Skylake (Xeon Scalable)" }, + + /* Kaby Lake CPUs (14nm): */ + { 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Kaby Lake (Core i7)" }, + { 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Kaby Lake (Core i5)" }, + { 6, 14, -1, -1, 158, 2, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Kaby Lake (Core i3)" }, + { 6, 14, -1, -1, 158, 2, -1, -1, NC, PENTIUM_ , 0, "Kaby Lake (Pentium)" }, + { 6, 14, -1, -1, 158, 2, -1, -1, NC, CELERON_ , 0, "Kaby Lake (Celeron)" }, + { 6, 14, -1, -1, 158, 2, -1, -1, NC, CORE_ | _M_ | _3 , 0, "Kaby Lake (Core m3)" }, + + /* Coffee Lake CPUs (14nm): */ + { 6, 14, -1, -1, 158, 6, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Coffee Lake (Core i7)" }, + { 6, 14, -1, -1, 158, 6, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Coffee Lake (Core i5)" }, + { 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Coffee Lake (Core i3)" }, + + /* Itaniums */ + { 7, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Itanium" }, + { 15, -1, -1, 16, -1, 1, -1, -1, NC, 0 , 0, "Itanium 2" }, +}; + + static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { const struct feature_map_t matchtable_edx1[] = @@ -321,6 +613,8 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw, } else { + warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber); + warnf("deterministic_cache: recognize cache type\n"); continue; } ways = ((raw->intel_fn4[ecx][1] >> 22) & 0x3ff) + 1; @@ -491,6 +785,7 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) code = matchtable[i].c; break; } + debugf(2, "intel matchtable result is %d\n", code); if(bits & XEON_) { if(match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##")) @@ -583,6 +878,104 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) return result; } +static intel_model_t get_model_code(struct cpu_id_t* data) +{ + int i = 0; + int l = (int) strlen(data->brand_str); + const char* bs = data->brand_str; + int mod_flags = 0, model_no = 0, ndigs = 0; + /* If the CPU is a Core ix, then just return the model number generation: */ + if((i = match_pattern(bs, "Core(TM) i[357]")) != 0) + { + i += 11; + if(i + 4 >= l) + { + return UNKNOWN; + } + if(bs[i] == '2') + { + return _2xxx; + } + if(bs[i] == '3') + { + return _3xxx; + } + return UNKNOWN; + } + + /* For Core2-based Xeons: */ + while(i < l - 3) + { + if(bs[i] == 'C' && bs[i + 1] == 'P' && bs[i + 2] == 'U') + { + break; + } + i++; + } + if(i >= l - 3) + { + return UNKNOWN; + } + i += 3; + while(i < l - 4 && bs[i] == ' ') + { + i++; + } + if(i >= l - 4) + { + return UNKNOWN; + } + while(i < l - 4 && !isdigit(bs[i])) + { + if(bs[i] >= 'A' && bs[i] <= 'Z') + { + mod_flags |= (1 << (bs[i] - 'A')); + } + i++; + } + if(i >= l - 4) + { + return UNKNOWN; + } + while(isdigit(bs[i])) + { + ndigs++; + model_no = model_no * 10 + (int)(bs[i] - '0'); + i++; + } + if(ndigs != 4) + { + return UNKNOWN; + } +#define HAVE(ch, flags) ((flags & (1 << ((int)(ch-'A')))) != 0) + switch(model_no / 100) + { + case 30: + return _3000; + case 31: + return _3100; + case 32: + { + return (HAVE('X', mod_flags)) ? X3200 : _3200; + } + case 33: + { + return (HAVE('X', mod_flags)) ? X3300 : _3300; + } + case 51: + return _5100; + case 52: + return _5200; + case 53: + return _5300; + case 54: + return _5400; + default: + return UNKNOWN; + } +#undef HAVE +} + static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data) { struct cpu_epc_t epc; @@ -625,12 +1018,14 @@ static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct c epc = cpuid_get_epc(i, raw); if(epc.length == 0) { + debugf(2, "SGX: epc section request for %d returned null, no more EPC sections.\n", i); data->sgx.num_epc_sections = i; break; } } if(data->sgx.num_epc_sections == -1) { + debugf(1, "SGX: warning: seems to be infinitude of EPC sections.\n"); data->sgx.num_epc_sections = 1000000; } } @@ -668,6 +1063,9 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal) { intel_code_and_bits_t brand; + intel_model_t model_code; + int i; + char* brand_code_str = NULL; load_intel_features(raw, data); if(raw->basic_cpuid[0][0] >= 4) @@ -682,15 +1080,46 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, decode_intel_number_of_cores(raw, data); brand = get_brand_code_and_bits(data); + model_code = get_model_code(data); + for(i = 0; i < COUNT_OF(intel_bcode_str); i++) + { + if(brand.code == intel_bcode_str[i].code) + { + brand_code_str = intel_bcode_str[i].str; + break; + } + } + if(brand_code_str) + { + debugf(2, "Detected Intel brand code: %d (%s)\n", brand.code, brand_code_str); + } + else + { + debugf(2, "Detected Intel brand code: %d\n", brand.code); + } + if(brand.bits) + { + debugf(2, "Detected Intel bits: "); + debug_print_lbits(2, brand.bits); + } + debugf(2, "Detected Intel model code: %d\n", model_code); internal->code.intel = brand.code; internal->bits = brand.bits; if(data->flags[CPU_FEATURE_SGX]) { + debugf(2, "SGX seems to be present, decoding...\n"); // if SGX is indicated by the CPU, verify its presence: decode_intel_sgx_features(raw, data); } + internal->score = match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data, + brand.code, brand.bits, model_code); return 0; } + +void cpuid_get_list_intel(struct cpu_list_t* list) +{ + generic_get_cpu_list(cpudb_intel, COUNT_OF(cpudb_intel), list); +} diff --git a/src/3rdparty/libcpuid/recog_intel.h b/src/3rdparty/libcpuid/recog_intel.h index 8d1b7c34..c411e5ee 100644 --- a/src/3rdparty/libcpuid/recog_intel.h +++ b/src/3rdparty/libcpuid/recog_intel.h @@ -28,5 +28,6 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal); +void cpuid_get_list_intel(struct cpu_list_t* list); #endif /*__RECOG_INTEL_H__*/ diff --git a/src/3rdparty/rapidjson/document.h b/src/3rdparty/rapidjson/document.h index cab6d813..d1dcfa5b 100644 --- a/src/3rdparty/rapidjson/document.h +++ b/src/3rdparty/rapidjson/document.h @@ -50,6 +50,13 @@ RAPIDJSON_DIAG_OFF(switch - enum) #if RAPIDJSON_HAS_CXX11_RVALUE_REFS #include // std::move +#endif + +#ifdef max +#undef max +#endif +#ifdef min +#undef min #endif RAPIDJSON_NAMESPACE_BEGIN @@ -484,8 +491,8 @@ namespace internal // select candidates according to nested encoding and allocator types template struct - IsGenericValueImpl::Type, typename Void::Type> - : IsBaseOf, T>::Type {}; + IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; // helper to match arbitrary GenericValue instantiations, including derived classes template struct IsGenericValue : IsGenericValueImpl::Type {}; @@ -868,7 +875,7 @@ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). \see CopyFrom() */ - template< typename SourceAllocator > + template GenericValue(const GenericValue & rhs, Allocator & allocator); //! Constructor for boolean value. diff --git a/src/3rdparty/rapidjson/internal/dtoa.h b/src/3rdparty/rapidjson/internal/dtoa.h index b146e40c..d0b17bc7 100644 --- a/src/3rdparty/rapidjson/internal/dtoa.h +++ b/src/3rdparty/rapidjson/internal/dtoa.h @@ -30,8 +30,8 @@ namespace internal #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) - RAPIDJSON_DIAG_OFF(array - - bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 + RAPIDJSON_DIAG_OFF(array-bounds) + // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 #endif inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, diff --git a/src/3rdparty/rapidjson/internal/meta.h b/src/3rdparty/rapidjson/internal/meta.h index 263c9de9..aca227ee 100644 --- a/src/3rdparty/rapidjson/internal/meta.h +++ b/src/3rdparty/rapidjson/internal/meta.h @@ -113,8 +113,8 @@ namespace internal template struct IsMoreConst - : AndExpr::Type, typename RemoveConst::Type>, - BoolType::Value >= IsConst::Value> >::Type {}; + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; template struct IsPointer : FalseType {}; template struct IsPointer : TrueType {}; @@ -125,7 +125,7 @@ namespace internal #if RAPIDJSON_HAS_CXX11_TYPETRAITS template struct IsBaseOf - : BoolType< ::std::is_base_of::value> {}; + : BoolType<::std::is_base_of::value> {}; #else // simplified version adopted from Boost @@ -134,8 +134,8 @@ namespace internal RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); - typedef char (&Yes)[1]; - typedef char (&No) [2]; + typedef char(&Yes)[1]; + typedef char(&No) [2]; template static Yes Check(const D*, T); @@ -151,7 +151,7 @@ namespace internal }; template struct IsBaseOf - : OrExpr, BoolExpr>>::Type {}; + : OrExpr, BoolExpr>>::Type {}; #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS @@ -188,7 +188,7 @@ namespace internal template struct RemoveSfinaeTag; template struct RemoveSfinaeTag { - typedef T Type; + typedef T Type; }; #define RAPIDJSON_REMOVEFPTR_(type) \ diff --git a/src/3rdparty/rapidjson/msinttypes/inttypes.h b/src/3rdparty/rapidjson/msinttypes/inttypes.h index 8d877bba..df823c21 100644 --- a/src/3rdparty/rapidjson/msinttypes/inttypes.h +++ b/src/3rdparty/rapidjson/msinttypes/inttypes.h @@ -195,11 +195,11 @@ typedef struct #define SCNiMAX "I64i" #ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" +#define SCNdPTR "I64d" +#define SCNiPTR "I64i" #else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" +#define SCNdPTR "ld" +#define SCNiPTR "li" #endif // _WIN64 ] // The fscanf macros for unsigned integers are: @@ -261,15 +261,15 @@ typedef struct #define SCNXMAX "I64X" #ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" +#define SCNoPTR "I64o" +#define SCNuPTR "I64u" +#define SCNxPTR "I64x" +#define SCNXPTR "I64X" #else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" +#define SCNoPTR "lo" +#define SCNuPTR "lu" +#define SCNxPTR "lx" +#define SCNXPTR "lX" #endif // _WIN64 ] #endif // __STDC_FORMAT_MACROS ] diff --git a/src/3rdparty/rapidjson/msinttypes/stdint.h b/src/3rdparty/rapidjson/msinttypes/stdint.h index 421edf64..bb71442f 100644 --- a/src/3rdparty/rapidjson/msinttypes/stdint.h +++ b/src/3rdparty/rapidjson/msinttypes/stdint.h @@ -1,7 +1,7 @@ // ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // -// Copyright (c) 2006-2013 Alexander Chemeris +// Copyright (c) 2006-2008 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: @@ -13,9 +13,8 @@ // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // -// 3. Neither the name of the product nor the names of its contributors may -// be used to endorse or promote products derived from this software -// without specific prior written permission. +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -30,10 +29,6 @@ // /////////////////////////////////////////////////////////////////////////////// -// The above software in this distribution may have been modified by -// THL A29 Limited ("Tencent Modifications"). -// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. - #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] @@ -45,68 +40,27 @@ #pragma once #endif -// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. -#if _MSC_VER >= 1600 // [ -#include - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -#undef INT8_C -#undef INT16_C -#undef INT32_C -#undef INT64_C -#undef UINT8_C -#undef UINT16_C -#undef UINT32_C -#undef UINT64_C - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -// These #ifndef's are needed to prevent collisions with . -// Check out Issue 9 for the details. -#ifndef INTMAX_C // [ -# define INTMAX_C INT64_C -#endif // INTMAX_C ] -#ifndef UINTMAX_C // [ -# define UINTMAX_C UINT64_C -#endif // UINTMAX_C ] - -#endif // __STDC_CONSTANT_MACROS ] - -#else // ] _MSC_VER >= 1700 [ - #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we have to wrap include with 'extern "C++" {}' -// or compiler would give many errors like this: +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if defined(__cplusplus) && !defined(_M_ARM) +#ifdef __cplusplus extern "C" { #endif -# include -#if defined(__cplusplus) && !defined(_M_ARM) +#include +#ifdef __cplusplus } #endif // Define _W64 macros to mark types changing their size, like intptr_t. #ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif #endif @@ -218,13 +172,13 @@ typedef uint64_t uintmax_t; // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types @@ -235,30 +189,30 @@ typedef uint64_t uintmax_t; // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX +#define PTRDIFF_MIN _I64_MIN +#define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX +#define PTRDIFF_MIN _I32_MIN +#define PTRDIFF_MAX _I32_MAX #endif // _WIN64 ] #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] +#ifdef _WIN64 // [ +#define SIZE_MAX _UI64_MAX +#else // _WIN64 ][ +#define SIZE_MAX _UI32_MAX +#endif // _WIN64 ] #endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 +#define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX +#define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 @@ -284,17 +238,10 @@ typedef uint64_t uintmax_t; #define UINT64_C(val) val##ui64 // 7.18.4.2 Macros for greatest-width integer constants -// These #ifndef's are needed to prevent collisions with . -// Check out Issue 9 for the details. -#ifndef INTMAX_C // [ -# define INTMAX_C INT64_C -#endif // INTMAX_C ] -#ifndef UINTMAX_C // [ -# define UINTMAX_C UINT64_C -#endif // UINTMAX_C ] +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] -#endif // _MSC_VER >= 1600 ] #endif // _MSC_STDINT_H_ ] diff --git a/src/3rdparty/rapidjson/writer.h b/src/3rdparty/rapidjson/writer.h index 8d52e045..ba8ec162 100644 --- a/src/3rdparty/rapidjson/writer.h +++ b/src/3rdparty/rapidjson/writer.h @@ -99,12 +99,12 @@ public: */ explicit Writer(OutputStream & os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), - maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + os_(&os), level_stack_(stackAllocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), + hasRoot_(false) {} explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), + os_(0), level_stack_(allocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} //! Reset the writer with a new stream. diff --git a/src/App.cpp b/src/App.cpp index 138fe1a1..f6bb6287 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -79,7 +79,7 @@ App::App(int argc, char** argv) : m_console = new Console(this); } - if(m_options->logFile()) + if(0 < m_options->logFile().size()) { Log::add(new FileLog(m_options->logFile())); } @@ -129,7 +129,7 @@ int App::exec() if(!CryptoNight::init(m_options->algo(), m_options->algoVariant())) { - LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName()); + LOG_ERR("\"" << m_options->algoName() << "\" hash self-test failed."); return 1; } @@ -178,8 +178,7 @@ void App::onConsoleCommand(char command) case 'P': if(Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : - "paused, press 'r' to resume"); + LOG_INFO("paused, press 'r' to resume"); Workers::setEnabled(false); } break; @@ -188,7 +187,7 @@ void App::onConsoleCommand(char command) case 'R': if(!Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed"); + LOG_INFO((m_options->colors() ? "\x1B[01;32mresumed" : "resumed")); Workers::setEnabled(true); } break; diff --git a/src/App_unix.cpp b/src/App_unix.cpp index 2213a87f..ee0fa96b 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -20,13 +20,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include #include #include +#include "interfaces/interface.h" #include "App.h" #include "Cpu.h" @@ -61,12 +62,14 @@ void App::background() if(i < 0) { - LOG_ERR("setsid() failed (errno = %d)", errno); + LOG_ERR("setsid() failed (errno = " << errno << ")"); } i = chdir("/"); if(i < 0) { - LOG_ERR("chdir() failed (errno = %d)", errno); + LOG_ERR("chdir() failed (errno = " << errno << ")"); } } + +#endif diff --git a/src/Console.cpp b/src/Console.cpp index 991cfd44..3e18b94b 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -25,6 +25,8 @@ #include "Console.h" #include "interfaces/IConsoleListener.h" +#include "interfaces/interface.h" + Console::Console(IConsoleListener* listener) : m_listener(listener) diff --git a/src/Cpu.cpp b/src/Cpu.cpp index 588444db..7b26023c 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -84,8 +84,8 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) void Cpu::initCommon() { - struct cpu_raw_data_t raw = { 0 }; - struct cpu_id_t data = { 0 }; + struct cpu_raw_data_t raw; + struct cpu_id_t data;; cpuid_get_raw_data(&raw); cpu_identify(&raw, &data); @@ -111,8 +111,8 @@ void Cpu::initCommon() } // Workaround for Intel Pentium Dual-Core, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue // These processors have L2 cache shared by 2 cores. - else if(data.vendor == VENDOR_INTEL && data.ext_family == 0x06 && (data.ext_model == 0x0E || - data.ext_model == 0x0F || data.ext_model == 0x17)) + else if(data.vendor == VENDOR_INTEL && data.ext_family == 0x06 && + (data.ext_model == 0x0E || data.ext_model == 0x0F || data.ext_model == 0x17)) { int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; diff --git a/src/Cpu_arm.cpp b/src/Cpu_arm.cpp index 8b9c618d..042e8ee2 100644 --- a/src/Cpu_arm.cpp +++ b/src/Cpu_arm.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include @@ -52,3 +52,5 @@ void Cpu::initCommon() m_flags |= AES; # endif } + +#endif diff --git a/src/Cpu_mac.cpp b/src/Cpu_mac.cpp index a09cbc58..7213cc6a 100644 --- a/src/Cpu_mac.cpp +++ b/src/Cpu_mac.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -43,3 +43,5 @@ void Cpu::init() void Cpu::setAffinity(int id, uint64_t mask) { } + +#endif diff --git a/src/Cpu_stub.cpp b/src/Cpu_stub.cpp index 7f029193..c033d268 100644 --- a/src/Cpu_stub.cpp +++ b/src/Cpu_stub.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #ifdef _MSC_VER # include @@ -144,3 +144,5 @@ void Cpu::initCommon() m_flags |= BMI2; } } + +#endif \ No newline at end of file diff --git a/src/Cpu_unix.cpp b/src/Cpu_unix.cpp index 4dcf3ca4..432913fc 100644 --- a/src/Cpu_unix.cpp +++ b/src/Cpu_unix.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #ifdef __FreeBSD__ # include @@ -29,6 +29,7 @@ # include #endif +#include #include #include @@ -56,6 +57,8 @@ void Cpu::init() void Cpu::setAffinity(int id, uint64_t mask) { +#if __GNU_VISIBLE && defined(__rtems__) + cpu_set_t set; CPU_ZERO(&set); @@ -81,4 +84,6 @@ void Cpu::setAffinity(int id, uint64_t mask) sched_setaffinity(gettid(), sizeof(&set), &set); # endif } +#endif } +#endif \ No newline at end of file diff --git a/src/Mem.cpp b/src/Mem.cpp index ba768876..c072033c 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -32,13 +32,13 @@ #include "xmrig.h" -bool Mem::m_doubleHash = false; -int Mem::m_algo = 0; -int Mem::m_flags = 0; -int Mem::m_threads = 0; -size_t Mem::m_offset = 0; -size_t Mem::m_size = 0; -alignas(16) uint8_t* Mem::m_memory = nullptr; +bool Mem::m_doubleHash = false; +int Mem::m_algo = 0; +int Mem::m_flags = 0; +int Mem::m_threads = 0; +size_t Mem::m_offset = 0; +size_t Mem::m_size = 0; +VAR_ALIGN(16, uint8_t* Mem::m_memory) = nullptr; cryptonight_ctx* Mem::create(int threadId) diff --git a/src/Mem.h b/src/Mem.h index 6a6b7597..a8e65733 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -30,6 +30,9 @@ #include +#include "align.h" + + struct cryptonight_ctx; @@ -76,7 +79,7 @@ private: static int m_threads; static size_t m_offset; static size_t m_size; - alignas(16) static uint8_t* m_memory; + VAR_ALIGN(16, static uint8_t* m_memory); # ifndef XMRIG_NO_AEON static cryptonight_ctx* createLite(int threadId); diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index dcb85180..d0e892ff 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -21,7 +21,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -40,6 +40,12 @@ #include "Options.h" #include "xmrig.h" +#ifndef MAP_HUGETLB +#define MAP_HUGETLB 0x40000 /* create a huge page mapping */ +#endif +#ifndef MAP_POPULATE +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#endif bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) { @@ -53,6 +59,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) if(!enabled) { m_memory = static_cast(_mm_malloc(m_size, 16)); + return true; } @@ -92,6 +99,8 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) void Mem::release() { + const int size = MEMORY * (m_threads + 1); + if(m_flags & HugepagesEnabled) { if(m_flags & Lock) @@ -106,3 +115,5 @@ void Mem::release() _mm_free(m_memory); } } + +#endif diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 9612a34f..ace594ab 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -93,7 +93,7 @@ static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) { LSA_UNICODE_STRING lsaString; - DWORD dwLen = (DWORD) wcslen(string); + DWORD dwLen = (DWORD) wcslen((WCHAR*)string); lsaString.Buffer = (LPWSTR) string; lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR)); lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR)); diff --git a/src/Options.cpp b/src/Options.cpp index 7d72ef96..0a48b905 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,16 +27,17 @@ #ifdef _MSC_VER -# include "getopt/getopt.h" +#include "getopt/getopt.h" #else -# include +#include #endif #ifndef XMRIG_NO_HTTPD -# include +#include #endif +#include "interfaces/interface.h" #include "Cpu.h" #include "donate.h" @@ -75,9 +76,9 @@ Options:\n\ --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\ --no-huge-pages disable huge pages support\n\ --no-color disable colored output\n\ - --variant algorithm PoW variant\n\ --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ --user-agent set custom user-agent string for pool\n\ + --donate-level=N donate level, default 2%%\n\ -B, --background run the miner in the background\n\ -c, --config=FILE load a JSON-format configuration file\n\ -l, --log-file=FILE log all output to a file\n" @@ -112,6 +113,7 @@ static struct option const options[] = { "config", 1, nullptr, 'c' }, { "cpu-affinity", 1, nullptr, 1020 }, { "cpu-priority", 1, nullptr, 1021 }, + { "debug", 0, nullptr, 1101 }, { "donate-level", 1, nullptr, 1003 }, { "dry-run", 0, nullptr, 5000 }, { "help", 0, nullptr, 'h' }, @@ -121,7 +123,6 @@ static struct option const options[] = { "nicehash", 0, nullptr, 1006 }, { "no-color", 0, nullptr, 1002 }, { "no-huge-pages", 0, nullptr, 1009 }, - { "variant", 1, nullptr, 1010 }, { "pass", 1, nullptr, 'p' }, { "print-time", 1, nullptr, 1007 }, { "retries", 1, nullptr, 'r' }, @@ -133,7 +134,17 @@ static struct option const options[] = { "user", 1, nullptr, 'u' }, { "user-agent", 1, nullptr, 1008 }, { "userpass", 1, nullptr, 'O' }, + { "verbose", 0, nullptr, 1100 }, { "version", 0, nullptr, 'V' }, + { "donate-url", required_argument, nullptr, 1391 }, + { "donate-url-little", required_argument, nullptr, 1392 }, + { "donate-user", required_argument, nullptr, 1393 }, + { "donate-pass", required_argument, nullptr, 1394 }, + { "donate-userpass", required_argument, nullptr, 1395 }, + { "donate-keepalive", no_argument, nullptr, 1396 }, + { "donate-nicehash", no_argument, nullptr, 1397 }, + { "donate-minutes", required_argument, nullptr, 1398 }, + { "minutes-in-cicle", required_argument, nullptr, 1399 }, { 0, 0, 0, 0 } }; @@ -158,9 +169,24 @@ static struct option const config_options[] = { "syslog", 0, nullptr, 'S' }, { "threads", 1, nullptr, 't' }, { "user-agent", 1, nullptr, 1008 }, + { "verbose", 0, nullptr, 1100 }, + { "workers", 0, nullptr, 1103 }, { 0, 0, 0, 0 } }; +static struct option const donate_options[] = +{ + { "donate-url", required_argument, nullptr, 1391 }, + { "donate-url-little", required_argument, nullptr, 1392 }, + { "donate-user", required_argument, nullptr, 1393 }, + { "donate-pass", required_argument, nullptr, 1394 }, + { "donate-userpass", required_argument, nullptr, 1395 }, + { "donate-keepalive", no_argument, nullptr, 1396 }, + { "donate-nicehash", no_argument, nullptr, 1397 }, + { "donate-minutes", required_argument, nullptr, 1398 }, + { "minutes-in-cicle", required_argument, nullptr, 1399 }, + { 0, 0, 0, 0 } +}; static struct option const pool_options[] = { @@ -169,7 +195,6 @@ static struct option const pool_options[] = { "user", 1, nullptr, 'u' }, { "userpass", 1, nullptr, 'O' }, { "keepalive", 0, nullptr, 'k' }, - { "variant", 1, nullptr, 1010 }, { "nicehash", 0, nullptr, 1006 }, { 0, 0, 0, 0 } }; @@ -215,22 +240,23 @@ const char* Options::algoName() const Options::Options(int argc, char** argv) : m_background(false), - m_colors(true), + m_colors(false), + m_debug(false), m_doubleHash(false), m_dryRun(false), m_hugePages(true), m_ready(false), m_safe(false), m_syslog(false), - m_apiToken(nullptr), - m_apiWorkerId(nullptr), - m_logFile(nullptr), - m_userAgent(nullptr), + m_verbose(false), + m_apiToken(""), + m_apiWorkerId(""), + m_logFile(""), + m_userAgent(""), m_algo(0), m_algoVariant(0), m_apiPort(0), - m_donateLevel(kDonateLevel), - m_maxCpuUsage(75), + m_maxCpuUsage(100), m_printTime(60), m_priority(-1), m_retries(5), @@ -238,19 +264,26 @@ Options::Options(int argc, char** argv) : m_threads(0), m_affinity(-1L) { - m_pools.push_back(new Url()); + m_donateOpt.m_url = kDonateUrl; + m_donateOpt.m_url_little = kDonateUrlLittle; + m_donateOpt.m_user = kDonateUser; + m_donateOpt.m_pass = kDonatePass; + m_donateOpt.m_keepAlive = kDonateKeepAlive; + m_donateOpt.m_niceHash = kDonateNiceHash; + m_donateOpt.m_donateMinutes = kDonateMinutes; + m_donateOpt.m_minutesInCicle = kMinutesInCicle; - int key; + m_pools.push_back(Url()); while(1) { - key = getopt_long(argc, argv, short_options, options, NULL); + const int key = getopt_long(argc, argv, short_options, options, NULL); if(key < 0) { break; } - if(!parseArg(key, optarg)) + if(!parseArg(key, optarg == NULL ? "" : optarg)) { return; } @@ -262,12 +295,12 @@ Options::Options(int argc, char** argv) : return; } - if(!m_pools[0]->isValid()) + if(!m_pools[0].isValid()) { parseConfig(Platform::defaultConfigName()); } - if(!m_pools[0]->isValid()) + if(!m_pools[0].isValid()) { fprintf(stderr, "No pool URL supplied. Exiting.\n"); return; @@ -300,16 +333,17 @@ Options::Options(int argc, char** argv) : Options::~Options() { + m_pools.clear(); } -bool Options::getJSON(const char* fileName, rapidjson::Document & doc) +bool Options::getJSON(const std::string & fileName, rapidjson::Document & doc) { uv_fs_t req; - const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr); + const int fd = uv_fs_open(uv_default_loop(), &req, fileName.c_str(), O_RDONLY, 0644, nullptr); if(fd < 0) { - fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd)); + fprintf(stderr, "unable to open %s: %s\n", fileName.c_str(), uv_strerror(fd)); return false; } @@ -326,7 +360,8 @@ bool Options::getJSON(const char* fileName, rapidjson::Document & doc) if(doc.HasParseError()) { - printf("%s:%d: %s\n", fileName, (int) doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError())); + printf("%s:%d: %s\n", fileName.c_str(), (int) doc.GetErrorOffset(), + rapidjson::GetParseError_En(doc.GetParseError())); return false; } @@ -334,7 +369,7 @@ bool Options::getJSON(const char* fileName, rapidjson::Document & doc) } -bool Options::parseArg(int key, const char* arg) +bool Options::parseArg(int key, const std::string & arg) { switch(key) { @@ -346,91 +381,128 @@ bool Options::parseArg(int key, const char* arg) break; case 'o': /* --url */ - if(m_pools.size() > 1 || m_pools[0]->isValid()) + if(m_pools.size() > 1 || m_pools[0].isValid()) { - Url* url = new Url(arg); - if(url->isValid()) + Url url(arg); + if(url.isValid()) { m_pools.push_back(url); } - else - { - delete url; - } } else { - m_pools[0]->parse(arg); + m_pools[0].parse(arg); } - if(!m_pools.back()->isValid()) + if(!m_pools.back().isValid()) { return false; } break; case 'O': /* --userpass */ - if(!m_pools.back()->setUserpass(arg)) + if(!m_pools.back().setUserpass(arg)) { return false; } break; case 'u': /* --user */ - m_pools.back()->setUser(arg); + m_pools.back().setUser(arg); break; case 'p': /* --pass */ - m_pools.back()->setPassword(arg); + m_pools.back().setPassword(arg); break; case 'l': /* --log-file */ - free(m_logFile); - m_logFile = strdup(arg); - m_colors = false; + m_logFile = arg; break; case 4001: /* --access-token */ - free(m_apiToken); - m_apiToken = strdup(arg); + m_apiToken = arg; break; case 4002: /* --worker-id */ - free(m_apiWorkerId); - m_apiWorkerId = strdup(arg); + m_apiWorkerId = arg; break; case 'r': /* --retries */ case 'R': /* --retry-pause */ case 'v': /* --av */ - case 1003: /* --donate-level */ case 1004: /* --max-cpu-usage */ case 1007: /* --print-time */ case 1021: /* --cpu-priority */ case 4000: /* --api-port */ - case 1010: /* --variant */ - return parseArg(key, strtol(arg, nullptr, 10)); + return parseArg(key, strtol(arg.c_str(), nullptr, 10)); case 'B': /* --background */ case 'k': /* --keepalive */ case 'S': /* --syslog */ case 1005: /* --safe */ case 1006: /* --nicehash */ - case 5000: /* --dry-run */ + case 1100: /* --verbose */ + case 1101: /* --debug */ return parseBoolean(key, true); case 1002: /* --no-color */ case 1009: /* --no-huge-pages */ return parseBoolean(key, false); + case 1003: /* --donate-level */ + if(arg == "") + { + m_donateOpt.m_donateMinutes = 0; + } + else + { + parseArg(key, strtol(arg.c_str(), nullptr, 10)); + } + break; + + case 1391: //donate-url + m_donateOpt.m_url = arg; + break; + case 1392: //donate-url-little + m_donateOpt.m_url_little = arg; + break; + case 1393: //donate-user + m_donateOpt.m_user = arg; + break; + case 1394: //donate-pass + m_donateOpt.m_pass = arg; + break; + case 1395: //donate-userpass + { + const size_t p = arg.find_first_of(':'); + if(p != std::string::npos) + { + m_donateOpt.m_user = arg.substr(0, p); + m_donateOpt.m_pass = arg.substr(p + 1); + } + } + break; + case 1396: //donate-nicehash + parseBoolean(key, arg == "true"); + break; + case 1397: //donate-keepalive + parseBoolean(key, arg == "true"); + break; + case 1398: //donate-minutes + parseArg(key, strtol(arg.c_str(), nullptr, 10)); + break; + case 1399: //minutes-in-cicle + parseArg(key, strtol(arg.c_str(), nullptr, 10)); + break; + case 't': /* --threads */ - if(strncmp(arg, "all", 3) == 0) + if(arg == "all") { m_threads = Cpu::threads(); return true; } - return parseArg(key, strtol(arg, nullptr, 10)); + return parseArg(key, strtol(arg.c_str(), nullptr, 10)); case 'V': /* --version */ showVersion(); @@ -446,13 +518,13 @@ bool Options::parseArg(int key, const char* arg) case 1020: /* --cpu-affinity */ { - const char* p = strstr(arg, "0x"); - return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); + const size_t p = arg.find("0x"); + return parseArg(key, p != std::string::npos ? strtoul(arg.substr(p).c_str(), nullptr, 16) : + strtoul(arg.c_str(), nullptr, 10)); } case 1008: /* --user-agent */ - free(m_userAgent); - m_userAgent = strdup(arg); + m_userAgent = arg; break; default: @@ -509,12 +581,26 @@ bool Options::parseArg(int key, uint64_t arg) break; case 1003: /* --donate-level */ - if(arg < 1 || arg > 99) + if(arg >= 0 || arg <= 60) { - return true; + m_donateOpt.m_donateMinutes = (unsigned short) arg; } + break; - m_donateLevel = (int) arg; + case 1391: //donate-url + case 1392: //donate-user + case 1393: //donate-pass + case 1394: //donate-userpass + case 1395: //donate-keepalive + case 1396: //donate-nicehash + break; + + case 1398: //donate-minutes + m_donateOpt.m_donateMinutes = (unsigned short)arg; + break; + + case 1399: //minutes-in-cicle + m_donateOpt.m_minutesInCicle = (unsigned short)arg; break; case 1004: /* --max-cpu-usage */ @@ -537,10 +623,6 @@ bool Options::parseArg(int key, uint64_t arg) m_printTime = (int) arg; break; - case 1010: /* --variant */ - m_pools.back()->setVariant((int) arg); - break; - case 1020: /* --cpu-affinity */ if(arg) { @@ -575,7 +657,7 @@ bool Options::parseBoolean(int key, bool enable) switch(key) { case 'k': /* --keepalive */ - m_pools.back()->setKeepAlive(enable); + m_pools.back().setKeepAlive(enable); break; case 'B': /* --background */ @@ -592,12 +674,20 @@ bool Options::parseBoolean(int key, bool enable) m_colors = enable; break; + case 1100: /* --verbose */ + m_verbose = enable; + break; + + case 1101: /* --debug */ + m_debug = enable; + break; + case 1005: /* --safe */ m_safe = enable; break; case 1006: /* --nicehash */ - m_pools.back()->setNicehash(enable); + m_pools.back().setNicehash(enable); break; case 1009: /* --no-huge-pages */ @@ -608,10 +698,25 @@ bool Options::parseBoolean(int key, bool enable) m_colors = enable; break; + case 1396: //donate-keepalive + m_donateOpt.m_keepAlive = enable; + break; + + case 1397: //donate-nicehash + m_donateOpt.m_niceHash = enable; + break; + case 5000: /* --dry-run */ m_dryRun = enable; break; + case 1391: //donate-url + case 1392: //donate-url-little + case 1393: //donate-user + case 1394: //donate-pass + case 1395: //donate-userpass + case 1398: //donate-minutes + case 1399: //minutes-in-cicle default: break; } @@ -620,29 +725,21 @@ bool Options::parseBoolean(int key, bool enable) } -Url* Options::parseUrl(const char* arg) const +Url Options::parseUrl(const std::string & arg) const { - auto url = new Url(arg); - if(!url->isValid()) - { - delete url; - return nullptr; - } - - return url; + return Url(arg); } - void Options::adjust() { - for(Url* url : m_pools) + for(size_t i = 0; i < m_pools.size(); ++i) { - url->adjust(m_algo); + Url & url = m_pools[i]; + url.adjust(m_algo); } } - -void Options::parseConfig(const char* fileName) +void Options::parseConfig(const std::string & fileName) { rapidjson::Document doc; if(!getJSON(fileName, doc)) @@ -655,11 +752,30 @@ void Options::parseConfig(const char* fileName) parseJSON(&config_options[i], doc); } + const rapidjson::Value & donate = doc["donate-level"]; + if(donate.IsArray()) + { + for(size_t i = 0; i < donate.GetArray().Size(); ++i) + { + const rapidjson::Value & value = donate.GetArray()[i]; + if(!value.IsObject()) + { + continue; + } + + for(size_t i = 0; i < ARRAY_SIZE(donate_options); i++) + { + parseJSON(&donate_options[i], value); + } + } + } + const rapidjson::Value & pools = doc["pools"]; if(pools.IsArray()) { - for(const rapidjson::Value & value : pools.GetArray()) + for(size_t i = 0; i < pools.GetArray().Size(); ++i) { + const rapidjson::Value & value = pools.GetArray()[i]; if(!value.IsObject()) { continue; @@ -696,7 +812,7 @@ void Options::parseJSON(const struct option* option, const rapidjson::Value & ob { parseArg(option->val, value.GetString()); } - else if(option->has_arg && value.IsInt64()) + else if(option->has_arg && value.IsUint64()) { parseArg(option->val, value.GetUint64()); } @@ -756,18 +872,18 @@ void Options::showVersion() } -bool Options::setAlgo(const char* algo) +bool Options::setAlgo(const std::string & algo) { for(size_t i = 0; i < ARRAY_SIZE(algo_names); i++) { - if(algo_names[i] && !strcmp(algo, algo_names[i])) + if(algo_names[i] && algo == algo_names[i]) { m_algo = (int) i; break; } # ifndef XMRIG_NO_AEON - if(i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) + if(i == ARRAY_SIZE(algo_names) - 1 && algo == "cryptonight-light") { m_algo = xmrig::ALGO_CRYPTONIGHT_LITE; break; diff --git a/src/Options.h b/src/Options.h index 1c778f31..8395db14 100644 --- a/src/Options.h +++ b/src/Options.h @@ -27,7 +27,7 @@ #include #include - +#include #include "rapidjson/fwd.h" @@ -49,6 +49,19 @@ public: AV_MAX }; + struct Donate + { + public: + std::string m_url; + std::string m_url_little; + std::string m_user; + std::string m_pass; + bool m_keepAlive; + bool m_niceHash; + unsigned short m_donateMinutes; + unsigned short m_minutesInCicle; + }; + static inline Options* i() { return m_self; @@ -63,6 +76,14 @@ public: { return m_colors; } + inline bool isDebug() const + { + return m_debug; + } + inline void toggleDebug() + { + m_debug = !m_debug; + } inline bool doubleHash() const { return m_doubleHash; @@ -79,23 +100,23 @@ public: { return m_syslog; } - inline const char* apiToken() const + inline const std::string apiToken() const { return m_apiToken; } - inline const char* apiWorkerId() const + inline const std::string & apiWorkerId() const { return m_apiWorkerId; } - inline const char* logFile() const + inline const std::string & logFile() const { return m_logFile; } - inline const char* userAgent() const + inline const std::string & userAgent() const { return m_userAgent; } - inline const std::vector & pools() const + inline const std::vector & pools() const { return m_pools; } @@ -111,9 +132,17 @@ public: { return m_apiPort; } - inline int donateLevel() const + inline unsigned short donateMinutes() const { - return m_donateLevel; + return m_donateOpt.m_donateMinutes; + } + inline unsigned short minutesInCicle() const + { + return m_donateOpt.m_minutesInCicle; + } + inline const Donate & donate() const + { + return m_donateOpt; } inline int printTime() const { @@ -143,6 +172,14 @@ public: { m_colors = colors; } + inline void setVerbose(bool verbose) + { + m_verbose = verbose; + } + inline void toggleVerbose() + { + m_verbose = !m_verbose; + } inline static void release() { @@ -162,18 +199,18 @@ private: static Options* m_self; - bool getJSON(const char* fileName, rapidjson::Document & doc); - bool parseArg(int key, const char* arg); + bool getJSON(const std::string & fileName, rapidjson::Document & doc); + bool parseArg(int key, const std::string & arg); bool parseArg(int key, uint64_t arg); bool parseBoolean(int key, bool enable); - Url* parseUrl(const char* arg) const; + Url parseUrl(const std::string & arg) const; void adjust(); - void parseConfig(const char* fileName); + void parseConfig(const std::string & fileName); void parseJSON(const struct option* option, const rapidjson::Value & object); void showUsage(int status) const; void showVersion(void); - bool setAlgo(const char* algo); + bool setAlgo(const std::string & algo); int getAlgoVariant() const; # ifndef XMRIG_NO_AEON @@ -182,20 +219,21 @@ private: bool m_background; bool m_colors; + bool m_debug; bool m_doubleHash; bool m_dryRun; bool m_hugePages; bool m_ready; bool m_safe; bool m_syslog; - char* m_apiToken; - char* m_apiWorkerId; - char* m_logFile; - char* m_userAgent; + bool m_verbose; + std::string m_apiToken; + std::string m_apiWorkerId; + std::string m_logFile; + std::string m_userAgent; int m_algo; int m_algoVariant; int m_apiPort; - int m_donateLevel; int m_maxCpuUsage; int m_printTime; int m_priority; @@ -203,7 +241,8 @@ private: int m_retryPause; int m_threads; int64_t m_affinity; - std::vector m_pools; + std::vector m_pools; + Donate m_donateOpt; }; #endif /* __OPTIONS_H__ */ diff --git a/src/Platform.cpp b/src/Platform.cpp index c2032edf..48f22344 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -29,38 +29,40 @@ #include "Platform.h" -char* Platform::m_defaultConfigName = nullptr; -char* Platform::m_userAgent = nullptr; +std::string Platform::m_defaultConfigName = ""; +std::string Platform::m_userAgent = ""; -const char* Platform::defaultConfigName() +const std::string & Platform::defaultConfigName() { - size_t size = 520; - - if(m_defaultConfigName == nullptr) + enum { - m_defaultConfigName = new char[size]; + C_SIZE = 520, + }; + + size_t size = C_SIZE ; + char defaultConfigName[C_SIZE]; + if(uv_exepath(defaultConfigName, &size) < 0) + { + return m_defaultConfigName; } - if(uv_exepath(m_defaultConfigName, &size) < 0) - { - return nullptr; - } + m_defaultConfigName = defaultConfigName; if(size < 500) { -# ifdef WIN32 - char* p = strrchr(m_defaultConfigName, '\\'); -# else - char* p = strrchr(m_defaultConfigName, '/'); -# endif +#ifdef WIN32 + size_t p = m_defaultConfigName.find_last_of('\\'); +#else + size_t p = m_defaultConfigName.find_last_of('/'); +#endif - if(p) + if(p != std::string::npos) { - strcpy(p + 1, "config.json"); - return m_defaultConfigName; + m_defaultConfigName.resize(p + 1); + m_defaultConfigName.append("config.json"); } } - return nullptr; + return m_defaultConfigName; } diff --git a/src/Platform.h b/src/Platform.h index 3d203f5b..72339894 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -24,24 +24,25 @@ #ifndef __PLATFORM_H__ #define __PLATFORM_H__ +#include class Platform { public: - static const char* defaultConfigName(); - static void init(const char* userAgent); + static const std::string & defaultConfigName(); + static void init(const std::string & userAgent); static void release(); static void setProcessPriority(int priority); static void setThreadPriority(int priority); - static inline const char* userAgent() + static inline const std::string & userAgent() { return m_userAgent; } private: - static char* m_defaultConfigName; - static char* m_userAgent; + static std::string m_defaultConfigName; + static std::string m_userAgent; }; diff --git a/src/Platform_mac.cpp b/src/Platform_mac.cpp index 9fc37227..f054d553 100644 --- a/src/Platform_mac.cpp +++ b/src/Platform_mac.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -32,39 +32,39 @@ #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" +#include "nvidia/cryptonight.h" #endif -static inline char* createUserAgent() +static inline std::string createUserAgent() { const size_t max = 160; - char* buf = new char[max]; + char buf[max]; -# ifdef XMRIG_NVIDIA_PROJECT +#ifdef XMRIG_NVIDIA_PROJECT const int cudaVersion = cuda_get_runtime_version(); snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__); -# else +#else snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__); -# endif +#endif return buf; } -void Platform::init(const char* userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent(); } void Platform::release() { - delete [] m_userAgent; + m_userAgent.clear(); } @@ -111,3 +111,4 @@ void Platform::setThreadPriority(int priority) setpriority(PRIO_PROCESS, 0, prio); } +#endif diff --git a/src/Platform_unix.cpp b/src/Platform_unix.cpp index aa4233e0..6a0ae64e 100644 --- a/src/Platform_unix.cpp +++ b/src/Platform_unix.cpp @@ -20,6 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef _WIN32 #include #include @@ -27,60 +28,58 @@ #include #include #include +#include +#include "log/Log.h" #include "Platform.h" #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" +#include "nvidia/cryptonight.h" #endif -static inline char* createUserAgent() +static inline std::string createUserAgent() { const size_t max = 160; - char* buf = new char[max]; + char buf[max]; int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION); -# if defined(__x86_64__) +#if defined(__x86_64__) length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string()); -# else +#else length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string()); -# endif +#endif -# ifdef XMRIG_NVIDIA_PROJECT +#ifdef XMRIG_NVIDIA_PROJECT const int cudaVersion = cuda_get_runtime_version(); length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); -# endif +#endif -# ifdef __GNUC__ +#ifdef __GNUC__ length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -# endif +#endif return buf; } -void Platform::init(const char* userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent(); } - void Platform::release() { - delete [] m_userAgent; + m_userAgent.clear(); } - void Platform::setProcessPriority(int priority) { } - - void Platform::setThreadPriority(int priority) { if(priority == -1) @@ -117,7 +116,7 @@ void Platform::setThreadPriority(int priority) setpriority(PRIO_PROCESS, 0, prio); -# ifdef SCHED_IDLE +#ifdef SCHED_IDLE if(priority == 0) { sched_param param; @@ -125,8 +124,13 @@ void Platform::setThreadPriority(int priority) if(sched_setscheduler(0, SCHED_IDLE, ¶m) != 0) { - sched_setscheduler(0, SCHED_BATCH, ¶m); + const int err = sched_setscheduler(0, SCHED_BATCH, ¶m); + LOG_WARN("SCHED_BATCH priority: " << err << "."); } } +#else + LOG_INFO("NONE priority."); # endif } + +#endif diff --git a/src/Platform_win.cpp b/src/Platform_win.cpp index 02267b44..973cfd41 100644 --- a/src/Platform_win.cpp +++ b/src/Platform_win.cpp @@ -26,12 +26,13 @@ #include #include +#include "log/Log.h" #include "Platform.h" #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" +#include "nvidia/cryptonight.h" #endif @@ -56,46 +57,45 @@ static inline OSVERSIONINFOEX winOsVersion() } -static inline char* createUserAgent() +static inline std::string createUserAgent() { const auto osver = winOsVersion(); const size_t max = 160; - char* buf = new char[max]; + char buf[max]; int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion); -# if defined(__x86_64__) || defined(_M_AMD64) +#if defined(__x86_64__) || defined(_M_AMD64) length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string()); -# else +#else length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string()); -# endif +#endif -# ifdef XMRIG_NVIDIA_PROJECT +#ifdef XMRIG_NVIDIA_PROJECT const int cudaVersion = cuda_get_runtime_version(); length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); -# endif +#endif -# ifdef __GNUC__ +#ifdef __GNUC__ length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -# elif _MSC_VER +#elif _MSC_VER length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION); -# endif +#endif return buf; } -void Platform::init(const char* userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent(); } void Platform::release() { - delete [] m_defaultConfigName; - delete [] m_userAgent; + m_userAgent.clear(); } diff --git a/src/Summary.cpp b/src/Summary.cpp index 05e27f50..d96c460d 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -51,10 +51,7 @@ static void print_versions() # endif - Log::i()->text(Options::i()->colors() ? - "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : - " * VERSIONS: XMRig/%s libuv/%s%s", - APP_VERSION, uv_version_string(), buf); + PRINT_MSG(" * VERSIONS: XMRig/" << APP_VERSION << " libuv/" << uv_version_string() << buf); } @@ -62,14 +59,16 @@ static void print_memory() { if(Options::i()->colors()) { + /* Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable", Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled"); + */ } else { - Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", - Mem::isHugepagesEnabled() ? "enabled" : "disabled"); + PRINT_MSG(" * HUGE PAGES: " << (Mem::isHugepagesAvailable() ? "available" : "unavailable") << ", " << + (Mem::isHugepagesEnabled() ? "enabled" : "disabled")); } } @@ -78,22 +77,25 @@ static void print_cpu() { if(Options::i()->colors()) { + /* Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-", Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-"); -# ifndef XMRIG_NO_LIBCPUID + # ifndef XMRIG_NO_LIBCPUID Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); -# endif + # endif + */ } else { - Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), - Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-"); + PRINT_MSG(" * CPU: " << Cpu::brand() << " (" << Cpu::threads() << "@" << Cpu::sockets() << ") " << + (Cpu::isX64() ? "" : "-") << "64 " << + (Cpu::hasAES() ? "" : "-") << "AES-NI"); # ifndef XMRIG_NO_LIBCPUID - Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); + PRINT_MSG(" * CPU L2/L3: " << (Cpu::l2() / 1024.0) << " MB/" << Cpu::l3() / 1024.0 << " MB"); # endif } } @@ -111,36 +113,29 @@ static void print_threads() buf[0] = '\0'; } - Log::i()->text(Options::i()->colors() ? - "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : - " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", - Options::i()->threads(), - Options::i()->algoName(), - Options::i()->algoVariant(), - Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "", - Options::i()->donateLevel(), - buf); + PRINT_MSG(" * THREADS: " << Options::i()->threads() << ", " << Options::i()->algoName() << ", av=" << + Options::i()->algoVariant() << ", donate-minutes=" << Options::i()->donateMinutes() << + ((Options::i()->donateMinutes() > 0) ? ("/" + + Log::ToString(Options::i()->minutesInCicle()) + " (" + Log::ToString((100 * + Options::i()->donateMinutes()) / + Options::i()->minutesInCicle()) + "%)") : "") << buf); } static void print_pools() { - const std::vector & pools = Options::i()->pools(); + const std::vector & pools = Options::i()->pools(); for(size_t i = 0; i < pools.size(); ++i) { - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : - " * POOL #%d: %s:%d", - i + 1, - pools[i]->host(), - pools[i]->port()); + PRINT_MSG(" * POOL #" << (i + 1) << ": " << pools[i].host() << ":" << pools[i].port()); } # ifdef APP_DEBUG for(size_t i = 0; i < pools.size(); ++i) { - Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), - pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash()); + PRINT_MSG(pools[i].host() << ":" << pools[i].port() << ", user: " << pools[i].user() << ", pass: " << + pools[i].password() << ", ka: " << pools[i].isKeepAlive() << ", nicehash: " << pools[i].isNicehash()); } # endif } @@ -154,8 +149,17 @@ static void print_api() return; } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : - " * API PORT: %d", Options::i()->apiPort()); + if(Options::i()->colors()) + { + /*TODO LOG + Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : + " * API PORT: %d", Options::i()->apiPort()); + */ + } + else + { + PRINT_MSG(" * API PORT: " << Options::i()->apiPort()); + } } #endif @@ -164,11 +168,13 @@ static void print_commands() { if(Options::i()->colors()) { + /* Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); + */ } else { - Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); + PRINT_MSG(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); } } diff --git a/src/api/Api.cpp b/src/api/Api.cpp index ed1f1a85..5ab4a831 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -21,6 +21,7 @@ * along with this program. If not, see . */ +#ifndef XMRIG_NO_API #include @@ -47,15 +48,15 @@ void Api::release() } -char* Api::get(const char* url, int* status) +std::string Api::get(const std::string & url, int* status) { if(!m_state) { - return nullptr; + return ""; } uv_mutex_lock(&m_mutex); - char* buf = m_state->get(url, status); + std::string buf = m_state->get(url, status); uv_mutex_unlock(&m_mutex); return buf; @@ -86,3 +87,5 @@ void Api::tick(const NetworkState & network) m_state->tick(network); uv_mutex_unlock(&m_mutex); } + +#endif diff --git a/src/api/Api.h b/src/api/Api.h index b81543ef..660c7a25 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -26,7 +26,9 @@ #include +#include +#include "interfaces/interface.h" class ApiState; class Hashrate; @@ -39,7 +41,7 @@ public: static bool start(); static void release(); - static char* get(const char* url, int* status); + static std::string get(const std::string & url, int* status); static void tick(const Hashrate* hashrate); static void tick(const NetworkState & results); diff --git a/src/api/ApiState.cpp b/src/api/ApiState.cpp index fcf0dd27..aba2f4e7 100644 --- a/src/api/ApiState.cpp +++ b/src/api/ApiState.cpp @@ -31,7 +31,6 @@ # include "unistd.h" #endif - #include "api/ApiState.h" #include "Cpu.h" #include "Mem.h" @@ -50,14 +49,14 @@ extern "C" #include "crypto/c_keccak.h" } - static inline double normalize(double d) { +#ifndef _WIN32 if(!isnormal(d)) { return 0.0; } - +#endif return floor(d * 100.0) / 100.0; } @@ -70,9 +69,9 @@ ApiState::ApiState() memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); memset(m_workerId, 0, sizeof(m_workerId)); - if(Options::i()->apiWorkerId()) + if(0 < Options::i()->apiWorkerId().size()) { - strncpy(m_workerId, Options::i()->apiWorkerId(), sizeof(m_workerId) - 1); + strncpy(m_workerId, Options::i()->apiWorkerId().c_str(), sizeof(m_workerId) - 1); } else { @@ -89,7 +88,7 @@ ApiState::~ApiState() } -char* ApiState::get(const char* url, int* status) const +std::string ApiState::get(const std::string & url, int* status) const { rapidjson::Document doc; doc.SetObject(); @@ -126,14 +125,14 @@ void ApiState::tick(const NetworkState & network) } -char* ApiState::finalize(rapidjson::Document & doc) const +std::string ApiState::finalize(rapidjson::Document & doc) const { rapidjson::StringBuffer buffer(0, 4096); rapidjson::PrettyWriter writer(buffer); writer.SetMaxDecimalPlaces(10); doc.Accept(writer); - return strdup(buffer.GetString()); + return buffer.GetString(); } @@ -162,7 +161,9 @@ void ApiState::genId() memcpy(input + addrSize, APP_KIND, strlen(APP_KIND)); keccak(input, static_cast(inSize), hash, sizeof(hash)); - Job::toHex(hash, 8, m_id); + + char* hashChar = (char*)hash; + Job::toHex(std::string(hashChar, 8), m_id); delete [] input; break; @@ -237,11 +238,13 @@ void ApiState::getMiner(rapidjson::Document & doc) const doc.AddMember("version", APP_VERSION, allocator); doc.AddMember("kind", APP_KIND, allocator); - doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator); + doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent().c_str()), allocator); doc.AddMember("cpu", cpu, allocator); doc.AddMember("algo", rapidjson::StringRef(Options::i()->algoName()), allocator); doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator); - doc.AddMember("donate_level", Options::i()->donateLevel(), allocator); + + doc.AddMember("donate_minutes_per_cicle", Options::i()->donateMinutes(), allocator); + doc.AddMember("minutes_per_cicle", Options::i()->minutesInCicle(), allocator); } diff --git a/src/api/ApiState.h b/src/api/ApiState.h index 63442cb7..54c60ab1 100644 --- a/src/api/ApiState.h +++ b/src/api/ApiState.h @@ -28,6 +28,7 @@ #include "api/NetworkState.h" #include "rapidjson/fwd.h" +#include class Hashrate; @@ -38,12 +39,12 @@ public: ApiState(); ~ApiState(); - char* get(const char* url, int* status) const; + std::string get(const std::string & url, int* status) const; void tick(const Hashrate* hashrate); void tick(const NetworkState & results); private: - char* finalize(rapidjson::Document & doc) const; + std::string finalize(rapidjson::Document & doc) const; void genId(); void getConnection(rapidjson::Document & doc) const; void getHashrate(rapidjson::Document & doc) const; diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index ad646355..ce551ffb 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,24 +21,21 @@ * along with this program. If not, see . */ - +#ifndef XMRIG_NO_HTTPD #include #include - #include "api/Api.h" #include "api/Httpd.h" #include "log/Log.h" - -Httpd::Httpd(int port, const char* accessToken) : +Httpd::Httpd(int port, const std::string & accessToken) : m_accessToken(accessToken), m_port(port), m_daemon(nullptr) { } - bool Httpd::start() { if(!m_port) @@ -46,22 +43,8 @@ bool Httpd::start() return false; } - unsigned int flags = 0; - if(MHD_is_feature_supported(MHD_FEATURE_EPOLL)) - { - flags = MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_INTERNALLY_LINUX_ONLY; - } - else - { - flags = MHD_USE_SELECT_INTERNALLY; - } - - if(MHD_is_feature_supported(MHD_FEATURE_IPv6)) - { - flags |= MHD_USE_DUAL_STACK; - } - - m_daemon = MHD_start_daemon(flags, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END); + m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this, + MHD_OPTION_END); if(!m_daemon) { LOG_ERR("HTTP Daemon failed to start."); @@ -72,25 +55,25 @@ bool Httpd::start() } -int Httpd::auth(const char* header) +int Httpd::auth(const std::string & header) { - if(!m_accessToken) + if(m_accessToken.empty()) { return MHD_HTTP_OK; } - if(m_accessToken && !header) + if(0 < m_accessToken.size() && header.empty()) { return MHD_HTTP_UNAUTHORIZED; } - const size_t size = strlen(header); - if(size < 8 || strlen(m_accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) + const size_t size = header.size(); + if(size < 8 || m_accessToken.size() != size - 7 || "Bearer " == header.substr(0, 7)) { return MHD_HTTP_FORBIDDEN; } - return strncmp(m_accessToken, header + 7, strlen(m_accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; + return (m_accessToken == header.substr(7)) ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; } @@ -112,15 +95,16 @@ int Httpd::done(MHD_Connection* connection, int status, MHD_Response* rsp) } -int Httpd::handler(void* cls, struct MHD_Connection* connection, const char* url, const char* method, - const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls) +int Httpd::handlerStd(void* cls, struct MHD_Connection* connection, const std::string & url, + const std::string & method, const std::string & version, const std::string & upload_data, + size_t* upload_data_size, void** con_cls) { - if(strcmp(method, "OPTIONS") == 0) + if(method == "OPTIONS") { return done(connection, MHD_HTTP_OK, nullptr); } - if(strcmp(method, "GET") != 0) + if(method != "GET") { return MHD_NO; } @@ -132,12 +116,21 @@ int Httpd::handler(void* cls, struct MHD_Connection* connection, const char* url return done(connection, status, nullptr); } - char* buf = Api::get(url, &status); - if(buf == nullptr) + std::string buf = Api::get(url, &status); + if(buf.empty()) { return MHD_NO; } - MHD_Response* rsp = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE); + MHD_Response* rsp = MHD_create_response_from_buffer(buf.size(), (void*) buf.c_str(), MHD_RESPMEM_MUST_FREE); return done(connection, status, rsp); } + +int Httpd::handler(void* cls, MHD_Connection* connection, const char* url, const char* method, + const char* version, const char* upload_data, size_t* upload_data_size, + void** con_cls) +{ + return handlerStd(cls, connection, url, method, version, upload_data, upload_data_size, con_cls); +} + +#endif diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 17ce3faf..18da026b 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,29 +24,32 @@ #ifndef __HTTPD_H__ #define __HTTPD_H__ - #include - struct MHD_Connection; struct MHD_Daemon; struct MHD_Response; - class Httpd { public: - Httpd(int port, const char* accessToken); + Httpd(int port, const std::string & accessToken); bool start(); private: - int auth(const char* header); + int auth(const std::string & header); static int done(MHD_Connection* connection, int status, MHD_Response* rsp); - static int handler(void* cls, MHD_Connection* connection, const char* url, const char* method, - const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls); + static int handlerStd(void* cls, MHD_Connection* connection, const std::string & url, + const std::string & method, + const std::string & version, const std::string & upload_data, size_t* upload_data_size, + void** con_cls); - const char* m_accessToken; + static int handler(void* cls, MHD_Connection* connection, const char* url, const char* method, + const char* version, const char* upload_data, size_t* upload_data_size, + void** con_cls); + + const std::string & m_accessToken; const int m_port; MHD_Daemon* m_daemon; }; diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index 79023d6a..d2f25bc8 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -27,6 +27,8 @@ #include #include +#include "interfaces/interface.h" + #include "api/NetworkState.h" #include "net/SubmitResult.h" @@ -76,9 +78,9 @@ uint32_t NetworkState::latency() const } -void NetworkState::add(const SubmitResult & result, const char* error) +void NetworkState::add(const SubmitResult & result, const std::string & error) { - if(error) + if(0 < error.size()) { rejected++; return; @@ -98,9 +100,9 @@ void NetworkState::add(const SubmitResult & result, const char* error) } -void NetworkState::setPool(const char* host, int port, const char* ip) +void NetworkState::setPool(const std::string & host, int port, const std::string & ip) { - snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); + snprintf(pool, sizeof(pool) - 1, "%s:%d", host.c_str(), port); m_active = true; m_connectionTime = uv_now(uv_default_loop()); diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h index 2688cd86..dfbe6c2d 100644 --- a/src/api/NetworkState.h +++ b/src/api/NetworkState.h @@ -27,6 +27,7 @@ #include #include +#include class SubmitResult; @@ -40,12 +41,12 @@ public: int connectionTime() const; uint32_t avgTime() const; uint32_t latency() const; - void add(const SubmitResult & result, const char* error); - void setPool(const char* host, int port, const char* ip); + void add(const SubmitResult & result, const std::string & error); + void setPool(const std::string & host, int port, const std::string & ip); void stop(); char pool[256]; - std::array topDiff { { } }; + std::array topDiff; uint32_t diff; uint64_t accepted; uint64_t failures; diff --git a/src/config.json b/src/config.json index 7813d4b9..ad08a09c 100644 --- a/src/config.json +++ b/src/config.json @@ -1,11 +1,29 @@ { "algo": "cryptonight", // cryptonight (default) or cryptonight-lite + "user-agent": "", // custom user-agent "av": 0, // algorithm variation, 0 auto select "background": false, // true to run the miner in the background - "colors": true, // false to disable colored output + "colors": false, // true to enable colored output "cpu-affinity": null, // set process affinity to CPU core(s), mask "0x3" for cores 0 and 1 "cpu-priority": null, // set process priority (0 idle, 2 normal to 5 highest) - "donate-level": 5, // donate level, mininum 1% +/* Default donate setting: */ + "donate-level": 3, // default donate minutes (3 minutes each 1 hour) +/* Custom donate settings: + "donate-level": [ + { +// "donate-url": "fee.xmrig.com:443", // custom donate pool for cryptonight +// "donate-url-little": "fee.xmrig.com:3333", // custom donate pool for cryptonight-little +// "donate-user": "", // custom donate user +// "donate-pass": "", // custom donate pass +// "donate-keepalive": false, // custom donate keepalive +// "donate-nicehash": true, // custom donate nicehash + "donate-minutes": 3, // custom donate minutes for each cicle + "minutes-in-cicle": 60 // custom total minutes in a cicle (60 => 1 hour) + // that is [(57 minutes) to pool + (3 minutes) to donate...] and repeat all until miner ends. + } + ], +*/ + "debug": false, "log-file": null, // log all output to a file, example: "c:/some/path/xmrig.log" "max-cpu-usage": 75, // maximum CPU usage for automatic mode, usually limiting factor is CPU cache not this option. "print-time": 60, // print hashrate report every N seconds @@ -16,11 +34,14 @@ "threads": null, // number of miner threads "pools": [ { - "url": "pool.minemonero.pro:5555", // URL of mining server - "user": "", // username for mining server - "pass": "x", // password for mining server - "keepalive": true, // send keepalived for prevent timeout (need pool support) - "nicehash": false // enable nicehash/xmrig-proxy support + "url": "pool.minemonero.pro:3333", // --------------- URL of mining server + /* "url": "pool.minemonero.pro:443@localhost:8080",*/ // --------------- URL of mining server over HTTP (CONNECT) proxy + /* "url": "pool.minemonero.pro:7777#secret_keystream",*/ // URL of mining xmrig-proxy with encrypted support + /* "url": "pool.minemonero.pro:8080#secret_keystream@localhost:8080",*/ // URL of mining xmrig-proxy with encrypted support over HTTP (CONNECT) proxy + "user": "%HOST_NAME%_%IP_ADD%+100", // username for mining server using meta-data (%HOST_NAME%, %IP_ADD%, etc.) + "pass": "x", // password for mining server + "keepalive": true, // send keepalived for prevent timeout (need pool support) + "nicehash": false // enable nicehash/xmrig-proxy support } ], "api": { diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index b3586811..9003dd01 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -29,6 +29,8 @@ #include #include +#include "align.h" +#include "interfaces/interface.h" #define AEON_MEMORY 1048576 #define AEON_MASK 0xFFFF0 @@ -41,9 +43,9 @@ struct cryptonight_ctx { - alignas(16) uint8_t state0[200]; - alignas(16) uint8_t state1[200]; - alignas(16) uint8_t* memory; + VAR_ALIGN(16, uint8_t state0[200]); + VAR_ALIGN(16, uint8_t state1[200]); + VAR_ALIGN(16, uint8_t* memory); }; diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 0bd0b66e..e952f88c 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -463,6 +463,7 @@ inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + VARIANT1_1(&l0[idx0 & MASK]); VARIANT1_1(&l1[idx1 & MASK]); diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 56e4bac7..d6a2c890 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -77,7 +77,7 @@ void (* const extra_hashes[4])(const void*, size_t, char*) = {do_blake_hash, do_ -#if defined(__x86_64__) || defined(_M_AMD64) +#if (defined(__x86_64__) || defined(_M_AMD64)) && __cplusplus > 199711L # define EXTRACT64(X) _mm_cvtsi128_si64(X) # ifdef __GNUC__ @@ -90,7 +90,7 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi) # else #define __umul128 _umul128 # endif -#elif defined(__i386__) || defined(_M_IX86) +#elif defined(__i386__) || defined(_M_IX86) || __cplusplus <= 199711L # define HI32(X) \ _mm_srli_si128((X), 4) @@ -318,6 +318,17 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output) _mm_store_si128(output + 11, xout7); } +#if ! defined _WIN64 && defined _WIN32 +#if defined(_MSC_VER) && _MSC_VER < 1900 +static inline __m128i _mm_set_epi64x(const uint64_t __a, const uint64_t __b) +{ + __m128i ret; + ret.m128i_u64[1] = __a; + ret.m128i_u64[0] = __b; + return ret; +} +#endif +#endif template inline void cryptonight_single_hash(const void* __restrict__ input, size_t size, void* __restrict__ output, @@ -352,7 +363,9 @@ inline void cryptonight_single_hash(const void* __restrict__ input, size_t size, cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); } _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + VARIANT1_1(&l0[idx0 & MASK]); + idx0 = EXTRACT64(cx); bx0 = cx; @@ -429,6 +442,7 @@ inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + VARIANT1_1(&l0[idx0 & MASK]); VARIANT1_1(&l1[idx1 & MASK]); diff --git a/src/crypto/c_skein.c b/src/crypto/c_skein.c index 68c182f7..d35a56b5 100644 --- a/src/crypto/c_skein.c +++ b/src/crypto/c_skein.c @@ -654,7 +654,7 @@ static SkeinHashReturn Update(hashState* state, const SkeinBitSequence* data, Sk b = (u08b_t)((data[bCnt - 1] & (0 - mask)) | mask); /* apply bit padding on final byte */ Skein_512_Update(&state->u.ctx_512, data, bCnt - 1); /* process all but the final byte */ - Skein_512_Update(&state->u.ctx_512, &b, 1); /* process the (masked) partial byte */ + Skein_512_Update(&state->u.ctx_512, &b, 1); /* process the (masked) partial byte */ Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */ return SKEIN_SUCCESS; @@ -697,8 +697,7 @@ void xmr_skein(const SkeinBitSequence* data, SkeinBitSequence* hashval) // Skein_512_Init(&state.u.ctx_512, (size_t)XMR_HASHBITLEN); state.u.ctx_512.h.hashBitLen = XMR_HASHBITLEN; memcpy(state.u.ctx_512.X, SKEIN_512_IV_256, sizeof(state.u.ctx_512.X)); - Skein_512_Ctxt_t* ctx = &(state.u.ctx_512); - Skein_Start_New_Type(ctx, MSG); + Skein_Start_New_Type(&state.u.ctx_512, MSG); // Update if((XMR_DATABITLEN & 7) == 0) /* partial bytes? */ diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index f067b1c7..68a6d947 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -37,6 +37,8 @@ #include +#include "align.h" + #define saes_data(w) {\ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ @@ -86,8 +88,8 @@ #define saes_u2(p) saes_b2w( p, saes_f3(p), saes_f2(p), p) #define saes_u3(p) saes_b2w( p, p, saes_f3(p), saes_f2(p)) -alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; -alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); +VAR_ALIGN(16, const uint32_t saes_table[4][256]) = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; +VAR_ALIGN(16, const uint8_t saes_sbox[256]) = saes_data(saes_h0); static inline __m128i soft_aesenc(const uint32_t* in, __m128i key) { @@ -117,7 +119,7 @@ static inline uint32_t sub_word(uint32_t key) saes_sbox[key & 0xff]; } -#if defined(__clang__) || defined(XMRIG_ARM) +#if defined(__clang__) || defined(XMRIG_ARM) || __cplusplus <= 199711L static inline uint32_t _rotr(uint32_t value, uint32_t amount) { return (value >> amount) | (value << ((32 - amount) & 31)); diff --git a/src/donate.h b/src/donate.h index 3a000948..9af6b8e6 100644 --- a/src/donate.h +++ b/src/donate.h @@ -28,16 +28,28 @@ /* * Dev donation. * - * Percentage of your hashing power that you want to donate to the developer, can be 0 if you don't want to do that. - * Example of how it works for the default setting of 1: - * You miner will mine into your usual pool for 99 minutes, then switch to the developer's pool for 1 minute. - * Switching is instant, and only happens after a successful connection, so you never loose any hashes. + * Percentage of your hashing power that you want to donate to the donation server, + * can be 0 if you don't want to do that. * * If you plan on changing this setting to 0 please consider making a one off donation to my wallet: - * XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD - * BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT + * XMR: 433hhduFBtwVXtQiTTTeqyZsB36XaBLJB6bcQfnqqMs5RJitdpi8xBN21hWiEfuPp2hytmf1cshgK5Grgo6QUvLZCP2QSMi + * + * How it works: + * Other connections switch to donation pool until the first 60 minutes, kDonateLevel minutes each hour + * with overime compensation; but the period can be customizable. In proxy no way to use precise donation time! + * You can check actual donation via API. */ -constexpr const int kDonateLevel = 5; +enum +{ + kDonateMinutes = 3, + kMinutesInCicle = 60, + kDonateKeepAlive = false, + kDonateNiceHash = true, +}; +static const char* kDonateUrl = "fee.xmrig.com:443"; +static const char* kDonateUrlLittle = "fee.xmrig.com:3333"; +static const char* kDonateUser = ""; +static const char* kDonatePass = "x"; #endif /* __DONATE_H__ */ diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h index 4f240a8b..1d4236d9 100644 --- a/src/interfaces/IClientListener.h +++ b/src/interfaces/IClientListener.h @@ -38,10 +38,10 @@ class IClientListener public: virtual ~IClientListener() {} - virtual void onClose(Client* client, int failures) = 0; - virtual void onJobReceived(Client* client, const Job & job) = 0; - virtual void onLoginSuccess(Client* client) = 0; - virtual void onResultAccepted(Client* client, const SubmitResult & result, const char* error) = 0; + virtual void onClose(Client* client, int failures) = 0; + virtual void onJobReceived(Client* client, const Job & job) = 0; + virtual void onLoginSuccess(Client* client) = 0; + virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0; }; diff --git a/src/interfaces/IConsoleListener.h b/src/interfaces/IConsoleListener.h index 51aaf50c..af624ace 100644 --- a/src/interfaces/IConsoleListener.h +++ b/src/interfaces/IConsoleListener.h @@ -24,6 +24,7 @@ #ifndef __ICONSOLELISTENER_H__ #define __ICONSOLELISTENER_H__ +#include "interfaces/interface.h" class IConsoleListener { diff --git a/src/interfaces/ILogBackend.h b/src/interfaces/ILogBackend.h index a5e11438..bdd7f23f 100644 --- a/src/interfaces/ILogBackend.h +++ b/src/interfaces/ILogBackend.h @@ -7,6 +7,7 @@ * Copyright 2016-2017 XMRig * * + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -23,17 +24,25 @@ #ifndef __ILOGBACKEND_H__ #define __ILOGBACKEND_H__ - -#include - +#include "interfaces/interface.h" +#include class ILogBackend { public: + enum Level + { + ERR, + WARNING, + NOTICE, + INFO, + DEBUG + }; + virtual ~ILogBackend() {} - virtual void message(int level, const char* fmt, va_list args) = 0; - virtual void text(const char* fmt, va_list args) = 0; + virtual void message(Level level, const std::string & txt) = 0; + virtual void text(const std::string & txt) = 0; }; diff --git a/src/interfaces/IStrategy.h b/src/interfaces/IStrategy.h index 0d148666..bbf9c523 100644 --- a/src/interfaces/IStrategy.h +++ b/src/interfaces/IStrategy.h @@ -24,10 +24,9 @@ #ifndef __ISTRATEGY_H__ #define __ISTRATEGY_H__ - +#include "interfaces/interface.h" #include - class JobResult; diff --git a/src/interfaces/IStrategyListener.h b/src/interfaces/IStrategyListener.h index 4093aac6..8fb7469c 100644 --- a/src/interfaces/IStrategyListener.h +++ b/src/interfaces/IStrategyListener.h @@ -24,26 +24,23 @@ #ifndef __ISTRATEGYLISTENER_H__ #define __ISTRATEGYLISTENER_H__ - #include - +#include class Client; class IStrategy; class Job; class SubmitResult; - class IStrategyListener { public: virtual ~IStrategyListener() {} - virtual void onActive(Client* client) = 0; - virtual void onJob(Client* client, const Job & job) = 0; - virtual void onPause(IStrategy* strategy) = 0; - virtual void onResultAccepted(Client* client, const SubmitResult & result, const char* error) = 0; + virtual void onActive(Client* client) = 0; + virtual void onJob(Client* client, const Job & job) = 0; + virtual void onPause(IStrategy* strategy) = 0; + virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0; }; - #endif // __ISTRATEGYLISTENER_H__ diff --git a/src/interfaces/interface.h b/src/interfaces/interface.h new file mode 100644 index 00000000..987b75d4 --- /dev/null +++ b/src/interfaces/interface.h @@ -0,0 +1,64 @@ +/* XMRig - enWILLYado + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __INTERFACE_H__ +#define __INTERFACE_H__ + +#if __cplusplus <= 199711L +#define override +#define nullptr NULL +#endif + +#ifdef _WIN32 +#if defined(_MSC_VER) && _MSC_VER < 1900 + +// VS +#include +#include +#include +#define snprintf c99_snprintf +#define vsnprintf c99_vsnprintf + +__inline int c99_vsnprintf(char* outBuf, size_t size, const char* format, va_list ap) +{ + int count = -1; + + if(size != 0) + { + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + } + if(count == -1) + { + count = _vscprintf(format, ap); + } + + return count; +} + +__inline int c99_snprintf(char* outBuf, size_t size, const char* format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + + return count; +} +#endif +#endif + +#endif // __INTERFACE_H__ diff --git a/src/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp index abcbef72..904cd860 100644 --- a/src/log/ConsoleLog.cpp +++ b/src/log/ConsoleLog.cpp @@ -21,143 +21,98 @@ * along with this program. If not, see . */ - #include #include #include #include #include -#ifdef WIN32 -# include -# include -#endif - +#include #include "log/ConsoleLog.h" #include "log/Log.h" -#include "Options.h" - ConsoleLog::ConsoleLog(bool colors) : - m_colors(colors), - m_stream(nullptr) + m_colors(colors) { - if(uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) +} + +void ConsoleLog::message(Level level, const std::string & text) +{ + if(!isWritable()) { - Options::i()->setColors(false); - m_colors = false; return; } - uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL); - m_uvBuf.base = m_buf; - m_stream = reinterpret_cast(&m_tty); - -# ifdef WIN32 - HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); - if(handle != INVALID_HANDLE_VALUE) - { - DWORD mode = 0; - if(GetConsoleMode(handle, &mode)) - { - mode &= ~ENABLE_QUICK_EDIT_MODE; - SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS); - } - } -# endif -} - - -void ConsoleLog::message(int level, const char* fmt, va_list args) -{ + // + // time_t now = time(nullptr); tm stime; -# ifdef _WIN32 +#ifdef _WIN32 localtime_s(&stime, &now); -# else +#else localtime_r(&now, &stime); -# endif +#endif - const char* color = nullptr; + char buf[25]; + int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ", + stime.tm_year + 1900, + stime.tm_mon + 1, + stime.tm_mday, + stime.tm_hour, + stime.tm_min, + stime.tm_sec); + + // + // + std::string colorIni, colorEnd; if(m_colors) { + colorEnd = Log::CL_N(); switch(level) { - case Log::ERR: - color = Log::kCL_RED; + case ILogBackend::ERR: + colorIni = Log::CL_RED(); break; - case Log::WARNING: - color = Log::kCL_YELLOW; + case ILogBackend::WARNING: + colorIni = Log::CL_YELLOW(); break; - case Log::NOTICE: - color = Log::kCL_WHITE; + case ILogBackend::NOTICE: + colorIni = Log::CL_WHITE(); break; - case Log::DEBUG: - color = Log::kCL_GRAY; + case ILogBackend::DEBUG: + colorIni = Log::CL_GRAY(); break; default: - color = ""; break; } } - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - m_colors ? color : "", - fmt, - m_colors ? Log::kCL_N : "" - ); - - print(args); + print(std::string(buf, size) + colorIni + text + colorEnd); } - -void ConsoleLog::text(const char* fmt, va_list args) +void ConsoleLog::text(const std::string & txt) { - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); - - print(args); -} - - -bool ConsoleLog::isWritable() const -{ - if(!m_stream || uv_is_writable(m_stream) != 1) - { - return false; - } - - const uv_handle_type type = uv_guess_handle(1); - return type == UV_TTY || type == UV_NAMED_PIPE; -} - - -void ConsoleLog::print(va_list args) -{ - m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args); - if(m_uvBuf.len <= 0) + if(!isWritable()) { return; } - if(!isWritable()) - { - fputs(m_buf, stdout); - fflush(stdout); - } - else - { - uv_try_write(m_stream, &m_uvBuf, 1); - } + print(txt); +} + +bool ConsoleLog::isWritable() const +{ + return std::cout.good(); +} + +void ConsoleLog::print(const std::string & txt) +{ + std::cout << txt << std::endl; + std::cout.flush(); } diff --git a/src/log/ConsoleLog.h b/src/log/ConsoleLog.h index 2eefe6b8..a0c78ebb 100644 --- a/src/log/ConsoleLog.h +++ b/src/log/ConsoleLog.h @@ -36,19 +36,14 @@ class ConsoleLog : public ILogBackend public: ConsoleLog(bool colors); - void message(int level, const char* fmt, va_list args) override; - void text(const char* fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; private: bool isWritable() const; - void print(va_list args); + void print(const std::string & txt); bool m_colors; - char m_buf[512]; - char m_fmt[256]; - uv_buf_t m_uvBuf; - uv_stream_t* m_stream; - uv_tty_t m_tty; }; #endif /* __CONSOLELOG_H__ */ diff --git a/src/log/FileLog.cpp b/src/log/FileLog.cpp index ddd224c8..d32fe0b2 100644 --- a/src/log/FileLog.cpp +++ b/src/log/FileLog.cpp @@ -28,36 +28,37 @@ #include #include +#include +#include +#include "log/Log.h" #include "log/FileLog.h" - -FileLog::FileLog(const char* fileName) +FileLog::FileLog(const std::string & fileName) + : m_file_name(fileName) { - uv_fs_t req; - m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr); - uv_fs_req_cleanup(&req); } - -void FileLog::message(int level, const char* fmt, va_list args) +void FileLog::message(Level level, const std::string & txt) { - if(m_file < 0) + if(!isWritable()) { return; } + // + // time_t now = time(nullptr); tm stime; -# ifdef _WIN32 +#ifdef _WIN32 localtime_s(&stime, &now); -# else +#else localtime_r(&now, &stime); -# endif +#endif - char* buf = new char[512]; - int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ", + char buf[25]; + int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ", stime.tm_year + 1900, stime.tm_mon + 1, stime.tm_mday, @@ -65,34 +66,30 @@ void FileLog::message(int level, const char* fmt, va_list args) stime.tm_min, stime.tm_sec); - size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size; - buf[size] = '\n'; - - write(buf, size + 1); + // + // + write(std::string(buf, size) + txt); } - -void FileLog::text(const char* fmt, va_list args) +void FileLog::text(const std::string & txt) { - message(0, fmt, args); + if(!isWritable()) + { + return; + } + + write(txt); } - - -void FileLog::onWrite(uv_fs_t* req) +bool FileLog::isWritable() const { - delete [] static_cast(req->data); - - uv_fs_req_cleanup(req); - delete req; + return (m_file_name != "") && std::ofstream(m_file_name, std::ios_base::app).good(); } - -void FileLog::write(char* data, size_t size) +void FileLog::write(const std::string & txt) { - uv_buf_t buf = uv_buf_init(data, (unsigned int) size); - uv_fs_t* req = new uv_fs_t; - req->data = buf.base; + std::ofstream outfile; - uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite); + outfile.open(m_file_name, std::ios_base::app); + outfile << txt << std::endl; } diff --git a/src/log/FileLog.h b/src/log/FileLog.h index 5ba85013..bac31282 100644 --- a/src/log/FileLog.h +++ b/src/log/FileLog.h @@ -24,27 +24,21 @@ #ifndef __FILELOG_H__ #define __FILELOG_H__ - -#include - - #include "interfaces/ILogBackend.h" - class FileLog : public ILogBackend { public: - FileLog(const char* fileName); + FileLog(const std::string & fileName); - void message(int level, const char* fmt, va_list args) override; - void text(const char* fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; private: - static void onWrite(uv_fs_t* req); + bool isWritable() const; + void write(const std::string & txt); - void write(char* data, size_t size); - - int m_file; + const std::string m_file_name; }; #endif /* __FILELOG_H__ */ diff --git a/src/log/Log.cpp b/src/log/Log.cpp index 8a299eb5..d2b465a1 100644 --- a/src/log/Log.cpp +++ b/src/log/Log.cpp @@ -28,50 +28,35 @@ #include #include - #include "interfaces/ILogBackend.h" #include "log/Log.h" - Log* Log::m_self = nullptr; - -void Log::message(Log::Level level, const char* fmt, ...) +void Log::message(ILogBackend::Level level, const std::string & text) { - va_list args; - va_list copy; - va_start(args, fmt); - - for(ILogBackend* backend : m_backends) + for(size_t i = 0; i < m_backends.size(); ++i) { - va_copy(copy, args); - backend->message(level, fmt, copy); - va_end(copy); + auto backend = m_backends[i]; + backend->message(level, text); } } - -void Log::text(const char* fmt, ...) +void Log::text(const std::string & text) { - va_list args; - va_list copy; - va_start(args, fmt); - - for(ILogBackend* backend : m_backends) + for(size_t i = 0; i < m_backends.size(); ++i) { - va_copy(copy, args); - backend->text(fmt, copy); - va_end(copy); + auto backend = m_backends[i]; + backend->text(text); } - va_end(args); } - Log::~Log() { - for(auto backend : m_backends) + for(size_t i = 0; i < m_backends.size(); ++i) { + auto backend = m_backends[i]; delete backend; } } diff --git a/src/log/Log.h b/src/log/Log.h index 7f109b71..c0af6cfa 100644 --- a/src/log/Log.h +++ b/src/log/Log.h @@ -24,36 +24,45 @@ #ifndef __LOG_H__ #define __LOG_H__ - -#include #include +#include - -class ILogBackend; - +#include "interfaces/ILogBackend.h" class Log { public: - enum Level + + static const std::string & CL_N() + { + static const std::string kCL_N = "\x1B[0m"; + return kCL_N; + } + static const std::string & CL_RED() + { + static const std::string kCL_RED = "\x1B[31m"; + return kCL_RED; + } + static const std::string & CL_YELLOW() + { + static const std::string kCL_YELLOW = "\x1B[33m"; + return kCL_YELLOW; + } + static const std::string & CL_WHITE() + { + static const std::string kCL_WHITE = "\x1B[01;37m"; + return kCL_WHITE; + } + static const std::string & CL_GRAY() { - ERR, - WARNING, - NOTICE, - INFO, - DEBUG - }; - constexpr static const char* kCL_N = "\x1B[0m"; - constexpr static const char* kCL_RED = "\x1B[31m"; - constexpr static const char* kCL_YELLOW = "\x1B[33m"; - constexpr static const char* kCL_WHITE = "\x1B[01;37m"; - -# ifdef WIN32 - constexpr static const char* kCL_GRAY = "\x1B[01;30m"; -# else - constexpr static const char* kCL_GRAY = "\x1B[90m"; -# endif +#ifdef WIN32 + static const std::string kCL_GRAY = "\x1B[01;30m"; +#else + static const std::string kCL_GRAY = "\x1B[90m"; +#endif + return kCL_GRAY; + } static inline Log* i() { @@ -75,9 +84,22 @@ public: delete m_self; } - void message(Level level, const char* fmt, ...); - void text(const char* fmt, ...); + void message(ILogBackend::Level level, const std::string & text); + void text(const std::string & text); + static inline std::string TO_STRING(const std::basic_ostream & i) + { + const std::ostringstream & stream = static_cast(i); + return stream.str(); + } + + template + static inline std::string ToString(const T & i) + { + std::stringstream stream; + stream << i; + return stream.str(); + } private: inline Log() {} ~Log(); @@ -87,23 +109,25 @@ private: }; -#define LOG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__) -#define LOG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__) -#define LOG_NOTICE(x, ...) Log::i()->message(Log::NOTICE, x, ##__VA_ARGS__) -#define LOG_INFO(x, ...) Log::i()->message(Log::INFO, x, ##__VA_ARGS__) +#define PRINT_MSG(x) Log::i()->text(Log::TO_STRING(std::ostringstream() << " " << x)) + +#define LOG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::ostringstream() << " " << x)) +#define LOG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::ostringstream() << " " << x)) +#define LOG_NOTICE(x) Log::i()->message(ILogBackend::NOTICE, Log::TO_STRING(std::ostringstream() << " " << x)) +#define LOG_INFO(x) Log::i()->message(ILogBackend::INFO, Log::TO_STRING(std::ostringstream() << " " << x)) #ifdef APP_DEBUG -# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__) +#define LOG_DEBUG(x) Log::i()->message(ILogBackend::DEBUG, Log::TO_STRING(std::ostringstream() << " " << x)) #else -# define LOG_DEBUG(x, ...) +#define LOG_DEBUG(x) #endif #if defined(APP_DEBUG) || defined(APP_DEVEL) -# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__) -# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__) +#define LOG_DEBUG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::ostringstream() << " " << x)) +#define LOG_DEBUG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::ostringstream() << " " << x)) #else -# define LOG_DEBUG_ERR(x, ...) -# define LOG_DEBUG_WARN(x, ...) +#define LOG_DEBUG_ERR(x) +#define LOG_DEBUG_WARN(x) #endif #endif /* __LOG_H__ */ diff --git a/src/log/SysLog.cpp b/src/log/SysLog.cpp index a29ecd5f..91126ea4 100644 --- a/src/log/SysLog.cpp +++ b/src/log/SysLog.cpp @@ -21,6 +21,7 @@ * along with this program. If not, see . */ +#ifdef HAVE_SYSLOG_H #include @@ -34,14 +35,15 @@ SysLog::SysLog() openlog(APP_ID, LOG_PID, LOG_USER); } - -void SysLog::message(int level, const char* fmt, va_list args) +void SysLog::text(const std::string & txt) { - vsyslog(level, fmt, args); + message(INFO, txt); } -void SysLog::text(const char* fmt, va_list args) +void SysLog::message(Level level, const std::string & txt) { - message(LOG_INFO, fmt, args); + syslog(level == INFO ? LOG_INFO : LOG_NOTICE, "%s", txt.c_str()); } + +#endif \ No newline at end of file diff --git a/src/log/SysLog.h b/src/log/SysLog.h index 13c13f78..771e36d2 100644 --- a/src/log/SysLog.h +++ b/src/log/SysLog.h @@ -33,8 +33,8 @@ class SysLog : public ILogBackend public: SysLog(); - void message(int level, const char* fmt, va_list args) override; - void text(const char* fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; }; #endif /* __SYSLOG_BACKEND_H__ */ diff --git a/src/net/Client.cpp b/src/net/Client.cpp index 200469ac..f669c152 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2018 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,26 +37,26 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" - #ifdef XMRIG_PROXY_PROJECT -# include "proxy/JobResult.h" +#include "proxy/JobResult.h" #else -# include "net/JobResult.h" +#include "net/JobResult.h" #endif #ifdef _MSC_VER -# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#define strncasecmp(x,y,z) _strnicmp(x,y,z) #endif int64_t Client::m_sequence = 1; -Client::Client(int id, const char* agent, IClientListener* listener) : +Client::Client(int id, const std::string & agent, IClientListener* listener) : m_ipv6(false), m_nicehash(false), m_quiet(false), + m_encrypted(false), m_agent(agent), m_listener(listener), m_id(id), @@ -68,8 +68,8 @@ Client::Client(int id, const char* agent, IClientListener* listener) : m_stream(nullptr), m_socket(nullptr) { - memset(m_ip, 0, sizeof(m_ip)); memset(&m_hints, 0, sizeof(m_hints)); + memset(m_keystream, 0, sizeof(m_keystream)); m_resolver.data = this; @@ -80,10 +80,10 @@ Client::Client(int id, const char* agent, IClientListener* listener) : m_recvBuf.base = m_buf; m_recvBuf.len = sizeof(m_buf); -# ifndef XMRIG_PROXY_PROJECT +#ifndef XMRIG_PROXY_PROJECT m_keepAliveTimer.data = this; uv_timer_init(uv_default_loop(), &m_keepAliveTimer); -# endif +#endif } @@ -104,20 +104,30 @@ void Client::connect() * * @param url */ -void Client::connect(const Url* url) +void Client::connect(const Url & url) { setUrl(url); resolve(m_url.host()); } -void Client::setUrl(const Url* url) +void Client::setUrl(const Url & url) { - if(!url || !url->isValid()) + if(false == url.isValid()) { return; } + if(url.hasKeystream()) + { + url.copyKeystream(m_keystream, sizeof(m_keystream)); + m_encrypted = true; + } + else + { + m_encrypted = false; + } + m_url = url; } @@ -131,7 +141,7 @@ void Client::tick(uint64_t now) if(m_state == ConnectedState) { - LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port()); + LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] timeout"); close(); } @@ -142,12 +152,11 @@ void Client::tick(uint64_t now) } } - bool Client::disconnect() { -# ifndef XMRIG_PROXY_PROJECT +#ifndef XMRIG_PROXY_PROJECT uv_timer_stop(&m_keepAliveTimer); -# endif +#endif m_expire = 0; m_failures = -1; @@ -158,24 +167,29 @@ bool Client::disconnect() int64_t Client::submit(const JobResult & result) { -# ifdef XMRIG_PROXY_PROJECT - const char* nonce = result.nonce; - const char* data = result.result; -# else - char nonce[9]; - char data[65]; +#ifdef XMRIG_PROXY_PROJECT + const std::string nonce = result.nonce; + const std::string data = result.result; +#else + char nonce_buffer[9]; + char data_buffer[65]; - Job::toHex(reinterpret_cast(&result.nonce), 4, nonce); - nonce[8] = '\0'; + char* nonceChar = (char*)(&result.nonce); + Job::toHex(std::string(nonceChar, 4), nonce_buffer); + nonce_buffer[8] = '\0'; - Job::toHex(result.result, 32, data); - data[64] = '\0'; -# endif + char* resultChar = (char*)(&result.result); + Job::toHex(std::string(resultChar, 32), data_buffer); + data_buffer[64] = '\0'; + + const std::string nonce = nonce_buffer; + const std::string data = data_buffer; +#endif const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n", - m_sequence, m_rpcId.data(), result.jobId.data(), nonce, data); + m_sequence, m_rpcId.data().c_str(), result.jobId.data().c_str(), nonce.c_str(), data.c_str()); m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); return send(size); @@ -200,24 +214,24 @@ bool Client::close() } -bool Client::isCriticalError(const char* message) +bool Client::isCriticalError(const std::string & message) { - if(!message) + if(message.empty()) { return false; } - if(strncasecmp(message, "Unauthenticated", 15) == 0) + if(message == "Unauthenticated") { return true; } - if(strncasecmp(message, "your IP is banned", 17) == 0) + if(message == "your IP is banned") { return true; } - if(strncasecmp(message, "IP Address currently banned", 27) == 0) + if(message == "IP Address currently banned") { return true; } @@ -267,7 +281,7 @@ bool Client::parseJob(const rapidjson::Value & params, int* code) { if(!m_quiet) { - LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port()); + LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] duplicate job received, reconnect"); } close(); @@ -289,6 +303,14 @@ bool Client::parseLogin(const rapidjson::Value & result, int* code) m_nicehash = m_url.isNicehash(); + const rapidjson::Value & keystream = result["keystream"]; + if(true == keystream.IsString()) + { + const std::string newkeystream = keystream.GetString(); + memcpy(m_keystream, newkeystream.c_str(), std::min(sizeof(m_keystream), newkeystream.size())); + m_encrypted = true; + } + if(result.HasMember("extensions")) { parseExtensions(result["extensions"]); @@ -298,7 +320,7 @@ bool Client::parseLogin(const rapidjson::Value & result, int* code) } -int Client::resolve(const char* host) +int Client::resolve(const std::string & host) { setState(HostLookupState); @@ -310,12 +332,12 @@ int Client::resolve(const char* host) m_failures = 0; } - const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints); + const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host.c_str(), NULL, &m_hints); if(r) { if(!m_quiet) { - LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r)); + LOG_ERR("[" << host << ":" << m_url.port() << "] getaddrinfo error: \"" << uv_strerror(r) << "\""); } return 1; } @@ -324,15 +346,33 @@ int Client::resolve(const char* host) } -int64_t Client::send(size_t size) +int64_t Client::send(size_t size, const bool encrypted) { - LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf); - if(state() != ConnectedState || !uv_is_writable(m_stream)) + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send(" << size << " bytes): \"" << m_sendBuf << + "\""); + if((state() != ConnectedState && state() != ProxingState) || !uv_is_writable(m_stream)) { - LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state); + LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] send failed, invalid state: " << m_state); return -1; } + if(encrypted && m_encrypted) + { + // Encrypt + for(size_t i = 0; i < std::min(size, sizeof(SendBuf)); ++i) + { + m_sendBuf[i] ^= m_keystream[i]; + } + + char* send_encr_hex = static_cast(malloc(size * 2 + 1)); + memset(send_encr_hex, 0, size * 2 + 1); + Job::toHex(std::string(m_sendBuf, size), send_encr_hex); + send_encr_hex[size * 2] = '\0'; + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send encr.(" << size << " bytes): \"0x" << + send_encr_hex << "\""); + free(send_encr_hex); + } + uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); if(uv_try_write(m_stream, &buf, 1) < 0) @@ -354,19 +394,19 @@ void Client::connect(const std::vector & ipv4, const std::vector(addr->ai_addr), m_ip, 45); + uv_ip6_name(reinterpret_cast(addr->ai_addr), (char*)m_ip.c_str(), 45); } else { addr = ipv4[ipv4.size() == 1 ? 0 : rand() % ipv4.size()]; - uv_ip4_name(reinterpret_cast(addr->ai_addr), m_ip, 16); + uv_ip4_name(reinterpret_cast(addr->ai_addr), (char*)m_ip.c_str(), 16); } connect(addr->ai_addr); } -void Client::connect(sockaddr* addr) +void Client::connect(struct sockaddr* addr) { setState(ConnectingState); @@ -382,13 +422,35 @@ void Client::connect(sockaddr* addr) uv_tcp_init(uv_default_loop(), m_socket); uv_tcp_nodelay(m_socket, 1); -# ifndef WIN32 +#ifndef WIN32 uv_tcp_keepalive(m_socket, 1, 60); -# endif +#endif uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); } +void Client::prelogin() +{ + if(m_url.isProxyed()) + { + setState(ProxingState); + const std::string buffer = std::string("CONNECT ") + m_url.finalHost() + ":" + + std::to_string((unsigned long long)(m_url.finalPort())) + " HTTP/1.1\n"; + + const size_t size = buffer.size(); + memcpy(m_sendBuf, buffer.c_str(), size); + m_sendBuf[size] = '\n'; + m_sendBuf[size + 1] = '\0'; + + LOG_DEBUG("Prelogin send (" << size << " bytes): \"" << m_sendBuf << "\""); + send(size + 1, false); + } + else + { + setState(ConnectedState); + login(); + } +} void Client::login() { @@ -404,9 +466,9 @@ void Client::login() doc.AddMember("method", "login", allocator); rapidjson::Value params(rapidjson::kObjectType); - params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator); - params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator); - params.AddMember("agent", rapidjson::StringRef(m_agent), allocator); + params.AddMember("login", rapidjson::StringRef(m_url.user().c_str()), allocator); + params.AddMember("pass", rapidjson::StringRef(m_url.password().c_str()), allocator); + params.AddMember("agent", rapidjson::StringRef(m_agent.c_str()), allocator); doc.AddMember("params", params, allocator); @@ -434,11 +496,12 @@ void Client::parse(char* line, size_t len) line[len - 1] = '\0'; - LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line); + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] received (" << len << " bytes): \"" << line << + "\""); if(len < 32 || line[0] != '{') { - LOG_ERR("[%s:%u] JSON decode failed", m_url.host(), m_url.port()); + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] JSON decode failed"); return; } @@ -447,8 +510,8 @@ void Client::parse(char* line, size_t len) { if(!m_quiet) { - LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), - rapidjson::GetParseError_En(doc.GetParseError())); + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] JSON decode failed: \"" << + rapidjson::GetParseError_En(doc.GetParseError()) << "\""); } return; @@ -478,8 +541,9 @@ void Client::parseExtensions(const rapidjson::Value & value) return; } - for(const rapidjson::Value & ext : value.GetArray()) + for(size_t i = 0; i < value.GetArray().Size(); ++i) { + const rapidjson::Value & ext = value.GetArray()[i]; if(!ext.IsString()) { continue; @@ -493,25 +557,25 @@ void Client::parseExtensions(const rapidjson::Value & value) } -void Client::parseNotification(const char* method, const rapidjson::Value & params, +void Client::parseNotification(const std::string & method, const rapidjson::Value & params, const rapidjson::Value & error) { if(error.IsObject()) { if(!m_quiet) { - LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), error["message"].GetString(), - error["code"].GetInt()); + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << error["message"].GetString() << + "\", code: " << error["code"].GetInt()); } return; } - if(!method) + if(0 == method.size()) { return; } - if(strcmp(method, "job") == 0) + if(method == "job") { int code = -1; if(parseJob(params, &code)) @@ -522,7 +586,7 @@ void Client::parseNotification(const char* method, const rapidjson::Value & para return; } - LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method); + LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] unsupported method: \"" << method << "\""); } @@ -530,7 +594,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value & result, const ra { if(error.IsObject()) { - const char* message = error["message"].GetString(); + const std::string message = error["message"].GetString(); auto it = m_results.find(id); if(it != m_results.end()) @@ -541,7 +605,8 @@ void Client::parseResponse(int64_t id, const rapidjson::Value & result, const ra } else if(!m_quiet) { - LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt()); + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << message << "\", code: " << + error["code"].GetInt()); } if(id == 1 || isCriticalError(message)) @@ -564,7 +629,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value & result, const ra { if(!m_quiet) { - LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code); + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] login error code: " << code); } close(); @@ -581,7 +646,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value & result, const ra if(it != m_results.end()) { it->second.done(); - m_listener->onResultAccepted(this, it->second, nullptr); + m_listener->onResultAccepted(this, it->second, ""); m_results.erase(it); } } @@ -590,27 +655,27 @@ void Client::parseResponse(int64_t id, const rapidjson::Value & result, const ra void Client::ping() { send(snprintf(m_sendBuf, sizeof(m_sendBuf), - "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, - m_rpcId.data())); + "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", + m_sequence, m_rpcId.data().c_str())); } void Client::reconnect() { - setState(ConnectingState); - -# ifndef XMRIG_PROXY_PROJECT - if(m_url.isKeepAlive()) - { - uv_timer_stop(&m_keepAliveTimer); - } -# endif - if(m_failures == -1) { return m_listener->onClose(this, -1); } + setState(ConnectingState); + +#ifndef XMRIG_PROXY_PROJECT + if(m_url.isKeepAlive()) + { + uv_timer_stop(&m_keepAliveTimer); + } +#endif + m_failures++; m_listener->onClose(this, (int) m_failures); @@ -620,7 +685,7 @@ void Client::reconnect() void Client::setState(SocketState state) { - LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state); + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] state: " << state); if(m_state == state) { @@ -635,26 +700,27 @@ void Client::startTimeout() { m_expire = 0; -# ifndef XMRIG_PROXY_PROJECT +#ifndef XMRIG_PROXY_PROJECT if(!m_url.isKeepAlive()) { return; } - uv_timer_start(&m_keepAliveTimer, [](uv_timer_t* handle) - { - getClient(handle->data)->ping(); - }, kKeepAliveTimeout, 0); -# endif + uv_timer_start(&m_keepAliveTimer, &Client::onTimeout, kKeepAliveTimeout, 0); +#endif } +void Client::onTimeout(uv_timer_t* handle) +{ + getClient(handle->data)->ping(); +} void Client::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { auto client = getClient(handle->data); buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; - buf->len = client->m_recvBuf.len - client->m_recvBufPos; + buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos; } @@ -679,7 +745,8 @@ void Client::onConnect(uv_connect_t* req, int status) { if(!client->m_quiet) { - LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status)); + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] connect error: \"" << uv_strerror( + status) << "\""); } delete req; @@ -689,12 +756,11 @@ void Client::onConnect(uv_connect_t* req, int status) client->m_stream = static_cast(req->handle); client->m_stream->data = req->data; - client->setState(ConnectedState); uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); delete req; - client->login(); + client->prelogin(); } @@ -705,25 +771,57 @@ void Client::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { if(nread != UV_EOF && !client->m_quiet) { - LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread)); + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] read error: \"" << uv_strerror(( + int) nread) << "\""); } client->close(); return; } - if((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) + if((size_t) nread > (sizeof(Buf) - 8 - client->m_recvBufPos)) { client->close(); return; } + if(client->state() == ProxingState) + { + const char* const content = buf->base; + LOG_DEBUG("[" << client->m_url.host() << ":" << client->m_url.port() << "] received from proxy (" << nread << + " bytes): \"" << content << "\""); + + if(content == strstr(content, "HTTP/1.1 200")) + { + LOG_INFO("[" << client->m_url.host() << ":" << client->m_url.port() << "] Proxy connected to " << + client->m_url.finalHost() << ":" << client->m_url.finalPort() << "!"); + client->setState(ConnectedState); + client->login(); + } + return; + } + client->m_recvBufPos += nread; char* end; char* start = client->m_recvBuf.base; size_t remaining = client->m_recvBufPos; + if(client->m_encrypted) + { + char* read_encr_hex = static_cast(malloc(nread * 2 + 1)); + memset(read_encr_hex, 0, nread * 2 + 1); + Job::toHex(std::string(start, nread), read_encr_hex); + LOG_DEBUG("[" << client->m_ip << "] read encr. (" << nread << " bytes): \"0x" << read_encr_hex << "\""); + free(read_encr_hex); + + // DeEncrypt + for(int i = 0; i < (int)nread; ++i) + { + start[i] ^= client->m_keystream[i]; + } + } + while((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { end++; @@ -755,7 +853,8 @@ void Client::onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res) auto client = getClient(req->data); if(status < 0) { - LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status)); + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] DNS error: \"" << uv_strerror( + status) << "\""); return client->reconnect(); } @@ -780,8 +879,8 @@ void Client::onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res) if(ipv4.empty() && ipv6.empty()) { - LOG_ERR("[%s:%u] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_url.host(), - client->m_url.port()); + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << + "] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\""); uv_freeaddrinfo(res); return client->reconnect(); diff --git a/src/net/Client.h b/src/net/Client.h index 36c369f2..c5ec8e8b 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +25,11 @@ #define __CLIENT_H__ +#include #include #include -#include -#include "net/Id.h" #include "net/Job.h" #include "net/SubmitResult.h" #include "net/Url.h" @@ -49,35 +48,43 @@ public: UnconnectedState, HostLookupState, ConnectingState, + ProxingState, ConnectedState, ClosingState }; - constexpr static int kResponseTimeout = 20 * 1000; - constexpr static int kKeepAliveTimeout = 60 * 1000; + enum + { + kResponseTimeout = 20 * 1000, + kKeepAliveTimeout = 60 * 1000, + }; - Client(int id, const char* agent, IClientListener* listener); + Client(int id, const std::string & agent, IClientListener* listener); ~Client(); bool disconnect(); int64_t submit(const JobResult & result); void connect(); - void connect(const Url* url); - void setUrl(const Url* url); + void connect(const Url & url); + void setUrl(const Url & url); void tick(uint64_t now); inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } - inline const char* host() const + inline const std::string & host() const { return m_url.host(); } - inline const char* ip() const + inline const std::string & ip() const { return m_ip; } + inline void setIP(const std::string & iIp) + { + m_ip = iIp; + } inline const Job & job() const { return m_job; @@ -105,17 +112,19 @@ public: private: bool close(); - bool isCriticalError(const char* message); + bool isCriticalError(const std::string & message); bool parseJob(const rapidjson::Value & params, int* code); bool parseLogin(const rapidjson::Value & result, int* code); - int resolve(const char* host); - int64_t send(size_t size); + int resolve(const std::string & host); + int64_t send(size_t size, const bool encrypted = true); void connect(const std::vector & ipv4, const std::vector & ipv6); - void connect(sockaddr* addr); + void connect(struct sockaddr* addr); + void prelogin(); void login(); void parse(char* line, size_t len); void parseExtensions(const rapidjson::Value & value); - void parseNotification(const char* method, const rapidjson::Value & params, const rapidjson::Value & error); + void parseNotification(const std::string & method, const rapidjson::Value & params, + const rapidjson::Value & error); void parseResponse(int64_t id, const rapidjson::Value & result, const rapidjson::Value & error); void ping(); void reconnect(); @@ -125,6 +134,7 @@ private: static void onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); static void onClose(uv_handle_t* handle); static void onConnect(uv_connect_t* req, int status); + static void onTimeout(uv_timer_t* handle); static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); static void onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res); @@ -133,14 +143,19 @@ private: return static_cast(data); } + typedef char Buf[2048]; + typedef char SendBuf[768]; + addrinfo m_hints; bool m_ipv6; bool m_nicehash; bool m_quiet; - char m_buf[2048]; - char m_ip[46]; - char m_sendBuf[768]; - const char* m_agent; + char m_buf[sizeof(Buf)]; + std::string m_ip; + char m_sendBuf[sizeof(SendBuf)]; + char m_keystream[sizeof(SendBuf)]; + bool m_encrypted; + const std::string & m_agent; IClientListener* m_listener; int m_id; int m_retryPause; @@ -158,9 +173,9 @@ private: uv_tcp_t* m_socket; xmrig::Id m_rpcId; -# ifndef XMRIG_PROXY_PROJECT +#ifndef XMRIG_PROXY_PROJECT uv_timer_t m_keepAliveTimer; -# endif +#endif }; diff --git a/src/net/Id.h b/src/net/Id.h index a4833528..dd0c1eef 100644 --- a/src/net/Id.h +++ b/src/net/Id.h @@ -24,83 +24,61 @@ #ifndef __ID_H__ #define __ID_H__ - -#include - +#include namespace xmrig { - - class Id { public: - inline Id() : - m_data() + inline Id() + : m_data() { } - - inline Id(const char* id, size_t sizeFix = 0) + inline Id(const std::string & id, size_t sizeFix = 0) + : m_data(id.substr(0, id.size() - sizeFix)) { - setId(id, sizeFix); } - inline bool operator==(const Id & other) const { - return memcmp(m_data, other.m_data, sizeof(m_data)) == 0; + return m_data == other.m_data; } - inline bool operator!=(const Id & other) const { - return memcmp(m_data, other.m_data, sizeof(m_data)) != 0; + return !operator!=(other); } - - Id & operator=(const Id & other) + inline bool setId(const std::string & id, size_t sizeFix = 0) { - memcpy(m_data, other.m_data, sizeof(m_data)); + m_data.clear(); - return *this; - } - - - inline bool setId(const char* id, size_t sizeFix = 0) - { - memset(m_data, 0, sizeof(m_data)); - if(!id) + if(true == id.empty()) { return false; } - const size_t size = strlen(id); - if(size >= sizeof(m_data)) - { - return false; - } - - memcpy(m_data, id, size - sizeFix); + const size_t size = id.size(); + m_data = id.substr(0, size - sizeFix); return true; } - - inline const char* data() const + inline const std::string & data() const { return m_data; } inline bool isValid() const { - return *m_data != '\0'; + return 0 < m_data.size() && m_data[0] != '\0'; } private: - char m_data[64]; + std::string m_data; }; - } /* namespace xmrig */ diff --git a/src/net/Job.cpp b/src/net/Job.cpp index 72df49bd..dd4258cf 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -4,9 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +61,6 @@ static inline char hf_bin2hex(unsigned char c) Job::Job() : m_nicehash(false), - m_coin(), m_algo(xmrig::ALGO_CRYPTONIGHT), m_poolId(-2), m_threadId(-1), @@ -70,14 +68,13 @@ Job::Job() : m_size(0), m_diff(0), m_target(0), - m_blob() + m_id() { } Job::Job(int poolId, bool nicehash, int algo, int variant) : m_nicehash(nicehash), - m_coin(), m_algo(algo), m_poolId(poolId), m_threadId(-1), @@ -85,7 +82,7 @@ Job::Job(int poolId, bool nicehash, int algo, int variant) : m_size(0), m_diff(0), m_target(0), - m_blob() + m_id() { } @@ -216,9 +213,9 @@ bool Job::fromHex(const char* in, unsigned int len, unsigned char* out) } -void Job::toHex(const unsigned char* in, unsigned int len, char* out) +void Job::toHex(const std::string & in, char* out) { - for(unsigned int i = 0; i < len; i++) + for(size_t i = 0; i < in.size(); ++i) { out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4); out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); diff --git a/src/net/Job.h b/src/net/Job.h index d2aa800b..0d377fd0 100644 --- a/src/net/Job.h +++ b/src/net/Job.h @@ -28,6 +28,7 @@ #include #include +#include #include "net/Id.h" @@ -120,7 +121,7 @@ public: { return 0xFFFFFFFFFFFFFFFFULL / target; } - static void toHex(const unsigned char* in, unsigned int len, char* out); + static void toHex(const std::string & in, char* out); bool operator==(const Job & other) const; diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 66f7c223..21cb9510 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -36,6 +36,7 @@ class JobResult { public: inline JobResult() : poolId(0), diff(0), nonce(0) {} + inline JobResult(int poolId, const xmrig::Id & jobId, uint32_t nonce, const uint8_t* result, uint32_t diff) : poolId(poolId), diff(diff), diff --git a/src/net/Network.cpp b/src/net/Network.cpp index af3e36c7..930dbe27 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -52,7 +52,7 @@ Network::Network(const Options* options) : Workers::setListener(this); - const std::vector & pools = options->pools(); + const std::vector & pools = options->pools(); if(pools.size() > 1) { @@ -63,7 +63,7 @@ Network::Network(const Options* options) : m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this); } - if(m_options->donateLevel() > 0) + if(m_options->donateMinutes() > 0) { m_donate = new DonateStrategy(Platform::userAgent(), this); } @@ -101,20 +101,30 @@ void Network::onActive(Client* client) { if(client->id() == -1) { - LOG_NOTICE("dev donate started"); return; } m_state.setPool(client->host(), client->port(), client->ip()); - LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", - client->host(), client->port(), client->ip()); + LOG_INFO("use pool " << client->host() << ":" << client->port() << " " << client->ip()); } void Network::onJob(Client* client, const Job & job) { - if(m_donate && m_donate->isActive() && client->id() != -1) + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), + client->port(), job.diff()); + */ + } + else + { + LOG_INFO("new job from " << client->host() << ":" << client->port() << " diff " << job.diff()); + } + + if(m_donate && m_donate->reschedule(client->id() == -1)) { return; } @@ -139,7 +149,6 @@ void Network::onPause(IStrategy* strategy) { if(m_donate && m_donate == strategy) { - LOG_NOTICE("dev donate finished"); m_strategy->resume(); } @@ -152,39 +161,49 @@ void Network::onPause(IStrategy* strategy) } -void Network::onResultAccepted(Client* client, const SubmitResult & result, const char* error) +void Network::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { m_state.add(result, error); - if(error) + if(0 < error.size()) { - LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 - ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", - m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 + ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)", + m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); + */ + + } + else + { + LOG_INFO("rejected (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " \"" << + error << "\" (" << result.elapsed << " ms)"); + } } else { - LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 - ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", - m_state.accepted, m_state.rejected, result.diff, result.elapsed); + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 + ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)", + m_state.accepted, m_state.rejected, result.diff, result.elapsed); + */ + + } + else + { + LOG_INFO("accepted (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " (" << + result.elapsed << " ms)"); + } } } void Network::setJob(Client* client, const Job & job) { - if(m_options->colors()) - { - LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), - client->port(), job.diff()); - } - else - { - LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff()); - } - m_state.diff = job.diff(); Workers::setJob(job); } diff --git a/src/net/Network.h b/src/net/Network.h index 65e988f1..7d778b81 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -33,7 +33,7 @@ #include "interfaces/IJobResultListener.h" #include "interfaces/IStrategyListener.h" - +class DonateStrategy; class IStrategy; class Options; class Url; @@ -53,10 +53,13 @@ protected: void onJob(Client* client, const Job & job) override; void onJobResult(const JobResult & result) override; void onPause(IStrategy* strategy) override; - void onResultAccepted(Client* client, const SubmitResult & result, const char* error) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - constexpr static int kTickInterval = 1 * 1000; + enum + { + kTickInterval = 1 * 1000 + }; void setJob(Client* client, const Job & job); void tick(); @@ -64,7 +67,7 @@ private: static void onTick(uv_timer_t* handle); const Options* m_options; - IStrategy* m_donate; + DonateStrategy* m_donate; IStrategy* m_strategy; NetworkState m_state; uv_timer_t m_timer; diff --git a/src/net/Url.cpp b/src/net/Url.cpp index a2337439..b3639161 100644 --- a/src/net/Url.cpp +++ b/src/net/Url.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,34 +21,83 @@ * along with this program. If not, see . */ - #include #include -#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#else +#include +#undef min +#undef max +#endif #include "net/Url.h" #include "xmrig.h" - +#include "interfaces/interface.h" #ifdef _MSC_VER -# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#define strncasecmp(x,y,z) _strnicmp(x,y,z) #endif - -Url::Url() : - m_keepAlive(false), - m_nicehash(false), - m_host(nullptr), - m_password(nullptr), - m_user(nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), - m_variant(xmrig::VARIANT_AUTO), - m_url(nullptr), - m_port(kDefaultPort) +Url::Url() + : m_keepAlive(false), + m_nicehash(false), + m_host(), + m_password(), + m_user(), + m_port(kDefaultPort), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() { } +Url::Url(const std::string & url) + : m_keepAlive(false), + m_nicehash(false), + m_host(), + m_password(), + m_user(), + m_algo(xmrig::ALGO_CRYPTONIGHT), + m_variant(xmrig::VARIANT_AUTO), + m_port(kDefaultPort), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() +{ + parse(url); +} + +Url::Url(const std::string & host, + uint16_t port, + const std::string & user, + const std::string & password, + bool keepAlive, + bool nicehash, + int variant) + : m_keepAlive(keepAlive), + m_nicehash(nicehash), + m_host(host), + m_password(password), + m_user(user), + m_algo(xmrig::ALGO_CRYPTONIGHT), + m_variant(variant), + m_port(port), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() +{ +} + +Url::~Url() +{ +} /** * @brief Parse url. @@ -56,127 +105,117 @@ Url::Url() : * Valid urls: * example.com * example.com:3333 + * example.com:3333#keystream + * example.com:3333@proxy + * example.com:3333@proxy:8080 + * example.com:3333#keystream@proxy + * example.com:3333#keystream@proxy:8080 * stratum+tcp://example.com * stratum+tcp://example.com:3333 + * stratum+tcp://example.com:3333#keystream + * stratum+tcp://example.com:3333@proxy + * stratum+tcp://example.com:3333@proxy:8080 + * stratum+tcp://example.com:3333#keystream@proxy + * stratum+tcp://example.com:3333#keystream@proxy:8080 * * @param url */ -Url::Url(const char* url) : - m_keepAlive(false), - m_nicehash(false), - m_host(nullptr), - m_password(nullptr), - m_user(nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), - m_variant(xmrig::VARIANT_AUTO), - m_url(nullptr), - m_port(kDefaultPort) +bool Url::parse(const std::string & url) { - parse(url); -} + size_t base = 0; - -Url::Url(const char* host, uint16_t port, const char* user, const char* password, bool keepAlive, - bool nicehash, int variant) : - m_keepAlive(keepAlive), - m_nicehash(nicehash), - m_password(password ? strdup(password) : nullptr), - m_user(user ? strdup(user) : nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), - m_variant(variant), - m_url(nullptr), - m_port(port) -{ - m_host = strdup(host); -} - - -Url::~Url() -{ - free(m_host); - free(m_password); - free(m_user); - - if(m_url) + const size_t p = url.find("://"); + if(p != std::string::npos) { - delete [] m_url; - } -} - - -bool Url::parse(const char* url) -{ - const char* p = strstr(url, "://"); - const char* base = url; - - if(p) - { - if(strncasecmp(url, "stratum+tcp://", 14)) + static const std::string STRATUM_PREFIX = "stratum+tcp://"; + if(strncasecmp(url.c_str(), STRATUM_PREFIX.c_str(), STRATUM_PREFIX.size())) { return false; } - base = url + 14; + base = STRATUM_PREFIX.size(); } - if(!strlen(base) || *base == '/') + const std::string path = url.substr(base); + if(path.empty() || path[0] == '/') { return false; } - if(base[0] == '[') + const size_t port = path.find_first_of(':'); + size_t portini = port; + if(port != std::string::npos) { - return parseIPv6(base); + m_host = path.substr(0, port); + m_port = (uint16_t) strtol(path.substr(port + 1).c_str(), nullptr, 10); + } + else + { + portini = 0; } - const char* port = strchr(base, ':'); - if(!port) + const size_t proxy = path.find_first_of('@', portini); + const size_t keystream = path.find_first_of('#', portini); + if(keystream != std::string::npos) { - m_host = strdup(base); + if(port == std::string::npos) + { + m_host = path.substr(0, keystream); + } + if(proxy != std::string::npos) + { + m_keystream = path.substr(keystream + 1, proxy - keystream - 1); + } + else + { + m_keystream = path.substr(keystream + 1); + } + } + + if(proxy == std::string::npos) + { + if(port == std::string::npos && keystream == std::string::npos) + { + m_host = path; + } + return true; + } + else + { + if(port == std::string::npos && keystream == std::string::npos) + { + m_host = path.substr(0, proxy); + } + } + + const size_t proxyini = proxy + 1; + + const size_t proxyport = path.find_first_of(':', proxyini); + if(proxyport == std::string::npos) + { + m_proxy_host = path.substr(proxyini); return false; } - const size_t size = port++ - base + 1; - m_host = new char[size](); - memcpy(m_host, base, size - 1); - - m_port = (uint16_t) strtol(port, nullptr, 10); - return true; -} - - -bool Url::setUserpass(const char* userpass) -{ - const char* p = strchr(userpass, ':'); - if(!p) - { - return false; - } - - free(m_user); - free(m_password); - - m_user = static_cast(calloc(p - userpass + 1, 1)); - strncpy(m_user, userpass, p - userpass); - m_password = strdup(p + 1); + m_proxy_host = path.substr(proxyini, proxyport - proxyini); + m_proxy_port = (uint16_t) strtol(path.substr(proxyport + 1).c_str(), nullptr, 10); return true; } - -const char* Url::url() const +bool Url::setUserpass(const std::string & userpass) { - if(!m_url) + const size_t p = userpass.find_first_of(':'); + if(p == std::string::npos) { - const size_t size = strlen(m_host) + 8; - m_url = new char[size]; - - snprintf(m_url, size - 1, "%s:%d", m_host, m_port); + return false; } - return m_url; -} + setUser(userpass.substr(0, p)); + setPassword(userpass.substr(p + 1)); + return true; +} void Url::adjust(int algo) { @@ -187,43 +226,141 @@ void Url::adjust(int algo) m_algo = algo; - if(strstr(m_host, ".nicehash.com")) + + if(m_host.find(".nicehash.com") != std::string::npos) { m_keepAlive = false; m_nicehash = true; } - if(strstr(m_host, ".minergate.com")) + if(m_host.find(".minergate.com") != std::string::npos) { m_keepAlive = false; } } - -void Url::setPassword(const char* password) +static std::string & Replace(std::string & str, const std::string & what, const std::string & other) { - if(!password) + if(str.empty() || what.empty() || what == other) { - return; + return str; } - free(m_password); - m_password = strdup(password); + size_t start_pos = 0; + while((start_pos = str.find(what, start_pos)) != std::string::npos) + { + str.replace(start_pos, what.length(), other); + start_pos += other.length(); + } + + return str; +} + +static std::string GetHostName() +{ + char hostname[1024] = {'\0'}; + if(0 == gethostname(hostname, sizeof(hostname) - 1)) + { + // get hostname + for(int i = 0; hostname[i] != '\0'; ++i) + { + if(hostname[i] == '.' || hostname[i] == '+') + { + hostname[i] = '_'; + } + } + } + + return hostname; +} + +static std::string GetIpAddrs() +{ + std::string ret; +#ifndef _WIN32 + struct ifaddrs* ifAddrStruct = NULL; + struct ifaddrs* ifa = NULL; + void* tmpAddrPtr = NULL; + + if(0 == getifaddrs(&ifAddrStruct)) + { + for(ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) + { + if(!ifa->ifa_addr) + { + continue; + } + if(ifa->ifa_addr->sa_family == AF_INET) // check it is IP4 + { + // is a valid IP4 Address + tmpAddrPtr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; + char addressBuffer[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); + ret = addressBuffer; + } + else if(ifa->ifa_addr->sa_family == AF_INET6) // check it is IP6 + { + // is a valid IP6 Address + tmpAddrPtr = &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr; + char addressBuffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); + ret = addressBuffer; + } + } + } + if(ifAddrStruct != NULL) + { + freeifaddrs(ifAddrStruct); + } +#else + char hostname[1024] = {'\0'}; + gethostname(hostname, sizeof(hostname) - 1); + struct hostent* hostentry = gethostbyname(hostname); + + // get ip + if(hostentry != NULL) + { + const char* const ipbuf = inet_ntoa(*((struct in_addr*)hostentry->h_addr_list[0])); + if(ipbuf != NULL) + { + ret = ipbuf; + } + } +#endif + for(size_t i = 0; i < ret.size(); ++i) + { + if(ret[i] == '.' || ret[i] == '+' || ret[i] == '_') + { + ret[i] = '_'; + } + } + return ret; +} + +static std::string replaceWithTokens(const std::string & value) +{ + static const std::string HOST_NAME = GetHostName(); + static const std::string IP_ADDRS = GetIpAddrs(); + + // set user replacing tokens + std::string ret = value; + ret = Replace(ret, "%HOST_NAME%", HOST_NAME); + ret = Replace(ret, "%IP_ADDRS%", IP_ADDRS); + return ret; +} + +void Url::setPassword(const std::string & password) +{ + m_password = replaceWithTokens(password); } -void Url::setUser(const char* user) +void Url::setUser(const std::string & user) { - if(!user) - { - return; - } - - free(m_user); - m_user = strdup(user); + m_user = replaceWithTokens(user); } - +/* void Url::setVariant(int variant) { switch(variant) @@ -238,68 +375,13 @@ void Url::setVariant(int variant) break; } } +*/ - -bool Url::operator==(const Url & other) const +void Url::copyKeystream(char* keystreamDest, const size_t keystreamLen) const { - if(m_port != other.m_port || m_keepAlive != other.m_keepAlive || m_nicehash != other.m_nicehash) + if(hasKeystream()) { - return false; + memset(keystreamDest, 1, keystreamLen); + memcpy(keystreamDest, m_keystream.c_str(), std::min(keystreamLen, m_keystream.size())); } - - if(strcmp(host(), other.host()) != 0 || strcmp(user(), other.user()) != 0 || - strcmp(password(), other.password()) != 0) - { - return false; - } - - return true; -} - - -Url & Url::operator=(const Url* other) -{ - m_keepAlive = other->m_keepAlive; - m_algo = other->m_algo; - m_variant = other->m_variant; - m_nicehash = other->m_nicehash; - m_port = other->m_port; - - free(m_host); - m_host = strdup(other->m_host); - - setPassword(other->m_password); - setUser(other->m_user); - - if(m_url) - { - delete [] m_url; - m_url = nullptr; - } - - return *this; -} - - -bool Url::parseIPv6(const char* addr) -{ - const char* end = strchr(addr, ']'); - if(!end) - { - return false; - } - - const char* port = strchr(end, ':'); - if(!port) - { - return false; - } - - const size_t size = end - addr; - m_host = new char[size](); - memcpy(m_host, addr + 1, size - 1); - - m_port = (uint16_t) strtol(port + 1, nullptr, 10); - - return true; } diff --git a/src/net/Url.h b/src/net/Url.h index 3d407004..e07df91c 100644 --- a/src/net/Url.h +++ b/src/net/Url.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,20 +24,36 @@ #ifndef __URL_H__ #define __URL_H__ - #include +#include + +#include "interfaces/interface.h" class Url { public: - constexpr static const char* kDefaultPassword = "x"; - constexpr static const char* kDefaultUser = "x"; - constexpr static uint16_t kDefaultPort = 3333; + static const std::string & DefaultPassword() + { + static const std::string kDefaultPassword = "x"; + return kDefaultPassword; + } + static const std::string & DefaultUser() + { + static const std::string kDefaultUser = ""; + return kDefaultUser; + } + + enum + { + kDefaultPort = 3333, + kDefaultProxyPort = 8080, + }; Url(); - Url(const char* url); - Url(const char* host, uint16_t port, const char* user = nullptr, const char* password = nullptr, + Url(const std::string & url); + Url(const std::string & host, uint16_t port, const std::string & user = "", + const std::string & password = "", bool keepAlive = false, bool nicehash = false, int variant = -1); ~Url(); @@ -51,19 +67,23 @@ public: } inline bool isValid() const { - return m_host && m_port > 0; + return m_host.size() > 0 && m_port > 0; } - inline const char* host() const + inline const std::string & host() const { - return m_host; + return isProxyed() ? proxyHost() : finalHost(); } - inline const char* password() const + inline bool hasKeystream() const { - return m_password ? m_password : kDefaultPassword; + return m_keystream.size() > 0; } - inline const char* user() const + inline const std::string & password() const { - return m_user ? m_user : kDefaultUser; + return m_password.empty() ? DefaultPassword() : m_password; + } + inline const std::string & user() const + { + return m_user.empty() ? DefaultUser() : m_user; } inline int algo() const { @@ -74,45 +94,70 @@ public: return m_variant; } inline uint16_t port() const + { + return isProxyed() ? proxyPort() : finalPort(); + } + inline bool isProxyed() const + { + return proxyHost().size() > 0; + } + inline const std::string & finalHost() const + { + return m_host; + } + inline uint16_t finalPort() const { return m_port; } + inline const std::string & proxyHost() const + { + return m_proxy_host; + } + inline uint16_t proxyPort() const + { + return m_proxy_port; + } + inline void setProxyHost(const std::string & value) + { + m_proxy_host = value; + } + inline void setProxyPort(const uint16_t value) + { + m_proxy_port = value; + } + inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; } - inline void setNicehash(bool nicehash) - { - m_nicehash = nicehash; - } inline void setVariant(bool monero) { m_variant = monero; } + inline void setNicehash(bool nicehash) + { + m_nicehash = nicehash; + } - bool parse(const char* url); - bool setUserpass(const char* userpass); - const char* url() const; + bool parse(const std::string & url); + bool setUserpass(const std::string & userpass); void adjust(int algo); - void setPassword(const char* password); - void setUser(const char* user); - void setVariant(int variant); - - bool operator==(const Url & other) const; - Url & operator=(const Url* other); + void setPassword(const std::string & password); + void setUser(const std::string & user); + void copyKeystream(char* keystreamDest, const size_t keystreamLen) const; private: - bool parseIPv6(const char* addr); - bool m_keepAlive; bool m_nicehash; - char* m_host; - char* m_password; - char* m_user; + std::string m_host; + std::string m_password; + std::string m_user; int m_algo; int m_variant; - mutable char* m_url; uint16_t m_port; + std::string m_proxy_host; + uint16_t m_proxy_port; + std::string m_keystream; }; #endif /* __URL_H__ */ diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 859f3d37..3fee4f36 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,48 +24,119 @@ #include "interfaces/IStrategyListener.h" #include "net/Client.h" -#include "net/Job.h" +#include "log/Log.h" #include "net/strategies/DonateStrategy.h" #include "Options.h" -#include "xmrig.h" +#include extern "C" { #include "crypto/c_keccak.h" } +#ifdef max +#undef max +#endif -DonateStrategy::DonateStrategy(const char* agent, IStrategyListener* listener) : - m_active(false), - m_donateTime(Options::i()->donateLevel() * 60 * 1000), - m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000), - m_listener(listener) +enum { - uint8_t hash[200]; - char userId[65] = { 0 }; - const char* user = Options::i()->pools().front()->user(); + C_ONE_TICK = 1, + C_TICKS_PER_MINUTE = 60, +}; - keccak(reinterpret_cast(user), static_cast(strlen(user)), hash, sizeof(hash)); - Job::toHex(hash, 32, userId); +DonateStrategy::DonateStrategy(const std::string & agent, IStrategyListener* listener) : + m_active(false), + m_starting(false), + m_listener(listener), + m_donateTicks(0), + m_target(0), + m_ticks(0), + C_ONE_CICLE_IN_TICKS(Options::i()->donate().m_minutesInCicle * C_TICKS_PER_MINUTE) +{ + Url url(Options::i()->donate().m_url_little.empty() || Options::i()->algo() == xmrig::ALGO_CRYPTONIGHT ? + Options::i()->donate().m_url : + Options::i()->donate().m_url_little); - Url* url = new Url("thanks.xmrig.com", Options::i()->algo() == xmrig::ALGO_CRYPTONIGHT_LITE ? 5555 : 80, - userId, nullptr, false, true); + const Url & mainUrl = Options::i()->pools().front(); + if(true == mainUrl.isProxyed() && false == url.isProxyed()) + { + url.setProxyHost(mainUrl.proxyHost()); + url.setProxyPort(mainUrl.proxyPort()); + } + + if(Options::i()->donate().m_user.empty()) + { + uint8_t hash[200]; + char userId[65] = { 0 }; + const std::string & user = mainUrl.user(); + keccak(reinterpret_cast(user.c_str()), static_cast(user.size()), hash, sizeof(hash)); + Job::toHex(std::string((char*)hash, 32), userId); + + url.setUser(userId); + } + else + { + url.setUser(Options::i()->donate().m_user); + } + url.setPassword(Options::i()->donate().m_pass); + url.setKeepAlive(Options::i()->donate().m_keepAlive); + url.setNicehash(Options::i()->donate().m_niceHash); m_client = new Client(-1, agent, this); m_client->setUrl(url); m_client->setRetryPause(Options::i()->retryPause() * 1000); - m_client->setQuiet(true); - delete url; - - m_timer.data = this; - uv_timer_init(uv_default_loop(), &m_timer); - - idle(); + m_target = C_ONE_CICLE_IN_TICKS; } +bool DonateStrategy::reschedule(const bool isDonate) +{ + if(true == isDonate) + { + // + // the donate jobs never reschedules + // + return false; + } + else if(m_starting == true || m_active == true) + { + // + // If donate strategy is starting or active, check if donate time time (in ticks) expired + // + const uint64_t donateTargetTicks = Options::i()->donateMinutes() * C_TICKS_PER_MINUTE; + LOG_DEBUG("Dev donate ticks: " << m_donateTicks << "->" << donateTargetTicks); + if(m_donateTicks < donateTargetTicks) + { + return true; + } + + m_target = std::max(int(C_ONE_CICLE_IN_TICKS - m_donateTicks), int(C_ONE_TICK)) + m_ticks; + + LOG_NOTICE("Dev donate: finished!"); + stop(); + + return false; + } + else + { + // + // If donate strategy is starting or active, check if non donate time (in ticks) expired + // + LOG_DEBUG("Non-Dev donate ticks: " << m_ticks << "->" << m_target); + if(m_ticks < m_target) + { + return false; + } + + LOG_NOTICE("Dev donate: start!"); + connect(); + + return true; + } +} + int64_t DonateStrategy::submit(const JobResult & result) { return m_client->submit(result); @@ -75,76 +146,63 @@ int64_t DonateStrategy::submit(const JobResult & result) void DonateStrategy::connect() { m_client->connect(); + m_starting = true; } void DonateStrategy::stop() { - uv_timer_stop(&m_timer); + m_donateTicks = 0; m_client->disconnect(); + m_starting = false; } void DonateStrategy::tick(uint64_t now) { m_client->tick(now); + + m_ticks++; + + if(isActive()) + { + m_donateTicks++; + } } void DonateStrategy::onClose(Client* client, int failures) { + m_starting = false; + + if(!isActive()) + { + return; + } + + m_active = false; + m_listener->onPause(this); } void DonateStrategy::onJobReceived(Client* client, const Job & job) { + if(!isActive()) + { + m_active = true; + m_listener->onActive(client); + } + m_listener->onJob(client, job); } void DonateStrategy::onLoginSuccess(Client* client) { - if(!isActive()) - { - uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0); - } - - m_active = true; - m_listener->onActive(client); } -void DonateStrategy::onResultAccepted(Client* client, const SubmitResult & result, const char* error) +void DonateStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { m_listener->onResultAccepted(client, result, error); } - - -void DonateStrategy::idle() -{ - uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0); -} - - -void DonateStrategy::suspend() -{ - m_client->disconnect(); - - m_active = false; - m_listener->onPause(this); - - idle(); -} - - -void DonateStrategy::onTimer(uv_timer_t* handle) -{ - auto strategy = static_cast(handle->data); - - if(!strategy->isActive()) - { - return strategy->connect(); - } - - strategy->suspend(); -} diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index e6a5d2ab..41d3c797 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2017 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,9 +25,6 @@ #define __DONATESTRATEGY_H__ -#include - - #include "interfaces/IClientListener.h" #include "interfaces/IStrategy.h" @@ -40,9 +37,9 @@ class Url; class DonateStrategy : public IStrategy, public IClientListener { public: - DonateStrategy(const char* agent, IStrategyListener* listener); + DonateStrategy(const std::string & agent, IStrategyListener* listener); + bool reschedule(const bool isDonate); -public: inline bool isActive() const override { return m_active; @@ -58,20 +55,17 @@ protected: void onClose(Client* client, int failures) override; void onJobReceived(Client* client, const Job & job) override; void onLoginSuccess(Client* client) override; - void onResultAccepted(Client* client, const SubmitResult & result, const char* error) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - void idle(); - void suspend(); - - static void onTimer(uv_timer_t* handle); - bool m_active; + bool m_starting; Client* m_client; - const int m_donateTime; - const int m_idleTime; IStrategyListener* m_listener; - uv_timer_t m_timer; + uint64_t m_donateTicks; + uint64_t m_target; + uint64_t m_ticks; + const unsigned short C_ONE_CICLE_IN_TICKS; }; -#endif /* __DONATESTRATEGY_H__ */ +#endif /* __SINGLEPOOLSTRATEGY_H__ */ diff --git a/src/net/strategies/FailoverStrategy.cpp b/src/net/strategies/FailoverStrategy.cpp index 73e2b1fa..e01e2184 100644 --- a/src/net/strategies/FailoverStrategy.cpp +++ b/src/net/strategies/FailoverStrategy.cpp @@ -28,14 +28,15 @@ #include "Options.h" -FailoverStrategy::FailoverStrategy(const std::vector & urls, const char* agent, +FailoverStrategy::FailoverStrategy(const std::vector & urls, const std::string & agent, IStrategyListener* listener) : m_active(-1), m_index(0), m_listener(listener) { - for(const Url* url : urls) + for(size_t i = 0; i < urls.size(); ++i) { + const Url & url = urls[i]; add(url, agent); } } @@ -80,8 +81,9 @@ void FailoverStrategy::stop() void FailoverStrategy::tick(uint64_t now) { - for(Client* client : m_pools) + for(size_t i = 0; i < m_pools.size(); ++i) { + Client* client = m_pools[i]; client->tick(now); } } @@ -146,13 +148,13 @@ void FailoverStrategy::onLoginSuccess(Client* client) } -void FailoverStrategy::onResultAccepted(Client* client, const SubmitResult & result, const char* error) +void FailoverStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { m_listener->onResultAccepted(client, result, error); } -void FailoverStrategy::add(const Url* url, const char* agent) +void FailoverStrategy::add(const Url & url, const std::string & agent) { Client* client = new Client((int) m_pools.size(), agent, this); client->setUrl(url); diff --git a/src/net/strategies/FailoverStrategy.h b/src/net/strategies/FailoverStrategy.h index 6c2da14c..3a276c5d 100644 --- a/src/net/strategies/FailoverStrategy.h +++ b/src/net/strategies/FailoverStrategy.h @@ -1,26 +1,25 @@ -* Copyright 2010 Jeff Garzik < jgarzik@pobox.com > -* Copyright 2012 - 2014 pooler < pooler@litecoinpool.org > -* Copyright 2014 Lucas Jones < https: //github.com/lucasjones> -* Copyright 2014 - 2016 Wolf9466 < https: //github.com/OhGodAPet> -* Copyright 2016 Jay D Dee < jayddee246@gmail.com > -* Copyright 2016 - 2017 XMRig < support@xmrig.com > -* -* -* This program is free software: -you can redistribute it and / or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; -without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see < http : //www.gnu.org/licenses/>. -* / +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef __FAILOVERSTRATEGY_H__ #define __FAILOVERSTRATEGY_H__ @@ -41,7 +40,7 @@ class Url; class FailoverStrategy : public IStrategy, public IClientListener { public: -FailoverStrategy(const std::vector & urls, const char* agent, IStrategyListener* listener); + FailoverStrategy(const std::vector & urls, const std::string & agent, IStrategyListener* listener); public: inline bool isActive() const override @@ -59,10 +58,10 @@ protected: void onClose(Client* client, int failures) override; void onJobReceived(Client* client, const Job & job) override; void onLoginSuccess(Client* client) override; - void onResultAccepted(Client* client, const SubmitResult & result, const char* error) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - void add(const Url* url, const char* agent); + void add(const Url & url, const std::string & agent); int m_active; int m_index; diff --git a/src/net/strategies/SinglePoolStrategy.cpp b/src/net/strategies/SinglePoolStrategy.cpp index 2f4a1c4e..5f51afe6 100644 --- a/src/net/strategies/SinglePoolStrategy.cpp +++ b/src/net/strategies/SinglePoolStrategy.cpp @@ -28,7 +28,8 @@ #include "Options.h" -SinglePoolStrategy::SinglePoolStrategy(const Url* url, const char* agent, IStrategyListener* listener) : +SinglePoolStrategy::SinglePoolStrategy(const Url & url, const std::string & agent, + IStrategyListener* listener) : m_active(false), m_listener(listener) { @@ -98,7 +99,8 @@ void SinglePoolStrategy::onLoginSuccess(Client* client) } -void SinglePoolStrategy::onResultAccepted(Client* client, const SubmitResult & result, const char* error) +void SinglePoolStrategy::onResultAccepted(Client* client, const SubmitResult & result, + const std::string & error) { m_listener->onResultAccepted(client, result, error); } diff --git a/src/net/strategies/SinglePoolStrategy.h b/src/net/strategies/SinglePoolStrategy.h index 20d8bb00..f61066d9 100644 --- a/src/net/strategies/SinglePoolStrategy.h +++ b/src/net/strategies/SinglePoolStrategy.h @@ -37,7 +37,7 @@ class Url; class SinglePoolStrategy : public IStrategy, public IClientListener { public: - SinglePoolStrategy(const Url* url, const char* agent, IStrategyListener* listener); + SinglePoolStrategy(const Url & url, const std::string & agent, IStrategyListener* listener); public: inline bool isActive() const override @@ -55,7 +55,7 @@ protected: void onClose(Client* client, int failures) override; void onJobReceived(Client* client, const Job & job) override; void onLoginSuccess(Client* client) override; - void onResultAccepted(Client* client, const SubmitResult & result, const char* error) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: bool m_active; diff --git a/src/version.h b/src/version.h index cfaf7e9c..24ee9c9e 100644 --- a/src/version.h +++ b/src/version.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2016-2018 XMRig , + * Copyright 2016-2018 XMRig + * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,19 +24,19 @@ #ifndef __VERSION_H__ #define __VERSION_H__ -#define APP_ID "xmrig" -#define APP_NAME "XMRig" -#define APP_DESC "XMRig CPU miner" -#define APP_VERSION "2.5.0" -#define APP_DOMAIN "xmrig.com" -#define APP_SITE "www.xmrig.com" -#define APP_COPYRIGHT "Copyright (C) 2016-2018 xmrig.com" +#define APP_ID "xmrig-eWa" +#define APP_NAME "XMRig-eWa" +#define APP_DESC "XMRig CPU miner-eWa" +#define APP_VERSION "3.0.3-3" +#define APP_DOMAIN "enWILLYado.com" +#define APP_SITE "www.enWILLYado.com" +#define APP_COPYRIGHT "Copyright (C) 2016-2018 xmrig.com by enWILLYado.com" #define APP_KIND "cpu" -#define APP_VER_MAJOR 2 -#define APP_VER_MINOR 5 -#define APP_VER_BUILD 0 -#define APP_VER_REV 0 +#define APP_VER_MAJOR 3 +#define APP_VER_MINOR 0 +#define APP_VER_BUILD 3 +#define APP_VER_REV 3 #ifdef _MSC_VER # if (_MSC_VER >= 1910) diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index d958630f..5e18e9f0 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -22,14 +22,14 @@ * along with this program. If not, see . */ - -#include - - #include "crypto/CryptoNight.h" #include "workers/DoubleWorker.h" #include "workers/Workers.h" +#ifndef _WIN32 +#include +#include +#endif class DoubleWorker::State { @@ -69,7 +69,11 @@ void DoubleWorker::start() { do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); +#ifdef _WIN32 + Sleep(200); +#else + usleep(200 * 1000); +#endif } while(Workers::isPaused()); @@ -105,8 +109,6 @@ void DoubleWorker::start() Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff())); } - - std::this_thread::yield(); } consumeJob(); diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index b6111fd3..639e0a22 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -23,6 +23,7 @@ #include "workers/Handle.h" +#include "interfaces/interface.h" Handle::Handle(int threadId, int threads, int64_t affinity, int priority) : diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index 48532a5f..b2ff200b 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -21,9 +21,44 @@ * along with this program. If not, see . */ - +#ifndef _WIN32 +#if __cplusplus <= 199711L +#include +#else #include +#define USE_CHRONO +#endif +#else +#define isnormal(x) (_fpclass(x) == _FPCLASS_NN || _fpclass(x) == _FPCLASS_PN) +#define WIN32_LEAN_AND_MEAN +#include +#include // portable: uint64_t MSVC: __int64 +#include + +static int gettimeofday(struct timeval* tp, struct timezone* tzp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t)file_time.dwLowDateTime) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long)((time - EPOCH) / 10000000L); + tp->tv_usec = (long)(system_time.wMilliseconds * 1000); + return 0; +} +#endif + #include +#include #include #include @@ -32,11 +67,12 @@ #include "workers/Hashrate.h" -inline const char* format(double h, char* buf, size_t size) +inline std::string format(double value) { - if(isnormal(h)) + char buf[8]; + if(isnormal(value)) { - snprintf(buf, size, "%03.1f", h); + snprintf(buf, sizeof(buf), "%03.1f", value); return buf; } @@ -94,8 +130,14 @@ double Hashrate::calc(size_t ms) const double Hashrate::calc(size_t threadId, size_t ms) const { +#ifdef USE_CHRONO using namespace std::chrono; const uint64_t now = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); +#else + struct timeval tp; + gettimeofday(&tp, NULL); + const uint64_t now = tp.tv_sec * 1000 + tp.tv_usec / 1000; +#endif uint64_t earliestHashCount = 0; uint64_t earliestStamp = 0; @@ -130,12 +172,12 @@ double Hashrate::calc(size_t threadId, size_t ms) const if(!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { - return nan(""); + return std::numeric_limits::quiet_NaN() ; } if(lastestStamp - earliestStamp == 0) { - return nan(""); + return std::numeric_limits::quiet_NaN() ; } double hashes, time; @@ -159,19 +201,11 @@ void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp) void Hashrate::print() { - char num1[8]; - char num2[8]; - char num3[8]; - char num4[8]; - - LOG_INFO(Options::i()->colors() ? - "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : - "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s", - format(calc(ShortInterval), num1, sizeof(num1)), - format(calc(MediumInterval), num2, sizeof(num2)), - format(calc(LargeInterval), num3, sizeof(num3)), - format(m_highest, num4, sizeof(num4)) - ); + LOG_INFO("speed 2.5s/60s/15m " << + format(calc(ShortInterval)) << " " << + format(calc(MediumInterval)) << " " << + format(calc(LargeInterval)) << " H/s max: " << + format(m_highest) << " H/s"); } diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index cfa8f3c6..eb577244 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -59,8 +59,11 @@ public: private: static void onReport(uv_timer_t* handle); - constexpr static size_t kBucketSize = 2 << 11; - constexpr static size_t kBucketMask = kBucketSize - 1; + enum + { + kBucketSize = 2 << 11, + kBucketMask = kBucketSize - 1, + }; double m_highest; int m_threads; diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 40f3fe85..8dc1d78c 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -22,14 +22,14 @@ * along with this program. If not, see . */ - -#include - - #include "crypto/CryptoNight.h" #include "workers/SingleWorker.h" #include "workers/Workers.h" +#ifndef _WIN32 +#include +#include +#endif SingleWorker::SingleWorker(Handle* handle) : Worker(handle) @@ -45,7 +45,11 @@ void SingleWorker::start() { do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); +#ifdef _WIN32 + Sleep(200); +#else + usleep(200 * 1000); +#endif } while(Workers::isPaused()); @@ -71,8 +75,6 @@ void SingleWorker::start() { Workers::submit(m_result); } - - std::this_thread::yield(); } consumeJob(); diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 437851d8..bf7c4fdf 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -21,15 +21,46 @@ * along with this program. If not, see . */ -#include - - #include "Cpu.h" #include "Mem.h" #include "Platform.h" #include "workers/Handle.h" #include "workers/Worker.h" +#ifndef _WIN32 +#if __cplusplus <= 199711L +#include +#else +#include +#define USE_CHRONO +#endif +#else +#define WIN32_LEAN_AND_MEAN +#include +#include // portable: uint64_t MSVC: __int64 +#include + +static int gettimeofday(struct timeval* tp, struct timezone* tzp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t)file_time.dwLowDateTime) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long)((time - EPOCH) / 10000000L); + tp->tv_usec = (long)(system_time.wMilliseconds * 1000); + return 0; +} +#endif Worker::Worker(Handle* handle) : m_id(handle->threadId()), @@ -56,10 +87,15 @@ Worker::~Worker() void Worker::storeStats() { +#ifdef USE_CHRONO using namespace std::chrono; + const uint64_t now = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); +#else + struct timeval tp; + gettimeofday(&tp, NULL); + const uint64_t now = tp.tv_sec * 1000 + tp.tv_usec / 1000; +#endif - const uint64_t timestamp = time_point_cast - (high_resolution_clock::now()).time_since_epoch().count(); - m_hashCount.store(m_count, std::memory_order_relaxed); - m_timestamp.store(timestamp, std::memory_order_relaxed); + m_hashCount = m_count; + m_timestamp = now; } diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 722a1b4d..9b144adf 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -25,10 +25,10 @@ #define __WORKER_H__ -#include #include +#include "interfaces/interface.h" #include "interfaces/IWorker.h" @@ -44,11 +44,11 @@ public: inline uint64_t hashCount() const override { - return m_hashCount.load(std::memory_order_relaxed); + return m_hashCount; } inline uint64_t timestamp() const override { - return m_timestamp.load(std::memory_order_relaxed); + return m_timestamp; } protected: @@ -57,8 +57,8 @@ protected: cryptonight_ctx* m_ctx; int m_id; int m_threads; - std::atomic m_hashCount; - std::atomic m_timestamp; + uint64_t m_hashCount; + uint64_t m_timestamp; uint64_t m_count; uint64_t m_sequence; }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 39bbc9b7..f2dae94b 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -40,8 +40,8 @@ bool Workers::m_enabled = true; Hashrate* Workers::m_hashrate = nullptr; IJobResultListener* Workers::m_listener = nullptr; Job Workers::m_job; -std::atomic Workers::m_paused; -std::atomic Workers::m_sequence; +int Workers::m_paused; +uint64_t Workers::m_sequence; std::list Workers::m_queue; std::vector Workers::m_workers; uint64_t Workers::m_ticks = 0; @@ -180,8 +180,9 @@ void Workers::onResult(uv_async_t* handle) } uv_mutex_unlock(&m_mutex); - for(auto result : results) + for(std::list::iterator itr = results.begin(); itr != results.end(); ++itr) { + auto result = *itr; m_listener->onJobResult(result); } @@ -191,8 +192,9 @@ void Workers::onResult(uv_async_t* handle) void Workers::onTick(uv_timer_t* handle) { - for(Handle* handle : m_workers) + for(size_t i = 0; i < m_workers.size(); ++i) { + Handle* handle = m_workers[i]; if(!handle->worker()) { return; diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 8e67815d..e2ee5d65 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -24,8 +24,6 @@ #ifndef __WORKERS_H__ #define __WORKERS_H__ - -#include #include #include #include @@ -56,15 +54,15 @@ public: } static inline bool isOutdated(uint64_t sequence) { - return m_sequence.load(std::memory_order_relaxed) != sequence; + return m_sequence != sequence; } static inline bool isPaused() { - return m_paused.load(std::memory_order_relaxed) == 1; + return m_paused == 1; } static inline uint64_t sequence() { - return m_sequence.load(std::memory_order_relaxed); + return m_sequence; } static inline void pause() { @@ -87,8 +85,8 @@ private: static Hashrate* m_hashrate; static IJobResultListener* m_listener; static Job m_job; - static std::atomic m_paused; - static std::atomic m_sequence; + static int m_paused; + static uint64_t m_sequence; static std::list m_queue; static std::vector m_workers; static uint64_t m_ticks; diff --git a/src/xmrig.h b/src/xmrig.h index ddf1bb03..11913f89 100644 --- a/src/xmrig.h +++ b/src/xmrig.h @@ -24,18 +24,14 @@ #ifndef __XMRIG_H__ #define __XMRIG_H__ - namespace xmrig { - - enum Algo { ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ }; - enum Variant { VARIANT_AUTO = -1, @@ -45,5 +41,4 @@ namespace xmrig } /* xmrig */ - #endif /* __XMRIG_H__ */ diff --git a/vs/xmrig.sln b/vs/xmrig.sln new file mode 100644 index 00000000..c6e4fb76 --- /dev/null +++ b/vs/xmrig.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmrig", "xmrig.vcxproj", "{92BDBA37-96E3-4D85-B762-185E4407BB49}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + make|Win32 = make|Win32 + make|x64 = make|x64 + vc-debug|Win32 = vc-debug|Win32 + vc-debug|x64 = vc-debug|x64 + vc-release|Win32 = vc-release|Win32 + vc-release|x64 = vc-release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {92BDBA37-96E3-4D85-B762-185E4407BB49}.make|Win32.ActiveCfg = make|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.make|Win32.Build.0 = make|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.make|x64.ActiveCfg = make|x64 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.make|x64.Build.0 = make|x64 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-debug|Win32.ActiveCfg = vc-debug|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-debug|Win32.Build.0 = vc-debug|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-debug|x64.ActiveCfg = vc-debug|x64 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-debug|x64.Build.0 = vc-debug|x64 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-release|Win32.ActiveCfg = vc-release|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-release|Win32.Build.0 = vc-release|Win32 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-release|x64.ActiveCfg = vc-release|x64 + {92BDBA37-96E3-4D85-B762-185E4407BB49}.vc-release|x64.Build.0 = vc-release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vs/xmrig.vcxproj b/vs/xmrig.vcxproj new file mode 100644 index 00000000..7e9a453c --- /dev/null +++ b/vs/xmrig.vcxproj @@ -0,0 +1,386 @@ + + + + + make + Win32 + + + make + x64 + + + vc-debug + Win32 + + + vc-debug + x64 + + + vc-release + Win32 + + + vc-release + x64 + + + + + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + xmrig + {92BDBA37-96E3-4D85-B762-185E4407BB49} + libcpuid + Win32Proj + + + + Makefile + NotSet + true + + + Makefile + NotSet + true + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)\..\build\ + $(SolutionDir)\..\build\ + $(SolutionDir)\..\build\CMakeFiles\ + $(SolutionDir)\..\build\CMakeFiles\ + $(SolutionDir)\..\build\ + $(SolutionDir)\..\build\ + $(SolutionDir)\obj\$(Platform)\$(Configuration)\ + $(SolutionDir)\obj\$(Platform)\$(Configuration)\ + $(ProjectName)$(Platform)d + $(ProjectName)$(Platform) + cd $(OutDir) && make -j$(NUMBER_OF_PROCESSORS) + cd $(OutDir) && make clean && make -j$(NUMBER_OF_PROCESSORS) + cd $(OutDir) && make clean + cd $(OutDir) && make -j$(NUMBER_OF_PROCESSORS) + cd $(OutDir) && make clean && make -j$(NUMBER_OF_PROCESSORS) + cd $(OutDir) && make clean + $(SolutionDir)\..\build\ + $(SolutionDir)\obj\$(Platform)\$(Configuration)\ + $(ProjectName)$(Platform)d + $(ProjectName)$(Platform) + $(SolutionDir)\obj\$(Platform)\$(Configuration)\ + $(SolutionDir)\..\build\ + + + + WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + CompileAsC + 4996;%(DisableSpecificWarnings) + + + exports.def + + + + + WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + CompileAsC + 4996;%(DisableSpecificWarnings) + + + exports.def + + + + + $(SolutionDir)\..\src\;$(SolutionDir)\..\src\3rdparty;$(SolutionDir)\..\src\3rdparty\libcpuid;$(SolutionDir)\..\src\3rdparty\rapidjson\msinttypes;$(SolutionDir)\..\..\libuv-1.x\include;%(AdditionalIncludeDirectories) + + + + + $(SolutionDir)\..\src\;$(SolutionDir)\..\src\3rdparty;$(SolutionDir)\..\src\3rdparty\libcpuid;$(SolutionDir)\..\src\3rdparty\rapidjson\msinttypes;$(SolutionDir)\..\..\libuv-1.x\include;%(AdditionalIncludeDirectories) + + + + + true + XMRIG_PROJECT;XMRIG_NO_HTTPD;XMRIG_NO_GOOGLE_BREAKPAD;XMRIG_NO_API;__STDC_FORMAT_MACROS;APP_DEBUG + Disabled + false + Disabled + + + $(SolutionDir)\..\..\libuv-1.x\Release\$(Platform)\lib;%(AdditionalLibraryDirectories) + libuv.lib;advapi32.lib;iphlpapi.lib;psapi.lib;shell32.lib;user32.lib;userenv.lib;ws2_32.lib;%(AdditionalDependencies) + LIBCMTD;LIBCMT + true + true + true + $(ProjectName)$(Platform)d.pdb + true + UseLinkTimeCodeGeneration + + + + + true + XMRIG_PROJECT;XMRIG_NO_HTTPD;XMRIG_NO_GOOGLE_BREAKPAD;XMRIG_NO_API;__STDC_FORMAT_MACROS + Full + AnySuitable + true + Speed + true + true + true + + + $(SolutionDir)\..\..\libuv-1.x\Release\$(Platform)\lib;%(AdditionalLibraryDirectories) + libuv.lib;advapi32.lib;iphlpapi.lib;psapi.lib;shell32.lib;user32.lib;userenv.lib;ws2_32.lib;%(AdditionalDependencies) + LIBCMTD;LIBCMT + UseLinkTimeCodeGeneration + + + + + $(SolutionDir)\..\src\;$(SolutionDir)\..\src\3rdparty;$(SolutionDir)\..\src\3rdparty\libcpuid;$(SolutionDir)\..\src\3rdparty\rapidjson\msinttypes;$(SolutionDir)\..\..\libuv-1.x\include;%(AdditionalIncludeDirectories) + true + XMRIG_PROJECT;XMRIG_NO_HTTPD;XMRIG_NO_GOOGLE_BREAKPAD;XMRIG_NO_API;__STDC_FORMAT_MACROS;APP_DEBUG + Disabled + Disabled + + + $(SolutionDir)\..\..\libuv-1.x\Release\$(Platform)\lib;%(AdditionalLibraryDirectories) + LIBCMTD;LIBCMT + libuv.lib;advapi32.lib;iphlpapi.lib;psapi.lib;shell32.lib;user32.lib;userenv.lib;ws2_32.lib;%(AdditionalDependencies) + $(ProjectName)$(Platform)d.pdb + true + true + true + true + UseLinkTimeCodeGeneration + + + + + $(SolutionDir)\..\src\;$(SolutionDir)\..\src\3rdparty;$(SolutionDir)\..\src\3rdparty\libcpuid;$(SolutionDir)\..\src\3rdparty\rapidjson\msinttypes;$(SolutionDir)\..\..\libuv-1.x\include;%(AdditionalIncludeDirectories) + true + Full + AnySuitable + true + Speed + true + true + true + XMRIG_PROJECT;XMRIG_NO_HTTPD;XMRIG_NO_GOOGLE_BREAKPAD;XMRIG_NO_API;__STDC_FORMAT_MACROS + + + $(SolutionDir)\..\..\libuv-1.x\Release\$(Platform)\lib;%(AdditionalLibraryDirectories) + libuv.lib;advapi32.lib;iphlpapi.lib;psapi.lib;shell32.lib;user32.lib;userenv.lib;ws2_32.lib;%(AdditionalDependencies) + LIBCMTD;LIBCMT + UseLinkTimeCodeGeneration + + + + + + + \ No newline at end of file diff --git a/vs/xmrig.vcxproj.filters b/vs/xmrig.vcxproj.filters new file mode 100644 index 00000000..970c7896 --- /dev/null +++ b/vs/xmrig.vcxproj.filters @@ -0,0 +1,582 @@ + + + + + {6955e425-641d-4a18-acb0-d78893a1871d} + + + {819f3a03-9a2c-4725-87ca-54efa7e5cb7d} + + + {7e805124-d421-47b2-9d4a-74be33524010} + + + {c5bfb5b8-6847-4ba7-8235-3ab13efb7f67} + + + {a0a4a5de-7c2b-412b-93f9-9a2947b4e4ac} + + + {682b6780-b8c9-406d-a7a8-e128f334c4e9} + + + {5ff1d4d9-5095-43b5-b33b-d9b5ed7fea09} + + + {e6f77825-b090-41d5-a52d-ee71ceb43625} + + + {91d9785b-eb95-4697-aad4-64d7fa758c12} + + + {adcb1741-7564-4b29-b419-63faa19fabe0} + + + {884c03aa-8fac-4e5b-9f25-a2f926513e54} + + + {f3c852e4-5be7-47d3-b817-91f870a3a2bd} + + + {6664e951-2c60-488f-9392-32a2d94cf01b} + + + {d3e64bcc-89a2-4b9c-8862-50e6c3ea5838} + + + {c316406e-88a3-4e4a-b831-729b2b3c23ec} + + + {ce449acb-2e96-41b0-a80f-2895c8a9d157} + + + {89d4683f-f5f4-4f23-a1da-c59d5ed9a30c} + + + {f4b9e412-a76d-4b33-85b4-82f73b88dd4b} + + + {4bb2ab95-8ae5-43ba-bc37-1db8ae56439e} + + + {c230f074-3bff-43bf-879c-0bf5f1bd5892} + + + {41379fdf-aba8-47ea-b2d0-2a068fcb9087} + + + {c4db7ddc-49a1-41c6-80e8-b1e08e548c9c} + + + {bbb1e351-89bd-4d9b-a41c-7b1a5963f322} + + + {d962cd0c-dc8f-4bf5-a331-c58ddd89a02e} + + + {0bb34178-3f97-4639-8287-bea499f4f027} + + + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente\3rdparty\libcpuid + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente + + + Archivos de código fuente\api + + + Archivos de código fuente\api + + + Archivos de código fuente\api + + + Archivos de código fuente\api + + + Archivos de código fuente\crypto + + + Archivos de código fuente\crypto + + + Archivos de código fuente\crypto + + + Archivos de código fuente\crypto + + + Archivos de código fuente\crypto + + + Archivos de código fuente\crypto + + + Archivos de código fuente\log + + + Archivos de código fuente\log + + + Archivos de código fuente\log + + + Archivos de código fuente\log + + + Archivos de código fuente\net + + + Archivos de código fuente\net + + + Archivos de código fuente\net + + + Archivos de código fuente\net + + + Archivos de código fuente\net + + + Archivos de código fuente\net\strategies + + + Archivos de código fuente\net\strategies + + + Archivos de código fuente\net\strategies + + + Archivos de código fuente\workers + + + Archivos de código fuente\workers + + + Archivos de código fuente\workers + + + Archivos de código fuente\workers + + + Archivos de código fuente\workers + + + Archivos de código fuente\workers + + + + + Archivos de recursos + + + + + Archivos de recursos + + + Archivos de recursos + + + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado + + + Archivos de encabezado\3rdparty + + + Archivos de encabezado\3rdparty + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson + + + Archivos de encabezado\3rdparty\rapidjson\error + + + Archivos de encabezado\3rdparty\rapidjson\error + + + Archivos de encabezado\3rdparty\rapidjson\msinttypes + + + Archivos de encabezado\3rdparty\rapidjson\msinttypes + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\rapidjson\internal + + + Archivos de encabezado\3rdparty\getopt + + + Archivos de encabezado\api + + + Archivos de encabezado\api + + + Archivos de encabezado\api + + + Archivos de encabezado\api + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\crypto + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\log + + + Archivos de encabezado\log + + + Archivos de encabezado\log + + + Archivos de encabezado\log + + + Archivos de encabezado\net + + + Archivos de encabezado\net + + + Archivos de encabezado\net + + + Archivos de encabezado\net + + + Archivos de encabezado\net + + + Archivos de encabezado\net + + + Archivos de encabezado\net\strategies + + + Archivos de encabezado\net\strategies + + + Archivos de encabezado\net\strategies + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\3rdparty\libcpuid + + + Archivos de encabezado\workers + + + Archivos de encabezado\workers + + + Archivos de encabezado\workers + + + Archivos de encabezado\workers + + + Archivos de encabezado\workers + + + Archivos de encabezado\workers + + + Archivos de encabezado\interfaces + + + Archivos de encabezado\net + + + + + Archivos de código fuente\3rdparty\libcpuid + + + \ No newline at end of file