blob: a22c47245cb4a4949006a44b8b22216929c7dff9 [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>
4
Andrew Jefferya8b8a812023-04-05 14:32:12 +09305#include <limits.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09306#include <stdio.h>
7
8/** CRC32 code derived from work by Gary S. Brown.
9 * http://web.mit.edu/freebsd/head/sys/libkern/crc32.c
10 *
11 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
12 * code or tables extracted from it, as desired without restriction.
13 *
14 */
15static uint32_t crc32_tab[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093016 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
17 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
18 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
19 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
20 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
21 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
22 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
23 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
24 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
25 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
26 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
27 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
28 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
29 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
30 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
31 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
32 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
33 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
34 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
35 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
36 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
37 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
38 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
39 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
40 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
41 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
42 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
43 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
44 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
45 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
46 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
47 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
48 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
49 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
50 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
51 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
52 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
53 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
54 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
55 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
56 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
57 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
58 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
59};
Andrew Jeffery9c766792022-08-10 23:12:49 +093060
61/* 0x07(polynomial: x8+x2+x1+1)
62 */
63static const uint8_t crc8_table[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093064 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
65 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
66 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
67 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
68 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
69 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
70 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
71 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
72 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
73 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
74 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
75 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
76 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
77 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
78 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
79 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
80 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
81 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
82 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
83 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
84 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
85 0xfa, 0xfd, 0xf4, 0xf3
86};
Andrew Jeffery9c766792022-08-10 23:12:49 +093087
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093088LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093089uint32_t crc32(const void *data, size_t size)
90{
91 const uint8_t *p = data;
92 uint32_t crc = ~0U;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093093 while (size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093094 crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093095 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093096 return crc ^ ~0U;
97}
98
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093099LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930100uint8_t crc8(const void *data, size_t size)
101{
102 const uint8_t *p = data;
103 uint8_t crc = 0x00;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930104 while (size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930105 crc = crc8_table[crc ^ *p++];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930106 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930107 return crc;
108}
109
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930110#define BCD_H(v) (((v) >> 4) & 0xf)
Patrick Williamsc0b5a6e2023-10-20 11:20:16 -0500111#define BCD_L(v) ((v) & 0xf)
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930112#define AS_CHAR(digit) ((digit) + '0')
113#define INSERT_CHAR(c, b, n) \
114 { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930115 if ((n) > 1) { \
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930116 *(b)++ = (c); \
117 (n)--; \
118 } \
119 }
120#define INSERT_INT(i, b, n) INSERT_CHAR(AS_CHAR(i), (b), (n))
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930121
122LIBPLDM_ABI_STABLE
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930123ssize_t ver2str(const ver32_t *version, char *buffer, size_t buffer_size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930124{
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930125 ssize_t remaining;
126 char *cursor;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930127
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930128 if (!version || !buffer) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930129 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930130 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930131
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930132 if (!buffer_size) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930133 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930134 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930135
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930136 if (buffer_size > SSIZE_MAX) {
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930137 return -1;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930138 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930139
140 cursor = buffer;
141 remaining = (ssize_t)buffer_size;
142
143 if (version->major < 0xf0)
144 INSERT_INT(BCD_H(version->major), cursor, remaining)
145 INSERT_INT(BCD_L(version->major), cursor, remaining);
146 INSERT_CHAR('.', cursor, remaining);
147
148 if (version->minor < 0xf0)
149 INSERT_INT(BCD_H(version->minor), cursor, remaining);
150 INSERT_INT(BCD_L(version->minor), cursor, remaining);
151
152 if (version->update < 0xff) {
153 INSERT_CHAR('.', cursor, remaining);
154 if (version->update < 0xf0)
155 INSERT_INT(BCD_H(version->update), cursor, remaining);
156 INSERT_INT(BCD_L(version->update), cursor, remaining);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930157 }
Andrew Jefferya8b8a812023-04-05 14:32:12 +0930158
159 if (version->alpha)
160 INSERT_CHAR(version->alpha, cursor, remaining);
161
162 *cursor = '\0';
163
164 return (ssize_t)buffer_size - remaining;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930165}
166
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930167LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168uint8_t bcd2dec8(uint8_t bcd)
169{
Andrew Jeffery3c016182023-04-05 14:23:21 +0930170 return (bcd >> 4) * 10 + (bcd & 0x0f);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930171}
172
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930173LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930174uint8_t dec2bcd8(uint8_t dec)
175{
Andrew Jefferye21df502023-04-05 14:28:47 +0930176 return ((dec / 10) << 4) + (dec % 10);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930177}
178
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930179LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930180uint16_t bcd2dec16(uint16_t bcd)
181{
182 return bcd2dec8(bcd >> 8) * 100 + bcd2dec8(bcd & 0xff);
183}
184
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930185LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930186uint16_t dec2bcd16(uint16_t dec)
187{
Andrew Jeffery3ce64fb2023-04-12 22:21:40 +0930188 return dec2bcd8(dec % 100) | ((uint16_t)(dec2bcd8(dec / 100)) << 8);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930189}
190
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930191LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192uint32_t bcd2dec32(uint32_t bcd)
193{
194 return bcd2dec16(bcd >> 16) * 10000 + bcd2dec16(bcd & 0xffff);
195}
196
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930197LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930198uint32_t dec2bcd32(uint32_t dec)
199{
Andrew Jeffery3ce64fb2023-04-12 22:21:40 +0930200 return dec2bcd16(dec % 10000) |
201 ((uint32_t)(dec2bcd16(dec / 10000)) << 16);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930202}
203
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930204LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930205bool is_time_legal(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day,
206 uint8_t month, uint16_t year)
207{
208 if (month < 1 || month > 12) {
209 return false;
210 }
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930211 static const int days[13] = { 0, 31, 28, 31, 30, 31, 30,
212 31, 31, 30, 31, 30, 31 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930213 int rday = days[month];
214 if (month == 2 &&
215 ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
216 rday += 1;
217 }
218 if (year < 1970 || day < 1 || day > rday || seconds > 59 ||
219 minutes > 59 || hours > 23) {
220 return false;
221 }
222 return true;
223}
224
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930225LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930226bool is_transfer_flag_valid(uint8_t transfer_flag)
227{
228 switch (transfer_flag) {
229 case PLDM_START:
230 case PLDM_MIDDLE:
231 case PLDM_END:
232 case PLDM_START_AND_END:
233 return true;
234
235 default:
236 return false;
237 }
238}