File: | util/supermicro/smcbiosinfo/smcbiosinfo.c |
Warning: | line 81, column 10 Although the value stored to 'read' is used in the enclosing expression, the value is never actually read from 'read' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | |
3 | #include <stdio.h> |
4 | #include <string.h> |
5 | #include <stdlib.h> |
6 | #include <stdint.h> |
7 | #include <unistd.h> |
8 | #include <sys/types.h> |
9 | #include <sys/stat.h> |
10 | #include <getopt.h> |
11 | #include <errno(*__errno_location ()).h> |
12 | #include <stdarg.h> |
13 | |
14 | /* Place the following struct somewhere in the ROM: */ |
15 | struct SMC_BIOS_Update { |
16 | uint8_t magic0[4]; // always 0xaa00b1ed |
17 | char magic1[4]; // always $FID |
18 | uint8_t magic2[2]; // always 0x7804 |
19 | uint8_t space0; // always zero |
20 | // SMCinfotool doesn't care for the first letter |
21 | // The BMC webinterface does. |
22 | char boardid[9]; // "100000000" |
23 | uint8_t space1[15]; // unknown data |
24 | uint8_t space2; // always 0x1f |
25 | char ukn_majorVer[2];// unknown |
26 | uint8_t space3; // always zero |
27 | char ukn_minorVer[2];// unknown |
28 | uint8_t space4; // always zero |
29 | char majorVer[3]; // BIOS major version |
30 | char minorVer[2]; // BIOS minor version |
31 | uint8_t space5; // always zero |
32 | uint16_t year; // year |
33 | uint8_t month; // month |
34 | uint8_t day; // day |
35 | uint32_t space6; // unknown data |
36 | uint8_t space7; // all ones |
37 | char str[15]; // "SUPERMSMCI--MB1" |
38 | uint8_t space8[3]; // always zero |
39 | uint64_t space9[6]; // all ones |
40 | } __packed__attribute__((__packed__)); |
41 | |
42 | static const char *optstring = "b:i:o:h"; |
43 | |
44 | static struct option long_options[] = { |
45 | {"boardid", required_argument1, 0, 'b' }, |
46 | {"input", required_argument1, 0, 'i' }, |
47 | {"output", required_argument1, 0, 'o' }, |
48 | {"help", no_argument0, 0, 'h' }, |
49 | }; |
50 | |
51 | static void usage(void) |
52 | { |
53 | printf("smcbiosinfo: Create BIOSInfo for BMC BIOS updates\n"); |
54 | printf("Usage: smcbiosinfo [options] -i build.h -b <boardid> -o <filename>\n"); |
55 | printf("-b | --boardid <ID> The board ID assigned by SMC\n"); |
56 | printf("-i | --input <FILE> The build.h file to parse\n"); |
57 | printf("-o | --output <FILE> The file to generate\n"); |
58 | printf("-h | --help Print this help\n"); |
59 | } |
60 | |
61 | static int bcd2int(int hex) |
62 | { |
63 | if (hex > 0xff) |
64 | return -1; |
65 | return ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F); |
66 | } |
67 | |
68 | static char *get_line(char *fn, char *match) |
69 | { |
70 | ssize_t read; |
71 | char *line = NULL((void*)0); |
72 | char *ret = NULL((void*)0); |
73 | size_t len = 0; |
74 | |
75 | FILE *fp = fopen(fn, "r"); |
76 | if (fp == NULL((void*)0)) { |
77 | fprintf(stderrstderr, "E: Couldn't open file '%s'\n", fn); |
78 | return NULL((void*)0); |
79 | } |
80 | |
81 | while ((read = getline(&line, &len, fp)) != -1) { |
Although the value stored to 'read' is used in the enclosing expression, the value is never actually read from 'read' | |
82 | if (strstr(line, match) != NULL((void*)0)) { |
83 | ret = strdup(strstr(line, match) + strlen(match)); |
84 | break; |
85 | } |
86 | } |
87 | |
88 | if (!ret) |
89 | fprintf(stderrstderr, "E: %s not found in %s\n", match, fn); |
90 | |
91 | fclose(fp); |
92 | return ret; |
93 | } |
94 | |
95 | static int get_line_as_int(char *fn, char *match, int bcd) |
96 | { |
97 | int ret = -1; |
98 | char *s = get_line(fn, match); |
99 | if (s && strlen(s) > 0) { |
100 | char *endptr; |
101 | ret = strtol(s, &endptr, 0); |
102 | if (*endptr != '\0' && *endptr != '\n') { |
103 | fprintf(stderrstderr, "E: Couldn't parse number for key '%s'\n", match); |
104 | return -1; |
105 | } |
106 | if (bcd) |
107 | ret = bcd2int(ret); |
108 | free(s); |
109 | } else { |
110 | fprintf(stderrstderr, "E: Got invalid line for key '%s'\n", match); |
111 | } |
112 | |
113 | return ret; |
114 | } |
115 | |
116 | int main(int argc, char **argv) |
117 | { |
118 | int c; |
119 | int ret = 1; |
120 | char *filename = NULL((void*)0); |
121 | char *inputfilename = NULL((void*)0); |
122 | char *boardid = NULL((void*)0); |
123 | int num; |
124 | |
125 | while (1) { |
126 | int optindex = 0; |
127 | |
128 | c = getopt_long(argc, argv, optstring, long_options, &optindex); |
129 | |
130 | if (c == -1) |
131 | break; |
132 | |
133 | switch (c) { |
134 | case 'b': |
135 | boardid = strdup(optarg); |
136 | break; |
137 | case 'i': |
138 | inputfilename = strdup(optarg); |
139 | break; |
140 | case 'o': |
141 | filename = strdup(optarg); |
142 | break; |
143 | case 'h': |
144 | ret = 0; /* fallthrough */ |
145 | case '?': |
146 | usage(); |
147 | goto out; |
148 | default: |
149 | break; |
150 | } |
151 | } |
152 | |
153 | if (!inputfilename) { |
154 | fprintf(stderrstderr, "E: Must specify build.h filename\n"); |
155 | goto out; |
156 | } |
157 | if (!filename) { |
158 | fprintf(stderrstderr, "E: Must specify a destination filename\n"); |
159 | goto out; |
160 | } |
161 | |
162 | if (!boardid || strlen(boardid) == 0) { |
163 | fprintf(stderrstderr, "E: Board ID must be set\n"); |
164 | goto out; |
165 | } |
166 | if (strlen(boardid) > 8) { |
167 | fprintf(stderrstderr, "E: Board ID must be less than 8 characters\n"); |
168 | goto out; |
169 | } |
170 | |
171 | // generate the table |
172 | |
173 | struct SMC_BIOS_Update sbu = { |
174 | {0xed, 0xb1, 0x00, 0xaa}, |
175 | "$FID", |
176 | {0x04, 0x78}, |
177 | 0, // space |
178 | "100000000", // boardid |
179 | {}, // unknown data |
180 | 0x1f, // space |
181 | "05", // unknown data |
182 | 0, // zero |
183 | "06", // unknown data |
184 | 0, // zero |
185 | "000", // major |
186 | "00", // minor |
187 | 0, // zero |
188 | 0, // year |
189 | 0, // month |
190 | 0, //day |
191 | 0, // unknown data |
192 | 0xff, // space |
193 | "SUPERMSMCI--MB1", |
194 | {0, 0, 0}, // all zero |
195 | {~0, ~0, ~0, ~0, ~0, ~0}, // all ones |
196 | }; |
197 | |
198 | num = get_line_as_int(inputfilename, "COREBOOT_MAJOR_VERSION", 0); |
199 | if (num < 0) |
200 | goto out; |
201 | |
202 | if (num < 999) { |
203 | char tmp[4]; |
204 | snprintf(tmp, sizeof(tmp), "%03d", num); |
205 | memcpy(&sbu.majorVer, &tmp, sizeof(sbu.majorVer)); |
206 | } else { |
207 | fprintf(stderrstderr, "E: Unsupported coreboot major version\n"); |
208 | goto out; |
209 | } |
210 | |
211 | num = get_line_as_int(inputfilename, "COREBOOT_MINOR_VERSION", 0); |
212 | if (num < 0) |
213 | goto out; |
214 | |
215 | if (num < 99) { |
216 | char tmp[3]; |
217 | snprintf(tmp, sizeof(tmp), "%02d", num); |
218 | memcpy(&sbu.minorVer, &tmp, sizeof(sbu.minorVer)); |
219 | } else { |
220 | fprintf(stderrstderr, "E: Unsupported coreboot minor version\n"); |
221 | goto out; |
222 | } |
223 | |
224 | num = get_line_as_int(inputfilename, "COREBOOT_BUILD_YEAR_BCD", 1); |
225 | if (num < 0) |
226 | goto out; |
227 | sbu.year = 2000 + num; |
228 | |
229 | num = get_line_as_int(inputfilename, "COREBOOT_BUILD_MONTH_BCD", 1); |
230 | if (num < 0) |
231 | goto out; |
232 | sbu.month = num; |
233 | |
234 | num = get_line_as_int(inputfilename, "COREBOOT_BUILD_DAY_BCD", 1); |
235 | if (num < 0) |
236 | goto out; |
237 | sbu.day = num; |
238 | |
239 | memcpy(&sbu.boardid[1], boardid, strlen(boardid)); |
240 | |
241 | // write the table |
242 | FILE *fd = fopen(filename, "wb"); |
243 | if (!fd) { |
244 | fprintf(stderrstderr, "E: %s open failed: %s\n", filename, strerror(errno(*__errno_location ()))); |
245 | goto out; |
246 | } |
247 | |
248 | if (fwrite(&sbu, 1, sizeof(sbu), fd) != sizeof(sbu)) { |
249 | fprintf(stderrstderr, "E: %s write failed: %s\n", filename, strerror(errno(*__errno_location ()))); |
250 | fclose(fd); |
251 | goto out; |
252 | } |
253 | |
254 | if (fclose(fd)) { |
255 | fprintf(stderrstderr, "E: %s close failed: %s\n", filename, strerror(errno(*__errno_location ()))); |
256 | goto out; |
257 | } |
258 | |
259 | ret = 0; |
260 | out: |
261 | if (ret > 0) |
262 | fprintf(stderrstderr, "E: Error creating '%s'\n", filename); |
263 | |
264 | free(filename); |
265 | |
266 | exit(ret); |
267 | |
268 | return 0; |
269 | } |