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