#include <string.h>
#include "OemSMMCmds.h"
#include "com_BmcType.h"
#include "main.h"
#include "Storlead.h"
#include "SensorMonitor.h"
#include "Sensor.h"
#include "com_IPMI_SDRRecord.h"
#include "SDR.h"
#include "SELRecord.h"
#include "driver.h"
#include "fcntl.h"
#include "Api.h"

int  Storlead_GetSysInfo(uint8_t* pReq, uint8_t ReqLen,  uint8_t* pRes)
{
	char Title[] = "系统信息";
	char Text[] = "模块名称:多端口光纤接口模块;FPGA型号:XC7VX690T;简介: ";
	int len = 0,remainLen = 0;
	uint16_t offset = (pReq[2]<<8) | pReq[1];
	int totalLen = 0;
	char *pStr = NULL;
	int reqLen = (pReq[4]<<8) | pReq[3];
	
	switch(pReq[0])
	{
	case 0:	//get Title
		while(Title[totalLen])
		{
			totalLen++;
		}
        //printf("title total len = %#x\n",totalLen);
		pStr = Title;
		break;
	case 1:
		while(Text[totalLen])
		{
			totalLen++;
		}
		//printf("text total len = %#x\n", totalLen);
		pStr = Text;
		break;
	default:
		*pRes = CC_PARAM_OUT_OF_RANGE;
		return 1;
	}
	
	*pRes= CC_NORMAL;

	if(offset > totalLen)
	{
		printf("Invalid offset: %#x\n", offset);
		*pRes= CC_PARAM_OUT_OF_RANGE;
		return 1;
	}
	
	if(reqLen == 0)	
	{
		len = totalLen - offset;
	}
	else
	{
		len = (reqLen > (totalLen-offset)) ? (totalLen-offset) : reqLen;
	}
	
	remainLen = totalLen - offset - len;
	*(pRes+1) = len&0xff;
    *(pRes+2) = (len>>8)&0xff;
	*(pRes+3) = remainLen&0xff;
    *(pRes+4) = (remainLen>>8)&0xff;
	
	memcpy(pRes+5, pStr+offset, len);

	// int i;
	// printf("Example 80h: ");
	// for(i=0;i<5+len;i++)
	// 	printf("%#x ", pRes[i]);
	// printf("\n");

	return 5+len;	
}

