common.c
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 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 */ 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 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 79 int buffer_from_file(struct buffer *buffer, const char *filename) 80 { 81 return buffer_from_file_aligned_size(buffer, filename, 1); 82 } 83 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 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 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 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 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 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 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 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 }