/*****************************************************************
 *****************************************************************
 ***                                                            **
 ***    (C)Copyright 2005-2006, American Megatrends Inc.        **
 ***                                                            **
 ***            All Rights Reserved.                            **
 ***                                                            **
 ***        6145-F, Northbelt Parkway, Norcross,                **
 ***                                                            **
 ***        Georgia - 30071, USA. Phone-(770)-246-8600.         **
 ***                                                            **
 *****************************************************************
 *****************************************************************
 ******************************************************************
 *
 * AMIRestoreDefaults.c
 * AMI Restore Factory settings related implementation.
 *
 * Author: Gokula Kannan. S <gokulakannans@amiindia.co.in>
 ******************************************************************/

#include "Debug.h"
#include "Support.h"
#include "IPMIDefs.h"
#include "IPMI_AMIConf.h"
#include "AMIRestoreDefaults.h"
#include "flshfiles.h"
#include "flashlib.h"
#include "PendTask.h"
#include <sys/reboot.h>
#include <linux/reboot.h>
#include <dlfcn.h>
#include <pthread.h>
//#include "OSPort.h"
#include "PDKAccess.h"
//#include "IPMIConf.h"
#include "libpreserveconf.h"
#include "featuredef.h"

#define RESTORE_PRESERVE_CMD "/usr/local/bin/preservecfg 1 &"
#define RESTORE_DEFAULTS_CMD "sh /etc/restoredefaults.sh restore &"

int AMIRestoreDefaults(_NEAR_ INT8U* pReq, INT32U ReqLen, _NEAR_ INT8U* pRes,int BMCInst)
{
    RestartService_T Service;
    INT8U *curchannel;

    if(ReqLen > 0)
    {
        *pRes = CC_REQ_INV_LEN;
        return sizeof(*pRes);
    }

    int retVal = PrepareFlashArea(FLSH_CMD_DUMMY_FLASH_AREA, g_corefeatures.dual_image_support);
    if (retVal != EXIT_SUCCESS)
    {
        IPMI_ERROR("Flash is going on currently");
        (*pRes) = CC_DEV_IN_FIRMWARE_UPDATE_MODE;
        goto end;
    }

    if(g_corefeatures.preserve_config == ENABLED)
    {
        system (RESTORE_PRESERVE_CMD);
    }
    else
    {
        system (RESTORE_DEFAULTS_CMD);
    }
    TINFO("Stopping adviserd...");
    system("/etc/init.d/adviserd.sh stop");
	
    TINFO("Restoring to default configuration... Done");

    /* PDK Module Post Set Reboot Cause*/
    if(g_PDKHandle[PDK_SETREBOOTCAUSE] != NULL)
    {
        ((INT8U(*)(INT8U,int)) g_PDKHandle[PDK_SETREBOOTCAUSE])(SETREBOOTCAUSE_IPMI_CMD_PROCESSING,BMCInst);
    }

    //Post BMC Reboot task to Pend task    
    Service.ServiceName = REBOOT;
    Service.SleepSeconds = 3;		// Sleep for 3 Seconds
    SetPendStatus(PEND_OP_RESTART_SERVICES, PEND_STATUS_PENDING);    
    OS_THREAD_TLS_GET(g_tls.CurChannel,curchannel);
    PostPendTask(PEND_OP_RESTART_SERVICES, (INT8U *) &Service, sizeof(RestartService_T),*curchannel & 0xF,BMCInst);

    (*pRes) = CC_SUCCESS;
end:
    return sizeof(*pRes);
}


