#include <string.h>
#include "ianos.h"
#include "elfload/elfload.h"
#include <module.h>
#include <mem/heap.h>
#include <storage/sd.h>
#include <utils/types.h>
#include <gfx_utils.h>
extern heap_t _heap;
static bdk_params_t _bdk_params = {
.gfx_con = (void *)&gfx_con,
.gfx_ctx = (void *)&gfx_ctxt,
.heap = &_heap,
.memcpy = (memcpy_t)&memcpy,
.memset = (memset_t)&memset,
.extension_magic = 0
};
static void *_ianos_alloc_cb(el_ctx *ctx, Elf_Addr phys, Elf_Addr virt, Elf_Addr size)
{
return (void *)virt;
}
static el_status _ianos_read_cb(el_ctx *ctx, void *dest, size_t nb, size_t offset)
{
memcpy(dest, (void *)(ctx->eaddr + offset), nb);
return EL_OK;
}
int ianos_loader(ianos_lib_t *lib, char *path)
{
el_ctx ctx;
lib->buf = NULL;
if (!lib->bdk)
lib->bdk = &_bdk_params;
ctx.eaddr = (Elf_Addr)sd_file_read(path, NULL);
if (!ctx.eaddr)
goto error;
ctx.pread = _ianos_read_cb;
if (el_init(&ctx))
goto error;
if (lib->type & IA_SHARED_LIB)
goto error;
switch (lib->type & ~IA_SHARED_LIB)
{
case IA_DRAM_LIB:
lib->buf = malloc(ctx.memsz);
break;
case IA_IRAM_LIB:
break;
case IA_AUTO_LIB:
default:
lib->buf = malloc(ctx.memsz);
break;
}
if (!lib->buf)
goto error;
ctx.base_load_vaddr = ctx.base_load_paddr = (Elf_Addr)lib->buf;
if (el_load(&ctx, _ianos_alloc_cb))
goto error;
if (el_relocate(&ctx))
goto error;
free((void *)ctx.eaddr);
Elf_Addr epaddr = ctx.ehdr.e_entry + (Elf_Addr)lib->buf;
moduleEntrypoint ep = (moduleEntrypoint)epaddr;
ep(lib->private, lib->bdk);
return 0;
error:
free((void *)ctx.eaddr);
free(lib->buf);
return 1;
}
uintptr_t ianos_static_module(char *path, void *private)
{
el_ctx ctx;
Elf_Addr buf = 0;
Elf_Addr epaddr = 0;
ctx.eaddr = (Elf_Addr)sd_file_read(path, NULL);
if (!ctx.eaddr)
goto error;
ctx.pread = _ianos_read_cb;
if (el_init(&ctx))
goto error;
buf = (Elf_Addr)malloc(ctx.memsz);
if (!buf)
goto error;
ctx.base_load_vaddr = ctx.base_load_paddr = buf;
if (el_load(&ctx, _ianos_alloc_cb))
goto error;
if (el_relocate(&ctx))
goto error;
free((void *)ctx.eaddr);
epaddr = ctx.ehdr.e_entry + buf;
moduleEntrypoint ep = (moduleEntrypoint)epaddr;
ep(private, &_bdk_params);
return (uintptr_t)epaddr;
error:
free((void *)ctx.eaddr);
free((void *)buf);
return 0;
}