/*
 * Brief:	Get all sensor information.
 * Author:	Jimbo_zhang@outlook.com
 * Data:		2019-4-27
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "goahead.h"

#include "libipmi_AppDevice.h"
#include "libipmi_session.h"
#include "libipmi_errorcodes.h"
#include "libipmi_struct.h"
#include "libipmi_sdr.h"
#include "libipmi_sensor.h"
#include "libipmi_storlead_OEM.h"
#include "com_IPMI_Storlead.h"
#include "libipmi_StorDevice.h"
#include "com_BmcType.h"
#include "com_BMCCfg.h"
#include "com_IPMI_App.h"


uint16_t LIBIPMI_HL_SetFanInfo( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t fanIndex, uint8_t fanMode, uint8_t fanLevel, int timeout)
{
	uint16_t wRet = 0;
	uint8_t	Res[10];
	uint8_t Req[10];
	uint32_t dwResLen;
	Req[0]	= fanIndex;
	Req[1] 	= fanMode;
	Req[2]	= fanLevel;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,   NETFNLUN_IPMI_STORLEAD, CMD_SET_FAN_INFO,
													(uint8_t*)Req, 3,
													(uint8_t *)Res, &dwResLen,
													timeout);
	return wRet;
}

uint16_t IPMC_SetFanInfo( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, uint8_t fanIndex, uint8_t fanMode, uint8_t fanLevel, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_SET_FAN_INFO;	
	Req[7] = fanIndex;
	Req[8] = fanMode;
	Req[9] = fanLevel;
	Req[10] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7] + Req[8] + Req[9])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 11,
											Res, &dwResLen,
											timeout);
	if(( wRet != 0 ) || (Res[6] != 0))
	{
			printf("Error IPMC_SetFanInfo\n");
			return -1;
	}
	return wRet;
}

uint16_t LIBIPMI_HL_GetSysInfo( IPMI20_UDS_SESSION_T *pUDSSession, SysInfo_T *pSysInfo, int timeout)
{
	
	uint16_t wRet = 0;
	uint8_t Req[5];
	uint8_t	Res[MAX_TEXT_LEN+5];
	uint32_t dwResLen;
	uint16_t strLen, remainLen;
	uint16_t offset = 0;

	//get title
	Req[0] = 0;
	Req[1] = 0;
	Req[2] = 0;
	Req[3] = MAX_TITLE_LEN&0xff;
	Req[4] = (MAX_TITLE_LEN>>8)&0xff;	//max title len
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,   
												NETFNLUN_IPMI_STORLEAD, CMD_GET_SYS_INFO,
												(uint8_t*)Req, 5,
												(uint8_t *)Res, &dwResLen,
												timeout);
	if((wRet != 0) || (Res[0] != 0))
	{
		printf("---> get Title error\n");
		return -1;
	}
	strLen = (Res[2]<<8) | Res[1];
	remainLen = (Res[4]<<8) | Res[3];
	memcpy(pSysInfo->title,&Res[5],strLen);

	//get text
	Req[0] = 1;
	Req[1] = 0;
	Req[2] = 0;
	Req[3] = MAX_TEXT_LEN&0xff;
	Req[4] = (MAX_TEXT_LEN>>8)&0xff;	//max text len
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,   
												NETFNLUN_IPMI_STORLEAD, CMD_GET_SYS_INFO,
												(uint8_t*)Req, 5,
												(uint8_t *)Res, &dwResLen,
												timeout);
	if((wRet != 0) || (Res[0] != 0))
	{
		printf("---> get Text error\n");
		return -1;
	}
	strLen = (Res[2]<<8) | Res[1];
	remainLen = (Res[4]<<8) | Res[3];
	memcpy(pSysInfo->text,&Res[5],strLen);
	
	return 0;
}

uint16_t IPMC_GetSysInfo( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, SysInfo_T *pSysInfo, int timeout)
{
	
	uint16_t 	wRet = 0;
	uint8_t 	Req[20] = {0};
	uint8_t		Res[MAX_TEXT_LEN+5];
	uint16_t 	strLen, remainLen;
	uint32_t	dwResLen;
	

	//get title
	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_SYS_INFO;	
	Req[7] = 0;
	Req[8] = 0;
	Req[9] = 0;
	Req[10] = MAX_TITLE_LEN&0xff;
	Req[11] = (MAX_TITLE_LEN>>8)&0xff;	//max title len
	Req[12] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7] + Req[8] + Req[9] + Req[10] + Req[11])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 13,
											Res, &dwResLen,
											timeout);

	if((wRet != 0) || (Res[6] != 0))
	{
		printf("---> get Title error\n");
		return -1;
	}
	strLen = (Res[8]<<8) | Res[7];
	remainLen = (Res[10]<<8) | Res[9];
	memcpy(pSysInfo->title,&Res[11],strLen);

	//get text
	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_SYS_INFO;	
	Req[7] = 1;
	Req[8] = 0;
	Req[9] = 0;
	Req[10] = MAX_TEXT_LEN&0xff;
	Req[11] = (MAX_TEXT_LEN>>8)&0xff;	//max text len
	Req[12] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7] + Req[8] + Req[9] + Req[10] + Req[11])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 13,
											Res, &dwResLen,
											timeout);
	if((wRet != 0) || (Res[6] != 0))
	{
		printf("---> get Text error\n");
		return -1;
	}
	strLen = (Res[8]<<8) | Res[7];
	remainLen = (Res[10]<<8) | Res[9];
	memcpy(pSysInfo->text,&Res[11],strLen);
	
	return 0;
}

int LIBIPMI_HL_GetAllBladeStatus(IPMI20_UDS_SESSION_T *pUDSSession, BladeStatus_T *BladeStatus, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t pRes[BLADE_NUMBERS*sizeof(BladeStatus_T)+1];
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_STORLEAD, CMD_GET_ALLBLADE_INFO,
							NULL, 0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);
	if(( wRet != 0 ) || (pRes[0] != 0))
	{
			printf("Error getting Blade Status Info\n");
			memset(BladeStatus, 0, BLADE_NUMBERS*sizeof(BladeStatus_T));
	}
		
	memcpy(BladeStatus, pRes+1, BLADE_NUMBERS*sizeof(BladeStatus_T));
	return 0;
}


int LIBIPMI_HL_GetFanInfo(IPMI20_UDS_SESSION_T *pUDSSession, FanInfo_T* pFanInfo, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	*pRes = (uint8_t *)walloc(MAX_FAN_NUMS*sizeof(FanInfo_T) + 10);
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_STORLEAD, CMD_GET_FAN_INFO,
							NULL,	0,
							(uint8_t*)pRes,  &dwResLen,
							timeout);

	//printf("dwResLen %d\n", dwResLen);
	if(( wRet != 0 ) || (pRes[0] != 0))
	{
		printf("Error LIBIPMI_HL_GetFanInfo\n");
		return -1;
	}

	memcpy((uint8_t*)pFanInfo, pRes+1, dwResLen-1);	//remove ccode 
	return 0;
}

int IPMC_GetFanInfo(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, FanInfo_T* pFanInfo, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		*Res = (uint8_t *)walloc(MAX_FAN_NUMS*sizeof(FanInfo_T) + 20);

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_FAN_INFO;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 8,
											Res, &dwResLen,
											timeout);
	if(( wRet != 0 ) || (Res[6] != 0))
	{
			printf("Error IPMC_GetFanInfo\n");
			return -1;
	}

	memcpy((uint8_t*)pFanInfo, &Res[7], dwResLen-8);	//remove header and chksum
	return 0;
}

uint16_t IPMICMD_ResetBMC(IPMI20_UDS_SESSION_T *pUDSSession, int timeout)
{
	uint16_t wRet;
	uint32_t dwResLen;
	uint8_t res;
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,
						NETFNLUN_IPMI_APP, CMD_COLD_RESET,
						NULL, 0,
						(uint8_t*)&res, &dwResLen,
						timeout);
	
	return (wRet);
}

uint16_t IPMC_ResetBMC(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[10] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_APP;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_COLD_RESET;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_APP, CMD_SEND_MSG,
							Req, 8,
							Res,  &dwResLen,
							timeout);
	
	
	return (wRet);
}

uint16_t IPMICMD_SetLanInfo(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t index, uint8_t isSave, LanInfo_T *pLanInfo, int timeout)
{
	uint16_t wRet;
	uint32_t dwResLen;
	uint8_t res[10];
	uint8_t req[100];
	
	req[0] = index; 
	req[1] = isSave;
	memcpy(&req[2], pLanInfo, sizeof(LanInfo_T));
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,
						NETFNLUN_IPMI_STORLEAD, CMD_SET_LAN_INFO,
						req, sizeof(LanInfo_T)+2,
						(uint8_t*)res, &dwResLen,
						timeout);
	if(res[0] != 0)
	{
		printf("Set lan Info error!\n");
		return -1;
	}
	
	return (wRet);
}

uint16_t IPMICMD_GetLanInfo(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t index, LanInfo_T *pLanInfo, int timeout)
{
	uint16_t wRet;
	uint32_t dwResLen;
	uint8_t res[100];
	uint8_t req[10];
	
	req[0] = index; 
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,
						NETFNLUN_IPMI_STORLEAD, CMD_GET_LAN_INFO,
						req, 1,
						res, &dwResLen,
						timeout);
	if(res[0] != 0)
	{
		printf("Get lan info error!\n");
		return -1;
	}

	memcpy(pLanInfo, res+1, sizeof(LanInfo_T));
	return (wRet);
}

uint16_t IPMICMD_restoreFactorySettings(IPMI20_UDS_SESSION_T *pUDSSession, int timeout)
{
	uint16_t wRet;
	uint32_t dwResLen;
	uint8_t res;
	
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,
						NETFNLUN_IPMI_STORLEAD, CMD_RESTORE_FACTORY_SET,
						NULL, 0,
						(uint8_t*)&res, &dwResLen,
						timeout);
	
	return (wRet);
}

uint16_t IPMC_restoreFactorySettings(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, int timeout)
{
	uint16_t    wRet = 0;
    uint8_t     Req[20] = {0};
    uint8_t     Res[10];
    uint32_t    dwResLen;

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_RESTORE_FACTORY_SET;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req,8,
											Res, &dwResLen,
											timeout);

	return (wRet);
}

int LIBIPMI_IPMC_GetDeviceID(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, GetDevIDRes_T *DevIDRes, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[100] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_APP;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_DEV_ID;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_APP, CMD_SEND_MSG,
							Req, 8,
							Res,  &dwResLen,
							timeout);

	int i;
	printf("GetDeviceID Res %d: ", dwResLen);
	for(i=0;i<dwResLen;i++)
	{
		printf("%#x ", Res[i]);
	}
	printf("\n");

	memcpy(DevIDRes, &Res[6], sizeof(GetDevIDRes_T));
	if(( wRet != 0 ) || (Res[6] != 0))
	{
			printf("Error IPMC GetDeviceID\n");
			return -1;
	}
		
	return 0;
}

int IPMI_GetSensorName(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t sensor_number, uint8_t *sensor_name, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50] = {0};

	Req[0] = sensor_number;
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_STORLEAD, CMD_GET_SENSOR_NAME,
							Req, 1,
							Res,  &dwResLen,
							timeout);
	if((wRet != 0) || (Res[0] != 0))
	{
		printf("IPMI_GetSensorName failed!\n");
		memset(sensor_name, 0, MAX_ID_STR_LEN);
		return -1;
	}

	memcpy(sensor_name, &Res[1], MAX_ID_STR_LEN);
	return 0;
}

int IPMC_GetSensorName(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, uint8_t sensor_number, uint8_t *sensor_name, int timeout)
{
	int wRet = 0;
	uint32_t	dwResLen;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50] = {0};

	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_SENSOR_NAME;	
	Req[7] = sensor_number;
	Req[8] = 0x100 - (Req[4] + Req[5] + Req[6] + Req[7])&0xff;

	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
							NETFNLUN_IPMI_APP, CMD_SEND_MSG,
							Req, 9,
							Res,  &dwResLen,
							timeout);

	if((wRet != 0) || (Res[6] != 0))
	{
		printf("IPMI_GetSensorName failed!\n");
		memset(sensor_name, 0, MAX_ID_STR_LEN);
		return -1;
	}

	memcpy(sensor_name, &Res[7], MAX_ID_STR_LEN);
	return 0;
}

int IPMI_GetSensorHistory(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t sensor_number, uint8_t *history_buf, int timeout)
{
	uint8_t 	Req[10] = {0};
	uint32_t	dwResLen;
	uint16_t 	wRet;
	Req[0] = sensor_number;
    Req[1] = 0;
    Req[2] = 0;
    Req[3] = (MAX_HISTORY_LEN>>8)&0xff;
    Req[4] = MAX_HISTORY_LEN & 0xff;
    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,   
                                NETFNLUN_IPMI_STORLEAD, CMD_GET_SENSOR_HISTORY,
                                (uint8_t*)Req, 5,
                                (uint8_t *)history_buf, &dwResLen,
                                timeout);
    if((wRet != 0) || (history_buf[0] != 0))
    {
        printf("IPMI_GetSensorHistory error!\n");
        return -1;
    }

    return 0;
}

/*
	本地模块可以一次性全部获取，但是从模块的IPMB总线最大也就只能传输256个字节，所以要分开获取。
*/
int IPMC_GetSensorHistory(IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, uint8_t sensor_number, uint16_t offset, uint16_t length, uint8_t *history_buf, int timeout)
{
	uint8_t 	Req[20] = {0};
	uint32_t	dwResLen;
	uint16_t 	wRet;
    Req[0] = 0x40;  //Track | channel 0
    Req[1] = IpmbAddr;
    Req[2] = NETFNLUN_IPMI_STORLEAD;
    Req[3] = 0x100 - (Req[1] + Req[2])&0xff;    //checksum1
    Req[4] = 0x20;
    Req[5] = 0x10;
    Req[6] = CMD_GET_SENSOR_HISTORY;  
    Req[7] = sensor_number;
    Req[8] = offset&0xff; //offset lsb
    Req[9] = (offset>>8)&0xff; //offset msb
    Req[10] = length&0xff;      //readlen lsb
    Req[11] = (length>>8)&0xff;    //readlen msb
    Req[12] = 0x100 - (Req[4]+Req[5]+Req[6]+Req[7]+Req[8]+Req[9]+Req[10]+Req[11])&0xff;

    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
                                            DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
                                            Req, 13,
                                            history_buf, &dwResLen,
                                            timeout);
    if((wRet != 0) || (history_buf[6] != 0))
    {
        printf("IPMC_GetSensorHistory error!\n");
        return wRet;
    }

    return 0;
}

