147 lines
3.5 KiB
C
147 lines
3.5 KiB
C
// 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));
|
|
}
|