/**************************************************************** **************************************************************** ** ** ** (C)Copyright 2005-2006, American Megatrends . ** ** ** ** All Rights Reserved. ** ** ** ** 6145-F, Northbelt Parkway, Norcross, ** ** ** ** Georgia - 30071, USA. Phone-(770)-246-8600. ** ** ** **************************************************************** ***************************************************************** * * Sel.c * Sel Command Handler * * Author: Bakka Ravinder Reddy * *****************************************************************/ #define ENABLE_DEBUG_MACROS 0 #include "SEL.h" #include "com_IPMI_Sensor.h" #include "SELRecord.h" #include //#include "Storlead_BMC_LIb.h" #include "Support.h" #include "main.h" #include #include "Api.h" /* Reserved bit macro definitions */ #define RESERVED_BITS_PARTIALADDSELENTRY 0xF0 //(BIT7 | BIT6 | BIT5 | BIT4) #if SEL_DEVICE == 1 /*** Local Definitions ***/ #define SEL_RECORD_SIZE 16 #define CLR_SEL_PASSWORD_STR_LEN 3 #define CLEAR_SEL_GET_STATUS 0x00 #define CLEAR_SEL_ACTION 0xaa #define SEL_ERASE_IN_PROGRESS 0x00 #define SEL_ERASE_COMPLETED 0x01 #define SEL_ALLOC_UNIT_SIZE 0x10 #define SEL_MAX_RECORD_SIZE 0x10 #define INVALID_RECORD_ID 0x00 #define OVERFLOW_FLAG 0x80 #define DELETE_SEL_SUPPORT 0x08 #define PARTIAL_ADD_SEL_SUPPORT 0x04 #define RESERVE_SEL_SUPPORT 0x02 #define GET_SEL_ALLOC_SUPPORT 0x01 #define NO_SUPPORT 0x00 #define STATUS_DELETE_SEL ((uint8_t)0xA5) #define SEL_ALMOST_FULL_PERCENTAGE 75 #define SEL_PARTIAL_ADD_REQUEST_MISC_BYTES 6 #define SEL_PARTIAL_ADD_CMD_MAX_LEN 22 #define SEL_INITIALIZED 0x01 #define SEL_UNINITIALIZED 0x00 #define PRE_CLK_SET 0x00 #define POST_CLK_SET 0x80 /*** Prototype Declaration ***/ static SELRec_T* GetNextSELEntry ( SELRec_T* rec); static SELRec_T* GetSELRec(uint16_t RecID); static uint8_t SELTimeClockSync(uint8_t Action); /*** Global variables ***/ /*** Module variables ***/ //SELRepository_T* m_sel; #define SENSOR_TYPE_EVT_LOGGING 0x10 /* System Event Message */ static uint8_t m_SysEventMsg [] = { 0x00, 0x00, //Record ID 0x02, //Record Type is System 0x00, 0x00, 0x00, 0x00, //TimeStamp 0x20, 0x00, //Generator ID is BMC IPMI_EVM_REVISION, SENSOR_TYPE_SYSTEM_EVENT, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF }; /*--------------------------------------- * GetSELInfo *---------------------------------------*/ int GetSELInfo ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { SELInfo_T* pSelInfo = ( SELInfo_T*) pRes; SELRepository_T* m_sel; m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; pSelInfo->RecCt = m_sel->NumRecords; pSelInfo->FreeSpace = (g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord - m_sel->NumRecords) * sizeof(SELRec_T); pSelInfo->AddTimeStamp = (m_sel->AddTimeStamp); pSelInfo->EraseTimeStamp =( m_sel->EraseTimeStamp); pSelInfo->CompletionCode = CC_NORMAL; pSelInfo->Version = SEL_VERSION; pSelInfo->OpSupport=NO_SUPPORT; if(g_BMCInfo.IpmiConfig.SELConfig.SELOverFlow == TRUE) { pSelInfo->OpSupport |= OVERFLOW_FLAG; } pSelInfo->OpSupport|= RESERVE_SEL_SUPPORT; pSelInfo->OpSupport|= GET_SEL_ALLOC_SUPPORT; pSelInfo->OpSupport|=PARTIAL_ADD_SEL_SUPPORT; pSelInfo->OpSupport|= DELETE_SEL_SUPPORT; return sizeof (SELInfo_T); } /*--------------------------------------- * GetSELAllocationInfo *---------------------------------------*/ int GetSELAllocationInfo( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { SELAllocInfo_T* pAllocInfo = ( SELAllocInfo_T*) pRes; SELRepository_T* m_sel; pAllocInfo->CompletionCode = CC_NORMAL; pAllocInfo->NumAllocUnits = MAX_SEL_RECORD; pAllocInfo->AllocUnitSize = (sizeof (SELRec_T)); m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; pAllocInfo->NumFreeAllocUnits = ((g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord - m_sel->NumRecords)); pAllocInfo->LargestFreeBlock = sizeof(SELRec_T); pAllocInfo->MaxRecSize = sizeof(SELRec_T); return sizeof(SELAllocInfo_T); } /*--------------------------------------- * ReserveSEL *---------------------------------------*/ int ReserveSEL ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { ReserveSELRes_T* pRsvSelRes = ( ReserveSELRes_T*) pRes; g_BMCInfo.IpmiConfig.SELConfig.SelReservationID++; if (0 == g_BMCInfo.IpmiConfig.SELConfig.SelReservationID) { g_BMCInfo.IpmiConfig.SELConfig.SelReservationID = 1; } pRsvSelRes->CompletionCode = CC_NORMAL; pRsvSelRes->ReservationID = g_BMCInfo.IpmiConfig.SELConfig.SelReservationID; g_BMCInfo.IpmiConfig.SELConfig.PartialAdd=0 ;//Addded for DR#30287 FlushIPMIToFlash(); return sizeof (ReserveSELRes_T); } /*--------------------------------------- * GetSELEntry *---------------------------------------*/ int GetSELEntry ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { SELRec_T* pSelRec; SELRec_T* pNextSelRec; GetSELReq_T* pGetSelReq = ( GetSELReq_T*) pReq; GetSELRes_T* pGetSelRes = ( GetSELRes_T*) pRes; uint16_t LastRecID = 0,FirstRecID = 0; SELRepository_T* m_sel = NULL; uint16_t NumRecords = 0; m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; NumRecords = m_sel->NumRecords; pGetSelRes->CompletionCode = CC_NORMAL; // if (pGetSelReq->ReservationID && g_BMCInfo.SELConfig.RsrvIDCancelled) // { // pGetSelRes->CompletionCode = CC_INV_RESERVATION_ID; // return sizeof (uint8_t); // } /* Check if the reservation IDs match */ if ((g_BMCInfo.IpmiConfig.SELConfig.SelReservationID != pGetSelReq->ReservationID) && ((0 != pGetSelReq->Offset) || (pGetSelReq->ReservationID != 0)) ) { pGetSelRes->CompletionCode = CC_INV_RESERVATION_ID; return sizeof (uint8_t); } if (0 == m_sel->NumRecords) { pGetSelRes->CompletionCode = CC_SEL_REC_NOT_PRESENT; return sizeof (uint8_t); } FirstRecID = m_sel->FirstRecID; LastRecID = m_sel->LastRecID; //printf("---> FirstRecID %d, LastRecID %d\n", FirstRecID, LastRecID); /* If ID == 0x0000 return first record */ if (0 == pGetSelReq->RecID) { pSelRec = GetSELRec(FirstRecID); if (0 == pSelRec) { printf("Warning: Not find SEL Record\n"); pGetSelRes->CompletionCode = CC_SEL_REC_NOT_PRESENT; return sizeof(uint8_t); } else { pNextSelRec = GetNextSELEntry (pSelRec); } if (0 == pNextSelRec) { pGetSelRes->NextRecID = 0xFFFF; } else { pGetSelRes->NextRecID = pNextSelRec->EvtRecord.hdr.ID; } pGetSelReq->RecID = FirstRecID; } else if (0xFFFF == pGetSelReq->RecID) { pSelRec = GetSELRec(LastRecID); if(0== pSelRec) { pGetSelRes->CompletionCode = CC_SEL_REC_NOT_PRESENT; return sizeof(uint8_t); } pGetSelRes->NextRecID = 0xFFFF; } pSelRec = GetSELRec(pGetSelReq->RecID); if (pSelRec == 0) { pGetSelRes->CompletionCode = CC_SEL_REC_NOT_PRESENT; return sizeof (uint8_t); } if(LastRecID == pGetSelReq->RecID) { pGetSelRes->NextRecID = 0xFFFF; } else { pNextSelRec = GetNextSELEntry (pSelRec); if (0 == pNextSelRec) { /*If the given SEL ID is the maximum SEL record ,then the next SEL ID will be the First SEL ID in case of Circular SEL Implementation */ if(g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord == NumRecords) { pGetSelRes->NextRecID = 0; } else { pGetSelRes->NextRecID = 0xFFFF; } } else { pGetSelRes->NextRecID = pNextSelRec->EvtRecord.hdr.ID; } } if ((0xff == pGetSelReq->Size) && (sizeof (SELEventRecord_T) >= pGetSelReq->Offset)) { pGetSelReq->Size = sizeof (SELEventRecord_T) - pGetSelReq->Offset; } // Check for the request bytes and offset not to exceed the actual size of the record else if ((pGetSelReq->Size > (sizeof(SELEventRecord_T))) || (pGetSelReq->Offset > (sizeof(SELEventRecord_T))) || (pGetSelReq->Size > ((sizeof(SELEventRecord_T))- pGetSelReq->Offset))) { pGetSelRes->CompletionCode = CC_PARAM_OUT_OF_RANGE; return sizeof (uint8_t); } memcpy(pGetSelRes + 1, (( uint8_t*)&pSelRec->EvtRecord) + pGetSelReq->Offset, pGetSelReq->Size); return sizeof(GetSELRes_T) + pGetSelReq->Size; } /*--------------------------------------- * LockedAddSELEntry with SEL locked *---------------------------------------*/ int LockedAddSELEntry ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { AddSELRes_T* pAddSelRes = ( AddSELRes_T*) pRes; SELRecHdr_T* pSelRec = ( SELRecHdr_T*) pReq; uint16_t index = 0; uint16_t NumRecords=0; // m_sel = ( SELRepository_T*)g_BMCInfo.pSEL; NumRecords = (( SELRepository_T*)g_BMCInfo.pSEL)->NumRecords; /* If we dont have enough space return invalid ID */ if (NumRecords >= g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord) { if (((( SELRepository_T*)g_BMCInfo.pSEL)->SELIndex == g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord)) { (( SELRepository_T*)g_BMCInfo.pSEL)->SELIndex = 0; } /*Reset the SEL OverFlow Flag in Circular SEL mode*/ g_BMCInfo.IpmiConfig.SELConfig.SELOverFlow = FALSE; } if((( SELRepository_T*)g_BMCInfo.pSEL)->LastRecID == 0xFFFE) { (( SELRepository_T*)g_BMCInfo.pSEL)->LastRecID = 0; } if( (( SELRepository_T*)g_BMCInfo.pSEL)->FirstRecID == 0xFFFE) { (( SELRepository_T*)g_BMCInfo.pSEL)->FirstRecID = 0; } if(NumRecords == g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord) { (( SELRepository_T*)g_BMCInfo.pSEL)->FirstRecID +=1; } /* time stamp for record type less than 0xE0*/ if (pSelRec->Type < 0xE0) { // The timestamp gets set if the hook is not present or if the hook returns -1 pSelRec->TimeStamp = GetSelTimeStamp (); } pSelRec->ID = ((( SELRepository_T*)g_BMCInfo.pSEL)->LastRecID) + 1; index = (( SELRepository_T*)g_BMCInfo.pSEL)->SELIndex ; memcpy (&(( SELRepository_T*)g_BMCInfo.pSEL)->SELRecord [index].EvtRecord , pSelRec, sizeof (SELEventRecord_T)); (( SELRepository_T*)g_BMCInfo.pSEL)->SELRecord [index].Valid = VALID_RECORD; (( SELRepository_T*)g_BMCInfo.pSEL)->SELRecord [index].Len = sizeof (SELEventRecord_T) + 2; if (( NumRecords < g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord)) { NumRecords = ++(( SELRepository_T*)g_BMCInfo.pSEL)->NumRecords; } /*Update the First SEL entry after clear SEL command*/ if( (( SELRepository_T*)g_BMCInfo.pSEL)->FirstRecID == 0) { (( SELRepository_T*)g_BMCInfo.pSEL)->FirstRecID = pSelRec->ID; } (( SELRepository_T*)g_BMCInfo.pSEL)->LastRecID += 1; (( SELRepository_T*)g_BMCInfo.pSEL)->SELIndex += 1; g_BMCInfo.IpmiConfig.SELConfig.LastEvtTS = (( SELRepository_T*)g_BMCInfo.pSEL)->AddTimeStamp = GetSelTimeStamp (); pAddSelRes->CompletionCode = CC_NORMAL; pAddSelRes->RecID = pSelRec->ID; FlushSELToFlash(); FlushIPMIToFlash(); return sizeof (AddSELRes_T); } /*--------------------------------------- * AddSELEntry *---------------------------------------*/ int AddSELEntry ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { int reslen = 0; reslen = LockedAddSELEntry(pReq, ReqLen, pRes); FlushSELToFlash(); return reslen; } /*--------------------------------------- * PartialAddSELEntry *---------------------------------------*/ int PartialAddSELEntry ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { PartialAddSELReq_T* pParAddSelReq = ( PartialAddSELReq_T*) pReq; PartialAddSELRes_T* pParAddSelRes = ( PartialAddSELRes_T*) pRes; uint16_t RecordID=0, ReservationID=0; uint8_t RecordOffset=0,Len=0; SELRepository_T* m_sel = ( SELRepository_T*)g_BMCInfo.pSEL; ReservationID = (uint16_t)(pParAddSelReq->LSBReservationID | ((uint16_t)pParAddSelReq->MSBReservationID << 8)); RecordID = (uint16_t)(((uint16_t)pParAddSelReq->MSBRecordID << 8) | pParAddSelReq->LSBRecordID); RecordOffset = (uint32_t)pParAddSelReq->Offset; Len = ReqLen; // /* Checks for the Valid Reservation ID */ // while(g_BMCInfo.SELConfig.RsrvIDCancelled) // { // if((ReservationID == 0) && (pParAddSelReq->Progress == 1) && (ReqLen == SEL_PARTIAL_ADD_CMD_MAX_LEN)) // break; // else // { // if(ReqLen < SEL_PARTIAL_ADD_REQUEST_MISC_BYTES) // { // pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; // return(sizeof(PartialAddSELRes_T)); // } // else // { // pParAddSelRes->CompletionCode = CC_INV_RESERVATION_ID; // pParAddSelRes->RecID = 0; // return(sizeof(PartialAddSELRes_T)); // } // } // } /* Check for the reserved bytes should b zero */ if ( 0 != (pParAddSelReq->Progress & RESERVED_BITS_PARTIALADDSELENTRY ) ) { pParAddSelRes->CompletionCode = CC_INV_DATA_FIELD; return sizeof(uint8_t); } if((pParAddSelReq->Progress>1)|| (pParAddSelReq->Offset>SEL_RECORD_SIZE)) { pParAddSelRes->CompletionCode = CC_PARAM_OUT_OF_RANGE; return(sizeof(PartialAddSELRes_T)); } else if(g_BMCInfo.IpmiConfig.SELConfig.PartialAdd==0) { if(((RecordOffset+(Len-SEL_PARTIAL_ADD_REQUEST_MISC_BYTES)==SEL_RECORD_SIZE)&&(pParAddSelReq->Progress!=1))|| (( RecordOffset+(Len-SEL_PARTIAL_ADD_REQUEST_MISC_BYTES)Progress==1))|| (RecordOffset+(Len-SEL_PARTIAL_ADD_REQUEST_MISC_BYTES)>SEL_RECORD_SIZE)) { pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; return(sizeof(PartialAddSELRes_T)); } } else if((ReservationID==0)&&(Len==SEL_PARTIAL_ADD_CMD_MAX_LEN)&&(pParAddSelReq->Progress!=1)) { pParAddSelRes->CompletionCode =CC_INV_DATA_FIELD; return(sizeof(PartialAddSELRes_T)); } /*Checking for reservation ID <Progress == 1) && (ReqLen == SEL_PARTIAL_ADD_CMD_MAX_LEN))) { if(g_BMCInfo.IpmiConfig.SELConfig.PartialAdd==0) { // Requirement says partial adds must start at 0, with no // gaps or overlaps. First request must be to RecordID = 0. if ((RecordID != 0) || (RecordOffset != 0)) { pParAddSelRes->CompletionCode = CC_INV_DATA_FIELD; return(sizeof(PartialAddSELRes_T));// Modified from sizeof (uint8_t); } memset((void *)&g_BMCInfo.IpmiConfig.SELConfig.SelPartialAddRecord, 0xFF, sizeof(SELEventRecord_T)); // Fill in the record ID into the partial add record. The // record ID is always the offset in memory of where the // SEL record starts (which includes a delete time first). RecordID = g_BMCInfo.IpmiConfig.SELConfig.SelPartialAddRecord.hdr.ID = m_sel->LastRecID +1; g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecordID=RecordID; g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset = 0; g_BMCInfo.IpmiConfig.SELConfig.PartialAdd=1; } else { if (RecordID != g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecordID) { pParAddSelRes->CompletionCode = CC_INV_DATA_FIELD; return sizeof (PartialAddSELRes_T); } } if (pParAddSelReq->Offset != g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset) { pParAddSelRes->CompletionCode = CC_INV_DATA_FIELD; return(sizeof(PartialAddSELRes_T)); } // Checking for Exceeding data values // if((g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset + Len - SEL_PARTIAL_ADD_REQUEST_MISC_BYTES) > SEL_MAX_RECORD_SIZE) { pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; return(sizeof(PartialAddSELRes_T)); } if((( g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset + Len - SEL_PARTIAL_ADD_REQUEST_MISC_BYTES) < SEL_MAX_RECORD_SIZE) && (pParAddSelReq->Progress == 1)) { pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; return(sizeof(PartialAddSELRes_T)); } if(((g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset + Len - SEL_PARTIAL_ADD_REQUEST_MISC_BYTES) == SEL_MAX_RECORD_SIZE) && (pParAddSelReq->Progress != 1)) { pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; return(sizeof(PartialAddSELRes_T)); } memcpy((void *)((uint8_t *)&g_BMCInfo.IpmiConfig.SELConfig.SelPartialAddRecord + RecordOffset), (void *)pParAddSelReq->RecordData, ((uint8_t)(Len - SEL_PARTIAL_ADD_REQUEST_MISC_BYTES))); g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecordID=RecordID; pParAddSelRes->RecID = RecordID; g_BMCInfo.IpmiConfig.SELConfig.PartialAddRecOffset += (Len - SEL_PARTIAL_ADD_REQUEST_MISC_BYTES); g_BMCInfo.IpmiConfig.SELConfig.PartialAdd=1; pParAddSelRes->CompletionCode = CC_NORMAL; //if the progress bit is 1 indicates that this is the last data of the record so put the entire record in sel repository if(pParAddSelReq->Progress==1) { // Checking for complete filling of gap if((pParAddSelReq->Offset + Len) == SEL_PARTIAL_ADD_CMD_MAX_LEN) { g_BMCInfo.IpmiConfig.SELConfig.PartialAdd=0; LockedAddSELEntry ( (uint8_t*)&g_BMCInfo.IpmiConfig.SELConfig.SelPartialAddRecord, sizeof(SELEventRecord_T), pRes); } else { pParAddSelRes->CompletionCode = CC_REQ_INV_LEN; return(sizeof(PartialAddSELRes_T)); } } } else { if(ReservationID != g_BMCInfo.IpmiConfig.SELConfig.SelReservationID) { pParAddSelRes->CompletionCode = CC_INV_RESERVATION_ID; return(sizeof(PartialAddSELRes_T)); } else { pParAddSelRes->CompletionCode = CC_INV_DATA_FIELD; return(sizeof(PartialAddSELRes_T)); } } FlushSELToFlash(); FlushIPMIToFlash(); return sizeof (PartialAddSELRes_T); } /*--------------------------------------- * DeleteSELEntry *---------------------------------------*/ int DeleteSELEntry ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { DeleteSELReq_T* pDelSelReq = ( DeleteSELReq_T*) pReq; DeleteSELRes_T* pDelSelRes = ( DeleteSELRes_T*) pRes; uint16_t LastRecID = 0,FirstRecID = 0; SELRepository_T* m_sel = NULL; SELRec_T *pRec = NULL, *pNextRec = NULL; m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; /* Check if the reservation IDs match */ if (((g_BMCInfo.IpmiConfig.SELConfig.SelReservationID != pDelSelReq->ReservationID) && (pDelSelReq->ReservationID != 0)) || (pDelSelReq->ReservationID == 0)) { pDelSelRes->CompletionCode = CC_INV_RESERVATION_ID; return sizeof (uint8_t); } LastRecID = m_sel->LastRecID; FirstRecID = m_sel->FirstRecID; if ( pDelSelReq->RecID == 0x0000 ) { pDelSelReq->RecID = FirstRecID ; } else if ( pDelSelReq->RecID == 0xFFFF ) { pDelSelReq->RecID = LastRecID; } pRec= GetSELRec(pDelSelReq->RecID); if ( pRec == 0 ||(pRec->Valid != VALID_RECORD) ) { pDelSelRes->CompletionCode = CC_SDR_REC_NOT_PRESENT; return sizeof (uint8_t); } //Update first record id after delete first sel entity. if(pDelSelReq->RecID == m_sel->FirstRecID) { pNextRec = GetNextSELEntry(pRec); if(pNextRec != NULL) { m_sel->FirstRecID = pNextRec->EvtRecord.hdr.ID; } else //No sel { m_sel->FirstRecID = 0; } } pRec->Valid = STATUS_DELETE_SEL; m_sel->NumRecords--; /*Update the Last Deleted SEL time*/ m_sel->EraseTimeStamp = GetSelTimeStamp (); // /*Update the First and last Record ID if the requested RecID is either First or Last*/ // FindRecOrder(); pDelSelRes->CompletionCode = CC_NORMAL; pDelSelRes->RecID = pDelSelReq->RecID; FlushSELToFlash(); FlushIPMIToFlash(); return sizeof (DeleteSELRes_T); } /*--------------------------------------- * ClearSEL *---------------------------------------*/ int ClearSEL ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { ClearSELReq_T* pClrSelReq = ( ClearSELReq_T*) pReq; ClearSELRes_T* pClrSelRes = ( ClearSELRes_T*) pRes; SELRepository_T* m_sel = NULL; m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; if (memcmp(pClrSelReq->CLR, "CLR", CLR_SEL_PASSWORD_STR_LEN)) { pClrSelRes->CompletionCode = CC_INV_DATA_FIELD; return sizeof (uint8_t); } if (pClrSelReq->InitOrStatus == CLEAR_SEL_GET_STATUS) { pClrSelRes->CompletionCode = CC_NORMAL; pClrSelRes->EraseProgress = SEL_ERASE_COMPLETED; return sizeof (ClearSELRes_T); } if (pClrSelReq->InitOrStatus != CLEAR_SEL_ACTION) { pClrSelRes->CompletionCode = CC_INV_DATA_FIELD; return sizeof (uint8_t); } /* Clear the fields of the SEL */ m_sel->LastRecID = 0; m_sel->FirstRecID = 0; m_sel->SELIndex = 0; m_sel->NumRecords = 0; memset (&m_sel->SELRecord [0], 0xFF, g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord * sizeof (SELRec_T)); /*Update the Last Deleted SEL time*/ g_BMCInfo.IpmiConfig.SELConfig.LastEvtTS = m_sel->EraseTimeStamp = GetSelTimeStamp (); pClrSelRes->CompletionCode = CC_NORMAL; pClrSelRes->EraseProgress = SEL_ERASE_COMPLETED; g_BMCInfo.IpmiConfig.SELConfig.SELOverFlow = FALSE; g_BMCInfo.IpmiConfig.SELConfig.selalmostfull = 0; FlushSELToFlash(); FlushIPMIToFlash(); return sizeof (ClearSELRes_T); } /*--------------------------------------- * GetSELTime *---------------------------------------*/ int GetSELTime ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { GetSELTimeRes_T* pGetSelTimeRes = ( GetSELTimeRes_T*) pRes; pGetSelTimeRes->CompletionCode = CC_NORMAL; pGetSelTimeRes->Time = (GET_SYSTEM_TIME_STAMP ()); return sizeof (GetSELTimeRes_T); } /** * @fn setUTC_Offset * @brief Set the UTC offset in the linux kernel. * @param[in] UTCOffset - Offset value in minutes. * @retval 0, on success. * 1, on failure. */ static int setUTC_Offset (int16_t UTCOffset) { int mins = 0, hrs = 0; if ((SEL_UTC_MIN_RANGE > UTCOffset) || (SEL_UTC_MAX_RANGE < UTCOffset) || (0 != (UTCOffset % 15))) { return 1; } hrs = UTCOffset / 60; mins = UTCOffset % 60; printf ("hrs : %d, mins : %d\n", hrs, mins); g_BMCInfo.IpmiConfig.SELTimeUTCOffset = UTCOffset; FlushIPMIToFlash(); return 0; } /*--------------------------------------- * SetSELTime *---------------------------------------*/ int SetSELTime ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { uint32_t localTime = 0; SetSELTimeReq_T* pSetSelTimeReq = ( SetSELTimeReq_T*) pReq; localTime = (pSetSelTimeReq->Time); SELTimeClockSync(PRE_CLK_SET); SET_SYSTEM_TIME_STAMP (&localTime); SELTimeClockSync(POST_CLK_SET); pRes [0] = CC_NORMAL; return sizeof (*pRes); } /*--------------------------------------- * GetSELTimeUTC_Offset *---------------------------------------*/ int GetSELTimeUTC_Offset ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { GetSELTimeUTCOffsetRes_T* pGetSelTimeUTCOffsetRes = ( GetSELTimeUTCOffsetRes_T*) pRes; pGetSelTimeUTCOffsetRes->CompletionCode = CC_NORMAL; pGetSelTimeUTCOffsetRes->UTCOffset = (g_BMCInfo.IpmiConfig.SELTimeUTCOffset); return sizeof (GetSELTimeUTCOffsetRes_T); } /*--------------------------------------- * SetSELTimeUTC_Offset *---------------------------------------*/ int SetSELTimeUTC_Offset ( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { SetSELTimeUTCOffsetReq_T* pSetSELTimeUTCOffsetReq = ( SetSELTimeUTCOffsetReq_T*) pReq; SetSELTimeUTCOffsetRes_T* pSetSELTimeUTCOffsetRes = ( SetSELTimeUTCOffsetRes_T*) pRes; int16_t UTCOffset; UTCOffset = (int16_t) (pSetSELTimeUTCOffsetReq->UTCOffset); if (((UTCOffset <= SEL_UTC_MAX_RANGE) && (UTCOffset >= SEL_UTC_MIN_RANGE)) || (UTCOffset == UNSPECIFIED_UTC_OFFSET)) { if (0 != setUTC_Offset ((UTCOffset == UNSPECIFIED_UTC_OFFSET) ? 0 : UTCOffset)) { pSetSELTimeUTCOffsetRes->CompletionCode = CC_INV_DATA_FIELD; return sizeof (*pRes); } pSetSELTimeUTCOffsetRes->CompletionCode = CC_NORMAL; } else { pSetSELTimeUTCOffsetRes->CompletionCode = CC_PARAM_OUT_OF_RANGE; } return sizeof (*pRes); } /*--------------------------------------- * GetAuxiliaryLogStatus *---------------------------------------*/ int GetAuxiliaryLogStatus( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { return 0; } /*--------------------------------------- * SetAuxiliaryLogStatus *---------------------------------------*/ int SetAuxiliaryLogStatus( uint8_t* pReq, uint8_t ReqLen, uint8_t* pRes) { return 0; } /*--------------------------------------- * GetNextSELEntry *---------------------------------------*/ static SELRec_T* GetNextSELEntry ( SELRec_T* rec) { SELRec_T* pRec = rec; SELRec_T* pLastRec = (((SELRepository_T*)g_BMCInfo.pSEL)->SELRecord + g_BMCInfo.IpmiConfig.SELConfig.MaxSELRecord - 1); pRec++; while (1) { if(pRec > pLastRec) { pRec = ((SELRepository_T*)g_BMCInfo.pSEL)->SELRecord; } if(pRec == rec) { break; } if (pRec->Valid == VALID_RECORD) { return pRec; } else if (pRec->Valid == STATUS_DELETE_SEL) { pRec++; } else { break; } } return 0; } /* @ fn GetSELRec @ brief This function is used to get the SEL Record based Record ID @ params RecID[in] Record ID BMCInst[in] @ returns SELRecord pointer on success and 0 on failures */ static SELRec_T* GetSELRec(uint16_t RecID) { int i=0; //int j; SELRepository_T* m_sel; m_sel = ( SELRepository_T*) g_BMCInfo.pSEL; for(i=0;iSELRecord[i]))[j]); // printf("\n"); if((m_sel->SELRecord[i].EvtRecord.hdr.ID == RecID) && (m_sel->SELRecord[i].Valid== VALID_RECORD)) { return &m_sel->SELRecord[i]; } } return 0; } /*--------------------------------------- * GetSelTimeStamp *---------------------------------------*/ uint32_t GetSelTimeStamp() { return (GET_SYSTEM_TIME_STAMP()); } #endif /* SEL_DEVICE */ /*--------------------------------------------------------------------------- * @fn SELTimeClockSync * * @brief This function is invoked when set SEL time, generate a pair of * events(pre and post clock setting) correlating the timestamps * for events occurring before and after the new clock value. * * @param Action - Specify pre-event or post-event. * @param BMCInst - Index of BMC instance. * * @return 0 - if success. * -1 - if error. *---------------------------------------------------------------------------*/ static uint8_t SELTimeClockSync(uint8_t Action) { SELEventRecord_T *EventRec = (SELEventRecord_T*)m_SysEventMsg; uint8_t pRes[sizeof(AddSELRes_T)]; EventRec->SensorNum = 0xFF; EventRec->EvtDirType = 0x6F; // Sensor Specific EventRec->EvtData1 = 0x05; // Offset 05h - Timestamp Clock Sync EventRec->EvtData2 = Action; EventRec->EvtData3 = 0xFF; LockedAddSELEntry((uint8_t*)EventRec, sizeof(SELEventRecord_T), pRes); return 0; } ///*--------------------------------------------------------------------------- // * @fn SetSELPolicy // * // * @brief This function is invoked when switch SEL policy, make appropriate // * adjustment for environment variables that related to SEL buffer. // * // * @param Policy - Specify Linear SEL policy or Circular SEL policy. // * @param BMCInst - Index of BMC instance. // *---------------------------------------------------------------------------*/ //void //SetSELPolicy(uint8_t Policy) //{ //// SELRepository_T* m_sel = NULL; // m_sel = (SELRepository_T*)g_BMCInfo.pSEL; // switch (Policy) // { // case LINEAR_SEL: // /* Reset LastRecID because GetNextSELEntry func will stop finding the next record if RecID >= LastRecRD, // but RecID may greater than LastRecID in Circular SEL mode. */ ///* LOCK_BMC_SHARED_MEM(BMCInst); // BMC_GET_SHARED_MEM (BMCInst)->m_LastRecID = m_sel->SELRecord[pBMCInfo->SELConfig.MaxSELRecord].EvtRecord.hdr.ID; // BMC_GET_SHARED_MEM (BMCInst)->m_SELIndex = m_sel->NumRecords; // BMC_GET_SHARED_MEM (BMCInst)->m_FirstRecID = m_sel->SELRecord[0].EvtRecord.hdr.ID; // UNLOCK_BMC_SHARED_MEM(BMCInst);*/ // break; // case CIRCULAR_SEL: // /*Update the Last and First Record ID when switch back to Circular-linear-Circular cycle */ //// if(m_sel->NumRecords == g_BMCInfo.SELConfig.MaxSELRecord) //// { //// FindRecOrder(); //// } // break; // } //}