ifdtool.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  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. " -s | --spifreq <20|33|50> set the SPI frequency\n"
  645. " -e | --em100 set SPI frequency to 20MHz and disable\n"
  646. " Dual Output Fast Read Support\n"
  647. " -l | --lock Lock firmware descriptor and ME region\n"
  648. " -u | --unlock Unlock firmware descriptor and ME region\n"
  649. " -r | --romsize Specify ROM size\n"
  650. " -D | --write-descriptor <file> Write descriptor at base\n"
  651. " -c | --create Create a new empty image\n"
  652. " -v | --version: print the version\n"
  653. " -h | --help: print this help\n\n"
  654. "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
  655. "\n");
  656. }
  657. /**
  658. * get_two_words() - Convert a string into two words separated by :
  659. *
  660. * The supplied string is split at ':', two substrings are allocated and
  661. * returned.
  662. *
  663. * @str: String to split
  664. * @firstp: Returns first string
  665. * @secondp: Returns second string
  666. * @return 0 if OK, -ve if @str does not have a :
  667. */
  668. static int get_two_words(const char *str, char **firstp, char **secondp)
  669. {
  670. const char *p;
  671. p = strchr(str, ':');
  672. if (!p)
  673. return -1;
  674. *firstp = strdup(str);
  675. (*firstp)[p - str] = '\0';
  676. *secondp = strdup(p + 1);
  677. return 0;
  678. }
  679. int main(int argc, char *argv[])
  680. {
  681. int opt, option_index = 0;
  682. int mode_dump = 0, mode_extract = 0, mode_inject = 0;
  683. int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
  684. int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
  685. int create = 0;
  686. char *region_type_string = NULL, *src_fname = NULL;
  687. char *addr_str = NULL;
  688. int region_type = -1, inputfreq = 0;
  689. enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
  690. unsigned int addr = 0;
  691. int rom_size = -1;
  692. bool write_it;
  693. char *filename;
  694. char *outfile = NULL;
  695. struct stat buf;
  696. int size = 0;
  697. int bios_fd;
  698. char *image;
  699. int ret;
  700. static struct option long_options[] = {
  701. {"create", 0, NULL, 'c'},
  702. {"dump", 0, NULL, 'd'},
  703. {"descriptor", 1, NULL, 'D'},
  704. {"em100", 0, NULL, 'e'},
  705. {"extract", 0, NULL, 'x'},
  706. {"inject", 1, NULL, 'i'},
  707. {"lock", 0, NULL, 'l'},
  708. {"romsize", 1, NULL, 'r'},
  709. {"spifreq", 1, NULL, 's'},
  710. {"unlock", 0, NULL, 'u'},
  711. {"write", 1, NULL, 'w'},
  712. {"version", 0, NULL, 'v'},
  713. {"help", 0, NULL, 'h'},
  714. {0, 0, 0, 0}
  715. };
  716. while ((opt = getopt_long(argc, argv, "cdD:ehi:lr:s:uvw:x?",
  717. long_options, &option_index)) != EOF) {
  718. switch (opt) {
  719. case 'c':
  720. create = 1;
  721. break;
  722. case 'd':
  723. mode_dump = 1;
  724. break;
  725. case 'D':
  726. mode_write_descriptor = 1;
  727. src_fname = optarg;
  728. break;
  729. case 'e':
  730. mode_em100 = 1;
  731. break;
  732. case 'i':
  733. if (get_two_words(optarg, &region_type_string,
  734. &src_fname)) {
  735. print_usage(argv[0]);
  736. exit(EXIT_FAILURE);
  737. }
  738. if (!strcasecmp("Descriptor", region_type_string))
  739. region_type = 0;
  740. else if (!strcasecmp("BIOS", region_type_string))
  741. region_type = 1;
  742. else if (!strcasecmp("ME", region_type_string))
  743. region_type = 2;
  744. else if (!strcasecmp("GbE", region_type_string))
  745. region_type = 3;
  746. else if (!strcasecmp("Platform", region_type_string))
  747. region_type = 4;
  748. if (region_type == -1) {
  749. fprintf(stderr, "No such region type: '%s'\n\n",
  750. region_type_string);
  751. print_usage(argv[0]);
  752. exit(EXIT_FAILURE);
  753. }
  754. mode_inject = 1;
  755. break;
  756. case 'l':
  757. mode_locked = 1;
  758. break;
  759. case 'r':
  760. rom_size = strtol(optarg, NULL, 0);
  761. debug("ROM size %d\n", rom_size);
  762. break;
  763. case 's':
  764. /* Parse the requested SPI frequency */
  765. inputfreq = strtol(optarg, NULL, 0);
  766. switch (inputfreq) {
  767. case 20:
  768. spifreq = SPI_FREQUENCY_20MHZ;
  769. break;
  770. case 33:
  771. spifreq = SPI_FREQUENCY_33MHZ;
  772. break;
  773. case 50:
  774. spifreq = SPI_FREQUENCY_50MHZ;
  775. break;
  776. default:
  777. fprintf(stderr, "Invalid SPI Frequency: %d\n",
  778. inputfreq);
  779. print_usage(argv[0]);
  780. exit(EXIT_FAILURE);
  781. }
  782. mode_spifreq = 1;
  783. break;
  784. case 'u':
  785. mode_unlocked = 1;
  786. break;
  787. case 'v':
  788. print_version();
  789. exit(EXIT_SUCCESS);
  790. break;
  791. case 'w':
  792. mode_write = 1;
  793. if (get_two_words(optarg, &addr_str, &src_fname)) {
  794. print_usage(argv[0]);
  795. exit(EXIT_FAILURE);
  796. }
  797. addr = strtol(optarg, NULL, 0);
  798. break;
  799. case 'x':
  800. mode_extract = 1;
  801. break;
  802. case 'h':
  803. case '?':
  804. default:
  805. print_usage(argv[0]);
  806. exit(EXIT_SUCCESS);
  807. break;
  808. }
  809. }
  810. if (mode_locked == 1 && mode_unlocked == 1) {
  811. fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
  812. exit(EXIT_FAILURE);
  813. }
  814. if (mode_inject == 1 && mode_write == 1) {
  815. fprintf(stderr, "Inject/Write are mutually exclusive\n");
  816. exit(EXIT_FAILURE);
  817. }
  818. if ((mode_dump + mode_extract + mode_inject +
  819. (mode_spifreq | mode_em100 | mode_unlocked |
  820. mode_locked)) > 1) {
  821. fprintf(stderr, "You may not specify more than one mode.\n\n");
  822. print_usage(argv[0]);
  823. exit(EXIT_FAILURE);
  824. }
  825. if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
  826. mode_em100 + mode_locked + mode_unlocked + mode_write +
  827. mode_write_descriptor) == 0 && !create) {
  828. fprintf(stderr, "You need to specify a mode.\n\n");
  829. print_usage(argv[0]);
  830. exit(EXIT_FAILURE);
  831. }
  832. if (create && rom_size == -1) {
  833. fprintf(stderr, "You need to specify a rom size when creating.\n\n");
  834. exit(EXIT_FAILURE);
  835. }
  836. if (optind + 1 != argc) {
  837. fprintf(stderr, "You need to specify a file.\n\n");
  838. print_usage(argv[0]);
  839. exit(EXIT_FAILURE);
  840. }
  841. filename = argv[optind];
  842. if (optind + 2 != argc)
  843. outfile = argv[optind + 1];
  844. if (create)
  845. bios_fd = open(filename, O_WRONLY | O_CREAT, 0666);
  846. else
  847. bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR);
  848. if (bios_fd == -1) {
  849. perror("Could not open file");
  850. exit(EXIT_FAILURE);
  851. }
  852. if (!create) {
  853. if (fstat(bios_fd, &buf) == -1) {
  854. perror("Could not stat file");
  855. exit(EXIT_FAILURE);
  856. }
  857. size = buf.st_size;
  858. }
  859. debug("File %s is %d bytes\n", filename, size);
  860. if (rom_size == -1)
  861. rom_size = size;
  862. image = malloc(rom_size);
  863. if (!image) {
  864. printf("Out of memory.\n");
  865. exit(EXIT_FAILURE);
  866. }
  867. memset(image, '\xff', rom_size);
  868. if (!create && read(bios_fd, image, size) != size) {
  869. perror("Could not read file");
  870. exit(EXIT_FAILURE);
  871. }
  872. if (size != rom_size) {
  873. debug("ROM size changed to %d bytes\n", rom_size);
  874. size = rom_size;
  875. }
  876. write_it = true;
  877. ret = 0;
  878. if (mode_dump) {
  879. ret = dump_fd(image, size);
  880. write_it = false;
  881. }
  882. if (mode_extract) {
  883. ret = write_regions(image, size);
  884. write_it = false;
  885. }
  886. if (mode_write_descriptor)
  887. ret = write_data(image, size, -size, src_fname);
  888. if (mode_inject)
  889. ret = inject_region(image, size, region_type, src_fname);
  890. if (mode_write)
  891. ret = write_data(image, size, addr, src_fname);
  892. if (mode_spifreq)
  893. set_spi_frequency(image, size, spifreq);
  894. if (mode_em100)
  895. set_em100_mode(image, size);
  896. if (mode_locked)
  897. lock_descriptor(image, size);
  898. if (mode_unlocked)
  899. unlock_descriptor(image, size);
  900. if (write_it) {
  901. if (outfile) {
  902. ret = write_image(outfile, image, size);
  903. } else {
  904. if (lseek(bios_fd, 0, SEEK_SET)) {
  905. perror("Error while seeking");
  906. ret = -1;
  907. }
  908. if (write(bios_fd, image, size) != size) {
  909. perror("Error while writing");
  910. ret = -1;
  911. }
  912. }
  913. }
  914. free(image);
  915. close(bios_fd);
  916. return ret ? 1 : 0;
  917. }