blob: b8d62a68c15f628c15a6c4767db6319984519240 [file] [log] [blame]
Uwe Hermannba290d12009-06-17 12:07:12 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2009 Carl-Daniel Hailfinger
Stefan Tauner4a038652013-07-17 09:28:00 +00006 * Copyright (C) 2011-2013 Stefan Tauner
Uwe Hermannba290d12009-06-17 12:07:12 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Uwe Hermannba290d12009-06-17 12:07:12 +000017 */
18
Carl-Daniel Hailfinger831e8f42010-05-30 22:24:40 +000019#include <stdio.h>
Uwe Hermannba290d12009-06-17 12:07:12 +000020#include <string.h>
21#include <stdlib.h>
Nico Huber519be662018-12-23 20:03:35 +010022#include <stddef.h>
Edward O'Callaghan3b64d812022-08-12 13:07:51 +100023#if HAVE_UTSNAME == 1
24#include <sys/utsname.h>
25#endif
26#if IS_WINDOWS
27#include <windows.h>
28#undef min
29#undef max
30#endif
31
Uwe Hermannba290d12009-06-17 12:07:12 +000032#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000033#include "programmer.h"
Uwe Hermannba290d12009-06-17 12:07:12 +000034
Edward O'Callaghan3b64d812022-08-12 13:07:51 +100035static void print_sysinfo(void)
36{
37#if IS_WINDOWS
38 SYSTEM_INFO si = { 0 };
39 OSVERSIONINFOEX osvi = { 0 };
40
41 msg_ginfo(" on Windows");
42 /* Tell Windows which version of the structure we want. */
43 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
44 if (GetVersionEx((OSVERSIONINFO*) &osvi))
Thomas Heijligen78ed6682022-08-08 21:55:07 +020045 msg_ginfo(" %lu.%lu", (unsigned long)osvi.dwMajorVersion,
46 (unsigned long)osvi.dwMinorVersion);
Edward O'Callaghan3b64d812022-08-12 13:07:51 +100047 else
48 msg_ginfo(" unknown version");
49 GetSystemInfo(&si);
50 switch (si.wProcessorArchitecture) {
51 case PROCESSOR_ARCHITECTURE_AMD64:
52 msg_ginfo(" (x86_64)");
53 break;
54 case PROCESSOR_ARCHITECTURE_INTEL:
55 msg_ginfo(" (x86)");
56 break;
57 default:
58 msg_ginfo(" (unknown arch)");
59 break;
60 }
61#elif HAVE_UTSNAME == 1
62 struct utsname osinfo;
63
64 uname(&osinfo);
65 msg_ginfo(" on %s %s (%s)", osinfo.sysname, osinfo.release,
66 osinfo.machine);
67#else
68 msg_ginfo(" on unknown machine");
69#endif
70}
71
72void print_buildinfo(void)
73{
74 msg_gdbg("flashrom was built with");
75#ifdef __clang__
76 msg_gdbg(" LLVM Clang");
77#ifdef __clang_version__
78 msg_gdbg(" %s,", __clang_version__);
79#else
80 msg_gdbg(" unknown version (before r102686),");
81#endif
82#elif defined(__GNUC__)
83 msg_gdbg(" GCC");
84#ifdef __VERSION__
85 msg_gdbg(" %s,", __VERSION__);
86#else
87 msg_gdbg(" unknown version,");
88#endif
89#else
90 msg_gdbg(" unknown compiler,");
91#endif
92#if defined (__FLASHROM_LITTLE_ENDIAN__)
93 msg_gdbg(" little endian");
94#elif defined (__FLASHROM_BIG_ENDIAN__)
95 msg_gdbg(" big endian");
96#else
97#error Endianness could not be determined
98#endif
99 msg_gdbg("\n");
100}
101
102void print_version(void)
103{
104 msg_ginfo("flashrom-stable %s", flashrom_version);
105 print_sysinfo();
106 msg_ginfo("\n");
107}
108
109void print_banner(void)
110{
111 msg_ginfo("flashrom is free software, get the source code at "
112 "https://flashrom.org\n");
113 msg_ginfo("\n");
114}
115
Stefan Tauner1181ee22014-06-01 02:13:23 +0000116static const char *test_state_to_text(enum test_state test_state)
117{
118 switch (test_state) {
119 case OK: return "OK";
120 case BAD: return "Not working";
121 case NA: return "N/A";
122 case DEP: return "Config-dependent";
123 case NT:
124 default: return "Untested";
125 }
126}
127
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000128static int print_supported_chips(void)
Uwe Hermannba290d12009-06-17 12:07:12 +0000129{
Stefan Tauner29e5d312011-09-12 22:55:01 +0000130 const char *delim = "/";
131 const int mintoklen = 5;
132 const int border = 2;
133 int i, chipcount = 0;
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000134 int maxvendorlen = strlen("Vendor") + 1;
135 int maxchiplen = strlen("Device") + 1;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000136 int maxtypelen = strlen("Type") + 1;
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000137 const struct flashchip *chip;
Stefan Tauner00155492011-06-26 20:45:35 +0000138 char *s;
Stefan Tauner4a038652013-07-17 09:28:00 +0000139 char *ven, *dev;
140 char *tmpven, *tmpdev, *tmpven_save, *tmpdev_save;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000141 int tmpvenlen, tmpdevlen, curvenlen, curdevlen;
Uwe Hermannba290d12009-06-17 12:07:12 +0000142
Stefan Tauner29e5d312011-09-12 22:55:01 +0000143 /* calculate maximum column widths and by iterating over all chips */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000144 for (chip = flashchips; chip->name != NULL; chip++) {
Stefan Tauner035492a2012-02-03 22:32:09 +0000145 /* Ignore generic entries. */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000146 if (!strncmp(chip->vendor, "Unknown", 7) ||
147 !strncmp(chip->vendor, "Programmer", 10) ||
148 !strncmp(chip->name, "unknown", 7))
Uwe Hermannba290d12009-06-17 12:07:12 +0000149 continue;
Uwe Hermannba290d12009-06-17 12:07:12 +0000150 chipcount++;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000151
152 /* Find maximum vendor length (respecting line splitting). */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000153 tmpven = (char *)chip->vendor;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000154 do {
155 /* and take minimum token lengths into account */
156 tmpvenlen = 0;
157 do {
158 tmpvenlen += strcspn(tmpven, delim);
159 /* skip to the address after the first token */
160 tmpven += tmpvenlen;
161 if (tmpven[0] == '\0')
162 break;
163 tmpven++;
164 } while (tmpvenlen < mintoklen);
165 maxvendorlen = max(maxvendorlen, tmpvenlen);
166 if (tmpven[0] == '\0')
167 break;
168 } while (1);
169
170 /* same for device name */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000171 tmpdev = (char *)chip->name;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000172 do {
173 tmpdevlen = 0;
174 do {
175 tmpdevlen += strcspn(tmpdev, delim);
176 tmpdev += tmpdevlen;
177 if (tmpdev[0] == '\0')
178 break;
179 tmpdev++;
180 } while (tmpdevlen < mintoklen);
181 maxchiplen = max(maxchiplen, tmpdevlen);
182 if (tmpdev[0] == '\0')
183 break;
184 } while (1);
185
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000186 s = flashbuses_to_text(chip->bustype);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000187 maxtypelen = max(maxtypelen, strlen(s));
188 free(s);
Carl-Daniel Hailfingerf7533422010-07-17 23:21:12 +0000189 }
Stefan Tauner29e5d312011-09-12 22:55:01 +0000190 maxvendorlen += border;
191 maxchiplen += border;
192 maxtypelen += border;
Uwe Hermannba290d12009-06-17 12:07:12 +0000193
Stefan Tauner12589362011-06-25 17:36:25 +0000194 msg_ginfo("Supported flash chips (total: %d):\n\n", chipcount);
195 msg_ginfo("Vendor");
Carl-Daniel Hailfingerf7533422010-07-17 23:21:12 +0000196 for (i = strlen("Vendor"); i < maxvendorlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000197 msg_ginfo(" ");
198 msg_ginfo("Device");
Carl-Daniel Hailfingerf7533422010-07-17 23:21:12 +0000199 for (i = strlen("Device"); i < maxchiplen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000200 msg_ginfo(" ");
Uwe Hermannba290d12009-06-17 12:07:12 +0000201
Stefan Tauner29e5d312011-09-12 22:55:01 +0000202 msg_ginfo("Test");
203 for (i = 0; i < border; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000204 msg_ginfo(" ");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000205 msg_ginfo("Known");
206 for (i = 0; i < border; i++)
207 msg_ginfo(" ");
Stefan Tauner0554ca52013-07-25 22:54:25 +0000208 msg_ginfo(" Size ");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000209 for (i = 0; i < border; i++)
210 msg_ginfo(" ");
211
212 msg_ginfo("Type");
213 for (i = strlen("Type"); i < maxtypelen; i++)
214 msg_ginfo(" ");
215 msg_gdbg("Voltage");
216 msg_ginfo("\n");
217
218 for (i = 0; i < maxvendorlen + maxchiplen; i++)
219 msg_ginfo(" ");
220 msg_ginfo("OK ");
221 for (i = 0; i < border; i++)
222 msg_ginfo(" ");
223 msg_ginfo("Broken");
224 for (i = 0; i < border; i++)
225 msg_ginfo(" ");
Stefan Tauner0554ca52013-07-25 22:54:25 +0000226 msg_ginfo("[kB] ");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000227 for (i = 0; i < border + maxtypelen; i++)
228 msg_ginfo(" ");
229 msg_gdbg("range [V]");
230 msg_ginfo("\n\n");
Stefan Tauner5c316f92015-02-08 21:57:52 +0000231 msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE, - = N/A)\n\n");
Uwe Hermannba290d12009-06-17 12:07:12 +0000232
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000233 for (chip = flashchips; chip->name != NULL; chip++) {
Stefan Tauner035492a2012-02-03 22:32:09 +0000234 /* Don't print generic entries. */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000235 if (!strncmp(chip->vendor, "Unknown", 7) ||
236 !strncmp(chip->vendor, "Programmer", 10) ||
237 !strncmp(chip->name, "unknown", 7))
Uwe Hermannba290d12009-06-17 12:07:12 +0000238 continue;
239
Stefan Tauner29e5d312011-09-12 22:55:01 +0000240 /* support for multiline vendor names:
241 * - make a copy of the original vendor name
242 * - use strok to put the first token in tmpven
243 * - keep track of the length of all tokens on the current line
244 * for ' '-padding in curvenlen
245 * - check if additional tokens should be printed on the current
246 * line
247 * - after all other values are printed print the surplus tokens
248 * on fresh lines
249 */
Stefan Tauner4a038652013-07-17 09:28:00 +0000250 ven = malloc(strlen(chip->vendor) + 1);
251 if (ven == NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000252 msg_gerr("Out of memory!\n");
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000253 return 1;
Stefan Tauner29e5d312011-09-12 22:55:01 +0000254 }
Stefan Tauner4a038652013-07-17 09:28:00 +0000255 strcpy(ven, chip->vendor);
Uwe Hermannba290d12009-06-17 12:07:12 +0000256
Stefan Tauner4a038652013-07-17 09:28:00 +0000257 tmpven = strtok_r(ven, delim, &tmpven_save);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000258 msg_ginfo("%s", tmpven);
259 curvenlen = strlen(tmpven);
Stefan Tauner4a038652013-07-17 09:28:00 +0000260 while ((tmpven = strtok_r(NULL, delim, &tmpven_save)) != NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000261 msg_ginfo("%s", delim);
262 curvenlen++;
263 tmpvenlen = strlen(tmpven);
264 if (tmpvenlen >= mintoklen)
265 break; /* big enough to be on its own line */
266 msg_ginfo("%s", tmpven);
267 curvenlen += tmpvenlen;
Uwe Hermannba290d12009-06-17 12:07:12 +0000268 }
269
Stefan Tauner29e5d312011-09-12 22:55:01 +0000270 for (i = curvenlen; i < maxvendorlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000271 msg_ginfo(" ");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000272
273 /* support for multiline device names as above */
Stefan Tauner4a038652013-07-17 09:28:00 +0000274 dev = malloc(strlen(chip->name) + 1);
275 if (dev == NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000276 msg_gerr("Out of memory!\n");
Jacob Garber4a7970b2019-08-12 14:31:46 -0600277 free(ven);
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000278 return 1;
Carl-Daniel Hailfingerf7533422010-07-17 23:21:12 +0000279 }
Stefan Tauner4a038652013-07-17 09:28:00 +0000280 strcpy(dev, chip->name);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000281
Stefan Tauner4a038652013-07-17 09:28:00 +0000282 tmpdev = strtok_r(dev, delim, &tmpdev_save);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000283 msg_ginfo("%s", tmpdev);
284 curdevlen = strlen(tmpdev);
Stefan Tauner4a038652013-07-17 09:28:00 +0000285 while ((tmpdev = strtok_r(NULL, delim, &tmpdev_save)) != NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000286 msg_ginfo("%s", delim);
287 curdevlen++;
288 tmpdevlen = strlen(tmpdev);
289 if (tmpdevlen >= mintoklen)
290 break; /* big enough to be on its own line */
291 msg_ginfo("%s", tmpdev);
292 curdevlen += tmpdevlen;
293 }
294
295 for (i = curdevlen; i < maxchiplen; i++)
296 msg_ginfo(" ");
297
Stefan Tauner6455dff2014-05-26 00:36:24 +0000298 if (chip->tested.probe == OK)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000299 msg_ginfo("P");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000300 else if (chip->tested.probe == NA)
301 msg_ginfo("-");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000302 else
303 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000304 if (chip->tested.read == OK)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000305 msg_ginfo("R");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000306 else if (chip->tested.read == NA)
307 msg_ginfo("-");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000308 else
309 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000310 if (chip->tested.erase == OK)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000311 msg_ginfo("E");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000312 else if (chip->tested.erase == NA)
313 msg_ginfo("-");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000314 else
315 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000316 if (chip->tested.write == OK)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000317 msg_ginfo("W");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000318 else if (chip->tested.write == NA)
319 msg_ginfo("-");
Stefan Tauner29e5d312011-09-12 22:55:01 +0000320 else
321 msg_ginfo(" ");
322 for (i = 0; i < border; i++)
323 msg_ginfo(" ");
324
Stefan Tauner6455dff2014-05-26 00:36:24 +0000325 if (chip->tested.probe == BAD)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000326 msg_ginfo("P");
327 else
328 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000329 if (chip->tested.read == BAD)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000330 msg_ginfo("R");
331 else
332 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000333 if (chip->tested.erase == BAD)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000334 msg_ginfo("E");
335 else
336 msg_ginfo(" ");
Stefan Tauner6455dff2014-05-26 00:36:24 +0000337 if (chip->tested.write == BAD)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000338 msg_ginfo("W");
339 else
340 msg_ginfo(" ");
341 for (i = 0; i < border + 1; i++)
342 msg_ginfo(" ");
343
Stefan Tauner0554ca52013-07-25 22:54:25 +0000344 msg_ginfo("%6d", chip->total_size);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000345 for (i = 0; i < border; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000346 msg_ginfo(" ");
Stefan Tauner00155492011-06-26 20:45:35 +0000347
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000348 s = flashbuses_to_text(chip->bustype);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000349 msg_ginfo("%s", s);
350 for (i = strlen(s); i < maxtypelen; i++)
351 msg_ginfo(" ");
Stefan Tauner00155492011-06-26 20:45:35 +0000352 free(s);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000353
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000354 if (chip->voltage.min == 0 && chip->voltage.max == 0)
Stefan Tauner29e5d312011-09-12 22:55:01 +0000355 msg_gdbg("no info");
356 else
357 msg_gdbg("%0.02f;%0.02f",
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000358 chip->voltage.min/(double)1000,
359 chip->voltage.max/(double)1000);
Stefan Tauner29e5d312011-09-12 22:55:01 +0000360
361 /* print surplus vendor and device name tokens */
362 while (tmpven != NULL || tmpdev != NULL) {
363 msg_ginfo("\n");
364 if (tmpven != NULL){
365 msg_ginfo("%s", tmpven);
366 curvenlen = strlen(tmpven);
Stefan Tauner4a038652013-07-17 09:28:00 +0000367 while ((tmpven = strtok_r(NULL, delim, &tmpven_save)) != NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000368 msg_ginfo("%s", delim);
369 curvenlen++;
370 tmpvenlen = strlen(tmpven);
371 /* big enough to be on its own line */
372 if (tmpvenlen >= mintoklen)
373 break;
374 msg_ginfo("%s", tmpven);
375 curvenlen += tmpvenlen;
376 }
377 } else
378 curvenlen = 0;
379
380 for (i = curvenlen; i < maxvendorlen; i++)
381 msg_ginfo(" ");
382
383 if (tmpdev != NULL){
384 msg_ginfo("%s", tmpdev);
385 curdevlen = strlen(tmpdev);
Stefan Tauner4a038652013-07-17 09:28:00 +0000386 while ((tmpdev = strtok_r(NULL, delim, &tmpdev_save)) != NULL) {
Stefan Tauner29e5d312011-09-12 22:55:01 +0000387 msg_ginfo("%s", delim);
388 curdevlen++;
389 tmpdevlen = strlen(tmpdev);
390 /* big enough to be on its own line */
391 if (tmpdevlen >= mintoklen)
392 break;
393 msg_ginfo("%s", tmpdev);
394 curdevlen += tmpdevlen;
395 }
396 }
397 }
398 msg_ginfo("\n");
Stefan Tauner4a038652013-07-17 09:28:00 +0000399 free(ven);
400 free(dev);
Uwe Hermannba290d12009-06-17 12:07:12 +0000401 }
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000402
403 return 0;
Uwe Hermannba290d12009-06-17 12:07:12 +0000404}
405
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +0000406#if CONFIG_INTERNAL == 1
Carl-Daniel Hailfingerad3cc552010-07-03 11:02:10 +0000407static void print_supported_chipsets(void)
Uwe Hermannba290d12009-06-17 12:07:12 +0000408{
Nico Huber519be662018-12-23 20:03:35 +0100409 unsigned int i, chipsetcount = 0;
Uwe Hermannba290d12009-06-17 12:07:12 +0000410 const struct penable *c = chipset_enables;
Nico Huber519be662018-12-23 20:03:35 +0100411 size_t maxvendorlen = strlen("Vendor") + 1;
412 size_t maxchipsetlen = strlen("Chipset") + 1;
Uwe Hermannba290d12009-06-17 12:07:12 +0000413
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000414 for (c = chipset_enables; c->vendor_name != NULL; c++) {
Uwe Hermannba290d12009-06-17 12:07:12 +0000415 chipsetcount++;
Nico Huber519be662018-12-23 20:03:35 +0100416 maxvendorlen = MAX(maxvendorlen, strlen(c->vendor_name));
417 maxchipsetlen = MAX(maxchipsetlen, strlen(c->device_name));
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000418 }
419 maxvendorlen++;
420 maxchipsetlen++;
Uwe Hermannba290d12009-06-17 12:07:12 +0000421
Nico Huber519be662018-12-23 20:03:35 +0100422 msg_ginfo("Supported chipsets (total: %u):\n\n", chipsetcount);
Uwe Hermannba290d12009-06-17 12:07:12 +0000423
Stefan Tauner12589362011-06-25 17:36:25 +0000424 msg_ginfo("Vendor");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000425 for (i = strlen("Vendor"); i < maxvendorlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000426 msg_ginfo(" ");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000427
Stefan Tauner12589362011-06-25 17:36:25 +0000428 msg_ginfo("Chipset");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000429 for (i = strlen("Chipset"); i < maxchipsetlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000430 msg_ginfo(" ");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000431
Stefan Tauner428ba2b2014-06-02 00:34:58 +0000432 msg_ginfo("PCI IDs Status\n\n");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000433
434 for (c = chipset_enables; c->vendor_name != NULL; c++) {
Stefan Tauner12589362011-06-25 17:36:25 +0000435 msg_ginfo("%s", c->vendor_name);
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000436 for (i = 0; i < maxvendorlen - strlen(c->vendor_name); i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000437 msg_ginfo(" ");
438 msg_ginfo("%s", c->device_name);
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000439 for (i = 0; i < maxchipsetlen - strlen(c->device_name); i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000440 msg_ginfo(" ");
Stefan Tauner428ba2b2014-06-02 00:34:58 +0000441 msg_ginfo("%04x:%04x %s\n", c->vendor_id, c->device_id,
442 test_state_to_text(c->status));
Uwe Hermannba290d12009-06-17 12:07:12 +0000443 }
444}
445
Carl-Daniel Hailfingerad3cc552010-07-03 11:02:10 +0000446static void print_supported_boards_helper(const struct board_info *boards,
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000447 const char *devicetype)
Uwe Hermannba290d12009-06-17 12:07:12 +0000448{
Nico Huber519be662018-12-23 20:03:35 +0100449 unsigned int i;
Stefan Tauner2c20b282012-07-28 19:35:26 +0000450 unsigned int boardcount_good = 0, boardcount_bad = 0, boardcount_nt = 0;
Carl-Daniel Hailfinger97d5b122011-08-31 16:19:50 +0000451 const struct board_match *e = board_matches;
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000452 const struct board_info *b = boards;
Nico Huber519be662018-12-23 20:03:35 +0100453 size_t maxvendorlen = strlen("Vendor") + 1;
454 size_t maxboardlen = strlen("Board") + 1;
Uwe Hermannba290d12009-06-17 12:07:12 +0000455
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000456 for (b = boards; b->vendor != NULL; b++) {
457 maxvendorlen = max(maxvendorlen, strlen(b->vendor));
458 maxboardlen = max(maxboardlen, strlen(b->name));
Stefan Tauner2c20b282012-07-28 19:35:26 +0000459 if (b->working == OK)
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000460 boardcount_good++;
Stefan Tauner2c20b282012-07-28 19:35:26 +0000461 else if (b->working == NT)
462 boardcount_nt++;
Uwe Hermannba290d12009-06-17 12:07:12 +0000463 else
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000464 boardcount_bad++;
Uwe Hermannba290d12009-06-17 12:07:12 +0000465 }
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000466 maxvendorlen++;
467 maxboardlen++;
Uwe Hermannba290d12009-06-17 12:07:12 +0000468
Stefan Tauner2c20b282012-07-28 19:35:26 +0000469 msg_ginfo("%d known %s (good: %d, untested: %d, bad: %d):\n\n",
470 boardcount_good + boardcount_nt + boardcount_bad,
471 devicetype, boardcount_good, boardcount_nt, boardcount_bad);
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000472
Stefan Tauner12589362011-06-25 17:36:25 +0000473 msg_ginfo("Vendor");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000474 for (i = strlen("Vendor"); i < maxvendorlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000475 msg_ginfo(" ");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000476
Stefan Tauner12589362011-06-25 17:36:25 +0000477 msg_ginfo("Board");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000478 for (i = strlen("Board"); i < maxboardlen; i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000479 msg_ginfo(" ");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000480
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000481 msg_ginfo("Status Required value for\n");
482 for (i = 0; i < maxvendorlen + maxboardlen + strlen("Status "); i++)
483 msg_ginfo(" ");
484 msg_ginfo("-p internal:mainboard=\n");
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000485
486 for (b = boards; b->vendor != NULL; b++) {
Stefan Tauner12589362011-06-25 17:36:25 +0000487 msg_ginfo("%s", b->vendor);
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000488 for (i = 0; i < maxvendorlen - strlen(b->vendor); i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000489 msg_ginfo(" ");
490 msg_ginfo("%s", b->name);
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000491 for (i = 0; i < maxboardlen - strlen(b->name); i++)
Stefan Tauner12589362011-06-25 17:36:25 +0000492 msg_ginfo(" ");
Stefan Reinauerf94d9ce2014-04-26 16:11:07 +0000493
Nico Huber5d068dd2019-11-17 13:39:46 +0100494 switch (b->working) {
495 case OK: msg_ginfo("OK "); break;
496 case NT: msg_ginfo("NT "); break;
497 case DEP: msg_ginfo("DEP "); break;
498 case NA: msg_ginfo("N/A "); break;
499 case BAD:
500 default: msg_ginfo("BAD "); break;
501 }
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000502
Carl-Daniel Hailfinger97d5b122011-08-31 16:19:50 +0000503 for (e = board_matches; e->vendor_name != NULL; e++) {
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000504 if (strcmp(e->vendor_name, b->vendor)
505 || strcmp(e->board_name, b->name))
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000506 continue;
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000507 if (e->lb_vendor == NULL)
Stefan Tauner12589362011-06-25 17:36:25 +0000508 msg_ginfo("(autodetected)");
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000509 else
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000510 msg_ginfo("%s:%s", e->lb_vendor,
Stefan Tauner7bcacb12011-05-26 01:35:19 +0000511 e->lb_part);
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000512 }
Stefan Tauner12589362011-06-25 17:36:25 +0000513 msg_ginfo("\n");
Peter Lemenkov4adf8a62010-06-01 10:13:17 +0000514 }
Uwe Hermannba290d12009-06-17 12:07:12 +0000515}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000516#endif
Uwe Hermannd0e347d2009-10-06 13:00:00 +0000517
Thomas Heijligen633d6db2021-03-31 19:09:44 +0200518static void print_supported_devs(const struct programmer_entry *const prog, const char *const type)
Stefan Tauneraf358d62012-12-27 18:40:26 +0000519{
Thomas Heijligen633d6db2021-03-31 19:09:44 +0200520 const struct dev_entry *const devs = prog->devs.dev;
521 msg_ginfo("\nSupported %s devices for the %s programmer:\n", type, prog->name);
Stefan Tauner1181ee22014-06-01 02:13:23 +0000522 unsigned int maxvendorlen = strlen("Vendor") + 1;
523 unsigned int maxdevlen = strlen("Device") + 1;
524
525 unsigned int i;
Stefan Tauneraf358d62012-12-27 18:40:26 +0000526 for (i = 0; devs[i].vendor_name != NULL; i++) {
Stefan Tauner1181ee22014-06-01 02:13:23 +0000527 maxvendorlen = max(maxvendorlen, strlen(devs[i].vendor_name));
528 maxdevlen = max(maxdevlen, strlen(devs[i].device_name));
529 }
530 maxvendorlen++;
531 maxdevlen++;
532
533 msg_ginfo("Vendor");
534 for (i = strlen("Vendor"); i < maxvendorlen; i++)
535 msg_ginfo(" ");
536
537 msg_ginfo("Device");
538 for (i = strlen("Device"); i < maxdevlen; i++)
539 msg_ginfo(" ");
540
541 msg_ginfo(" %s IDs Status\n", type);
542
543 for (i = 0; devs[i].vendor_name != NULL; i++) {
544 msg_ginfo("%s", devs[i].vendor_name);
545 unsigned int j;
546 for (j = strlen(devs[i].vendor_name); j < maxvendorlen; j++)
547 msg_ginfo(" ");
548 msg_ginfo("%s", devs[i].device_name);
549 for (j = strlen(devs[i].device_name); j < maxdevlen; j++)
550 msg_ginfo(" ");
551
552 msg_pinfo(" %04x:%04x %s\n", devs[i].vendor_id, devs[i].device_id,
553 test_state_to_text(devs[i].status));
Stefan Tauneraf358d62012-12-27 18:40:26 +0000554 }
555}
556
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000557int print_supported(void)
Carl-Daniel Hailfingerf5292052009-11-17 09:57:34 +0000558{
Stefan Tauneraf358d62012-12-27 18:40:26 +0000559 unsigned int i;
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000560 if (print_supported_chips())
561 return 1;
Carl-Daniel Hailfingera73fb492010-10-06 23:48:34 +0000562
Stefan Tauner12589362011-06-25 17:36:25 +0000563 msg_ginfo("\nSupported programmers:\n");
Carl-Daniel Hailfingera73fb492010-10-06 23:48:34 +0000564 list_programmers_linebreak(0, 80, 0);
Stefan Taunerb226cb12012-11-24 18:59:39 +0000565 msg_ginfo("\n");
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +0000566#if CONFIG_INTERNAL == 1
Thomas Heijligen79088ab2021-06-01 13:57:42 +0200567 msg_ginfo("\nSupported devices for the internal programmer:\n\n");
Carl-Daniel Hailfingera73fb492010-10-06 23:48:34 +0000568 print_supported_chipsets();
Stefan Tauner12589362011-06-25 17:36:25 +0000569 msg_ginfo("\n");
Stefan Tauner74dc73f2015-03-01 22:04:38 +0000570 print_supported_boards_helper(boards_known, "mainboards");
Stefan Tauner12589362011-06-25 17:36:25 +0000571 msg_ginfo("\n");
Stefan Tauner74dc73f2015-03-01 22:04:38 +0000572 print_supported_boards_helper(laptops_known, "mobile devices");
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000573#endif
Thomas Heijligend45cb592021-05-19 14:12:18 +0200574 for (i = 0; i < programmer_table_size; i++) {
Thomas Heijligen633d6db2021-03-31 19:09:44 +0200575 const struct programmer_entry *const prog = programmer_table[i];
576 switch (prog->type) {
Stefan Tauneraf358d62012-12-27 18:40:26 +0000577 case USB:
Stefan Tauner4b24a2d2012-12-27 18:40:36 +0000578 print_supported_devs(prog, "USB");
Stefan Tauneraf358d62012-12-27 18:40:26 +0000579 break;
Stefan Tauneraf358d62012-12-27 18:40:26 +0000580 case PCI:
Stefan Tauner4b24a2d2012-12-27 18:40:36 +0000581 print_supported_devs(prog, "PCI");
Stefan Tauneraf358d62012-12-27 18:40:26 +0000582 break;
Stefan Tauneraf358d62012-12-27 18:40:26 +0000583 case OTHER:
Thomas Heijligen633d6db2021-03-31 19:09:44 +0200584 if (prog->devs.note != NULL) {
585 msg_ginfo("\nSupported devices for the %s programmer:\n", prog->name);
586 msg_ginfo("%s", prog->devs.note);
Stefan Tauner4b24a2d2012-12-27 18:40:36 +0000587 }
Stefan Tauneraf358d62012-12-27 18:40:26 +0000588 break;
589 default:
Nico Huberac90af62022-12-18 00:22:47 +0000590 msg_gerr("\n%s: %s: Uninitialized programmer type!\n"
591 "Please report a bug at flashrom-stable@flashrom.org\n",
592 __func__, prog->name);
Stefan Tauneraf358d62012-12-27 18:40:26 +0000593 break;
594 }
595 }
Niklas Söderlundede2fa42012-10-23 13:06:46 +0000596 return 0;
Carl-Daniel Hailfingerf5292052009-11-17 09:57:34 +0000597}