int AMIGetPreserveConfStatus(_NEAR_ INT8U* pReq, INT32U ReqLen, _NEAR_ INT8U* pRes,int BMCInst)
{    
    GetPreserveConfigRes_T* pPreserveConfRes  =  ( GetPreserveConfigRes_T* ) pRes;
    GetPreserveConfigReq_T* pPreserveConfReq  =  ( GetPreserveConfigReq_T* ) pReq;
    int status = -1;

    void *dl_handle = NULL;
    int ( *dl_func )( int, char* )=NULL;

    if(g_corefeatures.preserve_config == ENABLED)
    {
        dl_handle = dlopen ( "/usr/local/lib/libpreserveconf.so", RTLD_NOW );
        if(NULL == dl_handle)
        {
            IPMI_ERROR("Error in loading libpreserveconf.so library %s\n", dlerror() );		
            return -1;
        }

        pPreserveConfRes->CompletionCode = CC_NORMAL;

        if (ReqLen != 1)
        {
            pPreserveConfRes->CompletionCode = CC_REQ_INV_LEN;
            goto end;
        }

        if(pPreserveConfReq->Selector >= 200)
        {
            if(g_PDKHandle[PDK_GETPRESERVESTATUS] != NULL)
            {
            TDBG("gloabl handle is not NULL\n");
            status = ((int(*)(int, int))g_PDKHandle[PDK_GETPRESERVESTATUS]) (pPreserveConfReq->Selector, BMCInst);
            if (-1 == status)
            {
                pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
            }
            if (-2 == status)
            {
                pPreserveConfRes->CompletionCode = CC_PARAM_NOT_SUPPORTED;
            }
            else
            {
                pPreserveConfRes->Status = status;
                TDBG("  status  :: %d\n", pPreserveConfRes->Status);
            }
            goto end;
        }
        }

        dl_func = dlsym (dl_handle, "GetPreserveStatus");
        if ( NULL == dl_func )
        {
            IPMI_ERROR("Error in getting symbol %s \n", dlerror());
            pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
            goto end;
        }

        //status = GetPreserveStatus(pPreserveConfReq->Selector, PRESERVE_AMI_FILE);
        status = dl_func(pPreserveConfReq->Selector, PRESERVE_AMI_FILE);
        if (-1 == status)
        {
            pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
        }
        else if (-2 == status)
        {
            pPreserveConfRes->CompletionCode = CC_PARAM_NOT_SUPPORTED;
        }
        else
        {
            pPreserveConfRes->Status = status;
            TDBG("  status  :: %d\n", pPreserveConfRes->Status);	
        }

        end:
            if (NULL != dl_handle)
                dlclose (dl_handle);

      return sizeof(GetPreserveConfigRes_T);
    }
    else
    {
        //If Preserve Conf feature is disabled in Project Configuration, return Not Support
        pPreserveConfRes->CompletionCode = CC_INV_CMD;
        return sizeof(GetPreserveConfigRes_T);
    }

}

int AMISetPreserveConfStatus(_NEAR_ INT8U* pReq, INT32U ReqLen, _NEAR_ INT8U* pRes,int BMCInst)
{	
    SetPreserveConfigRes_T* pPreserveConfRes  =  ( SetPreserveConfigRes_T* ) pRes;
    SetPreserveConfigReq_T* pPreserveConfReq  =  ( SetPreserveConfigReq_T* ) pReq;
    void *dl_handle = NULL;
    int ( *dl_func )( int, int, char* )=NULL;
    int status = -1;

    if(g_corefeatures.preserve_config == ENABLED)
    {
        dl_handle = dlopen ( "/usr/local/lib/libpreserveconf.so", RTLD_NOW );
        if(NULL == dl_handle)
        {
            IPMI_ERROR("Error in loading libpreserveconf.so library %s\n", dlerror() );		
            return -1;
        }

        memset (pPreserveConfRes, 0x00, sizeof (SetPreserveConfigRes_T));
        pPreserveConfRes->CompletionCode = CC_NORMAL;

        if (ReqLen != 2)
        {
            pPreserveConfRes->CompletionCode = CC_REQ_INV_LEN;
            goto end;
        }

        if (pPreserveConfReq->Status == 0 || pPreserveConfReq->Status == 1)
        {
        if(pPreserveConfReq->Selector >= 200)
        {
            if(g_PDKHandle[PDK_SETPRESERVESTATUS] != NULL)
            {
                status = ((int(*)(int, int, int))g_PDKHandle[PDK_SETPRESERVESTATUS]) (pPreserveConfReq->Selector, pPreserveConfReq->Status, BMCInst);
                if( -1 == status)
                {
                    pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
                }
                if (-2 == status)
                {
                    pPreserveConfRes->CompletionCode = CC_PARAM_NOT_SUPPORTED;
                }
                else
                    pPreserveConfRes->CompletionCode = status;

            goto end;
            }
        }

        dl_func = dlsym (dl_handle, "SetPreserveStatus");
        if ( NULL == dl_func )
        {
            IPMI_ERROR("Error in getting symbol %s \n", dlerror());
            pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
            goto end;
        }

        status = dl_func(pPreserveConfReq->Selector, pPreserveConfReq->Status, PRESERVE_AMI_FILE);
        if (-1 == status)
        {
            pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
        }
        else if (-2 == status)
        {
            pPreserveConfRes->CompletionCode = CC_PARAM_NOT_SUPPORTED;
        }
        else
            pPreserveConfRes->CompletionCode = CC_NORMAL;
            
        }
        else
        {
            pPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
        }

        end:
        if (NULL != dl_handle)
        dlclose (dl_handle);

        return sizeof(SetPreserveConfigRes_T);
    }
    else
    {
        //If Preserve Conf feature is disabled in Project Configuration, return Not Support 
        pPreserveConfRes->CompletionCode = CC_INV_CMD;
        return sizeof(SetPreserveConfigRes_T);
    }

}

