blob: 53ed4f7ed67e17510d022205980947c365ffa763 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10302#include <libpldm/base.h>
3#include <libpldm/utils.h>
Carter Chenff78bca2025-06-25 10:33:31 +08004#include "utils.h"
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10305
Andrew Jefferya8b8a812023-04-05 14:32:12 +09306#include <limits.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09307#include <stdio.h>
8
9/** CRC32 code derived from work by Gary S. Brown.
10 * http://web.mit.edu/freebsd/head/sys/libkern/crc32.c
11 *
12 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
13 * code or tables extracted from it, as desired without restriction.
14 *
15 */
16static uint32_t crc32_tab[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093017 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
18 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
19 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
20 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
21 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
22 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
23 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
24 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
25 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
26 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
27 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
28 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
29 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
30 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
31 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
32 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
33 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
34 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
35 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
36 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
37 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
38 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
39 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
40 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
41 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
42 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
43 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
44 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
45 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
46 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
47 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
48 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
49 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
50 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
51 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
52 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
53 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
54 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
55 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
56 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
57 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
58 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
59 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
60};
Andrew Jeffery9c766792022-08-10 23:12:49 +093061
62/* 0x07(polynomial: x8+x2+x1+1)
63 */
64static const uint8_t crc8_table[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093065 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
66 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
67 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
68 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
69 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
70 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
71 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
72 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
73 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
74 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
75 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
76 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
77 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
78 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
79 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
80 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
81 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
82 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
83 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
84 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
85 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
86 0xfa, 0xfd, 0xf4, 0xf3
87};
Andrew Jeffery9c766792022-08-10 23:12:49 +093088
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093089LIBPLDM_ABI_STABLE
Andrew Jefferya3863482025-04-05 20:11:02 +103090uint32_t pldm_edac_crc32(const void *data, size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +093091{
92 const uint8_t *p = data;
93 uint32_t crc = ~0U;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093094 while (size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093095 crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093096 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093097 return crc ^ ~0U;
98}
99
Carter Chenff78bca2025-06-25 10:33:31 +0800100int pldm_edac_crc32_validate(uint32_t expected, const void *data, size_t size)
101{
102 if (!data && size) { /* data is NULL but size is not zero */
103 return -EINVAL;
104 }
105 uint32_t actual = pldm_edac_crc32(data, size);
106 return (expected == actual) ? 0 : -EUCLEAN;
107}
108
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930109LIBPLDM_ABI_STABLE
Andrew Jefferyd0c9ae72025-04-05 20:11:02 +1030110uint8_t pldm_edac_crc8(const void *data, size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930111{
112 const uint8_t *p = data;
113 uint8_t crc = 0x00;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930114 while (size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115 crc = crc8_table[crc ^ *p++];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930116 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930117 return crc;
118}
119
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930120#define BCD_H(v) (((v) >> 4) & 0xf)
Patrick Williamsc0b5a6e2023-10-20 11:20:16 -0500121#define BCD_L(v) ((v) & 0xf)
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930122#define AS_CHAR(digit) ((digit) + '0')
123#define INSERT_CHAR(c, b, n) \
124 { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930125 if ((n) > 1) { \
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930126 *(b)++ = (c); \
127 (n)--; \
128 } \
129 }
130#define INSERT_INT(i, b, n) INSERT_CHAR(AS_CHAR(i), (b), (n))
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930131
132LIBPLDM_ABI_STABLE
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930133ssize_t ver2str(const ver32_t *version, char *buffer, size_t buffer_size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930134{
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930135 ssize_t remaining;
136 char *cursor;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930137
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930138 if (!version || !buffer) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930139 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930140 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930141
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930142 if (!buffer_size) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930143 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930144 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930145
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930146 if (buffer_size > SSIZE_MAX) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930147 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930148 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930149
150 cursor = buffer;
151 remaining = (ssize_t)buffer_size;
152
153 if (version->major < 0xf0)
154 INSERT_INT(BCD_H(version->major), cursor, remaining)
155 INSERT_INT(BCD_L(version->major), cursor, remaining);
156 INSERT_CHAR('.', cursor, remaining);
157
158 if (version->minor < 0xf0)
159 INSERT_INT(BCD_H(version->minor), cursor, remaining);
160 INSERT_INT(BCD_L(version->minor), cursor, remaining);
161
162 if (version->update < 0xff) {
163 INSERT_CHAR('.', cursor, remaining);
164 if (version->update < 0xf0)
165 INSERT_INT(BCD_H(version->update), cursor, remaining);
166 INSERT_INT(BCD_L(version->update), cursor, remaining);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930167 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930168
169 if (version->alpha)
170 INSERT_CHAR(version->alpha, cursor, remaining);
171
172 *cursor = '\0';
173
174 return (ssize_t)buffer_size - remaining;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930175}
176
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930177LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930178uint8_t bcd2dec8(uint8_t bcd)
179{
Andrew Jeffery3c016182023-04-05 14:23:21 +0930180 return (bcd >> 4) * 10 + (bcd & 0x0f);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930181}
182
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930183LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930184uint8_t dec2bcd8(uint8_t dec)
185{
Andrew Jefferye21df502023-04-05 14:28:47 +0930186 return ((dec / 10) << 4) + (dec % 10);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930187}
188
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930189LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930190uint16_t bcd2dec16(uint16_t bcd)
191{
192 return bcd2dec8(bcd >> 8) * 100 + bcd2dec8(bcd & 0xff);
193}
194
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930195LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196uint16_t dec2bcd16(uint16_t dec)
197{
Andrew Jeffery3ce64fb2023-04-12 22:21:40 +0930198 return dec2bcd8(dec % 100) | ((uint16_t)(dec2bcd8(dec / 100)) << 8);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930199}
200
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930201LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930202uint32_t bcd2dec32(uint32_t bcd)
203{
204 return bcd2dec16(bcd >> 16) * 10000 + bcd2dec16(bcd & 0xffff);
205}
206
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930207LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930208uint32_t dec2bcd32(uint32_t dec)
209{
Andrew Jeffery3ce64fb2023-04-12 22:21:40 +0930210 return dec2bcd16(dec % 10000) |
211 ((uint32_t)(dec2bcd16(dec / 10000)) << 16);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930212}
213
Andrew Jefferya1809632024-10-04 21:05:54 +0930214static int day_map(uint8_t month)
215{
216 switch (month) {
217 case 1:
218 return 31;
219 case 2:
220 return 28;
221 case 3:
222 return 31;
223 case 4:
224 return 30;
225 case 5:
226 return 31;
227 case 6:
228 return 30;
229 case 7:
230 case 8:
231 return 31;
232 case 9:
233 return 30;
234 case 10:
235 return 31;
236 case 11:
237 return 30;
238 case 12:
239 return 31;
240 default:
241 return 0;
242 }
243}
244
Andrew Jeffery800e1832025-04-05 18:56:14 +1030245LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930246bool is_time_legal(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day,
247 uint8_t month, uint16_t year)
248{
249 if (month < 1 || month > 12) {
250 return false;
251 }
Andrew Jefferya1809632024-10-04 21:05:54 +0930252 int rday = day_map(month);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930253 if (month == 2 &&
254 ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
255 rday += 1;
256 }
257 if (year < 1970 || day < 1 || day > rday || seconds > 59 ||
258 minutes > 59 || hours > 23) {
259 return false;
260 }
261 return true;
262}
263
Andrew Jefferyb7677b72025-04-05 18:56:14 +1030264LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930265bool is_transfer_flag_valid(uint8_t transfer_flag)
266{
267 switch (transfer_flag) {
268 case PLDM_START:
269 case PLDM_MIDDLE:
270 case PLDM_END:
271 case PLDM_START_AND_END:
272 return true;
273
274 default:
275 return false;
276 }
277}