diff --git a/Makefile b/Makefile index e1bdad4..01612fb 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,12 @@ ifneq ($(OS),Windows_NT) SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_DIR)soc.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h CFLAGS += -DARCH_ARM -Wno-unused-parameter -std=c99 + + os := $(shell uname -s) + ifeq ($(os), Darwin) + SOURCE += $(SRC_DIR)sysctl.c + HEADERS += $(SRC_DIR)sysctl.h + endif else # Error lines should not be tabulated because Makefile complains about it $(warning Unsupported arch detected: $(arch). See https://github.com/Dr-Noob/cpufetch#1-support) diff --git a/src/arm/midr.c b/src/arm/midr.c index 7a0dc76..8eba91a 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -4,8 +4,19 @@ #include #include #include -#include -#include + +#ifdef __linux__ + #include + #include +#elif defined __APPLE__ || __MACH__ + #include "sysctl.h" + // From Linux kernel: arch/arm64/include/asm/cputype.h + #define MIDR_APPLE_M1_ICESTORM 0x610F0220 + #define MIDR_APPLE_M1_FIRESTORM 0x610F0230 + #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM + #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3 + #endif +#endif #include "../common/global.h" #include "udev.h" @@ -132,6 +143,7 @@ struct features* get_features_info() { *ptr = false; } +#ifdef __linux__ errno = 0; long hwcaps = getauxval(AT_HWCAP); @@ -161,15 +173,22 @@ struct features* get_features_info() { feat->SHA1 = hwcaps & HWCAP2_SHA1; feat->SHA2 = hwcaps & HWCAP2_SHA2; } -#endif +#endif // ifdef __aarch64__ +#elif defined __APPLE__ || __MACH__ + // Must be M1 + feat->AES = true; + feat->CRC32 = true; + feat->SHA1 = true; + feat->SHA2 = true; + feat->NEON = true; +#endif // ifdef __linux__ return feat; } -struct cpuInfo* get_cpu_info() { - struct cpuInfo* cpu = emalloc(sizeof(struct cpuInfo)); +#ifdef __linux__ +struct cpuInfo* get_cpu_info_linux(struct cpuInfo* cpu) { init_cpu_info(cpu); - int ncores = get_ncores_from_cpuinfo(); bool success = false; int32_t* freq_array = emalloc(sizeof(uint32_t) * ncores); @@ -224,6 +243,73 @@ struct cpuInfo* get_cpu_info() { return cpu; } +#elif defined __APPLE__ || __MACH__ +void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu) { + // 1. Fill ICESTORM + struct cpuInfo* ice = cpu; + + ice->midr = MIDR_APPLE_M1_ICESTORM; + ice->arch = get_uarch_from_midr(ice->midr, ice); + ice->cach = get_cache_info(ice); + ice->feat = get_features_info(); + ice->topo = malloc(sizeof(struct topology)); + ice->topo->cach = ice->cach; + ice->topo->total_cores = 4; + ice->freq = malloc(sizeof(struct frequency)); + ice->freq->base = UNKNOWN_FREQ; + ice->freq->max = 2064; + ice->hv = malloc(sizeof(struct hypervisor)); + ice->hv->present = false; + ice->next_cpu = malloc(sizeof(struct cpuInfo)); + + // 2. Fill FIRESTORM + struct cpuInfo* fire = ice->next_cpu; + fire->midr = MIDR_APPLE_M1_FIRESTORM; + fire->arch = get_uarch_from_midr(fire->midr, fire); + fire->cach = get_cache_info(fire); + fire->feat = get_features_info(); + fire->topo = malloc(sizeof(struct topology)); + fire->topo->cach = fire->cach; + fire->topo->total_cores = 4; + fire->freq = malloc(sizeof(struct frequency)); + fire->freq->base = UNKNOWN_FREQ; + fire->freq->max = 3200; + fire->hv = malloc(sizeof(struct hypervisor)); + fire->hv->present = false; + fire->next_cpu = NULL; +} + +struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) { + uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily"); + + // Manually fill the cpuInfo assuming that the CPU + // is a ARM_FIRESTORM_ICESTORM (Apple M1) + if(cpu_family == CPUFAMILY_ARM_FIRESTORM_ICESTORM) { + cpu->num_cpus = 2; + cpu->soc = get_soc(); + fill_cpu_info_firestorm_icestorm(cpu); + cpu->peak_performance = get_peak_performance(cpu); + } + else { + printBug("Found invalid cpu_family: 0x%.8X", cpu_family); + return NULL; + } + + return cpu; +} +#endif + +struct cpuInfo* get_cpu_info() { + struct cpuInfo* cpu = malloc(sizeof(struct cpuInfo)); + init_cpu_info(cpu); + + #ifdef __linux__ + return get_cpu_info_linux(cpu); + #elif defined __APPLE__ || __MACH__ + return get_cpu_info_mach(cpu); + #endif +} + char* get_str_topology(struct cpuInfo* cpu, struct topology* topo, bool dual_socket) { uint32_t size = 3+7+1; char* string = emalloc(sizeof(char)*size); diff --git a/src/arm/soc.c b/src/arm/soc.c index 7097563..dd46c10 100644 --- a/src/arm/soc.c +++ b/src/arm/soc.c @@ -17,6 +17,7 @@ static char* soc_trademark_string[] = { [SOC_VENDOR_EXYNOS] = "Exynos ", [SOC_VENDOR_KIRIN] = "Kirin ", [SOC_VENDOR_BROADCOM] = "Broadcom BCM", + [SOC_VENDOR_APPLE] = "Apple " }; static char* soc_rpi_string[] = { @@ -586,6 +587,7 @@ struct system_on_chip* get_soc() { soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->process = UNKNOWN; +#ifdef __linux__ bool isRPi = is_raspberry_pi(); if(isRPi) { soc = guess_soc_raspbery_pi(soc); @@ -609,8 +611,11 @@ struct system_on_chip* get_soc() { printWarn("SoC detection failed using Android: No string found"); else if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name); -#endif +#endif // ifdef __ANDROID__ } +#elif defined __APPLE__ || __MACH__ + fill_soc(soc, "M1", SOC_APPLE_M1, 5); +#endif // ifdef __linux__ if(soc->raw_name == NULL) { soc->raw_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN)+1)); diff --git a/src/arm/soc.h b/src/arm/soc.h index 1dc10b3..90df32c 100644 --- a/src/arm/soc.h +++ b/src/arm/soc.h @@ -12,7 +12,8 @@ enum { SOC_VENDOR_MEDIATEK, SOC_VENDOR_EXYNOS, SOC_VENDOR_KIRIN, - SOC_VENDOR_BROADCOM + SOC_VENDOR_BROADCOM, + SOC_VENDOR_APPLE }; struct system_on_chip { diff --git a/src/arm/socs.h b/src/arm/socs.h index c028d11..66466b2 100644 --- a/src/arm/socs.h +++ b/src/arm/socs.h @@ -250,6 +250,8 @@ enum { SOC_SNAPD_SM8250, SOC_SNAPD_SM8250_AB, SOC_SNAPD_SM8350, + // APPLE + SOC_APPLE_M1 }; inline static VENDOR get_soc_vendor_from_soc(SOC soc) { @@ -258,6 +260,7 @@ inline static VENDOR get_soc_vendor_from_soc(SOC soc) { else if(soc >= SOC_EXYNOS_3475 && soc <= SOC_EXYNOS_880) return SOC_VENDOR_EXYNOS; else if(soc >= SOC_MTK_MT6889 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK; else if(soc >= SOC_SNAPD_QSD8650 && soc <= SOC_SNAPD_SM8350) return SOC_VENDOR_SNAPDRAGON; + else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M1) return SOC_VENDOR_APPLE; return SOC_VENDOR_UNKNOWN; } diff --git a/src/arm/sysctl.c b/src/arm/sysctl.c new file mode 100644 index 0000000..eefd7dd --- /dev/null +++ b/src/arm/sysctl.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +#include "../common/global.h" +#include "../common/cpu.h" + +uint32_t get_sys_info_by_name(char* name) { + size_t size = 0; + uint32_t ret = 0; + + if (sysctlbyname(name, NULL, &size, NULL, 0) != 0) { + printWarn("sysctlbyname(%s) failed: %s", name, strerror(errno)); + } + else if (size == sizeof(uint32_t)) { + sysctlbyname(name, &ret, &size, NULL, 0); + } + else { + printWarn("sysctl does not support non-integer lookup for '%s'", name); + } + + return ret; +} diff --git a/src/arm/sysctl.h b/src/arm/sysctl.h new file mode 100644 index 0000000..1140aec --- /dev/null +++ b/src/arm/sysctl.h @@ -0,0 +1,6 @@ +#ifndef __SYSCTL__ +#define __SYSCTL__ + +uint32_t get_sys_info_by_name(char* name); + +#endif diff --git a/src/arm/uarch.c b/src/arm/uarch.c index c006c93..d3d4d79 100644 --- a/src/arm/uarch.c +++ b/src/arm/uarch.c @@ -32,6 +32,7 @@ enum { ISA_ARMv8_1_A, ISA_ARMv8_2_A, ISA_ARMv8_3_A, + ISA_ARMv8_4_A, }; enum { @@ -91,6 +92,8 @@ enum { UARCH_TEMPEST, // Apple A12 processor (big cores). UARCH_LIGHTNING, // Apple A13 processor (big cores). UARCH_THUNDER, // Apple A13 processor (little cores). + UARCH_ICESTORM, // Apple M1 processor (little cores). + UARCH_FIRESTORM, // Apple M1 processor (big cores). // CAVIUM UARCH_THUNDERX, // Cavium ThunderX UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan). @@ -148,6 +151,8 @@ static const ISA isas_uarch[] = { [UARCH_EXYNOS_M3] = ISA_ARMv8_A, [UARCH_EXYNOS_M4] = ISA_ARMv8_2_A, [UARCH_EXYNOS_M5] = ISA_ARMv8_2_A, + [UARCH_ICESTORM] = ISA_ARMv8_4_A, + [UARCH_FIRESTORM] = ISA_ARMv8_4_A, [UARCH_PJ4] = ISA_ARMv7_A, }; @@ -162,6 +167,7 @@ static char* isas_string[] = { [ISA_ARMv8_1_A] = "ARMv8.1", [ISA_ARMv8_2_A] = "ARMv8.2", [ISA_ARMv8_3_A] = "ARMv8.3", + [ISA_ARMv8_4_A] = "ARMv8.4" }; #define UARCH_START if (false) {} @@ -280,6 +286,9 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) { CHECK_UARCH(arch, cpu, 'S', 0x003, 1, NA, "Exynos M4", UARCH_EXYNOS_M4, CPU_VENDOR_SAMSUNG) // Exynos 9820 CHECK_UARCH(arch, cpu, 'S', 0x004, 1, NA, "Exynos M5", UARCH_EXYNOS_M5, CPU_VENDOR_SAMSUNG) // Exynos 9820 (this one looks wrong at uarch.c ...) + CHECK_UARCH(arch, cpu, 'a', 0x022, NA, NA, "Icestorm", UARCH_ICESTORM, CPU_VENDOR_APPLE) + CHECK_UARCH(arch, cpu, 'a', 0x023, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE) + CHECK_UARCH(arch, cpu, 'V', 0x581, NA, NA, "PJ4", UARCH_PJ4, CPU_VENDOR_MARVELL) CHECK_UARCH(arch, cpu, 'V', 0x584, NA, NA, "PJ4B-MP", UARCH_PJ4, CPU_VENDOR_MARVELL) diff --git a/src/common/ascii.h b/src/common/ascii.h index 28ab64e..24b4cf8 100644 --- a/src/common/ascii.h +++ b/src/common/ascii.h @@ -184,6 +184,26 @@ $C1######### ################## ######## #### ######## \ $C1 \ $C1######### ################ ######## ## ######## " +// inspired by the neofetch mac logo +#define ASCII_APPLE \ +"$C1 'c. \ +$C1 ,xNMM. \ +$C1 .OMMMMo \ +$C1 OMMM0, \ +$C1 .;loddo:' loolloddol;. \ +$C1 cKMMMMMMMMMMNWMMMMMMMMMM0: \ +$C1 .KMMMMMMMMMMMMMMMMMMMMMMMWd. \ +$C1 XMMMMMMMMMMMMMMMMMMMMMMMX. \ +$C1;MMMMMMMMMMMMMMMMMMMMMMMM: \ +$C1:MMMMMMMMMMMMMMMMMMMMMMMM: \ +$C1.MMMMMMMMMMMMMMMMMMMMMMMMX. \ +$C1 kMMMMMMMMMMMMMMMMMMMMMMMMWd. \ +$C1 .XMMMMMMMMMMMMMMMMMMMMMMMMMMk \ +$C1 .XMMMMMMMMMMMMMMMMMMMMMMMMK. \ +$C1 kMMMMMMMMMMMMMMMMMMMMMMd \ +$C1 ;KMMMMMMMWXXWMMMMMMMk. \ +$C1 .cooc,. .,coo:. " + // --------------------- LONG LOGOS ------------------------- // #define ASCII_AMD_L \ "$C1 \ @@ -266,6 +286,7 @@ asciiL logo_kirin = { ASCII_KIRIN, 53, 12, false, {COLOR_FG_RED}, asciiL logo_broadcom = { ASCII_BROADCOM, 44, 19, false, {COLOR_FG_WHITE, COLOR_FG_RED}, {COLOR_FG_WHITE, COLOR_FG_RED} }; asciiL logo_arm = { ASCII_ARM, 42, 5, false, {COLOR_FG_CYAN}, {COLOR_FG_WHITE, COLOR_FG_CYAN} }; asciiL logo_ibm = { ASCII_IBM, 57, 13, true, {COLOR_BG_CYAN, COLOR_FG_WHITE}, {COLOR_FG_CYAN, COLOR_FG_WHITE} }; +asciiL logo_apple = { ASCII_APPLE, 32, 17, false, {COLOR_FG_WHITE}, {COLOR_FG_CYAN, COLOR_FG_WHITE} }; // Long variants | ----------------------------------------------------------------------------------------------------| asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {COLOR_BG_WHITE, COLOR_BG_GREEN}, {COLOR_FG_WHITE, COLOR_FG_GREEN} }; asciiL logo_intel_l = { ASCII_INTEL_L, 62, 19, true, {COLOR_BG_CYAN, COLOR_BG_WHITE}, {COLOR_FG_CYAN, COLOR_FG_WHITE} }; diff --git a/src/common/cpu.h b/src/common/cpu.h index fea607f..8da5998 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -10,6 +10,7 @@ enum { CPU_VENDOR_AMD, // ARCH_ARM CPU_VENDOR_ARM, + CPU_VENDOR_APPLE, CPU_VENDOR_BROADCOM, CPU_VENDOR_CAVIUM, CPU_VENDOR_NVIDIA, diff --git a/src/common/printer.c b/src/common/printer.c index 8f75063..30ae3e1 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -257,6 +257,8 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter art->art = &logo_kirin; else if(art->vendor == SOC_VENDOR_BROADCOM) art->art = &logo_broadcom; + else if(art->vendor == SOC_VENDOR_APPLE) + art->art = &logo_apple; else { if(term != NULL && ascii_fits_screen(term->w, logo_arm_l, lf)) art->art = &logo_arm_l; @@ -559,6 +561,7 @@ void print_ascii_arm(struct ascii* art, uint32_t la) { bool add_space = false; int32_t iters = max(logo->height, art->n_attributes_set); + printf("\n"); for(int32_t n=0; n < iters; n++) { // 1. Print logo if(n >= (int) art->additional_spaces && n < (int) logo->height + (int) art->additional_spaces) { @@ -610,7 +613,7 @@ void print_ascii_arm(struct ascii* art, uint32_t la) { } else printf("\n"); } - + printf("\n"); } bool print_cpufetch_arm(struct cpuInfo* cpu, STYLE s, struct color** cs, struct terminal* term) {