#!/bin/bash
#
# calvados/fretta_pkg/boot/scripts/pd-functions
# This script provides PD functions to other scripts.
#
# Copyright (c) 2014-2016 by Cisco Systems, Inc.
# All rights reserved.

# source PD-function library
if [ -f /etc/init.d/load_kernel_modules.sh ]; then
    source /etc/init.d/load_kernel_modules.sh
fi

#
# Get the file size in bytes, cross os
#
function filesize
{
    local file=$1
    size=`stat -c %s $file 2>/dev/null` # linux
    if [ $? -eq 0 ]; then
        echo $size
        return 0
    fi

    eval $(stat -s $file) # macos
    if [ $? -eq 0 ]; then
        echo $st_size
        return 0
    fi

    echo 0
    return -1
}

#
# Check if pd_funcions should be skipped
#
function skip_pd_functions {
    local install=$(cat /proc/cmdline | grep install=)
    if [ -n "${install}" ]; then
        return 1
    fi
    local sim=$(cat /proc/cmdline | grep simulator=)
    if [ -n "${sim}" ]; then
        return 1
    fi
    if [[ "${BOARDTYPE}" == "LC" ]] || [[ "${BOARDTYPE}" == "FC" ]] || [[ "${BOARDTYPE}" == "XC" ]]; then
        return 1
    fi
    return 0
}

#
# Which TTY should calvados con use
#
function platform_enable_calvados_con
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL='/dev/pts/0'
    declare -F platform_log &>/dev/null && platform_log "Calvados console on $ACTIVE_SERIAL"
    echo "Calvados console on $ACTIVE_SERIAL"
}

#
# Which TTY should calvados aux use
#
function platform_enable_calvados_aux
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL='/dev/pts/1'
    declare -F platform_log &>/dev/null && platform_log "Calvados aux on $ACTIVE_SERIAL"
    echo "Calvados aux on $ACTIVE_SERIAL"
}

#
# Which TTY should XR con use
#
function platform_enable_xr_con
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL_XR_CON="pts/0"
    declare -F platform_log &>/dev/null && platform_log "XR console on $ACTIVE_SERIAL_XR_CON"
    echo "XR console on $ACTIVE_SERIAL_XR_CON"
}

#
# Which TTY should XR aux use
#
function platform_enable_xr_aux
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL_XR_AUX="pts/1"
    declare -F platform_log &>/dev/null && platform_log "XR aux on $ACTIVE_SERIAL_XR_AUX"
    echo "XR aux on $ACTIVE_SERIAL_XR_AUX"
}


#
# Should we allow the first serial port to have a tty login?
#
function platform_enable_host_login_on_first_serial
{
    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    ACTIVE_SERIAL=''
}

# Do we want to enable host access on extra ttys? Good for development but
# is a security risk to leave host access visible.
#
function platform_starts_serial
{
    # FRETTA_BRINGUP_HACK - CSCut87979
    # Allow starts-serial to start serial login
    # If no active serial set, and on hostos, start serial on ttyS0
    [ -n "$ACTIVE_SERIAL" -o "$VMTYPE" != "hostos" ] || ACTIVE_SERIAL="/dev/ttyS0"

    #FRETTA_BRINGUP_HACK - CSCut90301
    #boardtype FC/XC is not defined yet, use arch as filter
    #FC/XC still uses boardtype as LC
    ARCH=`arch`
    if [ "$ARCH" == "armv7l" ]; then
        BOARDTYPE=$(get_cctrl_board_type)
    fi

    if [ "${BOARDTYPE}" == "FC" ] || [ "${BOARDTYPE}" == "XC" ] ; then
        if [ "$VMTYPE" == "hostos" ]; then
            ACTIVE_SERIAL="/dev/ttyS0"
        else
            ACTIVE_SERIAL="/dev/pts/0"
            if  ! (grep -q "pts/0" /etc/securetty)  ; then
                echo pts/0 >> /etc/securetty
            fi
        fi
        SPEED=115200
    elif [ "${BOARDTYPE}" == "LC" -a "$VMTYPE" != "hostos" ]; then
        ACTIVE_SERIAL="/dev/pts/0"
        if  ! (grep -q "pts/0" /etc/securetty)  ; then
            echo pts/0 >>/etc/securetty
        fi
        SPEED=115200
    elif [ "${BOARDTYPE}" == "LC" ]; then
        ACTIVE_SERIAL="/dev/ttyS1"
        SPEED=115200
    fi
    grep -q vmtype=hostos /proc/cmdline && return

    skip_pd_functions
    if [ $? -ne 0 ]; then
        return;
    fi
    #
    # We do not want host tty access unless enabled by development mode,
    # so default to no access.on
    #
    echo "Start serial incoming on $ACTIVE_SERIAL, Clearing .."
    declare -F platform_log &>/dev/null && platform_log "Start serial incoming on $ACTIVE_SERIAL, Clearing .."
    ACTIVE_SERIAL=
}

