misc.c 5.45 KB

/*************************************************************************
 *
 *  File: misc.c
 *
 *  This file contains various miscellaneous routines
 *
 *  $Header: /root/leakn64/depot/rf/sw/bbplayer/iosim/src/misc.c,v 1.4 2003/03/18 19:45:06 whs Exp $
 *
 */

#ifdef __sgi__
#include <sys/cachectl.h>
#endif
#include <sys/mman.h>
#include <sys/prctl.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#ifdef __sgi__
#include <libelf.h>
#endif 
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#ifndef __sgi__
#include <signal.h>
#endif

#include "sim.h"
#include "simipc.h"
#include "iomap.h"
#include "bcp_util.h"

#define	ZERO	"/dev/zero"
#define	MAXARGS	50

/*
 * External references
 */
extern char	IpcName[];

/*
 * Local variables
 */
static pid_t serverPid;

void
ExecServer(char *server)
{
	char ipcNameArg[_POSIX_PATH_MAX];
	static char *serverArgs[MAXARGS];
	char *sp;
	int i;

	i = 0;
	sp = server;
	while (*sp != '\0') {
		serverArgs[i++] = sp;
		while ((*sp != '\0') && !isspace(*sp))
			sp++;
		if (isspace(*sp))
			*sp++ = '\0';
	}

	strcpy(ipcNameArg, "+ipc=");
	strcat(ipcNameArg, basename(IpcName));

	serverArgs[i++] = ipcNameArg;
	serverArgs[i] = NULL;

	printf("Executing %s\n", server);
	if ((serverPid = fork()) == -1) {
		fprintf(stderr, "Can't fork (%s)\n", strerror(errno));
		exit(1);
	} else if (serverPid == 0) {
#ifdef __sgi__
		 if (prctl(PR_TERMCHILD) == -1) {
			fprintf(stderr, "prctl(PR_TERMCHILD) failed (%s)\n",
				strerror(errno));
			exit(1);
		 }
#else
		 if (prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) {
			fprintf(stderr, "prctl(PR_TERMCHILD) failed (%s)\n",
				strerror(errno));
			exit(1);
		 }
#endif
		execv(server, serverArgs);
		fprintf(stderr, "Can't exec %s (%s)\n",
			server, strerror(errno));
		exit(1);
	}
}

void
WaitServer(void)
{
	int status;

	waitpid(serverPid, &status, 0);
}

/*
 * Routine to search for the verilog server process
 * Loop forever until connection is established
 */
int
FindServer(void)
{
	static IpcPkt	req, rsp;
	int 		ret, fd;
	unsigned int 	i;

#if 1
retry:
#endif
	fd = IpcOpen(IPC_CLIENT);
	if (fd < 0) {
		exit(1);
	}
	i = 0;
	while (1) {
		i++;
		printf("Trying to connect to verilog server ...\n");
		ret = IpcConnect(fd);
		if (ret < 0) {
			/* Sleep for 5 seconds and try again */
			sleep(5);	
#if 0
			continue;
#else
			IpcClose(fd);
			goto retry;
#endif
		}
		else
			break;
	}
	/* Here, we send a dummy write request */
#ifdef __sgi__
	req.length = sizeof(IpcPkt);
	req.code   = REQ_SINGLE_WRITE;
	req.size   = 4;
	req.address = MI_VERSION_REG;
#else 
	req.length = htonl(sizeof(IpcPkt));
	req.code   = htonl(BCP_SYSCLK_PERIOD); 
#endif

        if (IpcSend(fd, (char *)&req, sizeof(req)) < 0) {
                IpcClose(fd);
                return(-1);
        }
        if (IpcReceive(fd, (char *)&rsp, sizeof(rsp)) < 0) {
                IpcClose(fd);
                return(-1);
        }

	IpcClose(fd);

	return(0);

} /* FindServer */


#ifdef __sgi__
/*
 * Attempt to load application and execute (NOT USED!)
 */
int
LoadApp(char *file, descriptor_t *dp)
{
	int fd, zerofd;
	int i;
	int foundtext = 0;
	Elf *elf;
	Elf32_Ehdr *ehdr;
	Elf32_Phdr *phdr;

	if ((zerofd = open(ZERO,O_RDWR)) < 0) {
		fprintf(stderr, "sim: %s: can't open (%s)\n",
			ZERO, strerror(errno));
		return(-1);
	}
	if ((fd = open(file, O_RDONLY)) < 0) {
		fprintf(stderr, "sim: %s: can't open (%s)\n",
			file, strerror(errno));
		return(-1);
	}
	if (elf_version(EV_CURRENT) == EV_NONE) {
		fprintf(stderr, "sim: elf library out of date\n");
		return(-1);
	}
	(void)elf_errno();
	if ((elf = elf_begin(fd, ELF_C_READ, (Elf *)NULL)) == NULL) {
		fprintf(stderr, "sim: elf_begin failed (%s)\n", elf_error());
		return(-1);
	}
	if ((ehdr = elf32_getehdr(elf)) == NULL) {
		fprintf(stderr, "sim: elf32_getehdr failed (%s)\n",
			elf_error());
		return(-1);
	}

	if ((phdr = elf32_getphdr(elf)) == NULL) {
		fprintf(stderr, "sim: elf32_getphdr failed (%s)\n",
			elf_error());
		return(-1);
	}

	for (i = 0; i < ehdr->e_phnum; i++) {

		if (phdr->p_type == PT_LOAD) {

		    if ((mmap((void *)phdr->p_vaddr, phdr->p_memsz,
			  PROT_READ|PROT_WRITE|PROT_EXEC,
			  MAP_FIXED|MAP_PRIVATE, zerofd, 0)) == (void *)-1) {
			fprintf(stderr, "sim: mmap(0x%x) failed (%s)\n",
				phdr->p_vaddr, strerror(errno));
		    }
		    if (lseek(fd, 0, SEEK_SET) < 0) {
			fprintf(stderr, "sim: lseek of %s failed (%s)\n",
				file, strerror(errno));
			return(-1);
		    }
		    if (read(fd, (void *)phdr->p_vaddr, phdr->p_filesz) !=
				phdr->p_filesz) {
			fprintf(stderr, "sim: read of %s failed (%s)\n",
				file, strerror(errno));
			return(-1);
		    }
		    cacheflush((void *)phdr->p_vaddr, phdr->p_filesz, BCACHE);
		    if (phdr->p_flags & PF_X) {
			dp->entry = (entry_t)ehdr->e_entry;
			dp->addr = phdr->p_vaddr;
			dp->size = phdr->p_memsz;
			foundtext = 1;
		    }

		/* Skip header */
		dp->entry = (entry_t)((char *)dp->entry + 160);	
		dp->addr = dp->addr + 160;
		printf("New DP: entry=0x%08x, *entry=0x%08x, addr=0x%08x\n", 
			dp->entry, *(minst_t *)(dp->entry), dp->addr);
		}
		else
			/* DEBUG */
			printf(" (X)\n");

		phdr++;
	}

	if (!foundtext) {
		fprintf(stderr,
			"sim: %s has no executable PT_LOAD sections\n", file);
		return(-1);
	} else {
		return(0);
	}
}  /* LoadApp */


/*
 * Called by LoadApp (NOT USED!)
 */
const char *
elf_error(void)
{
	int err;

	if ((err = elf_errno()) == 0)
		return("unknown");
	else
		return(elf_errmsg(err));
}
#endif