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.
22 #include <sys/types.h>
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" },
40 { "Platform Data", "pd" },
41 { "Reserved", "res1" },
42 { "Reserved", "res2" },
43 { "Reserved", "res3" },
47 static fdbar_t
*find_fd(char *image
, int size
)
51 /* Scan for FD signature */
52 for (i
= 0; i
< (size
- 4); i
+= 4) {
53 if (*(uint32_t *) (image
+ i
) == 0x0FF0A55A) {
55 break; // signature found.
60 printf("No Flash Descriptor found in this image\n");
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
);
81 fcba
= (fcba_t
*) (image
+ (((fdb
->flmap0
) & 0xff) << 4));
85 read_freq
= (fcba
->flcomp
>> 17) & 7;
88 case SPI_FREQUENCY_20MHZ
:
89 ifd_version
= IFD_VERSION_1
;
90 max_regions
= MAX_REGIONS_OLD
;
92 case SPI_FREQUENCY_17MHZ
:
93 ifd_version
= IFD_VERSION_2
;
94 max_regions
= MAX_REGIONS
;
97 fprintf(stderr
, "Unknown descriptor version: %d\n",
103 static region_t
get_region(frba_t
*frba
, int region_type
)
110 if (ifd_version
>= IFD_VERSION_2
)
115 limit_mask
= base_mask
<< 16;
117 switch (region_type
) {
119 flreg
= &frba
->flreg0
;
122 flreg
= &frba
->flreg1
;
125 flreg
= &frba
->flreg2
;
128 flreg
= &frba
->flreg3
;
131 flreg
= &frba
->flreg4
;
134 flreg
= &frba
->flreg5
;
137 flreg
= &frba
->flreg6
;
140 flreg
= &frba
->flreg7
;
143 flreg
= &frba
->flreg8
;
146 fprintf(stderr
, "Invalid region type %d.\n", region_type
);
150 region
.base
= (*flreg
& base_mask
) << 12;
151 region
.limit
= ((*flreg
& limit_mask
) >> 4) | 0xfff;
152 region
.size
= region
.limit
- region
.base
+ 1;
160 static void set_region(frba_t
*frba
, int region_type
, region_t region
)
162 switch (region_type
) {
164 frba
->flreg0
= (((region
.limit
>> 12) & 0x7fff) << 16)
165 | ((region
.base
>> 12) & 0x7fff);
168 frba
->flreg1
= (((region
.limit
>> 12) & 0x7fff) << 16)
169 | ((region
.base
>> 12) & 0x7fff);
172 frba
->flreg2
= (((region
.limit
>> 12) & 0x7fff) << 16)
173 | ((region
.base
>> 12) & 0x7fff);
176 frba
->flreg3
= (((region
.limit
>> 12) & 0x7fff) << 16)
177 | ((region
.base
>> 12) & 0x7fff);
180 frba
->flreg4
= (((region
.limit
>> 12) & 0x7fff) << 16)
181 | ((region
.base
>> 12) & 0x7fff);
184 fprintf(stderr
, "Invalid region type.\n");
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");
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");
206 return region_names
[region_type
].terse
;
209 static int region_num(const char *name
)
213 for (i
= 0; i
< max_regions
; i
++) {
214 if (strcasecmp(name
, region_names
[i
].pretty
) == 0)
216 if (strcasecmp(name
, region_names
[i
].terse
) == 0)
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
);
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
;
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");
299 for (i
= 0; i
< max_regions
; i
++) {
300 region_t region
= get_region(frba
, i
);
301 /* is region invalid? */
305 dump_region_layout(buf
, bufsize
, i
, frba
);
306 if (write(layout_fd
, buf
, strlen(buf
)) < 0) {
307 perror("Could not write to file");
312 printf("Wrote layout to %s\n", layout_fname
);
315 static void decode_spi_frequency(unsigned int freq
)
318 case SPI_FREQUENCY_20MHZ
:
321 case SPI_FREQUENCY_33MHZ
:
324 case SPI_FREQUENCY_48MHZ
:
327 case SPI_FREQUENCY_50MHZ_30MHZ
:
328 switch (ifd_version
) {
337 case SPI_FREQUENCY_17MHZ
:
341 printf("unknown<%x>MHz", freq
);
345 static void decode_component_density(unsigned int density
)
348 case COMPONENT_DENSITY_512KB
:
351 case COMPONENT_DENSITY_1MB
:
354 case COMPONENT_DENSITY_2MB
:
357 case COMPONENT_DENSITY_4MB
:
360 case COMPONENT_DENSITY_8MB
:
363 case COMPONENT_DENSITY_16MB
:
366 case COMPONENT_DENSITY_32MB
:
369 case COMPONENT_DENSITY_64MB
:
372 case COMPONENT_DENSITY_UNUSED
:
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
) {
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);
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);
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",
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
;
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",
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",
526 printf(" SPI Componend Device ID 0: 0x%02x\n",
528 printf(" SPI Componend Vendor ID: 0x%02x\n",
532 static void dump_vscc(uint32_t vscc
)
534 printf(" Lower Erase Opcode: 0x%02x\n",
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) {
545 printf("256 Byte\n");
558 printf(" Upper Erase Opcode: 0x%02x\n",
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) {
569 printf("256 Byte\n");
583 static void dump_vtba(vtba_t
*vtba
, int vtl
)
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
);
598 static void dump_oem(uint8_t *oem
)
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
]);
611 static void dump_fd(char *image
, int size
)
613 fdbar_t
*fdb
= find_fd(image
, size
);
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);
639 (image
+ ((fdb
->flumap1
& 0xff) << 4)),
640 (fdb
->flumap1
>> 8) & 0xff);
641 dump_oem((uint8_t *)image
+ 0xf00);
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
);
657 dump_frba_layout((frba_t
*)
658 (image
+ (((fdb
->flmap0
>> 16) & 0xff) << 4)),
662 static void write_regions(char *image
, int size
)
666 fdbar_t
*fdb
= find_fd(image
, size
);
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) {
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
);
682 perror("Error while trying to open file");
685 if (write(region_fd
, image
+ region
.base
, region
.size
) != region
.size
)
686 perror("Error while writing");
692 static void write_image(char *filename
, char *image
, int size
)
694 char new_filename
[FILENAME_MAX
]; // allow long file names
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
);
708 perror("Error while trying to open file");
711 if (write(new_fd
, image
, size
) != size
)
712 perror("Error while writing");
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));
740 switch (ifd_version
) {
742 freq
= SPI_FREQUENCY_20MHZ
;
745 freq
= SPI_FREQUENCY_17MHZ
;
748 freq
= SPI_FREQUENCY_17MHZ
;
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
);
766 switch (ifd_version
) {
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");
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");
782 printf("error: Unknown IFD version\n");
787 /* clear chip density for corresponding chip */
788 switch (selected_chip
) {
790 fcba
->flcomp
&= ~(0x7);
793 fcba
->flcomp
&= ~(0x7 << 3);
795 default: /*both chips*/
796 fcba
->flcomp
&= ~(0x3F);
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
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;
827 wr_shift
= FLMSTR_WR_SHIFT_V1
;
828 rd_shift
= FLMSTR_RD_SHIFT_V1
;
833 fmba
->flmstr3
= 0x118;
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
;
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
;
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);
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
,
888 fdbar_t
*fdb
= find_fd(image
, size
);
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
));
901 int region_fd
= open(region_fname
, O_RDONLY
| O_BINARY
);
902 if (region_fd
== -1) {
903 perror("Could not open file");
907 if (fstat(region_fd
, &buf
) == -1) {
908 perror("Could not stat file");
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
);
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
);
940 if (read(region_fd
, image
+ region
.base
+ offset
, region_size
)
942 perror("Could not read file");
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
)
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))
976 if ( ((r1
.base
>= r2
.base
) && (r1
.base
<= r2
.limit
)) ||
977 ((r1
.limit
>= r2
.base
) && (r1
.limit
<= r2
.limit
)) )
983 void new_layout(char *filename
, char *image
, int size
, char *layout_fname
)
987 char layout_region_name
[256];
990 region_t current_regions
[MAX_REGIONS
];
991 region_t new_regions
[MAX_REGIONS
];
995 /* load current descriptor map and regions */
996 fdbar_t
*fdb
= find_fd(image
, size
);
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");
1012 perror("Could not read layout file.\n");
1016 while (!feof(romlayout
)) {
1017 char *tstr1
, *tstr2
;
1019 if (2 != fscanf(romlayout
, "%255s %255s\n", tempstr
,
1020 layout_region_name
))
1023 region_number
= region_num(layout_region_name
);
1024 if (region_number
< 0)
1027 tstr1
= strtok(tempstr
, ":");
1028 tstr2
= strtok(NULL
, ":");
1029 if (!tstr1
|| !tstr2
) {
1030 fprintf(stderr
, "Could not parse layout file.\n");
1033 new_regions
[region_number
].base
= strtol(tstr1
,
1035 new_regions
[region_number
].limit
= strtol(tstr2
,
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;
1046 /* check new layout */
1047 for (i
= 0; i
< max_regions
; i
++) {
1048 if (new_regions
[i
].size
== 0)
1051 if (new_regions
[i
].size
< current_regions
[i
].size
) {
1052 printf("DANGER: Region %s is shrinking.\n",
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");
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
];
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
,
1112 /* update new descriptor regions */
1113 fdb
= find_fd(new_image
, new_extent
);
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
);
1126 static void print_version(void)
1128 printf("ifdtool v%s -- ", IFDTOOL_VERSION
);
1129 printf("Copyright (C) 2011 Google Inc.\n\n");
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
);
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"
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'},
1195 while ((opt
= getopt_long(argc
, argv
, "df:D:C:xi:n:s:p:eluvh?",
1196 long_options
, &option_index
)) != EOF
) {
1203 layout_fname
= strdup(optarg
);
1204 if (!layout_fname
) {
1205 fprintf(stderr
, "No layout file specified\n");
1206 print_usage(argv
[0]);
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]);
1221 region_fname
[0] = '\0';
1223 // Descriptor, BIOS, ME, GbE, Platform
1225 if (!strcasecmp("Descriptor", region_type_string
))
1227 else if (!strcasecmp("BIOS", region_type_string
))
1229 else if (!strcasecmp("ME", region_type_string
))
1231 else if (!strcasecmp("GbE", region_type_string
))
1233 else if (!strcasecmp("Platform", region_type_string
))
1235 else if (!strcasecmp("EC", region_type_string
))
1237 if (region_type
== -1) {
1238 fprintf(stderr
, "No such region type: '%s'\n\n",
1239 region_type_string
);
1240 print_usage(argv
[0]);
1247 layout_fname
= strdup(optarg
);
1248 if (!layout_fname
) {
1249 fprintf(stderr
, "No layout file specified\n");
1250 print_usage(argv
[0]);
1256 new_density
= strtoul(optarg
, NULL
, 0);
1257 switch (new_density
) {
1259 new_density
= COMPONENT_DENSITY_512KB
;
1262 new_density
= COMPONENT_DENSITY_1MB
;
1265 new_density
= COMPONENT_DENSITY_2MB
;
1268 new_density
= COMPONENT_DENSITY_4MB
;
1271 new_density
= COMPONENT_DENSITY_8MB
;
1274 new_density
= COMPONENT_DENSITY_16MB
;
1277 new_density
= COMPONENT_DENSITY_32MB
;
1280 new_density
= COMPONENT_DENSITY_64MB
;
1283 new_density
= COMPONENT_DENSITY_UNUSED
;
1286 printf("error: Unknown density\n");
1287 print_usage(argv
[0]);
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]);
1300 // Parse the requested SPI frequency
1301 inputfreq
= strtol(optarg
, NULL
, 0);
1302 switch (inputfreq
) {
1304 spifreq
= SPI_FREQUENCY_17MHZ
;
1307 spifreq
= SPI_FREQUENCY_20MHZ
;
1310 spifreq
= SPI_FREQUENCY_50MHZ_30MHZ
;
1313 spifreq
= SPI_FREQUENCY_33MHZ
;
1316 spifreq
= SPI_FREQUENCY_48MHZ
;
1319 spifreq
= SPI_FREQUENCY_50MHZ_30MHZ
;
1322 fprintf(stderr
, "Invalid SPI Frequency: %d\n",
1324 print_usage(argv
[0]);
1334 if (mode_unlocked
== 1) {
1335 fprintf(stderr
, "Locking/Unlocking FD and ME are mutually exclusive\n");
1341 if (mode_locked
== 1) {
1342 fprintf(stderr
, "Locking/Unlocking FD and ME are mutually exclusive\n");
1347 if (!strcmp(optarg
, "aplk")) {
1348 platform
= PLATFORM_APOLLOLAKE
;
1350 fprintf(stderr
, "Unknown platform: %s\n", optarg
);
1361 print_usage(argv
[0]);
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]);
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]);
1383 if (optind
+ 1 != argc
) {
1384 fprintf(stderr
, "You need to specify a file.\n\n");
1385 print_usage(argv
[0]);
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");
1396 if (fstat(bios_fd
, &buf
) == -1) {
1397 perror("Could not stat file");
1400 int size
= buf
.st_size
;
1402 printf("File %s is %d bytes\n", filename
, size
);
1404 char *image
= malloc(size
);
1406 printf("Out of memory.\n");
1410 if (read(bios_fd
, image
, size
) != size
) {
1411 perror("Could not read file");
1417 check_ifd_version(image
, size
);
1420 dump_fd(image
, size
);
1423 dump_layout(image
, size
, layout_fname
);
1426 write_regions(image
, size
);
1429 inject_region(filename
, image
, size
, region_type
,
1433 new_layout(filename
, image
, size
, layout_fname
);
1436 set_spi_frequency(filename
, image
, size
, spifreq
);
1439 set_chipdensity(filename
, image
, size
, new_density
);
1442 set_em100_mode(filename
, image
, size
);
1445 lock_descriptor(filename
, image
, size
);
1448 unlock_descriptor(filename
, image
, size
);