LCOV - code coverage report
Current view: top level - pkg/systemd - hw-detect.js Coverage Total Hit
Test: cockpit Lines: 87.3 % 126 110
Test Date: 2026-07-17 12:03:54

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2018 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5            2 : import cockpit from "cockpit";
       6              : 
       7              : import * as machine_info from "machine-info.js";
       8            2 : const _ = cockpit.gettext;
       9              : 
      10              : // map an info.system key to a /sys/class/dmi/id/* attribute name
      11            2 : const InfoDMIKey = {
      12            2 :     version: "product_version",
      13            2 :     name: "product_name",
      14            2 :     alt_version: "board_vendor",
      15            2 :     alt_name: "board_name",
      16            2 :     type: "chassis_type_str",
      17            2 :     bios_vendor: "bios_vendor",
      18            2 :     bios_version: "bios_version",
      19            2 :     bios_date: "bios_date",
      20            2 : };
      21              : 
      22            2 : const getDMI = info => machine_info.dmi_info()
      23            2 :         .then(fields => {
      24            2 :             Object.keys(InfoDMIKey).forEach(key => {
      25            2 :                 info.system[key] = fields[InfoDMIKey[key]];
      26            2 :             });
      27            2 :             return true;
      28            2 :         });
      29              : 
      30            2 : const getDeviceTree = info => machine_info.devicetree_info()
      31            2 :         .then(fields => {
      32              :             // if getDMI sets a field first, let that win
      33            1 :             if (fields.model && !info.system.name)
      34            1 :                 info.system.name = fields.model;
      35            2 :             return true;
      36            2 :         });
      37              : 
      38              : // Add info.pci [{slot, cls, vendor, model}] list
      39            2 : function findPCI(udevdb, info) {
      40            2 :     for (const syspath in udevdb) {
      41            2 :         const props = udevdb[syspath];
      42            2 :         if (props.SUBSYSTEM === "pci")
      43            2 :             info.pci.push({
      44            1 :                 slot: props.PCI_SLOT_NAME || syspath.split("/").pop() || "",
      45            1 :                 cls: props.ID_PCI_CLASS_FROM_DATABASE || props.PCI_CLASS.toString() || "",
      46            1 :                 vendor: props.ID_VENDOR_FROM_DATABASE || "",
      47            1 :                 model: props.ID_MODEL_FROM_DATABASE || props.PCI_ID || ""
      48            2 :             });
      49            2 :     }
      50            2 : }
      51              : 
      52            2 : function findMemoryDevices(udevdb, info) {
      53            2 :     const memoryArray = [];
      54            2 :     const dmipath = '/devices/virtual/dmi/id';
      55            2 :     if (!(dmipath in udevdb))
      56            2 :         return;
      57              : 
      58            2 :     const props = udevdb[dmipath];
      59              :     // Systemd now exposes memory information in udev, introduced in systemd => 248
      60              :     // https://github.com/systemd/systemd/blob/main/NEWS#L1713
      61            1 :     if (!('MEMORY_ARRAY_NUM_DEVICES' in props)) {
      62            1 :         return;
      63            1 :     }
      64              : 
      65            2 :     const devices = parseInt(props.MEMORY_ARRAY_NUM_DEVICES, 10);
      66            2 :     for (let slot = 0; slot < devices; slot++) {
      67            2 :         let memorySize = parseInt(props[`MEMORY_DEVICE_${slot}_SIZE`], 10);
      68            2 :         if (memorySize) {
      69            2 :             memorySize = cockpit.format_bytes(memorySize, { base2: true });
      70            1 :         } else {
      71            1 :             memorySize = _("Unknown");
      72            1 :         }
      73              : 
      74            2 :         let memoryRank = props[`MEMORY_DEVICE_${slot}_RANK`];
      75            1 :         if (memoryRank == 1) {
      76            1 :             memoryRank = _("Single rank");
      77            1 :         } else if (memoryRank == 2) {
      78            1 :             memoryRank = _("Dual rank");
      79            1 :         } else {
      80            2 :             memoryRank = _("Unknown");
      81            2 :         }
      82              : 
      83            2 :         let speed = props[`MEMORY_DEVICE_${slot}_SPEED_MTS`];
      84            1 :         if (speed) {
      85            1 :             speed += ' MT/s';
      86            1 :         } else {
      87            2 :             speed = _("Unknown");
      88            2 :         }
      89              : 
      90            2 :         let locator = _("Unknown");
      91            2 :         if (props[`MEMORY_DEVICE_${slot}_BANK_LOCATOR`] && props[`MEMORY_DEVICE_${slot}_LOCATOR`]) {
      92            2 :             locator = props[`MEMORY_DEVICE_${slot}_BANK_LOCATOR`] + ': ' + props[`MEMORY_DEVICE_${slot}_LOCATOR`];
      93            2 :         }
      94              : 
      95            2 :         memoryArray.push({
      96            2 :             locator,
      97            2 :             technology: props[`MEMORY_DEVICE_${slot}_MEMORY_TECHNOLOGY`] || _("Unknown"),
      98            1 :             type: props[`MEMORY_DEVICE_${slot}_TYPE`] || _("Unknown"),
      99            2 :             size: memorySize,
     100            1 :             state: props[`MEMORY_DEVICE_${slot}_TOTAL_WIDTH`] ? _("Present") : _("Absent"),
     101            2 :             rank: memoryRank,
     102            2 :             speed,
     103            2 :         });
     104            2 :     }
     105              : 
     106            2 :     info.memory = memoryArray;
     107            2 : }
     108              : 
     109            2 : export default function detect() {
     110            2 :     const info = { system: {}, pci: [], memory: [] };
     111            2 :     const tasks = [];
     112              : 
     113            2 :     tasks.push(machine_info.cpu_ram_info()
     114            2 :             .then(result => {
     115            1 :                 info.system.cpu_model = result.cpu_model || _("unknown");
     116            2 :                 info.system.nproc = result.cpus;
     117            2 :                 return true;
     118            2 :             }));
     119              : 
     120            2 :     tasks.push(getDMI(info)
     121            0 :             .catch(error => {
     122            0 :                 console.warn("Failed to get DMI information:", error.toString());
     123            0 :                 return true;
     124            0 :             }));
     125              : 
     126            2 :     tasks.push(getDeviceTree(info)
     127            0 :             .catch(error => {
     128            0 :                 console.debug("Failed to get DeviceTree information:", error.toString());
     129            0 :                 return true;
     130            0 :             }));
     131              : 
     132            2 :     tasks.push(machine_info.udev_info()
     133            2 :             .then(result => {
     134            2 :                 findPCI(result, info);
     135            2 :                 findMemoryDevices(result, info);
     136            2 :                 return true;
     137            2 :             })
     138            0 :             .catch(error => {
     139            0 :                 console.warn("Failed to get udev information:", error.toString());
     140            0 :                 return true;
     141            0 :             }));
     142              : 
     143              :     // Fallback if systemd < 248
     144            2 :     if (info.memory.length === 0) {
     145            2 :         tasks.push(machine_info.memory_info()
     146            2 :                 .then(result => {
     147            2 :                     info.memory = result;
     148            2 :                     return true;
     149            2 :                 })
     150            0 :                 .catch(error => {
     151            0 :                     console.warn("Failed to get dmidecode information: ", error.toString());
     152            0 :                     return true;
     153            0 :                 }));
     154            2 :     }
     155              : 
     156              :     // return info after all task promises got done
     157            2 :     return Promise.all(tasks).then(() => info);
     158            2 : }
        

Generated by: LCOV version 2.0-1