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