#define _GNU_SOURCE #include #include #include #include #include "my_cpuid.h" #include "debug.h" #include "x64emu.h" int get_cpuMhz() { int MHz = 0; char *p = NULL; if((p=getenv("BOX64_CPUMHZ"))) { MHz = atoi(p); return MHz; } char cpumhz[200]; sprintf(cpumhz, "%d", MHz?:1000); setenv("BOX64_CPUMHZ", cpumhz, 1); // set temp value incase box64 gets recursively called int cpucore = 0; while(cpucore!=-1) { char cpufreq[4096]; sprintf(cpufreq, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpucore); FILE *f = fopen(cpufreq, "r"); if(f) { int r; if(1==fscanf(f, "%d", &r)) { r /= 1000; if(MHz0) { // worked! (unless it's saying "lscpu: command not found" or something like that) if(!strstr(tmp, "lscpu")) { // trim ending while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1] = 0; // incase multiple cpu type are present, there will be multiple lines while(strchr(tmp, '\n')) *strchr(tmp,'\n') = ' '; // cut the float part (so '.' or ','), it's not needed if(strchr(tmp, '.')) *strchr(tmp, '.')= '\0'; if(strchr(tmp, ',')) *strchr(tmp, ',')= '\0'; int mhz; if(sscanf(tmp, "%d", &mhz)==1) MHz = mhz; } } } } #endif if(!MHz) MHz = 1000; // default to 1Ghz... sprintf(cpumhz, "%d", MHz); setenv("BOX64_CPUMHZ", cpumhz, 1); // set actual value return MHz; } static int nCPU = 0; static double bogoMips = 100.; static int read_ncpu = 0; void grabNCpu() { nCPU = 1; // default number of CPU to 1 FILE *f = fopen("/proc/cpuinfo", "r"); ssize_t dummy; if(f) { nCPU = 0; int bogo = 0; size_t len = 500; char* line = malloc(len); while ((dummy = getline(&line, &len, f)) != (ssize_t)-1) { if(!strncmp(line, "processor\t", strlen("processor\t"))) ++nCPU; if(!bogo && !strncmp(line, "BogoMIPS\t", strlen("BogoMIPS\t"))) { // grab 1st BogoMIPS float tmp; if(sscanf(line, "BogoMIPS\t: %g", &tmp)==1) { bogoMips = tmp; bogo = 1; } } } free(line); fclose(f); if(!nCPU) nCPU=1; } } int getNCpu() { if(!nCPU) grabNCpu(); read_ncpu = 1; if(BOX64ENV(maxcpu) && nCPU>BOX64ENV(maxcpu)) return BOX64ENV(maxcpu); return nCPU; } int getNCpuUnmasked() { if(!nCPU) grabNCpu(); return nCPU; } int canNCpuBeChanged() { return read_ncpu?0:1; } double getBogoMips() { if(!nCPU) grabNCpu(); return bogoMips; } const char* getCpuName() { static char name[200] = "Unknown CPU"; static int done = 0; if(done) return name; done = 1; char *p = NULL; if((p=getenv("BOX64_CPUNAME"))) { strcpy(name, p); return name; } setenv("BOX64_CPUNAME", name, 1); // temporary set #ifndef STATICBUILD FILE* f = popen("LC_ALL=C lscpu | grep -i \"model name:\" | head -n 1 | sed -r 's/(model name:)\\s{1,}//gi'", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); pclose(f); if(s>0) { // worked! (unless it's saying "lscpu: command not found" or something like that) if(!strstr(tmp, "lscpu")) { // trim ending while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1] = 0; strncpy(name, tmp, 199); } setenv("BOX64_CPUNAME", name, 1); return name; } } // failled, try to get architecture at least f = popen("uname -m", "r"); if(f) { char tmp[200] = ""; ssize_t s = fread(tmp, 1, 200, f); pclose(f); if(s>0) { // worked! // trim ending while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1] = 0; snprintf(name, 199, "unknown %s cpu", tmp); setenv("BOX64_CPUNAME", name, 1); return name; } } #endif // Nope, bye return name; } const char* getBoxCpuName() { static char branding[3*4*4+1] = ""; static int done = 0; if(!done) { done = 1; const char* name = getCpuName(); if(strstr(name, "MHz") || strstr(name, "GHz")) { // name already have the speed in it snprintf(branding, sizeof(branding), "Box64 on %.*s", 39, name); } else { unsigned int MHz = get_cpuMhz(); if(MHz>1500) { // swiches to GHz display... snprintf(branding, sizeof(branding), "Box64 on %.*s @%1.2f GHz", 28, name, MHz/1000.); } else { snprintf(branding, sizeof(branding), "Box64 on %.*s @%04d MHz", 28, name, MHz); } } } return branding; } uint32_t helper_getcpu(x64emu_t* emu) { #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && !defined(ANDROID) #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 28) uint32_t cpu, node; if(!getcpu(&cpu, &node)) return (node&0xff)<<12 | (cpu&0xff); #endif #endif return 0; } uint32_t fallback_random32() { return random() ^ (random()<<1); } uint32_t get_random32() { uint32_t ret; FILE* f = fopen("/dev/urandom", "rb"); if(f) { if(fread(&ret, sizeof(ret), 1, f)!=1) ret = fallback_random32(); fclose(f); } else ret = fallback_random32(); return ret; } uint64_t fallback_random64() { return random() ^ (((uint64_t)random())<<18) ^ (((uint64_t)random())<<41); } uint64_t get_random64() { uint64_t ret; FILE* f = fopen("/dev/urandom", "rb"); if(f) { if(fread(&ret, sizeof(ret), 1, f)!=1) ret = fallback_random64(); fclose(f); } else ret = fallback_random64(); return ret; }