uint16_t	IPMI_GetCurRunTime( IPMI20_UDS_SESSION_T *pUDSSession, uint32_t *minutes,int timeout)
{
    uint32_t		dwResLen;
    uint16_t		wRet;
    uint8_t 		Res[10];

    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
					    NETFNLUN_IPMI_STORLEAD, CMD_GET_CURRUNTIME,
					    NULL, 0 ,
					    Res, &dwResLen,
					    timeout);
    if((wRet != 0) || (Res[0] != 0))
    {
    	printf("IPMI_GetCurRunTime failed! ccode = %d\n", Res[0]);
    	*minutes = 0;
    	return -1;
    }
    *minutes = (Res[4]<<24) | (Res[3]<<16) | (Res[2]<<8) | Res[1];
    return 0;
}

uint16_t	IPMC_GetCurRunTime( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr, uint32_t *minutes,int timeout)
{

	uint16_t 	wRet = 0;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50];
	uint32_t	dwResLen;
	

	//get title
	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_GET_CURRUNTIME;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 8,
											Res, &dwResLen,
											timeout);
    if((wRet != 0) || (Res[6] != 0))
	{
		printf("---> IPMC_GetCurRunTime failed! ccode = %d\n", Res[6]);
		*minutes = 0;
		return -1;
	}
    *minutes = (Res[10]<<24) | (Res[9]<<16) | (Res[8]<<8) | Res[7];
        
    return 0;
}

