nes-proj/cpu/arm/at91sam7s/loader/ram-segments.c

140 lines
2.9 KiB
C

#ifndef __RAM_SEGMENTS_C__1POIF5E8U4__
#define __RAM_SEGMENTS_C__1POIF5E8U4__
#include <loader/elfloader-otf.h>
#include <loader/codeprop-otf.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
struct ram_output
{
struct elfloader_output output;
char *base;
unsigned int offset;
void *text;
void *rodata;
void *data;
void *bss;
};
static void *
allocate_segment(struct elfloader_output * const output,
unsigned int type, int size)
{
struct ram_output * const ram = (struct ram_output *)output;
void *block = malloc(size);
if (!block) return NULL;
switch(type) {
case ELFLOADER_SEG_TEXT:
if (ram->text) free(ram->text);
ram->text = block;
break;
case ELFLOADER_SEG_RODATA:
if (ram->rodata) free(ram->rodata);
ram->rodata = block;
break;
case ELFLOADER_SEG_DATA:
if (ram->data) free(ram->data);
ram->data = block;
break;
case ELFLOADER_SEG_BSS:
if (ram->bss) free(ram->bss);
ram->bss = block;
break;
default:
free(block);
return NULL;
}
return block;
}
static int
start_segment(struct elfloader_output *output,
unsigned int type, void *addr, int size)
{
((struct ram_output*)output)->base = addr;
((struct ram_output*)output)->offset = 0;
return ELFLOADER_OK;
}
static int
end_segment(struct elfloader_output *output)
{
return ELFLOADER_OK;
}
static int
write_segment(struct elfloader_output *output, const char *buf,
unsigned int len)
{
struct ram_output * const ram = (struct ram_output *)output;
memcpy(ram->base + ram->offset, buf, len);
ram->offset += len;
return len;
}
static unsigned int
segment_offset(struct elfloader_output *output)
{
return ((struct ram_output*)output)->offset;
}
static const struct elfloader_output_ops elf_output_ops =
{
allocate_segment,
start_segment,
end_segment,
write_segment,
segment_offset
};
static struct ram_output seg_output = {
{&elf_output_ops},
NULL,
0,
NULL,
NULL,
NULL,
NULL
};
PROCESS(ram_segments_cleanup_process, "RAM segments cleanup process");
PROCESS_THREAD(ram_segments_cleanup_process, ev, data)
{
PROCESS_BEGIN();
while(1) {
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED
|| ev == PROCESS_EVENT_EXIT);
if (ev == PROCESS_EVENT_EXIT) break;
if (elfloader_autostart_processes ||
elfloader_autostart_processes[0] == data) {
PROCESS_PAUSE(); /* Let the process exit */
if (seg_output.text) {
free(seg_output.text);
seg_output.text = NULL;
}
if (seg_output.rodata) {
free(seg_output.rodata);
seg_output.rodata = NULL;
}
if (seg_output.data) {
free(seg_output.data);
seg_output.data = NULL;
}
if (seg_output.bss) {
free(seg_output.bss);
seg_output.bss = NULL;
}
elfloader_autostart_processes = NULL;
}
}
PROCESS_END();
}
struct elfloader_output *codeprop_output = &seg_output.output;
#endif /* __RAM_SEGMENTS_C__1POIF5E8U4__ */