summaryrefslogtreecommitdiff
path: root/util/mkblob.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/mkblob.c')
-rw-r--r--util/mkblob.c321
1 files changed, 0 insertions, 321 deletions
diff --git a/util/mkblob.c b/util/mkblob.c
deleted file mode 100644
index ea6a946..0000000
--- a/util/mkblob.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/**
-** @file mkblob.c
-**
-** @author Warren R. Carithers
-**
-** Create a binary blob from a collection of ELF files.
-*/
-#define _DEFAULT_SOURCE
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <elf.h>
-
-/*
-** Blob file organization
-**
-** The file begins with a four-byte magic number and a four-byte integer
-** indicating the number of ELF files contained in the blob. This is
-** followed by an array of 32-byte file table entries, and then the contents
-** of the ELF files in the order they appear in the program file table.
-**
-** Bytes Contents
-** ----- ----------------------------
-** 0 - 3 File magic number ("BLB\0")
-** 4 - 7 Number of ELF files in blob ("n")
-** 8 - n*32+8 Program file table
-** n*32+9 - ? ELF file contents
-**
-** Each program file table entry contains the following information:
-**
-** name File name (up to 19 characters long)
-** offset Byte offset to the ELF header for this file
-** size Size of this ELF file, in bytes
-** flags Flags related to this file
-*/
-
-// blob header
-typedef struct header_s {
- char magic[4];
- uint32_t num;
-} header_t;
-
-// length of the file name field
-#define NAMELEN 20
-
-// program descriptor
-typedef struct prog_s {
- char name[NAMELEN]; // truncated name (15 chars)
- uint32_t offset; // offset from the beginning of the blob
- uint32_t size; // size of this ELF module
- uint32_t flags; // miscellaneous flags
-} prog_t;
-
-// modules must be written as multiples of eight bytes
-#define FL_ROUNDUP 0x00000001
-
-// mask for mod 8 checking
-#define FSIZE_MASK 0x00000007
-
-// program list entry
-typedef struct node_s {
- prog_t *data;
- char *fullname;
- struct node_s *next;
-} node_t;
-
-node_t *progs, *last_prog; // list pointers
-uint32_t n_progs; // number of files being copied
-uint32_t offset; // current file area offset
-
-/**
-** Name: process
-**
-** Do the initial processing for an ELF file
-**
-** @param name The name of the file
-*/
-void process(const char *name)
-{
- struct stat info;
-
- // check the name length
- if (strlen(name) >= NAMELEN) {
- fprintf(stderr, "%s: name exceeds length limit (%d)\n", name,
- NAMELEN - 1);
- return;
- }
-
- // does it exist?
- if (stat(name, &info) < 0) {
- perror(name);
- return;
- }
-
- // is it a regular file?
- if (!S_ISREG(info.st_mode)) {
- fprintf(stderr, "%s: not a regular file\n", name);
- return;
- }
-
- // open it and check the file header
- int fd = open(name, O_RDONLY);
- if (fd < 0) {
- perror(name);
- return;
- }
-
- // read and check the ELF header
- Elf32_Ehdr hdr;
- int n = read(fd, &hdr, sizeof(Elf32_Ehdr));
- close(fd);
-
- if (n != sizeof(Elf32_Ehdr)) {
- fprintf(stderr, "%s: header read was short - only %d\n", name, n);
- return;
- }
-
- if (hdr.e_ident[EI_MAG0] != ELFMAG0 || hdr.e_ident[EI_MAG1] != ELFMAG1 ||
- hdr.e_ident[EI_MAG2] != ELFMAG2 || hdr.e_ident[EI_MAG3] != ELFMAG3) {
- fprintf(stderr, "%s: bad ELF magic number\n", name);
- return;
- }
-
- // ok, it's a valid ELF file - create the prog list entry
- prog_t *new = calloc(1, sizeof(prog_t));
- if (new == NULL) {
- fprintf(stderr, "%s: calloc prog returned NULL\n", name);
- return;
- }
-
- node_t *node = calloc(1, sizeof(node_t));
- if (node == NULL) {
- free(new);
- fprintf(stderr, "%s: calloc node returned NULL\n", name);
- return;
- }
-
- node->data = new;
- node->fullname = strdup(name);
-
- // copy in the name
-
- // only want the last component
- const char *slash = strrchr(name, '/');
- if (slash == NULL) {
- // only the file name
- slash = name;
- } else {
- // skip the slash
- ++slash;
- }
-
- strncpy(new->name, slash, sizeof(new->name) - 1);
- new->offset = offset;
- new->size = info.st_size;
-
- // bump our counters
- ++n_progs;
- offset += info.st_size;
-
- // make sure it's a multiple of eight bytes long
- if ((info.st_size & FSIZE_MASK) != 0) {
- // nope, so we must round it up when we write it out
- new->flags |= FL_ROUNDUP;
- // increases the offset to the next file
- offset += 8 - (info.st_size & FSIZE_MASK);
- }
-
- // add to the list
- if (progs == NULL) {
- // first entry
- progs = node;
- } else {
- // add to the end
- if (last_prog == NULL) {
- fprintf(stderr, "%s: progs ! NULL, last_prog is NULL\n", name);
- free(new);
- free(node->fullname);
- free(node);
- return;
- }
- last_prog->next = node;
- }
- last_prog = node;
-}
-
-/**
-** Name: copy
-**
-** Copy the contents of a program list entry into the blob
-**
-** @param ofd The output FILE* to be written
-** @param prog Pointer to the program list entry for the file
-*/
-void copy(FILE *ofd, node_t *node)
-{
- prog_t *prog = node->data;
-
- // open it so we can copy it
- int fd = open(node->fullname, O_RDONLY);
- if (fd < 0) {
- perror(node->fullname);
- return;
- }
-
- uint8_t buf[512];
-
- // copy it block-by-block
- do {
- int n = read(fd, buf, 512);
- // no bytes --> we're done
- if (n < 1) {
- break;
- }
- // copy it, and verify the copy count
- int k = fwrite(buf, 1, n, ofd);
- if (k != n) {
- fprintf(stderr, "%s: write of %d returned %d\n", prog->name, n, k);
- }
- } while (1);
-
- printf("%s: copied %d", prog->name, prog->size);
-
- // do we need to round up?
- if ((prog->flags & FL_ROUNDUP) != 0) {
- // we'll fill with NUL bytes
- uint64_t filler = 0;
-
- // how many filler bytes do we need?
- int nbytes = 8 - (prog->size & FSIZE_MASK);
-
- // do it, and check the transfer count to be sure
- int n = fwrite(&filler, 1, nbytes, ofd);
- if (n != nbytes) {
- fprintf(stderr, "%s: fill write of %d returned %d\n", prog->name,
- nbytes, n);
- }
-
- // report that we added some filler bytes
- printf("(+%d)", n);
- }
- puts(" bytes");
-
- // all done!
- close(fd);
-}
-
-int main(int argc, char *argv[])
-{
- // construct program list
- for (int i = 1; i < argc; ++i) {
- process(argv[i]);
- }
-
- if (n_progs < 1) {
- fputs("Nothing to do... exiting.", stderr);
- exit(0);
- }
-
- // create the output file
- FILE *ofd;
- ofd = fopen("user.img", "wb");
- if (ofd == NULL) {
- perror("user.img");
- exit(1);
- }
-
- printf("Processing %d ELF files\n", n_progs);
-
- // we need to adjust the offset values so they are relative to the
- // start of the blob, not relative to the start of the file area.
- // do this by adding the sum of the file header and program entries
- // to each offset field.
-
- uint32_t hlen = sizeof(header_t) + n_progs * sizeof(prog_t);
- node_t *curr = progs;
- while (curr != NULL) {
- curr->data->offset += hlen;
- curr = curr->next;
- }
-
- // write out the blob header
- header_t hdr = { "BLB", n_progs };
- if (fwrite(&hdr, sizeof(header_t), 1, ofd) != 1) {
- perror("blob header");
- fclose(ofd);
- exit(1);
- }
-
- // next, the program entries
- curr = progs;
- while (curr != NULL) {
- if (fwrite(curr->data, sizeof(prog_t), 1, ofd) != 1) {
- perror("blob prog entry write");
- fclose(ofd);
- exit(1);
- }
- curr = curr->next;
- }
-
- // finally, copy the files
- curr = progs;
- while (curr != NULL) {
- prog_t *prog = curr->data;
- copy(ofd, curr);
- node_t *tmp = curr;
- curr = curr->next;
- free(tmp->data);
- free(tmp->fullname);
- free(tmp);
- }
-
- fclose(ofd);
-
- return 0;
-}