1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 07:02:34 +02:00
flashrom/cli_classic.c
Carl-Daniel Hailfinger ad3cc55e13 Kill global variables, constants and functions if local scope suffices
Constify variables where possible.
Initialize programmer-related variables explicitly in programmer_init to
allow running programmer_init from a clean state after
programmer_shutdown.
Prohibit registering programmer shutdown functions before init or after
shutdown.
Kill some dead code.
Rename global variables with namespace-polluting names.
Use a previously unused locking helper function in sst49lfxxxc.c.

This is needed for libflashrom.

Effects on the binary size of flashrom are minimal (300 bytes
shrinkage), but the data section shrinks by 4384 bytes, and that's a
good thing if flashrom is operating in constrained envionments.

Corresponding to flashrom svn r1068.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
2010-07-03 11:02:10 +00:00

460 lines
12 KiB
C

/*
* This file is part of the flashrom project.
*
* Copyright (C) 2000 Silicon Integrated System Corporation
* Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
* Copyright (C) 2005-2008 coresystems GmbH
* Copyright (C) 2008,2009,2010 Carl-Daniel Hailfinger
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include "flash.h"
#include "flashchips.h"
static void cli_classic_usage(const char *name)
{
const char *pname;
int pnamelen;
int remaining = 0;
enum programmer p;
printf("Usage: flashrom [-n] [-V] [-f] [-h|-R|-L|"
#if CONFIG_PRINT_WIKI == 1
"-z|"
#endif
"-E|-r <file>|-w <file>|-v <file>]\n"
" [-c <chipname>] [-m [<vendor>:]<part>] [-l <file>]\n"
" [-i <image>] [-p <programmername>[:<parameters>]]\n\n");
printf("Please note that the command line interface for flashrom has "
"changed between\n"
"0.9.1 and 0.9.2 and will change again before flashrom 1.0.\n"
"Do not use flashrom in scripts or other automated tools "
"without checking\n"
"that your flashrom version won't interpret options in a "
"different way.\n\n");
printf(" -h | --help print this help text\n"
" -R | --version print version (release)\n"
" -r | --read <file> read flash and save to "
"<file>\n"
" -w | --write <file> write <file> to flash\n"
" -v | --verify <file> verify flash against "
"<file>\n"
" -E | --erase erase flash device\n"
" -V | --verbose more verbose output\n"
" -c | --chip <chipname> probe only for specified "
"flash chip\n"
#if CONFIG_INTERNAL == 1
/* FIXME: --mainboard should be a programmer parameter */
" -m | --mainboard <[vendor:]part> override mainboard "
"detection\n"
#endif
" -f | --force force specific operations "
"(see man page)\n"
" -n | --noverify don't auto-verify\n"
" -l | --layout <file> read ROM layout from "
"<file>\n"
" -i | --image <name> only flash image <name> "
"from flash layout\n"
" -L | --list-supported print supported devices\n"
#if CONFIG_PRINT_WIKI == 1
" -z | --list-supported-wiki print supported devices "
"in wiki syntax\n"
#endif
" -p | --programmer <name>[:<param>] specify the programmer "
"device");
for (p = 0; p < PROGRAMMER_INVALID; p++) {
pname = programmer_table[p].name;
pnamelen = strlen(pname);
if (remaining - pnamelen - 2 < 0) {
printf("\n ");
remaining = 43;
} else {
printf(" ");
remaining--;
}
if (p == 0) {
printf("(");
remaining--;
}
printf("%s", pname);
remaining -= pnamelen;
if (p < PROGRAMMER_INVALID - 1) {
printf(",");
remaining--;
} else {
printf(")\n");
}
}
printf("\nYou can specify one of -h, -R, -L, "
#if CONFIG_PRINT_WIKI == 1
"-z, "
#endif
"-E, -r, -w, -v or no operation.\n"
"If no operation is specified, flashrom will only probe for "
"flash chips.\n\n");
}
static void cli_classic_abort_usage(void)
{
printf("Please run \"flashrom --help\" for usage info.\n");
exit(1);
}
int cli_classic(int argc, char *argv[])
{
unsigned long size;
/* Probe for up to three flash chips. */
struct flashchip *flash, *flashes[3];
const char *name;
int namelen;
int opt;
int option_index = 0;
int force = 0;
int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
int dont_verify_it = 0, list_supported = 0;
#if CONFIG_PRINT_WIKI == 1
int list_supported_wiki = 0;
#endif
int operation_specified = 0;
int i;
const char *optstring = "r:Rw:v:nVEfc:m:l:i:p:Lzh";
static struct option long_options[] = {
{"read", 1, 0, 'r'},
{"write", 1, 0, 'w'},
{"erase", 0, 0, 'E'},
{"verify", 1, 0, 'v'},
{"noverify", 0, 0, 'n'},
{"chip", 1, 0, 'c'},
{"mainboard", 1, 0, 'm'},
{"verbose", 0, 0, 'V'},
{"force", 0, 0, 'f'},
{"layout", 1, 0, 'l'},
{"image", 1, 0, 'i'},
{"list-supported", 0, 0, 'L'},
{"list-supported-wiki", 0, 0, 'z'},
{"programmer", 1, 0, 'p'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'R'},
{0, 0, 0, 0}
};
char *filename = NULL;
char *tempstr = NULL;
char *pparam = NULL;
print_version();
print_banner();
if (selfcheck())
exit(1);
setbuf(stdout, NULL);
/* FIXME: Delay all operation_specified checks until after command
* line parsing to allow --help overriding everything else.
*/
while ((opt = getopt_long(argc, argv, optstring,
long_options, &option_index)) != EOF) {
switch (opt) {
case 'r':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
filename = strdup(optarg);
read_it = 1;
break;
case 'w':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
filename = strdup(optarg);
write_it = 1;
break;
case 'v':
//FIXME: gracefully handle superfluous -v
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
if (dont_verify_it) {
fprintf(stderr, "--verify and --noverify are"
"mutually exclusive. Aborting.\n");
cli_classic_abort_usage();
}
filename = strdup(optarg);
verify_it = 1;
break;
case 'n':
if (verify_it) {
fprintf(stderr, "--verify and --noverify are"
"mutually exclusive. Aborting.\n");
cli_classic_abort_usage();
}
dont_verify_it = 1;
break;
case 'c':
chip_to_probe = strdup(optarg);
break;
case 'V':
verbose++;
break;
case 'E':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
erase_it = 1;
break;
case 'm':
#if CONFIG_INTERNAL == 1
tempstr = strdup(optarg);
lb_vendor_dev_from_string(tempstr);
#else
fprintf(stderr, "Error: Internal programmer support "
"was not compiled in and --mainboard only\n"
"applies to the internal programmer. Aborting.\n");
cli_classic_abort_usage();
#endif
break;
case 'f':
force = 1;
break;
case 'l':
tempstr = strdup(optarg);
if (read_romlayout(tempstr))
cli_classic_abort_usage();
break;
case 'i':
tempstr = strdup(optarg);
find_romentry(tempstr);
break;
case 'L':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
list_supported = 1;
break;
case 'z':
#if CONFIG_PRINT_WIKI == 1
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
list_supported_wiki = 1;
#else
fprintf(stderr, "Error: Wiki output was not compiled "
"in. Aborting.\n");
cli_classic_abort_usage();
#endif
break;
case 'p':
for (programmer = 0; programmer < PROGRAMMER_INVALID; programmer++) {
name = programmer_table[programmer].name;
namelen = strlen(name);
if (strncmp(optarg, name, namelen) == 0) {
switch (optarg[namelen]) {
case ':':
pparam = strdup(optarg + namelen + 1);
if (!strlen(pparam)) {
free(pparam);
pparam = NULL;
}
break;
case '\0':
break;
default:
/* The continue refers to the
* for loop. It is here to be
* able to differentiate between
* foo and foobar.
*/
continue;
}
break;
}
}
if (programmer == PROGRAMMER_INVALID) {
fprintf(stderr, "Error: Unknown programmer "
"%s.\n", optarg);
cli_classic_abort_usage();
}
break;
case 'R':
/* print_version() is always called during startup. */
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
exit(0);
break;
case 'h':
if (++operation_specified > 1) {
fprintf(stderr, "More than one operation "
"specified. Aborting.\n");
cli_classic_abort_usage();
}
cli_classic_usage(argv[0]);
exit(0);
break;
default:
cli_classic_abort_usage();
break;
}
}
/* FIXME: Print the actions flashrom will take. */
if (list_supported) {
print_supported();
exit(0);
}
#if CONFIG_PRINT_WIKI == 1
if (list_supported_wiki) {
print_supported_wiki();
exit(0);
}
#endif
if (optind < argc) {
fprintf(stderr, "Error: Extra parameter found.\n");
cli_classic_abort_usage();
}
#if CONFIG_INTERNAL == 1
if ((programmer != PROGRAMMER_INTERNAL) && (lb_part || lb_vendor)) {
fprintf(stderr, "Error: --mainboard requires the internal "
"programmer. Aborting.\n");
cli_classic_abort_usage();
}
#endif
if (chip_to_probe) {
for (flash = flashchips; flash && flash->name; flash++)
if (!strcmp(flash->name, chip_to_probe))
break;
if (!flash || !flash->name) {
fprintf(stderr, "Error: Unknown chip '%s' specified.\n",
chip_to_probe);
printf("Run flashrom -L to view the hardware supported "
"in this flashrom version.\n");
exit(1);
}
/* Clean up after the check. */
flash = NULL;
}
/* FIXME: Delay calibration should happen in programmer code. */
myusec_calibrate_delay();
if (programmer_init(pparam)) {
fprintf(stderr, "Error: Programmer initialization failed.\n");
exit(1);
}
/* FIXME: Delay calibration should happen in programmer code. */
for (i = 0; i < ARRAY_SIZE(flashes); i++) {
flashes[i] =
probe_flash(i ? flashes[i - 1] + 1 : flashchips, 0);
if (!flashes[i])
for (i++; i < ARRAY_SIZE(flashes); i++)
flashes[i] = NULL;
}
if (flashes[1]) {
printf("Multiple flash chips were detected:");
for (i = 0; i < ARRAY_SIZE(flashes) && flashes[i]; i++)
printf(" %s", flashes[i]->name);
printf("\nPlease specify which chip to use with the -c <chipname> option.\n");
programmer_shutdown();
exit(1);
} else if (!flashes[0]) {
printf("No EEPROM/flash device found.\n");
if (!force || !chip_to_probe) {
printf("Note: flashrom can never write if the flash chip isn't found automatically.\n");
}
if (force && read_it && chip_to_probe) {
printf("Force read (-f -r -c) requested, pretending the chip is there:\n");
flashes[0] = probe_flash(flashchips, 1);
if (!flashes[0]) {
printf("Probing for flash chip '%s' failed.\n", chip_to_probe);
programmer_shutdown();
exit(1);
}
printf("Please note that forced reads most likely contain garbage.\n");
return read_flash(flashes[0], filename);
}
// FIXME: flash writes stay enabled!
programmer_shutdown();
exit(1);
}
flash = flashes[0];
check_chip_supported(flash);
size = flash->total_size * 1024;
if (check_max_decode((buses_supported & flash->bustype), size) &&
(!force)) {
fprintf(stderr, "Chip is too big for this programmer "
"(-V gives details). Use --force to override.\n");
programmer_shutdown();
return 1;
}
if (!(read_it | write_it | verify_it | erase_it)) {
printf("No operations were specified.\n");
// FIXME: flash writes stay enabled!
programmer_shutdown();
exit(0);
}
if (!filename && !erase_it) {
printf("Error: No filename specified.\n");
// FIXME: flash writes stay enabled!
programmer_shutdown();
exit(1);
}
/* Always verify write operations unless -n is used. */
if (write_it && !dont_verify_it)
verify_it = 1;
return doit(flash, force, filename, read_it, write_it, erase_it, verify_it);
}