mirror of
https://github.com/gwenhael-le-moine/x49gp.git
synced 2024-12-25 21:58:49 +01:00
503 lines
10 KiB
C
503 lines
10 KiB
C
/* $Id: module.c,v 1.5 2008/12/11 12:18:17 ecd Exp $
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <errno.h>
|
|
|
|
#include <x49gp.h>
|
|
|
|
int
|
|
x49gp_modules_init(x49gp_t *x49gp)
|
|
{
|
|
x49gp_module_t *module;
|
|
int error;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u:\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
|
|
phys_ram_size = 0;
|
|
|
|
list_for_each_entry(module, &x49gp->modules, list) {
|
|
error = module->init(module);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
phys_ram_base = mmap(0, phys_ram_size, PROT_NONE, MAP_SHARED | MAP_ANON, -1, 0);
|
|
if (phys_ram_base == (uint8_t *) -1) {
|
|
fprintf(stderr, "%s: can't mmap %08x anonymous bytes\n",
|
|
__FUNCTION__, phys_ram_size);
|
|
exit(1);
|
|
}
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base);
|
|
#endif
|
|
|
|
phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
|
|
memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
|
|
|
|
ram_addr_t x49gp_ram_alloc(ram_addr_t size, uint8_t *base);
|
|
x49gp_ram_alloc(phys_ram_size, phys_ram_base);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_modules_exit(x49gp_t *x49gp)
|
|
{
|
|
x49gp_module_t *module, *next;
|
|
int error;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u:\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
|
|
list_for_each_entry_safe_reverse(module, next, &x49gp->modules, list) {
|
|
error = module->exit(module);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_modules_reset(x49gp_t *x49gp, x49gp_reset_t reset)
|
|
{
|
|
x49gp_module_t *module;
|
|
int error;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u:\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
|
|
list_for_each_entry(module, &x49gp->modules, list) {
|
|
error = module->reset(module, reset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_modules_load(x49gp_t *x49gp, const char *filename)
|
|
{
|
|
x49gp_module_t *module;
|
|
GError *gerror = NULL;
|
|
int error, result;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u:\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
|
|
if (g_mkdir_with_parents(x49gp->basename, 0755)) {
|
|
error = -errno;
|
|
fprintf(stderr, "%s:%u: g_mkdir_with_parents: %s\n",
|
|
__FUNCTION__, __LINE__, strerror(errno));
|
|
return error;
|
|
}
|
|
|
|
x49gp->config = g_key_file_new();
|
|
if (NULL == x49gp->config) {
|
|
fprintf(stderr, "%s:%u: g_key_file_new: Out of memory\n",
|
|
__FUNCTION__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (! g_key_file_load_from_file(x49gp->config, filename,
|
|
G_KEY_FILE_KEEP_COMMENTS, &gerror)
|
|
&& ! g_error_matches(gerror, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
|
|
fprintf(stderr, "%s:%u: g_key_file_load_from_file: %s\n",
|
|
__FUNCTION__, __LINE__, gerror->message);
|
|
g_key_file_free(x49gp->config);
|
|
return -EIO;
|
|
}
|
|
|
|
result = 0;
|
|
|
|
list_for_each_entry(module, &x49gp->modules, list) {
|
|
error = module->load(module, x49gp->config);
|
|
if (error) {
|
|
if (error == -EAGAIN) {
|
|
result = -EAGAIN;
|
|
} else {
|
|
return error;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
extern unsigned char *phys_ram_base;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s: phys_ram_base: %p\n", __FUNCTION__, phys_ram_base);
|
|
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
|
phys_ram_base[0],
|
|
phys_ram_base[1],
|
|
phys_ram_base[2],
|
|
phys_ram_base[3],
|
|
phys_ram_base[4],
|
|
phys_ram_base[5],
|
|
phys_ram_base[6],
|
|
phys_ram_base[7]);
|
|
#endif
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
x49gp_modules_save(x49gp_t *x49gp, const char *filename)
|
|
{
|
|
x49gp_module_t *module;
|
|
GError *gerror = NULL;
|
|
gchar *data;
|
|
gsize length;
|
|
int error;
|
|
int fd;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u:\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
|
|
list_for_each_entry(module, &x49gp->modules, list) {
|
|
error = module->save(module, x49gp->config);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
data = g_key_file_to_data(x49gp->config, &length, &gerror);
|
|
if (NULL == data) {
|
|
fprintf(stderr, "%s:%u: g_key_file_to_data: %s\n",
|
|
__FUNCTION__, __LINE__, gerror->message);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
if (fd < 0) {
|
|
error = -errno;
|
|
fprintf(stderr, "%s:%u: open %s: %s\n",
|
|
__FUNCTION__, __LINE__, filename, strerror(errno));
|
|
g_free(data);
|
|
return error;
|
|
}
|
|
|
|
|
|
if (write(fd, data, length) != length) {
|
|
error = -errno;
|
|
fprintf(stderr, "%s:%u: write %s: %s\n",
|
|
__FUNCTION__, __LINE__, filename, strerror(errno));
|
|
close(fd);
|
|
g_free(data);
|
|
return error;
|
|
}
|
|
|
|
close(fd);
|
|
g_free(data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_register(x49gp_module_t *module)
|
|
{
|
|
x49gp_t *x49gp = module->x49gp;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u: %s\n", __FUNCTION__, __LINE__, module->name);
|
|
#endif
|
|
|
|
list_add_tail(&module->list, &x49gp->modules);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_unregister(x49gp_module_t *module)
|
|
{
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf("%s:%u: %s\n", __FUNCTION__, __LINE__, module->name);
|
|
#endif
|
|
|
|
list_del(&module->list);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_filename(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, char *reset, char **valuep,
|
|
char **path)
|
|
{
|
|
x49gp_t *x49gp = module->x49gp;
|
|
int error;
|
|
|
|
error = x49gp_module_get_string(module, key, name, reset, valuep);
|
|
|
|
if (g_path_is_absolute(*valuep)) {
|
|
*path = g_strdup(*valuep);
|
|
return error;
|
|
}
|
|
|
|
*path = g_build_filename(x49gp->basename, *valuep, NULL);
|
|
if (NULL == path) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
module->name, __FUNCTION__, __LINE__);
|
|
g_free(*valuep);
|
|
*valuep = NULL;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
int
|
|
x49gp_module_set_filename(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, const char *value)
|
|
{
|
|
return x49gp_module_set_string(module, key, name, value);
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_int(x49gp_module_t *module, GKeyFile *key, const char *name,
|
|
int reset, int *valuep)
|
|
{
|
|
return x49gp_module_get_u32(module, key, name, reset,
|
|
(uint32_t *) valuep);
|
|
}
|
|
|
|
int
|
|
x49gp_module_set_int(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, int value)
|
|
{
|
|
char data[16];
|
|
|
|
snprintf(data, sizeof(data), "%d", value);
|
|
|
|
g_key_file_set_value(key, module->name, name, data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_uint(x49gp_module_t *module, GKeyFile *key, const char *name,
|
|
unsigned int reset, unsigned int *valuep)
|
|
{
|
|
return x49gp_module_get_u32(module, key, name, reset, valuep);
|
|
}
|
|
|
|
int
|
|
x49gp_module_set_uint(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, unsigned int value)
|
|
{
|
|
char data[16];
|
|
|
|
snprintf(data, sizeof(data), "%u", value);
|
|
|
|
g_key_file_set_value(key, module->name, name, data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_u32(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, uint32_t reset, uint32_t *valuep)
|
|
{
|
|
GError *gerror = NULL;
|
|
char *data, *end;
|
|
uint32_t value;
|
|
|
|
data = g_key_file_get_value(key, module->name, name, &gerror);
|
|
if (NULL == data) {
|
|
fprintf(stderr, "%s: %s:%u: key \"%s\" not found\n",
|
|
module->name, __FUNCTION__, __LINE__, name);
|
|
*valuep = reset;
|
|
return -EAGAIN;
|
|
}
|
|
|
|
value = strtoul(data, &end, 0);
|
|
if ((end == data) || (*end != '\0')) {
|
|
*valuep = reset;
|
|
g_free(data);
|
|
return -EAGAIN;
|
|
}
|
|
|
|
*valuep = value;
|
|
|
|
g_free(data);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_set_u32(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, uint32_t value)
|
|
{
|
|
char data[16];
|
|
|
|
snprintf(data, sizeof(data), "0x%08x", value);
|
|
|
|
g_key_file_set_value(key, module->name, name, data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_set_u64(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, uint64_t value)
|
|
{
|
|
char data[32];
|
|
|
|
snprintf(data, sizeof(data), "0x%016" PRIx64 "", value);
|
|
|
|
g_key_file_set_value(key, module->name, name, data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_u64(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, uint64_t reset, uint64_t *valuep)
|
|
{
|
|
GError *gerror = NULL;
|
|
char *data, *end;
|
|
uint64_t value;
|
|
|
|
data = g_key_file_get_value(key, module->name, name, &gerror);
|
|
if (NULL == data) {
|
|
fprintf(stderr, "%s: %s:%u: key \"%s\" not found\n",
|
|
module->name, __FUNCTION__, __LINE__, name);
|
|
*valuep = reset;
|
|
return -EAGAIN;
|
|
}
|
|
|
|
value = strtoull(data, &end, 0);
|
|
if ((end == data) || (*end != '\0')) {
|
|
*valuep = reset;
|
|
g_free(data);
|
|
return -EAGAIN;
|
|
}
|
|
|
|
*valuep = value;
|
|
|
|
g_free(data);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_get_string(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, char *reset, char **valuep)
|
|
{
|
|
GError *gerror = NULL;
|
|
char *data;
|
|
|
|
data = g_key_file_get_value(key, module->name, name, &gerror);
|
|
if (NULL == data) {
|
|
fprintf(stderr, "%s: %s:%u: key \"%s\" not found\n",
|
|
module->name, __FUNCTION__, __LINE__, name);
|
|
*valuep = g_strdup(reset);
|
|
return -EAGAIN;
|
|
}
|
|
|
|
*valuep = data;
|
|
return 0;
|
|
}
|
|
|
|
int x49gp_module_set_string(x49gp_module_t *module, GKeyFile *key,
|
|
const char *name, const char *value)
|
|
{
|
|
g_key_file_set_value(key, module->name, name, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_module_open_rodata(x49gp_module_t *module, const char *name,
|
|
char **path)
|
|
{
|
|
x49gp_t *x49gp = module->x49gp;
|
|
int fd;
|
|
int error;
|
|
|
|
*path = g_build_filename(x49gp->progpath, name, NULL);
|
|
if (NULL == *path) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
module->name, __FUNCTION__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
fd = open(*path, O_RDONLY);
|
|
|
|
#ifdef X49GP_DATADIR
|
|
if (fd < 0 && (errno == EACCES || errno == ENOENT)) {
|
|
g_free(*path);
|
|
|
|
*path = g_build_filename(X49GP_DATADIR, name, NULL);
|
|
if (NULL == *path) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
module->name, __FUNCTION__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
fd = open(*path, O_RDONLY);
|
|
}
|
|
#endif
|
|
|
|
if (fd < 0) {
|
|
error = -errno;
|
|
fprintf(stderr, "%s: %s:%u: open %s: %s\n",
|
|
module->name, __FUNCTION__, __LINE__,
|
|
*path, strerror(errno));
|
|
g_free(*path);
|
|
*path = NULL;
|
|
return error;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
int
|
|
x49gp_module_init(x49gp_t *x49gp, const char *name,
|
|
int (*init)(x49gp_module_t *),
|
|
int (*exit)(x49gp_module_t *),
|
|
int (*reset)(x49gp_module_t *, x49gp_reset_t),
|
|
int (*load)(x49gp_module_t *, GKeyFile *),
|
|
int (*save)(x49gp_module_t *, GKeyFile *),
|
|
void *user_data, x49gp_module_t **modulep)
|
|
{
|
|
x49gp_module_t *module;
|
|
|
|
module = malloc(sizeof(x49gp_module_t));
|
|
if (NULL == module) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
name, __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
memset(module, 0, sizeof(x49gp_module_t));
|
|
|
|
module->name = name;
|
|
|
|
module->init = init;
|
|
module->exit = exit;
|
|
module->reset = reset;
|
|
module->load = load;
|
|
module->save = save;
|
|
|
|
module->user_data = user_data;
|
|
|
|
// module->mutex = g_mutex_new();
|
|
module->x49gp = x49gp;
|
|
|
|
*modulep = module;
|
|
return 0;
|
|
}
|