coreboot-kgpe-d16/util/cbfstool/cbfscomptool.c
Julius Werner d477565dbd cbfstool: Use cbfs_serialized.h and standard vboot helpers
This patch reduces some code duplication in cbfstool by switching it to
use the CBFS data structure definitions in commonlib rather than its own
private copy. In addition, replace a few custom helpers related to hash
algorithms with the official vboot APIs of the same purpose.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: I22eae1bcd76d85fff17749617cfe4f1de55603f4
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41117
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Wim Vervoorn <wvervoorn@eltan.com>
2020-12-03 00:00:33 +00:00

191 lines
4.4 KiB
C

/* cbfs-compression-tool, CLI utility for dealing with CBFS compressed data */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include "cbfs.h"
#include "common.h"
const char *usage_text = "cbfs-compression-tool benchmark\n"
" runs benchmarks for all implemented algorithms\n"
"cbfs-compression-tool compress inFile outFile algo\n"
" compresses inFile with algo and stores in outFile\n"
"\n"
"'compress' file format:\n"
" 4 bytes little endian: algorithm ID (as used in CBFS)\n"
" 4 bytes little endian: uncompressed size\n"
" ...: compressed data stream\n";
static void usage(void)
{
puts(usage_text);
}
static int benchmark(void)
{
const int bufsize = 10*1024*1024;
char *data = malloc(bufsize);
if (!data) {
fprintf(stderr, "out of memory\n");
return 1;
}
char *compressed_data = malloc(bufsize);
if (!compressed_data) {
free(data);
fprintf(stderr, "out of memory\n");
return 1;
}
int i, l = strlen(usage_text) + 1;
for (i = 0; i + l < bufsize; i += l) {
memcpy(data + i, usage_text, l);
}
memset(data + i, 0, bufsize - i);
const struct typedesc_t *algo;
for (algo = &types_cbfs_compression[0]; algo->name != NULL; algo++) {
int outsize = bufsize;
printf("measuring '%s'\n", algo->name);
comp_func_ptr comp = compression_function(algo->type);
if (comp == NULL) {
printf("no handler associated with algorithm\n");
free(data);
free(compressed_data);
return 1;
}
struct timespec t_s, t_e;
clock_gettime(CLOCK_MONOTONIC, &t_s);
if (comp(data, bufsize, compressed_data, &outsize)) {
printf("compression failed");
return 1;
}
clock_gettime(CLOCK_MONOTONIC, &t_e);
printf("compressing %d bytes to %d took %ld seconds\n",
bufsize, outsize,
(long)(t_e.tv_sec - t_s.tv_sec));
}
free(data);
free(compressed_data);
return 0;
}
static int compress(char *infile, char *outfile, char *algoname,
int write_header)
{
int err = 1;
FILE *fin = NULL;
FILE *fout = NULL;
void *indata = NULL;
const struct typedesc_t *algo = &types_cbfs_compression[0];
while (algo->name != NULL) {
if (strcasecmp(algo->name, algoname) == 0) break;
algo++;
}
if (algo->name == NULL) {
fprintf(stderr, "algo '%s' is not supported.\n", algoname);
return 1;
}
comp_func_ptr comp = compression_function(algo->type);
if (comp == NULL) {
printf("no handler associated with algorithm\n");
return 1;
}
fin = fopen(infile, "rb");
if (!fin) {
fprintf(stderr, "could not open '%s'\n", infile);
return 1;
}
fout = fopen(outfile, "wb");
if (!fout) {
fprintf(stderr, "could not open '%s' for writing\n", outfile);
goto out;
}
if (fseek(fin, 0, SEEK_END) != 0) {
fprintf(stderr, "could not seek in input\n");
goto out;
}
long insize = ftell(fin);
if (insize < 0) {
fprintf(stderr, "could not determine input size\n");
goto out;
}
rewind(fin);
indata = malloc(insize);
if (!indata) {
fprintf(stderr, "out of memory\n");
goto out;
}
void *outdata = malloc(insize);
if (!outdata) {
fprintf(stderr, "out of memory\n");
goto out;
}
int outsize;
int remsize = insize;
while (remsize > 0) {
int readsz = fread(indata, 1, remsize, fin);
if (readsz < 0) {
fprintf(stderr, "failed to read input with %d bytes left\n", remsize);
goto out;
}
remsize -= readsz;
}
if (comp(indata, insize, outdata, &outsize) == -1) {
outsize = insize;
free(outdata);
outdata = indata;
algo = &types_cbfs_compression[0];
}
if (write_header) {
char header[8];
header[0] = algo->type & 0xff;
header[1] = (algo->type >> 8) & 0xff;
header[2] = (algo->type >> 16) & 0xff;
header[3] = (algo->type >> 24) & 0xff;
header[4] = insize & 0xff;
header[5] = (insize >> 8) & 0xff;
header[6] = (insize >> 16) & 0xff;
header[7] = (insize >> 24) & 0xff;
if (fwrite(header, 8, 1, fout) != 1) {
fprintf(stderr, "failed writing header\n");
goto out;
}
}
if (fwrite(outdata, outsize, 1, fout) != 1) {
fprintf(stderr, "failed writing compressed data\n");
goto out;
}
err = 0;
out:
if (fin) fclose(fin);
if (fout) fclose(fout);
if (indata) free(indata);
return err;
}
int main(int argc, char **argv)
{
if ((argc == 2) && (strcmp(argv[1], "benchmark") == 0))
return benchmark();
if ((argc == 5) && (strcmp(argv[1], "compress") == 0))
return compress(argv[2], argv[3], argv[4], 1);
if ((argc == 5) && (strcmp(argv[1], "rawcompress") == 0))
return compress(argv[2], argv[3], argv[4], 0);
usage();
return 1;
}