libpayload: increase MAX_ARGC_COUNT
[coreboot.git] / util / ifdtool / ifdtool.c
blob45dd97cd4259f7a1c9587ffd1000ec0de5d7ee44
1 /*
2 * ifdtool - dump Intel Firmware Descriptor information
4 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <getopt.h>
21 #include <fcntl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include "ifdtool.h"
26 #ifndef O_BINARY
27 #define O_BINARY 0
28 #endif
30 static int ifd_version;
31 static int max_regions = 0;
32 static int selected_chip = 0;
33 static int platform = -1;
35 static const struct region_name region_names[MAX_REGIONS] = {
36 { "Flash Descriptor", "fd" },
37 { "BIOS", "bios" },
38 { "Intel ME", "me" },
39 { "GbE", "gbe" },
40 { "Platform Data", "pd" },
41 { "Reserved", "res1" },
42 { "Reserved", "res2" },
43 { "Reserved", "res3" },
44 { "EC", "ec" },
47 static fdbar_t *find_fd(char *image, int size)
49 int i, found = 0;
51 /* Scan for FD signature */
52 for (i = 0; i < (size - 4); i += 4) {
53 if (*(uint32_t *) (image + i) == 0x0FF0A55A) {
54 found = 1;
55 break; // signature found.
59 if (!found) {
60 printf("No Flash Descriptor found in this image\n");
61 return NULL;
64 return (fdbar_t *) (image + i);
68 * There is no version field in the descriptor so to determine
69 * if this is a new descriptor format we check the hardcoded SPI
70 * read frequency to see if it is fixed at 20MHz or 17MHz.
72 static void check_ifd_version(char *image, int size)
74 fdbar_t *fdb = find_fd(image, size);
75 fcba_t *fcba;
76 int read_freq;
78 if (!fdb)
79 exit(EXIT_FAILURE);
81 fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
82 if (!fcba)
83 exit(EXIT_FAILURE);
85 read_freq = (fcba->flcomp >> 17) & 7;
87 switch (read_freq) {
88 case SPI_FREQUENCY_20MHZ:
89 ifd_version = IFD_VERSION_1;
90 max_regions = MAX_REGIONS_OLD;
91 break;
92 case SPI_FREQUENCY_17MHZ:
93 ifd_version = IFD_VERSION_2;
94 max_regions = MAX_REGIONS;
95 break;
96 default:
97 fprintf(stderr, "Unknown descriptor version: %d\n",
98 read_freq);
99 exit(EXIT_FAILURE);
103 static region_t get_region(frba_t *frba, int region_type)
105 int base_mask;
106 int limit_mask;
107 uint32_t *flreg;
108 region_t region;
110 if (ifd_version >= IFD_VERSION_2)
111 base_mask = 0x7fff;
112 else
113 base_mask = 0xfff;
115 limit_mask = base_mask << 16;
117 switch (region_type) {
118 case 0:
119 flreg = &frba->flreg0;
120 break;
121 case 1:
122 flreg = &frba->flreg1;
123 break;
124 case 2:
125 flreg = &frba->flreg2;
126 break;
127 case 3:
128 flreg = &frba->flreg3;
129 break;
130 case 4:
131 flreg = &frba->flreg4;
132 break;
133 case 5:
134 flreg = &frba->flreg5;
135 break;
136 case 6:
137 flreg = &frba->flreg6;
138 break;
139 case 7:
140 flreg = &frba->flreg7;
141 break;
142 case 8:
143 flreg = &frba->flreg8;
144 break;
145 default:
146 fprintf(stderr, "Invalid region type %d.\n", region_type);
147 exit (EXIT_FAILURE);
150 region.base = (*flreg & base_mask) << 12;
151 region.limit = ((*flreg & limit_mask) >> 4) | 0xfff;
152 region.size = region.limit - region.base + 1;
154 if (region.size < 0)
155 region.size = 0;
157 return region;
160 static void set_region(frba_t *frba, int region_type, region_t region)
162 switch (region_type) {
163 case 0:
164 frba->flreg0 = (((region.limit >> 12) & 0x7fff) << 16)
165 | ((region.base >> 12) & 0x7fff);
166 break;
167 case 1:
168 frba->flreg1 = (((region.limit >> 12) & 0x7fff) << 16)
169 | ((region.base >> 12) & 0x7fff);
170 break;
171 case 2:
172 frba->flreg2 = (((region.limit >> 12) & 0x7fff) << 16)
173 | ((region.base >> 12) & 0x7fff);
174 break;
175 case 3:
176 frba->flreg3 = (((region.limit >> 12) & 0x7fff) << 16)
177 | ((region.base >> 12) & 0x7fff);
178 break;
179 case 4:
180 frba->flreg4 = (((region.limit >> 12) & 0x7fff) << 16)
181 | ((region.base >> 12) & 0x7fff);
182 break;
183 default:
184 fprintf(stderr, "Invalid region type.\n");
185 exit (EXIT_FAILURE);
189 static const char *region_name(int region_type)
191 if (region_type < 0 || region_type >= max_regions) {
192 fprintf(stderr, "Invalid region type.\n");
193 exit (EXIT_FAILURE);
196 return region_names[region_type].pretty;
199 static const char *region_name_short(int region_type)
201 if (region_type < 0 || region_type >= max_regions) {
202 fprintf(stderr, "Invalid region type.\n");
203 exit (EXIT_FAILURE);
206 return region_names[region_type].terse;
209 static int region_num(const char *name)
211 int i;
213 for (i = 0; i < max_regions; i++) {
214 if (strcasecmp(name, region_names[i].pretty) == 0)
215 return i;
216 if (strcasecmp(name, region_names[i].terse) == 0)
217 return i;
220 return -1;
223 static const char *region_filename(int region_type)
225 static const char *region_filenames[MAX_REGIONS] = {
226 "flashregion_0_flashdescriptor.bin",
227 "flashregion_1_bios.bin",
228 "flashregion_2_intel_me.bin",
229 "flashregion_3_gbe.bin",
230 "flashregion_4_platform_data.bin",
231 "flashregion_5_reserved.bin",
232 "flashregion_6_reserved.bin",
233 "flashregion_7_reserved.bin",
234 "flashregion_8_ec.bin",
237 if (region_type < 0 || region_type >= max_regions) {
238 fprintf(stderr, "Invalid region type %d.\n", region_type);
239 exit (EXIT_FAILURE);
242 return region_filenames[region_type];
245 static void dump_region(int num, frba_t *frba)
247 region_t region = get_region(frba, num);
248 printf(" Flash Region %d (%s): %08x - %08x %s\n",
249 num, region_name(num), region.base, region.limit,
250 region.size < 1 ? "(unused)" : "");
253 static void dump_region_layout(char *buf, size_t bufsize, int num, frba_t *frba)
255 region_t region = get_region(frba, num);
256 snprintf(buf, bufsize, "%08x:%08x %s\n",
257 region.base, region.limit, region_name_short(num));
260 static void dump_frba(frba_t * frba)
262 printf("Found Region Section\n");
263 printf("FLREG0: 0x%08x\n", frba->flreg0);
264 dump_region(0, frba);
265 printf("FLREG1: 0x%08x\n", frba->flreg1);
266 dump_region(1, frba);
267 printf("FLREG2: 0x%08x\n", frba->flreg2);
268 dump_region(2, frba);
269 printf("FLREG3: 0x%08x\n", frba->flreg3);
270 dump_region(3, frba);
271 printf("FLREG4: 0x%08x\n", frba->flreg4);
272 dump_region(4, frba);
274 if (ifd_version >= IFD_VERSION_2) {
275 printf("FLREG5: 0x%08x\n", frba->flreg5);
276 dump_region(5, frba);
277 printf("FLREG6: 0x%08x\n", frba->flreg6);
278 dump_region(6, frba);
279 printf("FLREG7: 0x%08x\n", frba->flreg7);
280 dump_region(7, frba);
281 printf("FLREG8: 0x%08x\n", frba->flreg8);
282 dump_region(8, frba);
286 static void dump_frba_layout(frba_t * frba, char *layout_fname)
288 char buf[LAYOUT_LINELEN];
289 size_t bufsize = LAYOUT_LINELEN;
290 int i;
292 int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC,
293 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
294 if (layout_fd == -1) {
295 perror("Could not open file");
296 exit(EXIT_FAILURE);
299 for (i = 0; i < max_regions; i++) {
300 region_t region = get_region(frba, i);
301 /* is region invalid? */
302 if (region.size < 1)
303 continue;
305 dump_region_layout(buf, bufsize, i, frba);
306 if (write(layout_fd, buf, strlen(buf)) < 0) {
307 perror("Could not write to file");
308 exit(EXIT_FAILURE);
311 close(layout_fd);
312 printf("Wrote layout to %s\n", layout_fname);
315 static void decode_spi_frequency(unsigned int freq)
317 switch (freq) {
318 case SPI_FREQUENCY_20MHZ:
319 printf("20MHz");
320 break;
321 case SPI_FREQUENCY_33MHZ:
322 printf("33MHz");
323 break;
324 case SPI_FREQUENCY_48MHZ:
325 printf("48MHz");
326 break;
327 case SPI_FREQUENCY_50MHZ_30MHZ:
328 switch (ifd_version) {
329 case IFD_VERSION_1:
330 printf("50MHz");
331 break;
332 case IFD_VERSION_2:
333 printf("30MHz");
334 break;
336 break;
337 case SPI_FREQUENCY_17MHZ:
338 printf("17MHz");
339 break;
340 default:
341 printf("unknown<%x>MHz", freq);
345 static void decode_component_density(unsigned int density)
347 switch (density) {
348 case COMPONENT_DENSITY_512KB:
349 printf("512KB");
350 break;
351 case COMPONENT_DENSITY_1MB:
352 printf("1MB");
353 break;
354 case COMPONENT_DENSITY_2MB:
355 printf("2MB");
356 break;
357 case COMPONENT_DENSITY_4MB:
358 printf("4MB");
359 break;
360 case COMPONENT_DENSITY_8MB:
361 printf("8MB");
362 break;
363 case COMPONENT_DENSITY_16MB:
364 printf("16MB");
365 break;
366 case COMPONENT_DENSITY_32MB:
367 printf("32MB");
368 break;
369 case COMPONENT_DENSITY_64MB:
370 printf("64MB");
371 break;
372 case COMPONENT_DENSITY_UNUSED:
373 printf("UNUSED");
374 break;
375 default:
376 printf("unknown<%x>MB", density);
380 static void dump_fcba(fcba_t * fcba)
382 printf("\nFound Component Section\n");
383 printf("FLCOMP 0x%08x\n", fcba->flcomp);
384 printf(" Dual Output Fast Read Support: %ssupported\n",
385 (fcba->flcomp & (1 << 30))?"":"not ");
386 printf(" Read ID/Read Status Clock Frequency: ");
387 decode_spi_frequency((fcba->flcomp >> 27) & 7);
388 printf("\n Write/Erase Clock Frequency: ");
389 decode_spi_frequency((fcba->flcomp >> 24) & 7);
390 printf("\n Fast Read Clock Frequency: ");
391 decode_spi_frequency((fcba->flcomp >> 21) & 7);
392 printf("\n Fast Read Support: %ssupported",
393 (fcba->flcomp & (1 << 20))?"":"not ");
394 printf("\n Read Clock Frequency: ");
395 decode_spi_frequency((fcba->flcomp >> 17) & 7);
397 switch (ifd_version) {
398 case IFD_VERSION_1:
399 printf("\n Component 2 Density: ");
400 decode_component_density((fcba->flcomp >> 3) & 7);
401 printf("\n Component 1 Density: ");
402 decode_component_density(fcba->flcomp & 7);
403 break;
404 case IFD_VERSION_2:
405 printf("\n Component 2 Density: ");
406 decode_component_density((fcba->flcomp >> 4) & 0xf);
407 printf("\n Component 1 Density: ");
408 decode_component_density(fcba->flcomp & 0xf);
409 break;
412 printf("\n");
413 printf("FLILL 0x%08x\n", fcba->flill);
414 printf(" Invalid Instruction 3: 0x%02x\n",
415 (fcba->flill >> 24) & 0xff);
416 printf(" Invalid Instruction 2: 0x%02x\n",
417 (fcba->flill >> 16) & 0xff);
418 printf(" Invalid Instruction 1: 0x%02x\n",
419 (fcba->flill >> 8) & 0xff);
420 printf(" Invalid Instruction 0: 0x%02x\n",
421 fcba->flill & 0xff);
422 printf("FLPB 0x%08x\n", fcba->flpb);
423 printf(" Flash Partition Boundary Address: 0x%06x\n\n",
424 (fcba->flpb & 0xfff) << 12);
427 static void dump_fpsba(fpsba_t * fpsba)
429 printf("Found PCH Strap Section\n");
430 printf("PCHSTRP0: 0x%08x\n", fpsba->pchstrp0);
431 printf("PCHSTRP1: 0x%08x\n", fpsba->pchstrp1);
432 printf("PCHSTRP2: 0x%08x\n", fpsba->pchstrp2);
433 printf("PCHSTRP3: 0x%08x\n", fpsba->pchstrp3);
434 printf("PCHSTRP4: 0x%08x\n", fpsba->pchstrp4);
435 printf("PCHSTRP5: 0x%08x\n", fpsba->pchstrp5);
436 printf("PCHSTRP6: 0x%08x\n", fpsba->pchstrp6);
437 printf("PCHSTRP7: 0x%08x\n", fpsba->pchstrp7);
438 printf("PCHSTRP8: 0x%08x\n", fpsba->pchstrp8);
439 printf("PCHSTRP9: 0x%08x\n", fpsba->pchstrp9);
440 printf("PCHSTRP10: 0x%08x\n", fpsba->pchstrp10);
441 printf("PCHSTRP11: 0x%08x\n", fpsba->pchstrp11);
442 printf("PCHSTRP12: 0x%08x\n", fpsba->pchstrp12);
443 printf("PCHSTRP13: 0x%08x\n", fpsba->pchstrp13);
444 printf("PCHSTRP14: 0x%08x\n", fpsba->pchstrp14);
445 printf("PCHSTRP15: 0x%08x\n", fpsba->pchstrp15);
446 printf("PCHSTRP16: 0x%08x\n", fpsba->pchstrp16);
447 printf("PCHSTRP17: 0x%08x\n\n", fpsba->pchstrp17);
450 static void decode_flmstr(uint32_t flmstr)
452 int wr_shift, rd_shift;
453 if (ifd_version >= IFD_VERSION_2) {
454 wr_shift = FLMSTR_WR_SHIFT_V2;
455 rd_shift = FLMSTR_RD_SHIFT_V2;
456 } else {
457 wr_shift = FLMSTR_WR_SHIFT_V1;
458 rd_shift = FLMSTR_RD_SHIFT_V1;
461 /* EC region access only available on v2+ */
462 if (ifd_version >= IFD_VERSION_2)
463 printf(" EC Region Write Access: %s\n",
464 (flmstr & (1 << (wr_shift + 8))) ?
465 "enabled" : "disabled");
466 printf(" Platform Data Region Write Access: %s\n",
467 (flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");
468 printf(" GbE Region Write Access: %s\n",
469 (flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");
470 printf(" Intel ME Region Write Access: %s\n",
471 (flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");
472 printf(" Host CPU/BIOS Region Write Access: %s\n",
473 (flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");
474 printf(" Flash Descriptor Write Access: %s\n",
475 (flmstr & (1 << wr_shift)) ? "enabled" : "disabled");
477 if (ifd_version >= IFD_VERSION_2)
478 printf(" EC Region Read Access: %s\n",
479 (flmstr & (1 << (rd_shift + 8))) ?
480 "enabled" : "disabled");
481 printf(" Platform Data Region Read Access: %s\n",
482 (flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");
483 printf(" GbE Region Read Access: %s\n",
484 (flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");
485 printf(" Intel ME Region Read Access: %s\n",
486 (flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");
487 printf(" Host CPU/BIOS Region Read Access: %s\n",
488 (flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");
489 printf(" Flash Descriptor Read Access: %s\n",
490 (flmstr & (1 << rd_shift)) ? "enabled" : "disabled");
492 /* Requestor ID doesn't exist for ifd 2 */
493 if (ifd_version < IFD_VERSION_2)
494 printf(" Requester ID: 0x%04x\n\n",
495 flmstr & 0xffff);
498 static void dump_fmba(fmba_t * fmba)
500 printf("Found Master Section\n");
501 printf("FLMSTR1: 0x%08x (Host CPU/BIOS)\n", fmba->flmstr1);
502 decode_flmstr(fmba->flmstr1);
503 printf("FLMSTR2: 0x%08x (Intel ME)\n", fmba->flmstr2);
504 decode_flmstr(fmba->flmstr2);
505 printf("FLMSTR3: 0x%08x (GbE)\n", fmba->flmstr3);
506 decode_flmstr(fmba->flmstr3);
507 if (ifd_version >= IFD_VERSION_2) {
508 printf("FLMSTR5: 0x%08x (EC)\n", fmba->flmstr5);
509 decode_flmstr(fmba->flmstr5);
513 static void dump_fmsba(fmsba_t * fmsba)
515 printf("Found Processor Strap Section\n");
516 printf("????: 0x%08x\n", fmsba->data[0]);
517 printf("????: 0x%08x\n", fmsba->data[1]);
518 printf("????: 0x%08x\n", fmsba->data[2]);
519 printf("????: 0x%08x\n", fmsba->data[3]);
522 static void dump_jid(uint32_t jid)
524 printf(" SPI Componend Device ID 1: 0x%02x\n",
525 (jid >> 16) & 0xff);
526 printf(" SPI Componend Device ID 0: 0x%02x\n",
527 (jid >> 8) & 0xff);
528 printf(" SPI Componend Vendor ID: 0x%02x\n",
529 jid & 0xff);
532 static void dump_vscc(uint32_t vscc)
534 printf(" Lower Erase Opcode: 0x%02x\n",
535 vscc >> 24);
536 printf(" Lower Write Enable on Write Status: 0x%02x\n",
537 vscc & (1 << 20) ? 0x06 : 0x50);
538 printf(" Lower Write Status Required: %s\n",
539 vscc & (1 << 19) ? "Yes" : "No");
540 printf(" Lower Write Granularity: %d bytes\n",
541 vscc & (1 << 18) ? 64 : 1);
542 printf(" Lower Block / Sector Erase Size: ");
543 switch ((vscc >> 16) & 0x3) {
544 case 0:
545 printf("256 Byte\n");
546 break;
547 case 1:
548 printf("4KB\n");
549 break;
550 case 2:
551 printf("8KB\n");
552 break;
553 case 3:
554 printf("64KB\n");
555 break;
558 printf(" Upper Erase Opcode: 0x%02x\n",
559 (vscc >> 8) & 0xff);
560 printf(" Upper Write Enable on Write Status: 0x%02x\n",
561 vscc & (1 << 4) ? 0x06 : 0x50);
562 printf(" Upper Write Status Required: %s\n",
563 vscc & (1 << 3) ? "Yes" : "No");
564 printf(" Upper Write Granularity: %d bytes\n",
565 vscc & (1 << 2) ? 64 : 1);
566 printf(" Upper Block / Sector Erase Size: ");
567 switch (vscc & 0x3) {
568 case 0:
569 printf("256 Byte\n");
570 break;
571 case 1:
572 printf("4KB\n");
573 break;
574 case 2:
575 printf("8KB\n");
576 break;
577 case 3:
578 printf("64KB\n");
579 break;
583 static void dump_vtba(vtba_t *vtba, int vtl)
585 int i;
586 int num = (vtl >> 1) < 8 ? (vtl >> 1) : 8;
588 printf("ME VSCC table:\n");
589 for (i = 0; i < num; i++) {
590 printf(" JID%d: 0x%08x\n", i, vtba->entry[i].jid);
591 dump_jid(vtba->entry[i].jid);
592 printf(" VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc);
593 dump_vscc(vtba->entry[i].vscc);
595 printf("\n");
598 static void dump_oem(uint8_t *oem)
600 int i, j;
601 printf("OEM Section:\n");
602 for (i = 0; i < 4; i++) {
603 printf("%02x:", i << 4);
604 for (j = 0; j < 16; j++)
605 printf(" %02x", oem[(i<<4)+j]);
606 printf ("\n");
608 printf ("\n");
611 static void dump_fd(char *image, int size)
613 fdbar_t *fdb = find_fd(image, size);
614 if (!fdb)
615 exit(EXIT_FAILURE);
617 printf("FLMAP0: 0x%08x\n", fdb->flmap0);
618 printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7);
619 printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
620 printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
621 printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4);
623 printf("FLMAP1: 0x%08x\n", fdb->flmap1);
624 printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
625 printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
626 printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3);
627 printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4);
629 printf("FLMAP2: 0x%08x\n", fdb->flmap2);
630 printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
631 printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4);
633 printf("FLUMAP1: 0x%08x\n", fdb->flumap1);
634 printf(" Intel ME VSCC Table Length (VTL): %d\n",
635 (fdb->flumap1 >> 8) & 0xff);
636 printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",
637 (fdb->flumap1 & 0xff) << 4);
638 dump_vtba((vtba_t *)
639 (image + ((fdb->flumap1 & 0xff) << 4)),
640 (fdb->flumap1 >> 8) & 0xff);
641 dump_oem((uint8_t *)image + 0xf00);
642 dump_frba((frba_t *)
643 (image + (((fdb->flmap0 >> 16) & 0xff) << 4)));
644 dump_fcba((fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4)));
645 dump_fpsba((fpsba_t *)
646 (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
647 dump_fmba((fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4)));
648 dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));
651 static void dump_layout(char *image, int size, char *layout_fname)
653 fdbar_t *fdb = find_fd(image, size);
654 if (!fdb)
655 exit(EXIT_FAILURE);
657 dump_frba_layout((frba_t *)
658 (image + (((fdb->flmap0 >> 16) & 0xff) << 4)),
659 layout_fname);
662 static void write_regions(char *image, int size)
664 int i;
666 fdbar_t *fdb = find_fd(image, size);
667 if (!fdb)
668 exit(EXIT_FAILURE);
670 frba_t *frba =
671 (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
673 for (i = 0; i < max_regions; i++) {
674 region_t region = get_region(frba, i);
675 dump_region(i, frba);
676 if (region.size > 0) {
677 int region_fd;
678 region_fd = open(region_filename(i),
679 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
680 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
681 if (region_fd < 0) {
682 perror("Error while trying to open file");
683 exit(EXIT_FAILURE);
685 if (write(region_fd, image + region.base, region.size) != region.size)
686 perror("Error while writing");
687 close(region_fd);
692 static void write_image(char *filename, char *image, int size)
694 char new_filename[FILENAME_MAX]; // allow long file names
695 int new_fd;
697 // - 5: leave room for ".new\0"
698 strncpy(new_filename, filename, FILENAME_MAX - 5);
699 strncat(new_filename, ".new", FILENAME_MAX - strlen(filename));
701 printf("Writing new image to %s\n", new_filename);
703 // Now write out new image
704 new_fd = open(new_filename,
705 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
706 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
707 if (new_fd < 0) {
708 perror("Error while trying to open file");
709 exit(EXIT_FAILURE);
711 if (write(new_fd, image, size) != size)
712 perror("Error while writing");
713 close(new_fd);
716 static void set_spi_frequency(char *filename, char *image, int size,
717 enum spi_frequency freq)
719 fdbar_t *fdb = find_fd(image, size);
720 fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
722 /* clear bits 21-29 */
723 fcba->flcomp &= ~0x3fe00000;
724 /* Read ID and Read Status Clock Frequency */
725 fcba->flcomp |= freq << 27;
726 /* Write and Erase Clock Frequency */
727 fcba->flcomp |= freq << 24;
728 /* Fast Read Clock Frequency */
729 fcba->flcomp |= freq << 21;
731 write_image(filename, image, size);
734 static void set_em100_mode(char *filename, char *image, int size)
736 fdbar_t *fdb = find_fd(image, size);
737 fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
738 int freq;
740 switch (ifd_version) {
741 case IFD_VERSION_1:
742 freq = SPI_FREQUENCY_20MHZ;
743 break;
744 case IFD_VERSION_2:
745 freq = SPI_FREQUENCY_17MHZ;
746 break;
747 default:
748 freq = SPI_FREQUENCY_17MHZ;
749 break;
752 fcba->flcomp &= ~(1 << 30);
753 set_spi_frequency(filename, image, size, freq);
756 static void set_chipdensity(char *filename, char *image, int size,
757 unsigned int density)
759 fdbar_t *fdb = find_fd(image, size);
760 fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
762 printf("Setting chip density to ");
763 decode_component_density(density);
764 printf("\n");
766 switch (ifd_version) {
767 case IFD_VERSION_1:
768 /* fail if selected density is not supported by this version */
769 if ( (density == COMPONENT_DENSITY_32MB) ||
770 (density == COMPONENT_DENSITY_64MB) ||
771 (density == COMPONENT_DENSITY_UNUSED) ) {
772 printf("error: Selected density not supported in IFD version 1.\n");
773 exit(EXIT_FAILURE);
775 break;
776 case IFD_VERSION_2:
777 /* I do not have a version 2 IFD nor do i have the docs. */
778 printf("error: Changing the chip density for IFD version 2 has not been"
779 " implemented yet.\n");
780 exit(EXIT_FAILURE);
781 default:
782 printf("error: Unknown IFD version\n");
783 exit(EXIT_FAILURE);
784 break;
787 /* clear chip density for corresponding chip */
788 switch (selected_chip) {
789 case 1:
790 fcba->flcomp &= ~(0x7);
791 break;
792 case 2:
793 fcba->flcomp &= ~(0x7 << 3);
794 break;
795 default: /*both chips*/
796 fcba->flcomp &= ~(0x3F);
797 break;
800 /* set the new density */
801 if (selected_chip == 1 || selected_chip == 0)
802 fcba->flcomp |= (density); /* first chip */
803 if (selected_chip == 2 || selected_chip == 0)
804 fcba->flcomp |= (density << 3); /* second chip */
806 write_image(filename, image, size);
809 static void lock_descriptor(char *filename, char *image, int size)
811 int wr_shift, rd_shift;
812 fdbar_t *fdb = find_fd(image, size);
813 fmba_t *fmba = (fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4));
814 /* TODO: Dynamically take Platform Data Region and GbE Region
815 * into regard.
818 if (ifd_version >= IFD_VERSION_2) {
819 wr_shift = FLMSTR_WR_SHIFT_V2;
820 rd_shift = FLMSTR_RD_SHIFT_V2;
822 /* Clear non-reserved bits */
823 fmba->flmstr1 &= 0xff;
824 fmba->flmstr2 &= 0xff;
825 fmba->flmstr3 &= 0xff;
826 } else {
827 wr_shift = FLMSTR_WR_SHIFT_V1;
828 rd_shift = FLMSTR_RD_SHIFT_V1;
830 fmba->flmstr1 = 0;
831 fmba->flmstr2 = 0;
832 /* Requestor ID */
833 fmba->flmstr3 = 0x118;
836 switch (platform) {
837 case PLATFORM_APOLLOLAKE:
838 /* CPU/BIOS can read descriptor and BIOS */
839 fmba->flmstr1 |= 0x3 << rd_shift;
840 /* CPU/BIOS can write BIOS */
841 fmba->flmstr1 |= 0x2 << wr_shift;
842 /* TXE can read descriptor, BIOS and Device Expansion */
843 fmba->flmstr2 |= 0x23 << rd_shift;
844 /* TXE can only write Device Expansion */
845 fmba->flmstr2 |= 0x20 << wr_shift;
846 break;
847 default:
848 /* CPU/BIOS can read descriptor, BIOS, and GbE. */
849 fmba->flmstr1 |= 0xb << rd_shift;
850 /* CPU/BIOS can write BIOS and GbE. */
851 fmba->flmstr1 |= 0xa << wr_shift;
852 /* ME can read descriptor, ME, and GbE. */
853 fmba->flmstr2 |= 0xd << rd_shift;
854 /* ME can write ME and GbE. */
855 fmba->flmstr2 |= 0xc << wr_shift;
856 /* GbE can write only GbE. */
857 fmba->flmstr3 |= 0x8 << rd_shift;
858 /* GbE can read only GbE. */
859 fmba->flmstr3 |= 0x8 << wr_shift;
860 break;
863 write_image(filename, image, size);
866 static void unlock_descriptor(char *filename, char *image, int size)
868 fdbar_t *fdb = find_fd(image, size);
869 fmba_t *fmba = (fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4));
871 if (ifd_version >= IFD_VERSION_2) {
872 /* Access bits for each region are read: 19:8 write: 31:20 */
873 fmba->flmstr1 = 0xffffff00 | (fmba->flmstr1 & 0xff);
874 fmba->flmstr2 = 0xffffff00 | (fmba->flmstr2 & 0xff);
875 fmba->flmstr3 = 0xffffff00 | (fmba->flmstr3 & 0xff);
876 } else {
877 fmba->flmstr1 = 0xffff0000;
878 fmba->flmstr2 = 0xffff0000;
879 fmba->flmstr3 = 0x08080118;
882 write_image(filename, image, size);
885 void inject_region(char *filename, char *image, int size, int region_type,
886 char *region_fname)
888 fdbar_t *fdb = find_fd(image, size);
889 if (!fdb)
890 exit(EXIT_FAILURE);
891 frba_t *frba =
892 (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
894 region_t region = get_region(frba, region_type);
895 if (region.size <= 0xfff) {
896 fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
897 region_name(region_type));
898 exit(EXIT_FAILURE);
901 int region_fd = open(region_fname, O_RDONLY | O_BINARY);
902 if (region_fd == -1) {
903 perror("Could not open file");
904 exit(EXIT_FAILURE);
906 struct stat buf;
907 if (fstat(region_fd, &buf) == -1) {
908 perror("Could not stat file");
909 exit(EXIT_FAILURE);
911 int region_size = buf.st_size;
913 printf("File %s is %d bytes\n", region_fname, region_size);
915 if ( (region_size > region.size) || ((region_type != 1) &&
916 (region_size > region.size))) {
917 fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
918 " bytes. Not injecting.\n",
919 region_name(region_type), region.size,
920 region.size, region_size, region_size);
921 exit(EXIT_FAILURE);
924 int offset = 0;
925 if ((region_type == 1) && (region_size < region.size)) {
926 fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
927 " bytes. Padding before injecting.\n",
928 region_name(region_type), region.size,
929 region.size, region_size, region_size);
930 offset = region.size - region_size;
931 memset(image + region.base, 0xff, offset);
934 if (size < region.base + offset + region_size) {
935 fprintf(stderr, "Output file is too small. (%d < %d)\n",
936 size, region.base + offset + region_size);
937 exit(EXIT_FAILURE);
940 if (read(region_fd, image + region.base + offset, region_size)
941 != region_size) {
942 perror("Could not read file");
943 exit(EXIT_FAILURE);
946 close(region_fd);
948 printf("Adding %s as the %s section of %s\n",
949 region_fname, region_name(region_type), filename);
950 write_image(filename, image, size);
953 unsigned int next_pow2(unsigned int x)
955 unsigned int y = 1;
956 if (x == 0)
957 return 0;
958 while (y <= x)
959 y = y << 1;
961 return y;
965 * Determine if two memory regions overlap.
967 * @param r1, r2 Memory regions to compare.
968 * @return 0 if the two regions are seperate
969 * @return 1 if the two regions overlap
971 static int regions_collide(region_t r1, region_t r2)
973 if ((r1.size == 0) || (r2.size == 0))
974 return 0;
976 if ( ((r1.base >= r2.base) && (r1.base <= r2.limit)) ||
977 ((r1.limit >= r2.base) && (r1.limit <= r2.limit)) )
978 return 1;
980 return 0;
983 void new_layout(char *filename, char *image, int size, char *layout_fname)
985 FILE *romlayout;
986 char tempstr[256];
987 char layout_region_name[256];
988 int i, j;
989 int region_number;
990 region_t current_regions[MAX_REGIONS];
991 region_t new_regions[MAX_REGIONS];
992 int new_extent = 0;
993 char *new_image;
995 /* load current descriptor map and regions */
996 fdbar_t *fdb = find_fd(image, size);
997 if (!fdb)
998 exit(EXIT_FAILURE);
1000 frba_t *frba =
1001 (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
1003 for (i = 0; i < max_regions; i++) {
1004 current_regions[i] = get_region(frba, i);
1005 new_regions[i] = get_region(frba, i);
1008 /* read new layout */
1009 romlayout = fopen(layout_fname, "r");
1011 if (!romlayout) {
1012 perror("Could not read layout file.\n");
1013 exit(EXIT_FAILURE);
1016 while (!feof(romlayout)) {
1017 char *tstr1, *tstr2;
1019 if (2 != fscanf(romlayout, "%255s %255s\n", tempstr,
1020 layout_region_name))
1021 continue;
1023 region_number = region_num(layout_region_name);
1024 if (region_number < 0)
1025 continue;
1027 tstr1 = strtok(tempstr, ":");
1028 tstr2 = strtok(NULL, ":");
1029 if (!tstr1 || !tstr2) {
1030 fprintf(stderr, "Could not parse layout file.\n");
1031 exit(EXIT_FAILURE);
1033 new_regions[region_number].base = strtol(tstr1,
1034 (char **)NULL, 16);
1035 new_regions[region_number].limit = strtol(tstr2,
1036 (char **)NULL, 16);
1037 new_regions[region_number].size =
1038 new_regions[region_number].limit -
1039 new_regions[region_number].base + 1;
1041 if (new_regions[region_number].size < 0)
1042 new_regions[region_number].size = 0;
1044 fclose(romlayout);
1046 /* check new layout */
1047 for (i = 0; i < max_regions; i++) {
1048 if (new_regions[i].size == 0)
1049 continue;
1051 if (new_regions[i].size < current_regions[i].size) {
1052 printf("DANGER: Region %s is shrinking.\n",
1053 region_name(i));
1054 printf(" The region will be truncated to fit.\n");
1055 printf(" This may result in an unusable image.\n");
1058 for (j = i + 1; j < max_regions; j++) {
1059 if (regions_collide(new_regions[i], new_regions[j])) {
1060 fprintf(stderr, "Regions would overlap.\n");
1061 exit(EXIT_FAILURE);
1065 /* detect if the image size should grow */
1066 if (new_extent < new_regions[i].limit)
1067 new_extent = new_regions[i].limit;
1070 new_extent = next_pow2(new_extent - 1);
1071 if (new_extent != size) {
1072 printf("The image has changed in size.\n");
1073 printf("The old image is %d bytes.\n", size);
1074 printf("The new image is %d bytes.\n", new_extent);
1077 /* copy regions to a new image */
1078 new_image = malloc(new_extent);
1079 memset(new_image, 0xff, new_extent);
1080 for (i = 0; i < max_regions; i++) {
1081 int copy_size = new_regions[i].size;
1082 int offset_current = 0, offset_new = 0;
1083 region_t current = current_regions[i];
1084 region_t new = new_regions[i];
1086 if (new.size == 0)
1087 continue;
1089 if (new.size > current.size) {
1090 /* copy from the end of the current region */
1091 copy_size = current.size;
1092 offset_new = new.size - current.size;
1095 if (new.size < current.size) {
1096 /* copy to the end of the new region */
1097 offset_current = current.size - new.size;
1100 printf("Copy Descriptor %d (%s) (%d bytes)\n", i,
1101 region_name(i), copy_size);
1102 printf(" from %08x+%08x:%08x (%10d)\n", current.base,
1103 offset_current, current.limit, current.size);
1104 printf(" to %08x+%08x:%08x (%10d)\n", new.base,
1105 offset_new, new.limit, new.size);
1107 memcpy(new_image + new.base + offset_new,
1108 image + current.base + offset_current,
1109 copy_size);
1112 /* update new descriptor regions */
1113 fdb = find_fd(new_image, new_extent);
1114 if (!fdb)
1115 exit(EXIT_FAILURE);
1117 frba = (frba_t *) (new_image + (((fdb->flmap0 >> 16) & 0xff) << 4));
1118 for (i = 1; i < max_regions; i++) {
1119 set_region(frba, i, new_regions[i]);
1122 write_image(filename, new_image, new_extent);
1123 free(new_image);
1126 static void print_version(void)
1128 printf("ifdtool v%s -- ", IFDTOOL_VERSION);
1129 printf("Copyright (C) 2011 Google Inc.\n\n");
1130 printf
1131 ("This program is free software: you can redistribute it and/or modify\n"
1132 "it under the terms of the GNU General Public License as published by\n"
1133 "the Free Software Foundation, version 2 of the License.\n\n"
1134 "This program is distributed in the hope that it will be useful,\n"
1135 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1136 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1137 "GNU General Public License for more details.\n\n");
1140 static void print_usage(const char *name)
1142 printf("usage: %s [-vhdix?] <filename>\n", name);
1143 printf("\n"
1144 " -d | --dump: dump intel firmware descriptor\n"
1145 " -f | --layout <filename> dump regions into a flashrom layout file\n"
1146 " -x | --extract: extract intel fd modules\n"
1147 " -i | --inject <region>:<module> inject file <module> into region <region>\n"
1148 " -n | --newlayout <filename> update regions using a flashrom layout file\n"
1149 " -s | --spifreq <17|20|30|33|48|50> set the SPI frequency\n"
1150 " -D | --density <512|1|2|4|8|16> set chip density (512 in KByte, others in MByte)\n"
1151 " -C | --chip <0|1|2> select spi chip on which to operate\n"
1152 " can only be used once per run:\n"
1153 " 0 - both chips (default), 1 - first chip, 2 - second chip\n"
1154 " -e | --em100 set SPI frequency to 20MHz and disable\n"
1155 " Dual Output Fast Read Support\n"
1156 " -l | --lock Lock firmware descriptor and ME region\n"
1157 " -u | --unlock Unlock firmware descriptor and ME region\n"
1158 " -p | --platform Add platform-specific quirks\n"
1159 " aplk - Apollo Lake\n"
1160 " -v | --version: print the version\n"
1161 " -h | --help: print this help\n\n"
1162 "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
1163 "\n");
1166 int main(int argc, char *argv[])
1168 int opt, option_index = 0;
1169 int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
1170 int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0;
1171 int mode_layout = 0, mode_newlayout = 0, mode_density = 0;
1172 char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL;
1173 int region_type = -1, inputfreq = 0;
1174 unsigned int new_density = 0;
1175 enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
1177 static struct option long_options[] = {
1178 {"dump", 0, NULL, 'd'},
1179 {"layout", 1, NULL, 'f'},
1180 {"extract", 0, NULL, 'x'},
1181 {"inject", 1, NULL, 'i'},
1182 {"newlayout", 1, NULL, 'n'},
1183 {"spifreq", 1, NULL, 's'},
1184 {"density", 1, NULL, 'D'},
1185 {"chip", 1, NULL, 'C'},
1186 {"em100", 0, NULL, 'e'},
1187 {"lock", 0, NULL, 'l'},
1188 {"unlock", 0, NULL, 'u'},
1189 {"version", 0, NULL, 'v'},
1190 {"help", 0, NULL, 'h'},
1191 {"platform", 0, NULL, 'p'},
1192 {0, 0, 0, 0}
1195 while ((opt = getopt_long(argc, argv, "df:D:C:xi:n:s:p:eluvh?",
1196 long_options, &option_index)) != EOF) {
1197 switch (opt) {
1198 case 'd':
1199 mode_dump = 1;
1200 break;
1201 case 'f':
1202 mode_layout = 1;
1203 layout_fname = strdup(optarg);
1204 if (!layout_fname) {
1205 fprintf(stderr, "No layout file specified\n");
1206 print_usage(argv[0]);
1207 exit(EXIT_FAILURE);
1209 break;
1210 case 'x':
1211 mode_extract = 1;
1212 break;
1213 case 'i':
1214 // separate type and file name
1215 region_type_string = strdup(optarg);
1216 region_fname = strchr(region_type_string, ':');
1217 if (!region_fname) {
1218 print_usage(argv[0]);
1219 exit(EXIT_FAILURE);
1221 region_fname[0] = '\0';
1222 region_fname++;
1223 // Descriptor, BIOS, ME, GbE, Platform
1224 // valid type?
1225 if (!strcasecmp("Descriptor", region_type_string))
1226 region_type = 0;
1227 else if (!strcasecmp("BIOS", region_type_string))
1228 region_type = 1;
1229 else if (!strcasecmp("ME", region_type_string))
1230 region_type = 2;
1231 else if (!strcasecmp("GbE", region_type_string))
1232 region_type = 3;
1233 else if (!strcasecmp("Platform", region_type_string))
1234 region_type = 4;
1235 else if (!strcasecmp("EC", region_type_string))
1236 region_type = 8;
1237 if (region_type == -1) {
1238 fprintf(stderr, "No such region type: '%s'\n\n",
1239 region_type_string);
1240 print_usage(argv[0]);
1241 exit(EXIT_FAILURE);
1243 mode_inject = 1;
1244 break;
1245 case 'n':
1246 mode_newlayout = 1;
1247 layout_fname = strdup(optarg);
1248 if (!layout_fname) {
1249 fprintf(stderr, "No layout file specified\n");
1250 print_usage(argv[0]);
1251 exit(EXIT_FAILURE);
1253 break;
1254 case 'D':
1255 mode_density = 1;
1256 new_density = strtoul(optarg, NULL, 0);
1257 switch (new_density) {
1258 case 512:
1259 new_density = COMPONENT_DENSITY_512KB;
1260 break;
1261 case 1:
1262 new_density = COMPONENT_DENSITY_1MB;
1263 break;
1264 case 2:
1265 new_density = COMPONENT_DENSITY_2MB;
1266 break;
1267 case 4:
1268 new_density = COMPONENT_DENSITY_4MB;
1269 break;
1270 case 8:
1271 new_density = COMPONENT_DENSITY_8MB;
1272 break;
1273 case 16:
1274 new_density = COMPONENT_DENSITY_16MB;
1275 break;
1276 case 32:
1277 new_density = COMPONENT_DENSITY_32MB;
1278 break;
1279 case 64:
1280 new_density = COMPONENT_DENSITY_64MB;
1281 break;
1282 case 0:
1283 new_density = COMPONENT_DENSITY_UNUSED;
1284 break;
1285 default:
1286 printf("error: Unknown density\n");
1287 print_usage(argv[0]);
1288 exit(EXIT_FAILURE);
1290 break;
1291 case 'C':
1292 selected_chip = strtol(optarg, NULL, 0);
1293 if (selected_chip > 2) {
1294 fprintf(stderr, "error: Invalid chip selection\n");
1295 print_usage(argv[0]);
1296 exit(EXIT_FAILURE);
1298 break;
1299 case 's':
1300 // Parse the requested SPI frequency
1301 inputfreq = strtol(optarg, NULL, 0);
1302 switch (inputfreq) {
1303 case 17:
1304 spifreq = SPI_FREQUENCY_17MHZ;
1305 break;
1306 case 20:
1307 spifreq = SPI_FREQUENCY_20MHZ;
1308 break;
1309 case 30:
1310 spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
1311 break;
1312 case 33:
1313 spifreq = SPI_FREQUENCY_33MHZ;
1314 break;
1315 case 48:
1316 spifreq = SPI_FREQUENCY_48MHZ;
1317 break;
1318 case 50:
1319 spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
1320 break;
1321 default:
1322 fprintf(stderr, "Invalid SPI Frequency: %d\n",
1323 inputfreq);
1324 print_usage(argv[0]);
1325 exit(EXIT_FAILURE);
1327 mode_spifreq = 1;
1328 break;
1329 case 'e':
1330 mode_em100 = 1;
1331 break;
1332 case 'l':
1333 mode_locked = 1;
1334 if (mode_unlocked == 1) {
1335 fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
1336 exit(EXIT_FAILURE);
1338 break;
1339 case 'u':
1340 mode_unlocked = 1;
1341 if (mode_locked == 1) {
1342 fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
1343 exit(EXIT_FAILURE);
1345 break;
1346 case 'p':
1347 if (!strcmp(optarg, "aplk")) {
1348 platform = PLATFORM_APOLLOLAKE;
1349 } else {
1350 fprintf(stderr, "Unknown platform: %s\n", optarg);
1351 exit(EXIT_FAILURE);
1353 break;
1354 case 'v':
1355 print_version();
1356 exit(EXIT_SUCCESS);
1357 break;
1358 case 'h':
1359 case '?':
1360 default:
1361 print_usage(argv[0]);
1362 exit(EXIT_SUCCESS);
1363 break;
1367 if ((mode_dump + mode_layout + mode_extract + mode_inject +
1368 mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |
1369 mode_locked)) > 1) {
1370 fprintf(stderr, "You may not specify more than one mode.\n\n");
1371 print_usage(argv[0]);
1372 exit(EXIT_FAILURE);
1375 if ((mode_dump + mode_layout + mode_extract + mode_inject +
1376 mode_newlayout + mode_spifreq + mode_em100 + mode_locked +
1377 mode_unlocked + mode_density) == 0) {
1378 fprintf(stderr, "You need to specify a mode.\n\n");
1379 print_usage(argv[0]);
1380 exit(EXIT_FAILURE);
1383 if (optind + 1 != argc) {
1384 fprintf(stderr, "You need to specify a file.\n\n");
1385 print_usage(argv[0]);
1386 exit(EXIT_FAILURE);
1389 char *filename = argv[optind];
1390 int bios_fd = open(filename, O_RDONLY | O_BINARY);
1391 if (bios_fd == -1) {
1392 perror("Could not open file");
1393 exit(EXIT_FAILURE);
1395 struct stat buf;
1396 if (fstat(bios_fd, &buf) == -1) {
1397 perror("Could not stat file");
1398 exit(EXIT_FAILURE);
1400 int size = buf.st_size;
1402 printf("File %s is %d bytes\n", filename, size);
1404 char *image = malloc(size);
1405 if (!image) {
1406 printf("Out of memory.\n");
1407 exit(EXIT_FAILURE);
1410 if (read(bios_fd, image, size) != size) {
1411 perror("Could not read file");
1412 exit(EXIT_FAILURE);
1415 close(bios_fd);
1417 check_ifd_version(image, size);
1419 if (mode_dump)
1420 dump_fd(image, size);
1422 if (mode_layout)
1423 dump_layout(image, size, layout_fname);
1425 if (mode_extract)
1426 write_regions(image, size);
1428 if (mode_inject)
1429 inject_region(filename, image, size, region_type,
1430 region_fname);
1432 if (mode_newlayout)
1433 new_layout(filename, image, size, layout_fname);
1435 if (mode_spifreq)
1436 set_spi_frequency(filename, image, size, spifreq);
1438 if (mode_density)
1439 set_chipdensity(filename, image, size, new_density);
1441 if (mode_em100)
1442 set_em100_mode(filename, image, size);
1444 if (mode_locked)
1445 lock_descriptor(filename, image, size);
1447 if (mode_unlocked)
1448 unlock_descriptor(filename, image, size);
1450 free(image);
1452 return 0;