/* * Copyright (C) 2016-2017 Paul Kocialkowski * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "pcm-analysis.h" struct pcm_ops_data pcm_ops_data = { .address = 0, }; struct pcm_ops pcm_ops = { .asm_write = NULL, .disasm_write = pcm_disasm_write, .data = (void *) &pcm_ops_data, }; int pcm_disasm_write(void *data, unsigned int value, char *mnemonic) { struct pcm_ops_data *ops_data; if (data == NULL) return -1; ops_data = (struct pcm_ops_data *) data; if (mnemonic != NULL) printf("[0x%04x] 0x%08x ; %s\n", ops_data->address, value, mnemonic); else printf("[0x%04x] 0x%08x\n", ops_data->address, value); ops_data->address++; return 0; } int firmware_values(char *file, unsigned int **values) { struct stat stat_data; size_t size; int fd = -1; int rc; if (file == NULL || values == NULL) return -1; rc = stat(file, &stat_data); if (rc < 0) { fprintf(stderr, "Invalid file: %s\n", file); goto error; } size = stat_data.st_size; *values = malloc(size); fd = open(file, O_RDONLY, 0644); if (fd < 0) { fprintf(stderr, "Unable to open file: %s\n", file); goto error; } rc = read(fd, *values, size); if (rc <= 0) { fprintf(stderr, "Unable to read file: %s\n", file); goto error; } rc = size / sizeof(unsigned int); goto complete; error: rc = -1; if (*values != NULL) free(*values); complete: if (fd >= 0) close(fd); return rc; } int main(int argc, char *argv[]) { unsigned int *values = NULL; unsigned int count; int rc; int i; if (argc < 2 || argv[1] == NULL) return 1; rc = firmware_values(argv[1], &values); if (rc < 0 || values == NULL) goto error; count = rc; rc = pcm_ops_register(&pcm_ops); if (rc < 0) { fprintf(stderr, "Unable to set PCM OPS\n"); goto error; } i = 0; while (count > 0) { rc = pcm_op_disasm(&values[i], count); if (rc < 0) { pcm_disasm_write(pcm_ops.data, values[i], NULL); rc = 0; } count -= 1 + rc; i += 1 + rc; } rc = 0; goto complete; error: rc = 1; complete: if (values != NULL) free(values); return rc; }