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/pbuilder/liblar | |
parent | 91df5619dbb7d2064f9947f2fbc56477f7b707c3 (diff) | |
download | coreboot-7eb845e815924984b301aaf674b090cde28c1c6a.tar.xz |
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/pbuilder/liblar')
-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 |
6 files changed, 910 insertions, 0 deletions
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 |