#!/bin/bash
##****************************************************************************
##
## Copyright (c) 2009-24 Broadcom Corporation
##
## This program is the proprietary software of Broadcom Corporation and/or
## its licensors, and may only be used, duplicated, modified or distributed
## pursuant to the terms and conditions of a separate, written license
## agreement executed between you and Broadcom (an "Authorized License").
## Except as set forth in an Authorized License, Broadcom grants no license
## (express or implied), right to use, or waiver of any kind with respect to
## the Software, and Broadcom expressly reserves all rights in and to the
## Software and all intellectual property rights therein.  IF YOU HAVE NO
## AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY,
## AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE
## SOFTWARE.
##
## Except as expressly set forth in the Authorized License,
##
## 1.     This program, including its structure, sequence and organization,
## constitutes the valuable trade secrets of Broadcom, and you shall use all
## reasonable efforts to protect the confidentiality thereof, and to use this
## information only in connection with your use of Broadcom integrated circuit
## products.
##
## 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED
## "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS
## OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
## RESPECT TO THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL
## IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR
## A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET
## ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME
## THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
##
## 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM
## OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL,
## INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY
## RELATING TO YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM
## HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN
## EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1,
## WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY
## FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
##
##****************************************************************************

# Please refer to "So you want to upgrade OpenSSL?" at http://confluence.broadcom.com/display/RCS/RBB+CM-APP+SW for details

gccVersion="$(mipsisa32-elf-gcc -dumpversion)"
if [ "$gccVersion" == "7.3.0" ] ; then
    echo "gccVersion is correct $gccVersion"
else
    echo "Bad gccVersion $gccVersion"
    echo "Bad gccRoot $gccRoot"
    PATH="/tools/ecos/gnutools/gnutools_730_brcm/bin:$PATH"
    #echo "PATH =  $PATH"
    gccRoot=`which mipsisa32-elf-g++`
    gccRoot=${gccRoot%/mipsisa32-elf/bin/mipsisa32-elf-g++}
    gccVersion="$(mipsisa32-elf-gcc -dumpversion)"
    echo "New gccVersion $gccVersion"
    echo "New gccRoot $gccRoot"
fi

# YOU SHOULDN'T NEED TO MODIFY ANYTHING PAST THIS POINT
#######################################################

TARGET="mipsisa32-elf"
compilerDir=$(pwd)
# Get rid of the "/bin/", and add the architecture directory.  This is where
# all the eCos include files will be found.
#ECOS_INCLUDE=-I${compilerDir%rbb_cm_lib/OpenSSL}rbb_cm_src/Bfc/LibSupport/eCos/bcm33xx_ipv6_install/include
ECOS_LIB=${compilerDir%rbb_cm_lib/OpenSSL}rbb_cm_src/Bfc/LibSupport/OpenSSL
#OPENSSL_INCLUDE="-I. -I.. -I../include -I../include/openssl"
CC=$TARGET-gcc
AR=$TARGET-ar
GCC_VER="$(mipsisa32-elf-gcc -dumpversion)"
export ecos_bfc_include=-I${compilerDir%rbb_cm_lib/OpenSSL}rbb_cm_src/Bfc/LibSupport/eCos/bcm33xx_ipv6_install/include
export ecos_bfc_include=-I${compilerDir%rbb_cm_lib/OpenSSL}rbb_cm_src/Bfc/LibSupport/eCos/bcm33xx_ipv6_install/include
export ecos_include_dir=$ECOS_DIR/$ECOS_CONFIG_DIR/include
export ecos_toolchain_dir=`which mipsisa32-elf-gcc`
export ecos_toolchain_top=${ecos_toolchain_dir%\/bin*}
export ecos_toolchain_includes="-I$ecos_toolchain_top/lib/gcc/mipsisa32-elf/${GCC_VER}/include -I$ecos_toolchain_top/mipsisa32-elf/include/ $ecos_bfc_include"

#INCLUDE="$OPENSSL_INCLUDE $ECOS_INCLUDE"
#CFLAGS="-EB -mips32 -G0 -O1 -ffunction-sections -msoft-float -Wall -DNO_STRINGS_H -DOPENSSL_IMPLEMENTS_strncasecmp -DCPU=MIPS32 -DMIPSEB -DGETPID_IS_MEANINGLESS -DNO_SYS_UN_H -c"
# POODLE attack prevention
#CFLAGS+=" -DOPENSSL_NO_ENGINE -DOPENSSL_NO_ASM -DOPENSSL_NO_IDEA -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_RC2"
# Flags below were necessary for OpenSSL 1.0.2h to compile
#CFLAGS+=" -DOPENSSL_NO_DH -DOPENSSL_NO_MD4 -DOPENSSL_NO_WHIRLPOOL -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RIPEMD -DOPENSSL_NO_RIPEMD160"

