/*
 * 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 == 0){
		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;
}
