summaryrefslogtreecommitdiffstats
path: root/src/build
diff options
context:
space:
mode:
authorAndrew Geissler <andrewg@us.ibm.com>2011-07-07 17:11:24 -0500
committerMIKE J. JONES <mjjones@us.ibm.com>2011-07-14 10:18:09 -0500
commitb9558dcb65612b60a20719ea489dadda4776e1e4 (patch)
treed0f074f95d473fdaa5ebc29dfae27b21770a9f32 /src/build
parent038a9a46895333b86da8ca83c8effd29ff3e76e9 (diff)
downloadtalos-hostboot-b9558dcb65612b60a20719ea489dadda4776e1e4.tar.gz
talos-hostboot-b9558dcb65612b60a20719ea489dadda4776e1e4.zip
HW Procedure Compile Support
- New .tcl scripts to be used to do the compiling - New hw procedure function for hw procedure writers to overload for their testing Change-Id: I90af3f4d7aea07f63ec7f52daf224070c944ccee Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/190 Tested-by: Jenkins Server Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com> Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Diffstat (limited to 'src/build')
-rwxr-xr-xsrc/build/hwpf/prcd_compile.tcl467
-rwxr-xr-xsrc/build/hwpf/prcd_compile_test99
-rwxr-xr-xsrc/build/hwpf/prcd_server.tcl543
3 files changed, 1109 insertions, 0 deletions
diff --git a/src/build/hwpf/prcd_compile.tcl b/src/build/hwpf/prcd_compile.tcl
new file mode 100755
index 000000000..1e8d7a3bd
--- /dev/null
+++ b/src/build/hwpf/prcd_compile.tcl
@@ -0,0 +1,467 @@
+#!/bin/sh
+# The next line is executed by /bin/sh, but not tcl \
+exec tclsh "$0" "$@"
+
+# Name: prcd_compile.tcl - Compile a hardware procedure remotely
+#
+# Based on if_make.tcl by Doug Gilbert
+
+
+#---------------------------------------------------------
+# TBD - No Support Yet
+#---------------------------------------------------------
+proc getPassword { prompt } {
+ exec stty -echo echonl <@stdin
+
+ # Print the prompt
+ puts -nonewline stdout $prompt
+ flush stdout
+
+ # Read that password! :^)
+ gets stdin password
+
+ # Reset the terminal
+ exec stty echo -echonl <@stdin
+
+ return $password
+}
+
+#---------------------------------------------------------
+# TBD - No Support Yet
+#---------------------------------------------------------
+proc mysend { chan val } {
+ #puts "Sending>>>$val<<<<"
+ puts $chan $val
+}
+
+#---------------------------------------------------------
+# TBD - No Support Yet
+#---------------------------------------------------------
+proc telnetResult { telnet } {
+ global telnet_out
+ #puts "Reading $telnet"
+
+ if { [eof $telnet] || [catch { set dat [read $telnet]}] } {
+ #puts "GOT>>>AT END<<<"
+ set telnet_out {AT END}
+ if { [catch {close $telnet} res] } {
+ puts "Error: $res"
+ }
+ } else {
+ #puts "GOT>>>$dat<<<<"
+ append telnet_out $dat
+ }
+}
+
+
+# Wait for p to showup in telnet_out
+# return 1 if timout else returns 0
+proc wait_for { p } {
+ global telnet_out
+ while { 1 } {
+ vwait telnet_out
+ if { [string last $p $telnet_out] > -1 } { return 0 }
+ if { [string compare {timeout} $telnet_out] == 0 } { return 1 }
+ }
+}
+
+
+#---------------------------------------------------------
+# TBD - No Support Yet
+#---------------------------------------------------------
+proc get_fsp_info { fspip fsppassword} {
+ global telnet_out
+ set telnet_out {}
+
+ # Open telnet session
+ if {[catch {set telnet [open "|telnet $fspip" r+]} res]} {
+ puts "Could not telnet to $fspip"
+ return {}
+ }
+ fconfigure $telnet -buffering none -blocking 0
+
+ # all output from telnet session captured by telnetResult procedure
+ # put into telnet_out variable
+ fileevent $telnet readable [list telnetResult $telnet]
+
+ # Set a timeout of 20 seconds
+ set timeoutid [after 20000 {
+ set telnet_out {timeout}
+ close $telnet
+ } ]
+
+ if {[wait_for {login:}]} { return {} }
+
+ mysend $telnet {root}
+ if { [wait_for {Password:}]} { return {} }
+
+ mysend $telnet "$fsppassword"
+ while { 1 } {
+ vwait telnet_out
+ if { [string last {$} $telnet_out] > 0 } { break }
+ if { [string last {Login incorrect} $telnet_out] > 0 } {
+ puts {Login incorrect}
+ close $telnet
+ return {}
+ }
+ if { [string compare $telnet_out {timeout}] == 0 } { return {} }
+ }
+ set telnet_out {}
+
+ mysend $telnet {registry -r fstp/DriverName}
+ if { [wait_for {$}]} { return {} }
+
+ regexp {registry -r fstp/DriverName.+fips[0-9]+/(.+)\n.+} $telnet_out a driver
+ set telnet_out {}
+
+ mysend $telnet {cat /proc/mounts | grep /nfs}
+ if { [wait_for {$}]} { return {} }
+
+ regexp {.+\n(.+?):(.+?) +/nfs nfs .+} $telnet_out a companion_ip nfs_dir
+
+ mysend $telnet {exit}
+ if { [wait_for {AT END}]} { return {} }
+
+ # Cancel the timout
+ after cancel $timeoutid
+
+ return "$driver:$companion_ip:$nfs_dir"
+}
+
+#---------------------------------------------------------
+# TBD - No Support Yet
+#---------------------------------------------------------
+proc start_patch_server_on_fsp { fspip fsppassword } {
+ global telnet_out
+ global telnet
+ global fsp_server_port
+ set telnet_out {}
+ # Open telnet session
+ if {[catch {set telnet [open "|telnet $fspip" r+]} res]} {
+ puts "Could not telnet to $fspip"
+ return 0
+ }
+ fconfigure $telnet -buffering none -blocking 0
+
+ # all output from telnet session captured by telnetResult procedure
+ # put into telnet_out variable
+ fileevent $telnet readable [list telnetResult $telnet]
+
+ # Set a timeout of 20 seconds
+ set timeoutid [after 20000 {
+ set telnet_out {timeout}
+ close $telnet
+ } ]
+
+ if { [wait_for {login:}]} { return 0 }
+
+ mysend $telnet {root}
+ if { [wait_for {Password:}]} { return 0 }
+
+ mysend $telnet "$fsppassword"
+ while { 1 } {
+ vwait telnet_out
+ if { [string last {$} $telnet_out] > 0 } { break }
+ if { [string last {Login incorrect} $telnet_out] > 0 } {
+ puts {Login incorrect}
+ close $telnet
+ return 0
+ }
+ if { [string compare $telnet_out {timeout}] == 0 } { return 0 }
+ }
+ set telnet_out {}
+
+ mysend $telnet {mkdir -p /nfs/data/engd}
+ if { [wait_for {$}]} { return 0 }
+
+ set telnet_out {}
+ mysend $telnet {mkdir -p /nfs/data/rtbl}
+ if { [wait_for {$}]} { return 0 }
+
+ set telnet_out {}
+ mysend $telnet {killall cini_patcher}
+ if { [wait_for {$}]} { return 0 }
+
+ set telnet_out {}
+ mysend $telnet "cini_patcher &"
+ if { [wait_for {Server ready}]} { return 0 }
+
+ puts $telnet_out
+ set telnet_out {}
+ mysend $telnet {}
+ if { [wait_for {$}]} { return 0 }
+ set telnet_out {}
+
+ mysend $telnet {exit}
+ if { [wait_for {AT END}]} { return 0 }
+
+ # Cancel the timout
+ after cancel $timeoutid
+ return 1
+}
+
+# ------------------------
+# MAIN
+# ------------------------
+set userid $::env(USER)
+set home $::env(HOME)
+set domain [exec hostname -d]
+set version "1.0"
+
+set files [list]
+set cmds [list]
+set servers [list gfw160.austin.ibm.com]
+
+#-----------------------------------------------------------------------------------------
+# Parse ARGs
+#-----------------------------------------------------------------------------------------
+
+set state flag
+foreach arg $argv {
+ switch -- $state {
+ flag {
+ switch -glob -- $arg {
+ -quit { set cmds [list quit] }
+ -d { set state driverflag }
+# NOT SUPPORTED -s { set state fspflag }
+# NOT SUPPORTED -p { set state portflag }
+ -v { set verbose 1 }
+ -o { set state outputflag }
+ -*h* { puts {prcd_compile.tcl [--help] [-d <drivername>] [-o <ouput dir> ] fapiTestHwp.C fapiTestHwp.H }
+ puts {}
+ puts {Note that currently this tool only supports the 2 files listed above as input }
+ puts {}
+ puts {example: > prcd_compile.tcl -d b0621a_2001_Sprint2 -o ./output/ fapiTestHwp.C fapiTestHwp.C }
+ puts {}
+ puts {On success, 5 files (hbicore.bin and hbicore_test.bin, hbicore.syms }
+ puts { hbicore_test.syms and hbotStringFile) will be placed in the output dir. }
+ puts {}
+ puts {The -d and -o parameters are optional. Default for -d is the master level of code }
+ puts { and default for -o is the current working directory }
+ puts {}
+ puts "Version: $version"
+ puts {}
+ exit
+ }
+ *fapiTestHwp\.* { lappend files $arg }
+ default { puts "Unsupported File or Argument: $arg "
+ exit
+ }
+ }
+ }
+ driverflag {
+ #lappend cmds ":DRIVER $arg"
+ set driver $arg
+ set state flag
+ }
+ fspflag {
+ foreach {fspip fsp_port} [split $arg :] break
+ set state flag
+ }
+ portflag {
+ # Set the port the fsp patch server is listening on.
+ # This is not the telnet port used in simics.
+ # defaults to 7779
+ set fsp_server_port $arg
+ set state flag
+ }
+ outputflag {
+ set output_dir $arg
+ set state flag
+ }
+ }
+}
+
+if {![info exists fsp_server_port]} { set fsp_server_port 7779 }
+
+#-----------------------------------------------------------------------------------------
+# Get fspip if not specified
+#-----------------------------------------------------------------------------------------
+# TBD - NOT SUPPORTED
+if { ![info exists fspip] && ![info exists driver] } {
+# puts -nonewline {Enter telnet address of fsp: }
+# flush stdout
+# fconfigure stdin -blocking 1
+# foreach {fspip fsp_port} [split [gets stdin] { :}] break
+# fconfigure stdin -blockin 0
+# puts { No driver name input! }
+# exit
+}
+
+if { [info exists fspip] } {
+ set fsppassword [getPassword "root password for fsp $fspip:"]
+ set res [get_fsp_info "$fspip $fsp_port" $fsppassword]
+ if { $res != "" } { foreach {driver companion_ip nfs_dir} [split $res {:}] break }
+
+ if { [info exists driver]} {
+ puts "FSP Driver: $driver"
+ } else {
+ puts {FSP login failed!}
+ exit -1
+ }
+
+ if { $companion_ip != {} } {
+ puts "Companion: $companion_ip"
+ } else { unset companion_ip }
+
+
+ if { $nfs_dir != {} } {
+ puts "nfs_dir: $nfs_dir"
+ }
+}
+
+
+if { ![info exists driver] } {
+ # default to the master for the driver
+ set driver "master"
+}
+
+if { ![info exists output_dir] } {
+ # default to PWD for output
+ set output_dir "./"
+}
+
+# Make the output directory
+eval {exec} "mkdir -p $output_dir"
+
+lappend cmds ":INFO userid $userid version $version"
+lappend cmds ":DRIVER $driver"
+
+
+##########################################################
+# Generate command to send each input file
+##########################################################
+foreach filen $files {
+
+ set file_size [file size $filen]
+ set filesource($filen) $filen
+ lappend cmds ":HWP_FILE $filen $file_size"
+}
+
+##########################################################
+# Generate compile, retrieve, and complete directives
+##########################################################
+lappend cmds ":HWP_COMPILE"
+lappend cmds ":HWP_RETRIEVE"
+lappend cmds ":HWP_DONE"
+
+
+set xfer_file_list {}
+
+if {[llength $cmds] > 0 } {
+ set result ""
+ ##########################################################
+ # Find a server to run on
+ ##########################################################
+ foreach server $servers {
+ set result ""
+ puts "Trying $server ..."
+ if {[catch {set sockid [socket $server 7779] } res ] } {
+ set result " $res"
+ puts $result
+ continue
+ } else { break }
+ }
+ ##########################################################
+ # Now send all of the commands we generated sequentially
+ # to the server, waiting for a :DONE between each one.
+ ##########################################################
+ # Note that currently we only support fapiTestHwp.C and .H as input
+ if {$result == ""} {
+ puts "Connected to $server - Starting Compile"
+ foreach cmd $cmds {
+ if {[info exists verbose]} {puts "Send to hw procedure compiler: $cmd"}
+ if {[string compare $cmd {quit}] == 0 } {
+ puts $sockid {quit}
+ break
+ } elseif {[regexp {^:HWP_FILE +(.+) +(.+)} $cmd a hwpfilename filesize]} {
+ puts $sockid $cmd
+ set hwpfile [open $filesource($hwpfilename) r]
+ fconfigure $sockid -translation binary
+ fconfigure $hwpfile -translation binary
+ fcopy $hwpfile $sockid -size $filesize
+ close $hwpfile
+ fconfigure $sockid -translation auto
+ } else {
+ puts $sockid $cmd
+ }
+ flush $sockid
+ set line ""
+ while {[string compare $line {:DONE}] != 0} {
+ if {[eof $sockid]} { break }
+ gets $sockid line
+ if {[info exists verbose]} {puts "Received from hw procedure compiler: $line"}
+ if {[regexp {^:OBJ_FILE +(.+) +(.+)\n*} $line a b c] } {
+ fconfigure $sockid -translation binary
+ lappend xfer_file_list $b
+ set fp [open "$output_dir/$b" w]
+ fconfigure $fp -translation binary
+ fcopy $sockid $fp -size $c
+ close $fp
+ fconfigure $sockid -translation auto
+ } elseif {[regexp {.*error:.*} $line ->] } {
+ puts stderr "Error in compile - $line"
+ set error 1
+ }
+ }
+ if {[eof $sockid]} { break }
+ }
+ close $sockid
+ if {[info exists error]} {
+ puts "Compile Failed! See above errors"
+ exit -1
+ } else {
+ puts "Compile Complete"
+ }
+ } else {
+ # The server must be down
+ puts stderr "All The servers seems to be down"
+ exit -1
+ }
+}
+
+
+# telnet back to fsp and start patch server
+# TBD - Not implemented in this sprint
+if {[info exists companion_ip]} {
+ if {$companion_ip != {}} {
+ set res [start_patch_server_on_fsp "$fspip $fsp_port" $fsppassword]
+ if { $res } {
+ #puts "fspip $fspip"
+ if {[catch { set sockid [socket $fspip $fsp_server_port] } res ] } {
+ puts $res
+ exit -1
+ }
+ # call fspipResult when sockid becomes readable
+ fileevent $sockid readable [list fspipResult $sockid]
+ #fconfigure $sockid -buffering line
+
+ # send files
+ foreach f $xfer_file_list {
+ #puts "file: $f"
+ if {[string match {*.if} $f] || [string match {*.dat} $f] } {
+ set dest_dir {/nfs/data/engd}
+ } else {
+ set dest_dir {/nfs/data/rtbl}
+ }
+ set filesize [file size $f]
+ puts $sockid ":PUT $dest_dir/[file tail $f] $filesize"
+ puts ":FSPPUT $fspip:$dest_dir/[file tail $f] $filesize"
+ set hwpfile [open $f r]
+ fconfigure $sockid -translation binary
+ fconfigure $hwpfile -translation binary
+ #puts "fcopy $hwpfile $sockid -size $filesize"
+ fcopy $hwpfile $sockid -size $filesize
+ close $hwpfile
+ fconfigure $sockid -translation auto
+ }
+ close $sockid
+ }
+ }
+}
+
+# should only see data comming back if there were errors.
+proc fspipResult { sockid } {
+ gets $sockid line
+ puts $line
+}
diff --git a/src/build/hwpf/prcd_compile_test b/src/build/hwpf/prcd_compile_test
new file mode 100755
index 000000000..a1f4abed5
--- /dev/null
+++ b/src/build/hwpf/prcd_compile_test
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+#Note that this test case assumes 2 files present in the PWD (along with prcd_compile.tcl)
+# - fapiTestHwp.C and fapiTestHwp.H
+
+#BUILD="b0621a_2001_Sprint2"
+BUILD="master"
+
+###############################################################
+# Validate return code, exit on failure
+###############################################################
+function check_good_rc {
+
+ if [ $1 -eq 0 ]; then
+ echo SUCCESS
+ rm -f hbicore*
+ rm -f hbotStringFile
+ echo
+ else
+ echo FAIL; exit -1
+ fi
+}
+
+###############################################################
+# Validate return code is non-zero, exit on failure
+###############################################################
+function check_bad_rc {
+
+ if [ $1 -ne 0 ]; then
+ echo SUCCESS
+ echo
+ else
+ echo FAIL; exit -1
+ fi
+}
+
+###############################################################
+# Main
+###############################################################
+
+# Check if the needed files exist, if not try and copy them in
+if [ ! -f "./fapiTestHwp.H" ]; then
+ cp ../../include/usr/hwpf/hwp/fapiTestHwp.H ./
+ check_good_rc $?
+fi
+
+if [ ! -f "./fapiTestHwp.C" ]; then
+ cp ../../usr/hwpf/hwp/fapiTestHwp.C ./
+ check_good_rc $?
+fi
+
+echo
+
+echo "TEST - Good Path - Multi Process"
+./prcd_compile.tcl -d $BUILD ./fapiTestHwp.H ./fapiTestHwp.C &
+sleep 2
+./prcd_compile.tcl -d $BUILD ./fapiTestHwp.H ./fapiTestHwp.C &
+sleep 2
+./prcd_compile.tcl -d $BUILD ./fapiTestHwp.H ./fapiTestHwp.C &
+sleep 20
+
+echo
+echo "TEST - Good Path - 1 C File"
+./prcd_compile.tcl -d $BUILD ./fapiTestHwp.C
+check_good_rc $?
+
+echo
+echo "TEST - Good Path - 1 H File with -o Param"
+./prcd_compile.tcl -d $BUILD -o ./ ./fapiTestHwp.H
+check_good_rc $?
+
+echo
+echo "TEST - Good Path - 2 Files"
+./prcd_compile.tcl -d $BUILD ./fapiTestHwp.H ./fapiTestHwp.C
+check_good_rc $?
+
+echo
+echo "TEST - Good Path - Directory Path and Output Directory"
+cp fapiTestHwp.H /tmp/
+mkdir output
+./prcd_compile.tcl -d $BUILD -o ./output/ /tmp/fapiTestHwp.H fapiTestHwp.C
+check_good_rc $?
+rm -rf output
+rm /tmp/fapiTestHwp.H
+
+echo
+echo "TEST - Good Path - No Files"
+./prcd_compile.tcl -d $BUILD
+check_good_rc $?
+
+echo
+echo "TEST - Bad Path - Compile Failure"
+rm -f hbicore*;
+cp fapiTestHwp.H /tmp/
+echo COMPILE_FAIL >> /tmp/fapiTestHwp.H
+./prcd_compile.tcl -d $BUILD /tmp/fapiTestHwp.H fapiTestHwp.C
+check_bad_rc $?
+rm /tmp/fapiTestHwp.H
+
diff --git a/src/build/hwpf/prcd_server.tcl b/src/build/hwpf/prcd_server.tcl
new file mode 100755
index 000000000..2382872a1
--- /dev/null
+++ b/src/build/hwpf/prcd_server.tcl
@@ -0,0 +1,543 @@
+# the next line restarts using tclsh\
+exec tclsh "$0" "$@"
+
+
+# Name: prcd_server.tcl - Compile a hardware procedure provided by a client.
+#
+# Based on if_server.tcl by Doug Gilbert
+
+
+set version "1.0"
+
+############################################################################
+# Accept is called when a new client request comes in
+# An event is forked that calls AquireData whenever the socket becomes
+# readable the main thread continues to run looking for more client requests
+############################################################################
+
+proc Accept { sock addr port} {
+
+ global socklist
+ global log
+ puts "[clock format [clock seconds]]: Accept $sock from $addr port $port"
+ puts $log "$port: [clock format [clock seconds]]: Accept $sock from $addr port $port"
+ set socklist(addr,$sock) [list $addr $port]
+ fconfigure $sock -buffering line
+ fileevent $sock readable [list AquireData $sock]
+
+}
+
+
+############################################################################
+# AquireData is called whenever there is data avaiable from a client.
+# with line buffering on sock, this means when a line is
+# Processes commands and collect data from client
+############################################################################
+
+proc AquireData { sock } {
+
+ global socklist
+ global sandbox
+ global forever
+ global sb_dir
+ global sbname
+ global hwpfile
+ global git_sh
+ global backing
+ global log
+ global running
+ global driver
+
+
+ if { [eof $sock] || [catch {gets $sock line}] } {
+ puts "Client closed unexpectedly"
+ puts $log "$sock: Client closed unexpectedly"
+ CloseOut $sock
+ } else {
+ if { [string compare $line "quit"] == 0 } {
+ close $socklist(main)
+ puts $sock "hw procedure compiler server is terminating"
+ puts $log "$sock: hw procedure compiler server is terminating"
+ CloseOut $sock
+ set forever 0
+ } elseif {[regexp {:DRIVER +(.+)} $line a b] } {
+
+ ################################################################
+ # Make a unique sandbox backed to the driver specified
+ # Do a workon to the sandbox.
+ ################################################################
+
+ set driver $b
+ set release ""
+ puts $log "$sock: Input driver $driver"
+ flush $log
+
+ ################################################################
+ # create git repository
+ ################################################################
+
+ set sbname($sock) "sb[string range [clock seconds] 4 end]"
+ puts $sock "$sbname($sock)"
+ puts $log "$sock: $sbname($sock)"
+
+ # Make sure sandbox dir exists
+ if {[file exists $sb_dir]} {
+ file mkdir "$sb_dir/$sbname($sock)"
+
+ set git_sh($sock) [open "|bash" r+]
+ fconfigure $git_sh($sock) -buffering none
+ fileevent $git_sh($sock) readable [list IfResult $git_sh($sock) $sock $sbname($sock)]
+
+ ExtractSandbox $sock $git_sh($sock)
+
+ } else {
+ puts $sock "Could not extract code\n"
+ puts $log "$sock: Could not extract code\n)"
+ CloseOut $sock
+ }
+ } elseif {[regexp {:HWP_FILE +(.+) +(.+)} $line a b c] } {
+
+ ################################################################
+ # Open the hw procedure file in the hw procedure directory
+ ################################################################
+
+ puts $log "$sock: Input File $b $c"
+ flush $log
+
+ if { ![info exists sbname($sock)] } {
+ puts $sock "No sandbox found"
+ puts $log "$sock: No sandbox found"
+ CloseOut $sock
+ return
+
+ }
+ ################################################################
+ # Create the path to the file in the git sandbox
+ # If it's a .C file it goes to src/usr/hwpf/hwp/ otherwise
+ # it's a .H and needs to go to src/include/usr/hwpf/hwp/
+ # Note that I can't get /* to work correctly in the regexp so I had to
+ # hard code in the fapi which should be ok, but annoying.
+ ################################################################
+
+ if {[regexp {.*/*(fapi.+\.C)} $b -> file] } {
+ set filen "$sb_dir/$sbname($sock)/src/usr/hwpf/hwp/$file"
+ } elseif {[regexp {.*/*(fapi.+\.H)} $b -> file] } {
+ set filen "$sb_dir/$sbname($sock)/src/include/usr/hwpf/hwp/$file"
+ } else {
+ puts $sock "Invalid Input File - $b"
+ puts $log "$sock: Invalid Input File - $b"
+ CloseOut $sock
+ return
+ }
+
+ # Open with create/overwrite option
+ if {[catch {set hwpfile($sock) [open "$filen" w+] } res ] } {
+ puts $sock "Server can't open $filen"
+ puts $log "$sock: Server can't open $filen"
+ CloseOut $sock
+ } else {
+ fconfigure $hwpfile($sock) -translation binary
+ fconfigure $sock -translation binary
+ fcopy $sock $hwpfile($sock) -size $c
+ close $hwpfile($sock)
+ fconfigure $sock -translation auto
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ flush $sock
+ }
+ } elseif {[string compare $line ":HWP_COMPILE"] == 0} {
+ set git_sh($sock) [open "|bash" r+]
+ fconfigure $git_sh($sock) -buffering none
+ fileevent $git_sh($sock) readable [list IfResult $git_sh($sock) $sock $sbname($sock)]
+ puts $git_sh($sock) "cd $sb_dir/$sbname($sock)"
+ SendSandbox $sock $git_sh($sock)
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ flush $sock
+ flush $log
+ } elseif {[string compare $line ":HWP_RETRIEVE"] == 0} {
+ SendObjFiles $sock "$sb_dir/$sbname($sock)/img"
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ flush $sock
+ } elseif {[string compare $line ":HWP_DONE"] == 0} {
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ CloseOut $sock
+ set line ""
+ } elseif {[regexp {:INFO +(.+)} $line a b] } {
+ puts $sock ":DONE"
+ puts $log "$sock: $b"
+ flush $sock
+ flush $log
+ } else {
+ # Unrecognized command
+ # if it's just blank line then skipt it - else report it
+ if {[string length $line] > 0 } {
+ puts "Unknown command:$line"
+ puts $sock "Unknown command: $line"
+ puts $log "$sock: Unknown command: $line"
+ }
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ flush $sock
+ }
+
+ }
+
+}
+
+##################################################################
+# Clean up and close the socket
+##################################################################
+proc CloseOut { sock } {
+ global socklist
+ global sandbox
+ global sbname
+ global sb_dir
+ global git_sh
+ global backing
+ global log
+
+ if {![eof $sock]} { flush $sock }
+
+ puts $log "$sock [clock format [clock seconds]]: Close $socklist(addr,$sock)- "
+ flush $log
+ close $sock
+ puts "[clock format [clock seconds]]: Close $socklist(addr,$sock)- "
+ unset socklist(addr,$sock)
+ if {[info exists git_sh($sock)] } {
+ # Comment out next line to avoid deleting the /tmp/hwp/ sandbox
+ # eval {exec} "rm -rf $sb_dir/$sbname($sock)"
+ unset git_sh($sock)
+ #unset sandbox($sbname($sock))
+ }
+
+ if {[info exists sbname($sock)]} { unset sbname($sock) }
+ if {[info exists backint($sock)]} { unset backing($sock) }
+
+}
+
+##################################################################
+# Sets up the sandbox with the required code from git
+##################################################################
+proc ExtractSandbox { sock git_sh} {
+ global sandbox
+ global running
+ global sbname
+ global sb_dir
+ global driver
+ global log
+
+ ############################################################
+ # Create GIT repository and extract input driver
+ # Open a separate pipe which does the extraction and
+ # compiling
+ ############################################################
+ puts $git_sh "cd $sb_dir/$sbname($sock)"
+ puts $git_sh {git init}
+ puts $git_sh {git remote add gerrit ssh://gfw160.austin.ibm.com:29418/hostboot}
+ puts $git_sh {unlog}
+ puts $git_sh {git fetch gerrit}
+
+ if {[string compare $driver "master"] == 0} {
+ puts $log "$sock: Using master branch"
+ puts $git_sh "git checkout -b master gerrit/master"
+ } else {
+ puts $log "$sock: Using $driver branch"
+ puts $git_sh "git checkout -b $sbname($sock) $driver"
+ }
+
+ ##################################################
+ # tell the workon shell to terminate
+ ##################################################
+ puts $git_sh {echo :DONE}
+ flush $git_sh
+
+ ############################################################
+ ## if the git_sh is not done by 180 sec, it probably crashed
+ ## keep a list of running sandboxes
+ ## hopefully processes timeout in the same order they were started
+ ## Kick off an event that waits 10 sec then executes
+ ############################################################
+
+ lappend running $sbname($sock)
+ set timoutid [after 10000 {
+ set sandbox([lindex $running 0]) crashed
+ lreplace $running 0 0
+ } ]
+
+
+ ############################################################
+ ## This thread now waits until an event changes sandbox($sbname)
+ ## either the simulator exits or times out
+ ############################################################
+
+ vwait sandbox($sbname($sock))
+
+ ############################################################
+ # If the git_sh workon crashed then close the workon shell
+ # else cancel the timout event
+ ############################################################
+ if { [string compare $sandbox($sbname($sock)) "crashed"] == 0 } {
+ if { [catch {close $git_sh} res]} {
+ puts $sock "Failed: $res\n"
+ puts $log "$sock: Failed: $res\n"
+ }
+ set sandbox($sbname($sock)) idle
+ } else {
+ after cancel $timoutid
+ }
+ flush $sock
+ flush $log
+
+ ## just a flag to indicate sandbox is being used
+ set sandbox($sbname($sock)) running
+ puts $sock ":DONE"
+ puts $log "$sock: DONE"
+ flush $sock
+}
+
+
+##################################################################
+# Sets up the sandbox for the ifcompiler & sends commands
+# sets up an event to collect the simulation results
+# closes and deletes the sandbox
+##################################################################
+proc SendSandbox { sock git_sh} {
+ global sandbox
+ global running
+ global sbname
+ global missing_spies
+ global log
+
+ # set missing_spies($sock) {}
+
+##################################################################
+# Start Compile
+##################################################################
+
+ puts $git_sh "source env.bash; make -j4"
+
+##################################################################
+# tell the workon shell to terminate
+##################################################################
+
+ puts $git_sh {echo :DONE}
+ flush $git_sh
+
+##################################################################
+## if the git_sh is not done by 180 sec, it probably crashed
+## keep a list of running sandboxes
+## hopefully processes timeout in the same order they were started
+## Kick off an event that waits 180 sec then executes
+##################################################################
+
+ lappend running $sbname($sock)
+ set timoutid [after 180000 {
+ set sandbox([lindex $running 0]) crashed
+ lreplace $running 0 0
+
+ } ]
+
+
+##################################################################
+## This thread now waits until an event changes sandbox($sbname)
+## either the simulator exits or timesout
+##################################################################
+
+ vwait sandbox($sbname($sock))
+
+##################################################################
+# If the git_sh workon crashed then close the workon shell else cancel the
+# timout event
+##################################################################
+
+ if { [string compare $sandbox($sbname($sock)) "crashed"] == 0 } {
+ if { [catch {close $git_sh} res]} {
+ puts $sock "Fail: $res\n"
+ puts $log "$sock: Fail: $res\n"
+ }
+ set sandbox($sbname($sock)) idle
+ } else {
+ after cancel $timoutid
+ }
+
+ flush $sock
+ flush $log
+}
+
+
+##################################################################
+# This is a list of regular expressions. Any line sent to stdout during
+# mk processing that matches one of these expressions will be sent to the
+# client. Note: Everything from stderr gets returned
+##################################################################
+
+set explist [list {ERROR:.*} {^IfScrub..E>.*} {^Parse Error.*} ]
+
+##################################################################
+## This event catches the output of the sandbox when the pipe become readable
+## and sends it back to the client.
+## The git_sh pipe is closed when the full result has been processed
+##################################################################
+
+proc IfResult { git_sh sock sbname_sock } {
+ global sandbox
+ global explist
+ global log
+
+ if { [eof $git_sh] || [catch {gets $git_sh line}] } {
+ puts $sock "compile unexpectedly terminated. sandbox $sbname_sock"
+ puts $log "$sock: compile unexpectedly terminated. sandbox $sbname_sock"
+
+ if { [catch {close $git_sh} res] } {
+ puts $sock "Error is $res\n"
+ puts $log "$sock: Error is $res\n"
+ }
+ set sandbox($sbname_sock) "idle"
+ } else {
+
+ # Uncomment to send back all compile output
+ #puts $sock "$sock $line"
+ #puts $log "$sock: $line"
+
+ if { [string compare $line ":DONE"] == 0 } {
+ if { [catch {close $git_sh} res]} {
+ #res has the stderr
+ # Need to weed out the junk
+ set rlines [split $res "\n"]
+ foreach rline $rlines {
+ # weed out the errors from mk
+ if {[regexp {.*error.*} $rline ->] } {
+ puts $sock "$rline - ERROR"
+ puts $log "$sock: $rline"
+ }
+ }
+ }
+
+ puts $sock "Exit Sandbox"
+ puts $log "$sock: Exit Sandbox"
+ set sandbox($sbname_sock) "idle"
+
+ } else {
+ foreach exp $explist {
+ if {[regexp $exp $line a]} {
+ puts $sock $line
+ puts $log "$sock: $line"
+ }
+ }
+ }
+ }
+}
+
+
+##################################################################
+# send the *.if and *.dat files from the compile back to the client
+##################################################################
+proc SendObjFiles { sock obj_dir } {
+
+ global log
+
+ set hbi_files {}
+
+ # Send the .bin files
+ if {[catch {set hbi_files [glob -dir $obj_dir *.bin]} res]} {
+ puts $sock "ERROR: No *.bin files found in $obj_dir"
+ puts $log "$sock: ERROR: No *.bin files found in $obj_dir"
+ } else {
+ SendFiles $sock $hbi_files
+ }
+
+ # Now send the .syms files
+ if {[catch {set hbi_files [glob -dir $obj_dir *.syms]} res]} {
+ puts $sock "ERROR: No *.syms files found in $obj_dir"
+ puts $log "$sock: ERROR: No *.syms files found in $obj_dir"
+ } else {
+ SendFiles $sock $hbi_files
+ }
+
+ # Now send the hbotStringFile
+ if {[catch {set hbi_files [glob -dir $obj_dir hbotStringFile]} res]} {
+ puts $sock "ERROR: No hbotStringFile files found in $obj_dir"
+ puts $log "$sock: ERROR: No hbotStringFile files found in $obj_dir"
+ } else {
+ SendFiles $sock $hbi_files
+ }
+
+ flush $sock
+ flush $log
+
+}
+
+
+##################################################################
+# Send a file to the client
+##################################################################
+proc SendFiles { sock files } {
+ global log
+
+ foreach f $files {
+ set size [file size $f]
+ puts $sock ":OBJ_FILE [file tail $f] $size"
+ puts $log "$sock: :OBJ_FILE [file tail $f] $size"
+ fconfigure $sock -translation binary
+ set fp [open $f r]
+ fconfigure $fp -translation binary
+ fcopy $fp $sock -size $size
+ close $fp
+ fconfigure $sock -translation auto
+ }
+ flush $log
+}
+
+
+
+##################################################################
+# main
+##################################################################
+set forever 1
+set logfile {/tmp/prcd_server.log}
+set log {}
+
+
+# Where are we running?
+foreach {host site c d} [split [exec hostname] .] break
+if {[string compare $host {gfw160}] == 0} {
+ set sb_dir {/tmp/hwp/}
+ eval {exec} "mkdir -p $sb_dir"
+} else {
+ puts "Invalid Location to run server!"
+ exit -1
+}
+
+# array to keep track of ode sandboxes and thier state
+array set sandbox {
+
+ sb00000000 idle
+
+}
+
+array set backing {}
+
+puts "Logfile: $logfile"
+
+
+if { [file exists $logfile] } {
+ set log [open "$logfile" a]
+} else {
+ set log [open "$logfile" w 0666]
+}
+
+
+puts "Logfile: $logfile $log"
+exec chmod 666 $logfile
+
+puts "[clock format [clock seconds]]: HWP compiler Server is starting"
+puts $log "[clock format [clock seconds]]: HWP compiler Server is starting"
+flush $log
+
+set socklist(main) [socket -server Accept 7779]
+
+# By catching errors from vwait- we can ignore them
+catch {vwait forever}
OpenPOWER on IntegriCloud