Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: ui_utils.cc | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | /* | |
22 | * Copyright (C) 1991, Sun Microsystems, Inc. | |
23 | */ | |
24 | #pragma ident "@(#)1.14 06/01/25 ui_utils.cc" | |
25 | ||
26 | ||
27 | #include <sys/types.h> | |
28 | #include <assert.h> | |
29 | #include <stdio.h> | |
30 | #include <unistd.h> | |
31 | ||
32 | #include <stdio.h> | |
33 | #include <thread.h> | |
34 | #include <stdlib.h> | |
35 | #include <string.h> | |
36 | #include <sys/exec.h> | |
37 | #include <sys/stat.h> | |
38 | #include <sys/time.h> | |
39 | #include <sys/resource.h> | |
40 | #include <sys/procfs.h> | |
41 | #include <ctype.h> | |
42 | #include <dlfcn.h> | |
43 | ||
44 | #include "ui.h" | |
45 | #include "types.h" | |
46 | #include "blaze_globals.h" | |
47 | #include "system.h" | |
48 | ||
49 | #include "ui_utils.h" | |
50 | #include "sim_cmd_struct.h" | |
51 | #include "blaze_globals.h" | |
52 | #include "ui_cmd_struct.h" | |
53 | #include "ui_cmds.h" | |
54 | #include "blz_runtime.h" | |
55 | #include "macrolib.h" | |
56 | #include "scsi_ctrl.h" | |
57 | #include "remote.h" | |
58 | #include "tracemod.h" | |
59 | ||
60 | wd_thread_t *pwd_locker = NULL; | |
61 | time_thread_t *ptm_locker = NULL; | |
62 | ||
63 | ||
64 | #ifdef __cplusplus | |
65 | extern "C" { | |
66 | #endif | |
67 | static void * wd_thread_start (void *); | |
68 | static void * time_thread_start (void *); | |
69 | #ifdef __cplusplus | |
70 | } | |
71 | #endif | |
72 | ||
73 | ||
74 | ||
75 | ||
76 | /////////////////////////////////////////////////// | |
77 | // | |
78 | // Create Remote Interface | |
79 | // | |
80 | ||
81 | void *remote_lib_handle = NULL; | |
82 | RemoteExInterface g_remote_ex_intf; | |
83 | RemoteConfig g_remote_config; | |
84 | char remote_help_str[] = "remote [port=<port#>] [debug_on=1]"; | |
85 | ||
86 | ||
87 | int remote_cmd_action(void * /* usrdata */, int argc, char **argv) | |
88 | { | |
89 | // parse config arguments | |
90 | for (int i=1; i<argc; i++) | |
91 | { | |
92 | // get param name | |
93 | char *name_value = argv[i]; | |
94 | char *name = strtok ( name_value, " =" ); | |
95 | ||
96 | if (name == NULL) | |
97 | { | |
98 | ui->error("cannot read remote interface param name %s\n", name_value); | |
99 | continue; | |
100 | } | |
101 | ||
102 | // get param value | |
103 | int value = 0; | |
104 | char *param = strtok ( NULL, "\0" ); | |
105 | if (param == NULL) | |
106 | { | |
107 | ui->error("cannot read remote interface param value %s\n", name_value); | |
108 | continue; | |
109 | } | |
110 | else | |
111 | { | |
112 | value = (int)strtol(param, NULL, 0); | |
113 | } | |
114 | ||
115 | ||
116 | if (strcmp ( name, "port") == 0 ) | |
117 | { | |
118 | g_remote_config.port = value; | |
119 | } | |
120 | else if (strcmp ( name, "max_connections") == 0 ) | |
121 | { | |
122 | g_remote_config.max_connections = value; | |
123 | } | |
124 | else if (strcmp ( name, "debug_on") == 0 ) | |
125 | { | |
126 | g_remote_config.debug_on = value; | |
127 | } | |
128 | ||
129 | } | |
130 | ||
131 | // start remote interface | |
132 | g_remote_ex_intf.create(&g_remote_config); | |
133 | ||
134 | return 1; | |
135 | } | |
136 | ||
137 | // | |
138 | // initialize remote debugger interface | |
139 | // | |
140 | int init_remote_debugger_interface (char* fname, char* modname, void* lib_handle) | |
141 | { | |
142 | if (remote_lib_handle != 0) | |
143 | { | |
144 | ui->error("Remote Interface was loaded already %s\n", modname ); | |
145 | return 0; | |
146 | } | |
147 | ||
148 | remote_lib_handle = lib_handle; | |
149 | ||
150 | if ( remote_lib_handle == NULL ) | |
151 | { | |
152 | ui->error("cannot obtain a handle for Remote Interface library %s\n", fname ); | |
153 | return 0; | |
154 | } | |
155 | ||
156 | // extract lib exported interface | |
157 | GetRemoteIntfFn get_interface = (GetRemoteIntfFn)dlsym ( remote_lib_handle, "get_ex_remote_interface" ); | |
158 | ||
159 | if (get_interface == NULL) | |
160 | { | |
161 | ui->error("cannot find remote exported interface, wrong libriry\n"); | |
162 | exit (1); | |
163 | } | |
164 | ||
165 | // obtain remote interface | |
166 | get_interface ( &g_remote_ex_intf); | |
167 | ||
168 | UI_register_cmd_2("remote", remote_help_str, remote_cmd_action, NULL); | |
169 | ||
170 | // set defaults config params | |
171 | g_remote_config.port = INTF_PORT; | |
172 | g_remote_config.max_connections = MAX_CONNECTIONS; | |
173 | g_remote_config.port_step = MAX_PORT_STEP; | |
174 | g_remote_config.debug_on = 0; | |
175 | ||
176 | return 1; | |
177 | } | |
178 | ||
179 | // update stop status for the remote client if any extern | |
180 | int update_remote_ui() | |
181 | { | |
182 | if (g_remote_ex_intf.update_status) | |
183 | g_remote_ex_intf.update_status(SIGNAL_BREAKPOINT); | |
184 | return 0; | |
185 | } | |
186 | ||
187 | ||
188 | /////////////////////////////////////////////////////// | |
189 | /////////////////////////////////////////////////////// | |
190 | ||
191 | /* | |
192 | * This routine parses thru a string. It sets wp to point to the first | |
193 | * word in that string and returns a pointer to the rest of the line. | |
194 | * It puts a null character after the first word. | |
195 | * It eats leading white space characters. If string doesn't contain | |
196 | * any text, it sets wp and the return value to point to a null character. | |
197 | */ | |
198 | ||
199 | char* ui_parsew(char* cp, char** wp) | |
200 | { | |
201 | /* Eat leading white space. */ | |
202 | while (isspace(*cp)) | |
203 | cp++; | |
204 | ||
205 | if(wp) | |
206 | *wp = cp; | |
207 | ||
208 | /* No words in string so return. */ | |
209 | if (*cp == '\0') | |
210 | return (cp); | |
211 | ||
212 | /* skip over first word */ | |
213 | while (!isspace(*cp) && *cp != '\0') | |
214 | cp++; /* skip over word */ | |
215 | ||
216 | /* Put null char after first word in string. */ | |
217 | if (*cp != '\0') { | |
218 | *cp++ = '\0'; | |
219 | } | |
220 | ||
221 | /* Eat white space between first word and rest of line. */ | |
222 | while (isspace(*cp)) | |
223 | cp++; | |
224 | ||
225 | /* Strip off any white space at end of first word. */ | |
226 | if(wp) | |
227 | ui_remove_trailing_whitespace(*wp); | |
228 | ||
229 | /* Strip off any white space at end of line. */ | |
230 | ui_remove_trailing_whitespace(cp); | |
231 | ||
232 | return (cp); | |
233 | } | |
234 | ||
235 | /////////////////////////////////////////////////////// | |
236 | ||
237 | /* Strip off any white space or newlines at end of string. */ | |
238 | ||
239 | void ui_remove_trailing_whitespace(char* str) | |
240 | { | |
241 | char *cp; | |
242 | ||
243 | /* Null string. */ | |
244 | if (*str == '\0') { | |
245 | return; | |
246 | } | |
247 | ||
248 | for (cp = str + strlen(str) - 1; (cp >= str) && (*cp == '\n' || isspace(*cp)); cp--) { | |
249 | *cp = '\0'; | |
250 | } | |
251 | } | |
252 | ||
253 | // This function extracts a string from the buffer | |
254 | // passed in. Returned is a freshly allocated buffer | |
255 | // for the new string, which is null terminated. | |
256 | // | |
257 | // It is the caller's responsibility to eventually | |
258 | // free the allocated string. | |
259 | ||
260 | char * extract_string(char * cmd_str) | |
261 | { | |
262 | int len; | |
263 | char * p = cmd_str; | |
264 | char * bufp; | |
265 | bool_t is_quoted = false; | |
266 | int c; | |
267 | char * bp; | |
268 | ||
269 | while (isspace(*p)) p++; | |
270 | ||
271 | len = strlen(p); | |
272 | ||
273 | // be lazy, allocate all the space for the buffer | |
274 | assert(bufp = (char*)malloc(len+1)); | |
275 | ||
276 | if (*p == '\"') { | |
277 | is_quoted = true; | |
278 | p++; | |
279 | } | |
280 | ||
281 | bp = bufp; | |
282 | do { | |
283 | c = p[0]; | |
284 | switch (c) { | |
285 | case '\0': | |
286 | if (is_quoted) { | |
287 | ui->error("Missing closing quote at end of string: %s\n",cmd_str); | |
288 | goto fail; | |
289 | } | |
290 | goto success; | |
291 | ||
292 | case '\\': | |
293 | c = p[1]; | |
294 | switch (c) { | |
295 | case '\0': | |
296 | ui->error("Illegal escape at end of string: %s\n",cmd_str); | |
297 | goto fail; | |
298 | case 'n': c = '\n'; break; | |
299 | case 'r': c = '\r'; break; | |
300 | case 't': c = '\t'; break; | |
301 | case '"': c = '"'; break; | |
302 | case '\\': c = '\\'; break; | |
303 | default: | |
304 | ui->error("Unknown escape in string: %s\n",cmd_str); | |
305 | goto fail; | |
306 | } | |
307 | p++; | |
308 | break; | |
309 | ||
310 | case '"': | |
311 | if (is_quoted) goto success; | |
312 | ui->error("Quotes need to be escaped in the string: %s\n",cmd_str); | |
313 | goto fail; | |
314 | ||
315 | case ' ': | |
316 | case '\t': | |
317 | if (!is_quoted) goto success; | |
318 | break; | |
319 | ||
320 | default: | |
321 | break; | |
322 | } | |
323 | *bp++ = c; | |
324 | p++; | |
325 | } while (true); | |
326 | ||
327 | success: | |
328 | bp[0]='\0'; | |
329 | return bufp; | |
330 | ||
331 | ||
332 | fail: | |
333 | free(bufp); | |
334 | return (char *)0; | |
335 | } | |
336 | ||
337 | /////////////////////////////////////////////////////// | |
338 | ||
339 | // | |
340 | // SL (09/07/2001) | |
341 | // Added new routine for BLAZE UI parsing | |
342 | // | |
343 | ||
344 | // returns ARGV pointer, sets *ARGC | |
345 | ||
346 | char ** | |
347 | ui_argv_argc_parse (char *cmd, int *neval) | |
348 | { | |
349 | int argc = 4; /* *neval; using neval is dumb, requires user init */ | |
350 | int nargc = 0; | |
351 | char **pargv = (char**) calloc (argc, sizeof(char*)); | |
352 | char * cmdcopy = (char*) strdup(cmd); | |
353 | char *s = cmdcopy; | |
354 | char *ps; | |
355 | int inquotes = 0; /* flag when we're inside a " quoted string */ | |
356 | int backslash = 0; /* yet another flag... */ | |
357 | ||
358 | if (pargv == NULL) | |
359 | return NULL; | |
360 | ||
361 | // remove leading spaces if any | |
362 | ||
363 | while (isspace(*s)) { | |
364 | if ((*s == '\0') || (*s == '\n')) { | |
365 | *neval = 0; | |
366 | return NULL; | |
367 | } | |
368 | ++s; | |
369 | } | |
370 | ||
371 | ||
372 | ps = s; | |
373 | for (;;) { | |
374 | ||
375 | inquotes = 0; | |
376 | while (!isspace(*s) || inquotes) { | |
377 | if (*s == '"') | |
378 | inquotes = ! inquotes; | |
379 | ++s; | |
380 | if (*s == '\0') | |
381 | goto EOLINE; | |
382 | ||
383 | #if 0 /* not yet debugged, and needs to be before the ++s */ | |
384 | ||
385 | if (*s == '"' && ! backslash) inquotes = ! inquotes; | |
386 | if (backslash) | |
387 | backslash = 0; | |
388 | else | |
389 | if (*s == '\\') backslash = 1; | |
390 | #endif | |
391 | } | |
392 | ||
393 | // copy parsed arg into argv | |
394 | *s = '\0'; | |
395 | pargv[nargc++] = (char*) strdup (ps); | |
396 | ++s; | |
397 | ||
398 | // re-allocate argv if we have too many args | |
399 | // | |
400 | if (nargc >= argc) { | |
401 | argc <<= 1; | |
402 | pargv = (char**) realloc (pargv, sizeof(char*) * argc); | |
403 | } | |
404 | ||
405 | // | |
406 | // skip (insignificant) white-spaces between words | |
407 | // | |
408 | while (isspace(*s)) { | |
409 | ++s; | |
410 | } | |
411 | if ((*s == '\0') || (*s == '\n')) | |
412 | goto DONE; | |
413 | ps = s; | |
414 | } | |
415 | ||
416 | EOLINE: | |
417 | pargv[nargc++] = (char*) strdup (ps); | |
418 | DONE: | |
419 | free(cmdcopy); | |
420 | ||
421 | *neval = nargc; | |
422 | return pargv; | |
423 | } | |
424 | ||
425 | ||
426 | void ui_argv_free(int argc, char **argv) | |
427 | { | |
428 | int i; | |
429 | for (i=0; i<argc; i++) { | |
430 | free(argv[i]); | |
431 | } | |
432 | free(argv); | |
433 | } // ui_argv_free() | |
434 | ||
435 | /////////////////////////////////////////////////////// | |
436 | ||
437 | bool_t redirect_stdout (int target_fd) | |
438 | { | |
439 | int dup_fd = dup (fileno(stdout)); | |
440 | ||
441 | close( fileno(stdout) ); | |
442 | if (dup( target_fd ) <= -1) { | |
443 | ui->perror("dup"); | |
444 | return FALSE; | |
445 | } | |
446 | close (target_fd); | |
447 | store_stdout_fd (dup_fd); | |
448 | return TRUE; | |
449 | } | |
450 | ||
451 | /////////////////////////////////////////////////////// | |
452 | ||
453 | bool_t redirect_back () | |
454 | { | |
455 | ||
456 | int dup_fd = get_stdout_fd (); | |
457 | if (dup_fd <= -1) { | |
458 | ui->error("STDOUT has not been redirected\n"); | |
459 | return FALSE; | |
460 | } | |
461 | close( fileno(stdout) ); | |
462 | if (dup (dup_fd) <= -1) { | |
463 | ui->perror("dup"); | |
464 | return FALSE; | |
465 | } | |
466 | close(dup_fd); | |
467 | store_stdout_fd (-1); | |
468 | return TRUE; | |
469 | } |