1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// Access to pseudo "file" interface for configuration information.
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" // CONFIG_*
#include "malloc.h" // free
#include "output.h" // dprintf
#include "romfile.h" // struct romfile_s
#include "string.h" // memcmp
static struct romfile_s *RomfileRoot VARVERIFY32INIT;
void
romfile_add(struct romfile_s *file)
{
dprintf(3, "Add romfile: %s (size=%d)\n", file->name, file->size);
file->next = RomfileRoot;
RomfileRoot = file;
}
// Search for the specified file.
static struct romfile_s *
__romfile_findprefix(const char *prefix, int prefixlen, struct romfile_s *prev)
{
struct romfile_s *cur = RomfileRoot;
if (prev)
cur = prev->next;
while (cur) {
if (memcmp(prefix, cur->name, prefixlen) == 0)
return cur;
cur = cur->next;
}
return NULL;
}
struct romfile_s *
romfile_findprefix(const char *prefix, struct romfile_s *prev)
{
return __romfile_findprefix(prefix, strlen(prefix), prev);
}
struct romfile_s *
romfile_find(const char *name)
{
return __romfile_findprefix(name, strlen(name) + 1, NULL);
}
// Helper function to find, malloc_tmphigh, and copy a romfile. This
// function adds a trailing zero to the malloc'd copy.
void *
romfile_loadfile(const char *name, int *psize)
{
struct romfile_s *file = romfile_find(name);
if (!file)
return NULL;
int filesize = file->size;
if (!filesize)
return NULL;
char *data = malloc_tmphigh(filesize+1);
if (!data) {
warn_noalloc();
return NULL;
}
dprintf(5, "Copying romfile '%s' (len %d)\n", name, filesize);
int ret = file->copy(file, data, filesize);
if (ret < 0) {
free(data);
return NULL;
}
if (psize)
*psize = filesize;
data[filesize] = '\0';
return data;
}
// Attempt to load an integer from the given file - return 'defval'
// if unsuccessful.
u64
romfile_loadint(const char *name, u64 defval)
{
struct romfile_s *file = romfile_find(name);
if (!file)
return defval;
int filesize = file->size;
if (!filesize || filesize > sizeof(u64) || (filesize & (filesize-1)))
// Doesn't look like a valid integer.
return defval;
u64 val = 0;
int ret = file->copy(file, &val, sizeof(val));
if (ret < 0)
return defval;
return val;
}
struct const_romfile_s {
struct romfile_s file;
void *data;
};
static int
const_read_file(struct romfile_s *file, void *dst, u32 maxlen)
{
if (file->size > maxlen)
return -1;
struct const_romfile_s *cfile;
cfile = container_of(file, struct const_romfile_s, file);
if (maxlen > file->size)
maxlen = file->size;
memcpy(dst, cfile->data, maxlen);
return file->size;
}
static void
const_romfile_add(char *name, void *data, int size)
{
struct const_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
if (!cfile) {
warn_noalloc();
return;
}
memset(cfile, 0, sizeof(*cfile));
strtcpy(cfile->file.name, name, sizeof(cfile->file.name));
cfile->file.size = size;
cfile->file.copy = const_read_file;
cfile->data = data;
romfile_add(&cfile->file);
}
void
const_romfile_add_int(char *name, u32 value)
{
u32 *data = malloc_tmp(sizeof(*data));
if (!data) {
warn_noalloc();
return;
}
*data = value;
const_romfile_add(name, data, sizeof(*data));
}
|