1 /* BLDCFG.C (c) Copyright Roger Bowler, 1999-2009 */
2 /* ESA/390 Configuration Builder */
3
4 /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */
5
6 /*-------------------------------------------------------------------*/
7 /* This module builds the configuration tables for the Hercules */
8 /* ESA/390 emulator. It reads information about the processors */
9 /* and I/O devices from a configuration file. It allocates */
10 /* main storage and expanded storage, initializes control blocks, */
11 /* and creates detached threads to handle console attention */
12 /* requests and to maintain the TOD clock and CPU timers. */
13 /*-------------------------------------------------------------------*/
14
15 /*-------------------------------------------------------------------*/
16 /* Additional credits: */
17 /* TOD clock offset contributed by Jay Maynard */
18 /* Dynamic device attach/detach by Jan Jaeger */
19 /* OSTAILOR parameter by Jay Maynard */
20 /* PANRATE parameter by Reed H. Petty */
21 /* CPUPRIO parameter by Jan Jaeger */
22 /* HERCPRIO, TODPRIO, DEVPRIO parameters by Mark L. Gaubatz */
23 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
24 /* $(DEFSYM) symbol substitution support by Ivan Warren */
25 /* Patch for ${var=def} symbol substitution (hax #26), */
26 /* and INCLUDE <filename> support (modified hax #27), */
27 /* contributed by Enrico Sorichetti based on */
28 /* original patches by "Hackules" */
29 /*-------------------------------------------------------------------*/
30
31 #include "hstdinc.h"
32
33 #if !defined(_BLDCFG_C_)
34 #define _BLDCFG_C_
35 #endif
36
37 #if !defined(_HENGINE_DLL_)
38 #define _HENGINE_DLL_
39 #endif
40
41 #include "hercules.h"
42 #include "devtype.h"
43 #include "opcode.h"
44 #include "hostinfo.h"
45
46 #if defined(OPTION_FISHIO)
47 #include "w32chan.h"
48 #endif // defined(OPTION_FISHIO)
49
50 #if defined( OPTION_TAPE_AUTOMOUNT )
51 #include "tapedev.h"
52 #endif
53
54 #if !defined(_GEN_ARCH)
55
56 #if defined(_ARCHMODE3)
57 #define _GEN_ARCH _ARCHMODE3
58 #include "bldcfg.c"
59 #undef _GEN_ARCH
60 #endif
61
62 #if defined(_ARCHMODE2)
63 #define _GEN_ARCH _ARCHMODE2
64 #include "bldcfg.c"
65 #undef _GEN_ARCH
66 #endif
67
68 typedef struct _DEVARRAY
69 {
70 U16 cuu1;
71 U16 cuu2;
72 } DEVARRAY;
73
74 typedef struct _DEVNUMSDESC
75 {
76 BYTE lcss;
77 DEVARRAY *da;
78 } DEVNUMSDESC;
79
80 /*-------------------------------------------------------------------*/
81 /* Static data areas */
82 /*-------------------------------------------------------------------*/
83 #define MAX_INC_LEVEL 8 /* Maximum nest level */
84 static int inc_level; /* Current nesting level */
85 // following commented out ISW 20061009 : Not referenced anywhere.
86 // static int inc_fname[MAX_INC_LEVEL]; /* filename (base or incl) */
87 static int inc_stmtnum[MAX_INC_LEVEL]; /* statement number */
88 static int inc_ignore_errors = 0; /* 1==ignore include errors */
89 #ifdef EXTERNALGUI
90 static char buf[1024]; /* Config statement buffer */
91 #else /*!EXTERNALGUI*/
92 static char buf[256]; /* Config statement buffer */
93 #endif /*EXTERNALGUI*/
94 static char *keyword; /* -> Statement keyword */
95 static char *operand; /* -> First argument */
96 static int addargc; /* Number of additional args */
97 static char *addargv[MAX_ARGS]; /* Additional argument array */
98
99
100 /*-------------------------------------------------------------------*/
101 /* Subroutine to parse an argument string. The string that is passed */
102 /* is modified in-place by inserting null characters at the end of */
103 /* each argument found. The returned array of argument pointers */
104 /* then points to each argument found in the original string. Any */
105 /* argument that begins with '#' comment indicator causes early */
106 /* termination of the parsing and is not included in the count. Any */
107 /* argument found that starts with a quote or apostrophe causes */
108 /* all characters up to the next quote or apostrophe to be */
109 /* included as part of that argument. The quotes/apostrophes them- */
110 /* selves are not considered part of any argument and are ignored. */
111 /* p Points to string to be parsed. */
112 /* maxargc Maximum allowable number of arguments. (Prevents */
113 /* overflowing the pargv array) */
114 /* pargv Pointer to buffer for argument pointer array. */
115 /* pargc Pointer to number of arguments integer result. */
116 /* Returns number of arguments found. (same value as at *pargc) */
117 /*-------------------------------------------------------------------*/
parse_args(char * p,int maxargc,char ** pargv,int * pargc)118 DLL_EXPORT int parse_args (char* p, int maxargc, char** pargv, int* pargc)
119 {
120 for (*pargc = 0; *pargc < MAX_ARGS; ++*pargc) addargv[*pargc] = NULL;
121
122 *pargc = 0;
123 *pargv = NULL;
124
125 while (*p && *pargc < maxargc)
126 {
127 while (*p && isspace(*p)) p++; if (!*p) break; // find start of arg
128
129 if (*p == '#') break; // stop on comments
130
131 *pargv = p; ++*pargc; // count new arg
132
133 while (*p && !isspace(*p) && *p != '\"' && *p != '\'') p++; if (!*p) break; // find end of arg
134
135 if (*p == '\"' || *p == '\'')
136 {
137 char delim = *p;
138 if (p == *pargv) *pargv = p+1;
139 while (*++p && *p != delim) {}; if (!*p) break; // find end of quoted string
140 }
141
142 *p++ = 0; // mark end of arg
143 pargv++; // next arg ptr
144 }
145
146 return *pargc;
147 }
148
delayed_exit(int exit_code)149 void delayed_exit (int exit_code)
150 {
151 /* Delay exiting is to give the system
152 * time to display the error message. */
153 fflush(stderr);
154 fflush(stdout);
155 usleep(100000);
156 // hdl_shut();
157 do_shutdown();
158 fflush(stderr);
159 fflush(stdout);
160 usleep(100000);
161 exit(exit_code);
162 }
163
164
165 /* storage configuration routine. To be moved *JJ */
config_storage(unsigned mainsize,unsigned xpndsize)166 static void config_storage(unsigned mainsize, unsigned xpndsize)
167 {
168 int off;
169
170 /* Obtain main storage */
171 sysblk.mainsize = mainsize * 1024 * 1024ULL;
172
173 sysblk.mainstor = calloc((size_t)(sysblk.mainsize + 8192), 1);
174
175 if (sysblk.mainstor != NULL)
176 sysblk.main_clear = 1;
177 else
178 sysblk.mainstor = malloc((size_t)(sysblk.mainsize + 8192));
179
180 if (sysblk.mainstor == NULL)
181 {
182 logmsg(_("HHCCF031S Cannot obtain %dMB main storage: %s\n"),
183 mainsize, strerror(errno));
184 delayed_exit(1);
185 }
186
187 /* Trying to get mainstor aligned to the next 4K boundary - Greg */
188 off = (uintptr_t)sysblk.mainstor & 0xFFF;
189 sysblk.mainstor += off ? 4096 - off : 0;
190
191 /* Obtain main storage key array */
192 sysblk.storkeys = calloc((size_t)(sysblk.mainsize / STORAGE_KEY_UNITSIZE), 1);
193 if (sysblk.storkeys == NULL)
194 {
195 sysblk.main_clear = 0;
196 sysblk.storkeys = malloc((size_t)(sysblk.mainsize / STORAGE_KEY_UNITSIZE));
197 }
198 if (sysblk.storkeys == NULL)
199 {
200 logmsg(_("HHCCF032S Cannot obtain storage key array: %s\n"),
201 strerror(errno));
202 delayed_exit(1);
203 }
204
205 /* Initial power-on reset for main storage */
206 storage_clear();
207
208 #if 0 /*DEBUG-JJ-20/03/2000*/
209 /* Mark selected frames invalid for debugging purposes */
210 for (i = 64 ; i < (sysblk.mainsize / STORAGE_KEY_UNITSIZE); i += 2)
211 if (i < (sysblk.mainsize / STORAGE_KEY_UNITSIZE) - 64)
212 sysblk.storkeys[i] = STORKEY_BADFRM;
213 else
214 sysblk.storkeys[i++] = STORKEY_BADFRM;
215 #endif
216
217 if (xpndsize != 0)
218 {
219 #ifdef _FEATURE_EXPANDED_STORAGE
220
221 /* Obtain expanded storage */
222 sysblk.xpndsize = xpndsize * (1024*1024 / XSTORE_PAGESIZE);
223 sysblk.xpndstor = calloc(sysblk.xpndsize, XSTORE_PAGESIZE);
224 if (sysblk.xpndstor)
225 sysblk.xpnd_clear = 1;
226 else
227 sysblk.xpndstor = malloc((size_t)sysblk.xpndsize * XSTORE_PAGESIZE);
228 if (sysblk.xpndstor == NULL)
229 {
230 logmsg(_("HHCCF033S Cannot obtain %dMB expanded storage: "
231 "%s\n"),
232 xpndsize, strerror(errno));
233 delayed_exit(1);
234 }
235 /* Initial power-on reset for expanded storage */
236 xstorage_clear();
237 #else /*!_FEATURE_EXPANDED_STORAGE*/
238 logmsg(_("HHCCF034W Expanded storage support not installed\n"));
239 #endif /*!_FEATURE_EXPANDED_STORAGE*/
240 } /* end if(sysblk.xpndsize) */
241 }
242
243 #if defined( OPTION_TAPE_AUTOMOUNT )
244 /*-------------------------------------------------------------------*/
245 /* Add directory to AUTOMOUNT allowed/disallowed directories list */
246 /* */
247 /* Input: tamdir pointer to work character array of at least */
248 /* MAX_PATH size containing an allowed/disallowed */
249 /* directory specification, optionally prefixed */
250 /* with the '+' or '-' indicator. */
251 /* */
252 /* ppTAMDIR address of TAMDIR ptr that upon successful */
253 /* completion is updated to point to the TAMDIR */
254 /* entry that was just successfully added. */
255 /* */
256 /* Output: upon success, ppTAMDIR is updated to point to the TAMDIR */
257 /* entry just added. Upon error, ppTAMDIR is set to NULL and */
258 /* the original input character array is set to the inter- */
259 /* mediate value being processed when the error occurred. */
260 /* */
261 /* Returns: 0 == success */
262 /* 1 == unresolvable path */
263 /* 2 == path inaccessible */
264 /* 3 == conflict w/previous */
265 /* 4 == duplicates previous */
266 /* 5 == out of memory */
267 /* */
268 /*-------------------------------------------------------------------*/
add_tamdir(char * tamdir,TAMDIR ** ppTAMDIR)269 DLL_EXPORT int add_tamdir( char *tamdir, TAMDIR **ppTAMDIR )
270 {
271 int rc, rej = 0;
272 char dirwrk[ MAX_PATH ] = {0};
273
274 *ppTAMDIR = NULL;
275
276 if (*tamdir == '-')
277 {
278 rej = 1;
279 memmove (tamdir, tamdir+1, MAX_PATH);
280 }
281 else if (*tamdir == '+')
282 {
283 rej = 0;
284 memmove (tamdir, tamdir+1, MAX_PATH);
285 }
286
287 /* Convert tamdir to absolute path ending with a slash */
288
289 #if defined(_MSVC_)
290 /* (expand any embedded %var% environment variables) */
291 rc = expand_environ_vars( tamdir, dirwrk, MAX_PATH );
292 if (rc == 0)
293 strlcpy (tamdir, dirwrk, MAX_PATH);
294 #endif
295
296 if (!realpath( tamdir, dirwrk ))
297 return (1); /* ("unresolvable path") */
298 strlcpy (tamdir, dirwrk, MAX_PATH);
299
300 /* Verify that the path is valid */
301 if (access( tamdir, R_OK | W_OK ) != 0)
302 return (2); /* ("path inaccessible") */
303
304 /* Append trailing path separator if needed */
305 rc = strlen( tamdir );
306 if (tamdir[rc-1] != *PATH_SEP)
307 strlcat (tamdir, PATH_SEP, MAX_PATH);
308
309 /* Check for duplicate/conflicting specification */
310 for (*ppTAMDIR = sysblk.tamdir;
311 *ppTAMDIR;
312 *ppTAMDIR = (*ppTAMDIR)->next)
313 {
314 if (strfilenamecmp( tamdir, (*ppTAMDIR)->dir ) == 0)
315 {
316 if ((*ppTAMDIR)->rej != rej)
317 return (3); /* ("conflict w/previous") */
318 else
319 return (4); /* ("duplicates previous") */
320 }
321 }
322
323 /* Allocate new AUTOMOUNT directory entry */
324 *ppTAMDIR = malloc( sizeof(TAMDIR) );
325 if (!*ppTAMDIR)
326 return (5); /* ("out of memory") */
327
328 /* Fill in the new entry... */
329 (*ppTAMDIR)->dir = strdup (tamdir);
330 (*ppTAMDIR)->len = strlen (tamdir);
331 (*ppTAMDIR)->rej = rej;
332 (*ppTAMDIR)->next = NULL;
333
334 /* Add new entry to end of existing list... */
335 if (sysblk.tamdir == NULL)
336 sysblk.tamdir = *ppTAMDIR;
337 else
338 {
339 TAMDIR *pTAMDIR = sysblk.tamdir;
340 while (pTAMDIR->next)
341 pTAMDIR = pTAMDIR->next;
342 pTAMDIR->next = *ppTAMDIR;
343 }
344
345 /* Use first allowable dir as default */
346 if (rej == 0 && sysblk.defdir == NULL)
347 sysblk.defdir = (*ppTAMDIR)->dir;
348
349 return (0); /* ("success") */
350 }
351 #endif /* OPTION_TAPE_AUTOMOUNT */
352
353 /*-------------------------------------------------------------------*/
354 /* Subroutine to read a statement from the configuration file */
355 /* The statement is then parsed into keyword, operand, and */
356 /* additional arguments. The output values are: */
357 /* keyword Points to first word of statement */
358 /* operand Points to second word of statement */
359 /* addargc Contains number of additional arguments */
360 /* addargv An array of pointers to each additional argument */
361 /* Returns 0 if successful, -1 if end of file */
362 /*-------------------------------------------------------------------*/
read_config(char * fname,FILE * fp)363 static int read_config (char *fname, FILE *fp)
364 {
365 int i; /* Array subscript */
366 int c; /* Character work area */
367 int stmtlen; /* Statement length */
368 #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
369 int inc_dollar; /* >=0 Ndx of dollar */
370 int inc_lbrace; /* >=0 Ndx of lbrace + 1 */
371 int inc_colon; /* >=0 Ndx of colon */
372 int inc_equals; /* >=0 Ndx of equals */
373 char *inc_envvar; /* ->Environment variable */
374 #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
375 int lstarted; /* Indicate if non-whitespace*/
376 /* has been seen yet in line */
377 char *cnfline; /* Pointer to copy of buffer */
378 #if defined(OPTION_CONFIG_SYMBOLS)
379 char *buf1; /* Pointer to resolved buffer*/
380 #endif /*defined(OPTION_CONFIG_SYMBOLS)*/
381
382 #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
383 inc_dollar = -1;
384 inc_lbrace = -1;
385 inc_colon = -1;
386 inc_equals = -1;
387 #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
388
389 while (1)
390 {
391 /* Increment statement number */
392 inc_stmtnum[inc_level]++;
393
394 /* Read next statement from configuration file */
395 for (stmtlen = 0, lstarted = 0; ;)
396 {
397 /* Read character from configuration file */
398 c = fgetc(fp);
399
400 /* Check for I/O error */
401 if (ferror(fp))
402 {
403 logmsg(_("HHCCF001S Error reading file %s line %d: %s\n"),
404 fname, inc_stmtnum[inc_level], strerror(errno));
405 delayed_exit(1);
406 }
407
408 /* Check for end of file */
409 if (stmtlen == 0 && (c == EOF || c == '\x1A'))
410 return -1;
411
412 /* Check for end of line */
413 if (c == '\n' || c == EOF || c == '\x1A')
414 break;
415
416 /* Ignore nulls and carriage returns */
417 if (c == '\0' || c == '\r') continue;
418
419 /* Check if it is a white space and no other character yet */
420 if(!lstarted && isspace(c)) continue;
421 lstarted=1;
422
423 /* Check that statement does not overflow buffer */
424 if (stmtlen >= (int)(sizeof(buf) - 1))
425 {
426 logmsg(_("HHCCF002S File %s line %d is too long\n"),
427 fname, inc_stmtnum[inc_level]);
428 delayed_exit(1);
429 }
430
431 #if defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
432 /* inc_dollar already processed? */
433 if (inc_dollar >= 0)
434 {
435 /* Left brace already processed? */
436 if (inc_lbrace >= 0)
437 {
438 /* End of variable spec? */
439 if (c == '}')
440 {
441 /* Terminate it */
442 buf[stmtlen] = '\0';
443
444 /* Terminate var name if we have a inc_colon specifier */
445 if (inc_colon >= 0)
446 {
447 buf[inc_colon] = '\0';
448 }
449
450 /* Terminate var name if we have a default value */
451 if (inc_equals >= 0)
452 {
453 buf[inc_equals] = '\0';
454 }
455
456 /* Reset statement index to start of variable */
457 stmtlen = inc_dollar;
458
459 /* Get variable value */
460 inc_envvar = getenv (&buf[inc_lbrace]);
461
462 /* Variable unset? */
463 if (inc_envvar == NULL)
464 {
465 /* Substitute default if specified */
466 if (inc_equals >= 0)
467 {
468 inc_envvar = &buf[inc_equals+1];
469 }
470 }
471 else // (environ variable defined)
472 {
473 /* Have ":=" specification? */
474 if (/*inc_colon >= 0 && */inc_equals >= 0)
475 {
476 /* Substitute default if value is NULL */
477 if (strlen (inc_envvar) == 0)
478 {
479 inc_envvar = &buf[inc_equals+1];
480 }
481 }
482 }
483
484 /* Have a value? (environment or default) */
485 if (inc_envvar != NULL)
486 {
487 /* Check that statement does not overflow buffer */
488 if (stmtlen+strlen(inc_envvar) >= sizeof(buf) - 1)
489 {
490 logmsg(_("HHCCF002S File %s line %d is too long\n"),
491 fname, inc_stmtnum[inc_level]);
492 delayed_exit(1);
493 }
494
495 /* Copy to buffer and update index */
496 stmtlen += sprintf (&buf[stmtlen], "%s", inc_envvar);
497 }
498
499 /* Reset indexes */
500 inc_equals = -1;
501 inc_colon = -1;
502 inc_lbrace = -1;
503 inc_dollar = -1;
504 continue;
505 }
506 else if (c == ':' && inc_colon < 0 && inc_equals < 0)
507 {
508 /* Remember possible start of default specifier */
509 inc_colon = stmtlen;
510 }
511 else if (c == '=' && inc_equals < 0)
512 {
513 /* Remember possible start of default specifier */
514 inc_equals = stmtlen;
515 }
516 }
517 else // (inc_lbrace < 0)
518 {
519 /* Remember start of variable name */
520 if (c == '{')
521 {
522 inc_lbrace = stmtlen + 1;
523 }
524 else
525 {
526 /* Reset inc_dollar specifier if immediately following
527 character is not a left brace */
528 inc_dollar = -1;
529 }
530 }
531 }
532 else // (inc_dollar < 0)
533 {
534 /* Enter variable substitution state */
535 if (c == '$')
536 {
537 inc_dollar = stmtlen;
538 }
539 }
540 #endif // defined( OPTION_ENHANCED_CONFIG_SYMBOLS )
541
542 /* Append character to buffer */
543 buf[stmtlen++] = c;
544
545 } /* end for(stmtlen) */
546
547 /* Remove trailing blanks and tabs */
548 while (stmtlen > 0 && (buf[stmtlen-1] == SPACE
549 || buf[stmtlen-1] == '\t')) stmtlen--;
550 buf[stmtlen] = '\0';
551
552 /* Ignore comments and null statements */
553 if (stmtlen == 0 || buf[0] == '*' || buf[0] == '#')
554 continue;
555
556 cnfline = strdup(buf);
557
558 /* Parse the statement just read */
559
560 #if defined(OPTION_CONFIG_SYMBOLS)
561
562 /* Perform variable substitution */
563 /* First, set some 'dynamic' symbols to their own values */
564
565 set_symbol("CUU","$(CUU)");
566 set_symbol("cuu","$(cuu)");
567 set_symbol("CCUU","$(CCUU)");
568 set_symbol("ccuu","$(ccuu)");
569
570 /* VERISION will be set here, earlier than in @PJJ */
571 /* console.c in order to make it usable in the @PJJ */
572 /* hercules configuration file. @PJJ */
573 set_symbol("VERSION", VERSION);
574
575 buf1=resolve_symbol_string(buf);
576
577 if(buf1!=NULL)
578 {
579 if(strlen(buf1)>=sizeof(buf))
580 {
581 logmsg(_("HHCCF002S File %s line %d is too long\n"),
582 fname, inc_stmtnum[inc_level]);
583 free(buf1);
584 delayed_exit(1);
585 }
586 strcpy(buf,buf1);
587
588 /* Free buf1 as explicitly stated to be needed in @PJJ */
589 /* resolve_symbol_string. @PJJ */
590 free(buf1);
591
592 }
593 #endif /*defined(OPTION_CONFIG_SYMBOLS)*/
594
595 parse_args (buf, MAX_ARGS, addargv, &addargc);
596
597 #if defined(OPTION_DYNAMIC_LOAD)
598 if(config_command)
599 {
600 if( config_command(addargc, (char**)addargv, cnfline) )
601 {
602 free(cnfline);
603 continue;
604 }
605 }
606 #endif /*defined(OPTION_DYNAMIC_LOAD)*/
607
608 if( !ProcessConfigCommand (addargc, (char**)addargv, cnfline) )
609 {
610 free(cnfline);
611 continue;
612 }
613
614 free(cnfline);
615
616 /* Move the first two arguments to separate variables */
617
618 keyword = addargv[0];
619 operand = addargv[1];
620
621 addargc = (addargc > 2) ? (addargc-2) : (0);
622
623 for (i = 0; i < MAX_ARGS; i++)
624 {
625 if (i < (MAX_ARGS-2)) addargv[i] = addargv[i+2];
626 else addargv[i] = NULL;
627 }
628
629 break;
630 } /* end while */
631
632 return 0;
633 } /* end function read_config */
634
lyear_adjust(int epoch)635 static inline S64 lyear_adjust(int epoch)
636 {
637 int year, leapyear;
638 U64 tod = hw_clock();
639
640 if(tod >= TOD_YEAR)
641 {
642 tod -= TOD_YEAR;
643 year = (tod / TOD_4YEARS * 4) + 1;
644 tod %= TOD_4YEARS;
645 if((leapyear = tod / TOD_YEAR) == 4)
646 year--;
647 year += leapyear;
648 }
649 else
650 year = 0;
651
652 if(epoch > 0)
653 return (((year % 4) != 0) && (((year % 4) - (epoch % 4)) <= 0)) ? -TOD_DAY : 0;
654 else
655 return (((year % 4) == 0 && (-epoch % 4) != 0) || ((year % 4) + (-epoch % 4) > 4)) ? TOD_DAY : 0;
656 }
657
658
659 DLL_EXPORT char *config_cnslport = "3270";
660 /*-------------------------------------------------------------------*/
661 /* Function to build system configuration */
662 /*-------------------------------------------------------------------*/
build_config(char * fname)663 void build_config (char *fname)
664 {
665 int rc; /* Return code */
666 int i; /* Array subscript */
667 int scount; /* Statement counter */
668 int cpu; /* CPU number */
669 int count; /* Counter */
670 FILE *inc_fp[MAX_INC_LEVEL]; /* Configuration file pointer*/
671
672 char *sserial; /* -> CPU serial string */
673 char *smodel; /* -> CPU model string */
674 char *sversion; /* -> CPU version string */
675 char *smainsize; /* -> Main size string */
676 char *sxpndsize; /* -> Expanded size string */
677 char *smaxcpu; /* -> Maximum number of CPUs */
678 char *snumcpu; /* -> Number of CPUs */
679 char *snumvec; /* -> Number of VFs */
680 char *sengines; /* -> Processor engine types */
681 char *ssysepoch; /* -> System epoch */
682 char *syroffset; /* -> System year offset */
683 char *stzoffset; /* -> System timezone offset */
684 char *shercprio; /* -> Hercules base priority */
685 char *stodprio; /* -> Timer thread priority */
686 char *scpuprio; /* -> CPU thread priority */
687 char *sdevprio; /* -> Device thread priority */
688 char *slogofile; /* -> 3270 logo file */
689 #if defined(_FEATURE_ECPSVM)
690 char *secpsvmlevel; /* -> ECPS:VM Keyword */
691 char *secpsvmlvl; /* -> ECPS:VM level (or 'no')*/
692 int ecpsvmac; /* -> ECPS:VM add'l arg cnt */
693 #endif /*defined(_FEATURE_ECPSVM)*/
694 #if defined(OPTION_SHARED_DEVICES)
695 char *sshrdport; /* -> Shared device port nbr */
696 #endif /*defined(OPTION_SHARED_DEVICES)*/
697 U16 version = 0x00; /* CPU version code */
698 int dfltver = 1; /* Default version code */
699 U32 serial; /* CPU serial number */
700 U16 model; /* CPU model number */
701 unsigned mainsize; /* Main storage size (MB) */
702 unsigned xpndsize; /* Expanded storage size (MB)*/
703 U16 maxcpu; /* Maximum number of CPUs */
704 U16 numcpu; /* Number of CPUs */
705 U16 numvec; /* Number of VFs */
706 #if defined(OPTION_SHARED_DEVICES)
707 U16 shrdport; /* Shared device port number */
708 #endif /*defined(OPTION_SHARED_DEVICES)*/
709 S32 sysepoch; /* System epoch year */
710 S32 tzoffset; /* System timezone offset */
711 S32 yroffset; /* System year offset */
712 S64 ly1960; /* Leap offset for 1960 epoch*/
713 int hercprio; /* Hercules base priority */
714 int todprio; /* Timer thread priority */
715 int cpuprio; /* CPU thread priority */
716 int devprio; /* Device thread priority */
717 DEVBLK *dev; /* -> Device Block */
718 char *sdevnum; /* -> Device number string */
719 char *sdevtype; /* -> Device type string */
720 int devtmax; /* Max number device threads */
721 #if defined(_FEATURE_ECPSVM)
722 int ecpsvmavail; /* ECPS:VM Available flag */
723 int ecpsvmlevel; /* ECPS:VM declared level */
724 #endif /*defined(_FEATURE_ECPSVM)*/
725 BYTE c; /* Work area for sscanf */
726 char *styp; /* -> Engine type string */
727 char *styp_values[] = {"CP","CF","AP","IL","??","IP"}; /* type values */
728 BYTE ptyp; /* Processor engine type */
729 #ifdef OPTION_SELECT_KLUDGE
730 int dummyfd[OPTION_SELECT_KLUDGE]; /* Dummy file descriptors --
731 this allows the console to
732 get a low fd when the msg
733 pipe is opened... prevents
734 cygwin from thrashing in
735 select(). sigh */
736 #endif
737 char hlogofile[FILENAME_MAX+1] = ""; /* File name from HERCLOGO */
738 char pathname[MAX_PATH]; /* file path in host format */
739
740 /* Initialize SETMODE and set user authority */
741 SETMODE(INIT);
742
743 #ifdef OPTION_SELECT_KLUDGE
744 /* Reserve some fd's to be used later for the message pipes */
745 for (i = 0; i < OPTION_SELECT_KLUDGE; i++)
746 dummyfd[i] = dup(fileno(stderr));
747 #endif
748
749 /* Open the base configuration file */
750 hostpath(pathname, fname, sizeof(pathname));
751 inc_level = 0;
752 inc_fp[inc_level] = fopen (pathname, "r");
753 if (inc_fp[inc_level] == NULL)
754 {
755 logmsg(_("HHCCF003S Open error file %s: %s\n"),
756 fname, strerror(errno));
757 delayed_exit(1);
758 }
759 inc_stmtnum[inc_level] = 0;
760
761 /* Set the default system parameter values */
762 serial = 0x000001;
763 model = 0x0586;
764 mainsize = 2;
765 xpndsize = 0;
766 maxcpu = 0;
767 numcpu = 0;
768 numvec = MAX_CPU_ENGINES;
769 sysepoch = 1900;
770 yroffset = 0;
771 tzoffset = 0;
772 #if defined(_390)
773 sysblk.arch_mode = ARCH_390;
774 #else
775 sysblk.arch_mode = ARCH_370;
776 #endif
777 #if defined(_900)
778 sysblk.arch_z900 = ARCH_900;
779 #endif
780 sysblk.pgminttr = OS_NONE;
781
782 sysblk.timerint = DEFAULT_TIMER_REFRESH_USECS;
783
784 #if defined( HTTP_SERVER_CONNECT_KLUDGE )
785 sysblk.http_server_kludge_msecs = 10;
786 #endif // defined( HTTP_SERVER_CONNECT_KLUDGE )
787
788 hercprio = DEFAULT_HERCPRIO;
789 todprio = DEFAULT_TOD_PRIO;
790 cpuprio = DEFAULT_CPU_PRIO;
791 devprio = DEFAULT_DEV_PRIO;
792 devtmax = MAX_DEVICE_THREADS;
793 sysblk.kaidle = KEEPALIVE_IDLE_TIME;
794 sysblk.kaintv = KEEPALIVE_PROBE_INTERVAL;
795 sysblk.kacnt = KEEPALIVE_PROBE_COUNT;
796 #if defined(_FEATURE_ECPSVM)
797 ecpsvmavail = 0;
798 ecpsvmlevel = 20;
799 #endif /*defined(_FEATURE_ECPSVM)*/
800 #if defined(OPTION_SHARED_DEVICES)
801 shrdport = 0;
802 #endif /*defined(OPTION_SHARED_DEVICES)*/
803
804 #if defined(_FEATURE_ASN_AND_LX_REUSE)
805 sysblk.asnandlxreuse = 0; /* ASN And LX Reuse is defaulted to DISABLE */
806 #endif
807
808 #ifdef PANEL_REFRESH_RATE
809 sysblk.panrate = PANEL_REFRESH_RATE_SLOW;
810 #endif
811
812 /* Initialize locks, conditions, and attributes */
813 initialize_lock (&sysblk.todlock);
814 initialize_lock (&sysblk.mainlock);
815 sysblk.mainowner = LOCK_OWNER_NONE;
816 initialize_lock (&sysblk.intlock);
817 initialize_lock (&sysblk.iointqlk);
818 sysblk.intowner = LOCK_OWNER_NONE;
819 initialize_lock (&sysblk.sigplock);
820 // initialize_detach_attr (&sysblk.detattr); // (moved to impl.c)
821 // initialize_join_attr (&sysblk.joinattr); // (moved to impl.c)
822 initialize_condition (&sysblk.cpucond);
823 for (i = 0; i < MAX_CPU_ENGINES; i++)
824 initialize_lock (&sysblk.cpulock[i]);
825 initialize_condition (&sysblk.sync_cond);
826 initialize_condition (&sysblk.sync_bc_cond);
827 #if defined(OPTION_INSTRUCTION_COUNTING)
828 initialize_lock (&sysblk.icount_lock);
829 #endif
830
831 #ifdef OPTION_PTTRACE
832 ptt_trace_init (0, 1);
833 #endif
834
835 #if defined(_FEATURE_MESSAGE_SECURITY_ASSIST)
836 /* Initialize the wrapping key registers lock */
837 initialize_lock(&sysblk.wklock);
838 #endif /*defined(_FEATURE_MESSAGE_SECURITY_ASSIST)*/
839
840 #if defined(OPTION_FISHIO)
841 InitIOScheduler // initialize i/o scheduler...
842 (
843 sysblk.arch_mode, // (for calling execute_ccw_chain)
844 &sysblk.devprio, // (ptr to device thread priority)
845 MAX_DEVICE_THREAD_IDLE_SECS, // (maximum device thread wait time)
846 devtmax // (maximum #of device threads allowed)
847 );
848 #else // !defined(OPTION_FISHIO)
849 initialize_lock (&sysblk.ioqlock);
850 initialize_condition (&sysblk.ioqcond);
851 /* Set max number device threads */
852 sysblk.devtmax = devtmax;
853 sysblk.devtwait = sysblk.devtnbr =
854 sysblk.devthwm = sysblk.devtunavail = 0;
855 #endif // defined(OPTION_FISHIO)
856
857 /* Default the licence setting */
858 losc_set(PGM_PRD_OS_RESTRICTED);
859
860 /* Default CPU type CP */
861 for (i = 0; i < MAX_CPU_ENGINES; i++)
862 sysblk.ptyp[i] = SCCB_PTYP_CP;
863
864 /* Cap the default priorities at zero if setuid not available */
865 #if !defined(NO_SETUID)
866 if (sysblk.suid != 0)
867 {
868 #endif /*!defined(NO_SETUID)*/
869 if (hercprio < 0)
870 hercprio = 0;
871 if (todprio < 0)
872 todprio = 0;
873 if (cpuprio < 0)
874 cpuprio = 0;
875 if (devprio < 0)
876 devprio = 0;
877 #if !defined(NO_SETUID)
878 }
879 #endif /*!defined(NO_SETUID)*/
880
881 /*****************************************************************/
882 /* Parse configuration file system parameter statements... */
883 /*****************************************************************/
884
885 for (scount = 0; ; scount++)
886 {
887 /* Read next record from the configuration file */
888 while (inc_level >= 0 && read_config (fname, inc_fp[inc_level]))
889 {
890 fclose (inc_fp[inc_level--]);
891 }
892 if (inc_level < 0)
893 {
894 logmsg(_("HHCCF004S No device records in file %s\n"),
895 fname);
896 delayed_exit(1);
897 }
898
899 #if defined( OPTION_ENHANCED_CONFIG_INCLUDE )
900 if (strcasecmp (keyword, "ignore") == 0)
901 {
902 if (strcasecmp (operand, "include_errors") == 0)
903 {
904 logmsg( _("HHCCF081I %s Will ignore include errors .\n"),
905 fname);
906 inc_ignore_errors = 1 ;
907 }
908
909 continue ;
910 }
911
912 /* Check for include statement */
913 if (strcasecmp (keyword, "include") == 0)
914 {
915 if (++inc_level >= MAX_INC_LEVEL)
916 {
917 logmsg(_( "HHCCF082S Error in %s line %d: "
918 "Maximum nesting level (%d) reached\n"),
919 fname, inc_stmtnum[inc_level-1], MAX_INC_LEVEL);
920 delayed_exit(1);
921 }
922
923 logmsg( _("HHCCF083I %s Including %s at %d.\n"),
924 fname, operand, inc_stmtnum[inc_level-1]);
925 hostpath(pathname, operand, sizeof(pathname));
926 inc_fp[inc_level] = fopen (pathname, "r");
927 if (inc_fp[inc_level] == NULL)
928 {
929 inc_level--;
930 if ( inc_ignore_errors == 1 )
931 {
932 logmsg(_("HHCCF084W %s Open error ignored file %s: %s\n"),
933 fname, operand, strerror(errno));
934 continue ;
935 }
936 else
937 {
938 logmsg(_("HHCCF085S %s Open error file %s: %s\n"),
939 fname, operand, strerror(errno));
940 delayed_exit(1);
941 }
942 }
943 inc_stmtnum[inc_level] = 0;
944 continue;
945 }
946 #endif // defined( OPTION_ENHANCED_CONFIG_INCLUDE )
947
948 /* Exit loop if first device statement found */
949 if (strlen(keyword) <= 4
950 && sscanf(keyword, "%x%c", &rc, &c) == 1)
951 break;
952 /* ISW */
953 /* Also exit if keyword contains '-', ',' or '.' */
954 /* Added because device statements may now be a compound device number specification */
955 if(strchr(keyword,'-'))
956 {
957 break;
958 }
959 if(strchr(keyword,'.'))
960 {
961 break;
962 }
963 if(strchr(keyword,','))
964 {
965 break;
966 }
967 /* Also exit if keyword contains ':' (added by Harold Grovesteen jan2008) */
968 /* Added because device statements may now contain channel set or LCSS id */
969 if(strchr(keyword,':'))
970 {
971 break;
972 }
973
974 /* Clear the operand value pointers */
975 sserial = NULL;
976 smodel = NULL;
977 sversion = NULL;
978 smainsize = NULL;
979 sxpndsize = NULL;
980 smaxcpu = NULL;
981 snumcpu = NULL;
982 snumvec = NULL;
983 sengines = NULL;
984 ssysepoch = NULL;
985 syroffset = NULL;
986 stzoffset = NULL;
987 shercprio = NULL;
988 stodprio = NULL;
989 scpuprio = NULL;
990 sdevprio = NULL;
991 slogofile = NULL;
992 #if defined(_FEATURE_ECPSVM)
993 secpsvmlevel = NULL;
994 secpsvmlvl = NULL;
995 ecpsvmac = 0;
996 #endif /*defined(_FEATURE_ECPSVM)*/
997
998 #if defined(OPTION_SHARED_DEVICES)
999 sshrdport = NULL;
1000 #endif /*defined(OPTION_SHARED_DEVICES)*/
1001
1002 /* Check for old-style CPU statement */
1003 if (scount == 0 && addargc == 5 && strlen(keyword) == 6
1004 && sscanf(keyword, "%x%c", &rc, &c) == 1)
1005 {
1006 sserial = keyword;
1007 smodel = operand;
1008 smainsize = addargv[0];
1009 sxpndsize = addargv[1];
1010 config_cnslport = strdup(addargv[2]);
1011 snumcpu = addargv[3];
1012 set_loadparm(addargv[4]);
1013 }
1014 else
1015 {
1016 if (strcasecmp (keyword, "cpuserial") == 0)
1017 {
1018 sserial = operand;
1019 }
1020 else if (strcasecmp (keyword, "cpumodel") == 0)
1021 {
1022 smodel = operand;
1023 }
1024 else if (strcasecmp (keyword, "mainsize") == 0)
1025 {
1026 smainsize = operand;
1027 }
1028 else if (strcasecmp (keyword, "xpndsize") == 0)
1029 {
1030 sxpndsize = operand;
1031 }
1032 else if (strcasecmp (keyword, "cnslport") == 0)
1033 {
1034 config_cnslport = strdup(operand);
1035 }
1036 else if (strcasecmp (keyword, "maxcpu") == 0)
1037 {
1038 smaxcpu = operand;
1039 }
1040 else if (strcasecmp (keyword, "numcpu") == 0)
1041 {
1042 snumcpu = operand;
1043 }
1044 else if (strcasecmp (keyword, "numvec") == 0)
1045 {
1046 snumvec = operand;
1047 }
1048 else if (strcasecmp (keyword, "engines") == 0)
1049 {
1050 sengines = operand;
1051 }
1052 else if (strcasecmp (keyword, "sysepoch") == 0)
1053 {
1054 ssysepoch = operand;
1055 if (addargc > 0)
1056 {
1057 syroffset = addargv[0];
1058 addargc--;
1059 }
1060 }
1061 else if (strcasecmp (keyword, "yroffset") == 0)
1062 {
1063 syroffset = operand;
1064 }
1065 else if (strcasecmp (keyword, "tzoffset") == 0)
1066 {
1067 stzoffset = operand;
1068 }
1069 else if (strcasecmp (keyword, "cpuverid") == 0)
1070 {
1071 sversion = operand;
1072 }
1073 else if (strcasecmp (keyword, "hercprio") == 0)
1074 {
1075 shercprio = operand;
1076 }
1077 else if (strcasecmp (keyword, "todprio") == 0)
1078 {
1079 stodprio = operand;
1080 }
1081 else if (strcasecmp (keyword, "cpuprio") == 0)
1082 {
1083 scpuprio = operand;
1084 }
1085 else if (strcasecmp (keyword, "devprio") == 0)
1086 {
1087 sdevprio = operand;
1088 }
1089 else if (strcasecmp (keyword, "logofile") == 0)
1090 {
1091 logmsg(_("HHCCF061W Warning in %s line %d: "
1092 "LOGOFILE statement deprecated. Use HERCLOGO instead\n"),
1093 fname, inc_stmtnum[inc_level]);
1094 slogofile=operand;
1095 }
1096 else if (strcasecmp (keyword, "herclogo") == 0)
1097 {
1098 slogofile=operand;
1099 }
1100 #if defined(_FEATURE_ECPSVM)
1101 /* ECPS:VM support */
1102 else if(strcasecmp(keyword, "ecps:vm") == 0)
1103 {
1104 secpsvmlevel=operand;
1105 secpsvmlvl=addargv[0];
1106 ecpsvmac=addargc;
1107 logmsg(_("HHCCF061W Warning in %s line %d: "
1108 "ECPS:VM Statement deprecated. Use ECPSVM instead\n"),
1109 fname, inc_stmtnum[inc_level]);
1110 addargc=0;
1111 }
1112 else if(strcasecmp(keyword, "ecpsvm") == 0)
1113 {
1114 secpsvmlevel=operand;
1115 secpsvmlvl=addargv[0];
1116 ecpsvmac=addargc;
1117 addargc=0;
1118 }
1119 #endif /*defined(_FEATURE_ECPSVM)*/
1120
1121 #if defined(OPTION_SHARED_DEVICES)
1122 else if (strcasecmp (keyword, "shrdport") == 0)
1123 {
1124 sshrdport = operand;
1125 }
1126 #endif /*defined(OPTION_SHARED_DEVICES)*/
1127
1128 else
1129 {
1130 logmsg( _("HHCCF008E Error in %s line %d: "
1131 "Syntax error: %s\n"),
1132 fname, inc_stmtnum[inc_level], keyword);
1133 operand = "";
1134 addargc = 0;
1135 }
1136
1137 /* Check for one and only one operand */
1138 if (operand == NULL || addargc != 0)
1139 {
1140 logmsg( _("HHCCF009E Error in %s line %d: "
1141 "Incorrect number of operands\n"),
1142 fname, inc_stmtnum[inc_level]);
1143 }
1144
1145 } /* end else (not old-style CPU statement) */
1146
1147 /* Parse CPU version number operand */
1148 if (sversion != NULL)
1149 {
1150 if (strlen(sversion) != 2
1151 || sscanf(sversion, "%hx%c", &version, &c) != 1
1152 || version>255)
1153 {
1154 logmsg(_("HHCCF012S Error in %s line %d: "
1155 "%s is not a valid CPU version code\n"),
1156 fname, inc_stmtnum[inc_level], sversion);
1157 delayed_exit(1);
1158 }
1159 dfltver = 0;
1160 }
1161
1162 /* Parse CPU serial number operand */
1163 if (sserial != NULL)
1164 {
1165 if (strlen(sserial) != 6
1166 || sscanf(sserial, "%x%c", &serial, &c) != 1)
1167 {
1168 logmsg(_("HHCCF051S Error in %s line %d: "
1169 "%s is not a valid serial number\n"),
1170 fname, inc_stmtnum[inc_level], sserial);
1171 delayed_exit(1);
1172 }
1173 }
1174
1175 /* Parse CPU model number operand */
1176 if (smodel != NULL)
1177 {
1178 if (strlen(smodel) != 4
1179 || sscanf(smodel, "%hx%c", &model, &c) != 1)
1180 {
1181 logmsg(_("HHCCF012S Error in %s line %d: "
1182 "%s is not a valid CPU model\n"),
1183 fname, inc_stmtnum[inc_level], smodel);
1184 delayed_exit(1);
1185 }
1186 }
1187
1188 /* Parse main storage size operand */
1189 if (smainsize != NULL)
1190 {
1191 if (sscanf(smainsize, "%u%c", &mainsize, &c) != 1
1192 || mainsize < 2
1193 || (mainsize > 4095 && sizeof(sysblk.mainsize) < 8)
1194 || (mainsize > 4095 && sizeof(size_t) < 8))
1195 {
1196 logmsg(_("HHCCF013S Error in %s line %d: "
1197 "Invalid main storage size %s\n"),
1198 fname, inc_stmtnum[inc_level], smainsize);
1199 delayed_exit(1);
1200 }
1201 }
1202
1203 /* Parse expanded storage size operand */
1204 if (sxpndsize != NULL)
1205 {
1206 if (sscanf(sxpndsize, "%u%c", &xpndsize, &c) != 1
1207 || xpndsize > (0x100000000ULL / XSTORE_PAGESIZE) - 1
1208 || (xpndsize > 4095 && sizeof(size_t) < 8))
1209 {
1210 logmsg(_("HHCCF014S Error in %s line %d: "
1211 "Invalid expanded storage size %s\n"),
1212 fname, inc_stmtnum[inc_level], sxpndsize);
1213 delayed_exit(1);
1214 }
1215 }
1216
1217 /* Parse Hercules priority operand */
1218 if (shercprio != NULL)
1219 if (sscanf(shercprio, "%d%c", &hercprio, &c) != 1)
1220 {
1221 logmsg(_("HHCCF016S Error in %s line %d: "
1222 "Invalid Hercules process group thread priority %s\n"),
1223 fname, inc_stmtnum[inc_level], shercprio);
1224 delayed_exit(1);
1225 }
1226
1227 #if !defined(NO_SETUID)
1228 if(sysblk.suid != 0 && hercprio < 0)
1229 {
1230 logmsg(_("HHCCF017W Hercules is not running as setuid root, "
1231 "cannot raise Hercules process group thread priority\n"));
1232 hercprio = 0; /* Set priority to Normal */
1233 }
1234 #endif /*!defined(NO_SETUID)*/
1235
1236 sysblk.hercprio = hercprio;
1237
1238 /* Parse TOD Clock priority operand */
1239 if (stodprio != NULL)
1240 if (sscanf(stodprio, "%d%c", &todprio, &c) != 1)
1241 {
1242 logmsg(_("HHCCF016S Error in %s line %d: "
1243 "Invalid TOD Clock thread priority %s\n"),
1244 fname, inc_stmtnum[inc_level], stodprio);
1245 delayed_exit(1);
1246 }
1247
1248 #if !defined(NO_SETUID)
1249 if(sysblk.suid != 0 && todprio < 0)
1250 {
1251 logmsg(_("HHCCF017W Hercules is not running as setuid root, "
1252 "cannot raise TOD Clock thread priority\n"));
1253 todprio = 0; /* Set priority to Normal */
1254 }
1255 #endif /*!defined(NO_SETUID)*/
1256
1257 sysblk.todprio = todprio;
1258
1259 /* Parse CPU thread priority operand */
1260 if (scpuprio != NULL)
1261 if (sscanf(scpuprio, "%d%c", &cpuprio, &c) != 1)
1262 {
1263 logmsg(_("HHCCF016S Error in %s line %d: "
1264 "Invalid CPU thread priority %s\n"),
1265 fname, inc_stmtnum[inc_level], scpuprio);
1266 delayed_exit(1);
1267 }
1268
1269 #if !defined(NO_SETUID)
1270 if(sysblk.suid != 0 && cpuprio < 0)
1271 {
1272 logmsg(_("HHCCF017W Hercules is not running as setuid root, "
1273 "cannot raise CPU priority\n"));
1274 cpuprio = 0; /* Set priority to Normal */
1275 }
1276 #endif /*!defined(NO_SETUID)*/
1277
1278 sysblk.cpuprio = cpuprio;
1279
1280 /* Parse Device thread priority operand */
1281 if (sdevprio != NULL)
1282 if (sscanf(sdevprio, "%d%c", &devprio, &c) != 1)
1283 {
1284 logmsg(_("HHCCF016S Error in %s line %d: "
1285 "Invalid device thread priority %s\n"),
1286 fname, inc_stmtnum[inc_level], sdevprio);
1287 delayed_exit(1);
1288 }
1289
1290 #if !defined(NO_SETUID)
1291 if(sysblk.suid != 0 && devprio < 0)
1292 logmsg(_("HHCCF017W Hercules is not running as setuid root, "
1293 "cannot raise device thread priority\n"));
1294 #endif /*!defined(NO_SETUID)*/
1295
1296 sysblk.devprio = devprio;
1297
1298 /* Parse Device thread priority operand */
1299 if (sdevprio != NULL)
1300 if (sscanf(sdevprio, "%d%c", &devprio, &c) != 1)
1301 {
1302 logmsg(_("HHCCF016S Error in %s line %d: "
1303 "Invalid device thread priority %s\n"),
1304 fname, inc_stmtnum[inc_level], sdevprio);
1305 delayed_exit(1);
1306 }
1307
1308 #if !defined(NO_SETUID)
1309 if(sysblk.suid != 0 && devprio < 0)
1310 logmsg(_("HHCCF017W Hercules is not running as setuid root, "
1311 "cannot raise device thread priority\n"));
1312 #endif /*!defined(NO_SETUID)*/
1313
1314 sysblk.devprio = devprio;
1315
1316 /* Parse maximum number of CPUs operand */
1317 if (smaxcpu != NULL)
1318 {
1319 if (sscanf(smaxcpu, "%hu%c", &maxcpu, &c) != 1
1320 || maxcpu < 1
1321 || maxcpu > MAX_CPU_ENGINES)
1322 {
1323 fprintf(stderr, _("HHCCF021S Error in %s line %d: "
1324 "Invalid maximum number of CPUs %s\n"),
1325 fname, inc_stmtnum[inc_level], smaxcpu);
1326 delayed_exit(1);
1327 }
1328 }
1329
1330 /* Parse number of CPUs operand */
1331 if (snumcpu != NULL)
1332 {
1333 if (sscanf(snumcpu, "%hu%c", &numcpu, &c) != 1
1334 || numcpu > MAX_CPU_ENGINES)
1335 {
1336 logmsg(_("HHCCF018S Error in %s line %d: "
1337 "Invalid number of CPUs %s\n"),
1338 fname, inc_stmtnum[inc_level], snumcpu);
1339 delayed_exit(1);
1340 }
1341 }
1342 sysblk.numcpu = numcpu ? numcpu : 1;
1343
1344 /* Parse number of VFs operand */
1345 if (snumvec != NULL)
1346 {
1347 #ifdef _FEATURE_VECTOR_FACILITY
1348 if (sscanf(snumvec, "%hu%c", &numvec, &c) != 1
1349 || numvec > MAX_CPU_ENGINES)
1350 {
1351 logmsg(_("HHCCF019S Error in %s line %d: "
1352 "Invalid number of VFs %s\n"),
1353 fname, inc_stmtnum[inc_level], snumvec);
1354 delayed_exit(1);
1355 }
1356 #else /*!_FEATURE_VECTOR_FACILITY*/
1357 logmsg(_("HHCCF020W Vector Facility support not configured\n"));
1358 #endif /*!_FEATURE_VECTOR_FACILITY*/
1359 }
1360 sysblk.numvec = numvec;
1361
1362 /* Parse processor engine types operand */
1363 /* example: ENGINES 4*CP,AP,2*IP */
1364 if (sengines != NULL)
1365 {
1366 styp = strtok(sengines,",");
1367 for (cpu = 0; styp != NULL; )
1368 {
1369 count = 1;
1370 if (isdigit(styp[0]))
1371 {
1372 if (sscanf(styp, "%d%c", &count, &c) != 2
1373 || c != '*' || count < 1)
1374 {
1375 logmsg(_("HHCCF074S Error in %s line %d: "
1376 "Invalid engine syntax %s\n"),
1377 fname, inc_stmtnum[inc_level], styp);
1378 delayed_exit(1);
1379 break;
1380 }
1381 styp = strchr(styp,'*') + 1;
1382 }
1383 if (strcasecmp(styp,"cp") == 0)
1384 ptyp = SCCB_PTYP_CP;
1385 else if (strcasecmp(styp,"cf") == 0)
1386 ptyp = SCCB_PTYP_ICF;
1387 else if (strcasecmp(styp,"il") == 0)
1388 ptyp = SCCB_PTYP_IFL;
1389 else if (strcasecmp(styp,"ap") == 0)
1390 ptyp = SCCB_PTYP_IFA;
1391 else if (strcasecmp(styp,"ip") == 0)
1392 ptyp = SCCB_PTYP_SUP;
1393 else {
1394 logmsg(_("HHCCF075S Error in %s line %d: "
1395 "Invalid engine type %s\n"),
1396 fname, inc_stmtnum[inc_level], styp);
1397 delayed_exit(1);
1398 break;
1399 }
1400 while (count-- > 0 && cpu < MAX_CPU_ENGINES)
1401 {
1402 logmsg("HHCCF077I Engine %d set to type %d (%s)\n",
1403 cpu, ptyp, styp_values[ptyp]);
1404 sysblk.ptyp[cpu++] = ptyp;
1405 }
1406 styp = strtok(NULL,",");
1407 }
1408 }
1409
1410 /* Parse system epoch operand */
1411 if (ssysepoch != NULL)
1412 {
1413 if (strlen(ssysepoch) != 4
1414 || sscanf(ssysepoch, "%d%c", &sysepoch, &c) != 1
1415 || sysepoch <= 1800 || sysepoch >= 2100)
1416 {
1417 logmsg(_("HHCCF022S Error in %s line %d: "
1418 "%s is not a valid system epoch.\n"
1419 " The only valid values are "
1420 "1801-2099\n"),
1421 fname, inc_stmtnum[inc_level], ssysepoch);
1422 delayed_exit(1);
1423 }
1424 }
1425
1426 /* Parse year offset operand */
1427 if (syroffset != NULL)
1428 {
1429 if (sscanf(syroffset, "%d%c", &yroffset, &c) != 1
1430 || (yroffset < -142) || (yroffset > 142))
1431 {
1432 logmsg(_("HHCCF070S Error in %s line %d: "
1433 "%s is not a valid year offset\n"),
1434 fname, inc_stmtnum[inc_level], syroffset);
1435 delayed_exit(1);
1436 }
1437 }
1438
1439 /* Parse timezone offset operand */
1440 if (stzoffset != NULL)
1441 {
1442 if (strlen(stzoffset) != 5
1443 || sscanf(stzoffset, "%d%c", &tzoffset, &c) != 1
1444 || (tzoffset < -2359) || (tzoffset > 2359))
1445 {
1446 logmsg(_("HHCCF023S Error in %s line %d: "
1447 "%s is not a valid timezone offset\n"),
1448 fname, inc_stmtnum[inc_level], stzoffset);
1449 delayed_exit(1);
1450 }
1451 }
1452
1453
1454 /* Parse terminal logo option */
1455 if (slogofile != NULL)
1456 {
1457 strncpy(hlogofile, slogofile, sizeof(hlogofile)-1);
1458 hlogofile[sizeof(hlogofile)-1] = '\0';
1459 }
1460
1461 #if defined(_FEATURE_ECPSVM)
1462 /* Parse ECPS:VM level */
1463 if(secpsvmlevel != NULL)
1464 {
1465 while(1) /* Dummy while loop for break support */
1466 {
1467 ecpsvmavail=0;
1468 ecpsvmlevel=0;
1469 if(strcasecmp(secpsvmlevel,"no")==0)
1470 {
1471 ecpsvmavail=0;
1472 break;
1473 }
1474 if(strcasecmp(secpsvmlevel,"yes")==0)
1475 {
1476 ecpsvmavail=1;
1477 ecpsvmlevel=20;
1478 break;
1479 }
1480 if(strcasecmp(secpsvmlevel,"level")==0)
1481 {
1482 ecpsvmavail=1;
1483 if(ecpsvmac==0)
1484 {
1485 logmsg(_("HHCCF062W Warning in %s line %d: "
1486 "Missing ECPSVM level value. 20 Assumed\n"),
1487 fname, inc_stmtnum[inc_level]);
1488 ecpsvmavail=1;
1489 ecpsvmlevel=20;
1490 break;
1491 }
1492 if (sscanf(secpsvmlvl, "%d%c", &ecpsvmlevel, &c) != 1)
1493 {
1494 logmsg(_("HHCCF051W Warning in %s line %d: "
1495 "Invalid ECPSVM level value : %s. 20 Assumed\n"),
1496 fname, inc_stmtnum[inc_level], secpsvmlevel);
1497 ecpsvmavail=1;
1498 ecpsvmlevel=20;
1499 break;
1500 }
1501 break;
1502 }
1503 ecpsvmavail=1;
1504 if (sscanf(secpsvmlevel, "%d%c", &ecpsvmlevel, &c) != 1)
1505 {
1506 logmsg(_("HHCCF051W Error in %s line %d: "
1507 "Invalid ECPSVM keyword : %s. NO Assumed\n"),
1508 fname, inc_stmtnum[inc_level], secpsvmlevel);
1509 ecpsvmavail=0;
1510 ecpsvmlevel=0;
1511 break;
1512 }
1513 else
1514 {
1515 logmsg(_("HHCCF063W Warning in %s line %d: "
1516 "Specifying ECPSVM level directly is deprecated. Use the 'LEVEL' keyword instead.\n"),
1517 fname, inc_stmtnum[inc_level]);
1518 break;
1519 }
1520 break;
1521 }
1522 sysblk.ecpsvm.available=ecpsvmavail;
1523 sysblk.ecpsvm.level=ecpsvmlevel;
1524 }
1525 #endif /*defined(_FEATURE_ECPSVM)*/
1526
1527 #if defined(OPTION_SHARED_DEVICES)
1528 /* Parse shared device port number operand */
1529 if (sshrdport != NULL)
1530 {
1531 if (sscanf(sshrdport, "%hu%c", &shrdport, &c) != 1
1532 || shrdport < 1024 )
1533 {
1534 logmsg(_("HHCCF029S Error in %s line %d: "
1535 "Invalid SHRDPORT port number %s\n"),
1536 fname, inc_stmtnum[inc_level], sshrdport);
1537 delayed_exit(1);
1538 }
1539 }
1540 #endif /*defined(OPTION_SHARED_DEVICES)*/
1541
1542 } /* end for(scount) (end of configuration file statement loop) */
1543
1544 /* Read the logofile */
1545 if (sysblk.logofile == NULL) /* LogoFile NOT passed in command line */
1546 {
1547 if (hlogofile[0] != '\0') /* LogoFile SET in hercules config */
1548 {
1549 readlogo(hlogofile);
1550 }
1551 else /* Try to Read Logo File using Default FileName */
1552 {
1553 slogofile=getenv("HERCLOGO");
1554 if (slogofile==NULL)
1555 {
1556 readlogo("herclogo.txt");
1557 }
1558 else
1559 {
1560 readlogo(slogofile);
1561 }
1562 } /* Otherwise Use Internal LOGO */
1563 }
1564 else /* LogoFile passed in command line */
1565 {
1566 readlogo(sysblk.logofile);
1567 }
1568
1569 #if defined( OPTION_TAPE_AUTOMOUNT )
1570 /* Define default AUTOMOUNT directory if needed */
1571 if (sysblk.tamdir && sysblk.defdir == NULL)
1572 {
1573 char cwd[ MAX_PATH ];
1574 TAMDIR *pNewTAMDIR = malloc( sizeof(TAMDIR) );
1575 if (!pNewTAMDIR)
1576 {
1577 logmsg( _("HHCCF900S Out of memory!\n"));
1578 delayed_exit(1);
1579 }
1580 VERIFY( getcwd( cwd, sizeof(cwd) ) != NULL );
1581 rc = strlen( cwd );
1582 if (cwd[rc-1] != *PATH_SEP)
1583 strlcat (cwd, PATH_SEP, sizeof(cwd));
1584 pNewTAMDIR->dir = strdup (cwd);
1585 pNewTAMDIR->len = strlen (cwd);
1586 pNewTAMDIR->rej = 0;
1587 pNewTAMDIR->next = sysblk.tamdir;
1588 sysblk.tamdir = pNewTAMDIR;
1589 sysblk.defdir = pNewTAMDIR->dir;
1590 logmsg(_("HHCCF090I Default Allowed AUTOMOUNT directory = \"%s\"\n"),
1591 sysblk.defdir);
1592 }
1593 #endif /* OPTION_TAPE_AUTOMOUNT */
1594
1595 /* Set root mode in order to set priority */
1596 SETMODE(ROOT);
1597
1598 /* Set Hercules base priority */
1599 if (setpriority(PRIO_PGRP, 0, hercprio))
1600 logmsg (_("HHCCF064W Hercules set priority %d failed: %s\n"),
1601 hercprio, strerror(errno));
1602
1603 /* Back to user mode */
1604 SETMODE(USER);
1605
1606 /* Display Hercules thread information on control panel */
1607 logmsg (_("HHCCF065I Hercules: tid="TIDPAT", pid=%d, pgid=%d, "
1608 "priority=%d\n"),
1609 thread_id(), getpid(), getpgrp(),
1610 getpriority(PRIO_PGRP,0));
1611
1612 #if defined(OPTION_SHARED_DEVICES)
1613 sysblk.shrdport = shrdport;
1614 #endif /*defined(OPTION_SHARED_DEVICES)*/
1615
1616 #if defined(_370) || defined(_390)
1617 if(dfltver)
1618 version =
1619 #if defined(_900)
1620 (sysblk.arch_mode == ARCH_900) ? 0x00 :
1621 #endif
1622 0xFD;
1623 #endif
1624 /* Build CPU identifier */
1625 sysblk.cpuid = ((U64)version << 56)
1626 | ((U64)serial << 32)
1627 | ((U64)model << 16);
1628
1629 /* Reset the clock steering registers */
1630 csr_reset();
1631
1632 /* Set up the system TOD clock offset: compute the number of
1633 * microseconds offset to 0000 GMT, 1 January 1900 */
1634
1635 if(sysepoch != 1900 && sysepoch != 1960)
1636 {
1637 if(sysepoch < 1960)
1638 logmsg(_("HHCCF072W SYSEPOCH %04d is deprecated. "
1639 "Please specify \"SYSEPOCH 1900 %s%d\".\n"),
1640 sysepoch, 1900-sysepoch > 0 ? "+" : "", 1900-sysepoch);
1641 else
1642 logmsg(_("HHCCF073W SYSEPOCH %04d is deprecated. "
1643 "Please specify \"SYSEPOCH 1960 %s%d\".\n"),
1644 sysepoch, 1960-sysepoch > 0 ? "+" : "", 1960-sysepoch);
1645 }
1646
1647 if(sysepoch == 1960 || sysepoch == 1988)
1648 ly1960 = TOD_DAY;
1649 else
1650 ly1960 = 0;
1651
1652 sysepoch -= 1900 + yroffset;
1653
1654 set_tod_epoch(((sysepoch*365+(sysepoch/4))*-TOD_DAY)+lyear_adjust(sysepoch)+ly1960);
1655
1656 sysblk.sysepoch = sysepoch;
1657
1658 /* Set the timezone offset */
1659 adjust_tod_epoch((tzoffset/100*3600+(tzoffset%100)*60)*16000000LL);
1660
1661 /* Gabor Hoffer (performance option) */
1662 copy_opcode_tables();
1663
1664 /*****************************************************************/
1665 /* Parse configuration file device statements... */
1666 /*****************************************************************/
1667
1668 while(1)
1669 {
1670 /* First two fields are device number and device type */
1671 sdevnum = keyword;
1672 sdevtype = operand;
1673
1674 if (sdevnum == NULL || sdevtype == NULL)
1675 {
1676 logmsg(_("HHCCF035S Error in %s line %d: "
1677 "Missing device number or device type\n"),
1678 fname, inc_stmtnum[inc_level]);
1679 delayed_exit(1);
1680 }
1681 /* Parse devnum */
1682 rc=parse_and_attach_devices(sdevnum,sdevtype,addargc,addargv);
1683
1684 if(rc==-2)
1685 {
1686 logmsg(_("HHCCF036S Error in %s line %d: "
1687 "%s is not a valid device number(s) specification\n"),
1688 fname, inc_stmtnum[inc_level], sdevnum);
1689 delayed_exit(1);
1690 }
1691
1692 /* Read next device record from the configuration file */
1693 #if defined( OPTION_ENHANCED_CONFIG_INCLUDE )
1694 while (1)
1695 {
1696 while (inc_level >= 0 && read_config (fname, inc_fp[inc_level]) )
1697 {
1698 fclose (inc_fp[inc_level--]);
1699 }
1700
1701 if (inc_level < 0 || strcasecmp (keyword, "include") != 0)
1702 break;
1703
1704 if (++inc_level >= MAX_INC_LEVEL)
1705 {
1706 logmsg(_( "HHCCF082S Error in %s line %d: "
1707 "Maximum nesting level (%d) reached\n"),
1708 fname, inc_stmtnum[inc_level-1], MAX_INC_LEVEL);
1709 delayed_exit(1);
1710 }
1711
1712 logmsg( _("HHCCF083I %s Including %s at %d .\n"),
1713 fname, operand, inc_stmtnum[inc_level-1]);
1714 hostpath(pathname, operand, sizeof(pathname));
1715 inc_fp[inc_level] = fopen (pathname, "r");
1716 if (inc_fp[inc_level] == NULL)
1717 {
1718 inc_level--;
1719 if ( inc_ignore_errors == 1 )
1720 {
1721 logmsg(_("HHCCF084W %s Open error ignored file %s: %s\n"),
1722 fname, operand, strerror(errno));
1723 continue ;
1724 }
1725 else
1726 {
1727 logmsg(_("HHCCF085E %s Open error file %s: %s\n"),
1728 fname, operand, strerror(errno));
1729 delayed_exit(1);
1730 }
1731 }
1732 inc_stmtnum[inc_level] = 0;
1733 continue;
1734 }
1735
1736 if (inc_level < 0)
1737 #else // !defined( OPTION_ENHANCED_CONFIG_INCLUDE )
1738 if (read_config (fname, inc_fp[inc_level]))
1739 #endif // defined( OPTION_ENHANCED_CONFIG_INCLUDE )
1740 break;
1741
1742 } /* end while(1) */
1743
1744 #if !defined( OPTION_ENHANCED_CONFIG_INCLUDE )
1745 /* close configuration file */
1746 rc = fclose(inc_fp[inc_level]);
1747 #endif // !defined( OPTION_ENHANCED_CONFIG_INCLUDE )
1748
1749 /* Now configure storage. We do this after processing the device
1750 * statements so the fork()ed hercifc process won't require as much
1751 * virtual storage. We will need to update all the devices too.
1752 */
1753 config_storage(mainsize, xpndsize);
1754 for (dev = sysblk.firstdev; dev; dev = dev->nextdev)
1755 {
1756 dev->mainstor = sysblk.mainstor;
1757 dev->storkeys = sysblk.storkeys;
1758 dev->mainlim = sysblk.mainsize - 1;
1759 }
1760
1761 #if defined(_FEATURE_REGION_RELOCATE)
1762 /* Initialize base zone storage view (SIE compat) */
1763 for(i = 0; i < FEATURE_SIE_MAXZONES; i++)
1764 {
1765 sysblk.zpb[i].mso = 0;
1766 sysblk.zpb[i].msl = (sysblk.mainsize - 1) >> 20;
1767 if(sysblk.xpndsize)
1768 {
1769 sysblk.zpb[i].eso = 0;
1770 sysblk.zpb[i].esl = ((size_t)sysblk.xpndsize * XSTORE_PAGESIZE - 1) >> 20;
1771 }
1772 else
1773 {
1774 sysblk.zpb[i].eso = -1;
1775 sysblk.zpb[i].esl = -1;
1776 }
1777 }
1778 #endif
1779
1780 /* Initialize dummy regs.
1781 * Dummy regs are used by the panel or gui when the target cpu
1782 * (sysblk.pcpu) is not configured (ie cpu_thread not started).
1783 */
1784 sysblk.dummyregs.mainstor = sysblk.mainstor;
1785 sysblk.dummyregs.psa = (PSA*)sysblk.mainstor;
1786 sysblk.dummyregs.storkeys = sysblk.storkeys;
1787 sysblk.dummyregs.mainlim = sysblk.mainsize - 1;
1788 sysblk.dummyregs.dummy = 1;
1789 initial_cpu_reset (&sysblk.dummyregs);
1790 sysblk.dummyregs.arch_mode = sysblk.arch_mode;
1791 sysblk.dummyregs.hostregs = &sysblk.dummyregs;
1792
1793 #ifdef OPTION_SELECT_KLUDGE
1794 /* Release the dummy file descriptors */
1795 for (i = 0; i < OPTION_SELECT_KLUDGE; i++)
1796 close(dummyfd[i]);
1797 #endif
1798
1799 /* Set default maximum number of CPUs */
1800 #ifdef _FEATURE_CPU_RECONFIG
1801 sysblk.maxcpu = sysblk.arch_mode == ARCH_370 ? numcpu : MAX_CPU_ENGINES;
1802 #else
1803 sysblk.maxcpu = numcpu;
1804 #endif /*_FEATURE_CPU_RECONFIG*/
1805
1806 /* Set maximum number of CPUs to specified value */
1807 if (maxcpu > 0) {
1808 sysblk.maxcpu = maxcpu;
1809 }
1810
1811 /* Check that numcpu does not exceed maxcpu */
1812 if (sysblk.numcpu > sysblk.maxcpu) {
1813 logmsg(_("HHCCF086S Error in %s: NUMCPU %d must not exceed MAXCPU %d\n"),
1814 fname, sysblk.numcpu, sysblk.maxcpu);
1815 delayed_exit(1);
1816 }
1817
1818 /* Start the CPUs */
1819 OBTAIN_INTLOCK(NULL);
1820 for(i = 0; i < numcpu; i++)
1821 configure_cpu(i);
1822 RELEASE_INTLOCK(NULL);
1823
1824 } /* end function build_config */
1825
1826 #endif /*!defined(_GEN_ARCH)*/
1827