int  Storlead_GetSensorInfo(uint8_t* pReq, uint8_t ReqLen,  uint8_t* pRes)
{
	StorleadGetSensorInfoRes_T *pGetSensorInfoRes = (StorleadGetSensorInfoRes_T *)pRes;
    uint8_t*   		pValidSensor = NULL;
    uint16_t       	SensorIndex = pReq[0];
    SensorInfo_T    pSensor ;
    SenInfo_T       SensorInfo;
    uint8_t 		SensorIsSigned = FALSE;
    uint16_t 		SensorReading = 0;
    SensorSharedMem_T*    pSMSharedMem;
    SDRRecHdr_T*     	  pSDRRec;
    FullSensorRec_T*      FullSDR;
    CompactSensorRec_T*   CompSDR;
    int i = 0;
    int             totalsize;

    /* Get the Sensor Shared Memory */
    pSMSharedMem = (SensorSharedMem_T*)&g_BMCInfo.SensorSharedMem;

    if(g_BMCInfo.SenConfig.ValidSensorCnt == 0)
    {
        pGetSensorInfoRes->CompletionCode = OEMCC_SENSOR_INFO_EMPTY;
        printf("ValidSensorCnt is 0\n");
        return 1;
    }

    if(SensorIndex >= g_BMCInfo.SenConfig.ValidSensorCnt)
    {
        pGetSensorInfoRes->CompletionCode = CC_PARAM_OUT_OF_RANGE;
        printf("Invalid SenosrIndex %d\n", SensorIndex);
        return 1;
    }

    //pValidSensor = (uint8_t*)(pAMIGetSensorInfoRes+1);
    // for(i = 0; i < g_BMCInfo.SenConfig.ValidSensorCnt; i++)
    // {
        //SensorIndex = g_BMCInfo.SenConfig.ValidSensorList[i];
        pSensor = pSMSharedMem->SensorInfo[SensorIndex];

        /*Copy the SDR Header*/
        memcpy(&pGetSensorInfoRes->SensorInfo.hdr,pSensor.SDRRec,sizeof(SDRRecHdr_T));

        pGetSensorInfoRes->SensorInfo.SensorNumber = pSensor.SensorNumber;
        pGetSensorInfoRes->SensorInfo.SensorTypeCode = pSensor.SensorTypeCode;
        pGetSensorInfoRes->SensorInfo.EventTypeCode = pSensor.EventTypeCode;

        pGetSensorInfoRes->SensorInfo.Units1 = pSensor.Units1;
        pGetSensorInfoRes->SensorInfo.Units2 = pSensor.Units2;
        pGetSensorInfoRes->SensorInfo.Units3 = pSensor.Units3;

        pGetSensorInfoRes->SensorInfo.M_LSB = pSensor.M_LSB;
        pGetSensorInfoRes->SensorInfo.M_MSB_Tolerance = pSensor.M_MSB_Tolerance;
        pGetSensorInfoRes->SensorInfo.B_LSB = pSensor.B_LSB;
        pGetSensorInfoRes->SensorInfo.B_MSB_Accuracy = pSensor.B_MSB_Accuracy;
        pGetSensorInfoRes->SensorInfo.Accuracy_MSB_Exp = pSensor.Accuracy_MSB_Exp;
        pGetSensorInfoRes->SensorInfo.RExp_BExp = pSensor.RExp_BExp;

        pGetSensorInfoRes->SensorInfo.LowerNonCritical = pSensor.LowerNonCritical;
        pGetSensorInfoRes->SensorInfo.LowerCritical = pSensor.LowerCritical;
        pGetSensorInfoRes->SensorInfo.LowerNonRecoverable = pSensor.LowerNonRecoverable;
        pGetSensorInfoRes->SensorInfo.UpperNonCritical = pSensor.UpperNonCritical;
        pGetSensorInfoRes->SensorInfo.UpperCritical = pSensor.UpperCritical;
        pGetSensorInfoRes->SensorInfo.UpperNonRecoverable= pSensor.UpperNonRecoverable;
        pGetSensorInfoRes->SensorInfo.Settable_Readable_ThreshMask= pSensor.SettableThreshMask;

        pGetSensorInfoRes->SensorInfo.Flags = pSensor.EventFlags & 0xe0;
        if((pSensor.EventFlags & BIT5) != 0)
        {
            pGetSensorInfoRes->SensorInfo.SensorReading = 0;
        }

        SensorReading = pSensor.SensorReading;
        pGetSensorInfoRes->SensorInfo.SensorReading = 0;
        SensorIsSigned = ( 0 != (pSensor.InternalFlags & BIT1));

        if (THRESHOLD_SENSOR_CLASS  == pSensor.EventTypeCode)
        {
            pGetSensorInfoRes->SensorInfo.SensorReading = (SensorReading & 0x00FF);
            pGetSensorInfoRes->SensorInfo.ComparisonStatus = 0;
            if((pSensor.DeassertionEventEnablesByte2 & BIT6) == BIT6 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperNonRecoverable) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT5;
                }
            }
            if((pSensor.DeassertionEventEnablesByte2 & BIT5) == BIT5 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperCritical) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT4;
                }
            }
            if((pSensor.DeassertionEventEnablesByte2 & BIT4) == BIT4 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.UpperNonCritical) >= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT3;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT6) == BIT6 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerNonRecoverable) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT2;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT5) == BIT5 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerCritical) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT1;
                }
            }
            if((pSensor.AssertionEventEnablesByte2 & BIT4) == BIT4 )
            {
                if (CompareValues(SensorIsSigned, pGetSensorInfoRes->SensorInfo.SensorReading, pSensor.LowerNonCritical) <= 0)
                {
                    pGetSensorInfoRes->SensorInfo.ComparisonStatus |= BIT0;
                }
            }

            pGetSensorInfoRes->SensorInfo.ComparisonStatus &= ((pSensor.SettableThreshMask >>  8) & 0xFF);
            pGetSensorInfoRes->SensorInfo.OptionalStatus = 0;
            // For Threshold sensor, [7:6] - reserved. Returned as 1b. Ignore on read.
            pGetSensorInfoRes->SensorInfo.ComparisonStatus |= THRESHOLD_RESERVED_BIT;
        }
        else
        {
            pGetSensorInfoRes->SensorInfo.ComparisonStatus = (((uint8_t) (SensorReading & 0x00FF)) & ((uint8_t) (pSensor.SettableThreshMask & 0x00FF)) );
            pGetSensorInfoRes->SensorInfo.OptionalStatus   = (((uint8_t) (SensorReading >> 8)) & ((uint8_t) (pSensor.SettableThreshMask >> 8)) );
            // For Discrete sensor, [7] - reserved. Returned as 1b. Ignore on read.
            pGetSensorInfoRes->SensorInfo.OptionalStatus  |= DISCRETE_RESERVED_BIT;
        }

        if((pSensor.EventFlags & BIT7) == 0)
        {
            pGetSensorInfoRes->SensorInfo.AssertionEventByte1 = 0;
            pGetSensorInfoRes->SensorInfo.AssertionEventByte2 = 0;
            pGetSensorInfoRes->SensorInfo.DeassertionEventByte1 = 0;
            pGetSensorInfoRes->SensorInfo.DeassertionEventByte2 = 0;
        }
        if((pSensor.SensorCaps & BIT6) == 0)
        {
             pGetSensorInfoRes->SensorInfo.AssertionEventByte1    = (pSensor.AssertionHistoryByte1 & pSensor.AssertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.AssertionEventByte2    = (pSensor.AssertionHistoryByte2 & pSensor.AssertionEventEnablesByte2);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte1    = (pSensor.DeassertionHistoryByte1 & pSensor.DeassertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte2    = (pSensor.DeassertionHistoryByte2 & pSensor.DeassertionEventEnablesByte2);
        }
        else
        {
             pGetSensorInfoRes->SensorInfo.AssertionEventByte1    = (pSensor.AssertionEventOccuredByte1 & pSensor.AssertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.AssertionEventByte2    = (pSensor.AssertionEventOccuredByte2 & pSensor.AssertionEventEnablesByte2);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte1    = (pSensor.DeassertionEventOccuredByte1 & pSensor.DeassertionEventEnablesByte1);
             pGetSensorInfoRes->SensorInfo.DeassertionEventByte2    = (pSensor.DeassertionEventOccuredByte2 & pSensor.DeassertionEventEnablesByte2);
        }
        pSDRRec = GetSDRRec(pSensor.SDRRec->ID);
        if(pSensor.SDRRec->Type  == FULL_SDR_REC)       /*Full SDR*/
        {
            FullSDR = (FullSensorRec_T *)pSDRRec;
            pGetSensorInfoRes->SensorInfo.OwnerID = FullSDR->OwnerID;
            pGetSensorInfoRes->SensorInfo.OwnerLUN= FullSDR->OwnerLUN;
            pGetSensorInfoRes->SensorInfo.MaxReading = FullSDR->MaxReading;
            pGetSensorInfoRes->SensorInfo.MinReading = FullSDR->MinReading;
            pGetSensorInfoRes->SensorInfo.Linearization = FullSDR->Linearization;
            memset(pGetSensorInfoRes->SensorInfo.SensorName,0,MAX_ID_STR_LEN);
            strncpy(pGetSensorInfoRes->SensorInfo.SensorName,FullSDR->IDStr, MAX_ID_STR_LEN - (sizeof(FullSensorRec_T) - sizeof(SDRRecHdr_T) - FullSDR->hdr.Len));
        }
        else if(pSensor.SDRRec->Type == COMPACT_SDR_REC)   /*Compact SDR*/
        {
            CompSDR = (CompactSensorRec_T *)pSDRRec;
            pGetSensorInfoRes->SensorInfo.OwnerID = CompSDR->OwnerID;
            pGetSensorInfoRes->SensorInfo.OwnerLUN= CompSDR->OwnerLUN;
            pGetSensorInfoRes->SensorInfo.MaxReading = 0;
            pGetSensorInfoRes->SensorInfo.MinReading = 0;
            pGetSensorInfoRes->SensorInfo.Linearization = 0;
            memset(pGetSensorInfoRes->SensorInfo.SensorName,0,MAX_ID_STR_LEN);
            strncpy(pGetSensorInfoRes->SensorInfo.SensorName,CompSDR->IDStr, MAX_ID_STR_LEN - (sizeof(CompactSensorRec_T) - sizeof(SDRRecHdr_T) - CompSDR->hdr.Len));
        }
        //memcpy(pValidSensor,(uint8_t *)&SensorInfo,sizeof(SenInfo_T));
        //pValidSensor = pValidSensor + sizeof(SenInfo_T);
    //}

    pGetSensorInfoRes->CompletionCode = CC_NORMAL;
    //pAMIGetSensorInfoRes->Noofentries = g_BMCInfo.SenConfig.ValidSensorCnt;

    //totalsize = sizeof(AMIGetSensorInfoRes_T) + (sizeof(SenInfo_T) * 11/*g_BMCInfo.SenConfig.ValidSensorCnt*/);
    // printf("return %d :", totalsize);
    // for(i=0;i<sizeof(AMIGetSensorInfoRes_T) + (sizeof(SenInfo_T) * g_BMCInfo.SenConfig.ValidSensorCnt);i++)
    // 	printf("%#x ", pRes[i]);
    // printf("\n");

    return sizeof(StorleadGetSensorInfoRes_T);
}

int Storlead_AuthorVerify(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    AuthorVerify_T *pAuthorVerify = (AuthorVerify_T *)pReq;
    int i;

    printf("Storlead_AuthorVerify, username: %s, password: %s\n", pAuthorVerify->name, pAuthorVerify->password);
    for(i=0;i<MAX_USER_NUM;i++)
    {
        if(strcmp(g_BMCInfo.UserInfoTbl[i].UserName, pAuthorVerify->name) == 0)
        {
            if(strcmp(g_BMCInfo.UserInfoTbl[i].UserPassword, pAuthorVerify->password)==0)
            {
                *pRes = CC_NORMAL;
                return 1;
            }
            else
            {
                printf("Invalid password!\n");
                *pRes = CC_PASSWORD_TEST_FAILED;
                return 1;
            }
        }
    }

    printf("Invalid username!\n");
    *pRes = CC_PASSWORD_TEST_FAILED;
    return 1;
}

/*
    Req[0]: sensor number
    Req[1]: offset_lsb
    Req[2]: offset_msb
    Req[3]: readlen_lsb
    Req[4]: readlen_msb
    -----------------------
    Res[0]: ccode
    Res[1]: return len lsb
    Res[2]: return len msb
*/
int Storlead_GetSensorHistory(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    uint8_t *pSensorHistory = pRes+3;
    uint8_t  sensorNum = pReq[0];
    uint16_t offset = (pReq[2]<<8) | pReq[1];
    uint16_t len = (pReq[4]<<8) | pReq[3];
    uint16_t total_len = 480;
    *pRes= CC_NORMAL;
    
    if(offset >= total_len)
    {
        *pRes = CC_PARAM_OUT_OF_RANGE;
        return 1;
    }
    
    if(getSensorHistory(sensorNum, pSensorHistory) != 0)
    {
        *pRes = CC_PARAM_OUT_OF_RANGE;
        return 1;
    };
    
    
    if(len > (total_len - offset))
        len = total_len - offset;
    printf("Storlead_GetSensorHistory(): len = %d, offset = %d, total_len = %d\n", len, offset, total_len);
    
    *(pRes+1) = len&0xff;
    *(pRes+2) = (len>>8)&0xff;
    
    return len+3;   
}

int Storlead_GetFanInfo(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    *pRes = CC_NORMAL;
    
    //for test
    int i;
    for(i=0;i<FAN_NUMBERS;i++)
        gFanInfo[i].speed++;

    memcpy(pRes+1, (uint8_t*)gFanInfo, FAN_NUMBERS*sizeof(FanInfo_T));
    return FAN_NUMBERS*sizeof(FanInfo_T) + 1;   
}

int Storlead_SetFanInfo(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    uint8_t index = pReq[0];
    uint8_t mode = pReq[1];         //0: 自动， 1：手动
    uint8_t level = pReq[2];

    *pRes = CC_NORMAL;
    if(index >= FAN_NUMBERS)
    {
        printf("Invalid index %d\n", index);
        *pRes = CC_PARAM_OUT_OF_RANGE;
        return 1;
    }

    if(mode > 1)
    {
        printf("Invalid mode %d\n", mode);
        *pRes = CC_PARAM_OUT_OF_RANGE;
        return 1;
    }

    if(level > 100)
        level = 100;

    gFanInfo[index].mode = mode;

    if(mode == 1)
    {
        gFanInfo[index].level = level;
    }

    return 1;
}

/*
    Req[0]: ChassisManageEn
*/
int Storlead_getAllBladeStatus(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    int i, index;
    MsgPkt_T    ReqPkt;
    MsgPkt_T    ResPkt;
    pRes[0] = CC_NORMAL;

    //if(pReq[0] == 0)
    if(g_BMCInfo.isChMC == 0)
    {
        for(i=0;i<BLADE_NUMBERS;i++)
        {
            gBladeStatus[i].present = 0;
            gBladeStatus[i].healthStatus = 0;
            sprintf(gBladeStatus[i].bladeName, "---");
            gBladeStatus[i].slotID = 0;
            gBladeStatus[i].pwrStatus = 0;
        }

        //当前模块的信息
        if(g_BMCInfo.IndexInChassis < BLADE_NUMBERS)
        {
            gBladeStatus[g_BMCInfo.IndexInChassis].present = 1;
            gBladeStatus[g_BMCInfo.IndexInChassis].healthStatus = 1;
            memcpy(gBladeStatus[g_BMCInfo.IndexInChassis].bladeName, g_BMCInfo.BladeName, 31);
            gBladeStatus[g_BMCInfo.IndexInChassis].slotID = g_BMCInfo.SlotID;
            gBladeStatus[g_BMCInfo.IndexInChassis].pwrStatus = g_BMCInfo.PowerGoodFlag;
            gBladeStatus[g_BMCInfo.IndexInChassis].isChMC = 1;  //从模块不能管理机箱，网页内显示机箱的默认选中刀片。

        }
    }
    else
    {
        for(index=0;index<BLADE_NUMBERS;index++)
        {
            if(gChassisIPMBAddr[index] == 0x20) //chMC
            {
                gBladeStatus[index].present = 1;
                gBladeStatus[index].healthStatus = 1;
                memcpy(gBladeStatus[index].bladeName, g_BMCInfo.BladeName, 31);
                gBladeStatus[index].slotID = g_BMCInfo.SlotID;
                gBladeStatus[index].pwrStatus = g_BMCInfo.PowerGoodFlag;
                gBladeStatus[index].isChMC = 1;
                continue;
            }

            ReqPkt.NetFnLUN  = NETFNLUN_IPMI_STORLEAD;
            ReqPkt.Cmd       = CMD_GET_BLADE_INFO;
            ReqPkt.Size      = 0;

            if(0 == API_BridgeInternal(&ReqPkt, &ResPkt, gChassisIPMBAddr[index], PRIMARY_IPMB_CHANNEL))
            {
                // printf("RECV: ");
                // for(i=0;i<ResPkt.Size;i++)
                //     printf("%x ", ResPkt.Data[i]);
                // printf("\n");

                if(ResPkt.Data[0] == 0)
                {
                    gBladeStatus[index].present = 1;
                    gBladeStatus[index].healthStatus = ResPkt.Data[1];
                    memcpy(gBladeStatus[index].bladeName, &ResPkt.Data[2], 31);
                    gBladeStatus[index].slotID = ResPkt.Data[33];
                    gBladeStatus[index].pwrStatus = ResPkt.Data[34];
                    gBladeStatus[index].isChMC = 0;
                }
                else
                {
                    gBladeStatus[index].present = 0;
                    gBladeStatus[index].healthStatus = 0;
                    sprintf(gBladeStatus[index].bladeName, "---");
                    gBladeStatus[index].slotID = 0;
                    gBladeStatus[index].pwrStatus = 0;
                    gBladeStatus[index].isChMC = 0;
                }
            }
            else
            {
                gBladeStatus[index].present = 0;
                gBladeStatus[index].healthStatus = 0;
                sprintf(gBladeStatus[index].bladeName, "---");
                gBladeStatus[index].slotID = 0;
                gBladeStatus[index].pwrStatus = 0;
                gBladeStatus[index].isChMC = 0;
            }
        }

    }

    memcpy(pRes+1, gBladeStatus, (BLADE_NUMBERS*sizeof(BladeStatus_T)));
    return 1+(BLADE_NUMBERS*sizeof(BladeStatus_T));
}

int Storlead_RestoreFactorSettings(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    int i;
    pRes[0] = CC_NORMAL;
    //擦除Flash   IpmiConfig
    pthread_mutex_lock(&Flash_Mutex);
    sf_sector_erase(5, CONFIG_FLASH_START);
    pthread_mutex_unlock(&Flash_Mutex);

    return 1;
}

int Storlead_GetLanInfo(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    pRes[0] = CC_NORMAL;
    uint8_t index = pReq[0];
    if(index > 0)
    {
        pRes[0] = CC_PARAM_OUT_OF_RANGE;
        return 1;
    }

    //Update LanInfo
    char ip_buf[16];
    getip(ip_buf);
    g_BMCInfo.IpmiConfig.LanInfo[index].IPAddr[0] = ip2dec(ip_buf, 0);
    g_BMCInfo.IpmiConfig.LanInfo[index].IPAddr[1] = ip2dec(ip_buf, 1);
    g_BMCInfo.IpmiConfig.LanInfo[index].IPAddr[2] = ip2dec(ip_buf, 2);
    g_BMCInfo.IpmiConfig.LanInfo[index].IPAddr[3] = ip2dec(ip_buf, 3);

    char mask_buf[16];
    getnetmask(mask_buf);
    g_BMCInfo.IpmiConfig.LanInfo[index].NetMask[0] = ip2dec(mask_buf, 0);
    g_BMCInfo.IpmiConfig.LanInfo[index].NetMask[1] = ip2dec(mask_buf, 1);
    g_BMCInfo.IpmiConfig.LanInfo[index].NetMask[2] = ip2dec(mask_buf, 2);
    g_BMCInfo.IpmiConfig.LanInfo[index].NetMask[3] = ip2dec(mask_buf, 3);

    char broadcast_buf[16];
    getbroadcast(broadcast_buf);
    g_BMCInfo.IpmiConfig.LanInfo[index].BroadCast[0] = ip2dec(broadcast_buf, 0);
    g_BMCInfo.IpmiConfig.LanInfo[index].BroadCast[1] = ip2dec(broadcast_buf, 1);
    g_BMCInfo.IpmiConfig.LanInfo[index].BroadCast[2] = ip2dec(broadcast_buf, 2);
    g_BMCInfo.IpmiConfig.LanInfo[index].BroadCast[3] = ip2dec(broadcast_buf, 3);

    char mac_buf[18];
    getmac(mac_buf);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[0] = mac2hex(mac_buf, 0);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[1] = mac2hex(mac_buf, 1);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[2] = mac2hex(mac_buf, 2);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[3] = mac2hex(mac_buf, 3);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[4] = mac2hex(mac_buf, 4);
    g_BMCInfo.IpmiConfig.LanInfo[index].MACAddr[5] = mac2hex(mac_buf, 5);

    //TODO: get default GetWay

    memcpy(pRes+1, &g_BMCInfo.IpmiConfig.LanInfo[index], sizeof(LanInfo_T));

    return 1+sizeof(LanInfo_T);
}

/*
    Req[0]:     index
    Req[1]:     isSave      0:掉电不保存，1：掉电保存
    Req[2~n]:   LanInfo_T
*/
int Storlead_SetLanInfo(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    MsgPkt_T m_MsgPkt;
    uint8_t index = pReq[0];
    uint8_t isSave = pReq[1];
    LanInfo_T *pLanInfo = (LanInfo_T*)&pReq[2];
    

    if(index > 0)   //只有一张网卡，index只能是0
    {
        pRes[0] = CC_PARAM_OUT_OF_RANGE;
        return 1;
    }

    memcpy(&g_BMCInfo.IpmiConfig.LanInfo[index], pLanInfo, sizeof(LanInfo_T));

    m_MsgPkt.Param      = PARAM_LAN;
    m_MsgPkt.NetFnLUN   = NETFNLUN_IPMI_STORLEAD;
    m_MsgPkt.Cmd        = CMD_SET_LAN_INFO;
    m_MsgPkt.Size       = sizeof(LanInfo_T)+2;
    m_MsgPkt.Data[0]    = index;
    m_MsgPkt.Data[1]    = isSave;
    memcpy(&m_MsgPkt.Data[2], pLanInfo, sizeof(LanInfo_T));
    PostMsg(gPendActionIfc, &m_MsgPkt);
    
    pRes[0] = CC_NORMAL;
    return 1;
}

/*
    res[0]: completeCode
    res[1]: healthStatus;   //0: 未知（灰色） 1：健康（绿色） 2：警告（黄色）3：错误（红色）
    res[2-22]: bladeName[31];  //10个汉字或30个字符
    res[23]: slotID;         
    res[24]: pwrStatus;      //0：未上电（灰色）     1：已上电（绿色）
*/
int Storlead_GetBladeInfo(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    pRes[0] = CC_NORMAL;
    pRes[1] = g_BMCInfo.BladeHealthSta;
    memcpy(&pRes[2], g_BMCInfo.BladeName, 31);
    pRes[33] = g_BMCInfo.SlotID;
    pRes[34] = g_BMCInfo.PowerGoodFlag;

    return 35;
}

/*
    Req[0] : sensor number

*/
int Storlead_GetSensorName(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    int i;
    SensorInfo_T*           pSensorInfo;

    memset(pRes, 0, MAX_ID_STR_LEN+1);    
    for(i=0;i<SENSOR_NUMBERS;i++)
    {
        pSensorInfo = (SensorInfo_T *)&g_BMCInfo.SensorSharedMem.SensorInfo [i];
        if(pReq[0] == pSensorInfo->SensorNumber)
        {
            memcpy(&pRes[1], ((FullSensorRec_T*)pSensorInfo->SDRRec)->IDStr, MAX_ID_STR_LEN);
            break;
        }
    }

    return MAX_ID_STR_LEN+1;
}

int Storlead_GetCurRunTime(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    pRes[0] = CC_NORMAL;
    pRes[1] = g_BMCInfo.BootValidMinutes&0xff;        //LSB
    pRes[2] = (g_BMCInfo.BootValidMinutes>>8)&0xff;
    pRes[3] = (g_BMCInfo.BootValidMinutes>>16)&0xff;
    pRes[4] = (g_BMCInfo.BootValidMinutes>>24)&0xff;
    return 5;
}

int Storlead_SaveConfig(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    pRes[0] = CC_NORMAL;
    int i;
    iflash_t iflash_arg;
    int ret = 0;
    int fd = open("/dev/iflash", O_RDWR);
    ret = ioctl(fd, IFLASH_UNLOCK, NULL);
    if(ret != 0)
    {
        printf("error: ret = %d\n", ret);
    }

    iflash_arg.sector = 8;
    ret = ioctl(fd, IFLASH_ERASESECTOR, &iflash_arg);
    if(ret != 0)
    {
        printf("error: ret = %d\n", ret);
    }

    /**** IpmiConfig + user info + FRU + SDR ****/
    //IpmiConfig    4KB
    iflash_arg.address = 0x08080000;
    iflash_arg.len = sizeof(IPMIConfig_T);  //最大256字节
    memcpy(iflash_arg.data, &g_BMCInfo.IpmiConfig, sizeof(IPMIConfig_T));
    ret = ioctl(fd, IFLASH_WRITEBYTE, &iflash_arg);
    if(ret != 0)
    {
        printf("error: ret = %d\n", ret);
    }
    //user info     4KB
    uint8_t usrinfolen = 50;//sizeof(UserInfo_T);
    for(i=0;i<MAX_USER_NUM;i++)
    {
        iflash_arg.address = 0x08081000 + usrinfolen*i;//sizeof(UserInfo_T)*i;
        iflash_arg.len = usrinfolen;//sizeof(UserInfo_T);  //最大256字节
        memcpy(iflash_arg.data, &(g_BMCInfo.UserInfoTbl[i]), usrinfolen);
        ret = ioctl(fd, IFLASH_WRITEBYTE, &iflash_arg);
        if(ret != 0)
        {
            printf("error: ret = %d\n", ret);
        }
    }    
    //FRU           4KB
    iflash_arg.address = 0x08082000;
    iflash_arg.len = sizeof(OemFRUData_T);  //最大256字节
    memcpy(iflash_arg.data, &g_BMCInfo.FRU, sizeof(OemFRUData_T));
    ret = ioctl(fd, IFLASH_WRITEBYTE, &iflash_arg);
    if(ret != 0)
    {
        printf("error: ret = %d\n", ret);
    }
    //SDR           4KB
    uint32_t    sdrSize =
        sizeof(SDRRepository_T) + sizeof(HdrMgmtCtrlrDevLocator_T) + sizeof(HdrFullSensorRec_T)*SENSOR_NUMBERS;     
    uint32_t    writebytes = 0;
    while(sdrSize>0)
    {   
        iflash_arg.address = 0x08083000 + writebytes;
        if(sdrSize > 256)
        {            
            iflash_arg.len = 256;  //最大256字节                                
            memcpy(iflash_arg.data, g_BMCInfo.pSDR+writebytes, 256);
            // printf("L1: ");
            // for(i=0;i<iflash_arg.len;i++)
            //     printf("%02x ", iflash_arg.data[i]);
            // printf("\n"); 
            writebytes += 256;
            sdrSize -= 256;
        }
        else
        {
            iflash_arg.len = sdrSize;  //最大256字节                        
            memcpy(iflash_arg.data, g_BMCInfo.pSDR+writebytes, sdrSize);
            // printf("L2: ");
            // for(i=0;i<iflash_arg.len;i++)
            //     printf("%02x ", iflash_arg.data[i]);
            // printf("\n"); 
            writebytes += sdrSize;
            sdrSize = 0;
        }
        
        ret = ioctl(fd, IFLASH_WRITEBYTE, &iflash_arg);
        if(ret != 0)
        {
            printf("error: ret = %d\n", ret);
        }
    }

    ret = ioctl(fd, IFLASH_LOCK, NULL);
    if(ret != 0)
    {
        printf("error: ret = %d\n", ret);
    }
    
    close(fd);

    return 1;
}

int Storlead_RestoreConfig(uint8_t *pReq, uint8_t ReqLen, uint8_t *pRes)
{
    pRes[0] = CC_NORMAL;    
    int i;
    uint8_t buf[32] = {0};
    /**** IpmiConfig + user info + FRU + SDR ****/
    memcpy(buf, (uint8_t*)0x08080000, 32);
    if(strcmp(buf, FirstPowerOnStr) != 0)
    {
        printf("No invalid config data!\n");
        return 1;
    }



    //IpmiConfig    4KB
    memcpy(&g_BMCInfo.IpmiConfig, (uint8_t*)0x08080000, sizeof(IPMIConfig_T));
    FlushIPMIToFlash();
    //user info     4KB
    uint8_t usrinfolen = 50;
    for(i=0;i<MAX_USER_NUM;i++)
    {
        memcpy(&(g_BMCInfo.UserInfoTbl[i]), (uint8_t*)0x08081000 + usrinfolen*i, sizeof(UserInfo_T));
    }
    FlushUserInfoTbl();
    //FRU           4KB
    memcpy(&g_BMCInfo.FRU, (uint8_t*)0x08082000, sizeof(OemFRUData_T));
    FlushFRUToFlash();
    //SDR           4KB
    uint32_t    sdrSize =
        sizeof(SDRRepository_T) + sizeof(HdrMgmtCtrlrDevLocator_T) + 
        sizeof(HdrFullSensorRec_T)*SENSOR_NUMBERS;     
    memcpy(g_BMCInfo.pSDR, (uint8_t*)0x08083000, sdrSize);
    // printf("read: ");
    // for(i=0;i<sdrSize;i++)
    //     printf("%02x ", ((uint8_t*)0x08083000)[i]);
    // printf("\n"); 
    FlushSDRToFlash();
        
    return 1;
}