mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00

This also expands the column for test status by 1 more char, since now maximum status is longer, PREWB vs PREW. print.c runs when command line option `flashrom -L` is invoked. Change-Id: If697fe3ba93dbe34bb8f7a9a4b1686fdb8b3ee58 Signed-off-by: Anastasia Klimchuk <aklm@flashrom.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/83131 Reviewed-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
627 lines
16 KiB
C
627 lines
16 KiB
C
/*
|
|
* This file is part of the flashrom project.
|
|
*
|
|
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
|
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
|
* Copyright (C) 2011-2013 Stefan Tauner
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#if HAVE_UTSNAME == 1
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
#if IS_WINDOWS
|
|
#include <windows.h>
|
|
#undef min
|
|
#undef max
|
|
#endif
|
|
|
|
#include "flash.h"
|
|
#include "programmer.h"
|
|
|
|
static const char *test_state_to_text(enum test_state test_state)
|
|
{
|
|
switch (test_state) {
|
|
case OK: return "OK";
|
|
case BAD: return "Not working";
|
|
case NA: return "N/A";
|
|
case DEP: return "Config-dependent";
|
|
case NT:
|
|
default: return "Untested";
|
|
}
|
|
}
|
|
|
|
static int print_supported_chips(void)
|
|
{
|
|
const char *delim = "/";
|
|
const int mintoklen = 5;
|
|
const int border = 2;
|
|
int i, chipcount = 0;
|
|
int maxvendorlen = strlen("Vendor") + 1;
|
|
int maxchiplen = strlen("Device") + 1;
|
|
int maxtypelen = strlen("Type") + 1;
|
|
const struct flashchip *chip;
|
|
char *s;
|
|
char *ven, *dev;
|
|
char *tmpven, *tmpdev, *tmpven_save, *tmpdev_save;
|
|
int tmpvenlen, tmpdevlen, curvenlen, curdevlen;
|
|
|
|
/* calculate maximum column widths and by iterating over all chips */
|
|
for (chip = flashchips; chip->name != NULL; chip++) {
|
|
/* Ignore generic entries. */
|
|
if (!strncmp(chip->vendor, "Unknown", 7) ||
|
|
!strncmp(chip->vendor, "Programmer", 10) ||
|
|
!strncmp(chip->name, "unknown", 7))
|
|
continue;
|
|
chipcount++;
|
|
|
|
/* Find maximum vendor length (respecting line splitting). */
|
|
tmpven = (char *)chip->vendor;
|
|
do {
|
|
/* and take minimum token lengths into account */
|
|
tmpvenlen = 0;
|
|
do {
|
|
tmpvenlen += strcspn(tmpven, delim);
|
|
/* skip to the address after the first token */
|
|
tmpven += tmpvenlen;
|
|
if (tmpven[0] == '\0')
|
|
break;
|
|
tmpven++;
|
|
} while (tmpvenlen < mintoklen);
|
|
maxvendorlen = max(maxvendorlen, tmpvenlen);
|
|
if (tmpven[0] == '\0')
|
|
break;
|
|
} while (1);
|
|
|
|
/* same for device name */
|
|
tmpdev = (char *)chip->name;
|
|
do {
|
|
tmpdevlen = 0;
|
|
do {
|
|
tmpdevlen += strcspn(tmpdev, delim);
|
|
tmpdev += tmpdevlen;
|
|
if (tmpdev[0] == '\0')
|
|
break;
|
|
tmpdev++;
|
|
} while (tmpdevlen < mintoklen);
|
|
maxchiplen = max(maxchiplen, tmpdevlen);
|
|
if (tmpdev[0] == '\0')
|
|
break;
|
|
} while (1);
|
|
|
|
s = flashbuses_to_text(chip->bustype);
|
|
if (s == NULL) {
|
|
msg_gerr("Out of memory!\n");
|
|
return 1;
|
|
}
|
|
maxtypelen = max(maxtypelen, strlen(s));
|
|
free(s);
|
|
}
|
|
maxvendorlen += border;
|
|
maxchiplen += border;
|
|
maxtypelen += border;
|
|
|
|
msg_ginfo("Supported flash chips (total: %d):\n\n", chipcount);
|
|
msg_ginfo("Vendor");
|
|
for (i = strlen("Vendor"); i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("Device");
|
|
for (i = strlen("Device"); i < maxchiplen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Test ");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("Known");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo(" Size ");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Type");
|
|
for (i = strlen("Type"); i < maxtypelen; i++)
|
|
msg_ginfo(" ");
|
|
msg_gdbg("Voltage");
|
|
msg_ginfo("\n");
|
|
|
|
for (i = 0; i < maxvendorlen + maxchiplen; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("OK ");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("Broken");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("[kB] ");
|
|
for (i = 0; i < border + maxtypelen; i++)
|
|
msg_ginfo(" ");
|
|
msg_gdbg("range [V]");
|
|
msg_ginfo("\n\n");
|
|
msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE, B = block-protect, - = N/A)\n\n");
|
|
|
|
for (chip = flashchips; chip->name != NULL; chip++) {
|
|
/* Don't print generic entries. */
|
|
if (!strncmp(chip->vendor, "Unknown", 7) ||
|
|
!strncmp(chip->vendor, "Programmer", 10) ||
|
|
!strncmp(chip->name, "unknown", 7))
|
|
continue;
|
|
|
|
/* support for multiline vendor names:
|
|
* - make a copy of the original vendor name
|
|
* - use strok to put the first token in tmpven
|
|
* - keep track of the length of all tokens on the current line
|
|
* for ' '-padding in curvenlen
|
|
* - check if additional tokens should be printed on the current
|
|
* line
|
|
* - after all other values are printed print the surplus tokens
|
|
* on fresh lines
|
|
*/
|
|
ven = malloc(strlen(chip->vendor) + 1);
|
|
if (ven == NULL) {
|
|
msg_gerr("Out of memory!\n");
|
|
return 1;
|
|
}
|
|
strcpy(ven, chip->vendor);
|
|
|
|
tmpven = strtok_r(ven, delim, &tmpven_save);
|
|
msg_ginfo("%s", tmpven);
|
|
curvenlen = strlen(tmpven);
|
|
while ((tmpven = strtok_r(NULL, delim, &tmpven_save)) != NULL) {
|
|
msg_ginfo("%s", delim);
|
|
curvenlen++;
|
|
tmpvenlen = strlen(tmpven);
|
|
if (tmpvenlen >= mintoklen)
|
|
break; /* big enough to be on its own line */
|
|
msg_ginfo("%s", tmpven);
|
|
curvenlen += tmpvenlen;
|
|
}
|
|
|
|
for (i = curvenlen; i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
/* support for multiline device names as above */
|
|
dev = malloc(strlen(chip->name) + 1);
|
|
if (dev == NULL) {
|
|
msg_gerr("Out of memory!\n");
|
|
free(ven);
|
|
return 1;
|
|
}
|
|
strcpy(dev, chip->name);
|
|
|
|
tmpdev = strtok_r(dev, delim, &tmpdev_save);
|
|
msg_ginfo("%s", tmpdev);
|
|
curdevlen = strlen(tmpdev);
|
|
while ((tmpdev = strtok_r(NULL, delim, &tmpdev_save)) != NULL) {
|
|
msg_ginfo("%s", delim);
|
|
curdevlen++;
|
|
tmpdevlen = strlen(tmpdev);
|
|
if (tmpdevlen >= mintoklen)
|
|
break; /* big enough to be on its own line */
|
|
msg_ginfo("%s", tmpdev);
|
|
curdevlen += tmpdevlen;
|
|
}
|
|
|
|
for (i = curdevlen; i < maxchiplen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
if (chip->tested.probe == OK)
|
|
msg_ginfo("P");
|
|
else if (chip->tested.probe == NA)
|
|
msg_ginfo("-");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.read == OK)
|
|
msg_ginfo("R");
|
|
else if (chip->tested.read == NA)
|
|
msg_ginfo("-");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.erase == OK)
|
|
msg_ginfo("E");
|
|
else if (chip->tested.erase == NA)
|
|
msg_ginfo("-");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.write == OK)
|
|
msg_ginfo("W");
|
|
else if (chip->tested.write == NA)
|
|
msg_ginfo("-");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.wp == OK)
|
|
msg_ginfo("B");
|
|
else if (chip->tested.wp == NA)
|
|
msg_ginfo("-");
|
|
else
|
|
msg_ginfo(" ");
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
|
|
if (chip->tested.probe == BAD)
|
|
msg_ginfo("P");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.read == BAD)
|
|
msg_ginfo("R");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.erase == BAD)
|
|
msg_ginfo("E");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.write == BAD)
|
|
msg_ginfo("W");
|
|
else
|
|
msg_ginfo(" ");
|
|
if (chip->tested.wp == BAD)
|
|
msg_ginfo("B");
|
|
else
|
|
msg_ginfo(" ");
|
|
for (i = 0; i < border + 1; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("%6d", chip->total_size);
|
|
for (i = 0; i < border; i++)
|
|
msg_ginfo(" ");
|
|
|
|
s = flashbuses_to_text(chip->bustype);
|
|
if (s == NULL) {
|
|
msg_gerr("Out of memory!\n");
|
|
free(ven);
|
|
free(dev);
|
|
return 1;
|
|
}
|
|
msg_ginfo("%s", s);
|
|
for (i = strlen(s); i < maxtypelen; i++)
|
|
msg_ginfo(" ");
|
|
free(s);
|
|
|
|
if (chip->voltage.min == 0 && chip->voltage.max == 0)
|
|
msg_gdbg("no info");
|
|
else
|
|
msg_gdbg("%0.02f;%0.02f",
|
|
chip->voltage.min/(double)1000,
|
|
chip->voltage.max/(double)1000);
|
|
|
|
/* print surplus vendor and device name tokens */
|
|
while (tmpven != NULL || tmpdev != NULL) {
|
|
msg_ginfo("\n");
|
|
if (tmpven != NULL){
|
|
msg_ginfo("%s", tmpven);
|
|
curvenlen = strlen(tmpven);
|
|
while ((tmpven = strtok_r(NULL, delim, &tmpven_save)) != NULL) {
|
|
msg_ginfo("%s", delim);
|
|
curvenlen++;
|
|
tmpvenlen = strlen(tmpven);
|
|
/* big enough to be on its own line */
|
|
if (tmpvenlen >= mintoklen)
|
|
break;
|
|
msg_ginfo("%s", tmpven);
|
|
curvenlen += tmpvenlen;
|
|
}
|
|
} else
|
|
curvenlen = 0;
|
|
|
|
for (i = curvenlen; i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
if (tmpdev != NULL){
|
|
msg_ginfo("%s", tmpdev);
|
|
curdevlen = strlen(tmpdev);
|
|
while ((tmpdev = strtok_r(NULL, delim, &tmpdev_save)) != NULL) {
|
|
msg_ginfo("%s", delim);
|
|
curdevlen++;
|
|
tmpdevlen = strlen(tmpdev);
|
|
/* big enough to be on its own line */
|
|
if (tmpdevlen >= mintoklen)
|
|
break;
|
|
msg_ginfo("%s", tmpdev);
|
|
curdevlen += tmpdevlen;
|
|
}
|
|
}
|
|
}
|
|
msg_ginfo("\n");
|
|
free(ven);
|
|
free(dev);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if CONFIG_INTERNAL == 1
|
|
static void print_supported_chipsets(void)
|
|
{
|
|
unsigned int i, chipsetcount = 0;
|
|
const struct penable *c = chipset_enables;
|
|
size_t maxvendorlen = strlen("Vendor") + 1;
|
|
size_t maxchipsetlen = strlen("Chipset") + 1;
|
|
|
|
for (c = chipset_enables; c->vendor_name != NULL; c++) {
|
|
chipsetcount++;
|
|
maxvendorlen = MAX(maxvendorlen, strlen(c->vendor_name));
|
|
maxchipsetlen = MAX(maxchipsetlen, strlen(c->device_name));
|
|
}
|
|
maxvendorlen++;
|
|
maxchipsetlen++;
|
|
|
|
msg_ginfo("Supported chipsets (total: %u):\n\n", chipsetcount);
|
|
|
|
msg_ginfo("Vendor");
|
|
for (i = strlen("Vendor"); i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Chipset");
|
|
for (i = strlen("Chipset"); i < maxchipsetlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("PCI IDs Status\n\n");
|
|
|
|
for (c = chipset_enables; c->vendor_name != NULL; c++) {
|
|
msg_ginfo("%s", c->vendor_name);
|
|
for (i = 0; i < maxvendorlen - strlen(c->vendor_name); i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("%s", c->device_name);
|
|
for (i = 0; i < maxchipsetlen - strlen(c->device_name); i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("%04x:%04x %s\n", c->vendor_id, c->device_id,
|
|
test_state_to_text(c->status));
|
|
}
|
|
}
|
|
|
|
static void print_supported_boards_helper(const struct board_info *boards,
|
|
const char *devicetype)
|
|
{
|
|
unsigned int i;
|
|
unsigned int boardcount_good = 0, boardcount_bad = 0, boardcount_nt = 0;
|
|
const struct board_match *e = board_matches;
|
|
const struct board_info *b = boards;
|
|
size_t maxvendorlen = strlen("Vendor") + 1;
|
|
size_t maxboardlen = strlen("Board") + 1;
|
|
|
|
for (b = boards; b->vendor != NULL; b++) {
|
|
maxvendorlen = max(maxvendorlen, strlen(b->vendor));
|
|
maxboardlen = max(maxboardlen, strlen(b->name));
|
|
if (b->working == OK)
|
|
boardcount_good++;
|
|
else if (b->working == NT)
|
|
boardcount_nt++;
|
|
else
|
|
boardcount_bad++;
|
|
}
|
|
maxvendorlen++;
|
|
maxboardlen++;
|
|
|
|
msg_ginfo("%d known %s (good: %d, untested: %d, bad: %d):\n\n",
|
|
boardcount_good + boardcount_nt + boardcount_bad,
|
|
devicetype, boardcount_good, boardcount_nt, boardcount_bad);
|
|
|
|
msg_ginfo("Vendor");
|
|
for (i = strlen("Vendor"); i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Board");
|
|
for (i = strlen("Board"); i < maxboardlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Status Required value for\n");
|
|
for (i = 0; i < maxvendorlen + maxboardlen + strlen("Status "); i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("-p internal:mainboard=\n");
|
|
|
|
for (b = boards; b->vendor != NULL; b++) {
|
|
msg_ginfo("%s", b->vendor);
|
|
for (i = 0; i < maxvendorlen - strlen(b->vendor); i++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("%s", b->name);
|
|
for (i = 0; i < maxboardlen - strlen(b->name); i++)
|
|
msg_ginfo(" ");
|
|
|
|
switch (b->working) {
|
|
case OK: msg_ginfo("OK "); break;
|
|
case NT: msg_ginfo("NT "); break;
|
|
case DEP: msg_ginfo("DEP "); break;
|
|
case NA: msg_ginfo("N/A "); break;
|
|
case BAD:
|
|
default: msg_ginfo("BAD "); break;
|
|
}
|
|
|
|
for (e = board_matches; e->vendor_name != NULL; e++) {
|
|
if (strcmp(e->vendor_name, b->vendor)
|
|
|| strcmp(e->board_name, b->name))
|
|
continue;
|
|
if (e->lb_vendor == NULL)
|
|
msg_ginfo("(autodetected)");
|
|
else
|
|
msg_ginfo("%s:%s", e->lb_vendor,
|
|
e->lb_part);
|
|
}
|
|
msg_ginfo("\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void print_supported_devs(const struct programmer_entry *const prog, const char *const type,
|
|
int* num_devs)
|
|
{
|
|
const struct dev_entry *const devs = prog->devs.dev;
|
|
msg_ginfo("\nSupported %s devices for the %s programmer:\n", type, prog->name);
|
|
unsigned int maxvendorlen = strlen("Vendor") + 1;
|
|
unsigned int maxdevlen = strlen("Device") + 1;
|
|
|
|
unsigned int i;
|
|
for (i = 0; devs[i].vendor_name != NULL; i++) {
|
|
maxvendorlen = max(maxvendorlen, strlen(devs[i].vendor_name));
|
|
maxdevlen = max(maxdevlen, strlen(devs[i].device_name));
|
|
}
|
|
maxvendorlen++;
|
|
maxdevlen++;
|
|
|
|
msg_ginfo("Vendor");
|
|
for (i = strlen("Vendor"); i < maxvendorlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo("Device");
|
|
for (i = strlen("Device"); i < maxdevlen; i++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_ginfo(" %s IDs Status\n", type);
|
|
|
|
for (i = 0; devs[i].vendor_name != NULL; i++) {
|
|
msg_ginfo("%s", devs[i].vendor_name);
|
|
unsigned int j;
|
|
for (j = strlen(devs[i].vendor_name); j < maxvendorlen; j++)
|
|
msg_ginfo(" ");
|
|
msg_ginfo("%s", devs[i].device_name);
|
|
for (j = strlen(devs[i].device_name); j < maxdevlen; j++)
|
|
msg_ginfo(" ");
|
|
|
|
msg_pinfo(" %04x:%04x %s\n", devs[i].vendor_id, devs[i].device_id,
|
|
test_state_to_text(devs[i].status));
|
|
if (devs[i].status == OK || devs[i].status == NT || devs[i].status == DEP)
|
|
*num_devs += 1;
|
|
}
|
|
}
|
|
|
|
int print_supported(void)
|
|
{
|
|
unsigned int i;
|
|
int num_pci_devs = 0;
|
|
int num_usb_devs = 0;
|
|
|
|
if (print_supported_chips())
|
|
return 1;
|
|
|
|
msg_ginfo("\nSupported programmers:\n");
|
|
list_programmers_linebreak(0, 80, 0);
|
|
msg_ginfo("\n");
|
|
#if CONFIG_INTERNAL == 1
|
|
msg_ginfo("\nSupported devices for the internal programmer:\n\n");
|
|
print_supported_chipsets();
|
|
msg_ginfo("\n");
|
|
print_supported_boards_helper(boards_known, "mainboards");
|
|
msg_ginfo("\n");
|
|
print_supported_boards_helper(laptops_known, "mobile devices");
|
|
#endif
|
|
for (i = 0; i < programmer_table_size; i++) {
|
|
const struct programmer_entry *const prog = programmer_table[i];
|
|
switch (prog->type) {
|
|
case USB:
|
|
print_supported_devs(prog, "USB", &num_usb_devs);
|
|
break;
|
|
case PCI:
|
|
print_supported_devs(prog, "PCI", &num_pci_devs);
|
|
break;
|
|
case OTHER:
|
|
if (prog->devs.note != NULL) {
|
|
msg_ginfo("\nSupported devices for the %s programmer:\n", prog->name);
|
|
msg_ginfo("%s", prog->devs.note);
|
|
}
|
|
break;
|
|
default:
|
|
msg_gerr("\n%s: %s: Uninitialized programmer type! Please report a bug at "
|
|
"flashrom@flashrom.org\n", __func__, prog->name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
msg_ginfo("\nSupported USB devices, total %d\nSupported PCI devices, total %d\n",
|
|
num_usb_devs, num_pci_devs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void print_sysinfo(void)
|
|
{
|
|
#if IS_WINDOWS
|
|
SYSTEM_INFO si = { 0 };
|
|
OSVERSIONINFOEX osvi = { 0 };
|
|
|
|
msg_ginfo(" on Windows");
|
|
/* Tell Windows which version of the structure we want. */
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
if (GetVersionEx((OSVERSIONINFO*) &osvi))
|
|
msg_ginfo(" %lu.%lu", (unsigned long)osvi.dwMajorVersion,
|
|
(unsigned long)osvi.dwMinorVersion);
|
|
else
|
|
msg_ginfo(" unknown version");
|
|
GetSystemInfo(&si);
|
|
switch (si.wProcessorArchitecture) {
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|
msg_ginfo(" (x86_64)");
|
|
break;
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
|
msg_ginfo(" (x86)");
|
|
break;
|
|
default:
|
|
msg_ginfo(" (unknown arch)");
|
|
break;
|
|
}
|
|
#elif HAVE_UTSNAME == 1
|
|
struct utsname osinfo;
|
|
|
|
uname(&osinfo);
|
|
msg_ginfo(" on %s %s (%s)", osinfo.sysname, osinfo.release,
|
|
osinfo.machine);
|
|
#else
|
|
msg_ginfo(" on unknown machine");
|
|
#endif
|
|
}
|
|
|
|
void print_buildinfo(void)
|
|
{
|
|
msg_gdbg("flashrom was built with");
|
|
#ifdef __clang__
|
|
msg_gdbg(" LLVM Clang");
|
|
#ifdef __clang_version__
|
|
msg_gdbg(" %s,", __clang_version__);
|
|
#else
|
|
msg_gdbg(" unknown version (before r102686),");
|
|
#endif
|
|
#elif defined(__GNUC__)
|
|
msg_gdbg(" GCC");
|
|
#ifdef __VERSION__
|
|
msg_gdbg(" %s,", __VERSION__);
|
|
#else
|
|
msg_gdbg(" unknown version,");
|
|
#endif
|
|
#else
|
|
msg_gdbg(" unknown compiler,");
|
|
#endif
|
|
#if defined (__FLASHROM_LITTLE_ENDIAN__)
|
|
msg_gdbg(" little endian");
|
|
#elif defined (__FLASHROM_BIG_ENDIAN__)
|
|
msg_gdbg(" big endian");
|
|
#else
|
|
#error Endianness could not be determined
|
|
#endif
|
|
msg_gdbg("\n");
|
|
}
|
|
|
|
void print_version(void)
|
|
{
|
|
msg_ginfo("flashrom %s", flashrom_version_info());
|
|
print_sysinfo();
|
|
msg_ginfo("\n");
|
|
}
|
|
|
|
void print_banner(void)
|
|
{
|
|
msg_ginfo("flashrom is free software, get the source code at "
|
|
"https://flashrom.org\n");
|
|
msg_ginfo("\n");
|
|
}
|