xref: /aosp_15_r20/external/coreboot/util/cbfstool/common.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* common utility functions for cbfstool */
2 /* SPDX-License-Identifier: GPL-2.0-only */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <strings.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <libgen.h>
12 #include "common.h"
13 #include "cbfs.h"
14 
15 /* Utilities */
16 int verbose = 0;
17 
get_file_size(FILE * f)18 static off_t get_file_size(FILE *f)
19 {
20 	off_t fsize;
21 	fseek(f, 0, SEEK_END);
22 	fsize = ftell(f);
23 	fseek(f, 0, SEEK_SET);
24 	return fsize;
25 }
26 
27 /* Buffer and file I/O */
buffer_create(struct buffer * buffer,size_t size,const char * name)28 int buffer_create(struct buffer *buffer, size_t size, const char *name)
29 {
30 	buffer->name = strdup(name);
31 	buffer->offset = 0;
32 	buffer->size = size;
33 	buffer->data = (char *)malloc(buffer->size);
34 	if (!buffer->data) {
35 		fprintf(stderr, "buffer_create: Insufficient memory (0x%zx).\n",
36 			size);
37 		if (buffer->name) {
38 			free(buffer->name);
39 			buffer->name = NULL;
40 		}
41 		return -1;
42 	}
43 	return 0;
44 }
45 
buffer_from_file_aligned_size(struct buffer * buffer,const char * filename,size_t size_granularity)46 int buffer_from_file_aligned_size(struct buffer *buffer, const char *filename,
47 				  size_t size_granularity)
48 {
49 	FILE *fp = fopen(filename, "rb");
50 	if (!fp) {
51 		perror(filename);
52 		return -1;
53 	}
54 	off_t file_size = get_file_size(fp);
55 	if (file_size < 0) {
56 		fprintf(stderr, "could not determine size of %s\n", filename);
57 		fclose(fp);
58 		return -1;
59 	}
60 	if (buffer_create(buffer, ALIGN_UP(file_size, size_granularity), filename)) {
61 		fprintf(stderr, "could not allocate buffer\n");
62 		fclose(fp);
63 		return -1;
64 	}
65 	if (fread(buffer->data, 1, file_size, fp) != (size_t)file_size) {
66 		fprintf(stderr, "incomplete read: %s\n", filename);
67 		fclose(fp);
68 		buffer_delete(buffer);
69 		return -1;
70 	}
71 	fclose(fp);
72 
73 	if (buffer->size > (size_t)file_size)
74 		memset(buffer->data + file_size, 0xff, buffer->size - file_size);
75 
76 	return 0;
77 }
78 
buffer_from_file(struct buffer * buffer,const char * filename)79 int buffer_from_file(struct buffer *buffer, const char *filename)
80 {
81 	return buffer_from_file_aligned_size(buffer, filename, 1);
82 }
83 
buffer_write_file(struct buffer * buffer,const char * filename)84 int buffer_write_file(struct buffer *buffer, const char *filename)
85 {
86 	FILE *fp = fopen(filename, "wb");
87 	if (!fp) {
88 		perror(filename);
89 		return -1;
90 	}
91 	assert(buffer && buffer->data);
92 	if (fwrite(buffer->data, 1, buffer->size, fp) != buffer->size) {
93 		fprintf(stderr, "incomplete write: %s\n", filename);
94 		fclose(fp);
95 		return -1;
96 	}
97 	fclose(fp);
98 	return 0;
99 }
100 
buffer_delete(struct buffer * buffer)101 void buffer_delete(struct buffer *buffer)
102 {
103 	assert(buffer);
104 	if (buffer->name) {
105 		free(buffer->name);
106 		buffer->name = NULL;
107 	}
108 	if (buffer->data) {
109 		free(buffer_get_original_backing(buffer));
110 		buffer->data = NULL;
111 	}
112 	buffer->offset = 0;
113 	buffer->size = 0;
114 }
115 
116 static struct {
117 	uint32_t arch;
118 	const char *name;
119 } arch_names[] = {
120 	{ CBFS_ARCHITECTURE_AARCH64, "arm64" },
121 	{ CBFS_ARCHITECTURE_ARM, "arm" },
122 	{ CBFS_ARCHITECTURE_MIPS, "mips" },
123 	{ CBFS_ARCHITECTURE_PPC64, "ppc64" },
124 	/* power8 is a reasonable alias */
125 	{ CBFS_ARCHITECTURE_PPC64, "power8" },
126 	{ CBFS_ARCHITECTURE_RISCV, "riscv" },
127 	{ CBFS_ARCHITECTURE_X86, "x86" },
128 	{ CBFS_ARCHITECTURE_UNKNOWN, "unknown" }
129 };
130 
string_to_arch(const char * arch_string)131 uint32_t string_to_arch(const char *arch_string)
132 {
133 	size_t i;
134 	uint32_t ret = CBFS_ARCHITECTURE_UNKNOWN;
135 
136 	for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
137 		if (!strcasecmp(arch_string, arch_names[i].name)) {
138 			ret = arch_names[i].arch;
139 			break;
140 		}
141 	}
142 
143 	return ret;
144 }
145 
arch_to_string(uint32_t a)146 const char *arch_to_string(uint32_t a)
147 {
148         size_t i;
149 	const char *ret = NULL;
150 
151 	for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
152 		if (a == arch_names[i].arch) {
153 			ret = arch_names[i].name;
154 			break;
155 		}
156 	}
157 
158 	return ret;
159 }
160 
print_supported_architectures(void)161 void print_supported_architectures(void)
162 {
163 	size_t i;
164 
165 	for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
166 		printf(i == 0? "  ":", ");
167 		printf("%s", arch_names[i].name);
168 	}
169 
170 	printf("\n");
171 }
172 
print_supported_filetypes(void)173 void print_supported_filetypes(void)
174 {
175 	int i;
176 
177 	for (i=0; filetypes[i].name; i++) {
178 		printf(" %s%c", filetypes[i].name, filetypes[i + 1].name ? ',' : '\n');
179 		if ((i%8) == 7)
180 			printf("\n");
181 	}
182 }
183 
intfiletype(const char * name)184 uint64_t intfiletype(const char *name)
185 {
186 	size_t i;
187 	for (i = 0; filetypes[i].name; i++)
188 		if (strcmp(filetypes[i].name, name) == 0)
189 			return filetypes[i].type;
190 	return -1;
191 }
192 
bintohex(uint8_t * data,size_t len)193 char *bintohex(uint8_t *data, size_t len)
194 {
195 	static const char translate[16] = "0123456789abcdef";
196 
197 	char *result = malloc(len * 2 + 1);
198 	if (result == NULL)
199 		return NULL;
200 
201 	result[len*2] = '\0';
202 	unsigned int i;
203 	for (i = 0; i < len; i++) {
204 		result[i*2] = translate[(data[i] >> 4) & 0xf];
205 		result[i*2+1] = translate[data[i] & 0xf];
206 	}
207 	return result;
208 }
209