Source to jet/memory.c
#include <Memory.h>
#include <OSUtils.h>
#include <SegLoad.h>
#include "jet.h"
typedef struct memblk {
unsigned long size;
struct memblk *next;
} memblk;
static void relocate(char *txt, char *relo);
static memblk *free_blocks;
void init_memory(char *m_begin, char *m_end)
{
free_blocks = (memblk *)(((unsigned long)m_begin + 0x03) & ~0x03);
free_blocks->size = (unsigned long)(m_end - m_begin - sizeof(memblk)) & ~0x03;
free_blocks->next = 0;
}
void *m_alloc(long number)
{
unsigned long size;
memblk *b;
if (number == -1) {
if (free_blocks == NULL)
return 0;
else
return (void *)free_blocks->size;
}
size = ((unsigned long)number + 0x03) & ~0x03;
if ((free_blocks == NULL) || (free_blocks->size < size))
return 0;
b = free_blocks;
if (free_blocks->size > size + sizeof(memblk)) {
free_blocks = (memblk *)((char *)free_blocks + sizeof(memblk) + size);
free_blocks->size = b->size - sizeof(memblk) - size;
free_blocks->next = b->next;
} else {
size = free_blocks->size;
free_blocks = NULL;
}
b->size = size;
b->next = 0;
return (void *)(b + 1);
}
long m_free(void *block)
{
memblk *b;
b = (memblk *)((char *)block - sizeof(memblk));
b->next = free_blocks;
free_blocks = b;
return 0;
}
long m_shrink(short zero, void *ptr, long size)
{
memblk *b1, *b2;
unsigned long s;
s = ((unsigned long)size + 0x03) & ~0x03;
b1 = (memblk *)((char *)ptr - sizeof(memblk));
b2 = (memblk *)((char *)b1 + sizeof(memblk) + s);
b2->size = b1->size - sizeof(memblk) - s;
b2->next = free_blocks;
free_blocks = b2;
b1->size = size;
return 0;
}
long m_xalloc(long number, short mode)
{
return -EINVAL;
}
/* this is no where near correct for the general case */
/* I just want it to work for mint right now */
long p_exec(short mode, void *ptr1, void *ptr2, void *ptr3)
{
long size;
short f;
struct aexec hdr;
_DTA dta;
char *prog, *cmd, *env;
if (mode != 0) {
c_conws("p_exec only supports mode 0\r\n");
p_term(0);
}
prog = ptr1;
cmd = ptr2;
env = ptr3;
f_setdta(&dta);
if (f_sfirst(prog, 0) < 0) {
c_conws("can't find ");
c_conws(prog);
c_conws("\r\n");
p_term(0);
}
size = curbp->p_hitpa - (curbp->p_lowtpa + sizeof(*curbp));
if (dta.dta_size > size) {
c_conws("not enough memory to load ");
c_conws(prog);
c_conws("\r\n");
p_term(0);
}
f = f_open(prog, O_RDONLY);
if (f < 0) {
c_conws("can't open ");
c_conws(prog);
c_conws("\r\n");
p_term(0);
}
f_read(f, sizeof(hdr), &hdr);
if (A_BADMAG(hdr)) {
c_conws(prog);
c_conws(" is not executable\r\n");
p_term(0);
}
curbp->p_env = env;
curbp->p_cmdlin[0] = strlen(cmd);
strcpy(curbp->p_cmdlin + 1, cmd);
curbp->p_tbase = (char *)(curbp + 1);
curbp->p_dbase = curbp->p_tbase + hdr.a_text;
curbp->p_bbase = curbp->p_dbase + hdr.a_data;
curbp->p_tlen = hdr.a_text;
curbp->p_dlen = hdr.a_data;
curbp->p_blen = hdr.a_bss;
f_read(f, dta.dta_size - sizeof(hdr), curbp->p_tbase);
f_close(f);
relocate(curbp->p_tbase, curbp->p_bbase + hdr.a_syms);
FlushInstructionCache();
memset(curbp->p_bbase, 0, curbp->p_blen);
call_sr = 0;
call_regs[0] = 0;
call_pc = (long)curbp->p_tbase;
call_sp = (long)curbp->p_hitpa - (2 *sizeof(long));
((long *)call_sp)[0] = 0xffffffff;
((long *)call_sp)[1] = (long)curbp;
if (vm) {
swap = 0;
mintssp = jet_stack;
if (HoldMemory(ApplicZone(), (long)(jet_stack)-(long)ApplicZone() +
dta.dta_size - sizeof(hdr) + 1) != 0) {
c_conws("Unable to Hold memory\r\n");
p_term(0);
}
asm(".word 0x7008,0xa08d /* enter supervisor mode */
movel sp,_macssp /* save the mac ssp */
movel _mintssp,sp "); /* restore the mint ssp */
}
out();
/* not reached */
return 0;
}
void p_term(short retcode)
{
c_conws("Press a key to quit program\r\n");
b_conin(2);
ExitToShell();
}
void p_term0(void)
{
p_term(0);
}
static void relocate(char *txt, char *relo)
{
char *text, *p;
int c;
long off, adr;
text = txt;
p = relo;
if (*((long *)p) == 0)
return;
off = (long)text;
adr = off + (*(long *)p);
p += sizeof(long);
for (;;) {
*((long *)adr) += (long)off;
for (;;) {
c = *p++ & 0xFF;
if (c != 1)
break;
adr += 254;
}
if (c == 0)
break;
if (c & 1) {
c_conws("relocation error\r\n");
p_term(0);
}
adr += c;
}
}