Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / ui_utils.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: ui_utils.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
/*
* Copyright (C) 1991, Sun Microsystems, Inc.
*/
#pragma ident "@(#)1.14 06/01/25 ui_utils.cc"
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <thread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/exec.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/procfs.h>
#include <ctype.h>
#include <dlfcn.h>
#include "ui.h"
#include "types.h"
#include "blaze_globals.h"
#include "system.h"
#include "ui_utils.h"
#include "sim_cmd_struct.h"
#include "blaze_globals.h"
#include "ui_cmd_struct.h"
#include "ui_cmds.h"
#include "blz_runtime.h"
#include "macrolib.h"
#include "scsi_ctrl.h"
#include "remote.h"
#include "tracemod.h"
wd_thread_t *pwd_locker = NULL;
time_thread_t *ptm_locker = NULL;
#ifdef __cplusplus
extern "C" {
#endif
static void * wd_thread_start (void *);
static void * time_thread_start (void *);
#ifdef __cplusplus
}
#endif
///////////////////////////////////////////////////
//
// Create Remote Interface
//
void *remote_lib_handle = NULL;
RemoteExInterface g_remote_ex_intf;
RemoteConfig g_remote_config;
char remote_help_str[] = "remote [port=<port#>] [debug_on=1]";
int remote_cmd_action(void * /* usrdata */, int argc, char **argv)
{
// parse config arguments
for (int i=1; i<argc; i++)
{
// get param name
char *name_value = argv[i];
char *name = strtok ( name_value, " =" );
if (name == NULL)
{
ui->error("cannot read remote interface param name %s\n", name_value);
continue;
}
// get param value
int value = 0;
char *param = strtok ( NULL, "\0" );
if (param == NULL)
{
ui->error("cannot read remote interface param value %s\n", name_value);
continue;
}
else
{
value = (int)strtol(param, NULL, 0);
}
if (strcmp ( name, "port") == 0 )
{
g_remote_config.port = value;
}
else if (strcmp ( name, "max_connections") == 0 )
{
g_remote_config.max_connections = value;
}
else if (strcmp ( name, "debug_on") == 0 )
{
g_remote_config.debug_on = value;
}
}
// start remote interface
g_remote_ex_intf.create(&g_remote_config);
return 1;
}
//
// initialize remote debugger interface
//
int init_remote_debugger_interface (char* fname, char* modname, void* lib_handle)
{
if (remote_lib_handle != 0)
{
ui->error("Remote Interface was loaded already %s\n", modname );
return 0;
}
remote_lib_handle = lib_handle;
if ( remote_lib_handle == NULL )
{
ui->error("cannot obtain a handle for Remote Interface library %s\n", fname );
return 0;
}
// extract lib exported interface
GetRemoteIntfFn get_interface = (GetRemoteIntfFn)dlsym ( remote_lib_handle, "get_ex_remote_interface" );
if (get_interface == NULL)
{
ui->error("cannot find remote exported interface, wrong libriry\n");
exit (1);
}
// obtain remote interface
get_interface ( &g_remote_ex_intf);
UI_register_cmd_2("remote", remote_help_str, remote_cmd_action, NULL);
// set defaults config params
g_remote_config.port = INTF_PORT;
g_remote_config.max_connections = MAX_CONNECTIONS;
g_remote_config.port_step = MAX_PORT_STEP;
g_remote_config.debug_on = 0;
return 1;
}
// update stop status for the remote client if any extern
int update_remote_ui()
{
if (g_remote_ex_intf.update_status)
g_remote_ex_intf.update_status(SIGNAL_BREAKPOINT);
return 0;
}
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/*
* This routine parses thru a string. It sets wp to point to the first
* word in that string and returns a pointer to the rest of the line.
* It puts a null character after the first word.
* It eats leading white space characters. If string doesn't contain
* any text, it sets wp and the return value to point to a null character.
*/
char* ui_parsew(char* cp, char** wp)
{
/* Eat leading white space. */
while (isspace(*cp))
cp++;
if(wp)
*wp = cp;
/* No words in string so return. */
if (*cp == '\0')
return (cp);
/* skip over first word */
while (!isspace(*cp) && *cp != '\0')
cp++; /* skip over word */
/* Put null char after first word in string. */
if (*cp != '\0') {
*cp++ = '\0';
}
/* Eat white space between first word and rest of line. */
while (isspace(*cp))
cp++;
/* Strip off any white space at end of first word. */
if(wp)
ui_remove_trailing_whitespace(*wp);
/* Strip off any white space at end of line. */
ui_remove_trailing_whitespace(cp);
return (cp);
}
///////////////////////////////////////////////////////
/* Strip off any white space or newlines at end of string. */
void ui_remove_trailing_whitespace(char* str)
{
char *cp;
/* Null string. */
if (*str == '\0') {
return;
}
for (cp = str + strlen(str) - 1; (cp >= str) && (*cp == '\n' || isspace(*cp)); cp--) {
*cp = '\0';
}
}
// This function extracts a string from the buffer
// passed in. Returned is a freshly allocated buffer
// for the new string, which is null terminated.
//
// It is the caller's responsibility to eventually
// free the allocated string.
char * extract_string(char * cmd_str)
{
int len;
char * p = cmd_str;
char * bufp;
bool_t is_quoted = false;
int c;
char * bp;
while (isspace(*p)) p++;
len = strlen(p);
// be lazy, allocate all the space for the buffer
assert(bufp = (char*)malloc(len+1));
if (*p == '\"') {
is_quoted = true;
p++;
}
bp = bufp;
do {
c = p[0];
switch (c) {
case '\0':
if (is_quoted) {
ui->error("Missing closing quote at end of string: %s\n",cmd_str);
goto fail;
}
goto success;
case '\\':
c = p[1];
switch (c) {
case '\0':
ui->error("Illegal escape at end of string: %s\n",cmd_str);
goto fail;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case '"': c = '"'; break;
case '\\': c = '\\'; break;
default:
ui->error("Unknown escape in string: %s\n",cmd_str);
goto fail;
}
p++;
break;
case '"':
if (is_quoted) goto success;
ui->error("Quotes need to be escaped in the string: %s\n",cmd_str);
goto fail;
case ' ':
case '\t':
if (!is_quoted) goto success;
break;
default:
break;
}
*bp++ = c;
p++;
} while (true);
success:
bp[0]='\0';
return bufp;
fail:
free(bufp);
return (char *)0;
}
///////////////////////////////////////////////////////
//
// SL (09/07/2001)
// Added new routine for BLAZE UI parsing
//
// returns ARGV pointer, sets *ARGC
char **
ui_argv_argc_parse (char *cmd, int *neval)
{
int argc = 4; /* *neval; using neval is dumb, requires user init */
int nargc = 0;
char **pargv = (char**) calloc (argc, sizeof(char*));
char * cmdcopy = (char*) strdup(cmd);
char *s = cmdcopy;
char *ps;
int inquotes = 0; /* flag when we're inside a " quoted string */
int backslash = 0; /* yet another flag... */
if (pargv == NULL)
return NULL;
// remove leading spaces if any
while (isspace(*s)) {
if ((*s == '\0') || (*s == '\n')) {
*neval = 0;
return NULL;
}
++s;
}
ps = s;
for (;;) {
inquotes = 0;
while (!isspace(*s) || inquotes) {
if (*s == '"')
inquotes = ! inquotes;
++s;
if (*s == '\0')
goto EOLINE;
#if 0 /* not yet debugged, and needs to be before the ++s */
if (*s == '"' && ! backslash) inquotes = ! inquotes;
if (backslash)
backslash = 0;
else
if (*s == '\\') backslash = 1;
#endif
}
// copy parsed arg into argv
*s = '\0';
pargv[nargc++] = (char*) strdup (ps);
++s;
// re-allocate argv if we have too many args
//
if (nargc >= argc) {
argc <<= 1;
pargv = (char**) realloc (pargv, sizeof(char*) * argc);
}
//
// skip (insignificant) white-spaces between words
//
while (isspace(*s)) {
++s;
}
if ((*s == '\0') || (*s == '\n'))
goto DONE;
ps = s;
}
EOLINE:
pargv[nargc++] = (char*) strdup (ps);
DONE:
free(cmdcopy);
*neval = nargc;
return pargv;
}
void ui_argv_free(int argc, char **argv)
{
int i;
for (i=0; i<argc; i++) {
free(argv[i]);
}
free(argv);
} // ui_argv_free()
///////////////////////////////////////////////////////
bool_t redirect_stdout (int target_fd)
{
int dup_fd = dup (fileno(stdout));
close( fileno(stdout) );
if (dup( target_fd ) <= -1) {
ui->perror("dup");
return FALSE;
}
close (target_fd);
store_stdout_fd (dup_fd);
return TRUE;
}
///////////////////////////////////////////////////////
bool_t redirect_back ()
{
int dup_fd = get_stdout_fd ();
if (dup_fd <= -1) {
ui->error("STDOUT has not been redirected\n");
return FALSE;
}
close( fileno(stdout) );
if (dup (dup_fd) <= -1) {
ui->perror("dup");
return FALSE;
}
close(dup_fd);
store_stdout_fd (-1);
return TRUE;
}