X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=util%2Fcbfstool%2Fcbfstool.c;h=b8abb515bf42cdddcb3dbb9a2f7b49c9958468ac;hb=a1e4824f73602a411826b27160a8818049ce0f97;hp=b9915e3fac7134e8289839b08b8472a878afe3bf;hpb=1d862ded11d4a2ca42d3d0aff4ea947dd28bcb68;p=coreboot.git diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index b9915e3fa..b8abb515b 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -1,7 +1,8 @@ /* - * cbfstool + * cbfstool, CLI utility for CBFS file manipulation * - * Copyright (C) 2008 Jordan Crouse + * Copyright (C) 2009 coresystems GmbH + * written by Patrick Georgi * * 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 @@ -17,141 +18,323 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -/* v2 compat: First, assumes a 64K bootblock. - * cbfstool coreboot.rom create 0x80000 coreboot.strip - * cbfstool coreboot.rom add-payload /tmp/filo.elf payload - * cbfstool coreboot.rom print - */ +#include +#include +#include +#include +#include "common.h" +#include "cbfs.h" +typedef enum { + CMD_ADD, + CMD_ADD_PAYLOAD, + CMD_ADD_STAGE, + CMD_CREATE, + CMD_LOCATE, + CMD_PRINT, + CMD_EXTRACT, +} cmd_t; -#include -#include -#include -#include -#include "cbfstool.h" - -extern int create_handler(struct rom *, int, char **); -extern int bootblock_handler(struct rom *, int, char **); -extern int print_handler(struct rom *, int, char **); -extern int add_handler(struct rom *, int, char **); -extern int delete_handler(struct rom *, int, char **); -extern int resize_handler(struct rom *, int, char **); -extern int add_payload_handler(struct rom *, int, char **); -extern int add_stage_handler(struct rom *, int, char **); - -extern void create_usage(void); -extern void bootblock_usage(void); -extern void print_usage(void); -extern void add_usage(void); -extern void delete_usage(void); -extern void resize_usage(void); -extern void add_payload_usage(void); -extern void add_stage_usage(void); - -struct { - char *command; - int (*handler) (struct rom *, int, char **); - void (*help) (void); -} commands[] = { - { - "add", add_handler, add_usage}, { - "add-payload", add_payload_handler, add_payload_usage}, { - "add-stage", add_stage_handler, add_stage_usage}, { - "bootblock", bootblock_handler, bootblock_usage}, { - "create", create_handler, create_usage}, { - "delete", delete_handler, delete_usage}, { - "print", print_handler, print_usage}, { - "resize", resize_handler, resize_usage}, { -"", NULL},}; +struct command { + cmd_t id; + const char *name; + int (*function) (int argc, char **argv); +}; + +static int cbfs_add(int argc, char **argv) +{ + char *romname = argv[1]; + char *cmd = argv[2]; + void *rom = loadrom(romname); -static struct rom rom; + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } -char cbfstool_bindir[255]; + if (argc < 5) { + printf("not enough arguments to '%s'.\n", cmd); + return 1; + } -void show_help(void) + char *filename = argv[3]; + char *cbfsname = argv[4]; + + uint32_t filesize = 0; + void *filedata = loadfile(filename, &filesize, 0, SEEK_SET); + if (filedata == NULL) { + printf("Could not load file '%s'.\n", filename); + return 1; + } + + uint32_t base = 0; + void *cbfsfile = NULL; + + if (argc < 6) { + printf("not enough arguments to 'add'.\n"); + return 1; + } + uint32_t type; + if (intfiletype(argv[5]) != ((uint64_t) - 1)) + type = intfiletype(argv[5]); + else + type = strtoul(argv[5], NULL, 0); + if (argc > 6) { + base = strtoul(argv[6], NULL, 0); + } + cbfsfile = create_cbfs_file(cbfsname, filedata, &filesize, type, &base); + if (add_file_to_cbfs(cbfsfile, filesize, base)) { + printf("Adding file '%s' failed.\n", filename); + return 1; + } + if (writerom(romname, rom, romsize)) + return 1; + return 0; +} + +static int cbfs_add_payload(int argc, char **argv) { - int i; + char *romname = argv[1]; + char *cmd = argv[2]; + void *rom = loadrom(romname); + + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } + + if (argc < 5) { + printf("not enough arguments to '%s'.\n", cmd); + return 1; + } + + char *filename = argv[3]; + char *cbfsname = argv[4]; + + uint32_t filesize = 0; + void *filedata = loadfile(filename, &filesize, 0, SEEK_SET); + if (filedata == NULL) { + printf("Could not load file '%s'.\n", filename); + return 1; + } - printf("cbfstool [OPTION] [[FILE] [COMMAND] [PARAMETERS]...\n"); - printf("Apply COMMANDS with PARAMETERS to FILE. If no COMMAND is\n"); - printf("given, run in interactive mode\n\n"); - printf("OPTIONs:\n"); - printf(" -h\t\tDisplay this help message\n"); - printf(" -C \tChange to the directory before operating\n\n"); - printf("COMMANDs:\n"); + uint32_t base = 0; + void *cbfsfile = NULL; - for (i = 0; commands[i].handler != NULL; i++) - commands[i].help(); + comp_algo algo = CBFS_COMPRESS_NONE; + if (argc > 5) { + if (argv[5][0] == 'l') + algo = CBFS_COMPRESS_LZMA; + } + if (argc > 6) { + base = strtoul(argv[6], NULL, 0); + } + unsigned char *payload; + filesize = parse_elf_to_payload(filedata, &payload, algo); + cbfsfile = + create_cbfs_file(cbfsname, payload, &filesize, + CBFS_COMPONENT_PAYLOAD, &base); + if (add_file_to_cbfs(cbfsfile, filesize, base)) { + printf("Adding payload '%s' failed.\n", filename); + return 1; + } + if (writerom(romname, rom, romsize)) + return 1; + return 0; } -int main(int argc, char **argv) +static int cbfs_add_stage(int argc, char **argv) { - char *cdir = NULL; - char *rname; - char *cmd; - int ret = -1, i; + char *romname = argv[1]; + char *cmd = argv[2]; + void *rom = loadrom(romname); + + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } + + if (argc < 5) { + printf("not enough arguments to '%s'.\n", cmd); + return 1; + } + + char *filename = argv[3]; + char *cbfsname = argv[4]; + + uint32_t filesize = 0; + void *filedata = loadfile(filename, &filesize, 0, SEEK_SET); + if (filedata == NULL) { + printf("Could not load file '%s'.\n", filename); + return 1; + } + + uint32_t base = 0; + void *cbfsfile = NULL; + + comp_algo algo = CBFS_COMPRESS_NONE; + if (argc > 5) { + if (argv[5][0] == 'l') + algo = CBFS_COMPRESS_LZMA; + } + if (argc > 6) { + base = strtoul(argv[6], NULL, 0); + } + unsigned char *stage; + filesize = parse_elf_to_stage(filedata, &stage, algo, &base); + cbfsfile = + create_cbfs_file(cbfsname, stage, &filesize, + CBFS_COMPONENT_STAGE, &base); - strncpy(cbfstool_bindir, dirname(argv[0]), 254); + if (add_file_to_cbfs(cbfsfile, filesize, base)) { + printf("Adding stage '%s' failed.\n", filename); + return 1; + } + if (writerom(romname, rom, romsize)) + return 1; + return 0; +} - while (1) { - signed ch = getopt(argc, argv, "hC:"); - if (ch == -1) - break; - switch (ch) { - case 'h': - show_help(); - return -1; - case 'C': - cdir = optarg; - break; - } +static int cbfs_create(int argc, char **argv) +{ + char *romname = argv[1]; + if (argc < 5) { + printf("not enough arguments to 'create'.\n"); + return 1; } - if (optind >= argc) { - show_help(); - return -1; + char* suffix; + uint32_t size = strtoul(argv[3], &suffix, 0); + if (tolower(suffix[0])=='k') { + size *= 1024; } + if (tolower(suffix[0])=='m') { + size *= 1024 * 1024; + } + char *bootblock = argv[4]; + uint32_t align = 0; + + if (argc > 5) + align = strtoul(argv[5], NULL, 0); - if (cdir != NULL && chdir(cdir)) { - ERROR("Unable to switch to %s: %m\n", cdir); - return -1; + return create_cbfs_image(romname, size, bootblock, align); +} + +static int cbfs_locate(int argc, char **argv) +{ + char *romname = argv[1]; + if (argc < 6) { + printf("not enough arguments to 'locate'.\n"); + return 1; } - rname = argv[optind]; - cmd = optind + 1 < argc ? argv[optind + 1] : NULL; + const char *file = argv[3]; + uint32_t filesize = getfilesize(file); + const char *filename = argv[4]; + int align = strtoul(argv[5], NULL, 0); + + printf("%x\n", cbfs_find_location(romname, filesize, filename, align)); + return 0; +} + +static int cbfs_print(int argc, char **argv) +{ + char *romname = argv[1]; + void *rom = loadrom(romname); + + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } + + print_cbfs_directory(romname); + return 0; +} + +static int cbfs_extract(int argc, char **argv) +{ + char *romname = argv[1]; + void *rom = loadrom(romname); - /* Open the ROM (if it exists) */ - rom.name = (unsigned char *)strdup(rname); + if (rom == NULL) { + printf("Could not load ROM image '%s'.\n", romname); + return 1; + } - if (!access(rname, F_OK)) { - if (open_rom(&rom, rname)) { - ERROR("Problem while reading the ROM\n"); - return -1; - } + if (argc != 5) + { + printf("Error: you must specify a CBFS name and a file to dump it in.\n"); + return 1; } - if (cmd) { - /* Process the incoming comand */ + return extract_file_from_cbfs(romname, argv[3], argv[4]); +} + +static const struct command commands[] = { + {CMD_ADD, "add", cbfs_add}, + {CMD_ADD_PAYLOAD, "add-payload", cbfs_add_payload}, + {CMD_ADD_STAGE, "add-stage", cbfs_add_stage}, + {CMD_CREATE, "create", cbfs_create}, + {CMD_LOCATE, "locate", cbfs_locate}, + {CMD_PRINT, "print", cbfs_print}, + {CMD_EXTRACT, "extract", cbfs_extract}, +}; - for (i = 0; commands[i].handler != NULL; i++) { - if (!strcmp(commands[i].command, cmd)) { - ret = commands[i].handler(&rom, - argc - 3, &argv[3]); - goto leave; - } - } +static void usage(void) +{ + printf + ("cbfstool: Management utility for CBFS formatted ROM images\n\n" + "USAGE:\n" " cbfstool [-h]\n" + " cbfstool FILE COMMAND [PARAMETERS]...\n\n" "OPTIONs:\n" + " -h Display this help message\n\n" + "COMMANDs:\n" + " add FILE NAME TYPE [base address] Add a component\n" + " add-payload FILE NAME [COMP] [base] Add a payload to the ROM\n" + " add-stage FILE NAME [COMP] [base] Add a stage to the ROM\n" + " create SIZE BOOTBLOCK [ALIGN] Create a ROM file\n" + " locate FILE NAME ALIGN Find a place for a file of that size\n" + " print Show the contents of the ROM\n" + " extract NAME FILE Extracts a raw payload from ROM\n" + "\n" + "TYPEs:\n" + ); + print_supported_filetypes(); +} - ERROR("Command %s not valid\n", cmd); - } else { - printf("Interactive mode not ready yet!\n"); +/* Small, OS/libc independent runtime check + * for endianess + */ +int host_bigendian = 0; + +static void which_endian(void) +{ + char test[4] = "1234"; + uint32_t inttest = *(uint32_t *) test; + if (inttest == 0x31323334) { + host_bigendian = 1; } +} -leave: - if (rom.ptr != NULL && rom.ptr != MAP_FAILED) - munmap(rom.ptr, rom.size); +int main(int argc, char **argv) +{ + int i; - if (rom.fd > 0) - close(rom.fd); + if (argc < 3) { + usage(); + return 1; + } + + which_endian(); + + char *cmd = argv[2]; + + for (i = 0; i < ARRAY_SIZE(commands); i++) { + if (strcmp(cmd, commands[i].name) != 0) + continue; + return commands[i].function(argc, argv); + } - return ret; + printf("Unknown command '%s'.\n", cmd); + usage(); + return 1; }