blob: 8ae9120acc3077248bc78213307aa835e15f2b9e [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);
37 }
38 return (buffer->data == NULL);
39}
40
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070041int buffer_from_file_aligned_size(struct buffer *buffer, const char *filename,
42 size_t size_granularity)
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010043{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080044 FILE *fp = fopen(filename, "rb");
45 if (!fp) {
46 perror(filename);
47 return -1;
48 }
Patrick Georgi80998032016-12-14 16:16:47 +010049 off_t file_size = get_file_size(fp);
50 if (file_size < 0) {
Patrick Georgi32eeff42014-08-11 09:27:18 +020051 fprintf(stderr, "could not determine size of %s\n", filename);
52 fclose(fp);
53 return -1;
54 }
Edward O'Callaghan01dbba52022-06-15 11:00:33 +100055 if (buffer_create(buffer, ALIGN_UP(file_size, size_granularity), filename)) {
56 fprintf(stderr, "could not allocate buffer\n");
57 fclose(fp);
58 return -1;
59 }
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070060 if (fread(buffer->data, 1, file_size, fp) != (size_t)file_size) {
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080061 fprintf(stderr, "incomplete read: %s\n", filename);
62 fclose(fp);
Sol Bouchere3260a02015-03-25 13:40:08 -070063 buffer_delete(buffer);
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080064 return -1;
65 }
66 fclose(fp);
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070067
68 if (buffer->size > (size_t)file_size)
69 memset(buffer->data + file_size, 0xff, buffer->size - file_size);
70
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080071 return 0;
72}
73
Furquan Shaikh2bfef8d2021-06-25 23:55:51 -070074int buffer_from_file(struct buffer *buffer, const char *filename)
75{
76 return buffer_from_file_aligned_size(buffer, filename, 1);
77}
78
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010079int buffer_write_file(struct buffer *buffer, const char *filename)
80{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080081 FILE *fp = fopen(filename, "wb");
82 if (!fp) {
83 perror(filename);
84 return -1;
85 }
86 assert(buffer && buffer->data);
87 if (fwrite(buffer->data, 1, buffer->size, fp) != buffer->size) {
88 fprintf(stderr, "incomplete write: %s\n", filename);
89 fclose(fp);
90 return -1;
91 }
92 fclose(fp);
93 return 0;
94}
95
Stefan Reinauer2dd161f2015-03-04 00:55:03 +010096void buffer_delete(struct buffer *buffer)
97{
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +080098 assert(buffer);
99 if (buffer->name) {
100 free(buffer->name);
101 buffer->name = NULL;
102 }
103 if (buffer->data) {
Patrick Georgi9b24f7c2015-11-11 18:43:11 +0100104 free(buffer_get_original_backing(buffer));
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +0800105 buffer->data = NULL;
106 }
Sol Boucher64c6cd72015-04-26 02:32:43 -0700107 buffer->offset = 0;
Hung-Te Lin3cfacbf2013-01-30 00:43:46 +0800108 buffer->size = 0;
109}
110
David Hendricks90ca3b62012-11-16 14:48:22 -0800111static struct {
112 uint32_t arch;
113 const char *name;
114} arch_names[] = {
Furquan Shaikh2af76f42014-04-28 16:39:40 -0700115 { CBFS_ARCHITECTURE_AARCH64, "arm64" },
Gabe Black51edd542013-09-30 23:00:33 -0700116 { CBFS_ARCHITECTURE_ARM, "arm" },
Paul Burton33186922014-06-13 23:56:45 +0100117 { CBFS_ARCHITECTURE_MIPS, "mips" },
Ronald G. Minniched4aa042015-12-11 18:19:52 +0000118 { CBFS_ARCHITECTURE_PPC64, "ppc64" },
119 /* power8 is a reasonable alias */
120 { CBFS_ARCHITECTURE_PPC64, "power8" },
Ronald G. Minnich833bf202014-10-16 10:55:39 +0000121 { CBFS_ARCHITECTURE_RISCV, "riscv" },
David Hendricks90ca3b62012-11-16 14:48:22 -0800122 { CBFS_ARCHITECTURE_X86, "x86" },
123 { CBFS_ARCHITECTURE_UNKNOWN, "unknown" }
124};
125
126uint32_t string_to_arch(const char *arch_string)
127{
Furquan Shaikh161d2332016-05-26 14:41:02 -0700128 size_t i;
David Hendricks90ca3b62012-11-16 14:48:22 -0800129 uint32_t ret = CBFS_ARCHITECTURE_UNKNOWN;
130
131 for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
132 if (!strcasecmp(arch_string, arch_names[i].name)) {
133 ret = arch_names[i].arch;
134 break;
135 }
136 }
137
138 return ret;
139}
140
Stefan Reinauer8f50e532013-11-13 14:34:57 -0800141const char *arch_to_string(uint32_t a)
142{
Furquan Shaikh161d2332016-05-26 14:41:02 -0700143 size_t i;
Stefan Reinauer8f50e532013-11-13 14:34:57 -0800144 const char *ret = NULL;
145
146 for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
147 if (a == arch_names[i].arch) {
148 ret = arch_names[i].name;
149 break;
150 }
151 }
152
153 return ret;
154}
155
Jonathan Neuschäferfbc66b92018-04-08 15:05:09 +0200156void print_supported_architectures(void)
157{
158 size_t i;
159
160 for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
161 printf(i == 0? " ":", ");
162 printf("%s", arch_names[i].name);
163 }
164
165 printf("\n");
166}
167
Stefan Reinauer07040582010-04-24 21:24:06 +0000168void print_supported_filetypes(void)
169{
Nico Huberf22f4082021-06-22 13:49:44 +0000170 int i;
Stefan Reinauer07040582010-04-24 21:24:06 +0000171
Nico Huberf22f4082021-06-22 13:49:44 +0000172 for (i=0; filetypes[i].name; i++) {
173 printf(" %s%c", filetypes[i].name, filetypes[i + 1].name ? ',' : '\n');
Stefan Reinauer07040582010-04-24 21:24:06 +0000174 if ((i%8) == 7)
Jonathan Neuschäfere32cea12018-04-08 15:05:09 +0200175 printf("\n");
Stefan Reinauer07040582010-04-24 21:24:06 +0000176 }
177}
178
Patrick Georgib7b56dd82009-09-14 13:29:27 +0000179uint64_t intfiletype(const char *name)
180{
Mathias Krause41c229c2012-07-17 21:17:15 +0200181 size_t i;
Nico Huberf22f4082021-06-22 13:49:44 +0000182 for (i = 0; filetypes[i].name; i++)
Patrick Georgib7b56dd82009-09-14 13:29:27 +0000183 if (strcmp(filetypes[i].name, name) == 0)
184 return filetypes[i].type;
185 return -1;
186}
Patrick Georgica97fa72015-10-01 15:52:56 +0200187
188char *bintohex(uint8_t *data, size_t len)
189{
190 static const char translate[16] = "0123456789abcdef";
191
192 char *result = malloc(len * 2 + 1);
193 if (result == NULL)
194 return NULL;
195
196 result[len*2] = '\0';
197 unsigned int i;
198 for (i = 0; i < len; i++) {
199 result[i*2] = translate[(data[i] >> 4) & 0xf];
200 result[i*2+1] = translate[data[i] & 0xf];
201 }
202 return result;
203}