* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "high_mem.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include "log_print.h"
* @brief : write to himem
* @param [in] : fd himem fd
* @param [in] : buffer msg written to himem
* @param [in] : len length of msg
* @return : ==LOG_FAILURE failure; ==LOG_SUCCESS success
*/
STATIC LogStatus HiMemWrite(int32_t fd, const char *buffer, size_t len)
{
ONE_ACT_ERR_LOG(fd <= 0, return LOG_FAILURE, "write failed. invalied fd.");
int32_t ret = (int32_t)write(fd, buffer, len);
ONE_ACT_ERR_LOG((ret < 0) || (ret != (int32_t)len),
return LOG_FAILURE, "write failed. ret = %d, errno :%d", ret, errno);
return LOG_SUCCESS;
}
* @brief : read from himem
* @param [in] : fd himem fd
* @param [in] : buffer msg read from himem
* @param [in] : len length of msg
* @return : ==LOG_FAILURE failure; >=0 success, return msg length
*/
STATIC int32_t HiMemRead(int32_t fd, char *buffer, size_t len)
{
ONE_ACT_ERR_LOG(fd <= 0, return LOG_FAILURE, "read failed, invalied fd.");
int32_t ret = (int32_t)read(fd, buffer, len);
if (ret < 0) {
return LOG_FAILURE;
}
return ret;
}
* @brief : init himem
* @param[out] : fd pointer to save himem fd
* @return : ==LOG_FAILURE failure; ==LOG_SUCCESS success
*/
LogStatus HiMemInit(int32_t *fd)
{
int32_t himemFd = open(HM_DRV_CHAR_DEV_USER_PATH, O_RDWR);
ONE_ACT_ERR_LOG(himemFd <= 0, return LOG_FAILURE, "open %s failed, errno :%d", HM_DRV_CHAR_DEV_USER_PATH, errno);
int32_t ret = ioctl(himemFd, HM_DRV_IOCTL_BIND_BLOCK, HM_DRV_BLOCK_TYPE_SLOG);
if (ret < 0) {
SELF_LOG_ERROR("bind himem failed. ret = %d, errno :%d", ret, errno);
(void)close(himemFd);
return LOG_FAILURE;
}
*fd = himemFd;
SELF_LOG_INFO("init himem fd success.");
return LOG_SUCCESS;
}
* @brief : free himem
* @param[out] : fd pointer to save himem fd
* @return : NA
*/
void HiMemFree(int32_t *fd)
{
if (*fd > 0) {
(void)close(*fd);
*fd = 0;
}
}
* @brief : construct himem log msg and write log msg
* @param[in] : fd himem fd
* @param[in] : buffer log msg
* @param[in] : len length of log msg
* @param[in] : type log type
* @return : ==LOG_FAILURE failure; >=0 success, return msg length
*/
STATIC int32_t HiMemWriteLog(int32_t fd, const char* buffer, uint32_t len, const LogHead *head)
{
HimemLogMsg logMsg;
errno_t err = memcpy_s(&logMsg.head, LOGHEAD_LEN, head, LOGHEAD_LEN);
ONE_ACT_ERR_LOG(err != EOK, return LOG_FAILURE, "memcpy failed. err = %d, errno :%d", err, errno);
err = memset_s(logMsg.msg, HIMEM_LOG_LENGTH, 0, HIMEM_LOG_LENGTH);
ONE_ACT_ERR_LOG(err != EOK, return LOG_FAILURE, "memset failed. err = %d, errno :%d", err, errno);
uint32_t msgLen = (len <= (HIMEM_LOG_LENGTH - 1U)) ? len : (HIMEM_LOG_LENGTH - 1U);
err = memcpy_s(logMsg.msg, HIMEM_LOG_LENGTH - 1U, buffer, msgLen);
ONE_ACT_ERR_LOG(err != EOK, return LOG_FAILURE, "memcpy failed. err = %d, errno :%d", err, errno);
return HiMemWrite(fd, (const char *)&logMsg, strlen(logMsg.msg) + LOGHEAD_LEN);
}
* @brief : read log msg from himem and parse log
* @param[in] : fd himem fd
* @param[out] : buffer log msg
* @param[in] : len read buffer length
* @param[out] : type log type
* @return : ==SYS_ERROR failure; >=0 success, return msg length
*/
STATIC int32_t HiMemReadLog(int32_t fd, char* buffer, size_t len, LogHead *head)
{
HimemLogMsg logMsg;
int32_t ret = HiMemRead(fd, (char *)&logMsg, sizeof(HimemLogMsg));
ONE_ACT_INFO_LOG(ret == 0, return 0, "read log length equal 0. ret = %d, errno :%d", ret, errno);
ONE_ACT_ERR_LOG((ret < 0) || (ret < (int32_t)LOGHEAD_LEN), return SYS_ERROR,
"read log length less then log size. ret = %d, errno :%d", ret, errno);
errno_t err = memset_s(buffer, len, 0, len);
ONE_ACT_ERR_LOG(err != EOK, return SYS_ERROR, "memset failed. err = %d, errno :%d", err, errno);
err = memcpy_s(buffer, len, logMsg.msg, (size_t)(long)ret - LOGHEAD_LEN);
ONE_ACT_ERR_LOG(err != EOK, return SYS_ERROR, "memcpy failed. err = %d, errno :%d", err, errno);
err = memcpy_s(head, LOGHEAD_LEN, &logMsg.head, LOGHEAD_LEN);
ONE_ACT_ERR_LOG(err != EOK, return SYS_ERROR, "memcpy failed. err = %d, errno :%d", err, errno);
return ret - (int32_t)LOGHEAD_LEN;
}
* @brief : write log msg from iambuf to himem
* @param[in] : fd himem fd
* @param[in] : logBuf iam log msg
* @return : ==SYS_ERROR failure; ==SYS_OK success
*/
int32_t HiMemWriteIamLog(int32_t fd, RingBufferStat *logBuf)
{
ONE_ACT_ERR_LOG(fd <= 0, return SYS_ERROR, "[input] fd=%d is invalid.", fd);
ONE_ACT_ERR_LOG(((logBuf == NULL) || (logBuf->ringBufferCtrl == NULL)), return SYS_ERROR, "no log write to himem.");
uint32_t count = 0;
RingBufferCtrl *ringBufferCtrl = logBuf->ringBufferCtrl;
int readRes = 0;
static ReadContext readContext = { 0U, 0U, 0U };
if (readContext.readIdx == 0U) {
LogBufReStart(logBuf->ringBufferCtrl, &readContext);
}
char buf[MSG_LENGTH];
LogHead msgRes;
while (true) {
readRes = LogBufRead(&readContext, ringBufferCtrl, buf, MSG_LENGTH, &msgRes);
if (readRes < 0) {
NO_ACT_ERR_LOG((readRes != (-(int32_t)BUFFER_READ_FINISH)),
"HiMemWriteIamLog read err res = %d check", readRes);
break;
}
if (readContext.lostCount != 0) {
NO_ACT_ERR_LOG((readContext.lostCount != 0), "LogBufRead lost = %lu check", readContext.lostCount);
readContext.lostCount = 0;
}
if (HiMemWriteLog(fd, buf, (uint32_t)msgRes.msgLength, &msgRes) == SYS_ERROR) {
count++;
}
}
NO_ACT_WARN_LOG(count > 0, "write log to himem loss %u log.", count);
return SYS_OK;
}
* @brief : read log msg frmm himem to iambuf
* @param[in] : fd himem fd
* @param[out] : logBuf iam log msg
* @return : ==0 failure; >=0 success
*/
uint32_t HiMemReadIamLog(int32_t fd, RingBufferStat *logBuf)
{
ONE_ACT_ERR_LOG(fd <= 0, return 0, "[input] fd=%d is invalid.", fd);
if ((logBuf == NULL) || (logBuf->ringBufferCtrl == NULL)) {
return 0;
}
LogHead head;
char msg[MSG_LENGTH];
RingBufferCtrl *ringBufferCtrl = logBuf->ringBufferCtrl;
uint32_t counts = 0;
while (true) {
int32_t len = HiMemReadLog(fd, msg, MSG_LENGTH, &head);
if (len <= 0) {
break;
}
head.msgLength = (uint16_t)len;
int32_t writeRes = LogBufWrite(ringBufferCtrl, msg, &head, NULL);
NO_ACT_ERR_LOG(writeRes < 0, "HiMemReadIamLog fail %d", writeRes);
counts++;
}
SELF_LOG_INFO("read log node count: %u", counts);
return counts;
}