mb/dell: Add Latitude E5520 (Sandy Bridge)
[coreboot.git] / util / cbfstool / cbfscomptool.c
blob5745093165fd6366c547073d9dfdb941ceda523b
1 /* cbfs-compression-tool, CLI utility for dealing with CBFS compressed data */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <strings.h>
8 #include <time.h>
10 #include "cbfs.h"
11 #include "common.h"
13 const char *usage_text = "cbfs-compression-tool benchmark\n"
14 " runs benchmarks for all implemented algorithms\n"
15 "cbfs-compression-tool compress inFile outFile algo\n"
16 " compresses inFile with algo and stores in outFile\n"
17 "\n"
18 "'compress' file format:\n"
19 " 4 bytes little endian: algorithm ID (as used in CBFS)\n"
20 " 4 bytes little endian: uncompressed size\n"
21 " ...: compressed data stream\n";
23 static void usage(void)
25 puts(usage_text);
28 static int benchmark(void)
30 const int bufsize = 10*1024*1024;
31 char *data = malloc(bufsize);
32 if (!data) {
33 fprintf(stderr, "out of memory\n");
34 return 1;
36 char *compressed_data = malloc(bufsize);
37 if (!compressed_data) {
38 free(data);
39 fprintf(stderr, "out of memory\n");
40 return 1;
42 int i, l = strlen(usage_text) + 1;
43 for (i = 0; i + l < bufsize; i += l) {
44 memcpy(data + i, usage_text, l);
46 memset(data + i, 0, bufsize - i);
47 const struct typedesc_t *algo;
48 for (algo = &types_cbfs_compression[0]; algo->name != NULL; algo++) {
49 int outsize = bufsize;
50 printf("measuring '%s'\n", algo->name);
51 comp_func_ptr comp = compression_function(algo->type);
52 if (comp == NULL) {
53 printf("no handler associated with algorithm\n");
54 free(data);
55 free(compressed_data);
56 return 1;
59 struct timespec t_s, t_e;
60 clock_gettime(CLOCK_MONOTONIC, &t_s);
62 if (comp(data, bufsize, compressed_data, &outsize)) {
63 printf("compression failed");
64 return 1;
67 clock_gettime(CLOCK_MONOTONIC, &t_e);
68 printf("compressing %d bytes to %d took %ld seconds\n",
69 bufsize, outsize,
70 (long)(t_e.tv_sec - t_s.tv_sec));
72 free(data);
73 free(compressed_data);
74 return 0;
77 static int compress(char *infile, char *outfile, char *algoname,
78 int write_header)
80 int err = 1;
81 FILE *fin = NULL;
82 FILE *fout = NULL;
83 void *indata = NULL;
85 const struct typedesc_t *algo = &types_cbfs_compression[0];
86 while (algo->name != NULL) {
87 if (strcasecmp(algo->name, algoname) == 0) break;
88 algo++;
90 if (algo->name == NULL) {
91 fprintf(stderr, "algo '%s' is not supported.\n", algoname);
92 return 1;
95 comp_func_ptr comp = compression_function(algo->type);
96 if (comp == NULL) {
97 printf("no handler associated with algorithm\n");
98 return 1;
101 fin = fopen(infile, "rb");
102 if (!fin) {
103 fprintf(stderr, "could not open '%s'\n", infile);
104 return 1;
106 fout = fopen(outfile, "wb");
107 if (!fout) {
108 fprintf(stderr, "could not open '%s' for writing\n", outfile);
109 goto out;
112 if (fseek(fin, 0, SEEK_END) != 0) {
113 fprintf(stderr, "could not seek in input\n");
114 goto out;
116 long insize = ftell(fin);
117 if (insize < 0) {
118 fprintf(stderr, "could not determine input size\n");
119 goto out;
121 rewind(fin);
123 indata = malloc(insize);
124 if (!indata) {
125 fprintf(stderr, "out of memory\n");
126 goto out;
129 void *outdata = malloc(insize);
130 if (!outdata) {
131 fprintf(stderr, "out of memory\n");
132 goto out;
134 int outsize;
136 int remsize = insize;
137 while (remsize > 0) {
138 int readsz = fread(indata, 1, remsize, fin);
139 if (readsz < 0) {
140 fprintf(stderr, "failed to read input with %d bytes left\n", remsize);
141 goto out;
143 remsize -= readsz;
146 if (comp(indata, insize, outdata, &outsize) == -1) {
147 outsize = insize;
148 free(outdata);
149 outdata = indata;
150 algo = &types_cbfs_compression[0];
153 if (write_header) {
154 char header[8];
155 header[0] = algo->type & 0xff;
156 header[1] = (algo->type >> 8) & 0xff;
157 header[2] = (algo->type >> 16) & 0xff;
158 header[3] = (algo->type >> 24) & 0xff;
159 header[4] = insize & 0xff;
160 header[5] = (insize >> 8) & 0xff;
161 header[6] = (insize >> 16) & 0xff;
162 header[7] = (insize >> 24) & 0xff;
163 if (fwrite(header, 8, 1, fout) != 1) {
164 fprintf(stderr, "failed writing header\n");
165 goto out;
168 if (fwrite(outdata, outsize, 1, fout) != 1) {
169 fprintf(stderr, "failed writing compressed data\n");
170 goto out;
173 err = 0;
174 out:
175 if (fin) fclose(fin);
176 if (fout) fclose(fout);
177 if (indata) free(indata);
178 return err;
181 int main(int argc, char **argv)
183 if ((argc == 2) && (strcmp(argv[1], "benchmark") == 0))
184 return benchmark();
185 if ((argc == 5) && (strcmp(argv[1], "compress") == 0))
186 return compress(argv[2], argv[3], argv[4], 1);
187 if ((argc == 5) && (strcmp(argv[1], "rawcompress") == 0))
188 return compress(argv[2], argv[3], argv[4], 0);
189 usage();
190 return 1;