/*
 * File map routines
 */
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <mach.h>

static int fdrw(Map*, Seg*, ulong, void*, uint, int);
static int zerorw(Map*, Seg*, ulong, void*, uint, int);
static int mrw(Map*, ulong, void*, uint, int);
static int datarw(Map*, Seg*, ulong, void*, uint, int);

Map*
allocmap(void)
{
	return mallocz(sizeof(Map), 1);
}

void
freemap(Map *map)
{
	if(map == nil)
		return;
	free(map->seg);
	free(map);
}

int
addseg(Map *map, Seg seg)
{
	Seg *ss;

	if(map == 0){
		werrstr("invalid map");
		return -1;
	}

	ss = realloc(map->seg, (map->nseg+1)*sizeof(ss[0]));
	if(ss == nil)
		return -1;
	map->seg = ss;
	if(seg.rw == nil){
		if(seg.name && strcmp(seg.name, "zero") == 0)
			seg.rw = zerorw;
		else if(seg.p)
			seg.rw = datarw;
		else
			seg.rw = fdrw;
	}
	map->seg[map->nseg] = seg;
	return map->nseg++;
}

int
findseg(Map *map, char *name, char *file)
{
	int i;

	if(map == 0)
		return -1;
	for(i=0; i<map->nseg; i++){
		if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0))
			continue;
		if(file && (!map->seg[i].file || strcmp(map->seg[i].file, file) != 0))
			continue;
		return i;
	}
	werrstr("segment %s in %s not found", name, file);
	return -1;
}

int
addrtoseg(Map *map, ulong addr, Seg *sp)
{
	int i;
	Seg *s;

	if(map == nil){
		werrstr("no map");
		return -1;
	}
	for(i=map->nseg-1; i>=0; i--){
		s = &map->seg[i];
		if(s->base <= addr && addr-s->base < s->size){
			if(sp)
				*sp = *s;
			return i;
		}
	}
	werrstr("address 0x%lux is not mapped", addr);
	return -1;
}

int
addrtosegafter(Map *map, ulong addr, Seg *sp)
{
	int i;
	Seg *s, *best;
	ulong bdist;

	if(map == nil){
		werrstr("no map");
		return -1;
	}

	/*
	 * If segments were sorted this would be easier,
	 * but since segments may overlap, sorting also
	 * requires splitting and rejoining, and that's just
	 * too complicated.
	 */
	best = nil;
	bdist = 0;
	for(i=map->nseg-1; i>=0; i--){
		s = &map->seg[i];
		if(s->base > addr){
			if(best==nil || s->base-addr < bdist){
				bdist = s->base - addr;
				best = s;
			}
		}
	}
	if(best){
		if(sp)
			*sp = *best;
		return best-map->seg;
	}
	werrstr("nothing mapped after address 0x%lux", addr);
	return -1;
}

void
removeseg(Map *map, int i)
{
	if(map == nil)
		return;
	if(i < 0 || i >= map->nseg)
		return;
	memmove(&map->seg[i], &map->seg[i+1], (map->nseg-(i+1))*sizeof(Seg));
	map->nseg--;
}

int
get1(Map *map, ulong addr, uchar *a, uint n)
{
	return mrw(map, addr, a, n, 1);
}

int
get2(Map *map, ulong addr, u16int *u)
{
	u16int v;

	if(mrw(map, addr, &v, 2, 1) < 0)
		return -1;
	*u = mach->swap2(v);
	return 2;
}

int
get4(Map *map, ulong addr, u32int *u)
{
	u32int v;

	if(mrw(map, addr, &v, 4, 1) < 0)
		return -1;
	*u = mach->swap4(v);
	return 4;
}

int
get8(Map *map, ulong addr, u64int *u)
{
	u64int v;

	if(mrw(map, addr, &v, 8, 1) < 0)
		return -1;
	*u = mach->swap8(v);
	return 8;
}

int
put1(Map *map, ulong addr, uchar *a, uint n)
{
	return mrw(map, addr, a, n, 0);
}

int
put2(Map *map, ulong addr, u16int u)
{
	u = mach->swap2(u);
	return mrw(map, addr, &u, 2, 0);
}

int
put4(Map *map, ulong addr, u32int u)
{
	u = mach->swap4(u);
	return mrw(map, addr, &u, 4, 0);
}

int
put8(Map *map, ulong addr, u64int u)
{
	u = mach->swap8(u);
	return mrw(map, addr, &u, 8, 0);
}

static Seg*
reloc(Map *map, ulong addr, uint n, ulong *off, uint *nn)
{
	int i;
	ulong o;

	if(map == nil){
		werrstr("invalid map");
		return nil;
	}

	for(i=map->nseg-1; i>=0; i--){
		if(map->seg[i].base <= addr){
			o = addr - map->seg[i].base;
			if(o >= map->seg[i].size)
				continue;
			if(o+n > map->seg[i].size)
				*nn = map->seg[i].size - o;
			else
				*nn = n;
			*off = o;
			return &map->seg[i];
		}
	}
	werrstr("address 0x%lux not mapped", addr);
	return nil;
}

static int
mrw(Map *map, ulong addr, void *a, uint n, int r)
{
	uint nn;
	uint tot;
	Seg *s;
	ulong off;

	for(tot=0; tot<n; tot+=nn){
		s = reloc(map, addr+tot, n-tot, &off, &nn);
		if(s == nil)
			return -1;
		if(s->rw(map, s, off, a, nn, r) < 0)
			return -1;
	}
	return 0;
}

static int
fdrw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
{
	int nn;
	uint tot;
	ulong off;

	USED(map);
	off = seg->offset + addr;
	for(tot=0; tot<n; tot+=nn){
		if(r)
			nn = pread(seg->fd, a, n-tot, off+tot);
		else
			nn = pwrite(seg->fd, a, n-tot, off+tot);
		if(nn < 0)
			return -1;	
		if(nn == 0){
			werrstr("partial %s at address 0x%lux in %s",
				r ? "read" : "write", off+tot, seg->file);
			return -1;
		}
	}
	return 0;
}

static int
zerorw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
{
	USED(map);
	USED(seg);
	USED(addr);

	if(r==0){
		werrstr("cannot write zero segment");
		return -1;
	}
	memset(a, 0, n);
	return 0;
}

static int
datarw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
{
	USED(map);

	if(r)
		memmove(a, seg->p+addr, n);
	else
		memmove(seg->p+addr, a, n);
	return 0;
}
