-CC = gcc
-PREFIX = /usr/local
-CFLAGS = -std=gnu99 -O2 -fomit-frame-pointer -Wall -D_BSD_SOURCE -D_GNU_SOURCE
-LDFLAGS =
+CC ?= gcc
-BINARY = b43-dasm.bin
-OBJECTS = main.o util.o
+PREFIX ?= /usr/local
-all: $(BINARY)
+CFLAGS ?= -O2 -fomit-frame-pointer
+CFLAGS += -std=gnu99 -Wall -D_BSD_SOURCE -D_GNU_SOURCE
+LDFLAGS ?=
-main.o: util.h list.h
+BIN = b43-dasm
+OBJECTS = main.o util.o args.o
+
+all: $(BIN)
+
+main.o: main.h util.h list.h args.h
util.o: util.h
-$(BINARY): $(OBJECTS)
- $(CC) $(CFLAGS) -o $(BINARY) $(OBJECTS) $(LDFLAGS)
+$(BIN): $(OBJECTS)
+ $(CC) $(CFLAGS) -o $(BIN) $(OBJECTS) $(LDFLAGS)
install: all
- -install -o 0 -g 0 -m 755 $(BINARY) $(PREFIX)/bin/
- -cp b43-dasm b43-dasm.inst
- -sed -i -e 's/installed=0/installed=1/' b43-dasm.inst
- -install -o 0 -g 0 -m 755 b43-dasm.inst $(PREFIX)/bin/b43-dasm
- -rm -f b43-dasm.inst
+ -install -o 0 -g 0 -m 755 $(BIN) $(PREFIX)/bin/
clean:
- -rm -f *~ *.o *.orig *.rej $(BINARY)
+ -rm -f *~ *.o *.orig *.rej
+
+distclean: clean
+ -rm -f $(BIN)
--- /dev/null
+/*
+ * Copyright (C) 2006-2007 Michael Buesch <mb@bu3sch.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "args.h"
+#include "main.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+int _debug;
+
+struct cmdline_args cmdargs = {
+ .arch = 5, /* Default to v5 architecture. */
+};
+
+#define ARG_MATCH 0
+#define ARG_NOMATCH 1
+#define ARG_ERROR -1
+
+static int do_cmp_arg(char **argv, int *pos,
+ const char *template,
+ int allow_merged,
+ char **param)
+{
+ char *arg;
+ char *next_arg;
+ size_t arg_len, template_len;
+
+ arg = argv[*pos];
+ next_arg = argv[*pos + 1];
+ arg_len = strlen(arg);
+ template_len = strlen(template);
+
+ if (param) {
+ /* Maybe we have a merged parameter here.
+ * A merged parameter is "-pfoobar" for example.
+ */
+ if (allow_merged && arg_len > template_len) {
+ if (memcmp(arg, template, template_len) == 0) {
+ *param = arg + template_len;
+ return ARG_MATCH;
+ }
+ return ARG_NOMATCH;
+ } else if (arg_len != template_len)
+ return ARG_NOMATCH;
+ *param = next_arg;
+ }
+ if (strcmp(arg, template) == 0) {
+ if (param) {
+ /* Skip the parameter on the next iteration. */
+ (*pos)++;
+ if (*param == 0) {
+ fprintf(stderr, "%s needs a parameter\n", arg);
+ return ARG_ERROR;
+ }
+ }
+ return ARG_MATCH;
+ }
+
+ return ARG_NOMATCH;
+}
+
+/* Simple and lean command line argument parsing. */
+static int cmp_arg(char **argv, int *pos,
+ const char *long_template,
+ const char *short_template,
+ char **param)
+{
+ int err;
+
+ if (long_template) {
+ err = do_cmp_arg(argv, pos, long_template, 0, param);
+ if (err == ARG_MATCH || err == ARG_ERROR)
+ return err;
+ }
+ err = ARG_NOMATCH;
+ if (short_template)
+ err = do_cmp_arg(argv, pos, short_template, 1, param);
+ return err;
+}
+
+static void usage(int argc, char **argv)
+{
+ fprintf(stderr, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]);
+ fprintf(stderr, " -a|--arch ARCH The architecture type of the input file\n");
+ fprintf(stderr, " -h|--help Print this help\n");
+ fprintf(stderr, " -d|--debug Print verbose debugging info\n");
+ fprintf(stderr, " Repeat for more verbose debugging\n");
+}
+
+int parse_args(int argc, char **argv)
+{
+ int i;
+ int res;
+ char *param;
+
+ infile_name = NULL;
+ outfile_name = NULL;
+
+ for (i = 1; i < argc; i++) {
+ if ((res = cmp_arg(argv, &i, "--help", "-h", 0)) == ARG_MATCH) {
+ usage(argc, argv);
+ return 1;
+ } else if ((res = cmp_arg(argv, &i, "--debug", "-d", 0)) == ARG_MATCH) {
+ _debug++;
+ } else if ((res = cmp_arg(argv, &i, "--arch", "-a", ¶m)) == ARG_MATCH) {
+ unsigned long arch;
+ char *tail;
+
+ arch = strtol(param, &tail, 0);
+ if (strlen(tail) || (arch != 5)) {
+ fprintf(stderr, "Unsupported architecture \"%s\"\n",
+ param);
+ return -1;
+ }
+ cmdargs.arch = arch;
+ } else {
+ if (!infile_name) {
+ infile_name = argv[i];
+ continue;
+ }
+ if (!outfile_name) {
+ outfile_name = argv[i];
+ continue;
+ }
+ fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
+ goto out_usage;
+ }
+ }
+ if (!infile_name || !outfile_name)
+ goto out_usage;
+
+ return 0;
+out_usage:
+ usage(argc, argv);
+ return -1;
+}
+
+int open_input_file(void)
+{
+ if (strcmp(infile_name, "-") == 0) {
+ infile = stdin;
+ } else {
+ infile = fopen(infile_name, "r");
+ if (!infile) {
+ fprintf(stderr, "Could not open INPUT_FILE %s\n",
+ infile_name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void close_input_file(void)
+{
+ if (strcmp(infile_name, "-") != 0)
+ fclose(infile);
+}
+
+int open_output_file(void)
+{
+ if (strcmp(outfile_name, "-") == 0) {
+ outfile = stdout;
+ } else {
+ outfile = fopen(outfile_name, "w+");
+ if (!outfile) {
+ fprintf(stderr, "Could not open OUTPUT_FILE %s\n",
+ outfile_name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void close_output_file(void)
+{
+ if (strcmp(outfile_name, "-") != 0)
+ fclose(outfile);
+}
--- /dev/null
+#ifndef B43_DASM_ARGS_H_
+#define B43_DASM_ARGS_H_
+
+struct cmdline_args {
+ unsigned int arch;
+};
+
+int parse_args(int argc, char **argv);
+
+int open_input_file(void);
+void close_input_file(void);
+int open_output_file(void);
+void close_output_file(void);
+
+extern int _debug;
+extern struct cmdline_args cmdargs;
+
+#define IS_DEBUG (_debug > 0)
+#define IS_VERBOSE_DEBUG (_debug > 1)
+#define IS_INSANE_DEBUG (_debug > 2)
+
+#endif /* B43_DASM_ARGS_H_ */
+++ /dev/null
-#!/bin/sh
-
-installed=0
-
-if [ $# -ne 2 ]; then
- echo "Usage: $0 input_file.fw output_file.asm"
- exit 1
-fi
-
-if [ -z "$B43_DASM" ]; then
- if [ $installed -eq 0 ] && [ -x "./b43-dasm.bin" ]; then
- B43_DASM="./b43-dasm.bin"
- else
- B43_DASM="b43-dasm.bin"
- fi
-fi
-
-infile="$1"
-outfile="$2"
-
-cat "$infile" | $B43_DASM "$outfile"
-
#include "list.h"
#include "util.h"
+#include "args.h"
#include <stdio.h>
#include <stdint.h>
};
struct disassembler_context {
+ /* The architecture of the input file. */
+ unsigned int arch;
+
struct bin_instruction *code;
size_t nr_insns;
};
-static FILE *infile;
+FILE *infile;
+FILE *outfile;
+const char *infile_name;
const char *outfile_name;
static void emit_asm(struct disassembler_context *ctx)
{
struct statement *stmt;
- FILE *fd;
int first, i;
+ int err;
- fd = fopen(outfile_name, "w+");
- if (!fd) {
- fprintf(stderr, "Could not open output file \"%s\"\n",
- outfile_name);
+ err = open_output_file();
+ if (err)
exit(1);
- }
- /* FIXME: We currently only support v5 architecture. */
- fprintf(fd, "%%arch 5\n\n");
+
+ fprintf(outfile, "%%arch %u\n\n", ctx->arch);
list_for_each_entry(stmt, &ctx->stmt_list, list) {
switch (stmt->type) {
case STMT_INSN:
- fprintf(fd, "\t%s", stmt->u.insn.name);
+ fprintf(outfile, "\t%s", stmt->u.insn.name);
first = 1;
for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
if (stmt->u.insn.is_labelref == i) {
- fprintf(fd, ",%s",
+ fprintf(outfile, ",%s",
stmt->u.insn.labelref->u.label.name);
}
if (!stmt->u.insn.operands[i])
continue;
if (first)
- fprintf(fd, "\t");
+ fprintf(outfile, "\t");
if (!first)
- fprintf(fd, ",");
+ fprintf(outfile, ",");
first = 0;
- fprintf(fd, "%s",
+ fprintf(outfile, "%s",
stmt->u.insn.operands[i]);
}
- fprintf(fd, "\n");
+ fprintf(outfile, "\n");
break;
case STMT_LABEL:
- fprintf(fd, "%s:\n", stmt->u.label.name);
+ fprintf(outfile, "%s:\n", stmt->u.label.name);
break;
}
}
- fclose(fd);
+
+ close_output_file();
}
-static void read_input(struct disassembler_context *ctx)
+static int read_input(struct disassembler_context *ctx)
{
size_t size = 0, pos = 0;
size_t ret;
unsigned char tmp[sizeof(uint64_t)];
uint64_t codeword;
struct fw_header hdr;
+ int err;
+
+ err = open_input_file();
+ if (err)
+ goto error;
ret = fread(&hdr, 1, sizeof(hdr), infile);
- if (!ret || ret != sizeof(hdr)) {
+ if (ret != sizeof(hdr)) {
fprintf(stderr, "Corrupt input file (not fwcutter output)\n");
- exit(1);
- }
-
- if (hdr.ver != 1) {
- fprintf(stderr, "Invalid fwcutter header version\n");
- exit(1);
+ goto err_close;
}
-
if (hdr.type != 'u') {
- fprintf(stderr, "Not a microcode image\n");
- exit(1);
+ fprintf(stderr, "Corrupt input file. Not a microcode image.\n");
+ goto err_close;
+ }
+ if (hdr.ver != 1) {
+ fprintf(stderr, "Invalid input file header version.\n");
+ goto err_close;
}
while (1) {
break;
if (ret != sizeof(uint64_t)) {
fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n");
- exit(1);
+ goto err_free_code;
}
codeword = 0;
ctx->code = code;
ctx->nr_insns = pos;
+
+ close_input_file();
+
+ return 0;
+
+err_free_code:
+ free(code);
+err_close:
+ close_input_file();
+error:
+ return -1;
}
static void disassemble(void)
{
struct disassembler_context ctx;
+ int err;
memset(&ctx, 0, sizeof(ctx));
INIT_LIST_HEAD(&ctx.stmt_list);
+ ctx.arch = cmdargs.arch;
- read_input(&ctx);
+ err = read_input(&ctx);
+ if (err)
+ exit(1);
disasm_opcodes(&ctx);
resolve_labels(&ctx);
emit_asm(&ctx);
}
-static void usage(int argc, char **argv)
-{
- fprintf(stderr, "Usage: %s output_file\n", argv[0]);
-}
-
-static void parse_args(int argc, char **argv)
-{
- if (argc != 2) {
- usage(argc, argv);
- exit(1);
- }
- outfile_name = argv[1];
-}
-
int main(int argc, char **argv)
{
- infile = stdin;
- parse_args(argc, argv);
+ int err, res = 1;
+
+ err = parse_args(argc, argv);
+ if (err < 0)
+ goto out;
+ if (err > 0) {
+ res = 0;
+ goto out;
+ }
disassemble();
-
+ res = 0;
+out:
/* Lazyman simply leaks all allocated memory. */
- return 0;
+ return res;
}
--- /dev/null
+#ifndef B43_DASM_MAIN_H_
+#define B43_DASM_MAIN_H_
+
+#include <stdio.h>
+
+
+FILE *infile;
+FILE *outfile;
+const char *infile_name;
+const char *outfile_name;
+
+#endif /* B43_DASM_MAIN_H_ */