Bug Summary

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'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name smcbiosinfo.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -resource-dir /opt/xgcc/lib/clang/17 -include /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include/commonlib/bsd/compiler.h -include /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include/commonlib/bsd/compiler.h -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _SVID_SOURCE -D _GNU_SOURCE -I /home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool/flashmap -I /home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool -I /cb-build/coreboot_scanbuild.0/sharedutils/cbfstool -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include -I 3rdparty/vboot/firmware/include -I 3rdparty/vboot/firmware/2lib/include -I 3rdparty/vboot/host/include -I 3rdparty/vboot/host/lib/include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1714465709 -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-02-073004-2299942-1 -x c util/supermicro/smcbiosinfo/smcbiosinfo.c
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: */
15struct 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
42static const char *optstring = "b:i:o:h";
43
44static 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
51static 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
61static int bcd2int(int hex)
62{
63 if (hex > 0xff)
64 return -1;
65 return ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
66}
67
68static 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
95static 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
116int 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;
260out:
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}