1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /* CSE Serger - Tool for stitching Intel CSE components */
12 #include "cse_serger.h"
14 #define NO_PARTITION_TYPE (-1)
16 static struct params
{
18 const char *partition_name
;
20 const char *output_dir
;
21 const char *image_name
;
22 const char *version_str
;
23 const char *input_file
;
24 struct region layout_regions
[BP_TOTAL
];
25 const char *layout_files
[BP_TOTAL
];
29 const char *version_str
;
30 const struct bpdt_ops
*ops
;
31 } bpdt_ops_table
[] = {
32 { "1.6", &bpdt_1_6_ops
},
33 { "1.7", &bpdt_1_7_ops
},
37 enum subpart_hdr_version version
;
38 const struct subpart_hdr_ops
*ops
;
39 } subpart_hdr_ops_table
[] = {
40 { SUBPART_HDR_VERSION_1
, &subpart_hdr_1_ops
},
41 { SUBPART_HDR_VERSION_2
, &subpart_hdr_2_ops
},
45 enum subpart_entry_version version
;
46 const struct subpart_entry_ops
*ops
;
47 } subpart_entry_ops_table
[] = {
48 { SUBPART_ENTRY_VERSION_1
, &subpart_entry_1_ops
},
51 enum bpdt_entry_type
{
81 struct buffer input_buff
;
83 const struct bpdt_ops
*bpdt_ops
;
84 const struct subpart_hdr_ops
*subpart_hdr_ops
;
85 const struct subpart_entry_ops
*subpart_entry_ops
;
87 bpdt_hdr_ptr bpdt_hdr
;
88 cse_layout_ptr cse_layout
;
89 struct bpdt_entry bpdt_entries
[MAX_SUBPARTS
];
90 struct buffer subpart_buff
[MAX_SUBPARTS
];
92 size_t file_end_offset
;
95 #define SUBPART_WITH_ALT(_index, _rname, _name, _aname) \
96 [_index] = { _rname, _name, _aname }
97 #define SUBPART(_index, _rname, _name) \
98 SUBPART_WITH_ALT(_index, _rname, _name, "")
100 static const struct {
101 const char *readable_name
;
103 const char *alt_name
;
105 SUBPART(SMIP
, "OEM SMIP", "SMIP"),
106 SUBPART(CSE_RBE
, "CSE RBE", "RBEP"),
107 SUBPART_WITH_ALT(CSE_BUP
, "CSE BUP", "FTPR", "MFTP"),
108 SUBPART(UCODE
, "Microcode", "UCOD"),
109 SUBPART(IBB
, "Initial Boot Block", "IBBP"),
110 SUBPART(S_BPDT
, "Secondary BPDT", "SBDT"),
111 SUBPART(OBB
, "OEM Boot Block", "OBBP"),
112 SUBPART(CSE_MAIN
, "CSE Main", "NFTP"),
113 SUBPART(ISH
, "ISH Firmware", "ISHP"),
114 SUBPART(CSE_IDLM
, "CSE IDLM", "DLMP"),
115 SUBPART(IFP_OVERRIDE
, "IFP override", "IFPP"),
116 SUBPART(UTOK
, "Debug tokens", "UTOK"),
117 SUBPART(UFS_PHY
, "UFS Phy", "UFSP"),
118 SUBPART(UFS_GPP
, "UFS GPP", "UFSG"),
119 SUBPART(PMC
, "PMC Firmware", "PMCP"),
120 SUBPART(IUNIT
, "IUNIT Firmware", "IUNP"),
121 SUBPART(NVM_CFG
, "NVM CFG", "NVMC"),
122 SUBPART(UEP
, "UEP", "UEPP"),
123 SUBPART(OEM_KM
, "OEM Key Manifest", "OEMP"),
124 SUBPART(PAVP
, "PAVP", "PAVP"),
125 SUBPART(IOM_FW
, "IOM Firmware", "IOMP"),
126 SUBPART(NPHY_FW
, "NPHY Firmware", "NPHY"),
127 SUBPART(TBT_FW
, "TBT Firmware", "TBTP"),
128 SUBPART(ICC
, "ICC Firmware", "PCHC"),
131 static const char *subpart_readable_name(enum bpdt_entry_type type
)
133 return subparts
[type
].readable_name
;
136 static const char *subpart_name(enum bpdt_entry_type type
)
138 return subparts
[type
].name
;
141 static const char *subpart_alt_name(enum bpdt_entry_type type
)
143 return subparts
[type
].alt_name
;
146 static struct buffer
*subpart_buff(int type
)
148 return &ifwi
.subpart_buff
[type
];
151 static int subpart_get_type_from_name(const char *name
)
155 for (i
= 0; i
< MAX_SUBPARTS
; i
++) {
156 if (subpart_name(i
) == NULL
)
159 if (!strcmp(subpart_name(i
), name
))
162 if (!strcmp(subpart_alt_name(i
), name
))
169 static const struct bpdt_ops
*get_bpdt_ops(const struct buffer
*buff
)
171 assert(buff
|| params
.version_str
);
173 for (size_t i
= 0; i
< ARRAY_SIZE(bpdt_ops_table
); i
++) {
174 if (params
.version_str
) {
175 if (!strcmp(params
.version_str
, bpdt_ops_table
[i
].version_str
))
176 return bpdt_ops_table
[i
].ops
;
180 if (bpdt_ops_table
[i
].ops
->match_version(buff
))
181 return bpdt_ops_table
[i
].ops
;
187 static const struct subpart_hdr_ops
*get_subpart_hdr_ops(void)
189 for (size_t i
= 0; i
< ARRAY_SIZE(subpart_hdr_ops_table
); i
++) {
190 if (subpart_hdr_ops_table
[i
].version
== ifwi
.bpdt_ops
->subpart_hdr_version
)
191 return subpart_hdr_ops_table
[i
].ops
;
197 static const struct subpart_entry_ops
*get_subpart_entry_ops(void)
199 for (size_t i
= 0; i
< ARRAY_SIZE(subpart_entry_ops_table
); i
++) {
200 if (subpart_entry_ops_table
[i
].version
== ifwi
.bpdt_ops
->subpart_entry_version
)
201 return subpart_entry_ops_table
[i
].ops
;
207 static int subpart_read(struct buffer
*input_buff
)
209 size_t input_size
= buffer_size(input_buff
);
210 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
213 for (size_t i
= 0; i
< ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
); i
++, e
++) {
217 if (e
->type
>= MAX_SUBPARTS
) {
218 ERROR("Invalid part type(%d)\n", e
->type
);
222 if (e
->offset
+ e
->size
> input_size
) {
223 ERROR("Part(%d) exceeds file size. Part offset=0x%x, Part size = 0x%x, File size = 0x%zx\n",
224 e
->type
, e
->offset
, e
->size
, input_size
);
228 buff
= subpart_buff(e
->type
);
229 if (buffer_size(buff
) != 0) {
230 ERROR("Multiple subparts of same type(%d %s)!\n",
231 e
->type
, subpart_name(e
->type
));
235 buffer_splice(buff
, input_buff
, e
->offset
, e
->size
);
241 static struct bpdt_entry
*find_bpdt_entry(uint32_t type
)
243 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
245 for (size_t i
= 0; i
< ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
); i
++, e
++) {
253 static struct bpdt_entry
*new_bpdt_entry(void)
255 size_t count
= ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
);
256 if (count
== MAX_SUBPARTS
) {
257 ERROR("No space for new BPDT entry!\n");
261 ifwi
.bpdt_ops
->inc_entry_count(ifwi
.bpdt_hdr
);
263 return &ifwi
.bpdt_entries
[count
];
266 static void set_file_end_offset(struct buffer
*buff
)
268 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
270 size_t count
= ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
);
272 ifwi
.file_end_offset
= ALIGN_UP(buffer_offset(buff
), BUFF_SIZE_ALIGN
);
274 for (size_t i
= 0; i
< count
; i
++, e
++) {
275 end_offset
= e
->offset
+ e
->size
;
276 if (end_offset
> ifwi
.file_end_offset
)
277 ifwi
.file_end_offset
= end_offset
;
282 static void read_bpdt_entries(struct buffer
*buff
)
284 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
285 size_t count
= ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
);
287 for (size_t i
= 0; i
< count
; i
++, e
++) {
288 READ_MEMBER(buff
, e
->type
);
289 READ_MEMBER(buff
, e
->offset
);
290 READ_MEMBER(buff
, e
->size
);
294 static int write_bpdt_entries(struct buffer
*buff
)
296 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
297 size_t count
= ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
);
299 if (buffer_size(buff
) < count
* sizeof(*e
)) {
300 ERROR("Not enough buffer space for bpdt entries!\n");
304 for (size_t i
= 0; i
< count
; i
++, e
++) {
305 WRITE_MEMBER(buff
, e
->type
);
306 WRITE_MEMBER(buff
, e
->offset
);
307 WRITE_MEMBER(buff
, e
->size
);
313 static void print_bpdt_entries(void)
315 const size_t count
= ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
);
320 const struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
322 printf("\n * BPDT entries\n");
324 printf("%-25s%-25s%-25s%-25s%-25s%-25s\n", "Entry #",
325 "Partition Name", "Human readable name", "Type", "Offset", "Size");
327 printf("===================================================================="
328 "====================================================================\n");
330 for (size_t i
= 0; i
< count
; i
++) {
331 printf("%-25zd%-25s%-25s%-25d0x%-23x0x%-23x"
332 "\n", i
+1, subpart_name(e
[i
].type
), subpart_readable_name(e
[i
].type
),
333 e
[i
].type
, e
[i
].offset
, e
[i
].size
);
336 printf("===================================================================="
337 "====================================================================\n");
340 static int ifwi_parse(const char *image_name
)
342 struct buffer
*input_buff
= &ifwi
.input_buff
;
343 struct buffer bpdt_buff
;
345 if (buffer_from_file(input_buff
, image_name
)) {
346 ERROR("Failed to read input file %s\n", image_name
);
350 buffer_clone(&bpdt_buff
, input_buff
);
352 ifwi
.bpdt_ops
= get_bpdt_ops(&bpdt_buff
);
353 if (!ifwi
.bpdt_ops
) {
354 ERROR("No matching bpdt_ops!\n");
358 ifwi
.bpdt_hdr
= ifwi
.bpdt_ops
->read_hdr(&bpdt_buff
);
359 if (ifwi
.bpdt_hdr
== NULL
)
362 read_bpdt_entries(&bpdt_buff
);
363 set_file_end_offset(&bpdt_buff
);
365 if (!ifwi
.bpdt_ops
->validate_checksum(ifwi
.bpdt_hdr
, &ifwi
.bpdt_entries
[0])) {
366 ERROR("Checksum failed!\n");
370 ifwi
.subpart_hdr_ops
= get_subpart_hdr_ops();
371 if (ifwi
.subpart_hdr_ops
== NULL
) {
372 ERROR("No matching subpart_hdr_ops for given BPDT!\n");
376 ifwi
.subpart_entry_ops
= get_subpart_entry_ops();
377 if (ifwi
.subpart_entry_ops
== NULL
) {
378 ERROR("No matching subpart_entry_ops for given BPDT!\n");
382 return subpart_read(&ifwi
.input_buff
);
385 static int subpart_write(struct buffer
*buff
)
387 struct bpdt_entry
*e
;
388 struct buffer
*s_buff
;
390 for (size_t i
= 0; i
< ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
); i
++) {
391 e
= &ifwi
.bpdt_entries
[i
];
396 if (e
->offset
+ e
->size
> buffer_size(buff
)) {
397 ERROR("Subpart end(0x%x) overflows buffer size(0x%zx)\n",
398 e
->offset
+ e
->size
, buffer_size(buff
));
402 s_buff
= subpart_buff(e
->type
);
404 if (buffer_size(s_buff
) != e
->size
) {
405 ERROR("Subpart buffer size does not match BPDT entry size!\n");
409 memcpy(buffer_get(buff
) + e
->offset
, buffer_get(s_buff
), e
->size
);
415 static int ifwi_repack(void)
420 struct buffer output_buff
;
421 const size_t size
= ifwi
.file_end_offset
;
422 struct buffer bpdt_buff
;
424 if (buffer_create(&output_buff
, size
, "Output IFWI")) {
425 ERROR("Unable to allocate output buff!\n");
429 buffer_clone(&bpdt_buff
, &output_buff
);
431 ifwi
.bpdt_ops
->update_checksum(ifwi
.bpdt_hdr
, &ifwi
.bpdt_entries
[0]);
433 if (ifwi
.bpdt_ops
->write_hdr(&bpdt_buff
, ifwi
.bpdt_hdr
))
436 if (write_bpdt_entries(&bpdt_buff
))
439 subpart_write(&output_buff
);
441 if (buffer_write_file(&output_buff
, params
.image_name
)) {
442 ERROR("File write error!\n");
446 printf("Image written successfully to %s.\n", params
.image_name
);
450 static bool should_process_partition(int type
)
452 if (params
.partition_name
) {
453 const char *name
= subpart_name(type
);
458 if (strcmp(params
.partition_name
, name
))
460 } else if (params
.partition_type
!= NO_PARTITION_TYPE
) {
461 if (params
.partition_type
!= type
)
468 static int process_entries(int (*fn
)(const struct bpdt_entry
*e
))
470 struct bpdt_entry
*e
= &ifwi
.bpdt_entries
[0];
473 for (size_t i
= 0; i
< ifwi
.bpdt_ops
->get_entry_count(ifwi
.bpdt_hdr
); i
++, e
++) {
477 if (!should_process_partition(e
->type
))
486 if (!found
&& params
.partition_name
) {
487 ERROR("Partition %s not found!\n", params
.partition_name
);
491 if (!found
&& params
.partition_type
!= NO_PARTITION_TYPE
) {
492 ERROR("Partition type %d not found!\n", params
.partition_type
);
499 static int print_subpart(const struct bpdt_entry
*e
)
504 printf("\n\n * Subpart entry #%d(%s)\n", e
->type
, subpart_readable_name(e
->type
));
506 buffer_clone(&buff
, subpart_buff(e
->type
));
507 hdr
= ifwi
.subpart_hdr_ops
->read(&buff
);
509 ERROR("Failed to read subpart header!\n");
513 ifwi
.subpart_hdr_ops
->print(hdr
);
514 ifwi
.subpart_entry_ops
->print(&buff
, ifwi
.subpart_hdr_ops
->get_entry_count(hdr
));
515 ifwi
.subpart_hdr_ops
->free(hdr
);
520 static int cmd_print(void)
522 ifwi
.bpdt_ops
->print_hdr(ifwi
.bpdt_hdr
);
523 print_bpdt_entries();
525 if (!params
.print_sub_parts
&& !params
.partition_name
&&
526 params
.partition_type
== NO_PARTITION_TYPE
)
529 return process_entries(print_subpart
);
532 static char *get_file_path(const char *name
)
534 size_t filename_len
= strlen(name
) + 1;
536 /* output_dir name followed by '/' */
537 if (params
.output_dir
)
538 filename_len
+= strlen(params
.output_dir
) + 1;
540 char *filepath
= malloc(filename_len
);
544 snprintf(filepath
, filename_len
, "%s%s%s",
545 params
.output_dir
? : "",
546 params
.output_dir
? "/" : "",
552 static int write_partition_to_file(const struct bpdt_entry
*e
)
554 size_t end_offset
= e
->offset
+ e
->size
- 1;
556 if (end_offset
> buffer_size(&ifwi
.input_buff
)) {
557 ERROR("Offset out of bounds!\n");
561 const char *name
= subpart_name(e
->type
);
562 char *filepath
= get_file_path(name
);
564 ERROR("Failed to allocate filepath!\n");
568 printf("Dumping %.4s in %s\n", name
, filepath
);
571 buffer_splice(&buff
, &ifwi
.input_buff
, e
->offset
, e
->size
);
572 buffer_write_file(&buff
, filepath
);
578 static int cmd_dump(void)
582 if (params
.output_dir
&& (stat(params
.output_dir
, &sb
) == -1)) {
583 ERROR("Failed to stat %s: %s\n", params
.output_dir
, strerror(errno
));
587 return process_entries(write_partition_to_file
);
590 static int cmd_print_layout(void)
592 if (params
.version_str
== NULL
) {
593 ERROR("No version provided!\n");
597 const struct bpdt_ops
*ops
= get_bpdt_ops(NULL
);
599 ERROR("No matching bpdt_ops!\n");
604 if (buffer_from_file(&buff
, params
.image_name
)) {
605 ERROR("Failed to read input file %s\n", params
.image_name
);
609 ifwi
.cse_layout
= ops
->read_layout(&buff
);
610 if (!ifwi
.cse_layout
) {
611 ERROR("Failed to read CSE layout!\n");
615 ops
->print_layout(ifwi
.cse_layout
);
620 static int allocate_buffer(struct buffer
*buff
, struct buffer
*wbuff
, const char *str
)
622 if (params
.version_str
== NULL
) {
623 ERROR("No version provided!\n");
627 ifwi
.bpdt_ops
= get_bpdt_ops(NULL
);
631 if (buffer_create(buff
, BUFF_SIZE_ALIGN
, str
)) {
632 ERROR("Buffer creation error!\n");
636 void *data
= buffer_get(buff
);
637 memset(data
, 0xff, buffer_size(buff
));
639 buffer_clone(wbuff
, buff
);
644 static size_t get_cse_region_end_offset(void)
649 for (size_t i
= 0; i
< BP_TOTAL
; i
++) {
650 end_offset
= region_end(¶ms
.layout_regions
[i
]);
651 if (end_offset
> offset
)
658 static int fill_layout_buffer(struct buffer
*buff
)
662 if (allocate_buffer(buff
, &wbuff
, "CSE layout"))
665 ifwi
.cse_layout
= ifwi
.bpdt_ops
->create_layout(¶ms
.layout_regions
[0]);
666 if (!ifwi
.cse_layout
) {
667 ERROR("Failed to create layout!\n");
671 if (ifwi
.bpdt_ops
->write_layout(&wbuff
, ifwi
.cse_layout
)) {
672 ERROR("Failed to write CSE layout!\n");
679 static int cmd_create_layout(void)
683 if (fill_layout_buffer(&buff
))
686 buffer_write_file(&buff
, params
.image_name
);
690 static int cmd_create_cse_region(void)
692 size_t file_size
= get_cse_region_end_offset();
693 struct buffer cse_buff
, layout_buff
;
695 if (fill_layout_buffer(&layout_buff
))
699 file_size
= buffer_size(&layout_buff
);
701 file_size
= ALIGN_UP(file_size
, BUFF_SIZE_ALIGN
);
702 if (buffer_create(&cse_buff
, file_size
, "CSE buff")) {
703 ERROR("CSE buffer creation error!\n");
707 memset(buffer_get(&cse_buff
), 0xff, buffer_size(&cse_buff
));
708 memcpy(buffer_get(&cse_buff
), buffer_get(&layout_buff
), buffer_size(&layout_buff
));
710 for (size_t i
= 0; i
< BP_TOTAL
; i
++) {
711 struct buffer wbuff
, rbuff
;
713 if (region_sz(¶ms
.layout_regions
[i
]) == 0)
716 buffer_clone(&wbuff
, &cse_buff
);
717 buffer_seek(&wbuff
, region_offset(¶ms
.layout_regions
[i
]));
719 if (params
.layout_files
[i
] == NULL
) {
721 ERROR("File name not provided for DP!\n");
723 ERROR("File name not provided for BP%zd!\n", i
);
728 if (buffer_from_file(&rbuff
, params
.layout_files
[i
])) {
729 ERROR("Failed to read %s\n", params
.layout_files
[i
]);
733 assert(buffer_size(&wbuff
) >= buffer_size(&rbuff
));
734 memcpy(buffer_get(&wbuff
), buffer_get(&rbuff
), buffer_size(&rbuff
));
737 buffer_write_file(&cse_buff
, params
.image_name
);
742 static int cmd_create_bpdt(void)
747 if (allocate_buffer(&buff
, &wbuff
, "BPDT header"))
750 ifwi
.bpdt_hdr
= ifwi
.bpdt_ops
->create_hdr();
751 if (!ifwi
.bpdt_hdr
) {
752 ERROR("Failed to create BPDT header!\n");
756 ifwi
.bpdt_ops
->update_checksum(ifwi
.bpdt_hdr
, NULL
);
758 if (ifwi
.bpdt_ops
->write_hdr(&wbuff
, ifwi
.bpdt_hdr
)) {
759 ERROR("Failed to write BPDT header!\n");
763 buffer_write_file(&buff
, params
.image_name
);
767 static int cmd_add(void)
769 if (!params
.partition_name
&& params
.partition_type
== NO_PARTITION_TYPE
) {
770 ERROR("Partition name/type is required for add!\n");
776 if (params
.partition_name
) {
777 type
= subpart_get_type_from_name(params
.partition_name
);
778 if (type
== NO_PARTITION_TYPE
) {
779 ERROR("Invalid partition %s\n", params
.partition_name
);
783 type
= params
.partition_type
;
784 if (type
> MAX_SUBPARTS
) {
785 ERROR("Invalid type %d\n", type
);
790 struct bpdt_entry
*e
= find_bpdt_entry(type
);
792 ERROR("Partition %s(%d) already exists!\n", params
.partition_name
? : "", type
);
796 e
= new_bpdt_entry();
806 if (params
.input_file
== NULL
)
809 struct buffer
*buff
= subpart_buff(type
);
810 if (buffer_from_file_aligned_size(buff
, params
.input_file
, BUFF_SIZE_ALIGN
)) {
811 ERROR("Failed to read input file %s\n", params
.input_file
);
815 e
->offset
= ALIGN_UP(ifwi
.file_end_offset
, BUFF_SIZE_ALIGN
);
816 e
->size
= buffer_size(buff
);
818 ifwi
.file_end_offset
= e
->offset
+ e
->size
;
823 static void parse_region(struct region
*r
, char *arg
)
827 tok
= strtok(arg
, ":");
828 r
->offset
= strtol(tok
, NULL
, 0);
830 tok
= strtok(NULL
, ":");
831 r
->size
= strtol(tok
, NULL
, 0);
834 static struct command
{
836 const char *optstring
;
840 { "print", "n:st:?", cmd_print
, true },
841 { "dump", "n:o:t:?", cmd_dump
, true },
842 { "create-layout", "v:?", cmd_create_layout
, false },
843 { "print-layout", "v:?", cmd_print_layout
, false },
844 { "create-bpdt", "v:?", cmd_create_bpdt
, false },
845 { "add", "f:n:t:v:?", cmd_add
, true },
846 { "create-cse-region", "v:?", cmd_create_cse_region
, false },
851 LONGOPT_BP1
= LONGOPT_START
,
865 static struct option long_options
[] = {
866 {"help", required_argument
, 0, 'h'},
867 {"parition_name", required_argument
, 0, 'n'},
868 {"output_dir", required_argument
, 0, 'o'},
869 {"sub_partition", no_argument
, 0, 's'},
870 {"version", required_argument
, 0, 'v'},
871 {"bp1", required_argument
, 0, LONGOPT_BP1
},
872 {"bp1_file", required_argument
, 0, LONGOPT_BP1_FILE
},
873 {"bp2", required_argument
, 0, LONGOPT_BP2
},
874 {"bp2_file", required_argument
, 0, LONGOPT_BP2_FILE
},
875 {"bp3", required_argument
, 0, LONGOPT_BP3
},
876 {"bp3_file", required_argument
, 0, LONGOPT_BP3_FILE
},
877 {"bp4", required_argument
, 0, LONGOPT_BP4
},
878 {"bp4_file", required_argument
, 0, LONGOPT_BP4_FILE
},
879 {"dp", required_argument
, 0, LONGOPT_DATA
},
880 {"dp_file", required_argument
, 0, LONGOPT_DATA_FILE
},
884 static bool valid_opt(size_t i
, int c
)
886 /* Check if it is one of the optstrings supported by the command. */
887 if (strchr(commands
[i
].optstring
, c
))
891 * Check if it is one of the non-ASCII characters. Currently, the
892 * non-ASCII characters are only checked against the valid list
893 * irrespective of the command.
895 return c
>= LONGOPT_START
&& c
< LONGOPT_END
;
898 static void usage(const char *name
)
900 printf("%s: Utility for stitching CSE components\n"
902 " %s FILE COMMAND\n\n"
904 " print [-s][-n NAME][-t TYPE]\n"
905 " dump [-o DIR][-n NAME]\n"
906 " create-layout --dp <offset:size> --bp* <offset:size> -v VERSION\n"
907 " create-cse-region --dp <offset:size> --dp_file <FILE> --bp* <offset:size>"
908 " --bp*_file <FILE> -v VERSION\n"
909 " print-layout -v VERSION\n"
910 " create-bpdt -v VERSION\n"
911 " add [-n NAME][-t TYPE][-f INPUT_FILE]\n"
913 " -f INPUT_FILE : Input file\n"
914 " -n NAME : Sub-partition name\n"
915 " -o DIR : Output directory\n"
916 " -s : Print sub-partition info\n"
917 " -t TYPE : Sub-partition type\n"
918 " -v VERSION : BPDT version\n"
919 " --dp <offset:size> : Offset and size of data partition\n"
920 " --dp_file <FILE> : File for data partition\n"
921 " --bp1 <offset:size> : Offset and size of BP1\n"
922 " --bp1_file <FILE> : File for BP1 partition\n"
923 " --bp2 <offset:size> : Offset and size of BP2\n"
924 " --bp2_file <FILE> : File for BP2 partition\n"
925 " --bp3 <offset:size> : Offset and size of BP3\n"
926 " --bp3_file <FILE> : File for BP3 partition\n"
927 " --bp4 <offset:size> : Offset and size of BP4\n"
928 " --bp4_file <FILE> : File for BP4 partition\n"
933 int main(int argc
, char **argv
)
936 printf("Incorrect number of args(%d)!\n", argc
);
941 const char *prog_name
= argv
[0];
942 const char *image_name
= argv
[1];
943 const char *cmd
= argv
[2];
947 params
.partition_type
= NO_PARTITION_TYPE
;
948 params
.image_name
= image_name
;
950 for (i
= 0; i
< ARRAY_SIZE(commands
); i
++) {
951 if (strcmp(cmd
, commands
[i
].name
))
958 c
= getopt_long(argc
, argv
, commands
[i
].optstring
,
959 long_options
, &option_index
);
964 if (!valid_opt(i
, c
)) {
965 if (c
< LONGOPT_START
) {
966 ERROR("Invalid option -- '%c'\n", c
);
968 ERROR("Invalid option -- '%d'\n", c
);
976 params
.input_file
= optarg
;
979 params
.partition_name
= optarg
;
982 params
.output_dir
= optarg
;
985 params
.print_sub_parts
= true;
988 params
.version_str
= optarg
;
991 params
.partition_type
= atoi(optarg
);
994 parse_region(¶ms
.layout_regions
[BP1
], optarg
);
997 parse_region(¶ms
.layout_regions
[BP2
], optarg
);
1000 parse_region(¶ms
.layout_regions
[BP3
], optarg
);
1003 parse_region(¶ms
.layout_regions
[BP4
], optarg
);
1006 parse_region(¶ms
.layout_regions
[DP
], optarg
);
1008 case LONGOPT_BP1_FILE
:
1009 params
.layout_files
[BP1
] = optarg
;
1011 case LONGOPT_BP2_FILE
:
1012 params
.layout_files
[BP2
] = optarg
;
1014 case LONGOPT_BP3_FILE
:
1015 params
.layout_files
[BP3
] = optarg
;
1017 case LONGOPT_BP4_FILE
:
1018 params
.layout_files
[BP4
] = optarg
;
1020 case LONGOPT_DATA_FILE
:
1021 params
.layout_files
[DP
] = optarg
;
1034 if (i
== ARRAY_SIZE(commands
)) {
1035 printf("No command match %s!\n", cmd
);
1040 if (commands
[i
].parse_ifwi
&& ifwi_parse(image_name
))
1043 if (commands
[i
].cb())
1046 return ifwi_repack();