master ohmu/fastfetch-openbsd / src / modules / physicalmemory / physicalmemory.c
ohmu  ·  2026-10-15
  1#include "common/printing.h"
  2#include "common/jsonconfig.h"
  3#include "common/size.h"
  4#include "detection/physicalmemory/physicalmemory.h"
  5#include "modules/physicalmemory/physicalmemory.h"
  6
  7bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) {
  8    FF_LIST_AUTO_DESTROY result = ffListCreate();
  9    const char* error = ffDetectPhysicalMemory(options, &result);
 10
 11    if (error) {
 12        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
 13        return false;
 14    }
 15
 16    if (result.length == 0) {
 17        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory devices detected");
 18        return false;
 19    }
 20
 21    FF_STRBUF_AUTO_DESTROY prettySize = ffStrbufCreate();
 22
 23    uint32_t i = 0;
 24    FF_LIST_FOR_EACH (FFPhysicalMemoryResult, device, result) {
 25        ffStrbufClear(&prettySize);
 26        if (device->installed) {
 27            ffSizeAppendNum(device->size, &prettySize);
 28        }
 29
 30        if (options->moduleArgs.outputFormat.length == 0) {
 31            ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), result.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
 32
 33            if (device->installed) {
 34                fputs(prettySize.chars, stdout);
 35                fputs(" - ", stdout);
 36                ffStrbufWriteTo(&device->type, stdout);
 37                if (device->maxSpeed > 0) {
 38                    printf("-%u", device->maxSpeed);
 39                }
 40                if (device->runningSpeed > 0 && device->runningSpeed != device->maxSpeed) {
 41                    printf(" @ %u MT/s", device->runningSpeed);
 42                }
 43                if (device->vendor.length > 0) {
 44                    printf(" (%s)", device->vendor.chars);
 45                }
 46                if (device->ecc) {
 47                    fputs(" - ECC", stdout);
 48                }
 49            } else {
 50                fputs("Empty", stdout);
 51                if (device->formFactor.length > 0) {
 52                    printf(" - %s", device->formFactor.chars);
 53                }
 54                if (device->locator.length > 0) {
 55                    printf(" (%s)", device->locator.chars);
 56                }
 57            }
 58            putchar('\n');
 59        } else {
 60            FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) {
 61                                                                                                                                        FF_ARG(device->size, "bytes"),
 62                                                                                                                                        FF_ARG(prettySize, "size"),
 63                                                                                                                                        FF_ARG(device->maxSpeed, "max-speed"),
 64                                                                                                                                        FF_ARG(device->runningSpeed, "running-speed"),
 65                                                                                                                                        FF_ARG(device->type, "type"),
 66                                                                                                                                        FF_ARG(device->formFactor, "form-factor"),
 67                                                                                                                                        FF_ARG(device->locator, "locator"),
 68                                                                                                                                        FF_ARG(device->vendor, "vendor"),
 69                                                                                                                                        FF_ARG(device->serial, "serial"),
 70                                                                                                                                        FF_ARG(device->partNumber, "part-number"),
 71                                                                                                                                        FF_ARG(device->ecc, "is-ecc-enabled"),
 72                                                                                                                                        FF_ARG(device->installed, "is-installed"),
 73                                                                                                                                    }));
 74        }
 75
 76        i++;
 77    }
 78
 79    FF_LIST_FOR_EACH (FFPhysicalMemoryResult, device, result) {
 80        ffStrbufDestroy(&device->type);
 81        ffStrbufDestroy(&device->locator);
 82        ffStrbufDestroy(&device->formFactor);
 83        ffStrbufDestroy(&device->vendor);
 84        ffStrbufDestroy(&device->serial);
 85        ffStrbufDestroy(&device->partNumber);
 86    }
 87
 88    return true;
 89}
 90
 91void ffParsePhysicalMemoryJsonObject(FFPhysicalMemoryOptions* options, yyjson_val* module) {
 92    yyjson_val *key, *val;
 93    size_t idx, max;
 94    yyjson_obj_foreach (module, idx, max, key, val) {
 95        if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
 96            continue;
 97        }
 98
 99        if (unsafe_yyjson_equals_str(key, "showEmptySlots")) {
100            options->showEmptySlots = yyjson_get_bool(val);
101            continue;
102        }
103
104        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
105    }
106}
107
108[[gnu::cold]]
109void ffGeneratePhysicalMemoryJsonConfig(FFPhysicalMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
110    ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
111    yyjson_mut_obj_add_bool(doc, module, "showEmptySlots", options->showEmptySlots);
112}
113
114bool ffGeneratePhysicalMemoryJsonResult(FFPhysicalMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
115    FF_LIST_AUTO_DESTROY result = ffListCreate();
116    const char* error = ffDetectPhysicalMemory(options, &result);
117
118    if (error) {
119        yyjson_mut_obj_add_str(doc, module, "error", error);
120        return false;
121    }
122
123    yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
124    FF_LIST_FOR_EACH (FFPhysicalMemoryResult, device, result) {
125        yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
126        yyjson_mut_obj_add_uint(doc, obj, "size", device->size);
127        yyjson_mut_obj_add_bool(doc, obj, "installed", device->installed);
128        yyjson_mut_obj_add_uint(doc, obj, "maxSpeed", device->maxSpeed);
129        yyjson_mut_obj_add_uint(doc, obj, "runningSpeed", device->runningSpeed);
130        yyjson_mut_obj_add_strbuf(doc, obj, "type", &device->type);
131        yyjson_mut_obj_add_strbuf(doc, obj, "locator", &device->locator);
132        yyjson_mut_obj_add_strbuf(doc, obj, "formFactor", &device->formFactor);
133        yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &device->vendor);
134        yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
135        yyjson_mut_obj_add_strbuf(doc, obj, "partNumber", &device->partNumber);
136        yyjson_mut_obj_add_bool(doc, obj, "ecc", device->ecc);
137    }
138
139    FF_LIST_FOR_EACH (FFPhysicalMemoryResult, device, result) {
140        ffStrbufDestroy(&device->type);
141        ffStrbufDestroy(&device->locator);
142        ffStrbufDestroy(&device->formFactor);
143        ffStrbufDestroy(&device->vendor);
144        ffStrbufDestroy(&device->serial);
145        ffStrbufDestroy(&device->partNumber);
146    }
147
148    return true;
149}
150
151void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) {
152    ffOptionInitModuleArg(&options->moduleArgs, "󰑭");
153    options->showEmptySlots = false;
154}
155
156void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) {
157    ffOptionDestroyModuleArg(&options->moduleArgs);
158}
159
160FFModuleBaseInfo ffPhysicalMemoryModuleInfo = {
161    .name = "PhysicalMemory",
162    .description = "Print system physical memory devices",
163    .displayName = {
164        .en = "Physical Memory",
165        .ar = "الذاكرة الفعلية",
166        .cs = "Fyzická paměť",
167        .de = "Physischer Speicher",
168        .es = "Memoria física",
169        .fi = "Fyysinen Muisti",
170        .fr = "Mémoire physique",
171        .gl = "Memoria física",
172        .he = "זיכרון פיזי",
173        .id = "Memori Fisik",
174        .it = "Memoria fisica",
175        .ja = "物理メモリ",
176        .ko = "물리 메모리",
177        .pl = "Pamięć fizyczna",
178        .pt = "Memória física",
179        .ru = "Физическая память",
180        .tr = "Fiziksel Bellek",
181        .uk = "Фізична пам'ять",
182        .vi = "Bộ nhớ vật lý",
183        .zh_CN = "物理内存",
184        .zh_TW = "實體記憶體",
185    },
186    .initOptions = (void*) ffInitPhysicalMemoryOptions,
187    .destroyOptions = (void*) ffDestroyPhysicalMemoryOptions,
188    .parseJsonObject = (void*) ffParsePhysicalMemoryJsonObject,
189    .printModule = (void*) ffPrintPhysicalMemory,
190    .generateJsonConfig = (void*) ffGeneratePhysicalMemoryJsonConfig,
191    .generateJsonResult = (void*) ffGeneratePhysicalMemoryJsonResult,
192    .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
193        { "Size (in bytes)", "bytes" },
194        { "Size formatted", "size" },
195        { "Max speed (in MT/s)", "max-speed" },
196        { "Running speed (in MT/s)", "running-speed" },
197        { "Type (DDR4, DDR5, etc.)", "type" },
198        { "Form factor (SODIMM, DIMM, etc.)", "form-factor" },
199        { "Bank/Device Locator (BANK0/SIMM0, BANK0/SIMM1, etc.)", "locator" },
200        { "Vendor", "vendor" },
201        { "Serial number", "serial" },
202        { "Part number", "part-number" },
203        { "True if ECC enabled", "is-ecc-enabled" },
204        { "True if a memory module is installed in the slot", "is-installed" },
205    })),
206    .defaultOrder = 40,
207};