########## 已修改文件 diff (git diff) ########## diff --git a/app_util/storelib_unf/build/oob/Makefile b/app_util/storelib_unf/build/oob/Makefile index 15409ca..7c30b96 100755 --- a/app_util/storelib_unf/build/oob/Makefile +++ b/app_util/storelib_unf/build/oob/Makefile @@ -49,7 +49,12 @@ else CFLAGS=-D_DEBUG -DNFS_DBG_FILE -I$(INC_STORELIB) -I$(INC_MPI) -I$(LIN_INC) -I$(LIN_SRC) -I$(COM_INC) -I$(COM_SRC) -I$(INC_MPI) -I$(INC_INT) -I$(INC_MR_API) -I$(INC_I2C) -DSL_BMC_SUPPORTED -D__SL_I2C__ -DOS_LINUX -DSYSTEM_TYPE_LINUX -DUNIX -DLINUX -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -D_GNU_SOURCE -O -fPIC -pthread -Wall -Wextra -Werror -W -Wfloat-equal -Wpointer-arith -Wpacked -Winline -Wdisabled-optimization -Wformat -Wshadow -Wwrite-strings -Wcast-qual -ggdb3 -DDEBUG -DSLIR_DEBUG -Wa,--noexecstack endif -ifeq ($(shell test $(GCCVER) -lt 8; echo $$?),0) +# -mstructure-size-boundary is ARM32-only, has no aarch64 equivalent. +# aarch64 default alignment matches the legacy -fpack-struct=8 behavior for these +# protocol structs (verified: MCTP_I2C_HDR=4, no size change), so add nothing. +ifeq ($(shell $(CROSS_COMPILE)gcc -dumpmachine | grep -c aarch64),1) + # aarch64: no extra pack flag +else ifeq ($(shell test $(GCCVER) -lt 8; echo $$?),0) CFLAGS += -mstructure-size-boundary=8 else CFLAGS += -fpack-struct=8 @@ -67,7 +72,7 @@ INC_STORELIB=../../../common_storeLib_hdr LIB_NAME = libstorelibit.so.$(LIB_VER) LIBS=-lpthread -ldl -L$(SRC) -OBJS=slooblinux.o slcommon.o sldebug.o sloobaenregister.o sloobaenprocessor.o sltopology.o slitctrl.o slitpd.o slitscsi.o sloobevent.o slI2C.o transpI2CMsg.o slMCTP.o transpPCIeVDM.o +OBJS=slooblinux.o slcommon.o sldebug.o sloobaenregister.o sloobaenprocessor.o sltopology.o slitctrl.o slitpd.o slitscsi.o sloobevent.o slI2C.o transpI2CMsg.o slMCTP.o transpPCIeVDM.o slBmcOpenUbmcI2c.o ifeq ($(mode), pcie) ifeq ($(mctpflag), 1) @@ -152,6 +157,9 @@ transpI2CCustomMsg.o: $(INC_INT)/slooboem.h $(INC_INT)/transpI2CCustomMsg.h $(SR $(COMPILER) -g $(CFLAGS) $(MCTPFLAGS) $(MY_ARCH) -c $(SRC)/transpI2CCustomMsg.c +slBmcOpenUbmcI2c.o: $(INC_INT)/i2c_drvr.h $(INC_INT)/slBmcOpenUbmcI2c.h $(COM_INC)/slinternal.h $(SRC)/slBmcOpenUbmcI2c.c + $(COMPILER) -g $(CFLAGS) $(MCTPFLAGS) $(MY_ARCH) -c $(SRC)/slBmcOpenUbmcI2c.c + clean: rm -f $(OBJS) rm -f libstorelibit.so* diff --git a/app_util/storelib_unf/src/common/include/slinternal.h b/app_util/storelib_unf/src/common/include/slinternal.h index 3831c46..2845bda 100755 --- a/app_util/storelib_unf/src/common/include/slinternal.h +++ b/app_util/storelib_unf/src/common/include/slinternal.h @@ -414,12 +414,24 @@ extern int gCleanAENOnExit; //used from DllMain & fini //address of #define SL_ADDR_OF(s, f, l) ((U8 *)s->f + s->l) +// openUBMC: dump the data returned to the storage layer for boundary localization. +// Uses SL_DEBUG_ERROR so it is printed regardless of debug level. Helpers declared +// in slcommon.c (see SL_DumpRetData()). +#define SL_DUMP_RET_DATA(p, sz, fmt_str) \ + do { \ + U32 __n = (sz); \ + if ((__n) > 0 && (__n) <= 512 && (p) != NULL) \ + SL_DumpRetData(fmt_str, (U8 *)(p), __n); \ + } while (0) + #define SL_EXIT_FUNC(func) {if(gReturnStatus == SL_ERR_MCTP_CMDSTATUS_WRONG_STATE)retVal = SL_ERR_MCTP_CMDSTATUS_WRONG_STATE; \ else retVal = func;SLReleaseMutex(GetCtrlMutex(pCtrl)); DebugLog(SL_DEBUG_LEVEL_1, "%s: Exit cmdType = 0x%x, cmd = 0x%x, retVal = 0x%x", __FUNCTION__, plcp->cmdType, plcp->cmd, retVal); \ + SL_DUMP_RET_DATA(plcp->pData, plcp->dataSize, __FUNCTION__); \ return (retVal); } #define SL_EXIT_SYS_FUNC(func) { retVal = func; \ DebugLog(SL_DEBUG_LEVEL_1, "%s: Exit cmdType = 0x%x, cmd = 0x%X, retVal = 0x%X", __FUNCTION__, plcp->cmdType, plcp->cmd, retVal); \ + SL_DUMP_RET_DATA(plcp->pData, plcp->dataSize, __FUNCTION__); \ return (retVal); } #define BUFFER_SIZE 512 @@ -2064,6 +2076,9 @@ void DebugLog(U32 dbgLevel, char *format, ...); void DebugLog(U32 dbgLevel, const char *format, ...); #endif +// openUBMC: dump data returned to the storage layer (see SL_DUMP_RET_DATA) +void SL_DumpRetData(const char *tag, const U8 *data, U32 len); + void DebugHexDump(U32 DebugType, const char *dataName, const char *pData, int dataLength); U32 SendIoctl(U32 ctrlId, MFI_IOCTL *pMfiIoctl, U32 length); void FillDebugInfo(); diff --git a/app_util/storelib_unf/src/common/source/slcommon.c b/app_util/storelib_unf/src/common/source/slcommon.c index 818e8b2..52e570a 100755 --- a/app_util/storelib_unf/src/common/source/slcommon.c +++ b/app_util/storelib_unf/src/common/source/slcommon.c @@ -19,6 +19,8 @@ #include "transpPCIeVDM.h" #include "transpI2CMsg.h" #include "transpI2CCustomMsg.h" +#include "i2c_drvr.h" +#include "slBmcOpenUbmcI2c.h" #include "sloobaenregister.h" #endif @@ -7091,7 +7093,35 @@ U32 GetInterfaceType(CSLSystem* This) if (dllInstanceI2C == NULL) { DebugLog(SL_DEBUG_ERROR, "%s: Failed to load library slit_bmc_i2c.so library dlerror = %s", __FUNCTION__,dlerror()); - return SL_ERR_OOB_I2C_LIBRARY_LOAD_FAILED; + /* openUBMC: fall back to the built-in adapter when the BMC storage + * component has registered its I2C callbacks via RegisterI2CFunc(). */ + if (SlBmcOpenUbmcI2cReady()) + { + DebugLog(SL_DEBUG_INFO, "%s: Using built-in openUBMC I2C adapter.", __FUNCTION__); + pfni2cSendRecvMsg = i2cSendRecvMsg; + pfni2cInit = i2cInit; + pfni2cUnInit = i2cUnInit; + + if (SL_SUCCESS != (rval = pfni2cInit())) + { + DebugLog(SL_DEBUG_ERROR, "%s: ERROR Failed built-in I2C Init", __FUNCTION__); + } + else + { + DebugLog(SL_DEBUG_INFO, "%s: built-in I2C Init succeeded", __FUNCTION__); + This->m_TransportType = SL_OOB_TRANSPORT_TYPE_I2C; + /* openUBMC: CSLSystem_Initialize() is never called, so the MCTP + * VendorID default (0x1000, LSI/Avago) is never applied on the I2C + * path and requests go out with VendorID 0x0000, which the ctrl + * rejects with PE_INVALID_PARAM(0x93). Set it explicitly here, + * mirroring the PCIE path at the top of InitLibIT. */ + This->m_libParam.MCTP.VendorID = 0x1000; + } + } + else + { + return SL_ERR_OOB_I2C_LIBRARY_LOAD_FAILED; + } } else { @@ -7215,6 +7245,28 @@ U32 DecideFlashCommand(SL_LIB_CMD_PARAM_T *plcp) return retVal; } +// openUBMC: dump the data returned to the storage layer, hex in chunks. +void SL_DumpRetData(const char *tag, const U8 *data, U32 len) +{ + U8 chunk[128]; + U32 cpos = 0; + U32 i = 0; + + DebugLog(SL_DEBUG_ERROR, "># %s RET dataSize=0x%x [", tag, len); + for (i = 0; i < len; i++) + { + cpos += (U32)snprintf((char *)&chunk[cpos], sizeof(chunk) - cpos, "%02x ", data[i]); + if (cpos >= sizeof(chunk) - 4) + { + DebugLog(SL_DEBUG_ERROR, "># %s", chunk); + cpos = 0; + } + } + if (cpos > 0) + DebugLog(SL_DEBUG_ERROR, "># %s", chunk); + DebugLog(SL_DEBUG_ERROR, "># ]"); +} + U32 ProcessLibCommandIT(SL_LIB_CMD_PARAM_T *plcp) { U32 ctrlId = 0; diff --git a/app_util/storelib_unf/src/common/source/sldebug.c b/app_util/storelib_unf/src/common/source/sldebug.c index 6571ea3..38727a7 100755 --- a/app_util/storelib_unf/src/common/source/sldebug.c +++ b/app_util/storelib_unf/src/common/source/sldebug.c @@ -61,6 +61,11 @@ int CSLDebug_Initialize(CSLDebug* This) This->m_I2C_Delay_For_Config = DEFAULT_I2C_DELAY_FOR_CONFIG; This->m_I2C_Delay_For_Drive = DEFAULT_I2C_DELAY_FOR_DRIVE; This->m_I2C_Bmc_I2C_Address = DEFAULT_I2C_BMC_I2C_ADDRESS; + /* openUBMC: these were left uninitialized (0) when the INI file is missing, + * causing (maxReadDataSize-1) to underflow to 0xFFFF. Restore defaults. */ + This->m_I2CMaxWriteSize = DEFAULT_I2C_MAX_WRITE_SIZE; + This->m_I2CMaxReadSize = DEFAULT_I2C_MAX_READ_SIZE; + This->m_I2CMaxReadWriteSize = DEFAULT_I2C_MAX_READWRITE_SIZE; This->m_I2C_Fw_Events_Poll_Interval = DEFAULT_I2C_DELAY_FW_EVENT_POLLING; This->m_SCSI_INQ_Retry_Count = 0; diff --git a/app_util/storelib_unf/src/common/source/slitctrl.c b/app_util/storelib_unf/src/common/source/slitctrl.c index da95da4..95d70f3 100755 --- a/app_util/storelib_unf/src/common/source/slitctrl.c +++ b/app_util/storelib_unf/src/common/source/slitctrl.c @@ -14,6 +14,7 @@ #ifndef OS_ARMEFI #ifdef __linux__ #include +#include #endif #endif @@ -1553,7 +1554,25 @@ U32 GetCtrlInfoFunc(U32 ctrlId, MR_CTRL_INFO *pCtrlInfo) DebugLog(SL_DEBUG_ERROR, "%s: Memory alloc pMnfPage0 failed", __FUNCTION__); return SL_ERR_MEMORY_ALLOC_FAILED; } - rval = GetManufacturingPage0(ctrlId, &pMnfPage0); + // openUBMC: the device Manufacturing config page may not be initialized yet right + // after power-up (SL_CONFIG_PL_NOT_INITIALIZED). Retry a few times so the MPIO + // firmware has time to initialize the page, mirroring the legacy customized lib. + { + U32 retry = 0; + const U32 maxRetry = 10; + do { + rval = GetManufacturingPage0(ctrlId, &pMnfPage0); + if (rval == SL_SUCCESS) + break; + retry++; + if (rval == SL_CONFIG_PL_NOT_INITIALIZED) + { + DebugLog(SL_DEBUG_ERROR, "%s: GetManufacturingPage0 not initialized, retry %u/%u", + __FUNCTION__, retry, maxRetry); + sleep(2); /* give the firmware time to init the config page */ + } + } while (rval == SL_CONFIG_PL_NOT_INITIALIZED && retry < maxRetry); + } if(rval == SL_SUCCESS) { /* ########## 新增源码文件 (完整内容) ########## ===== NEW FILE: app_util/storelib_unf/src/oob/source/slBmcOpenUbmcI2c.c ===== ----- app_util/storelib_unf/src/oob/source/slBmcOpenUbmcI2c.c ----- /**************************************************************** * File : slBmcOpenUbmcI2c.c * Module : openUBMC built-in I2C adapter for StoreLib IT OOB * Description : Implements the slit_bmc_i2c.so entry points * (i2cInit/i2cUnInit/i2cSendRecvMsg) and the legacy * RegisterI2CFunc() registration entry. * * Semantics cloned from the legacy Huawei customized * storelib library (verified by disassembly): * - recvDataLen == 0 : call write callback * cb(channel, sendBuf, sendLen) * - recvDataLen != 0 : call write-read callback * cb(channel, sendBuf, sendLen, recvBuf, recvLen) * - retry up to "tries" times until callback returns 0 * - return 0x800B when the needed callback is missing * * The BMC side callback performs the whole SMBus * transaction (including PEC handling and read timing), * so this layer only forwards the buffers. ***************************************************************** * Copyright (c) 2026 openUBMC. All rights reserved *****************************************************************/ #include "types.h" #include "slerrors.h" #include "i2c_drvr.h" #include "slBmcOpenUbmcI2c.h" #include "slinternal.h" /* SL status returned when the required BMC callback is not registered yet. * Matches the legacy customized library behavior (0x800B). */ #define SL_ERR_I2C_CALLBACK_NOT_REGISTERED 0x800B static SL_BMC_I2C_WRITE_FUNC g_I2cWriteFunc = NULL; static SL_BMC_I2C_WRITEREAD_FUNC g_I2cWriteReadFunc = NULL; void RegisterI2CFunc(SL_BMC_I2C_WRITE_FUNC i2c_write_func, SL_BMC_I2C_WRITEREAD_FUNC i2c_writeread_func) { g_I2cWriteFunc = i2c_write_func; g_I2cWriteReadFunc = i2c_writeread_func; DebugLog(SL_DEBUG_ERROR, "%s: i2c_write_func = 0x%p, i2c_writeread_func = 0x%p", __FUNCTION__, (void *)i2c_write_func, (void *)i2c_writeread_func); } int SlBmcOpenUbmcI2cReady(void) { return (g_I2cWriteFunc != NULL) && (g_I2cWriteReadFunc != NULL); } U32 i2cInit(void) { return SL_SUCCESS; } U32 i2cUnInit(void) { return SL_SUCCESS; } U32 i2cSendRecvMsg(U8 appID, U8 channelAddr, U8 deviceAddr, U8 *pSendBuffer, U16 sendDataLen, U8 *pRecvBuffer, U16 recvDataLen, U8 tries, U8 timeoutMSec) { U8 attempt = 0; int ret = SL_ERR_I2C_CALLBACK_NOT_REGISTERED; (void)appID; (void)deviceAddr; (void)timeoutMSec; for (;;) { if (recvDataLen == 0) { if (g_I2cWriteFunc == NULL) { return SL_ERR_I2C_CALLBACK_NOT_REGISTERED; } ret = g_I2cWriteFunc(channelAddr, pSendBuffer, (U8)sendDataLen); } else { if (g_I2cWriteReadFunc == NULL) { return SL_ERR_I2C_CALLBACK_NOT_REGISTERED; } ret = g_I2cWriteReadFunc(channelAddr, pSendBuffer, (U8)sendDataLen, pRecvBuffer, (U8)recvDataLen); } attempt++; if (ret == 0) { return SL_SUCCESS; } if (attempt >= tries) { DebugLog(SL_DEBUG_ERROR, "%s: channel 0x%x failed after %d attempt(s), ret = 0x%x", __FUNCTION__, channelAddr, attempt, ret); return (U32)ret; } } } ===== NEW FILE: app_util/storelib_unf/src/oob/include/slBmcOpenUbmcI2c.h ===== ----- app_util/storelib_unf/src/oob/include/slBmcOpenUbmcI2c.h ----- /**************************************************************** * File : slBmcOpenUbmcI2c.h * Module : openUBMC built-in I2C adapter for StoreLib IT OOB * Description : openUBMC BMC(storage/sml) registers its I2C callbacks * through RegisterI2CFunc(). This adapter turns the SDK * i2cSendRecvMsg() calls into those registered callbacks, * so no external slit_bmc_i2c.so is needed. The behavior * matches the legacy Huawei customized storelib library. ***************************************************************** * Copyright (c) 2026 openUBMC. All rights reserved *****************************************************************/ #ifndef __SL_BMC_OPENUBMC_I2C_H__ #define __SL_BMC_OPENUBMC_I2C_H__ #include "types.h" /* Callback types registered by openUBMC storage component (sml). * Keep binary compatible with storage sml_base.h: * typedef gint32 (*I2C_WRITE_FUNC)(guint8 obj_index, guint8 *pWritebuf, guint8 write_length); * typedef gint32 (*I2C_WRITEREAD_FUNC)(guint8 obj_index, guint8 *pWritebuf, guint8 write_length, * guint8 *pReadbuf, guint8 read_length); */ typedef int (*SL_BMC_I2C_WRITE_FUNC)(U8 obj_index, U8 *pWritebuf, U8 write_length); typedef int (*SL_BMC_I2C_WRITEREAD_FUNC)(U8 obj_index, U8 *pWritebuf, U8 write_length, U8 *pReadbuf, U8 read_length); /* Exported entry for BMC storage component to register its I2C callbacks. */ void RegisterI2CFunc(SL_BMC_I2C_WRITE_FUNC i2c_write_func, SL_BMC_I2C_WRITEREAD_FUNC i2c_writeread_func); /* Returns non-zero when both callbacks have been registered. */ int SlBmcOpenUbmcI2cReady(void); #endif /* __SL_BMC_OPENUBMC_I2C_H__ */ ===== NEW FILE: build_openubmc_it.sh ===== ----- build_openubmc_it.sh ----- #!/bin/bash # Build StoreLib IT OOB library for openUBMC (aarch64) # Usage: ./build_openubmc_it.sh [CROSS_COMPILE_PREFIX] # default prefix: /opt/hcc_arm64le/bin/aarch64-target-linux-gnu- set -e CROSS=${1:-/opt/hcc_arm64le/bin/aarch64-target-linux-gnu-} SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" BUILD_DIR="$SCRIPT_DIR/app_util/storelib_unf/build/oob" OUT_DIR="$SCRIPT_DIR/output" LIB_VER="07.3800.0200.0000" cd "$BUILD_DIR" make clean make CROSS_COMPILE="$CROSS" cfg=release mode=i2c mkdir -p "$OUT_DIR" cp "libstorelibit.so.$LIB_VER" "$OUT_DIR/libraidblibit.so" echo "==== exported symbols check ====" "${CROSS}nm" -D "$OUT_DIR/libraidblibit.so" | grep -E "RegisterI2CFunc|ProcessLibCommandIT|SetInitDone|i2cSendRecvMsg|i2cInit|i2cUnInit" || true echo "==== output ====" ls -la "$OUT_DIR/libraidblibit.so" file "$OUT_DIR/libraidblibit.so" 2>/dev/null || "${CROSS}objdump" -f "$OUT_DIR/libraidblibit.so" | head -5