fetchFlag=0
cleanFlag=0
openSSLTarball=""
version="1.1.1w"

function error 
{
        echo "ERROR: "$1
        exit 1
}

function parse_parameters 
{

        while getopts ":v:hfc" opt; do
          case $opt in
                v)
            version=$OPTARG
            ;;

                c)
                        cleanFlag=1
                        ;;
                f)
                        fetchFlag=1
                        ;;
                h)
                        echo "build script parameters"
                        echo "-f        : Fetch the source tarball from ftp.openssl.org"
                        echo "-v        : Specify version of OpenSSL to build. If not an existing version, use the -f flag to force a fetch"
                        echo "-h        : This"
                        exit 1
                        ;;
                \?)
                  error "Invalid option: -$OPTARG"
                  ;;
                :)
                  error "Option -$OPTARG requires an argument."
                  ;;
          esac
        done
}

function fetch_tarball 
{
    keep=0

        # Remove tarball if it exists since we're going to fetch a new
        # one anyway.
        if [ -f $openssl_tarball ]; then
                echo "$openssl_tarball exists. Use or re-download? [Y/n]"
                read keep
                if [ "$keep" = "n" ]; then
                rm $openssl_tarball
            fi
        fi

    if [ "$keep" = "n" ]; then
    echo Fetching $openssl_tarball from ftp.openssl.org
    wget ftp://ftp.openssl.org/source/$openssl_tarball
    if [ $? -ne 0 ]; then
        error "Could not retrieve $openssl_tarball from ftp.openssl.org"
        exit 1
    fi
    fi

        # If extracted version already exists, ask user if they want to overwrite
        if [ -d $openssl_dir ]; then
                echo "$openssl_dir exists.  Overwrite? [y/N]"
                read overwrite
                if [ "$overwrite" = "y" ]; then
                        rm -rf $openssl_dir
                else
                        exit 1
                fi
        fi

        # untar it
        tar -xzf $openssl_tarball
        if [ $? -ne 0 ]; then
                error "Could not unpack $openSSLTarball from ftp.openssl.org"
                exit 1
        fi
}

