AUTOMATIC BOOTSTRAP FOR THE VAX
by Alex Wong
Singapore Computer Systems
VAX PROFESSIONAL, JUNE 1987
There are many occasions when I wish the SHUTDOWN option "When will the
system be rebooted" would do its job truthfully by booting the VAX up at
the time I innocently entered. SHUTDOWN will even tell everyone on the
system that it will be "back up 12-MAY-1986 8:00" and on that day, if
you are late, you and your future generations will be branded as thieves
and liars. There is no VMS facility to automatically boot the system up
at a specific date and time and this can be quite useful.
Our VAX 11/730 is brought down every evening and weekend to avoid power
failure problems and since we do not need to operate non-stop, a UPS is not
justified. This means that every morning, someone has to turn on the system
and wait for the date and time prompt before making the first coffee of the
day. Even if you don't need coffee, the TU58 taking its own sweet time to
load microcode can make you take valium instead. With a self-boot facility,
you can solve the inconvenience of the daily startup chores and have a
peaceful night's sleep as well.
The idea of an automatic startup is to accept the reboot time during SHUTDOWN,
convert it to an appropriate format and write this into a specific memory
location. The last program that SHUTDOWN invokes is OPCCRASH which does some
housekeeping work before bugchecking the processor. OPCCRASH can be patched
to read the reboot time from memory, compare it with the VAX internal clock
and loop until both are equal. The processor can then be rebooted by writing
F02 (hex) to the console transmit data buffer register (PR$_TXDB).
The VAX has a time-of-day clock which is accessible through a 32-bit internal
register PR$_TODR and is constantly updated by hardware every 10 milliseconds.
Battery backup for the clock is not a standard feature on the 11/730, hence
the need to enter the date and time at startup. The base time for the time-
of-day clock is 00:00:00.00 hours on January first of the current year.
Basically, this means PR$_TODR contains the number of 10-ms intervals that
have elapsed since 1-JAN-YYYY 00:00:00. This figure is biased by 10000000 (hex)
so that smaller values would indicate loss of power or register overflow,
requiring the operator to reset the time.
System time, however, is defined by a 64-bit value measuring the number of
100-nanosecond intervals since 00:00 hours November 17 1858, the time base
for the Smithsonian Institution astronomical calendar. The timer and time
conversion system services such as BINTIM or ASCTIM accept system time in
the dd-mmm-yyy hh:mm:ss format and produce a quadword result. You can see
from this that the system time must be converted to a 32-bit TODR format for
time comparison.
The VMS system management procedure SHUTDOWN.COM brings down the operating
system in an orderly manner so that the processor can be powered off. As a
friendly gesture, it will prompt you for "When will the system be rebooted"
but do nothing apart from promising the world that it will be "back up later".
The answer to the prompt is stored in an imaginatively-named symbol called
ANS which is accessible by a program called AUTOBOOT. This program checks
ANS for either a null (produced by a carriage return response) or a valid
system time. If response is invalid, a local symbol OK is set to "0" which
causes SHUTDOWN to reprompt for reboot time. SHUTDOWN has been modified to
include this check and the changes are shown below.
ORIGINAL:
$a10: read/end_of_file=a10/prompt="''p3'" sys$command ans
$if ans .eqs. "" then ans = p4
CHANGED TO:
$a10: read/end_of_file=a10/prompt="''p3'" sys$command ans
$ IF F$LOCATE("system be rebooted",P3) .EQ. F$LENGTH(P3) THEN GOTO CONTIN
$ RUN SYS$SYSTEM:AUTOBOOT
$ IF .NOT. OK THEN GOTO A10
$ CONTIN:
$if ans .eqs. "" then ans = p4
The F$LOCATE(...) test is necessary because SHUTDOWN works in a recursive
manner. For each shutdown option, SHUTDOWN will invoke itself with several
parameters, one of which is the prompt to be displayed. Since the above
portion of DCL code is common to all options, the test ensures that the
AUTOBOOT program will be activated only in response to the prompt for reboot
time.
AUTOBOOT converts a valid system time from its character form in ANS to a
quadword value by calling the BINTIM system service. To obtain the reboot
time in 32-bit TODR form, the system time for 1-JAN-YYYY 00:00:00 is
subtracted from it and divided by 100000, giving the number of 10-ms intervals
since the start of year. This figure is written into memory location
SYS$GQ_VERSION which holds the VMS version number "V4.3". On my system, it
is at 80002BF4 and can be verified by checking SYS.MAP or use ANALYZE/SYSTEM
and invoke the command SHOW SYMBOL SYS$GQ_VERSION. You can, of course, use
any other "safe" locations if you like. For a null response, a zero longword
is written to memory. Incidentally, SHUTDOWN requires CMKRNL privilege to run
so there is no problem for AUTOBOOT to zap protected memory.
OPCCRASH executes in kernel mode to perform tasks such as flushing out the
modified page cache before bugchecking the processor. The image can be patched
to include code to extract the reboot time and do time comparisons at the point
just before the bugcheck code. To determine the patch address, analyze the
image OPCCRASH.EXE in SYS$SYSTEM to get the first transfer address.
$ ANALYZE/IMAGE SYS$SYSTEM:OPCCRASH
:
Image Activation Information
first transfer address: %X'00000292'
second transfer address: %X'00000000'
third transfer address: %X'00000000'
:
Add 2 to it (for the entry mask) and use PATCH to examine the instructions
until you encounter the location of instruction MTPR B^36E,#12 (366 in my
case).
$ PATCH
PATCH> E/I 294
:
PATCH> E/I
:
This instruction raises the IPL to lock out all interrupts before the bugcheck.
To be safe, confirm this by reading the VMS microfiche on OPCCRASH. Below is
a patch procedure OPPATCH.COM that I've used on my system to insert the extra
code. The patch procedure is invoked by the DCL command "$ PATCH @OPPATCH".
OPCCRASH.EXE
INSE/I 366='MTPR B^0000036E,#12'
'MOVL @#^X80002BF4,R9'
'TSTL R9'
'BEQL FIN'
'LOOP: MFPR #^X1B,R8'
'CMPL R8,R9'
'BLSSU LOOP'
'MTPR #^XF02,#^X23'
'FIN: NOP'
EXIT
UPDATE
The startup time is placed in R9 and tested for zero. If non-zero, the code
loops around comparing R8 (PR$_TODR) with the R9 until both are equal. The
processor is then rebooted by setting PR$_TXDB to ^XF02. If a zero is
extracted, code returns and OPCCRASH will bugcheck the processor as per
normal. The TODR(1B) and TXDB(23) internal registers are described by the
VAX Hardware Handbook and the Architecture Handbook.
Copy AUTOBOOT into SYS$SYSTEM and make sure you have duplicates of SHUTDOWN
and OPCCRASH before patching them. Below is a system shutdown with reboot at
8:00 am the next day (10-MAY-1986).
$ @SYS$SYSTEM:SHUTDOWN
SHUTDOWN -- Perform an Orderly System Shutdown
How many minutes until final shutdown [0]:
Reason for shutdown [Standalone]:
Do you want to spin down the disk volume [NO]? YES
Do you want to invoke the site-specific shutdown procedure [YES]?
Should an automatic system reboot be performed [NO]?
When will the system be rebooted [later]: 10-MAY-1986 8:00
:
Apart from the time, the only other valid entry is a carriage return. After
performing the shutdown functions, the CPU will monitor TODR until wakeup
time. The VMS 4.2 Release Notes states that the TODR register may not be
common to all VAX processors and recommends the use of a TIMEDWAIT macro
in LIB.MLB, so check this out. On my 11/730, there were no problems in
accessing TODR directly. Remember to put back the original SHUTDOWN and
OPCCRASH before doing any VMS update as the update may patch them.
.TITLE AUTOBOOT
; *******************************************************************
; AUTOBOOT: SHUTDOWN.COM PROMPTS FOR THE REBOOT TIME WHICH IS PLACED
; IN LOCAL SYMBOL "ANS". AUTOBOOT CHECKS ANS FOR NULL [later] OR A
; VALID SYSTEM TIME. AN INVALID RESPONSE WILL SET LOCAL SYMBOL "OK"
; TO ERROR (0) WHICH CAUSES SHUTDOWN TO REPROMPT FOR TIME. IF NULL,
; ZERO IS WRITTEN INTO LOCATION SYS$GQ_VERSION. IF VALID SYSTEM TIME,
; CONVERT IT TO MILLISEC BEFORE WRITING TO MEMORY.
;
; AUTHOR: ALEX WONG, SYSTEMS MANAGER CPU : 730, VMS 4.3
; SINGAPORE COMPUTER SYSTEMS
; GEN : MACRO AUTOBOOT, LINK AUTOBOOT DATE: 8-MAY-1986
; *******************************************************************
$LIBCLIDEF ; CLI DEFS
VERSION=^X80002BF4 ; LOC SYS$GQ_VERSION
;
LOCSYM: .BLKL 1 ; DCL SYMBOL TABLE
STIM: .BLKQ 1 ; DAY1 IN NANOSEC
ETIM: .BLKQ 1 ; REBOOT TIME (NS)
PARM: .LONG 1 ; CMKRNL ARG LIST
.ADDRESS TIMEUP
TIMEUP: .BLKL 1 ; REBOOT TIME (MS)
GPDESC: .LONG 50 ; COMMON STRING DESC
.ADDRESS BUF
BUF: .BLKB 50
UPDESC: .LONG 50 ; UPCASE STRING DESC
.ADDRESS UPBUF
UPBUF: .BLKB 50
ERSTAT: .LONG 1 ; ERROR STATUS DESC
.ADDRESS STAT
STAT: .ASCII /0/ ; INIT TO ERROR
DAY1: .LONG 23 ; START OF CURR YEAR
.ADDRESS ATIME
ATIME: .ASCII /01-JAN-YYYY 00:00:00.00/
ANS: .ASCID /ANS/ ; DCL SYMB ANS
OK: .ASCID /OK/ ; DCL SYMB OK
;
.ENTRY AUTOBOOT,^M<>
;
CLRL TIMEUP ; INIT TO ZERO
MOVL #LIB$K_CLI_LOCAL_SYM,LOCSYM ; LOC SYMB TABLE
$GETTIM_S TIMADR=STIM ; CURR DATE+TIME (NS)
$ASCTIM_S TIMBUF=GPDESC,TIMADR=STIM ; CONV TO ASCII
MOVL BUF+7,ATIME+7 ; EXTRACT CURR YEAR
$BINTIM_S TIMBUF=DAY1,TIMADR=STIM ; DAY1 IN NANOSEC
PUSHAW GPDESC ; SET UP CALL
PUSHAQ GPDESC
PUSHAQ ANS
CALLS #3,G^LIB$GET_SYMBOL ; READ ANS
BLBC R0,FIN
TSTW GPDESC ; IS IT NULL ?
BEQL DEFAULT ; YES, SET ZERO
MOVW GPDESC,UPDESC ; NO, SET UP CALL
PUSHAQ GPDESC
PUSHAQ UPDESC
CALLS #2,G^STR$UPCASE ; CONV TO UPCASE
$BINTIM_S TIMBUF=UPDESC,TIMADR=ETIM ; NANOSEC SYS TIME
BLBC R0,FIN
MOVQ STIM,R9 ; SET UP 64-BIT SUB
MOVQ ETIM,R7
SUBL2 R9,R7 ; SUB LOW 4 BYTES
SBWC R10,R8 ; SUB HIGH 4 BYTES
EDIV #100000,R7,R7,R8 ; CONV TO MILLSEC
ADDL3 #^X10000000,R7,TIMEUP ; ADD CLOCK BIAS
DEFAULT:
$CMKRNL_S ROUTIN=PUTIME,ARGLST=PARM ; ZAP PRIV MEMORY
MOVB #^A/1/,STAT ; SET SUCCESS
FIN:
PUSHAL LOCSYM ; LOC SYMB TABLE
PUSHAQ ERSTAT ; STATUS
PUSHAQ OK ; DCL SYMBOL OK
CALLS #3,G^LIB$SET_SYMBOL ; SET SYMBOL
RET
;
.ENTRY PUTIME,^M<>
MOVL @B^4(AP),@#VERSION ; ZAP LOCATION
MOVL #1,R0 ; SET SUCCESS
RET
.END AUTOBOOT