ifdtool.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. /*
  2. * ifdtool - Manage Intel Firmware Descriptor information
  3. *
  4. * Copyright 2014 Google, Inc
  5. *
  6. * SPDX-License-Identifier: GPL-2.0
  7. *
  8. * From Coreboot project, but it got a serious code clean-up
  9. * and a few new features
  10. */
  11. #include <assert.h>
  12. #include <fcntl.h>
  13. #include <getopt.h>
  14. #include <stdbool.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <libfdt.h>
  22. #include "ifdtool.h"
  23. #undef DEBUG
  24. #ifdef DEBUG
  25. #define debug(fmt, args...) printf(fmt, ##args)
  26. #else
  27. #define debug(fmt, args...)
  28. #endif
  29. #define FD_SIGNATURE 0x0FF0A55A
  30. #define FLREG_BASE(reg) ((reg & 0x00000fff) << 12);
  31. #define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff);
  32. struct input_file {
  33. char *fname;
  34. unsigned int addr;
  35. };
  36. /**
  37. * find_fd() - Find the flash description in the ROM image
  38. *
  39. * @image: Pointer to image
  40. * @size: Size of image in bytes
  41. * @return pointer to structure, or NULL if not found
  42. */
  43. static struct fdbar_t *find_fd(char *image, int size)
  44. {
  45. uint32_t *ptr, *end;
  46. /* Scan for FD signature */
  47. for (ptr = (uint32_t *)image, end = ptr + size / 4; ptr < end; ptr++) {
  48. if (*ptr == FD_SIGNATURE)
  49. break;
  50. }
  51. if (ptr == end) {
  52. printf("No Flash Descriptor found in this image\n");
  53. return NULL;
  54. }
  55. debug("Found Flash Descriptor signature at 0x%08lx\n",
  56. (char *)ptr - image);
  57. return (struct fdbar_t *)ptr;
  58. }
  59. /**
  60. * get_region() - Get information about the selected region
  61. *
  62. * @frba: Flash region list
  63. * @region_type: Type of region (0..MAX_REGIONS-1)
  64. * @region: Region information is written here
  65. * @return 0 if OK, else -ve
  66. */
  67. static int get_region(struct frba_t *frba, int region_type,
  68. struct region_t *region)
  69. {
  70. if (region_type >= MAX_REGIONS) {
  71. fprintf(stderr, "Invalid region type.\n");
  72. return -1;
  73. }
  74. region->base = FLREG_BASE(frba->flreg[region_type]);
  75. region->limit = FLREG_LIMIT(frba->flreg[region_type]);
  76. region->size = region->limit - region->base + 1;
  77. return 0;
  78. }
  79. static const char *region_name(int region_type)
  80. {
  81. static const char *const regions[] = {
  82. "Flash Descriptor",
  83. "BIOS",
  84. "Intel ME",
  85. "GbE",
  86. "Platform Data"
  87. };
  88. assert(region_type < MAX_REGIONS);
  89. return regions[region_type];
  90. }
  91. static const char *region_filename(int region_type)
  92. {
  93. static const char *const region_filenames[] = {
  94. "flashregion_0_flashdescriptor.bin",
  95. "flashregion_1_bios.bin",
  96. "flashregion_2_intel_me.bin",
  97. "flashregion_3_gbe.bin",
  98. "flashregion_4_platform_data.bin"
  99. };
  100. assert(region_type < MAX_REGIONS);
  101. return region_filenames[region_type];
  102. }
  103. static int dump_region(int num, struct frba_t *frba)
  104. {
  105. struct region_t region;
  106. int ret;
  107. ret = get_region(frba, num, &region);
  108. if (ret)
  109. return ret;
  110. printf(" Flash Region %d (%s): %08x - %08x %s\n",
  111. num, region_name(num), region.base, region.limit,
  112. region.size < 1 ? "(unused)" : "");
  113. return ret;
  114. }
  115. static void dump_frba(struct frba_t *frba)
  116. {
  117. int i;
  118. printf("Found Region Section\n");
  119. for (i = 0; i < MAX_REGIONS; i++) {
  120. printf("FLREG%d: 0x%08x\n", i, frba->flreg[i]);
  121. dump_region(i, frba);
  122. }
  123. }
  124. static void decode_spi_frequency(unsigned int freq)
  125. {
  126. switch (freq) {
  127. case SPI_FREQUENCY_20MHZ:
  128. printf("20MHz");
  129. break;
  130. case SPI_FREQUENCY_33MHZ:
  131. printf("33MHz");
  132. break;
  133. case SPI_FREQUENCY_50MHZ:
  134. printf("50MHz");
  135. break;
  136. default:
  137. printf("unknown<%x>MHz", freq);
  138. }
  139. }
  140. static void decode_component_density(unsigned int density)
  141. {
  142. switch (density) {
  143. case COMPONENT_DENSITY_512KB:
  144. printf("512KiB");
  145. break;
  146. case COMPONENT_DENSITY_1MB:
  147. printf("1MiB");
  148. break;
  149. case COMPONENT_DENSITY_2MB:
  150. printf("2MiB");
  151. break;
  152. case COMPONENT_DENSITY_4MB:
  153. printf("4MiB");
  154. break;
  155. case COMPONENT_DENSITY_8MB:
  156. printf("8MiB");
  157. break;
  158. case COMPONENT_DENSITY_16MB:
  159. printf("16MiB");
  160. break;
  161. default:
  162. printf("unknown<%x>MiB", density);
  163. }
  164. }
  165. static void dump_fcba(struct fcba_t *fcba)
  166. {
  167. printf("\nFound Component Section\n");
  168. printf("FLCOMP 0x%08x\n", fcba->flcomp);
  169. printf(" Dual Output Fast Read Support: %ssupported\n",
  170. (fcba->flcomp & (1 << 30)) ? "" : "not ");
  171. printf(" Read ID/Read Status Clock Frequency: ");
  172. decode_spi_frequency((fcba->flcomp >> 27) & 7);
  173. printf("\n Write/Erase Clock Frequency: ");
  174. decode_spi_frequency((fcba->flcomp >> 24) & 7);
  175. printf("\n Fast Read Clock Frequency: ");
  176. decode_spi_frequency((fcba->flcomp >> 21) & 7);
  177. printf("\n Fast Read Support: %ssupported",
  178. (fcba->flcomp & (1 << 20)) ? "" : "not ");
  179. printf("\n Read Clock Frequency: ");
  180. decode_spi_frequency((fcba->flcomp >> 17) & 7);
  181. printf("\n Component 2 Density: ");
  182. decode_component_density((fcba->flcomp >> 3) & 7);
  183. printf("\n Component 1 Density: ");
  184. decode_component_density(fcba->flcomp & 7);
  185. printf("\n");
  186. printf("FLILL 0x%08x\n", fcba->flill);
  187. printf(" Invalid Instruction 3: 0x%02x\n",
  188. (fcba->flill >> 24) & 0xff);
  189. printf(" Invalid Instruction 2: 0x%02x\n",
  190. (fcba->flill >> 16) & 0xff);
  191. printf(" Invalid Instruction 1: 0x%02x\n",
  192. (fcba->flill >> 8) & 0xff);
  193. printf(" Invalid Instruction 0: 0x%02x\n",
  194. fcba->flill & 0xff);
  195. printf("FLPB 0x%08x\n", fcba->flpb);
  196. printf(" Flash Partition Boundary Address: 0x%06x\n\n",
  197. (fcba->flpb & 0xfff) << 12);
  198. }
  199. static void dump_fpsba(struct fpsba_t *fpsba)
  200. {
  201. int i;
  202. printf("Found PCH Strap Section\n");
  203. for (i = 0; i < MAX_STRAPS; i++)
  204. printf("PCHSTRP%-2d: 0x%08x\n", i, fpsba->pchstrp[i]);
  205. }
  206. static const char *get_enabled(int flag)
  207. {
  208. return flag ? "enabled" : "disabled";
  209. }
  210. static void decode_flmstr(uint32_t flmstr)
  211. {
  212. printf(" Platform Data Region Write Access: %s\n",
  213. get_enabled(flmstr & (1 << 28)));
  214. printf(" GbE Region Write Access: %s\n",
  215. get_enabled(flmstr & (1 << 27)));
  216. printf(" Intel ME Region Write Access: %s\n",
  217. get_enabled(flmstr & (1 << 26)));
  218. printf(" Host CPU/BIOS Region Write Access: %s\n",
  219. get_enabled(flmstr & (1 << 25)));
  220. printf(" Flash Descriptor Write Access: %s\n",
  221. get_enabled(flmstr & (1 << 24)));
  222. printf(" Platform Data Region Read Access: %s\n",
  223. get_enabled(flmstr & (1 << 20)));
  224. printf(" GbE Region Read Access: %s\n",
  225. get_enabled(flmstr & (1 << 19)));
  226. printf(" Intel ME Region Read Access: %s\n",
  227. get_enabled(flmstr & (1 << 18)));
  228. printf(" Host CPU/BIOS Region Read Access: %s\n",
  229. get_enabled(flmstr & (1 << 17)));
  230. printf(" Flash Descriptor Read Access: %s\n",
  231. get_enabled(flmstr & (1 << 16)));
  232. printf(" Requester ID: 0x%04x\n\n",
  233. flmstr & 0xffff);
  234. }
  235. static void dump_fmba(struct fmba_t *fmba)
  236. {
  237. printf("Found Master Section\n");
  238. printf("FLMSTR1: 0x%08x (Host CPU/BIOS)\n", fmba->flmstr1);
  239. decode_flmstr(fmba->flmstr1);
  240. printf("FLMSTR2: 0x%08x (Intel ME)\n", fmba->flmstr2);
  241. decode_flmstr(fmba->flmstr2);
  242. printf("FLMSTR3: 0x%08x (GbE)\n", fmba->flmstr3);
  243. decode_flmstr(fmba->flmstr3);
  244. }
  245. static void dump_fmsba(struct fmsba_t *fmsba)
  246. {
  247. int i;
  248. printf("Found Processor Strap Section\n");
  249. for (i = 0; i < 4; i++)
  250. printf("????: 0x%08x\n", fmsba->data[0]);
  251. }
  252. static void dump_jid(uint32_t jid)
  253. {
  254. printf(" SPI Component Device ID 1: 0x%02x\n",
  255. (jid >> 16) & 0xff);
  256. printf(" SPI Component Device ID 0: 0x%02x\n",
  257. (jid >> 8) & 0xff);
  258. printf(" SPI Component Vendor ID: 0x%02x\n",
  259. jid & 0xff);
  260. }
  261. static void dump_vscc(uint32_t vscc)
  262. {
  263. printf(" Lower Erase Opcode: 0x%02x\n",
  264. vscc >> 24);
  265. printf(" Lower Write Enable on Write Status: 0x%02x\n",
  266. vscc & (1 << 20) ? 0x06 : 0x50);
  267. printf(" Lower Write Status Required: %s\n",
  268. vscc & (1 << 19) ? "Yes" : "No");
  269. printf(" Lower Write Granularity: %d bytes\n",
  270. vscc & (1 << 18) ? 64 : 1);
  271. printf(" Lower Block / Sector Erase Size: ");
  272. switch ((vscc >> 16) & 0x3) {
  273. case 0:
  274. printf("256 Byte\n");
  275. break;
  276. case 1:
  277. printf("4KB\n");
  278. break;
  279. case 2:
  280. printf("8KB\n");
  281. break;
  282. case 3:
  283. printf("64KB\n");
  284. break;
  285. }
  286. printf(" Upper Erase Opcode: 0x%02x\n",
  287. (vscc >> 8) & 0xff);
  288. printf(" Upper Write Enable on Write Status: 0x%02x\n",
  289. vscc & (1 << 4) ? 0x06 : 0x50);
  290. printf(" Upper Write Status Required: %s\n",
  291. vscc & (1 << 3) ? "Yes" : "No");
  292. printf(" Upper Write Granularity: %d bytes\n",
  293. vscc & (1 << 2) ? 64 : 1);
  294. printf(" Upper Block / Sector Erase Size: ");
  295. switch (vscc & 0x3) {
  296. case 0:
  297. printf("256 Byte\n");
  298. break;
  299. case 1:
  300. printf("4KB\n");
  301. break;
  302. case 2:
  303. printf("8KB\n");
  304. break;
  305. case 3:
  306. printf("64KB\n");
  307. break;
  308. }
  309. }
  310. static void dump_vtba(struct vtba_t *vtba, int vtl)
  311. {
  312. int i;
  313. int num = (vtl >> 1) < 8 ? (vtl >> 1) : 8;
  314. printf("ME VSCC table:\n");
  315. for (i = 0; i < num; i++) {
  316. printf(" JID%d: 0x%08x\n", i, vtba->entry[i].jid);
  317. dump_jid(vtba->entry[i].jid);
  318. printf(" VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc);
  319. dump_vscc(vtba->entry[i].vscc);
  320. }
  321. printf("\n");
  322. }
  323. static void dump_oem(uint8_t *oem)
  324. {
  325. int i, j;
  326. printf("OEM Section:\n");
  327. for (i = 0; i < 4; i++) {
  328. printf("%02x:", i << 4);
  329. for (j = 0; j < 16; j++)
  330. printf(" %02x", oem[(i<<4)+j]);
  331. printf("\n");
  332. }
  333. printf("\n");
  334. }
  335. /**
  336. * dump_fd() - Display a dump of the full flash description
  337. *
  338. * @image: Pointer to image
  339. * @size: Size of image in bytes
  340. * @return 0 if OK, -1 on error
  341. */
  342. static int dump_fd(char *image, int size)
  343. {
  344. struct fdbar_t *fdb = find_fd(image, size);
  345. if (!fdb)
  346. return -1;
  347. printf("FLMAP0: 0x%08x\n", fdb->flmap0);
  348. printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7);
  349. printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
  350. printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
  351. printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4);
  352. printf("FLMAP1: 0x%08x\n", fdb->flmap1);
  353. printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
  354. printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
  355. printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3);
  356. printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4);
  357. printf("FLMAP2: 0x%08x\n", fdb->flmap2);
  358. printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
  359. printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4);
  360. printf("FLUMAP1: 0x%08x\n", fdb->flumap1);
  361. printf(" Intel ME VSCC Table Length (VTL): %d\n",
  362. (fdb->flumap1 >> 8) & 0xff);
  363. printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",
  364. (fdb->flumap1 & 0xff) << 4);
  365. dump_vtba((struct vtba_t *)
  366. (image + ((fdb->flumap1 & 0xff) << 4)),
  367. (fdb->flumap1 >> 8) & 0xff);
  368. dump_oem((uint8_t *)image + 0xf00);
  369. dump_frba((struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff)
  370. << 4)));
  371. dump_fcba((struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)));
  372. dump_fpsba((struct fpsba_t *)
  373. (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
  374. dump_fmba((struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)));
  375. dump_fmsba((struct fmsba_t *)(image + (((fdb->flmap2) & 0xff) << 4)));
  376. return 0;
  377. }
  378. /**
  379. * write_regions() - Write each region from an image to its own file
  380. *
  381. * The filename to use in each case is fixed - see region_filename()
  382. *
  383. * @image: Pointer to image
  384. * @size: Size of image in bytes
  385. * @return 0 if OK, -ve on error
  386. */
  387. static int write_regions(char *image, int size)
  388. {
  389. struct fdbar_t *fdb;
  390. struct frba_t *frba;
  391. int ret = 0;
  392. int i;
  393. fdb = find_fd(image, size);
  394. if (!fdb)
  395. return -1;
  396. frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4));
  397. for (i = 0; i < MAX_REGIONS; i++) {
  398. struct region_t region;
  399. int region_fd;
  400. ret = get_region(frba, i, &region);
  401. if (ret)
  402. return ret;
  403. dump_region(i, frba);
  404. if (region.size <= 0)
  405. continue;
  406. region_fd = open(region_filename(i),
  407. O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
  408. S_IWUSR | S_IRGRP | S_IROTH);
  409. if (write(region_fd, image + region.base, region.size) !=
  410. region.size) {
  411. perror("Error while writing");
  412. ret = -1;
  413. }
  414. close(region_fd);
  415. }
  416. return ret;
  417. }
  418. static int perror_fname(const char *fmt, const char *fname)
  419. {
  420. char msg[strlen(fmt) + strlen(fname) + 1];
  421. sprintf(msg, fmt, fname);
  422. perror(msg);
  423. return -1;
  424. }
  425. /**
  426. * write_image() - Write the image to a file
  427. *
  428. * @filename: Filename to use for the image
  429. * @image: Pointer to image
  430. * @size: Size of image in bytes
  431. * @return 0 if OK, -ve on error
  432. */
  433. static int write_image(char *filename, char *image, int size)
  434. {
  435. int new_fd;
  436. debug("Writing new image to %s\n", filename);
  437. new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
  438. S_IWUSR | S_IRGRP | S_IROTH);
  439. if (new_fd < 0)
  440. return perror_fname("Could not open file '%s'", filename);
  441. if (write(new_fd, image, size) != size)
  442. return perror_fname("Could not write file '%s'", filename);
  443. close(new_fd);
  444. return 0;
  445. }
  446. /**
  447. * set_spi_frequency() - Set the SPI frequency to use when booting
  448. *
  449. * Several frequencies are supported, some of which work with fast devices.
  450. * For SPI emulators, the slowest (SPI_FREQUENCY_20MHZ) is often used. The
  451. * Intel boot system uses this information somehow on boot.
  452. *
  453. * The image is updated with the supplied value
  454. *
  455. * @image: Pointer to image
  456. * @size: Size of image in bytes
  457. * @freq: SPI frequency to use
  458. */
  459. static void set_spi_frequency(char *image, int size, enum spi_frequency freq)
  460. {
  461. struct fdbar_t *fdb = find_fd(image, size);
  462. struct fcba_t *fcba;
  463. fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4));
  464. /* clear bits 21-29 */
  465. fcba->flcomp &= ~0x3fe00000;
  466. /* Read ID and Read Status Clock Frequency */
  467. fcba->flcomp |= freq << 27;
  468. /* Write and Erase Clock Frequency */
  469. fcba->flcomp |= freq << 24;
  470. /* Fast Read Clock Frequency */
  471. fcba->flcomp |= freq << 21;
  472. }
  473. /**
  474. * set_em100_mode() - Set a SPI frequency that will work with Dediprog EM100
  475. *
  476. * @image: Pointer to image
  477. * @size: Size of image in bytes
  478. */
  479. static void set_em100_mode(char *image, int size)
  480. {
  481. struct fdbar_t *fdb = find_fd(image, size);
  482. struct fcba_t *fcba;
  483. fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4));
  484. fcba->flcomp &= ~(1 << 30);
  485. set_spi_frequency(image, size, SPI_FREQUENCY_20MHZ);
  486. }
  487. /**
  488. * lock_descriptor() - Lock the NE descriptor so it cannot be updated
  489. *
  490. * @image: Pointer to image
  491. * @size: Size of image in bytes
  492. */
  493. static void lock_descriptor(char *image, int size)
  494. {
  495. struct fdbar_t *fdb = find_fd(image, size);
  496. struct fmba_t *fmba;
  497. /*
  498. * TODO: Dynamically take Platform Data Region and GbE Region into
  499. * account.
  500. */
  501. fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4));
  502. fmba->flmstr1 = 0x0a0b0000;
  503. fmba->flmstr2 = 0x0c0d0000;
  504. fmba->flmstr3 = 0x08080118;
  505. }
  506. /**
  507. * unlock_descriptor() - Lock the NE descriptor so it can be updated
  508. *
  509. * @image: Pointer to image
  510. * @size: Size of image in bytes
  511. */
  512. static void unlock_descriptor(char *image, int size)
  513. {
  514. struct fdbar_t *fdb = find_fd(image, size);
  515. struct fmba_t *fmba;
  516. fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4));
  517. fmba->flmstr1 = 0xffff0000;
  518. fmba->flmstr2 = 0xffff0000;
  519. fmba->flmstr3 = 0x08080118;
  520. }
  521. /**
  522. * open_for_read() - Open a file for reading
  523. *
  524. * @fname: Filename to open
  525. * @sizep: Returns file size in bytes
  526. * @return 0 if OK, -1 on error
  527. */
  528. int open_for_read(const char *fname, int *sizep)
  529. {
  530. int fd = open(fname, O_RDONLY);
  531. struct stat buf;
  532. if (fd == -1)
  533. return perror_fname("Could not open file '%s'", fname);
  534. if (fstat(fd, &buf) == -1)
  535. return perror_fname("Could not stat file '%s'", fname);
  536. *sizep = buf.st_size;
  537. debug("File %s is %d bytes\n", fname, *sizep);
  538. return fd;
  539. }
  540. /**
  541. * inject_region() - Add a file to an image region
  542. *
  543. * This puts a file into a particular region of the flash. Several pre-defined
  544. * regions are used.
  545. *
  546. * @image: Pointer to image
  547. * @size: Size of image in bytes
  548. * @region_type: Region where the file should be added
  549. * @region_fname: Filename to add to the image
  550. * @return 0 if OK, -ve on error
  551. */
  552. int inject_region(char *image, int size, int region_type, char *region_fname)
  553. {
  554. struct fdbar_t *fdb = find_fd(image, size);
  555. struct region_t region;
  556. struct frba_t *frba;
  557. int region_size;
  558. int offset = 0;
  559. int region_fd;
  560. int ret;
  561. if (!fdb)
  562. exit(EXIT_FAILURE);
  563. frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4));
  564. ret = get_region(frba, region_type, &region);
  565. if (ret)
  566. return -1;
  567. if (region.size <= 0xfff) {
  568. fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
  569. region_name(region_type));
  570. return -1;
  571. }
  572. region_fd = open_for_read(region_fname, &region_size);
  573. if (region_fd < 0)
  574. return region_fd;
  575. if ((region_size > region.size) ||
  576. ((region_type != 1) && (region_size > region.size))) {
  577. fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Not injecting.\n",
  578. region_name(region_type), region.size,
  579. region.size, region_size, region_size);
  580. return -1;
  581. }
  582. if ((region_type == 1) && (region_size < region.size)) {
  583. fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Padding before injecting.\n",
  584. region_name(region_type), region.size,
  585. region.size, region_size, region_size);
  586. offset = region.size - region_size;
  587. memset(image + region.base, 0xff, offset);
  588. }
  589. if (size < region.base + offset + region_size) {
  590. fprintf(stderr, "Output file is too small. (%d < %d)\n",
  591. size, region.base + offset + region_size);
  592. return -1;
  593. }
  594. if (read(region_fd, image + region.base + offset, region_size)
  595. != region_size) {
  596. perror("Could not read file");
  597. return -1;
  598. }
  599. close(region_fd);
  600. debug("Adding %s as the %s section\n", region_fname,
  601. region_name(region_type));
  602. return 0;
  603. }
  604. /**
  605. * write_data() - Write some raw data into a region
  606. *
  607. * This puts a file into a particular place in the flash, ignoring the
  608. * regions. Be careful not to overwrite something important.
  609. *
  610. * @image: Pointer to image
  611. * @size: Size of image in bytes
  612. * @addr: x86 ROM address to put file. The ROM ends at
  613. * 0xffffffff so use an address relative to that. For an
  614. * 8MB ROM the start address is 0xfff80000.
  615. * @write_fname: Filename to add to the image
  616. * @offset_uboot_top: Offset of the top of U-Boot
  617. * @offset_uboot_start: Offset of the start of U-Boot
  618. * @return number of bytes written if OK, -ve on error
  619. */
  620. static int write_data(char *image, int size, unsigned int addr,
  621. const char *write_fname, int offset_uboot_top,
  622. int offset_uboot_start)
  623. {
  624. int write_fd, write_size;
  625. int offset;
  626. write_fd = open_for_read(write_fname, &write_size);
  627. if (write_fd < 0)
  628. return write_fd;
  629. offset = (uint32_t)(addr + size);
  630. if (offset_uboot_top) {
  631. if (offset_uboot_start < offset &&
  632. offset_uboot_top >= offset) {
  633. fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
  634. write_fname);
  635. fprintf(stderr,
  636. "U-Boot finishes at offset %x, file starts at %x\n",
  637. offset_uboot_top, offset);
  638. return -EXDEV;
  639. }
  640. if (offset_uboot_start > offset &&
  641. offset_uboot_start <= offset + write_size) {
  642. fprintf(stderr, "U-Boot image overlaps with region '%s'\n",
  643. write_fname);
  644. fprintf(stderr,
  645. "U-Boot starts at offset %x, file finishes at %x\n",
  646. offset_uboot_start, offset + write_size);
  647. return -EXDEV;
  648. }
  649. }
  650. debug("Writing %s to offset %#x\n", write_fname, offset);
  651. if (offset < 0 || offset + write_size > size) {
  652. fprintf(stderr, "Output file is too small. (%d < %d)\n",
  653. size, offset + write_size);
  654. return -1;
  655. }
  656. if (read(write_fd, image + offset, write_size) != write_size) {
  657. perror("Could not read file");
  658. return -1;
  659. }
  660. close(write_fd);
  661. return write_size;
  662. }
  663. static void print_version(void)
  664. {
  665. printf("ifdtool v%s -- ", IFDTOOL_VERSION);
  666. printf("Copyright (C) 2014 Google Inc.\n\n");
  667. printf("SPDX-License-Identifier: GPL-2.0+\n");
  668. }
  669. static void print_usage(const char *name)
  670. {
  671. printf("usage: %s [-vhdix?] <filename> [<outfile>]\n", name);
  672. printf("\n"
  673. " -d | --dump: dump intel firmware descriptor\n"
  674. " -x | --extract: extract intel fd modules\n"
  675. " -i | --inject <region>:<module> inject file <module> into region <region>\n"
  676. " -w | --write <addr>:<file> write file to appear at memory address <addr>\n"
  677. " multiple files can be written simultaneously\n"
  678. " -s | --spifreq <20|33|50> set the SPI frequency\n"
  679. " -e | --em100 set SPI frequency to 20MHz and disable\n"
  680. " Dual Output Fast Read Support\n"
  681. " -l | --lock Lock firmware descriptor and ME region\n"
  682. " -u | --unlock Unlock firmware descriptor and ME region\n"
  683. " -r | --romsize Specify ROM size\n"
  684. " -D | --write-descriptor <file> Write descriptor at base\n"
  685. " -c | --create Create a new empty image\n"
  686. " -v | --version: print the version\n"
  687. " -h | --help: print this help\n\n"
  688. "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
  689. "\n");
  690. }
  691. /**
  692. * get_two_words() - Convert a string into two words separated by :
  693. *
  694. * The supplied string is split at ':', two substrings are allocated and
  695. * returned.
  696. *
  697. * @str: String to split
  698. * @firstp: Returns first string
  699. * @secondp: Returns second string
  700. * @return 0 if OK, -ve if @str does not have a :
  701. */
  702. static int get_two_words(const char *str, char **firstp, char **secondp)
  703. {
  704. const char *p;
  705. p = strchr(str, ':');
  706. if (!p)
  707. return -1;
  708. *firstp = strdup(str);
  709. (*firstp)[p - str] = '\0';
  710. *secondp = strdup(p + 1);
  711. return 0;
  712. }
  713. int main(int argc, char *argv[])
  714. {
  715. int opt, option_index = 0;
  716. int mode_dump = 0, mode_extract = 0, mode_inject = 0;
  717. int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
  718. int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
  719. int create = 0;
  720. char *region_type_string = NULL, *inject_fname = NULL;
  721. char *desc_fname = NULL, *addr_str = NULL;
  722. int region_type = -1, inputfreq = 0;
  723. enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
  724. struct input_file input_file[WRITE_MAX], *ifile, *fdt = NULL;
  725. unsigned char wr_idx, wr_num = 0;
  726. int rom_size = -1;
  727. bool write_it;
  728. char *filename;
  729. char *outfile = NULL;
  730. struct stat buf;
  731. int size = 0;
  732. bool have_uboot = false;
  733. int bios_fd;
  734. char *image;
  735. int ret;
  736. static struct option long_options[] = {
  737. {"create", 0, NULL, 'c'},
  738. {"dump", 0, NULL, 'd'},
  739. {"descriptor", 1, NULL, 'D'},
  740. {"em100", 0, NULL, 'e'},
  741. {"extract", 0, NULL, 'x'},
  742. {"fdt", 1, NULL, 'f'},
  743. {"inject", 1, NULL, 'i'},
  744. {"lock", 0, NULL, 'l'},
  745. {"romsize", 1, NULL, 'r'},
  746. {"spifreq", 1, NULL, 's'},
  747. {"unlock", 0, NULL, 'u'},
  748. {"uboot", 1, NULL, 'U'},
  749. {"write", 1, NULL, 'w'},
  750. {"version", 0, NULL, 'v'},
  751. {"help", 0, NULL, 'h'},
  752. {0, 0, 0, 0}
  753. };
  754. while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?",
  755. long_options, &option_index)) != EOF) {
  756. switch (opt) {
  757. case 'c':
  758. create = 1;
  759. break;
  760. case 'd':
  761. mode_dump = 1;
  762. break;
  763. case 'D':
  764. mode_write_descriptor = 1;
  765. desc_fname = optarg;
  766. break;
  767. case 'e':
  768. mode_em100 = 1;
  769. break;
  770. case 'i':
  771. if (get_two_words(optarg, &region_type_string,
  772. &inject_fname)) {
  773. print_usage(argv[0]);
  774. exit(EXIT_FAILURE);
  775. }
  776. if (!strcasecmp("Descriptor", region_type_string))
  777. region_type = 0;
  778. else if (!strcasecmp("BIOS", region_type_string))
  779. region_type = 1;
  780. else if (!strcasecmp("ME", region_type_string))
  781. region_type = 2;
  782. else if (!strcasecmp("GbE", region_type_string))
  783. region_type = 3;
  784. else if (!strcasecmp("Platform", region_type_string))
  785. region_type = 4;
  786. if (region_type == -1) {
  787. fprintf(stderr, "No such region type: '%s'\n\n",
  788. region_type_string);
  789. print_usage(argv[0]);
  790. exit(EXIT_FAILURE);
  791. }
  792. mode_inject = 1;
  793. break;
  794. case 'l':
  795. mode_locked = 1;
  796. break;
  797. case 'r':
  798. rom_size = strtol(optarg, NULL, 0);
  799. debug("ROM size %d\n", rom_size);
  800. break;
  801. case 's':
  802. /* Parse the requested SPI frequency */
  803. inputfreq = strtol(optarg, NULL, 0);
  804. switch (inputfreq) {
  805. case 20:
  806. spifreq = SPI_FREQUENCY_20MHZ;
  807. break;
  808. case 33:
  809. spifreq = SPI_FREQUENCY_33MHZ;
  810. break;
  811. case 50:
  812. spifreq = SPI_FREQUENCY_50MHZ;
  813. break;
  814. default:
  815. fprintf(stderr, "Invalid SPI Frequency: %d\n",
  816. inputfreq);
  817. print_usage(argv[0]);
  818. exit(EXIT_FAILURE);
  819. }
  820. mode_spifreq = 1;
  821. break;
  822. case 'u':
  823. mode_unlocked = 1;
  824. break;
  825. case 'v':
  826. print_version();
  827. exit(EXIT_SUCCESS);
  828. break;
  829. case 'w':
  830. case 'U':
  831. case 'f':
  832. ifile = &input_file[wr_num];
  833. mode_write = 1;
  834. if (wr_num < WRITE_MAX) {
  835. if (get_two_words(optarg, &addr_str,
  836. &ifile->fname)) {
  837. print_usage(argv[0]);
  838. exit(EXIT_FAILURE);
  839. }
  840. ifile->addr = strtoll(optarg, NULL, 0);
  841. wr_num++;
  842. } else {
  843. fprintf(stderr,
  844. "The number of files to write simultaneously exceeds the limitation (%d)\n",
  845. WRITE_MAX);
  846. }
  847. break;
  848. case 'x':
  849. mode_extract = 1;
  850. break;
  851. case 'h':
  852. case '?':
  853. default:
  854. print_usage(argv[0]);
  855. exit(EXIT_SUCCESS);
  856. break;
  857. }
  858. }
  859. if (mode_locked == 1 && mode_unlocked == 1) {
  860. fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
  861. exit(EXIT_FAILURE);
  862. }
  863. if (mode_inject == 1 && mode_write == 1) {
  864. fprintf(stderr, "Inject/Write are mutually exclusive\n");
  865. exit(EXIT_FAILURE);
  866. }
  867. if ((mode_dump + mode_extract + mode_inject +
  868. (mode_spifreq | mode_em100 | mode_unlocked |
  869. mode_locked)) > 1) {
  870. fprintf(stderr, "You may not specify more than one mode.\n\n");
  871. print_usage(argv[0]);
  872. exit(EXIT_FAILURE);
  873. }
  874. if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
  875. mode_em100 + mode_locked + mode_unlocked + mode_write +
  876. mode_write_descriptor) == 0 && !create) {
  877. fprintf(stderr, "You need to specify a mode.\n\n");
  878. print_usage(argv[0]);
  879. exit(EXIT_FAILURE);
  880. }
  881. if (create && rom_size == -1) {
  882. fprintf(stderr, "You need to specify a rom size when creating.\n\n");
  883. exit(EXIT_FAILURE);
  884. }
  885. if (optind + 1 != argc) {
  886. fprintf(stderr, "You need to specify a file.\n\n");
  887. print_usage(argv[0]);
  888. exit(EXIT_FAILURE);
  889. }
  890. if (have_uboot && !fdt) {
  891. fprintf(stderr,
  892. "You must supply a device tree file for U-Boot\n\n");
  893. print_usage(argv[0]);
  894. exit(EXIT_FAILURE);
  895. }
  896. filename = argv[optind];
  897. if (optind + 2 != argc)
  898. outfile = argv[optind + 1];
  899. if (create)
  900. bios_fd = open(filename, O_WRONLY | O_CREAT, 0666);
  901. else
  902. bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR);
  903. if (bios_fd == -1) {
  904. perror("Could not open file");
  905. exit(EXIT_FAILURE);
  906. }
  907. if (!create) {
  908. if (fstat(bios_fd, &buf) == -1) {
  909. perror("Could not stat file");
  910. exit(EXIT_FAILURE);
  911. }
  912. size = buf.st_size;
  913. }
  914. debug("File %s is %d bytes\n", filename, size);
  915. if (rom_size == -1)
  916. rom_size = size;
  917. image = malloc(rom_size);
  918. if (!image) {
  919. printf("Out of memory.\n");
  920. exit(EXIT_FAILURE);
  921. }
  922. memset(image, '\xff', rom_size);
  923. if (!create && read(bios_fd, image, size) != size) {
  924. perror("Could not read file");
  925. exit(EXIT_FAILURE);
  926. }
  927. if (size != rom_size) {
  928. debug("ROM size changed to %d bytes\n", rom_size);
  929. size = rom_size;
  930. }
  931. write_it = true;
  932. ret = 0;
  933. if (mode_dump) {
  934. ret = dump_fd(image, size);
  935. write_it = false;
  936. }
  937. if (mode_extract) {
  938. ret = write_regions(image, size);
  939. write_it = false;
  940. }
  941. if (mode_write_descriptor)
  942. ret = write_data(image, size, -size, desc_fname, 0, 0);
  943. if (mode_inject)
  944. ret = inject_region(image, size, region_type, inject_fname);
  945. if (mode_write) {
  946. int offset_uboot_top = 0;
  947. int offset_uboot_start = 0;
  948. for (wr_idx = 0; wr_idx < wr_num; wr_idx++) {
  949. ifile = &input_file[wr_idx];
  950. ret = write_data(image, size, ifile->addr,
  951. ifile->fname, offset_uboot_top,
  952. offset_uboot_start);
  953. if (ret < 0)
  954. break;
  955. }
  956. }
  957. if (mode_spifreq)
  958. set_spi_frequency(image, size, spifreq);
  959. if (mode_em100)
  960. set_em100_mode(image, size);
  961. if (mode_locked)
  962. lock_descriptor(image, size);
  963. if (mode_unlocked)
  964. unlock_descriptor(image, size);
  965. if (write_it) {
  966. if (outfile) {
  967. ret = write_image(outfile, image, size);
  968. } else {
  969. if (lseek(bios_fd, 0, SEEK_SET)) {
  970. perror("Error while seeking");
  971. ret = -1;
  972. }
  973. if (write(bios_fd, image, size) != size) {
  974. perror("Error while writing");
  975. ret = -1;
  976. }
  977. }
  978. }
  979. free(image);
  980. close(bios_fd);
  981. return ret < 0 ? 1 : 0;
  982. }