int AMIGetAllPreserveConfStatus(_NEAR_ INT8U* pReq, INT32U ReqLen, _NEAR_ INT8U* pRes,int BMCInst)
{    
    GetAllPreserveConfigRes_T* pAllPreserveConfRes  =  ( GetAllPreserveConfigRes_T* ) pRes;
    int status = -1;

    void *dl_handle = NULL;
    int ( *dl_func )( unsigned int *, char* ) = NULL;
    unsigned int enabledstatus;

    if(g_corefeatures.preserve_config == ENABLED)
    {
        dl_handle = dlopen ( "/usr/local/lib/libpreserveconf.so", RTLD_NOW );
        if(NULL == dl_handle)
        {
            IPMI_ERROR("Error in loading libpreserveconf.so library %s\n", dlerror() );
            return -1;
        }

        pAllPreserveConfRes->CompletionCode = CC_NORMAL;

        dl_func = dlsym (dl_handle, "GetAllPreserveStatus");
        if ( NULL == dl_func )
        {
            IPMI_ERROR("Error in getting symbol %s \n", dlerror());
            pAllPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
            if (NULL != dl_handle)
                dlclose (dl_handle);

            return sizeof(GetAllPreserveConfigRes_T);
        }

        status = dl_func( &enabledstatus, PRESERVE_AMI_FILE );
        if (-1 == status)
        {
            pAllPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
        }
        else
        {
            pAllPreserveConfRes->EnabledStatus = enabledstatus;
            pAllPreserveConfRes->Status = status;
            TDBG("  status  :: %d\n", pAllPreserveConfRes->Status);
            pAllPreserveConfRes->Reserved = 0x00;
        }

        if (NULL != dl_handle)
            dlclose (dl_handle);

        return sizeof(GetAllPreserveConfigRes_T);
    }
    else
    {
        // If Preserve Conf feature is disabled in Project Configuration, return Not Support
        pAllPreserveConfRes->CompletionCode = CC_INV_CMD;
        return sizeof(GetAllPreserveConfigRes_T);
    }
}

int AMISetAllPreserveConfStatus(_NEAR_ INT8U* pReq, INT32U ReqLen, _NEAR_ INT8U* pRes,int BMCInst)
{
    SetAllPreserveConfigReq_T* pAllPreserveConfReq  =  ( SetAllPreserveConfigReq_T* ) pReq;
    SetAllPreserveConfigRes_T* pAllPreserveConfRes  =  ( SetAllPreserveConfigRes_T* ) pRes;
    void *dl_handle = NULL;
    int ( *dl_func )( int, char* ) = NULL;
    int status = -1;

    if ( pAllPreserveConfReq->Status >= BIT10)
    {
        pAllPreserveConfRes->CompletionCode = CC_INV_DATA_FIELD;
        return sizeof(SetAllPreserveConfigRes_T);
    } 

    if( ENABLED == g_corefeatures.preserve_config )
    {
        dl_handle = dlopen ( "/usr/local/lib/libpreserveconf.so", RTLD_NOW );
        if( NULL == dl_handle )
        {
            IPMI_ERROR("Error in loading libpreserveconf.so library %s\n", dlerror() );
            return -1;
        }

        memset (pAllPreserveConfRes, 0x00, sizeof (SetAllPreserveConfigRes_T));
        pAllPreserveConfRes->CompletionCode = CC_NORMAL;

        dl_func = dlsym (dl_handle, "SetAllPreserveStatus");
        if ( NULL == dl_func )
        {
            IPMI_ERROR("Error in getting symbol %s \n", dlerror());
            pAllPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
            if (NULL != dl_handle)
                dlclose (dl_handle);
            return sizeof(SetAllPreserveConfigRes_T);
        }

        status = dl_func( pAllPreserveConfReq->Status, PRESERVE_AMI_FILE);
        if ( -1 == status)
        {
            pAllPreserveConfRes->CompletionCode = CC_UNSPECIFIED_ERR;
        }
        else if ( -2 == status)
        {
            pAllPreserveConfRes->CompletionCode = CC_CMD_UNSUPPORTED_UNCONFIGURABLE;
        }
        else
        {
            pAllPreserveConfRes->CompletionCode = CC_NORMAL;
        }

        if (NULL != dl_handle)
            dlclose (dl_handle);

        return sizeof(SetAllPreserveConfigRes_T);
    }
    else
    {
        // If Preserve Conf feature is disabled in Project Configuration, return Not Support 
        pAllPreserveConfRes->CompletionCode = CC_INV_CMD;
        return sizeof(SetAllPreserveConfigRes_T);
    }
}