#
# Check we have somewhere to write logs to. At early boot we might not have
# /var/log, so use /tmp until then
#
function platform_log_choose_log_file
{
    #
    # Where to log shell script output to. If /var/log is not available, use
    # /tmp which surely must be usable.
    #
    local PLATFORM_LOG=/var/log/platform.log

    #
    # If we are installing, append onto the host install logs as platform.log 
    # is not saved by xrnginstall in save_install_log (yet)
    #
    grep -q "root=/dev/ram" /proc/cmdline
    if [ $? -eq 0 ]; then
        PLATFORM_LOG=/var/log/host-install.log
        #
        # A tad obscure, but this is the FD that pxe_install uses for logging.
        # Only if we log to this will our output get into host-install.log
        #
        PLATFORM_LOG=/dev/fd/107
    fi

    PLATFORM_LOG_FILE=$PLATFORM_LOG
    if [ ! -f $PLATFORM_LOG_FILE ]; then
        touch $PLATFORM_LOG_FILE &>/dev/null
    fi

    if [ ! -w $PLATFORM_LOG_FILE ]; then
        local PLATFORM_TMP_LOG=/tmp/platform.early.log

        PLATFORM_LOG_FILE=$PLATFORM_TMP_LOG
    fi

    #
    # Sanity check it doesn't get too large
    #
    if [ -f $PLATFORM_LOG_FILE ]; then
        local FILESIZE=`filesize $PLATFORM_LOG_FILE`
        local MAX=1048576

        if [ $FILESIZE -ge $MAX ]; then
            #
            # Chop off the start of the file
            #
            sed -i '1,100d' $PLATFORM_LOG_FILE
        fi
    fi
}

#
# Utility function to log to our platform log file to help with
# debugging shell script flow.
#
function platform_log
{
    platform_log_choose_log_file

    local DATE=`date`
    echo "$DATE ($0): $*" >> $PLATFORM_LOG_FILE
}

#
# Utility function to log to our platform log file to help with
# debugging shell script flow.
#
function platform_log_error
{
    platform_log_console $*

    backtrace
}

#
# Some calvados scripts use log message but it is not defined. Get the output
# into our platform log if log_message is not defined.
#
function log_message
{
    platform_log $*
}

#
# Log to file and console
#
function platform_log_console 
{
    platform_log_choose_log_file

    local DATE=`date`
    echo "$DATE ($0): $*" | tee -a $PLATFORM_LOG_FILE

    return ${PIPESTATUS[0]}
}

#
# Keep this function aliased as a variable, so that if PLATFORM_LOG_EXEC is 
# not defined due to an error in including this file, the callers command 
# still executes
#
PLATFORM_LOG_EXEC=platform_log_exec
PLATFORM_LOG_EXEC_CONSOLE=platform_log_exec_console

#
# Log results to the log file only
#
function platform_log_exec
{
    platform_log_choose_log_file
    platform_log "exec: $*"
    platform_log "    : in cwd" `pwd`

    local PREFIX="`date -u`: -- "
    $* 2>&1 | sed "s/^/${PREFIX}/g" >>$PLATFORM_LOG_FILE 2>&1

    return ${PIPESTATUS[0]}
}

#
# Log results to the log file and the console
#
function platform_log_exec_console
{
    platform_log_choose_log_file
    platform_log "exec: $*"
    platform_log "    : in cwd" `pwd`

    local PREFIX="`date -u`: -- "
    $* 2>&1 | sed "s/^/${PREFIX}/g" | tee -a $PLATFORM_LOG_FILE

    return ${PIPESTATUS[0]}
}

#
# Print a shell backtrace
#
function backtrace () {
    local deptn=${#FUNCNAME[@]}

    for ((i=1; i<$deptn; i++)); do
        local func="${FUNCNAME[$i]}"
        local line="${BASH_LINENO[$((i-1))]}"
        local src="${BASH_SOURCE[$((i-1))]}"
        printf '%*s at: %s(), %s, line %s\n' $i '' $func $src $line # indent
    done
}

function platform_log_backtrace_ () {
    local depth=${#FUNCNAME[@]}

    for ((i=1; i<$depth; i++)); do
        local func="${FUNCNAME[$i]}"
        local line="${BASH_LINENO[$((i-1))]}"
        local src="${BASH_SOURCE[$((i-1))]}"
        printf '%*s at: %s(), %s, line %s\n' $i '' $func $src $line >> $PLATFORM_LOG_FILE
    done
}

function platform_log_backtrace () {
    platform_log_choose_log_file

    platform_log_backtrace_
}

# This will help the CAPI and GSP packets to get proper priority
function set_vlan_priority_map() {
    local dev=$1
    for i in {0..7}
    do
       vconfig set_egress_map $dev $i $i  > /dev/null 2>&1
       vconfig set_ingress_map $dev $i $i  > /dev/null 2>&1
    done
}
 
# Console Mux details
# Console muxing is needed becase there is only one console
#
function platform_get_mux_tty_settings
{
    source /etc/init.d/spirit_pd.sh
    get_board_type
    if [ "${BOARDTYPE}" == "RP" ]; then
        MUX_TTY=/dev/ttyS0
        MUX_TTY_SPEED=9600
        MUX_TTY_TYPE=3
        MUX_TTY_FLOWCTRL=""
        MUX_TTY_SOCAT_OPTION="raw,echo=0,opost=1"
    fi
}

# App hosting Cgroup settings
function pd_tpa_cgroup_settings
{
    source /etc/init.d/spirit_pd.sh
    get_board_type
    if [[ "${BOARDTYPE}" == "RP" ]]; then
        APP_CGROUP_MEM_NUMA_NODES=0
        APP_CGROUP_CPUSET_CPUS=1-11
        APP_CGROUP_CPU_SHARES=256
        APP_CGROUP_MEM_LIMIT_IN_BYTES=1G
    fi        
}
