From e96082c67f462c3fade435c56e3914d3660a242f Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Wed, 30 Sep 2009 11:25:14 +0000 Subject: [PATCH] Added support for reading MSRs through dedicated driver on Win32 git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@69 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- contrib/MSR Driver/Kernel/TmpRdr.c | 127 +++++ contrib/MSR Driver/Kernel/TmpRdr.vcproj | 272 +++++++++++ contrib/MSR Driver/Kernel/resource.h | 14 + contrib/MSR Driver/Kernel/tmprdr.rc | 115 +++++ contrib/MSR Driver/TmpRdr.sys | Bin 0 -> 4608 bytes contrib/MSR Driver/TmpRdr64.sys | Bin 0 -> 5120 bytes cpuid_tool/cpuid_tool.c | 15 + libcpuid/cpuid_main.c | 2 +- libcpuid/embed_drivers.cpp | 87 ++++ libcpuid/libcpuid.h | 64 ++- libcpuid/libcpuid_util.c | 11 + libcpuid/libcpuid_util.h | 11 + libcpuid/libcpuid_vc71.vcproj | 9 + libcpuid/msrdriver.c | 594 ++++++++++++++++++++++++ libcpuid/rdmsr.c | 314 +++++++++++++ 15 files changed, 1633 insertions(+), 2 deletions(-) create mode 100644 contrib/MSR Driver/Kernel/TmpRdr.c create mode 100644 contrib/MSR Driver/Kernel/TmpRdr.vcproj create mode 100644 contrib/MSR Driver/Kernel/resource.h create mode 100644 contrib/MSR Driver/Kernel/tmprdr.rc create mode 100644 contrib/MSR Driver/TmpRdr.sys create mode 100644 contrib/MSR Driver/TmpRdr64.sys create mode 100644 libcpuid/embed_drivers.cpp create mode 100644 libcpuid/msrdriver.c create mode 100644 libcpuid/rdmsr.c diff --git a/contrib/MSR Driver/Kernel/TmpRdr.c b/contrib/MSR Driver/Kernel/TmpRdr.c new file mode 100644 index 0000000..a332a58 --- /dev/null +++ b/contrib/MSR Driver/Kernel/TmpRdr.c @@ -0,0 +1,127 @@ +#include + +#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) + +#define FLAG_HANDLE_OPENED 1 + +void UnloadDriver(PDRIVER_OBJECT DriverObject); +NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); + +typedef struct _DEVICE_EXTENSION{ + PDEVICE_OBJECT DeviceObject; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +PDEVICE_OBJECT g_pDeviceObject; + +#pragma alloc_text(PAGE0DEF, DriverEntry) + +// +NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){ + NTSTATUS ntStatus; + UNICODE_STRING uszDriverString; + UNICODE_STRING uszDeviceString; + + PDEVICE_OBJECT pDeviceObject; + PDEVICE_EXTENSION extension; + + // Point uszDriverString at the driver name + RtlInitUnicodeString(&uszDriverString, L"\\Device\\TmpRdr"); + + // Create and initialize device object + ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &uszDriverString, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); + if(ntStatus != STATUS_SUCCESS) + return ntStatus; + + // Assign extension variable + extension = pDeviceObject->DeviceExtension; + + // Point uszDeviceString at the device name + RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\TmpRdr"); + + // Create symbolic link to the user-visible name + ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString); + + if(ntStatus != STATUS_SUCCESS){ + // Delete device object if not successful + IoDeleteDevice(pDeviceObject); + return ntStatus; + } + + // Assign global pointer to the device object for use by the callback functions + g_pDeviceObject = pDeviceObject; + + // Load structure to point to IRP handlers + DriverObject->DriverUnload = UnloadDriver; + DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; + + // Return success + return ntStatus; +} + +// +NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ + PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +// +NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ + NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension; + __int64 *p__int64; + int iMSRregister; + + switch(irpStack->Parameters.DeviceIoControl.IoControlCode){ + case IOCTL_PROCVIEW_RDMSR: + if(irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(__int64)){ + if(irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(int)) + iMSRregister = *((int *)Irp->AssociatedIrp.SystemBuffer); + else + iMSRregister = 0x19c; + + p__int64 = Irp->AssociatedIrp.SystemBuffer; + *p__int64 = __readmsr(iMSRregister); + + ntStatus = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(__int64); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return ntStatus; + } + break; + default: + break; + } + + Irp->IoStatus.Status = ntStatus; + + if(ntStatus == STATUS_SUCCESS) + Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength; + else + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return ntStatus; +} + +// +void UnloadDriver(IN PDRIVER_OBJECT DriverObject){ + UNICODE_STRING uszDeviceString; + + IoDeleteDevice(DriverObject->DeviceObject); + + RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\TmpRdr"); + IoDeleteSymbolicLink(&uszDeviceString); +} diff --git a/contrib/MSR Driver/Kernel/TmpRdr.vcproj b/contrib/MSR Driver/Kernel/TmpRdr.vcproj new file mode 100644 index 0000000..332e349 --- /dev/null +++ b/contrib/MSR Driver/Kernel/TmpRdr.vcproj @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/MSR Driver/Kernel/resource.h b/contrib/MSR Driver/Kernel/resource.h new file mode 100644 index 0000000..6f9273c --- /dev/null +++ b/contrib/MSR Driver/Kernel/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by tmprdr.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/contrib/MSR Driver/Kernel/tmprdr.rc b/contrib/MSR Driver/Kernel/tmprdr.rc new file mode 100644 index 0000000..919329d --- /dev/null +++ b/contrib/MSR Driver/Kernel/tmprdr.rc @@ -0,0 +1,115 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Bulgarian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_BGR) +#ifdef _WIN32 +LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Bulgarian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x3L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "MSR reader 32-bit kernel driver" + VALUE "CompanyName", "Iron Steeds Inc." + VALUE "FileDescription", "TmpRdr 32-bit Kernel Module" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "TmpRdr" + VALUE "LegalCopyright", "Nick Gabarev '2009" + VALUE "OriginalFilename", "TmpRdr.sys" + VALUE "ProductName", "Core 2 Temperature Reader" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/contrib/MSR Driver/TmpRdr.sys b/contrib/MSR Driver/TmpRdr.sys new file mode 100644 index 0000000000000000000000000000000000000000..7349726be255f5804268c94584fd9ff23a6543d0 GIT binary patch literal 4608 zcmeHKO>9(E6#gC^?Gy&6N@F!me8oms==f+WDTd%6Gc5xx9oo_wY)YroNBijX&G_aG zX%`Z-LDRf8(T$0L#04vNE?6Lmv0*`Bfr-Qz12Ll8lIVgM7LDU~?)-E*NMkTD#`H|? zz2~0$o!|Rz?`_xdk5C1`$Ck?hmpKZBRKIq2oy%KZxUvP8YHl`O);e!C_KjN^J?*5% zocN@kh}(9`)kjR-$=bSQ>*4NReKIv_1~+fs*iWz*T9 z<@pWy{6!*lP;{0(C!c?-P~@m2dZn>26_HR3*eT;MupkAkq%>eu%Kpw=2O8GE1zmH> z<@!azNPNs?B?%F#RL6tPXxxnhBL#uNNnOe)1RM_L2(Xn=2zWE-n8_4@<04P9 zi9N}?j6%efP1o5qD&TcC`Dfzwn29%_`BtvZuWM*oxavp0=Qahr_Tl%Y0)e~RF_7Im zGv)I;yJx2SzHGJE9`O82PkecSC&)V!*xEc>Jv-oAY;TZHpe5IQ%ljs8%Ue7#L~AoA z8}K!;3$thHmwrCx-8*{Ji}-VCU#`wakK=pU%|{-@a&;(i+sNIxS~`$xB(c8q*cBM$ znRMAcV7tI}i7m_~G>9-voQ8!2$3gUAl1Huwqi{;=DP&fmGJk~NETgY}74(vSwWo_<@~|+t}VUjMV2qZ(D<~d)iB%9Hro+e>}bt$ve=P+jzi1BiJ=?(Be72Z zeg$?G&boNMCcG}(!?f1liNjhn6*iNmYxYi0j---SqSLY`fK9$0HyO1p_n2)Z`0nd< z9m^gAq9uITJZ&XR;5H>E52Pm3Vx-4>Cu?T-sM$~H0mqD2+HEVzi~6>k%1k(RGH6cG z+B!XM1vK@Pst3-lwxEG`x4d5;lGpHlKFGDOHN_FUda7Ho{snuR3qswihCk)rM= z3S*#^(eGhv&(yy)}P9P`{4D-dWm2#0g zIKvxQyrijPDSg3}-^Z0P9#-)bW9*{ND6*JZ%KBa6j?q<9 zPiiZXI~?P*xRPCYJc2)jXNd14c1$6q+G*B9G8y9wo=2S8^17IyzYbzX*rf8OIp4vW z8~p7NQ`o0s?k?!cZj0~Ye#=aDadl0CtlPBORgpi>SYp)AS0X|0E0IHe3F29&SDk2+ z_R{PfT6S5v{8|qs#jgT*UB$H8W@R-WRm(7A)p#N#-(nUkUoFtY?_Hu6|2A_-syJ5m zzQ*^30RB1E0^4Y%))+M2H$F5zHqILe<^SibF}5178f`|W@wPE$B#mj~tQ?(n`X5!` EPsQ$)UH||9 literal 0 HcmV?d00001 diff --git a/contrib/MSR Driver/TmpRdr64.sys b/contrib/MSR Driver/TmpRdr64.sys new file mode 100644 index 0000000000000000000000000000000000000000..d35db374eb277afbb665f1f001526ca82e095d1c GIT binary patch literal 5120 zcmeHLZ){Ul6h9rU6c}tsii?`~z($uSwQLI+7)`fz>^DYcx7E5)`Ow4PQ}*@+&3WqICO8v?Io z*}_#`t|GEg)qD~5{iuevcnF5KvWx~8()`aF*h^U@nDWV)F+CwC>UO^s-=*bG( zJyqbF?*VY>>Zp$PXLx!X8|Ee!8LUVW(V#0G4eMc|8*GF@;5biZZPn3FTp^=H0XK#Z4-w|Lv|8DG3PT33B(J&m+wM(y_WOPSGH>xf-8TI&q^HQVvS zSVJF_ng;pQWl1s4%PUSd&M8?^W?Gv0Su!1Om&TcCbpxN1XIjN`4tV37>Cgd~686Qh zaA1h1SvC~A>1Y5_o^U(?zw(67DVdHsVG*K@#msc`nIL&7NyDgB+D95iz=tVFJru_) z>!&EC?~pUa&BUmMQr^#$%J@YzCpzI9<;+-v#O&&p$l287P8{)UBJ<@4sEsAKXjBIBOW*eumcsJiJbEQ>4; zjN!r_X|Dep(`a0v1G*f$1Ajne)A8NcrrC0QJ(_$IL8r%;4LaSv z39nObnRw-jY#V04uT$b&n2sFaYc}X)qPq-CE5u~TUrfQdhpHLi^znY93Dz1VlH(Q{r+EM5m%-< zEbqd&E#j8!zKeYs?pb`-3#Cx_a92U0B~7sGq5$=xZpVo_fHPtj?SQVJ-U^xNg!THJ z{0%!l7R%Up=rPgC*EuUyx<6UPr~v6Wqid9)0eI6WhWAr}){k>N(YpfUrY2lkH={IB zpSZs6#=~c!HellTsle+v_Y-x(pC4^$*upsdtB@qxgnk>)Qv*t(Az@9RjzQxaf`+>T zBl&{4dfsme9uhQ$S%$?JJQW3~B&?E%TSc!Z#+5|G5ppqvLii`ZGCvpIZ-#L%;Zaf; zUlaWqSAIvSjB&e℞@=`b23&Q z7#>TrE02fq+h`5&K41rsftbj43i;rf4A3CF5PI{SYY5|Y0Mm!UncoNfS!zHGylPCX zv=Y9$3VnIC*<*3NS>sh)m=j(#7jicyR+ifyhmUUf$Y&#h2ujhDh>u5?FtP-+3ZE&| zX?WL>y?mP=mg18^v_<4{q0h>U{#`!3h}VL*g6CYEN$JTYa^jiisCoPZ<`5Hcl-7Tl K^%w*G6a59F +#include +#include +#include +#include +using namespace std; + +const char* drivers_root = "..\\contrib\\MSR Driver\\"; +const char* sourcefile = "msrdriver.c"; + +char* images[2]; +int sizes[2]; +const char* filenames[] = { "TmpRdr.sys", "TmpRdr64.sys" }; +vector source; + +bool read_image(const char* filename, char*& image, int& isize) +{ + char fn[512]; + sprintf(fn, "%s%s", drivers_root, filename); + FILE* f = fopen(fn, "rb"); + if (!f) return false; + fseek(f, 0, SEEK_END); + long size = ftell(f); + isize = (int) size; + rewind(f); + image = new char[size]; + fread(image, 1, size, f); + fclose(f); + return true; +} + +bool read_source(const char* filename) +{ + source.clear(); + FILE* f = fopen(filename, "rt"); + if (!f) return false; + char line[200]; + while (fgets(line, sizeof(line), f)) { + int i = (int) strlen(line); + if (i && line[i - 1] == '\n') line[--i] = 0; + source.push_back(string(line)); + } + fclose(f); + return true; +} + +void print_image(FILE* f, const char* image, int size) +{ + fprintf(f, "int cc_driver_code_size = %d;\n", size); + fprintf(f, "uint8_t cc_driver_code[%d] = {", size); + for (int i = 0; i < size; i++) { + if (i % 18 == 0) fprintf(f, "\n\t"); + fprintf(f, "0x%02x,", (unsigned) (unsigned char) image[i]); + } + fprintf(f, "\n};\n"); +} + +int main(void) +{ + for (int i = 0; i < 2; i++) + if (!read_image(filenames[i], images[i], sizes[i])) { + printf("Cannot read image `%s' from `%s'!\n", filenames[i], drivers_root); + return -1; + } + if (!read_source(sourcefile)) { + printf("Cannot read source `%s'\n", sourcefile); + return -2; + } + FILE* f = fopen(sourcefile, "wt"); + bool on = true; + for (unsigned i = 0; i < source.size(); i++) { + if (source[i] == "//} end") + on = true; + if (on) fprintf(f, "%s\n", source[i].c_str()); + if (source[i] == "//begin {") { + on = false; + fprintf(f, "#ifdef PLATFORM_X86\n"); + print_image(f, images[0], sizes[0]); + fprintf(f, "#else\n"); + print_image(f, images[1], sizes[1]); + fprintf(f, "#endif // PLATFORM_X86\n"); + } + } + return 0; +} diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index ae28dfb..f1de2b9 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -29,13 +29,15 @@ * @File libcpuid.h * @Author Veselin Georgiev * @Date Oct 2008 - * @Version 0.1.1 + * @Version 0.1.2 * * Version history: * * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle * new processor topology enumeration required on Core i7 + * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting + * kernel driver on Win32. */ /** @mainpage A simple libcpuid introduction @@ -341,6 +343,11 @@ typedef enum { ERR_BADFMT = -5, /*!< "Bad file format" */ ERR_NOT_IMP = -6, /*!< "Not implemented" */ ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */ + ERR_NO_RDMSR = -8, /*!< "RDMSR instruction is not supported" */ + ERR_NO_DRIVER= -9, /*!< "RDMSR driver error (generic)" */ + ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */ + ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */ + ERR_HANDLE = -12, /*!< "Bad handle" */ } cpu_error_t; /** @@ -694,6 +701,61 @@ void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list); */ void cpuid_free_cpu_list(struct cpu_list_t* list); +/** + * @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; +struct msr_driver_t* cpu_msr_driver_open(void); + +/** + * @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, int msr_index, uint64_t* result); + +/** + * @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/libcpuid/libcpuid_util.c b/libcpuid/libcpuid_util.c index eca536a..9a4358b 100644 --- a/libcpuid/libcpuid_util.c +++ b/libcpuid/libcpuid_util.c @@ -168,3 +168,14 @@ int match_pattern(const char* s, const char* p) } return 0; } + +struct cpu_id_t* get_cached_cpuid(void) +{ + static int initialized = 0; + static struct cpu_id_t id; + if (initialized) return &id; + if (cpu_identify(NULL, &id)) + memset(&id, 0, sizeof(id)); + initialized = 1; + return &id; +} diff --git a/libcpuid/libcpuid_util.h b/libcpuid/libcpuid_util.h index 0176b8a..dc0eac1 100644 --- a/libcpuid/libcpuid_util.h +++ b/libcpuid/libcpuid_util.h @@ -70,6 +70,17 @@ void generic_get_cpu_list(const struct match_entry_t* matchtable, int count, */ int match_pattern(const char* haystack, const char* pattern); +/* + * Gets an initialized cpu_id_t. It is cached, so that internal libcpuid + * machinery doesn't need to issue cpu_identify more than once. + */ +struct cpu_id_t* get_cached_cpuid(void); + +/* + * Sets the current errno + */ +int set_error(cpu_error_t err); + extern libcpuid_warn_fn_t _warn_fun; extern int _current_verboselevel; diff --git a/libcpuid/libcpuid_vc71.vcproj b/libcpuid/libcpuid_vc71.vcproj index 55bf3a4..543ad72 100644 --- a/libcpuid/libcpuid_vc71.vcproj +++ b/libcpuid/libcpuid_vc71.vcproj @@ -158,6 +158,12 @@ + + + + @@ -178,6 +184,9 @@ + + diff --git a/libcpuid/msrdriver.c b/libcpuid/msrdriver.c new file mode 100644 index 0000000..b5440ce --- /dev/null +++ b/libcpuid/msrdriver.c @@ -0,0 +1,594 @@ +/* + * 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 { +#ifdef PLATFORM_X86 +int cc_driver_code_size = 4608; +uint8_t cc_driver_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, +}; +#else +int cc_driver_code_size = 5120; +uint8_t cc_driver_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, +}; +#endif // PLATFORM_X86 +//} end +#endif // _WIN32 diff --git a/libcpuid/rdmsr.c b/libcpuid/rdmsr.c new file mode 100644 index 0000000..ab7d635 --- /dev/null +++ b/libcpuid/rdmsr.c @@ -0,0 +1,314 @@ +/* + * 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. + */ +#include +#include +#include "libcpuid.h" +#include "asm-bits.h" +#include "libcpuid_util.h" + +#ifndef _WIN32 +/* On Linux and Apple, we still do not support RDMSR, so supply dummy struct + and functions */ +struct msr_driver_t { int dummy; } +struct msr_driver_t* cpu_msr_driver_open(void) +{ + set_error(ERR_NOT_IMPL); + return NULL; +} + +int cpu_rdmsr(struct msr_driver_t* driver, int msr_index, uint64_t* result) +{ + return set_error(ERR_NOT_IMPL); +} + +int cpu_msr_driver_close(struct msr_driver_t* driver) +{ + return set_error(ERR_NOT_IMPL); +} + +#else /* _WIN32 */ +#include + +extern uint8_t cc_driver_code[]; +extern int cc_driver_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; +} + +static int rdmsr_supported(void) +{ + struct cpu_id_t* id = get_cached_cpuid(); + return id->flags[CPU_FEATURE_MSR]; +} + +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; + fwrite(cc_driver_code, 1, cc_driver_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; + } + } /*else { + switch(getImageType(lpszDriverFilePath)){ + case IMAGE_FILE_MACHINE_AMD64: + if(!isRunning_x64()){ + if(!DeleteFile(lpszDriverFilePath)){ + addLastErrorMessageMsgEx(g_hLogEdit, __TEXT("Error deleting driver file(due to binary incompatibility):"), GetLastError()); + goto clean_up; + } + if(!extractDriver(lpszDriverFilePath)) + goto clean_up; + } + break; + case IMAGE_FILE_MACHINE_I386: + if(isRunning_x64()){ + if(!DeleteFile(lpszDriverFilePath)){ + addLastErrorMessageMsgEx(g_hLogEdit, __TEXT("Error deleting driver file(due to binary incompatibility):"), GetLastError()); + goto clean_up; + } + if(!extractDriver(lpszDriverFilePath)) + goto clean_up; + } + 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, int 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->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 /* _WIN32 */