blob: 7154bc9d54254d641fee4de2902ddcb629780cb7 [file] [log] [blame]
Patrick Georgiea063cb2020-05-08 19:28:13 +02001/* common utility functions for cbfstool */
Patrick Georgi7333a112020-05-08 20:48:04 +02002/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Georgib7b56dd82009-09-14 13:29:27 +00003
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
Sol Boucher0e539312015-03-05 15:38:03 -08007#include <strings.h>
Patrick Georgi32eeff42014-08-11 09:27:18 +02008#include <sys/types.h>
9#include <sys/stat.h>
10#include <unistd.h>
Uwe Hermann942a40d2010-02-10 19:52:35 +000011#include <libgen.h>
Patrick Georgib7b56dd82009-09-14 13:29:27 +000012#include "common.h"
13#include "cbfs.h"
Patrick Georgib7b56dd82009-09-14 13:29:27 +000014
Hung-Te Lin332795c2013-01-28 15:53:34 +080015/* Utilities */
Aaron Durbinfae75172014-03-05 15:02:21 -060016int verbose = 0;
Hung-Te Lin332795c2013-01-28 15:53:34 +080017
Patrick Georgi32eeff42014-08-11 09:27:18 +020018static off_t get_file_size(FILE *f)
19{
Stefan Reinauer1bb487c2015-09-14 10:46:44 -070020 off_t fsize;
21 fseek(f, 0, SEEK_END);
22 fsize = ftell(f);
23 fseek(f, 0, SEEK_SET);
24 return fsize;
Patrick Georgi32eeff42014-08-11 09:27:18 +020025}
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080026
Stefan Reinauer1bb487c2015-09-14 10:46:44 -070027/* Buffer and file I/O */
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010028int buffer_create(struct buffer *buffer, size_t size, const char *name)
29{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080030 buffer->name = strdup(name);
Sol Boucher64c6cd72015-04-26 02:32:43 -070031 buffer->offset = 0;
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080032 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);
Shaik Shahina425413c2022-11-05 01:07:06 +053037 if (buffer->name) {
38 free(buffer->name);
39 buffer->name = NULL;
40 }
41 return -1;
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080042 }
Shaik Shahina425413c2022-11-05 01:07:06 +053043 return 0;
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080044}
45
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070046int buffer_from_file_aligned_size(struct buffer *buffer, const char *filename,
47 size_t size_granularity)
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010048{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080049 FILE *fp = fopen(filename, "rb");
50 if (!fp) {
51 perror(filename);
52 return -1;
53 }
Patrick Georgi80998032016-12-14 16:16:47 +010054 off_t file_size = get_file_size(fp);
55 if (file_size < 0) {
Patrick Georgi32eeff42014-08-11 09:27:18 +020056 fprintf(stderr, "could not determine size of %s\n", filename);
57 fclose(fp);
58 return -1;
59 }
Edward O'Callaghan01dbba52022-06-15 11:00:33 +100060 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 }
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070065 if (fread(buffer->data, 1, file_size, fp) != (size_t)file_size) {
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080066 fprintf(stderr, "incomplete read: %s\n", filename);
67 fclose(fp);
Sol Bouchere3260a02015-03-25 13:40:08 -070068 buffer_delete(buffer);
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080069 return -1;
70 }
71 fclose(fp);
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070072
73 if (buffer->size > (size_t)file_size)
74 memset(buffer->data + file_size, 0xff, buffer->size - file_size);
75
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080076 return 0;
77}
78
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070079int buffer_from_file(struct buffer *buffer, const char *filename)
80{
81 return buffer_from_file_aligned_size(buffer, filename, 1);
82}
83
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010084int buffer_write_file(struct buffer *buffer, const char *filename)
85{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080086 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
Stefan Reinauer2dd161f2015-03-04 00:55:03 +0100101void buffer_delete(struct buffer *buffer)
102{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +0800103 assert(buffer);
104 if (buffer->name) {
105 free(buffer->name);
106 buffer->name = NULL;
107 }
108 if (buffer->data) {
Patrick Georgi9b24f7c2015-11-11 18:43:11 +0100109 free(buffer_get_original_backing(buffer));
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +0800110 buffer->data = NULL;
111 }
Sol Boucher64c6cd72015-04-26 02:32:43 -0700112 buffer->offset = 0;
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +0800113 buffer->size = 0;
114}
115
David Hendricks90ca3b62012-11-16 14:48:22 -0800116static struct {
117 uint32_t arch;
118 const char *name;
119} arch_names[] = {
Furquan Shaikh2af76f42014-04-28 16:39:40 -0700120 { CBFS_ARCHITECTURE_AARCH64, "arm64" },
Gabe Black51edd542013-09-30 23:00:33 -0700121 { CBFS_ARCHITECTURE_ARM, "arm" },
Paul Burton33186922014-06-13 23:56:45 +0100122 { CBFS_ARCHITECTURE_MIPS, "mips" },
Ronald G. Minniched4aa042015-12-11 18:19:52 +0000123 { CBFS_ARCHITECTURE_PPC64, "ppc64" },
124 /* power8 is a reasonable alias */
125 { CBFS_ARCHITECTURE_PPC64, "power8" },
Ronald G. Minnich833bf202014-10-16 10:55:39 +0000126 { CBFS_ARCHITECTURE_RISCV, "riscv" },
David Hendricks90ca3b62012-11-16 14:48:22 -0800127 { CBFS_ARCHITECTURE_X86, "x86" },
128 { CBFS_ARCHITECTURE_UNKNOWN, "unknown" }
129};
130
131uint32_t string_to_arch(const char *arch_string)
132{
Furquan Shaikh161d2332016-05-26 14:41:02 -0700133 size_t i;
David Hendricks90ca3b62012-11-16 14:48:22 -0800134 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
Stefan Reinauer8f50e532013-11-13 14:34:57 -0800146const char *arch_to_string(uint32_t a)
147{
Furquan Shaikh161d2332016-05-26 14:41:02 -0700148 size_t i;
Stefan Reinauer8f50e532013-11-13 14:34:57 -0800149 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
Jonathan Neuschäferfbc66b92018-04-08 15:05:09 +0200161void 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
Stefan Reinauer07040582010-04-24 21:24:06 +0000173void print_supported_filetypes(void)
174{
Nico Huberf22f4082021-06-22 13:49:44 +0000175 int i;
Stefan Reinauer07040582010-04-24 21:24:06 +0000176
Nico Huberf22f4082021-06-22 13:49:44 +0000177 for (i=0; filetypes[i].name; i++) {
178 printf(" %s%c", filetypes[i].name, filetypes[i + 1].name ? ',' : '\n');
Stefan Reinauer07040582010-04-24 21:24:06 +0000179 if ((i%8) == 7)
Jonathan Neuschäfere32cea12018-04-08 15:05:09 +0200180 printf("\n");
Stefan Reinauer07040582010-04-24 21:24:06 +0000181 }
182}
183
Patrick Georgib7b56dd82009-09-14 13:29:27 +0000184uint64_t intfiletype(const char *name)
185{
Mathias Krause41c229c2012-07-17 21:17:15 +0200186 size_t i;
Nico Huberf22f4082021-06-22 13:49:44 +0000187 for (i = 0; filetypes[i].name; i++)
Patrick Georgib7b56dd82009-09-14 13:29:27 +0000188 if (strcmp(filetypes[i].name, name) == 0)
189 return filetypes[i].type;
190 return -1;
191}
Patrick Georgica97fa72015-10-01 15:52:56 +0200192
193char *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}