/src/systemd/src/fundamental/chid-fundamental.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: BSD-3-Clause */ |
2 | | |
3 | | /* |
4 | | * Based on Nikita Travkin's dtbloader implementation. |
5 | | * Copyright (c) 2024 Nikita Travkin <nikita@trvn.ru> |
6 | | * |
7 | | * https://github.com/TravMurav/dtbloader/blob/main/src/chid.c |
8 | | */ |
9 | | |
10 | | /* |
11 | | * Based on Linaro dtbloader implementation. |
12 | | * Copyright (c) 2019, Linaro. All rights reserved. |
13 | | * |
14 | | * https://github.com/aarch64-laptops/edk2/blob/dtbloader-app/EmbeddedPkg/Application/ConfigTableLoader/CHID.c |
15 | | */ |
16 | | |
17 | | #if SD_BOOT |
18 | | # include "efi-string.h" |
19 | | # include "util.h" |
20 | | #else |
21 | | # include <byteswap.h> |
22 | | # include <string.h> |
23 | | # include <utf8.h> |
24 | 0 | #define strlen16 char16_strlen |
25 | | #endif |
26 | | |
27 | | #include "chid-fundamental.h" |
28 | | #include "macro-fundamental.h" |
29 | | #include "memory-util-fundamental.h" |
30 | | #include "sha1-fundamental.h" |
31 | | |
32 | | static void get_chid( |
33 | | const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], |
34 | | uint32_t mask, |
35 | 0 | EFI_GUID *ret_chid) { |
36 | |
|
37 | 0 | assert(mask != 0); |
38 | 0 | assert(ret_chid); |
39 | |
|
40 | 0 | struct sha1_ctx ctx = {}; |
41 | 0 | sha1_init_ctx(&ctx); |
42 | |
|
43 | 0 | static const EFI_GUID namespace = { UINT32_C(0x12d8ff70), UINT16_C(0x7f4c), UINT16_C(0x7d4c), {} }; /* Swapped to BE */ |
44 | 0 | sha1_process_bytes(&namespace, sizeof(namespace), &ctx); |
45 | |
|
46 | 0 | for (ChidSmbiosFields i = 0; i < _CHID_SMBIOS_FIELDS_MAX; i++) { |
47 | 0 | if (!FLAGS_SET(mask, UINT32_C(1) << i)) |
48 | 0 | continue; |
49 | | |
50 | 0 | if (!smbios_fields[i]) { |
51 | | /* If some SMBIOS field is missing, don't generate the CHID, as per spec */ |
52 | 0 | memzero(ret_chid, sizeof(EFI_GUID)); |
53 | 0 | return; |
54 | 0 | } |
55 | | |
56 | 0 | if (i > 0) |
57 | 0 | sha1_process_bytes(L"&", 2, &ctx); |
58 | |
|
59 | 0 | sha1_process_bytes(smbios_fields[i], strlen16(smbios_fields[i]) * sizeof(char16_t), &ctx); |
60 | 0 | } |
61 | | |
62 | 0 | uint8_t hash[SHA1_DIGEST_SIZE]; |
63 | 0 | sha1_finish_ctx(&ctx, hash); |
64 | |
|
65 | 0 | assert_cc(sizeof(hash) >= sizeof(*ret_chid)); |
66 | 0 | memcpy(ret_chid, hash, sizeof(*ret_chid)); |
67 | | |
68 | | /* Convert the resulting CHID back to little-endian: */ |
69 | 0 | ret_chid->Data1 = bswap_32(ret_chid->Data1); |
70 | 0 | ret_chid->Data2 = bswap_16(ret_chid->Data2); |
71 | 0 | ret_chid->Data3 = bswap_16(ret_chid->Data3); |
72 | | |
73 | | /* set specific bits according to RFC4122 Section 4.1.3 */ |
74 | 0 | ret_chid->Data3 = (ret_chid->Data3 & 0x0fff) | (5 << 12); |
75 | 0 | ret_chid->Data4[0] = (ret_chid->Data4[0] & UINT8_C(0x3f)) | UINT8_C(0x80); |
76 | 0 | } |
77 | | |
78 | | const uint32_t chid_smbios_table[CHID_TYPES_MAX] = { |
79 | | [0] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
80 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
81 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
82 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) | |
83 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VENDOR) | |
84 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VERSION) | |
85 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MAJOR) | |
86 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MINOR), |
87 | | |
88 | | [1] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
89 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
90 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
91 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VENDOR) | |
92 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VERSION) | |
93 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MAJOR) | |
94 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MINOR), |
95 | | |
96 | | [2] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
97 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
98 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VENDOR) | |
99 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_VERSION) | |
100 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MAJOR) | |
101 | | (UINT32_C(1) << CHID_SMBIOS_BIOS_MINOR), |
102 | | |
103 | | [3] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
104 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
105 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
106 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) | |
107 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) | |
108 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT), |
109 | | |
110 | | [4] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
111 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
112 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
113 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU), |
114 | | |
115 | | [5] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
116 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
117 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME), |
118 | | |
119 | | [6] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
120 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) | |
121 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) | |
122 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT), |
123 | | |
124 | | [7] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
125 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU), |
126 | | |
127 | | [8] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
128 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) | |
129 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) | |
130 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT), |
131 | | |
132 | | [9] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
133 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME), |
134 | | |
135 | | [10] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
136 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
137 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) | |
138 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT), |
139 | | |
140 | | [11] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
141 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY), |
142 | | |
143 | | [12] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
144 | | (UINT32_C(1) << CHID_SMBIOS_ENCLOSURE_TYPE), |
145 | | |
146 | | [13] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
147 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) | |
148 | | (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT), |
149 | | |
150 | | [14] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER), |
151 | | |
152 | | /* Extra non-standard CHIDs */ |
153 | | |
154 | | [EXTRA_CHID_BASE + 0] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
155 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
156 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME)| |
157 | | (UINT32_C(1) << CHID_EDID_PANEL), |
158 | | |
159 | | [EXTRA_CHID_BASE + 1] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
160 | | (UINT32_C(1) << CHID_SMBIOS_FAMILY) | |
161 | | (UINT32_C(1) << CHID_EDID_PANEL), |
162 | | |
163 | | [EXTRA_CHID_BASE + 2] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) | |
164 | | (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) | |
165 | | (UINT32_C(1) << CHID_EDID_PANEL), |
166 | | }; |
167 | | |
168 | 0 | void chid_calculate(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], EFI_GUID ret_chids[static CHID_TYPES_MAX]) { |
169 | 0 | assert(smbios_fields); |
170 | 0 | assert(ret_chids); |
171 | |
|
172 | 0 | for (size_t i = 0; i < CHID_TYPES_MAX; i++) { |
173 | 0 | if (chid_smbios_table[i] == 0) { |
174 | 0 | memzero(&ret_chids[i], sizeof(EFI_GUID)); |
175 | 0 | continue; |
176 | 0 | } |
177 | | |
178 | 0 | get_chid(smbios_fields, chid_smbios_table[i], &ret_chids[i]); |
179 | 0 | } |
180 | 0 | } |