ifdtool.c 26 KB

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