diff options
author | Uwe Hermann <uwe@hermann-uwe.de> | 2008-11-02 17:01:06 +0000 |
---|---|---|
committer | Uwe Hermann <uwe@hermann-uwe.de> | 2008-11-02 17:01:06 +0000 |
commit | 7eb845e815924984b301aaf674b090cde28c1c6a (patch) | |
tree | d85a1080fd20b0ad8e1859d012fe90ba9cdf1cd9 /payloads/bayou/util | |
parent | 91df5619dbb7d2064f9947f2fbc56477f7b707c3 (diff) |
Import a slightly modified Bayou version into svn. This is based
on the last snapshot posted by Jordan Crouse. This commit is long
overdue.
Changes by me include:
- Rename 'utils' to 'util' for consistency with our other projects.
- Move the main code out of src/* into the top-level directory.
- Add missing license headers to the following files:
Makefile, pbuilder/liblar/Makefile, util/pbuilder/Makefile.
- Dropped the util/pbuilder/lzma completely. I'm working on reusing
the lzma/ dir from v3 via svn:externals. Alas, this also means
that Bayou won't yet compile out of the box.
- Coding-style and white-space fixes (indent) for all files.
Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3719 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'payloads/bayou/util')
-rw-r--r-- | payloads/bayou/util/pbuilder/Makefile | 38 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/config.c | 265 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/create.c | 200 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/Makefile | 31 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/lar.h | 95 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/lib.c | 461 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/liblar.h | 75 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/self.c | 206 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/liblar/self.h | 42 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/main.c | 82 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/pbuilder.h | 77 | ||||
-rw-r--r-- | payloads/bayou/util/pbuilder/show.c | 131 |
12 files changed, 1703 insertions, 0 deletions
diff --git a/payloads/bayou/util/pbuilder/Makefile b/payloads/bayou/util/pbuilder/Makefile new file mode 100644 index 0000000000..8483935cc6 --- /dev/null +++ b/payloads/bayou/util/pbuilder/Makefile @@ -0,0 +1,38 @@ +## +## This file is part of the bayou project. +## +## Copyright (C) 2008 Advanced Micro Devices, Inc. +## +## 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. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +CC=gcc +PBUILDOBJS := config.o create.o show.o main.o +INCLUDES := -Iliblar/ +CFLAGS=-Wall -Werror -g + +pbuilder: $(PBUILDOBJS) $(LZMA_OBJ) liblar/liblar.a + $(CXX) -o $@ $(PBUILDOBJS) $(LZMA_OBJ) -L ./liblar -llar -lexpat + +liblar/liblar.a: + make -C liblar + +include lzma/Makefile + +%.o: %.c + $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $< + +clean: + rm -f pbuilder *.o + make -C liblar clean diff --git a/payloads/bayou/util/pbuilder/config.c b/payloads/bayou/util/pbuilder/config.c new file mode 100644 index 0000000000..7b517335e3 --- /dev/null +++ b/payloads/bayou/util/pbuilder/config.c @@ -0,0 +1,265 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _GNU_SOURCE + +#include <stdlib.h> +#include <string.h> +#include <expat.h> +#include <ctype.h> +#include "pbuilder.h" + +#define STATE_NONE 0x00 +#define STATE_BAYOUCONFIG 0x01 +#define STATE_GLOBAL 0x02 +#define STATE_GLOBAL_TIMEOUT 0x03 +#define STATE_PAYLOADS 0x04 +#define STATE_PAYLOAD 0x05 +#define STATE_PAYLOAD_TITLE 0x06 +#define STATE_PAYLOAD_FILE 0x07 +#define STATE_PAYLOAD_LARNAME 0x08 +#define STATE_PAYLOAD_CHAIN 0x09 +#define STATE_PAYLOAD_CHAIN_FILE 0x0A +#define STATE_PAYLOAD_CHAIN_LARNAME 0x0B + +static struct userdata { + struct config *config; + struct pentry *payload; + struct pentry *chain; + int state; +} userdata; + +static char buffer[8192]; + +static struct { + char *element; + int pstate; + int state; +} states[] = { + {"BayouConfig", STATE_NONE, STATE_BAYOUCONFIG}, + {"global", STATE_BAYOUCONFIG, STATE_GLOBAL}, + {"timeout", STATE_GLOBAL, STATE_GLOBAL_TIMEOUT}, + {"payloads", STATE_BAYOUCONFIG, STATE_PAYLOADS}, + {"payload", STATE_PAYLOADS, STATE_PAYLOAD}, + {"title", STATE_PAYLOAD, STATE_PAYLOAD_TITLE}, + {"lar", STATE_PAYLOAD, STATE_PAYLOAD_LARNAME}, + {"file", STATE_PAYLOAD, STATE_PAYLOAD_FILE}, + {"chain", STATE_PAYLOAD, STATE_PAYLOAD_CHAIN}, + {"file", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_FILE}, + {"lar", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_LARNAME}, + {NULL}, +}; + +static struct pentry *newPayload(struct config *config) +{ + struct pentry **tmp, *ret; + + tmp = realloc(config->entries, + (config->n_entries + 1) * sizeof(struct pentry *)); + + if (tmp == NULL) + return NULL; + + config->entries = tmp; + + ret = config->entries[config->n_entries] = calloc(sizeof(*ret), 1); + + if (ret == NULL) + return NULL; + + /* Yes, I want this to be ++config->n_entries (the index is 1 based). */ + ret->index = ++config->n_entries; + + return ret; +} + +static void parseFlags(struct pentry *entry, const char *flags) +{ + char *p = (char *)flags; + char *n; + + while (*p) { + n = strchr(p, ','); + + if (n) + *(n++) = 0; + + if (!strcmp(p, "default")) + entry->flags |= BPT_FLAG_DEFAULT; + else if (!strcmp(p, "nolist")) + entry->flags |= BPT_FLAG_NOSHOW; + else + warn("W: Unknown payload flag %s\n", p); + + if (!n) + break; + + for (p = n; *p && isspace(*p); p++) ; + } +} + +static struct pentry *addPayload(struct config *config, const char **attr) +{ + struct pentry *ret = newPayload(config); + int i = 0; + + if (ret == NULL) + die("E: Could not allocate memory for a new payload\n"); + + while (attr[i] != NULL) { + if (!strcmp(attr[i], "type")) { + if (!strcmp(attr[i + 1], "chain")) + ret->type = BPT_TYPE_CHAIN; + else if (!strcmp(attr[i + 1], "chooser")) + ret->type = BPT_TYPE_CHOOSER; + else + die("E: Invalid payload type %s\n", + attr[i + 1]); + } else if (!strcmp(attr[i], "flags")) + parseFlags(ret, attr[i + 1]); + + i += 2; + } + + return ret; +} + +static struct pentry *addChain(struct config *config, struct pentry *parent) +{ + struct pentry *ret = newPayload(config); + + if (ret == NULL) + die("E: Could not allocate memory for a new payload\n"); + + ret->parent = parent->index; + ret->type = BPT_TYPE_SUBCHAIN; + + return ret; +} + +static void start(void *data, const char *el, const char **attr) +{ + int i; + struct userdata *d = (struct userdata *)data; + + for (i = 0; states[i].element != NULL; i++) { + if (d->state != states[i].pstate) + continue; + + if (!strcmp(el, states[i].element)) { + d->state = states[i].state; + break; + } + } + + if (states[i].element == NULL) + die("E: Unknown element %s\n", el); + + if (d->state == STATE_PAYLOAD) + d->payload = addPayload(d->config, attr); + + if (d->state == STATE_PAYLOAD_CHAIN) + d->chain = addChain(d->config, d->payload); +} + +static void data(void *data, const char *val, int len) +{ + struct userdata *d = (struct userdata *)data; + int l; + + switch (d->state) { + case STATE_GLOBAL_TIMEOUT: + d->config->timeout = atoi(val); + break; + case STATE_PAYLOAD_TITLE: + l = sizeof(d->payload->title) - 1 > len ? + len : sizeof(d->payload->title) - 1; + + strncpy((char *)d->payload->title, (char *)val, l); + d->payload->title[l] = '\0'; + break; + case STATE_PAYLOAD_FILE: + d->payload->file = strndup(val, len); + break; + case STATE_PAYLOAD_LARNAME: + d->payload->larname = strndup(val, len); + break; + case STATE_PAYLOAD_CHAIN_FILE: + d->chain->file = strndup(val, len); + break; + case STATE_PAYLOAD_CHAIN_LARNAME: + d->chain->larname = strndup(val, len); + break; + default: + break; + } +} + +static void end(void *data, const char *el) +{ + struct userdata *d = (struct userdata *)data; + int i; + + if (d->state == STATE_PAYLOAD_CHAIN) + d->chain = NULL; + + if (d->state == STATE_PAYLOAD) + d->payload = NULL; + + for (i = 0; states[i].element != NULL; i++) { + if (d->state != states[i].state) + continue; + + if (!strcmp(el, states[i].element)) { + d->state = states[i].pstate; + break; + } + } + + if (states[i].element == NULL) + die("E: Unable to find the reverse state for %s\n", el); +} + +void parseconfig(FILE *stream, struct config *config) +{ + XML_Parser p = XML_ParserCreate(NULL); + int eof = 0; + + if (p == NULL) + die("E: Could not create the parser\n"); + + XML_SetElementHandler(p, start, end); + XML_SetCharacterDataHandler(p, data); + + userdata.config = config; + + XML_SetUserData(p, &userdata); + + while (!eof) { + int len = fread(buffer, 1, 8192, stream); + + eof = feof(stream); + + if (ferror(stream)) + die("E: Error reading the stream\n"); + + if (!XML_Parse(p, buffer, len, eof)) + die("E: Error parsing the XML data\n"); + } +} diff --git a/payloads/bayou/util/pbuilder/create.c b/payloads/bayou/util/pbuilder/create.c new file mode 100644 index 0000000000..313283c302 --- /dev/null +++ b/payloads/bayou/util/pbuilder/create.c @@ -0,0 +1,200 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <libgen.h> +#include "liblar.h" +#include "pbuilder.h" + +void do_lzma_compress(char *in, int in_len, char *out, int *out_len); + +int add_bpt_to_lar(struct LAR *lar, struct config *config) +{ + char *buffer; + int ret, i, len = sizeof(struct bpt_config); + struct bpt_config *cfg; + struct LARAttr attr; + char *ptr; + + for (i = 0; i < config->n_entries; i++) { + len += sizeof(struct bpt_pentry); + + if (config->entries[i]->type != BPT_TYPE_CHAIN) + len += ((strlen(config->entries[i]->larname) + + 15) & ~0x0F); + } + + buffer = calloc(len, 1); + + if (buffer == NULL) + return -1; + + cfg = (struct bpt_config *)buffer; + + cfg->id = BPT_ID; + cfg->timeout = config->timeout; + cfg->entries = config->n_entries; + + ptr = buffer + sizeof(struct bpt_config); + + for (i = 0; i < config->n_entries; i++) { + int nlen = 0; + struct bpt_pentry *pentry = (struct bpt_pentry *)ptr; + + pentry->index = config->entries[i]->index; + pentry->parent = config->entries[i]->parent; + pentry->type = config->entries[i]->type; + pentry->flags = config->entries[i]->flags; + + strncpy((char *)pentry->title, + (char *)config->entries[i]->title, + sizeof(pentry->title)); + + if (config->entries[i]->type != BPT_TYPE_CHAIN) { + nlen = strlen(config->entries[i]->larname); + nlen = (nlen + 15) & ~0x0F; + + strcpy((char *)(ptr + sizeof(struct bpt_pentry)), + config->entries[i]->larname); + + pentry->nlen = nlen; + } + + ptr += sizeof(struct bpt_pentry); + + if (config->entries[i]->type != BPT_TYPE_CHAIN) + ptr += nlen; + } + + LAR_SetAttrs(&attr, "bayou_payload_table", ALGO_NONE); + + ret = LAR_AppendBuffer(lar, (unsigned char *)buffer, len, &attr); + free(buffer); + return ret; +} + +struct lfile { + char *file; + char *larname; +}; + +int n_lfiles; + +int create_lar_from_config(const char *input, const char *output) +{ + struct config config; + FILE *stream; + struct LAR *lar; + struct LARAttr attr; + int i, j, ret = -1; + struct lfile *lfiles; + + stream = fopen(input, "r"); + + if (stream == NULL) { + warn("E: Couldn't open %s for reading\n", input); + return -1; + } + + memset(&config, 0, sizeof(config)); + + parseconfig(stream, &config); + fclose(stream); + + lar = LAR_Create(output); + + if (lar == NULL) { + warn("E: Couldn't create a new lar file\n"); + return -1; + } + + LAR_SetCompressionFuncs(lar, ALGO_LZMA, do_lzma_compress, NULL); + + lfiles = calloc(sizeof(struct lfile), config.n_entries); + + if (lfiles == NULL) { + warn("E: Couldn't allocate memory: %m\n"); + return -1; + } + + for (i = 0; i < config.n_entries; i++) { + /* Master chain entries don't have files associated with them. */ + if (config.entries[i]->type == BPT_TYPE_CHAIN) + continue; + + if (access(config.entries[i]->file, R_OK)) { + warn("E: Could not find file %s\n", + config.entries[i]->file); + + goto err; + } + + if (config.entries[i]->larname == NULL) { + config.entries[i]->larname = + strdup(basename(config.entries[i]->file)); + + if (config.entries[i]->larname == NULL) { + warn("E: Could not allocate memory for the default name\n"); + goto err; + } + } + + /* + * Add the file to the list of files to add to the LAR - skip + * any duplicates, but be on the lookout for the same LAR name + * attached to a different file. + */ + for (j = 0; j < n_lfiles; j++) { + if (!strcmp(lfiles[j].larname, + config.entries[i]->larname)) { + if (strcmp(lfiles[j].file, + config.entries[i]->file)) { + warn("E: LAR name '%s' has already been used\n", config.entries[i]->larname); + goto err; + } + break; + } + } + + if (j == n_lfiles) { + lfiles[n_lfiles].file = config.entries[i]->file; + lfiles[n_lfiles++].larname = config.entries[i]->larname; + } + } + + /* Add all the files to the LAR. */ + for (i = 0; i < n_lfiles; i++) { + LAR_SetAttrs(&attr, lfiles[i].larname, ALGO_LZMA); + + if (LAR_AppendFile(lar, lfiles[i].file, &attr)) { + warn("E: Could not add %s to the LAR\n", + lfiles[i].file); + goto err; + } + } + + ret = add_bpt_to_lar(lar, &config); + +err: + LAR_Close(lar); + return ret; +} diff --git a/payloads/bayou/util/pbuilder/liblar/Makefile b/payloads/bayou/util/pbuilder/liblar/Makefile new file mode 100644 index 0000000000..23f2feb035 --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/Makefile @@ -0,0 +1,31 @@ +## +## This file is part of the bayou project. +## +## Copyright (C) 2008 Advanced Micro Devices, Inc. +## +## 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. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +CC = gcc +LAROBJS = self.o lib.o +CFLAGS = -g -Wall + +liblar.a: $(LAROBJS) + ar rc $@ $(LAROBJS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +clean: + rm -f liblar.a *.o diff --git a/payloads/bayou/util/pbuilder/liblar/lar.h b/payloads/bayou/util/pbuilder/liblar/lar.h new file mode 100644 index 0000000000..9ef827d0e0 --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/lar.h @@ -0,0 +1,95 @@ +/* + * lar - lightweight archiver + * + * Copyright (C) 2006 coresystems GmbH + * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH) + * Copyright (C) 2007 Patrick Georgi <patrick@georgi-clan.de> + * + * This file is dual-licensed. You can choose between: + * - The GNU GPL, version 2, as published by the Free Software Foundation + * - The revised BSD license (without advertising clause) + * + * --------------------------------------------------------------------------- + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * --------------------------------------------------------------------------- + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * --------------------------------------------------------------------------- + */ + +#include <stdio.h> +#include <stdint.h> + +#define MAGIC "LARCHIVE" +#define MAX_PATHLEN 1024 +#define BOOTBLOCK_SIZE 20480 + +#define BOOTBLOCK_NAME "bootblock" +#define BOOTBLOCK_NAME_LEN 16 + +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint8_t u8; + +/* NOTE -- This and the coreboot lar.h may NOT be in sync. Be careful. */ +struct lar_header { + char magic[8]; + u32 len; + u32 reallen; + u32 checksum; + u32 compchecksum; + /* Filenames are limited to 2^31-1-sizeof(lar_header)-1 bytes. + * "Nobody will ever need more than 640k" */ + u32 offset; + /* Compression: + * 0 = no compression + * 1 = lzma + * 2 = nrv2b + * 3 = zeroes + */ + u32 compression; + u64 entry; + u64 loadaddress; +}; + +enum compalgo { + ALGO_NONE = 0, + ALGO_LZMA = 1, + ALGO_NRV2B = 2, + ALGO_ZEROES = 3, + /* invalid should always be the last entry. */ + ALGO_INVALID +}; diff --git a/payloads/bayou/util/pbuilder/liblar/lib.c b/payloads/bayou/util/pbuilder/liblar/lib.c new file mode 100644 index 0000000000..f0e0a41bd4 --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/lib.c @@ -0,0 +1,461 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <arpa/inet.h> + +#include "liblar.h" +#include "self.h" + +static int lar_compress(struct LAR *lar, int algo, char *src, char *dst, + int len) +{ + int ret; + + if (!lar->cfuncs[algo]) + return -1; + + lar->cfuncs[algo] (src, len, dst, &ret); + return ret; +} + +static int lar_decompress(struct LAR *lar, int algo, char *src, char *dst, + int slen, int dlen) +{ + if (!lar->dfuncs[algo]) + return -1; + + lar->dfuncs[algo] (src, slen, dst, dlen); + return dlen; +} + +static struct LARHeader *lar_get_header(struct LAR *lar, const char *filename) +{ + char *buffer; + int offset = 0; + struct LARHeader *lheader = NULL; + struct lar_header *header; + + printf("Getting %s\n", filename); + + buffer = malloc(sizeof(struct lar_header) + MAX_PATHLEN); + + if (buffer == NULL) + return NULL; + + while (1) { + int ret; + + if (lseek(lar->fd, offset, SEEK_SET) == -1) + goto err; + + ret = read(lar->fd, buffer, sizeof(struct lar_header)); + + if (ret <= 0) + goto err; + + header = (struct lar_header *)buffer; + + if (strncmp(header->magic, MAGIC, sizeof(MAGIC))) + goto err; + + ret = read(lar->fd, buffer + sizeof(struct lar_header), + ntohl(header->offset) - sizeof(struct lar_header)); + + if (ret <= 0) + goto err; + + if (!strcmp(buffer + sizeof(struct lar_header), filename)) + break; + + offset += ntohl(header->offset) + + ((ntohl(header->len) + 15) & ~0xF); + } + + lheader = calloc(sizeof(struct LARHeader), 1); + + if (lheader == NULL) + goto err; + + lheader->hoffset = offset; + lheader->offset = offset + ntohl(header->offset); + + lheader->reallen = ntohl(header->reallen); + lheader->len = ntohl(header->len); + + lheader->loadaddress = ntohl(header->loadaddress); + lheader->compression = ntohl(header->compression); + lheader->entry = ntohl(header->entry); + lheader->checksum = ntohl(header->checksum); + +err: + free(buffer); + return lheader; +} + +static int LAR_AppendBlob(struct LAR *lar, unsigned char *buffer, + int len, int rlen, struct LARAttr *attr) +{ + int nlen, nsize, lsize, i; + struct lar_header *header; + u8 *lptr; + u32 csum = 0; + + if (attr == NULL) + return -1; + + nlen = strlen(attr->name) + 1; + + if (nlen > MAX_PATHLEN - 1) + nlen = MAX_PATHLEN - 1; + + nsize = (nlen + 15) & ~0xF; + + lsize = sizeof(struct lar_header) + nsize + len; + lptr = calloc(lsize + 1, 1); + + if (lptr == NULL) + return -1; + + header = (struct lar_header *)lptr; + + memcpy(header->magic, MAGIC, 8); + header->reallen = htonl(rlen); + header->len = htonl(len); + header->offset = htonl(lsize - len); + header->loadaddress = htonl(attr->loadaddr); + header->compression = htonl(attr->compression); + header->entry = htonl(attr->entry); + + strncpy(((char *)header) + sizeof(struct lar_header), attr->name, nlen); + + for (i = 0; i < sizeof(struct lar_header) + nsize; i += 4) + csum += *((u32 *) (lptr + i)); + + for (i = 0; i < len; i += 4) { + /* + * The checksum needs to include the 16 byte padding at + * the end of the data before the next lar header. The + * problem is that the padding isn't going to be in the + * buffer, and if we try to read off the end of the buffer, + * we are just asking for trouble. So account for the + * situation where the datalen is not a multiple of four + * and get a safe value to add into the checksum. + * The rest of the padding will be zero, and can be safely + * ignored here. + */ + if ((len - i) < 4) { + u32 val = 0; + int t; + + for (t = 0; t < (len - i); t++) + val |= *((u8 *) buffer + (i + t)) << (t * 8); + csum += val; + } else + csum += *((u32 *) (buffer + i)); + } + + header->checksum = (u32) (~0 - csum); + + lseek(lar->fd, 0, SEEK_END); + + /* FIXME: Error check here. */ + + write(lar->fd, header, sizeof(struct lar_header) + nsize); + write(lar->fd, buffer, len); + + /* Add in padding to the next 16 byte boundary. */ + if (lsize & 0xF) { + int i; + char null = '\0'; + + for (i = lsize & 0xF; i < 0x10; i++) + write(lar->fd, &null, 1); + } + + return 0; +} + +int LAR_AppendBuffer(struct LAR *lar, unsigned char *buffer, int len, + struct LARAttr *attr) +{ + unsigned char *tbuf; + int rlen, ret = -1; + + if (attr->compression == ALGO_NONE) + return LAR_AppendBlob(lar, buffer, len, len, attr); + + tbuf = malloc(len); + + if (tbuf == NULL) + return -1; + + rlen = lar_compress(lar, attr->compression, (char *)buffer, + (char *)tbuf, len); + + if (rlen > 0) + ret = LAR_AppendBlob(lar, tbuf, rlen, len, attr); + + free(tbuf); + return ret; +} + +int LAR_AppendSelf(struct LAR *lar, const char *filename, struct LARAttr *attr) +{ + unsigned char *buffer; + int len = elf_to_self(filename, &buffer, + lar->cfuncs[attr->compression]); + int ret; + + if (len == -1) + return -1; + + ret = LAR_AppendBlob(lar, buffer, len, len, attr); + free(buffer); + + return ret; +} + +int LAR_AppendFile(struct LAR *lar, const char *filename, struct LARAttr *attr) +{ + int fd; + struct stat s; + char *filep; + int ret; + + if (iself((char *)filename)) + return LAR_AppendSelf(lar, filename, attr); + + fd = open(filename, O_RDONLY); + + if (fd == -1) + return -1; + + if (fstat(fd, &s)) + return -1; + + filep = (char *)mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + + if (filep == MAP_FAILED) + return -1; + + ret = LAR_AppendBuffer(lar, (unsigned char *)filep, s.st_size, attr); + + munmap(filep, s.st_size); + return ret; +} + +int LAR_DeleteFile(struct LAR *lar, const char *filename) +{ + struct LARHeader *header = lar_get_header(lar, filename); + int len, ret = -1; + char *filep, *buffer; + + if (header == NULL) + return -1; + + buffer = malloc(4096); + if (buffer == NULL) + return -1; + + len = header->offset + header->len; + + /* First, map the space and zero it out. */ + + filep = (char *)mmap(0, len, PROT_READ, MAP_SHARED, lar->fd, + header->hoffset); + + if (filep == MAP_FAILED) + return -1; + + memset(filep, 0, len); + munmap(filep, len); + + /* Now move the rest of the LAR into place. */ + /* FIXME: This does not account for the bootblock! */ + + int dst = header->hoffset; + int src = header->hoffset + len; + + while (1) { + int l, w; + + if (lseek(lar->fd, src, SEEK_SET)) + goto err; + + l = read(lar->fd, buffer, 8192); + + if (l == -1) + goto err; + if (l == 0) + goto err; + if (lseek(lar->fd, dst, SEEK_SET)) + goto err; + + w = write(lar->fd, buffer, l); + + if (w <= 0) + goto err; + + dst += w; + src += w; + } + + ret = 0; + +err: + free(buffer); + return ret; +} + +void LAR_CloseFile(struct LARFile *file) +{ + if (file != NULL) { + if (file->buffer != NULL) + free(file->buffer); + free(file); + } +} + +struct LARFile *LAR_MapFile(struct LAR *lar, const char *filename) +{ + struct LARFile *file; + struct LARHeader *header = lar_get_header(lar, filename); + char *filep; + int ret; + + if (header == NULL) + return NULL; + + file = calloc(sizeof(struct LARFile), 1); + + if (file == NULL) + return NULL; + + file->len = header->reallen; + file->buffer = calloc(header->reallen, 1); + + if (file->buffer == NULL) + goto err; + + /* + * The offset needs to be a multiple of PAGE_SIZE, so just mmap + * from offset 0, its easier then doing the math. + */ + + filep = mmap(0, header->offset + header->len, + PROT_READ, MAP_SHARED, lar->fd, 0); + + if (filep == MAP_FAILED) { + printf("Map failed: %m\n"); + goto err; + } + + if (header->compression != ALGO_NONE) { + ret = lar_decompress(lar, header->compression, + filep + header->offset, file->buffer, + header->len, header->reallen); + } else { + memcpy(file->buffer, filep + header->offset, header->len); + ret = header->len; + } + + munmap(filep, header->offset + header->len); + + if (ret == header->reallen) + return file; + +err: + if (file->buffer) + free(file->buffer); + + free(file); + return NULL; +} + +int LAR_SetCompressionFuncs(struct LAR *lar, int algo, + LAR_CompFunc cfunc, LAR_DecompFunc dfunc) +{ + + if (algo >= ALGO_INVALID) + return -1; + + lar->cfuncs[algo] = cfunc; + lar->dfuncs[algo] = dfunc; + + return 0; +} + +void LAR_Close(struct LAR *lar) +{ + if (lar != NULL) { + if (lar->fd) + close(lar->fd); + + free(lar); + } +} + +struct LAR *LAR_Open(const char *filename) +{ + struct LAR *lar = calloc(sizeof(struct LAR), 1); + + if (lar == NULL) + return NULL; + + lar->fd = open(filename, O_RDWR); + + if (lar->fd > 0) + return lar; + + free(lar); + return NULL; +} + +struct LAR *LAR_Create(const char *filename) +{ + struct LAR *lar = calloc(sizeof(struct LAR), 1); + + if (lar == NULL) + return NULL; + + lar->fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + + if (lar->fd > 0) + return lar; + + free(lar); + return NULL; +} + +void LAR_SetAttrs(struct LARAttr *attrs, char *name, int algo) +{ + if (attrs == NULL) + return; + + memset(attrs, 0, sizeof(*attrs)); + snprintf(attrs->name, sizeof(attrs->name) - 1, name); + attrs->compression = algo; +} diff --git a/payloads/bayou/util/pbuilder/liblar/liblar.h b/payloads/bayou/util/pbuilder/liblar/liblar.h new file mode 100644 index 0000000000..bd60e1e31b --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/liblar.h @@ -0,0 +1,75 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _LIBLAR_H_ +#define _LIBLAR_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "lar.h" + +typedef void (*LAR_CompFunc) (char *, int, char *, int *); +typedef void (*LAR_DecompFunc) (char *, int, char *, int); + +struct LAR { + int fd; + LAR_CompFunc cfuncs[ALGO_INVALID]; + LAR_DecompFunc dfuncs[ALGO_INVALID]; +}; + +struct LARHeader { + u32 len; + u32 reallen; + u32 checksum; + u32 compression; + u64 loadaddress; + u64 entry; + /* These are the offsets within the file. */ + unsigned int offset; + unsigned int hoffset; +}; + +struct LARAttr { + char name[MAX_PATHLEN]; + u64 loadaddr; + int compression; + u64 entry; +}; + +struct LARFile { + int len; + char *buffer; +}; + +int LAR_AppendBuffer(struct LAR *lar, unsigned char *buffer, int len, + struct LARAttr *attr); +int LAR_AppendSelf(struct LAR *lar, const char *filename, struct LARAttr *attr); +int LAR_AppendFile(struct LAR *lar, const char *filename, struct LARAttr *attr); +int LAR_DeleteFile(struct LAR *lar, const char *filename); +void LAR_CloseFile(struct LARFile *file); +struct LARFile *LAR_MapFile(struct LAR *lar, const char *filename); +int LAR_SetCompressionFuncs(struct LAR *lar, int algo, + LAR_CompFunc cfunc, LAR_DecompFunc dfunc); +void LAR_Close(struct LAR *lar); +struct LAR *LAR_Open(const char *filename); +struct LAR *LAR_Create(const char *filename); +void LAR_SetAttrs(struct LARAttr *attrs, char *name, int algo); + +#endif diff --git a/payloads/bayou/util/pbuilder/liblar/self.c b/payloads/bayou/util/pbuilder/liblar/self.c new file mode 100644 index 0000000000..c7fff3d97f --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/self.c @@ -0,0 +1,206 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Includes code from util/lar from coreboot-v3 + * + * Copyright (C) 2006-2007 coresystems GmbH + * Copyright (C) 2007 Patrick Georgi <patrick@georgi-clan.de> + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <elf.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdint.h> + +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint8_t u8; + +#include "self.h" + +int elf_to_self(const char *filename, unsigned char **buffer, + void (*compress) (char *, int, char *, int *)) +{ + struct stat s; + Elf32_Phdr *phdr; + Elf32_Ehdr *ehdr; + Elf32_Shdr *shdr; + void *filep; + char *header, *strtab; + unsigned char *sptr; + int headers, segments = 1, isize = 0, osize = 0, doffset = 0, fd, i; + struct self_segment *segs; + + if (stat(filename, &s)) { + printf("Unable to stat %s: %m\n", filename); + return -1; + } + + fd = open(filename, O_RDONLY); + + if (fd == -1) { + printf("Unable to open %s: %m\n", filename); + return -1; + } + + /* Map the file so that we can easily parse it. */ + filep = (void *) + mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + + if (filep == MAP_FAILED) { + close(fd); + return -1; + } + + ehdr = (Elf32_Ehdr *) filep; + headers = ehdr->e_phnum; + header = (char *)ehdr; + + phdr = (Elf32_Phdr *) & (header[ehdr->e_phoff]); + shdr = (Elf32_Shdr *) & (header[ehdr->e_shoff]); + + strtab = &header[shdr[ehdr->e_shstrndx].sh_offset]; + + /* Count number of headers - look for the .notes.pinfo section. */ + for (i = 0; i < ehdr->e_shnum; i++) { + char *name; + + if (i == ehdr->e_shstrndx) + continue; + + if (shdr[i].sh_size == 0) + continue; + + name = (char *)(strtab + shdr[i].sh_name); + + if (!strcmp(name, ".note.pinfo")) + segments++; + } + + /* + * Now, regular headers - we only care about PT_LOAD headers, + * because thats what we're actually going to load. + */ + for (i = 0; i < headers; i++) { + if (phdr[i].p_type != PT_LOAD) + continue; + + /* Empty segments are never interesting. */ + if (phdr[i].p_memsz == 0) + continue; + + isize += phdr[i].p_filesz; + segments++; + } + + /* Allocate a block of memory to store the SELF in. */ + sptr = calloc((segments * sizeof(struct self_segment)) + isize, 1); + doffset = (segments * sizeof(struct self_segment)); + + if (sptr == NULL) + goto err; + + segs = (struct self_segment *)sptr; + segments = 0; + + for (i = 0; i < ehdr->e_shnum; i++) { + char *name; + + if (i == ehdr->e_shstrndx) + continue; + + if (shdr[i].sh_size == 0) + continue; + + name = (char *)(strtab + shdr[i].sh_name); + + if (!strcmp(name, ".note.pinfo")) { + segs[segments].type = SELF_TYPE_PARAMS; + segs[segments].load_addr = 0; + segs[segments].len = (u32) shdr[i].sh_size; + segs[segments].offset = doffset; + + memcpy((unsigned long *)(sptr + doffset), + &header[shdr[i].sh_offset], shdr[i].sh_size); + + doffset += segs[segments].len; + osize += segs[segments].len; + + segments++; + } + } + + for (i = 0; i < headers; i++) { + if (phdr[i].p_type != PT_LOAD) + continue; + + if (phdr[i].p_memsz == 0) + continue; + + segs[segments].type = SELF_TYPE_DATA; + segs[segments].load_addr = (u64) phdr[i].p_paddr; + segs[segments].mem_len = (u32) phdr[i].p_memsz; + segs[segments].offset = doffset; + + compress((char *)&header[phdr[i].p_offset], + phdr[i].p_filesz, + (char *)(sptr + doffset), (int *)&segs[segments].len); + + doffset += segs[segments].len; + osize += segs[segments].len; + + segments++; + } + + segs[segments].type = SELF_TYPE_ENTRY; + segs[segments++].load_addr = (unsigned long long)ehdr->e_entry; + + *buffer = sptr; + + munmap(filep, s.st_size); + close(fd); + + return (segments * sizeof(struct self_segment)) + osize; + +err: + munmap(filep, s.st_size); + close(fd); + + return -1; +} + +int iself(char *filename) +{ + Elf32_Ehdr ehdr; + int fd = open(filename, O_RDONLY); + int ret = 0; + + if (fd == -1) + return 0; + + if (read(fd, &ehdr, sizeof(ehdr)) == sizeof(ehdr)) + ret = !memcmp(ehdr.e_ident, ELFMAG, 4); + + close(fd); + + return ret; +} diff --git a/payloads/bayou/util/pbuilder/liblar/self.h b/payloads/bayou/util/pbuilder/liblar/self.h new file mode 100644 index 0000000000..0667373d3d --- /dev/null +++ b/payloads/bayou/util/pbuilder/liblar/self.h @@ -0,0 +1,42 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SELF_H_ +#define SELF_H_ + +struct self_segment { + u32 type; + u32 offset; + u64 load_addr; + u32 len; + u32 mem_len; +}; + +#define SELF_TYPE_CODE 0x45444F43 +#define SELF_TYPE_DATA 0x41544144 +#define SELF_TYPE_BSS 0x20535342 +#define SELF_TYPE_PARAMS 0x41524150 +#define SELF_TYPE_ENTRY 0x52544E45 + +int elf_to_self(const char *filename, unsigned char **buffer, + void (*compress) (char *, int, char *, int *)); + +int iself(char *filename); + +#endif diff --git a/payloads/bayou/util/pbuilder/main.c b/payloads/bayou/util/pbuilder/main.c new file mode 100644 index 0000000000..f5ce374b16 --- /dev/null +++ b/payloads/bayou/util/pbuilder/main.c @@ -0,0 +1,82 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include "pbuilder.h" + +static void usage(void) +{ + printf("./pbuilder [-c config] [create|show] [LAR]\n"); +} + +int main(int argc, char **argv) +{ + char *config = NULL; + + while (1) { + signed ch = getopt(argc, argv, "c:"); + if (ch == -1) + break; + + switch (ch) { + case 'c': + config = optarg; + break; + default: + usage(); + return -1; + } + } + + if (optind >= argc) { + usage(); + return 0; + } + + if (!strcmp(argv[optind], "create")) { + if (config == NULL) { + warn("E: No config was provided\n"); + usage(); + return -1; + } + + if (optind + 1 >= argc) { + warn("E: No LAR name was given\n"); + usage(); + return -1; + } + + create_lar_from_config((const char *)config, + (const char *)argv[optind + 1]); + } else if (!strcmp(argv[optind], "show")) { + if (optind + 1 >= argc) { + warn("E: No LAR name was given\n"); + usage(); + return -1; + } + pbuilder_show_lar((const char *)argv[optind + 1]); + } else { + usage(); + return -1; + } + + return 0; +} diff --git a/payloads/bayou/util/pbuilder/pbuilder.h b/payloads/bayou/util/pbuilder/pbuilder.h new file mode 100644 index 0000000000..80902bc78f --- /dev/null +++ b/payloads/bayou/util/pbuilder/pbuilder.h @@ -0,0 +1,77 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> + +#ifndef PBUILDER_H_ +#define PBUILDER_H_ + +#include <stdint.h> +#include <stdio.h> + +#define warn(fmt, args...) fprintf(stderr, fmt, ##args) +#define die(fmt, args...) \ + do { fprintf(stderr, fmt, ##args); exit(-1); } \ + while(0) + +struct pentry { + uint8_t index; + uint8_t parent; + uint8_t type; + uint8_t flags; + uint8_t title[64]; + char *file; + char *larname; +}; + +struct config { + int timeout; + int n_entries; + struct pentry **entries; +}; + +struct bpt_config { + uint32_t id; + uint8_t timeout; + uint8_t entries; + uint8_t padding[10]; +}; + +struct bpt_pentry { + uint8_t index; + uint8_t parent; + uint8_t type; + uint8_t flags; + uint8_t title[64]; + uint8_t nlen; +}; + +#define BPT_ID 0x30545042 +#define BPT_TYPE_CHOOSER 0x01 +#define BPT_TYPE_CHAIN 0x02 +#define BPT_TYPE_SUBCHAIN 0x03 + +#define BPT_FLAG_DEFAULT 0x01 +#define BPT_FLAG_NOSHOW 0x02 + +int pbuilder_show_lar(const char *input); +int create_lar_from_config(const char *input, const char *output); +void parseconfig(FILE * stream, struct config *config); + +#endif diff --git a/payloads/bayou/util/pbuilder/show.c b/payloads/bayou/util/pbuilder/show.c new file mode 100644 index 0000000000..9cb0598c50 --- /dev/null +++ b/payloads/bayou/util/pbuilder/show.c @@ -0,0 +1,131 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include "liblar.h" +#include "pbuilder.h" + +void show_subchain(struct bpt_config *cfg, char *fptr, int index) +{ + int i; + char *ptr = fptr + sizeof(struct bpt_config); + + for (i = 0; i < cfg->entries; i++) { + struct bpt_pentry *entry = (struct bpt_pentry *)ptr; + + if (entry->parent == index) + printf(" + %.64s\n", + ptr + sizeof(struct bpt_pentry)); + + ptr += (sizeof(struct bpt_pentry) + entry->nlen); + } +} + +int show_payloads(struct bpt_config *cfg, char *fptr) +{ + int i; + char *ptr = fptr + sizeof(struct bpt_config); + + for (i = 0; i < cfg->entries; i++) { + struct bpt_pentry *entry = (struct bpt_pentry *)ptr; + + if (entry->parent != 0) { + ptr += (sizeof(struct bpt_pentry) + entry->nlen); + continue; + } + + printf(" "); + + if (entry->flags & BPT_FLAG_DEFAULT) + printf("D"); + else + printf(" "); + + if (entry->flags & BPT_FLAG_NOSHOW) + printf("N"); + else + printf(" "); + + switch (entry->type) { + case BPT_TYPE_CHOOSER: + printf(" MENU "); + break; + case BPT_TYPE_CHAIN: + printf(" CHAIN"); + break; + } + + if (entry->title[0] != 0) + printf(" %.64s\n", entry->title); + else + printf(" - no title -\n"); + + if (entry->type == BPT_TYPE_CHOOSER) + printf(" %.60s\n", + ptr + sizeof(struct bpt_pentry)); + else + show_subchain(cfg, fptr, entry->index); + + ptr += (sizeof(struct bpt_pentry) + entry->nlen); + } + + return 0; +} + +int pbuilder_show_lar(const char *input) +{ + int ret = -1; + struct LAR *lar; + struct bpt_config *cfg; + struct LARFile *lfile; + + lar = LAR_Open(input); + + if (lar == NULL) { + warn("E: Couldn't open LAR %s\n", input); + return -1; + } + + lfile = LAR_MapFile(lar, "bayou_payload_table"); + + if (lfile == NULL) { + warn("E: Couldn't find the bayou payload table. Nothing to do.\n"); + goto err; + } + + cfg = (struct bpt_config *)lfile->buffer; + + if (cfg->id != BPT_ID) { + warn("E: BPT ID does not match\n"); + goto err; + } + + printf("Bayou Payload Configuration\n"); + printf("Timeout = %d seconds\n", cfg->timeout); + + printf("Payload List:\n"); + show_payloads(cfg, lfile->buffer); + ret = 0; + +err: + LAR_CloseFile(lfile); + LAR_Close(lar); + + return ret; +} |