uint16_t	IPMI_SaveConfig( IPMI20_UDS_SESSION_T *pUDSSession,int timeout)
{
    uint32_t		dwResLen;
    uint16_t		wRet;
    uint8_t 		Res[10];

    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
					    NETFNLUN_IPMI_STORLEAD, CMD_SAVE_CONFIG,
					    NULL, 0 ,
					    Res, &dwResLen,
					    timeout);
    if((wRet != 0) || (Res[0] != 0))
    {
    	printf("IPMI_SaveConfig failed! ccode = %d\n", Res[0]);
    	return -1;
    }
    printf("IPMI_SaveConfig successful!\n");
    return 0;
}

uint16_t	IPMC_SaveConfig( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr,int timeout)
{

	uint16_t 	wRet = 0;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50];
	uint32_t	dwResLen;
	

	//get title
	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_SAVE_CONFIG;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 8,
											Res, &dwResLen,
											timeout);
    if((wRet != 0) || (Res[6] != 0))
	{
		printf("---> IPMC_SaveConfig failed! ccode = %d\n", Res[6]);
		return -1;
	}
    printf("IPMC_SaveConfig successful!\n");
    return 0;
}

uint16_t	IPMI_RestoreConfig( IPMI20_UDS_SESSION_T *pUDSSession,int timeout)
{
    uint32_t		dwResLen;
    uint16_t		wRet;
    uint8_t 		Res[10];

    wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession,  
					    NETFNLUN_IPMI_STORLEAD, CMD_RESTORE_CONFIG,
					    NULL, 0 ,
					    Res, &dwResLen,
					    timeout);
    if((wRet != 0) || (Res[0] != 0))
    {
    	printf("IPMI_RestoreConfig failed! ccode = %d\n", Res[0]);
    	return -1;
    }
    printf("IPMI_RestoreConfig successful!\n");
    return 0;
}

