Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-hwids-fdt.c
Line
Count
Source
1
/*
2
 * Copyright 2023 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuContext"
8
9
#include "config.h"
10
11
#include "fu-context-private.h"
12
#include "fu-fdt-firmware.h"
13
#include "fu-hwids-private.h"
14
15
gboolean
16
fu_hwids_fdt_setup(FuContext *ctx, FuHwids *self, GError **error)
17
0
{
18
0
  g_autofree gchar *chassis_type = NULL;
19
0
  g_auto(GStrv) compatible = NULL;
20
0
  g_autoptr(FuFirmware) fdt_img = NULL;
21
0
  g_autoptr(FuFdtImage) fdt_img_baseb = NULL;
22
0
  g_autoptr(FuFdtImage) fdt_img_fwver = NULL;
23
0
  g_autoptr(FuFirmware) fdt = NULL;
24
0
  struct {
25
0
    const gchar *hwid;
26
0
    const gchar *key;
27
0
  } map[] = {
28
0
      {FU_HWIDS_KEY_MANUFACTURER, "vendor"},
29
0
      {FU_HWIDS_KEY_FAMILY, "model-name"},
30
0
      {FU_HWIDS_KEY_PRODUCT_NAME, "model"},
31
0
  };
32
33
  /* adds compatible GUIDs */
34
0
  fdt = fu_context_get_fdt(ctx, error);
35
0
  if (fdt == NULL)
36
0
    return FALSE;
37
0
  fdt_img = fu_firmware_get_image_by_id(fdt, NULL, error);
38
0
  if (fdt_img == NULL)
39
0
    return FALSE;
40
0
  if (!fu_fdt_image_get_attr_strlist(FU_FDT_IMAGE(fdt_img), "compatible", &compatible, error))
41
0
    return FALSE;
42
0
  for (guint i = 0; compatible[i] != NULL; i++) {
43
0
    g_autofree gchar *guid = fwupd_guid_hash_string(compatible[i]);
44
0
    g_debug("using %s for DT compatible %s", guid, compatible[i]);
45
0
    fu_hwids_add_guid(self, guid);
46
0
  }
47
48
  /* root node */
49
0
  for (guint i = 0; i < G_N_ELEMENTS(map); i++) {
50
0
    g_autofree gchar *tmp = NULL;
51
0
    fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img), map[i].key, &tmp, NULL);
52
0
    if (tmp == NULL)
53
0
      continue;
54
0
    fu_hwids_add_value(self, map[i].hwid, tmp);
55
0
  }
56
57
  /* chassis kind */
58
0
  fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img), "chassis-type", &chassis_type, NULL);
59
0
  if (chassis_type != NULL) {
60
0
    struct {
61
0
      FuSmbiosChassisKind chassis_kind;
62
0
      const gchar *dt;
63
0
    } chassis_map[] = {{FU_SMBIOS_CHASSIS_KIND_CONVERTIBLE, "convertible"},
64
0
           {FU_SMBIOS_CHASSIS_KIND_EMBEDDED_PC, "embedded"},
65
0
           {FU_SMBIOS_CHASSIS_KIND_HAND_HELD, "handset"},
66
0
           {FU_SMBIOS_CHASSIS_KIND_LAPTOP, "laptop"},
67
0
           {FU_SMBIOS_CHASSIS_KIND_TABLET, "tablet"},
68
0
           {FU_SMBIOS_CHASSIS_KIND_UNKNOWN, NULL}};
69
0
    for (guint i = 0; chassis_map[i].dt != NULL; i++) {
70
0
      if (g_strcmp0(chassis_type, chassis_map[i].dt) == 0) {
71
0
        fu_context_set_chassis_kind(ctx, chassis_map[i].chassis_kind);
72
0
        break;
73
0
      }
74
0
    }
75
0
  }
76
77
  /* fallback */
78
0
  if (g_strv_length(compatible) > 0) {
79
0
    g_auto(GStrv) compatible0 = g_strsplit(compatible[0], ",", -1);
80
0
    fu_hwids_add_value(self, FU_HWIDS_KEY_MANUFACTURER, compatible0[0]);
81
0
    if (g_strv_length(compatible0) > 1)
82
0
      fu_hwids_add_value(self, FU_HWIDS_KEY_PRODUCT_NAME, compatible0[1]);
83
0
  }
84
0
  if (g_strv_length(compatible) > 1)
85
0
    fu_hwids_add_value(self, FU_HWIDS_KEY_FAMILY, compatible[1]);
86
0
  if (fu_context_get_chassis_kind(ctx) == FU_SMBIOS_CHASSIS_KIND_UNKNOWN) {
87
0
    if (fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img), "battery", NULL, NULL))
88
0
      fu_context_set_chassis_kind(ctx, FU_SMBIOS_CHASSIS_KIND_PORTABLE);
89
0
  }
90
0
  fdt_img_fwver =
91
0
      fu_fdt_firmware_get_image_by_path(FU_FDT_FIRMWARE(fdt), "/ibm,firmware-versions", NULL);
92
0
  if (fdt_img_fwver != NULL) {
93
0
    g_autofree gchar *version = NULL;
94
0
    fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img), "version", &version, NULL);
95
0
    fu_hwids_add_value(self, FU_HWIDS_KEY_BIOS_VERSION, version);
96
0
  }
97
98
  /* fall back to the firmware unix time */
99
0
  if (fdt_img_fwver == NULL) {
100
0
    fdt_img_fwver = fu_fdt_firmware_get_image_by_path(FU_FDT_FIRMWARE(fdt),
101
0
                  "/chosen/bootloader",
102
0
                  NULL);
103
0
  }
104
0
  if (fdt_img_fwver != NULL) {
105
0
    guint32 timestamp = 0;
106
0
    fu_fdt_image_get_attr_u32(FU_FDT_IMAGE(fdt_img_fwver),
107
0
            "build-timestamp",
108
0
            &timestamp,
109
0
            NULL);
110
0
    if (timestamp != 0) {
111
0
      g_autoptr(GDateTime) dt = g_date_time_new_from_unix_utc(timestamp);
112
0
      g_autofree gchar *version = g_date_time_format(dt, "%Y%m%d");
113
0
      fu_hwids_add_value(self, FU_HWIDS_KEY_BIOS_VERSION, version);
114
0
    }
115
0
  }
116
117
0
  fdt_img_baseb = fu_fdt_firmware_get_image_by_path(
118
0
      FU_FDT_FIRMWARE(fdt),
119
0
      "/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800",
120
0
      NULL);
121
0
  if (fdt_img_baseb != NULL) {
122
0
    g_autofree gchar *vendor = NULL;
123
0
    g_autofree gchar *product = NULL;
124
0
    fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img_baseb), "vendor", &vendor, NULL);
125
0
    fu_fdt_image_get_attr_str(FU_FDT_IMAGE(fdt_img_baseb),
126
0
            "part-number",
127
0
            &product,
128
0
            NULL);
129
0
    if (vendor != NULL)
130
0
      fu_hwids_add_value(self, FU_HWIDS_KEY_BASEBOARD_MANUFACTURER, vendor);
131
0
    if (product != NULL)
132
0
      fu_hwids_add_value(self, FU_HWIDS_KEY_BASEBOARD_PRODUCT, product);
133
0
  }
134
135
  /* success */
136
0
  return TRUE;
137
0
}