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