# Patch OpenSSL source as it won't compile as is.  The changes are minimal 
# and we hope to push them upstream  back into OpenSSL so that we won't have
# to maintain these.
function patch_openssl 
{
   cp ../*.patch .

   # First check if patch was already applied.  If it is, don't attempt to patch again
   patch -f --dry-run --silent Configure Configure.patch
   if [ $? -eq 0 ]; then
       # The Configure script has no support for eCos MIPS builds, so we'll 
       # patch that in.
       patch Configure Configure.patch
   fi

   # First check if patch was already applied.  If it is, don't attempt to patch again
   patch -f --dry-run --silent crypto/pkcs7/bio_pk7.c bio_pk7.c.patch
   if [ $? -eq 0 ]; then 
       # The bio_pk7.c file includes memory.h, which doesn't exist and is not
       # required for our target. Our patch will wrap the include in an ifdef
       # so that it is excluded.
       patch crypto/pkcs7/bio_pk7.c bio_pk7.c.patch
   fi
}

# Patch OpenSSL source for version 1.1.1b to 1.1.1w.
function patch_openssl_1.1.1b_w
{
   cp ../openssl.$version.diff .
   patch -p1 < openssl.$version.diff
   rm openssl.$version.diff
}


# Copy OpenSSL header files for version 1.1.1m to 1.1.1w.
function copy_headers_openssl_1.1.1m_w
{
    cp crypto/asn1/asn1_local.h $ECOS_LIB/include/openssl
    cp include/openssl/asn1.h $ECOS_LIB/include/openssl
    cp include/crypto/asn1.h $ECOS_LIB/include/crypto
    cp crypto/dh/dh_local.h $ECOS_LIB/include/openssl
    cp crypto/hmac/hmac_local.h $ECOS_LIB/include/openssl
    cp crypto/rsa/rsa_local.h $ECOS_LIB/include/openssl
    cp crypto/x509/x509_local.h $ECOS_LIB/include/openssl
    cp crypto/bio/bio_local.h $ECOS_LIB/include/openssl
    cp include/crypto/evp.h $ECOS_LIB/include/crypto
    cp include/openssl/evp.h $ECOS_LIB/include/openssl
    cp include/openssl/x509.h $ECOS_LIB/include/openssl
    cp include/crypto/x509.h $ECOS_LIB/include/crypto
    cp include/internal/refcount.h $ECOS_LIB/include/internal
    cp include/internal/nelem.h $ECOS_LIB/include/internal
    # copy header files required by CxC SIP
    cp ssl/ssl_local.h $ECOS_LIB/include/openssl
    cp ssl/record/record.h $ECOS_LIB/include/record
    cp ssl/statem/statem.h $ECOS_LIB/include/statem
    cp ssl/packet_local.h $ECOS_LIB/include/openssl
    cp include/internal/dane.h $ECOS_LIB/include/internal
    cp include/internal/tsan_assist.h $ECOS_LIB/include/internal
    cp include/internal/numbers.h $ECOS_LIB/include/internal
    cp include/internal/bio.h $ECOS_LIB/include/internal
    cp crypto/comp/comp_local.h $ECOS_LIB/include/openssl
    # copy header files for d30
    cp crypto/evp/evp_local.h $ECOS_LIB/include/openssl
    # copy header files for openssh
    cp crypto/bn/bn_local.h $ECOS_LIB/include/openssl
    cp crypto/dsa/dsa_local.h $ECOS_LIB/include/openssl
    cp include/crypto/bn.h $ECOS_LIB/include/crypto
    cp include/crypto/bn_conf.h $ECOS_LIB/include/crypto
    cp include/crypto/ec.h $ECOS_LIB/include/crypto
    cp crypto/ec/ec_local.h $ECOS_LIB/include/openssl
}

# Build the OpenSSL libraries. This function will first patch the OpenSSL source
# and then run the standard "configure" script.  The goal is to keep the build process
# as close to the standard openssl build as possible.
function build_openssl
{
    cd $openssl_dir
    if [ $version = "1.1.1w" ]; then
        patch_openssl_1.1.1b_w
    else
        echo "Attempted to build an old ssl version $version"
        exit 1
    fi

    # Run configure with our target and a couple of flags that aren't easily set by defines
    ./Configure ecos-mips32 no-threads no-asm
    if [ $? -neq 0 ]; then
        echo "Configure script failed. Please review the patches and hand merge if required"
        exit 1
    fi

    # Run make depend to generate all the dependencies. The make depend command produces some errors
    # but these are benign and seem to be a result of cross-compiling for eCos.
    make depend
    if [ $? -neq 0 ]; then
        echo "make depend failed. Please review the patches and the output of Configure and fix any errors before proceeding"
        exit 1
    fi

    # Finally build our libraries!
    make build_libs
    if [ -f libssl.a ] && [ -f libcrypto.a ]; then
        echo "make build_libs succeeded!"
    else
        echo "make build_libs failed. Please review the patches and the output of Configure and make depend and fix any errors before proceeding"
        exit 1
    fi

    # Need to check for presence of output libs as a sure sign of success/failure.
}

function copy_libsandheaders
{
    echo Copying libraries and header files...
    
    rm -rf $ECOS_LIB/include/openssl
    rm -rf $ECOS_LIB/include/crypto
    rm -rf $ECOS_LIB/include/internal
    rm -rf $ECOS_LIB/include/record
    rm -rf $ECOS_LIB/include/statem
    rm -rf $ECOS_LIB/include/*
    mkdir $ECOS_LIB/include/openssl
    mkdir $ECOS_LIB/include/crypto
    mkdir $ECOS_LIB/include/internal
    mkdir $ECOS_LIB/include/record
    mkdir $ECOS_LIB/include/statem
    cp include/openssl/* $ECOS_LIB/include/openssl
    cp include/internal/cryptlib.h $ECOS_LIB/include/openssl
    cp e_os.h $ECOS_LIB/include/openssl
    cp libcrypto.a $ECOS_LIB
    cp libssl.a $ECOS_LIB

    # copy header files for various versions
    if [ $version = "1.1.1w" ]; then
        copy_headers_openssl_1.1.1m_w
    fi

    cd ..
}

function clean_openssl 
{
    echo Deleting $openssl_dir ...
    rm -rf $openssl_dir
    echo Extracting $openssl_tarball ...
    tar zxvf $openssl_tarball
    echo Finshed!
    exit 1
}

# Start of main

# First let's parse the paramets
parse_parameters "$@"

openssl_dir=openssl-$version
openssl_tarball=$openssl_dir.tar.gz

echo "Building revision: $version"

# See if we need to retrieve the tarball
if [ $fetchFlag = 1 ]; then
        fetch_tarball
fi

# Clean
if [ $cleanFlag = 1 ]; then
        clean_openssl
fi

# Build the code
build_openssl

# Copy the newly built libs and header files
copy_libsandheaders

echo "All done"

exit 0

