view ffstools/tiffs-rd/decode.c @ 914:bf302e52c8ea

Source-dirs: add tchtools
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 29 Dec 2022 22:21:04 +0000
parents ed983d4040a8
children
line wrap: on
line source

/*
 * This C module implements the decode command, displaying certain
 * FFS files in a developer-friendly decoded form.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "types.h"
#include "struct.h"
#include "globals.h"
#include "pathname.h"

extern void write_afcdac_ascii();
extern void write_stdmap_ascii();
extern void write_adccal_table();
extern void write_afcparams_table();
extern void write_tx_ramps_table();
extern void write_tx_levels_table();
extern void write_tx_calchan_table();
extern void write_tx_caltemp_table();
extern void write_rx_calchan_table();
extern void write_rx_caltemp_table();
extern void write_rx_agcparams_table();

static void
pcm_IMEI_decode(bin, outf)
	u8 *bin;
	FILE *outf;
{
	u8 rev[8];
	unsigned n;

	for (n = 0; n < 8; n++)
		rev[n] = ((bin[n] & 0xF0) >> 4) | ((bin[n] & 0x0F) << 4);
	fprintf(outf, "%02X%02X%02X%02X-%02X%02X%02X-%02X\n", rev[0], rev[1],
		rev[2], rev[3], rev[4], rev[5], rev[6], rev[7]);
}

static struct map {
	char		*req_name;
	char		*pathname;
	int		need_band;
	unsigned	size;
	void		(*decode_func)();
} map_table[] = {
  {"adccal",       "/sys/adccal",             0,  36, write_adccal_table},
  {"afcdac",       "/gsm/rf/afcdac",          0,   2, write_afcdac_ascii},
  {"afcparams",    "/gsm/rf/afcparams",       0,  24, write_afcparams_table},
  {"stdmap",       "/gsm/rf/stdmap",          0,   2, write_stdmap_ascii},
  {"tx-ramps",     "/gsm/rf/tx/ramps.%s",     1, 512, write_tx_ramps_table},
  {"tx-levels",    "/gsm/rf/tx/levels.%s",    1, 128, write_tx_levels_table},
  {"tx-calchan",   "/gsm/rf/tx/calchan.%s",   1, 128, write_tx_calchan_table},
  {"tx-caltemp",   "/gsm/rf/tx/caltemp.%s",   1,  40, write_tx_caltemp_table},
  {"rx-calchan",   "/gsm/rf/rx/calchan.%s",   1,  40, write_rx_calchan_table},
  {"rx-caltemp",   "/gsm/rf/rx/caltemp.%s",   1,  44, write_rx_caltemp_table},
  {"rx-agcparams", "/gsm/rf/rx/agcparams.%s", 1,   8, write_rx_agcparams_table},
  {"pcm-IMEI",     "/pcm/IMEI",               0,   8, pcm_IMEI_decode},
  {0,              0,                         0,   0, 0}
};

static u8 file_read_buf[512];
static unsigned file_expected_size;
static unsigned file_read_ptr;

static void
read_chunk(ch)
	struct chunkinfo *ch;
{
	if (!ch->len)
		return;
	if (file_read_ptr + ch->len > file_expected_size) {
		fprintf(stderr, "error: FFS file is longer than expected\n");
		exit(1);
	}
	bcopy(ch->start, file_read_buf + file_read_ptr, ch->len);
	file_read_ptr += ch->len;
}

static void
segment_read_callback(inf, opaque)
	struct inode_info *inf;
	u_long opaque;
{
	struct chunkinfo chi;

	size_extra_chunk(inf, &chi);
	read_chunk(&chi);
}

cmd_decode(argc, argv)
	char **argv;
{
	struct map *map;
	char pathname[PATHNAME_BUF_SIZE];
	int headino;
	struct inode_info *inf;
	struct chunkinfo chi;

	if (argc < 2) {
usage:		fprintf(stderr, "usage: decode file-keyword [band]\n");
		exit(1);
	}
	for (map = map_table; map->req_name; map++)
		if (!strcmp(map->req_name, argv[1]))
			break;
	if (!map->req_name) {
		fprintf(stderr, "error: file keyword \"%s\" not known\n",
			argv[1]);
		exit(1);
	}
	if (map->need_band) {
		if (argc < 3) {
			fprintf(stderr,
				"error: band not specified for %s table\n",
				map->req_name);
			exit(1);
		}
		if (argc > 3)
			goto usage;
		if (strlen(argv[2]) > 7) {
			fprintf(stderr,
				"error: band name argument is too long\n");
			exit(1);
		}
		sprintf(pathname, map->pathname, argv[2]);
	} else {
		if (argc > 2)
			goto usage;
		strcpy(pathname, map->pathname);
	}
	file_expected_size = map->size;

	read_ffs_image();
	find_inode_block();
	alloc_inode_table();
	find_root_inode();

	headino = find_pathname(pathname);
	inf = inode_info[headino];
	if (inf->type != 0xF1) {
		fprintf(stderr, "error: FFS object is not a regular file\n");
		exit(1);
	}
	size_head_chunk(inf, &chi);
	read_chunk(&chi);
	iterate_seg_file(headino, segment_read_callback, 0L, 0, 0);
	if (file_read_ptr < file_expected_size) {
		fprintf(stderr, "error: FFS file is shorter than expected\n");
		exit(1);
	}
	map->decode_func(file_read_buf, stdout);
	exit(0);
}