cli_mfg.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2000 Silicon Integrated System Corporation
  5. * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
  6. * Copyright (C) 2005-2008 coresystems GmbH
  7. * Copyright (C) 2008,2009,2010 Carl-Daniel Hailfinger
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include <stdio.h>
  24. #include <fcntl.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <getopt.h>
  30. #include <errno.h>
  31. #include "big_lock.h"
  32. #include "flash.h"
  33. #include "flashchips.h"
  34. #include "layout.h"
  35. #include "power.h"
  36. #include "programmer.h"
  37. #include "writeprotect.h"
  38. #define LOCK_TIMEOUT_SECS 180
  39. int set_ignore_lock = 0;
  40. #if CONFIG_INTERNAL == 1
  41. static enum programmer default_programmer = PROGRAMMER_INTERNAL;
  42. #elif CONFIG_DUMMY == 1
  43. static enum programmer default_programmer = PROGRAMMER_DUMMY;
  44. #else
  45. /* If neither internal nor dummy are selected, we must pick a sensible default.
  46. * Since there is no reason to prefer a particular external programmer, we fail
  47. * if more than one of them is selected. If only one is selected, it is clear
  48. * that the user wants that one to become the default.
  49. */
  50. #if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL+CONFIG_NICINTEL_SPI+CONFIG_OGP_SPI+CONFIG_SATAMV > 1
  51. #error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all programmers except one.
  52. #endif
  53. static enum programmer default_programmer =
  54. #if CONFIG_NIC3COM == 1
  55. PROGRAMMER_NIC3COM
  56. #endif
  57. #if CONFIG_NICREALTEK == 1
  58. PROGRAMMER_NICREALTEK
  59. #endif
  60. #if CONFIG_NICNATSEMI == 1
  61. PROGRAMMER_NICNATSEMI
  62. #endif
  63. #if CONFIG_GFXNVIDIA == 1
  64. PROGRAMMER_GFXNVIDIA
  65. #endif
  66. #if CONFIG_DRKAISER == 1
  67. PROGRAMMER_DRKAISER
  68. #endif
  69. #if CONFIG_SATASII == 1
  70. PROGRAMMER_SATASII
  71. #endif
  72. #if CONFIG_ATAHPT == 1
  73. PROGRAMMER_ATAHPT
  74. #endif
  75. #if CONFIG_FT2232_SPI == 1
  76. PROGRAMMER_FT2232_SPI
  77. #endif
  78. #if CONFIG_SERPROG == 1
  79. PROGRAMMER_SERPROG
  80. #endif
  81. #if CONFIG_BUSPIRATE_SPI == 1
  82. PROGRAMMER_BUSPIRATE_SPI
  83. #endif
  84. #if CONFIG_DEDIPROG == 1
  85. PROGRAMMER_DEDIPROG
  86. #endif
  87. #if CONFIG_RAYER_SPI == 1
  88. PROGRAMMER_RAYER_SPI
  89. #endif
  90. #if CONFIG_NICINTEL == 1
  91. PROGRAMMER_NICINTEL
  92. #endif
  93. #if CONFIG_NICINTEL_SPI == 1
  94. PROGRAMMER_NICINTEL_SPI
  95. #endif
  96. #if CONFIG_OGP_SPI == 1
  97. PROGRAMMER_OGP_SPI
  98. #endif
  99. #if CONFIG_SATAMV == 1
  100. PROGRAMMER_SATAMV
  101. #endif
  102. #if CONFIG_LINUX_MTD == 1
  103. PROGRAMMER_LINUX_MTD
  104. #endif
  105. #if CONFIG_LINUX_SPI == 1
  106. PROGRAMMER_LINUX_SPI
  107. #endif
  108. ;
  109. #endif
  110. void cli_mfg_usage(const char *name)
  111. {
  112. msg_ginfo("Usage: flashrom [-n] [-V] [-f] [-h|-R|-L|"
  113. #if CONFIG_PRINT_WIKI == 1
  114. "-z|"
  115. #endif
  116. "-E|-r <file>|-w <file>|-v <file>]\n"
  117. " [-i <image>[:<file>]] [-c <chipname>]\n"
  118. "[-o <file>] [-l <file>]\n"
  119. " [-p <programmer>[:<parameters>]]\n\n");
  120. msg_ginfo("Please note that the command line interface for flashrom has "
  121. "changed between\n"
  122. "0.9.1 and 0.9.2 and will change again before flashrom 1.0.\n"
  123. "Do not use flashrom in scripts or other automated tools "
  124. "without checking\n"
  125. "that your flashrom version won't interpret options in a "
  126. "different way.\n\n");
  127. msg_ginfo(" -h | --help print this help text\n"
  128. " -R | --version print version (release)\n"
  129. " -r | --read <file|-> read flash and save to "
  130. "<file> or write on the standard output\n"
  131. " -w | --write <file|-> write <file> or "
  132. "the content provided on the standard input to flash\n"
  133. " -v | --verify <file|-> verify flash against "
  134. "<file> or the content provided on the standard input\n"
  135. " -E | --erase erase flash device\n"
  136. " -V | --verbose more verbose output\n"
  137. " -c | --chip <chipname> probe only for specified "
  138. "flash chip\n"
  139. " -f | --force force specific operations "
  140. "(see man page)\n"
  141. " -n | --noverify don't auto-verify\n"
  142. " -l | --layout <file> read ROM layout from "
  143. "<file>\n"
  144. " -i | --image <name>[:<file>] only access image <name> "
  145. "from flash layout\n"
  146. " -o | --output <name> log to file <name>\n"
  147. " -L | --list-supported print supported devices\n"
  148. " -x | --extract extract regions to files\n"
  149. #if CONFIG_PRINT_WIKI == 1
  150. " -z | --list-supported-wiki print supported devices "
  151. "in wiki syntax\n"
  152. #endif
  153. " -b | --broken-timers assume system timers are "
  154. "broken\n"
  155. " -p | --programmer <name>[:<param>] specify the programmer "
  156. "device\n"
  157. );
  158. list_programmers_linebreak(37, 80, 1);
  159. msg_ginfo("Long-options:\n"
  160. " --diff <file> diff from file instead of ROM\n"
  161. " --fast-verify only verify -i part\n"
  162. " --flash-name flash vendor and device name\n"
  163. " --get-size get chip size (bytes)\n"
  164. " --ignore-fmap ignore fmap structure\n"
  165. " --ignore-lock do not acquire big lock\n"
  166. " --wp-disable disable write protection\n"
  167. " --wp-enable enable write protection\n"
  168. " --wp-list list write protection ranges\n"
  169. " --wp-range <start> <length> set write protect range\n"
  170. " --wp-region <region> set write protect range by region name\n"
  171. " --wp-status show write protect status\n"
  172. );
  173. msg_ginfo("\nYou can specify one of -h, -R, -L, "
  174. #if CONFIG_PRINT_WIKI == 1
  175. "-z, "
  176. #endif
  177. "-E, -r, -w, -v or no operation.\n"
  178. "If no operation is specified, flashrom will only probe for "
  179. "flash chips.\n\n");
  180. }
  181. void cli_mfg_abort_usage(const char *name)
  182. {
  183. msg_gerr("Please run \"%s --help\" for usage info.\n", name);
  184. exit(1);
  185. }
  186. static int check_filename(char *filename, char *type)
  187. {
  188. if (!filename || (filename[0] == '\0')) {
  189. fprintf(stderr, "Error: No %s file specified.\n", type);
  190. return 1;
  191. }
  192. /* Not an error, but maybe the user intended to specify a CLI option instead of a file name. */
  193. if (filename[0] == '-')
  194. fprintf(stderr, "Warning: Supplied %s file name starts with -\n", type);
  195. return 0;
  196. }
  197. enum LONGOPT_RETURN_VALUES {
  198. /* start after ASCII chars */
  199. LONGOPT_GET_SIZE = 256,
  200. LONGOPT_DIFF,
  201. LONGOPT_FLASH_NAME,
  202. LONGOPT_WP_STATUS,
  203. LONGOPT_WP_SET_RANGE,
  204. LONGOPT_WP_SET_REGION,
  205. LONGOPT_WP_ENABLE,
  206. LONGOPT_WP_DISABLE,
  207. LONGOPT_WP_LIST,
  208. LONGOPT_IGNORE_FMAP,
  209. LONGOPT_FAST_VERIFY,
  210. LONGOPT_IGNORE_LOCK,
  211. };
  212. int main(int argc, char *argv[])
  213. {
  214. unsigned long size;
  215. /* Probe for up to three flash chips. */
  216. const struct flashchip *flash;
  217. struct flashctx flashes[3];
  218. struct flashctx *fill_flash;
  219. int startchip = 0;
  220. int chipcount = 0;
  221. const char *name;
  222. int namelen;
  223. int opt;
  224. int option_index = 0;
  225. int force = 0;
  226. int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0,
  227. get_size = 0, dont_verify_it = 0, list_supported = 0,
  228. extract_it = 0, flash_name = 0;
  229. int set_wp_range = 0, set_wp_region = 0, set_wp_enable = 0,
  230. set_wp_disable = 0, wp_status = 0, wp_list = 0;
  231. int set_ignore_fmap = 0;
  232. #if CONFIG_PRINT_WIKI == 1
  233. int list_supported_wiki = 0;
  234. #endif
  235. int operation_specified = 0;
  236. int i;
  237. enum programmer prog = PROGRAMMER_INVALID;
  238. int rc = 0;
  239. int found_chip = 0;
  240. const char *optstring = "rRwvnVEfc:l:i:p:o:Lzhbx";
  241. static struct option long_options[] = {
  242. {"read", 0, 0, 'r'},
  243. {"write", 0, 0, 'w'},
  244. {"erase", 0, 0, 'E'},
  245. {"verify", 0, 0, 'v'},
  246. {"noverify", 0, 0, 'n'},
  247. {"chip", 1, 0, 'c'},
  248. {"verbose", 0, 0, 'V'},
  249. {"force", 0, 0, 'f'},
  250. {"layout", 1, 0, 'l'},
  251. {"image", 1, 0, 'i'},
  252. {"list-supported", 0, 0, 'L'},
  253. {"list-supported-wiki", 0, 0, 'z'},
  254. {"extract", 0, 0, 'x'},
  255. {"programmer", 1, 0, 'p'},
  256. {"help", 0, 0, 'h'},
  257. {"version", 0, 0, 'R'},
  258. {"output", 1, 0, 'o'},
  259. {"get-size", 0, 0, LONGOPT_GET_SIZE},
  260. {"flash-name", 0, 0, LONGOPT_FLASH_NAME},
  261. {"diff", 1, 0, LONGOPT_DIFF},
  262. {"wp-status", 0, 0, LONGOPT_WP_STATUS},
  263. {"wp-range", 0, 0, LONGOPT_WP_SET_RANGE},
  264. {"wp-region", 1, 0, LONGOPT_WP_SET_REGION},
  265. {"wp-enable", optional_argument, 0, LONGOPT_WP_ENABLE},
  266. {"wp-disable", 0, 0, LONGOPT_WP_DISABLE},
  267. {"wp-list", 0, 0, LONGOPT_WP_LIST},
  268. {"broken-timers", 0, 0, 'b' },
  269. {"ignore-fmap", 0, 0, LONGOPT_IGNORE_FMAP},
  270. {"fast-verify", 0, 0, LONGOPT_FAST_VERIFY},
  271. {"ignore-lock", 0, 0, LONGOPT_IGNORE_LOCK},
  272. {0, 0, 0, 0}
  273. };
  274. char *filename = NULL;
  275. char *layoutfile = NULL;
  276. char *diff_file = NULL;
  277. char *logfile = NULL;
  278. char *tempstr = NULL;
  279. char *pparam = NULL;
  280. char *wp_mode_opt = NULL;
  281. char *wp_region = NULL;
  282. print_version();
  283. if (selfcheck())
  284. exit(1);
  285. setbuf(stdout, NULL);
  286. /* FIXME: Delay all operation_specified checks until after command
  287. * line parsing to allow --help overriding everything else.
  288. */
  289. while ((opt = getopt_long(argc, argv, optstring,
  290. long_options, &option_index)) != EOF) {
  291. switch (opt) {
  292. case 'r':
  293. if (++operation_specified > 1) {
  294. msg_gerr("More than one operation "
  295. "specified. Aborting.\n");
  296. cli_mfg_abort_usage(argv[0]);
  297. }
  298. read_it = 1;
  299. #if CONFIG_USE_OS_TIMER == 0
  300. /* horrible workaround for excess time spent in
  301. * ichspi.c code: */
  302. broken_timer = 1;
  303. #endif
  304. break;
  305. case 'w':
  306. if (++operation_specified > 1) {
  307. msg_gerr("More than one operation "
  308. "specified. Aborting.\n");
  309. cli_mfg_abort_usage(argv[0]);
  310. }
  311. write_it = 1;
  312. #if CONFIG_USE_OS_TIMER == 0
  313. /* horrible workaround for excess time spent in
  314. * ichspi.c code: */
  315. broken_timer = 1;
  316. #endif
  317. break;
  318. case 'v':
  319. //FIXME: gracefully handle superfluous -v
  320. if (++operation_specified > 1) {
  321. msg_gerr("More than one operation "
  322. "specified. Aborting.\n");
  323. cli_mfg_abort_usage(argv[0]);
  324. }
  325. if (dont_verify_it) {
  326. msg_gerr("--verify and --noverify are"
  327. "mutually exclusive. Aborting.\n");
  328. cli_mfg_abort_usage(argv[0]);
  329. }
  330. if (!verify_it) verify_it = VERIFY_FULL;
  331. #if CONFIG_USE_OS_TIMER == 0
  332. /* horrible workaround for excess time spent in
  333. * ichspi.c code: */
  334. broken_timer = 1;
  335. #endif
  336. break;
  337. case 'n':
  338. if (verify_it) {
  339. msg_gerr("--verify and --noverify are"
  340. "mutually exclusive. Aborting.\n");
  341. cli_mfg_abort_usage(argv[0]);
  342. }
  343. dont_verify_it = 1;
  344. break;
  345. case 'c':
  346. chip_to_probe = strdup(optarg);
  347. break;
  348. case 'V':
  349. verbose_screen++;
  350. if(verbose_screen > MSG_DEBUG2)
  351. verbose_logfile = verbose_screen;
  352. break;
  353. case 'E':
  354. if (++operation_specified > 1) {
  355. msg_gerr("More than one operation "
  356. "specified. Aborting.\n");
  357. cli_mfg_abort_usage(argv[0]);
  358. }
  359. erase_it = 1;
  360. #if CONFIG_USE_OS_TIMER == 0
  361. /* horrible workaround for excess time spent in
  362. * ichspi.c code: */
  363. broken_timer = 1;
  364. #endif
  365. break;
  366. case 'f':
  367. force = 1;
  368. break;
  369. case 'l':
  370. if (layoutfile) {
  371. fprintf(stderr, "Error: --layout specified more than once. Aborting\n");
  372. cli_mfg_abort_usage(argv[0]);
  373. }
  374. layoutfile = strdup(optarg);
  375. break;
  376. case 'i':
  377. tempstr = strdup(optarg);
  378. if (register_include_arg(tempstr) < 0)
  379. exit(1);
  380. break;
  381. case 'L':
  382. if (++operation_specified > 1) {
  383. msg_gerr("More than one operation "
  384. "specified. Aborting.\n");
  385. cli_mfg_abort_usage(argv[0]);
  386. }
  387. list_supported = 1;
  388. break;
  389. case 'x':
  390. if (++operation_specified > 1) {
  391. msg_gerr("More than one operation "
  392. "specified. Aborting.\n");
  393. cli_mfg_abort_usage(argv[0]);
  394. }
  395. extract_it = 1;
  396. break;
  397. case 'z':
  398. #if CONFIG_PRINT_WIKI == 1
  399. if (++operation_specified > 1) {
  400. msg_gerr("More than one operation "
  401. "specified. Aborting.\n");
  402. cli_mfg_abort_usage(argv[0]);
  403. }
  404. list_supported_wiki = 1;
  405. #else
  406. msg_gerr("Error: Wiki output was not compiled "
  407. "in. Aborting.\n");
  408. cli_mfg_abort_usage(argv[0]);
  409. #endif
  410. break;
  411. case 'p':
  412. if (prog != PROGRAMMER_INVALID) {
  413. msg_gerr("Error: --programmer specified "
  414. "more than once. You can separate "
  415. "multiple\nparameters for a programmer "
  416. "with \",\". Please see the man page "
  417. "for details.\n");
  418. cli_mfg_abort_usage(argv[0]);
  419. }
  420. for (prog = 0; prog < PROGRAMMER_INVALID; prog++) {
  421. name = programmer_table[prog].name;
  422. namelen = strlen(name);
  423. if (strncmp(optarg, name, namelen) == 0) {
  424. switch (optarg[namelen]) {
  425. case ':':
  426. pparam = strdup(optarg + namelen + 1);
  427. if (!strlen(pparam)) {
  428. free(pparam);
  429. pparam = NULL;
  430. }
  431. break;
  432. case '\0':
  433. break;
  434. default:
  435. /* The continue refers to the
  436. * for loop. It is here to be
  437. * able to differentiate between
  438. * foo and foobar.
  439. */
  440. continue;
  441. }
  442. break;
  443. }
  444. }
  445. for (i = 0; aliases[i].name; i++) {
  446. name = aliases[i].name;
  447. namelen = strlen(aliases[i].name);
  448. if (strncmp(optarg, name, namelen))
  449. continue;
  450. switch (optarg[namelen]) {
  451. case ':':
  452. pparam = strdup(optarg + namelen + 1);
  453. if (!strlen(pparam)) {
  454. free(pparam);
  455. pparam = NULL;
  456. }
  457. break;
  458. case '\0':
  459. break;
  460. default:
  461. /* The continue refers to the for-loop.
  462. * It is here to be able to
  463. * differentiate between foo and foobar.
  464. */
  465. continue;
  466. }
  467. alias = &aliases[i];
  468. msg_gdbg("Programmer alias: \"%s\", parameter: "
  469. " \"%s\",\n", alias->name, pparam);
  470. break;
  471. }
  472. if ((prog == PROGRAMMER_INVALID) && !alias) {
  473. msg_gerr("Error: Unknown programmer "
  474. "%s.\n", optarg);
  475. cli_mfg_abort_usage(argv[0]);
  476. }
  477. if ((prog != PROGRAMMER_INVALID) && alias) {
  478. msg_gerr("Error: Alias cannot be used "
  479. "with programmer name.\n");
  480. cli_mfg_abort_usage(argv[0]);
  481. }
  482. break;
  483. case 'R':
  484. /* print_version() is always called during startup. */
  485. if (++operation_specified > 1) {
  486. msg_gerr("More than one operation "
  487. "specified. Aborting.\n");
  488. cli_mfg_abort_usage(argv[0]);
  489. }
  490. exit(0);
  491. break;
  492. case 'h':
  493. if (++operation_specified > 1) {
  494. msg_gerr("More than one operation "
  495. "specified. Aborting.\n");
  496. cli_mfg_abort_usage(argv[0]);
  497. }
  498. cli_mfg_usage(argv[0]);
  499. exit(0);
  500. break;
  501. case 'o':
  502. #ifdef STANDALONE
  503. fprintf(stderr, "Log file not supported in standalone mode. Aborting.\n");
  504. cli_mfg_abort_usage(argv[0]);
  505. #else /* STANDALONE */
  506. logfile = strdup(optarg);
  507. if (logfile[0] == '\0') {
  508. fprintf(stderr, "No log filename specified.\n");
  509. cli_mfg_abort_usage(argv[0]);
  510. }
  511. #endif /* STANDALONE */
  512. break;
  513. case LONGOPT_GET_SIZE:
  514. get_size = 1;
  515. break;
  516. case LONGOPT_WP_STATUS:
  517. wp_status = 1;
  518. break;
  519. case LONGOPT_WP_LIST:
  520. wp_list = 1;
  521. break;
  522. case LONGOPT_WP_SET_RANGE:
  523. set_wp_range = 1;
  524. break;
  525. case LONGOPT_WP_SET_REGION:
  526. set_wp_region = 1;
  527. wp_region = strdup(optarg);
  528. break;
  529. case LONGOPT_WP_ENABLE:
  530. set_wp_enable = 1;
  531. if (optarg)
  532. wp_mode_opt = strdup(optarg);
  533. break;
  534. case LONGOPT_WP_DISABLE:
  535. set_wp_disable = 1;
  536. break;
  537. case LONGOPT_FLASH_NAME:
  538. flash_name = 1;
  539. break;
  540. case LONGOPT_DIFF:
  541. diff_file = strdup(optarg);
  542. break;
  543. case LONGOPT_IGNORE_FMAP:
  544. set_ignore_fmap = 1;
  545. break;
  546. case LONGOPT_FAST_VERIFY:
  547. verify_it = VERIFY_PARTIAL;
  548. break;
  549. case 'b':
  550. broken_timer = 1;
  551. break;
  552. case LONGOPT_IGNORE_LOCK:
  553. set_ignore_lock = 1;
  554. break;
  555. default:
  556. cli_mfg_abort_usage(argv[0]);
  557. break;
  558. }
  559. }
  560. /* FIXME: Print the actions flashrom will take. */
  561. if (list_supported) {
  562. print_supported();
  563. exit(0);
  564. }
  565. #if CONFIG_PRINT_WIKI == 1
  566. if (list_supported_wiki) {
  567. print_supported_wiki();
  568. exit(0);
  569. }
  570. #endif
  571. #if 0
  572. if (optind < argc) {
  573. msg_gerr("Error: Extra parameter found.\n");
  574. cli_mfg_abort_usage(argv[0]);
  575. }
  576. #endif
  577. if (layoutfile && check_filename(layoutfile, "layout")) {
  578. cli_mfg_abort_usage(argv[0]);
  579. }
  580. #ifndef STANDALONE
  581. if (logfile && check_filename(logfile, "log"))
  582. cli_mfg_abort_usage(argv[0]);
  583. if (logfile && open_logfile(logfile))
  584. return 1;
  585. #endif /* !STANDALONE */
  586. if (read_it || write_it || verify_it) {
  587. if (argv[optind])
  588. filename = argv[optind];
  589. }
  590. #ifndef STANDALONE
  591. start_logging();
  592. #endif /* !STANDALONE */
  593. print_buildinfo();
  594. msg_gdbg("Command line (%i args):", argc - 1);
  595. for (i = 0; i < argc; i++) {
  596. msg_gdbg(" %s", argv[i]);
  597. }
  598. msg_gdbg("\n");
  599. if (layoutfile && read_romlayout(layoutfile)) {
  600. cli_mfg_abort_usage(argv[0]);
  601. }
  602. if (chip_to_probe) {
  603. for (flash = flashchips; flash && flash->name; flash++) {
  604. if (!strcmp(flash->name, chip_to_probe)) {
  605. found_chip = 1;
  606. break;
  607. }
  608. }
  609. for (flash = flashchips_hwseq; flash && flash->name &&
  610. !found_chip; flash++) {
  611. if (!strcmp(flash->name, chip_to_probe)) {
  612. found_chip = 1;
  613. break;
  614. }
  615. }
  616. if (!found_chip) {
  617. msg_gerr("Error: Unknown chip '%s' specified.\n",
  618. chip_to_probe);
  619. msg_gerr("Run flashrom -L to view the hardware supported "
  620. "in this flashrom version.\n");
  621. exit(1);
  622. }
  623. /* Clean up after the check. */
  624. flash = NULL;
  625. }
  626. if (prog == PROGRAMMER_INVALID)
  627. prog = default_programmer;
  628. #if USE_BIG_LOCK == 1
  629. /* get lock before doing any work that touches hardware */
  630. if (!set_ignore_lock) {
  631. msg_gdbg("Acquiring lock (timeout=%d sec)...\n", LOCK_TIMEOUT_SECS);
  632. if (acquire_big_lock(LOCK_TIMEOUT_SECS) < 0) {
  633. msg_gerr("Could not acquire lock.\n");
  634. exit(1);
  635. }
  636. msg_gdbg("Lock acquired.\n");
  637. }
  638. #endif
  639. /*
  640. * Let powerd know that we're updating firmware so machine stays awake.
  641. *
  642. * A bit of history behind this small block of code:
  643. * chromium-os:15025 - If broken_timer == 1, use busy loop instead of
  644. * OS timers to avoid excessive usleep overhead during "long" operations
  645. * involving reads, erases, and writes. This was mostly a problem on
  646. * old machines with poor DVFS implementations.
  647. *
  648. * chromium-os:18895 - Disabled power management to prevent system from
  649. * going to sleep while doing a destructive operation.
  650. *
  651. * chromium-os:19321 - Use OS timers for non-destructive operations to
  652. * avoid UI jank.
  653. *
  654. * chromium:400641 - Powerd is smarter now, so instead of stopping it
  655. * manually we'll use a file lock so it knows not to put the machine
  656. * to sleep or do other things that can interfere.
  657. *
  658. */
  659. if (write_it || erase_it)
  660. disable_power_management();
  661. /* FIXME: Delay calibration should happen in programmer code. */
  662. myusec_calibrate_delay();
  663. if (programmer_init(prog, pparam)) {
  664. msg_gerr("Error: Programmer initialization failed.\n");
  665. rc = 1;
  666. goto cli_mfg_silent_exit;
  667. }
  668. /* FIXME: Delay calibration should happen in programmer code. */
  669. for (i = 0; i < ARRAY_SIZE(flashes); i++) {
  670. startchip = probe_flash(startchip, &flashes[i], 0);
  671. if (startchip == -1)
  672. break;
  673. chipcount++;
  674. startchip++;
  675. }
  676. if (chipcount > 1) {
  677. msg_gerr("Multiple flash chips were detected:");
  678. for (i = 0; i < chipcount; i++)
  679. msg_gerr(" %s", flashes[i].name);
  680. msg_gerr("\nPlease specify which chip to use with the -c <chipname> option.\n");
  681. programmer_shutdown();
  682. exit(1);
  683. } else if (!chipcount) {
  684. msg_gerr("No EEPROM/flash device found.\n");
  685. if (!force || !chip_to_probe) {
  686. msg_gerr("Note: flashrom can never write if the flash chip isn't found automatically.\n");
  687. }
  688. if (force && read_it && chip_to_probe) {
  689. msg_ginfo("Force read (-f -r -c) requested, pretending the chip is there:\n");
  690. startchip = probe_flash(0, &flashes[0], 1);
  691. if (startchip == -1) {
  692. msg_gerr("Probing for flash chip '%s' failed.\n", chip_to_probe);
  693. rc = 1;
  694. goto cli_mfg_silent_exit;
  695. }
  696. msg_ginfo("Please note that forced reads most likely contain garbage.\n");
  697. return read_flash_to_file(&flashes[0], filename);
  698. }
  699. // FIXME: flash writes stay enabled!
  700. rc = 1;
  701. goto cli_mfg_silent_exit;
  702. }
  703. fill_flash = &flashes[0];
  704. check_chip_supported(fill_flash);
  705. size = fill_flash->total_size * 1024;
  706. if (check_max_decode((buses_supported & fill_flash->bustype), size) &&
  707. (!force)) {
  708. msg_gerr("Chip is too big for this programmer "
  709. "(-V gives details). Use --force to override.\n");
  710. rc = 1;
  711. goto cli_mfg_silent_exit;
  712. }
  713. if (!(read_it | write_it | verify_it | erase_it | flash_name |
  714. get_size | set_wp_range | set_wp_region | set_wp_enable |
  715. set_wp_disable | wp_status | wp_list | extract_it)) {
  716. msg_gerr("No operations were specified.\n");
  717. // FIXME: flash writes stay enabled!
  718. rc = 0;
  719. goto cli_mfg_silent_exit;
  720. }
  721. if (set_wp_enable && set_wp_disable) {
  722. msg_ginfo("Error: --wp-enable and --wp-disable are mutually exclusive\n");
  723. rc = 1;
  724. goto cli_mfg_silent_exit;
  725. }
  726. /*
  727. * Common rules for -r/-w/-v syntax parsing:
  728. * - If no filename is specified at all, quit.
  729. * - If no filename is specified for -r/-w/-v, but files are specified
  730. * for -i, then the number of file arguments for -i options must be
  731. * equal to the total number of -i options.
  732. *
  733. * Rules for reading:
  734. * - If files are specified for -i args but not -r, do partial reads for
  735. * each -i arg, creating a new file for each region. Each -i option
  736. * must specify a filename.
  737. * - If filenames are specified for -r and -i args, then:
  738. * - Do partial read for each -i arg, creating a new file for
  739. * each region where a filename is provided (-i region:filename).
  740. * - Create a ROM-sized file with partially filled content. For each
  741. * -i arg, fill the corresponding offset with content from ROM.
  742. *
  743. * Rules for writing and verifying:
  744. * - If files are specified for both -w/-v and -i args, -i files take
  745. * priority. (Note: We determined this was the most useful syntax for
  746. * chromium.org's flashrom after some discussion. Upstream may wish
  747. * to quit in this case due to ambiguity).
  748. * See: http://crbug.com/263495.
  749. * - If file is specified for -w/-v and no files are specified with -i
  750. * args, then the file is to be used for writing/verifying the entire
  751. * ROM.
  752. * - If files are specified for -i args but not -w, do partial writes
  753. * for each -i arg. Likewise for -v and -i args. All -i args must
  754. * supply a filename. Any omission is considered ambiguous.
  755. * - Regions with a filename associated must not overlap. This is also
  756. * considered ambiguous. Note: This is checked later since it requires
  757. * processing the layout/fmap first.
  758. */
  759. if (read_it || write_it || verify_it) {
  760. char op;
  761. if (read_it)
  762. op = 'r';
  763. else if (write_it)
  764. op = 'w';
  765. else if (verify_it)
  766. op = 'v';
  767. else {
  768. msg_gerr("Error: Unknown file operation\n");
  769. rc = 1;
  770. goto cli_mfg_silent_exit;
  771. }
  772. if (!filename) {
  773. if (!get_num_include_args()) {
  774. msg_gerr("Error: No file specified for -%c.\n",
  775. op);
  776. rc = 1;
  777. goto cli_mfg_silent_exit;
  778. }
  779. if (num_include_files() != get_num_include_args()) {
  780. msg_gerr("Error: One or more -i arguments is "
  781. " missing a filename.\n");
  782. rc = 1;
  783. goto cli_mfg_silent_exit;
  784. }
  785. }
  786. }
  787. /* Always verify write operations unless -n is used. */
  788. if (write_it && !dont_verify_it)
  789. if (!verify_it) verify_it = VERIFY_FULL;
  790. /* Partial verify requested, but no -i args: Need to full verify. */
  791. if (verify_it == VERIFY_PARTIAL && !specified_partition())
  792. verify_it = VERIFY_FULL;
  793. /* Note: set_wp_disable should be done before setting the range */
  794. if (set_wp_disable) {
  795. if (fill_flash->wp && fill_flash->wp->disable) {
  796. rc |= fill_flash->wp->disable(fill_flash);
  797. } else {
  798. msg_gerr("Error: write protect is not supported "
  799. "on this flash chip.\n");
  800. rc = 1;
  801. goto cli_mfg_silent_exit;
  802. }
  803. }
  804. if (flash_name) {
  805. if (fill_flash->vendor && fill_flash->name) {
  806. msg_ginfo("vendor=\"%s\" name=\"%s\"\n",
  807. fill_flash->vendor, fill_flash->name);
  808. goto cli_mfg_silent_exit;
  809. } else {
  810. rc = -1;
  811. goto cli_mfg_silent_exit;
  812. }
  813. }
  814. /* If the user doesn't specify any -i argument, then we can skip the
  815. * fmap parsing to speed up. */
  816. if (get_num_include_args() == 0 && !extract_it) {
  817. msg_gdbg("No -i argument is specified, set ignore_fmap.\n");
  818. set_ignore_fmap = 1;
  819. }
  820. /* add entries for regions specified in flashmap */
  821. if (!set_ignore_fmap && add_fmap_entries(fill_flash) < 0) {
  822. rc = 1;
  823. goto cli_mfg_silent_exit;
  824. }
  825. if (set_wp_range || set_wp_region) {
  826. if (set_wp_range && set_wp_region) {
  827. msg_gerr("Error: Cannot use both --wp-range and "
  828. "--wp-region simultaneously.\n");
  829. rc = 1;
  830. goto cli_mfg_silent_exit;
  831. }
  832. if (!fill_flash->wp || !fill_flash->wp->set_range) {
  833. msg_gerr("Error: write protect is not supported "
  834. "on this flash chip.\n");
  835. rc = 1;
  836. goto cli_mfg_silent_exit;
  837. }
  838. }
  839. /* Note: set_wp_range must happen before set_wp_enable */
  840. if (set_wp_range) {
  841. unsigned int start, len;
  842. char *endptr = NULL;
  843. if ((argc - optind) != 2) {
  844. msg_gerr("Error: invalid number of arguments\n");
  845. rc = 1;
  846. goto cli_mfg_silent_exit;
  847. }
  848. /* FIXME: add some error checking */
  849. start = strtoul(argv[optind], &endptr, 0);
  850. if (errno == ERANGE || errno == EINVAL || *endptr != '\0') {
  851. msg_gerr("Error: value \"%s\" invalid\n", argv[optind]);
  852. rc = 1;
  853. goto cli_mfg_silent_exit;
  854. }
  855. len = strtoul(argv[optind + 1], &endptr, 0);
  856. if (errno == ERANGE || errno == EINVAL || *endptr != '\0') {
  857. msg_gerr("Error: value \"%s\" invalid\n", argv[optind + 1]);
  858. rc = 1;
  859. goto cli_mfg_silent_exit;
  860. }
  861. rc |= fill_flash->wp->set_range(fill_flash, start, len);
  862. }
  863. if (set_wp_region && wp_region) {
  864. int n;
  865. romlayout_t entry;
  866. n = find_romentry(wp_region);
  867. if (n < 0) {
  868. msg_gerr("Error: Unable to find region \"%s\"\n",
  869. wp_region);
  870. rc = 1;
  871. goto cli_mfg_silent_exit;
  872. }
  873. if (fill_romentry(&entry, n)) {
  874. rc = 1;
  875. goto cli_mfg_silent_exit;
  876. }
  877. rc |= fill_flash->wp->set_range(fill_flash,
  878. entry.start, entry.end - entry.start + 1);
  879. free(wp_region);
  880. }
  881. if (!rc && set_wp_enable) {
  882. enum wp_mode wp_mode;
  883. if (wp_mode_opt)
  884. wp_mode = get_wp_mode(wp_mode_opt);
  885. else
  886. wp_mode = WP_MODE_HARDWARE; /* default */
  887. if (wp_mode == WP_MODE_UNKNOWN) {
  888. msg_gerr("Error: Invalid WP mode: \"%s\"\n", wp_mode_opt);
  889. rc = 1;
  890. goto cli_mfg_silent_exit;
  891. }
  892. if (fill_flash->wp && fill_flash->wp->enable) {
  893. rc |= fill_flash->wp->enable(fill_flash, wp_mode);
  894. } else {
  895. msg_gerr("Error: write protect is not supported "
  896. "on this flash chip.\n");
  897. rc = 1;
  898. goto cli_mfg_silent_exit;
  899. }
  900. }
  901. if (get_size) {
  902. msg_ginfo("%d\n", fill_flash->total_size * 1024);
  903. goto cli_mfg_silent_exit;
  904. }
  905. if (wp_status) {
  906. if (fill_flash->wp && fill_flash->wp->wp_status) {
  907. rc |= fill_flash->wp->wp_status(fill_flash);
  908. } else {
  909. msg_gerr("Error: write protect is not supported "
  910. "on this flash chip.\n");
  911. rc = 1;
  912. }
  913. goto cli_mfg_silent_exit;
  914. }
  915. if (wp_list) {
  916. msg_ginfo("Valid write protection ranges:\n");
  917. if (fill_flash->wp && fill_flash->wp->list_ranges) {
  918. rc |= fill_flash->wp->list_ranges(fill_flash);
  919. } else {
  920. msg_gerr("Error: write protect is not supported "
  921. "on this flash chip.\n");
  922. rc = 1;
  923. }
  924. goto cli_mfg_silent_exit;
  925. }
  926. if (read_it || write_it || erase_it || verify_it || extract_it) {
  927. rc = doit(fill_flash, force, filename,
  928. read_it, write_it, erase_it, verify_it,
  929. extract_it, diff_file);
  930. }
  931. msg_ginfo("%s\n", rc ? "FAILED" : "SUCCESS");
  932. cli_mfg_silent_exit:
  933. programmer_shutdown(); /* must be done after chip_restore() */
  934. #if USE_BIG_LOCK == 1
  935. if (!set_ignore_lock)
  936. release_big_lock();
  937. #endif
  938. if (restore_power_management()) {
  939. msg_gerr("Unable to re-enable power management\n");
  940. rc |= 1;
  941. }
  942. #ifndef STANDALONE
  943. rc |= close_logfile();
  944. #endif /* !STANDALONE */
  945. return rc;
  946. }