uint16_t	IPMC_RestoreConfig( IPMI20_UDS_SESSION_T *pUDSSession, uint8_t IpmbAddr,int timeout)
{

	uint16_t 	wRet = 0;
	uint8_t 	Req[10] = {0};
	uint8_t		Res[50];
	uint32_t	dwResLen;
	

	//get title
	Req[0] = 0x40;	//Track | channel 0
	Req[1] = IpmbAddr;
	Req[2] = NETFNLUN_IPMI_STORLEAD;
	Req[3] = 0x100 - (Req[1] + Req[2])&0xff;	//checksum1
	Req[4] = 0x20;
	Req[5] = 0x10;
	Req[6] = CMD_RESTORE_CONFIG;	
	Req[7] = 0x100 - (Req[4] + Req[5] + Req[6])&0xff;

	//dwResLen = sizeof(GetDevIDRes_T);
	wRet = LIBIPMI_Send_RAW_IPMI2_0_Command(pUDSSession, 
											DEFAULT_NET_FN_LUN, CMD_SEND_MSG,
											Req, 8,
											Res, &dwResLen,
											timeout);
    if((wRet != 0) || (Res[6] != 0))
	{
		printf("IPMC_RestoreConfig failed! ccode = %d\n", Res[6]);
		return -1;
	}
	printf("IPMC_RestoreConfig successful!\n");
    return 0;
}