/* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * 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 FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <stdio.h>
#include <string.h>
#include "platform.h"
#include "utils/file_securec.h"
#include "sml.h"
#include "sml_errcodes.h"
#include "pd_log_process.h"
#include "sata_log.h"

#define PD_FARM_LOG_COLLECT_TIMEOUT (300 * 1000) // FARM Log日志数据收集的超时时间300s

#define PD_LOG_SATA_ERROR_LOG_MAX_SECTORS 1
#define PD_LOG_SATA_PHY_EVENT_LOG_MAX_SECTORS 1
#define PD_LOG_SATA_SEAGATE_GLIST_MAX_SECTORS 5
#define PD_LOG_SATA_SEAGATE_PLIST_MAX_SECTORS 1
#define PD_LOG_SATA_SEAGATE_CR_EVENT_MAX_SECTORS 20
#define PD_LOG_SATA_SEAGATE_FARM_MAX_SECTORS 192

#define PD_LOG_SATA_LOG_FILE "SATA_Log"

ATA_SMART_DISKSTATUS_DESC_S g_seagate_ce_log_desc[] = {
    {0x0, "recovered write"},
    {0x1, "IOEDC Error"},
    {0x2, "SMART trip    "},
    {0x3, "marked as BBM   "},
    {0x4, "data scrubbed   "},
    {0x5, "reallocated   "},
    {0x6, "wedge reallocated   "},
    {0x7, "reallocation failed  "},
    {0x8, "write BBM data scrubbed  "},
    {0x9, "write BBM reallocated"},
    {0xa, "write BBM wedge reallocated"},
    {0xb, "write BBM reallocation failed"},
    {0xc, "reset during command"},
    {0xd, "lube mitigation failure"},
    {0xe, "fast flush fail"},
    {0xf, "rewrite"},
    {0x10, "rewrite HC decreased"},
    {0x11, "rewrite HC increased"},
    {0x12, "virgin rewrite"},
    {0x13, "freefall unload"},
    {0x14, "freefall sensor status change"},
    {0x15, "ovly load fail"},
    {0x16, "ovly incompatible"},
    {0x17, "DCO capacity change"},
    {0x18, "SetMax capacity change"},
    {0x19, "reallocation write-verify failed"},
    {0x1a, "long seek event"},
    {0x24, "Bad read, recovered       "},
    {0x25, "Bad read, unrecovered     "},
    {0x103, "BGMS marked as BBM   "},
    {0x104, "BGMS data scrubbed"},
    {0x105, "BGMS reallocated"},
    {0x106, "BGMS wedge reallocated"},
    {0x107, "BGMS reallocation failed"},
    {0x108, "BGMS write BBM data scrubbed"},
    {0x109, "BGMS write BBM reallocated"},
    {0x10a, "BGMS write BBM wedge reallocated"},
    {0x10b, "BGMS write BBM reallocation failed"},
    {0x10f, "BGMS rewrite"},
    {0x119, "BGMS reallocation write-verify failed"},
    {0x11b, "BGMS dos rewrite"},
    {0x204, "RAW data scrubbed   "},
    {0x205, "RAW reallocated   "},
    {0x206, "RAW wedge reallocated"},
    {0x207, "RAW reallocation failed   "},
    {0x208, "RAW write BBM data scrubbed"},
    {0x209, "RAW write BBM reallocated"},
    {0x20a, "RAW write BBM wedge reallocated"},
    {0x20b, "RAW write BBM reallocation failed"},
    {0x20f, "RAW rewrite   "},
    {0x219, "RAW reallocation write-verify failed"}
};

/*
 * Description: 判断硬盘的model是否在farmlog的支持型号列表中
 * History: 1.2018年9月17日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
gint32 pd_log_check_farm_supported(PD_LOG_S *pd_log)
{
    if (pd_log == NULL) {
        debug_log(DLOG_ERROR, "%s invalid param", __FUNCTION__);
        return FALSE;
    }

    gchar *pd_model_supported[] = {"ST1000NM0055", "ST2000NM0055", "ST3000NM0005", "ST4000NM0035", "ST4000NM0115",
        "ST6000NM0115", "ST8000NM0055", "ST10000NM0086", "ST10000NM0478", "ST12000NM0008", "ST14000NM0018",
        "ST8000NC0002", "ST10000NM001G", "ST10000NM002B", "ST10000NM017B", "ST12000NM000J", "ST12000NM001G",
        "ST12000NM003J", "ST14000NM000J", "ST14000NM001G", "ST14000NM003J", "ST16000NM000J", "ST16000NM001G",
        "ST16000NM003J", "ST16000NM018J", "ST18000NM000J", "ST18000NM003J", "ST18000NM014J", "ST2000NM000A",
        "ST4000NM000A", "ST4000NM000B", "ST6000NM004B", "ST6000NM019B", "ST6000NM021A", "ST6000NM022A",
        "ST8000NM000A", "ST8000NM002A", "ST8000NM002B", "ST8000NM017B", "ST20000NM007D"};

    gint32 i;
    gint32 size = (gint32)GET_ARRAY_ITEMS(pd_model_supported);
    for (i = 0; i < size; i++) {
        if (NULL != strstr(pd_log->pd_model, pd_model_supported[i])) {
            return TRUE;
        }
    }
    return FALSE;
}

static gint32 pd_log_collect_seagate_sata_from_oob(guint8 ctrl_index, guint16 pd_device_id, PD_LOG_S *pd_log)
{
    /* 7. 收集Seagate SATA硬盘的Glist */
    pd_log->SATADevice.seagate_glist.log_type = PD_LOG_SATA_SEAGATE_GLIST;
    pd_log->SATADevice.seagate_glist.max_raw_data_size.sectors = PD_LOG_SATA_SEAGATE_GLIST_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.seagate_glist,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.seagate_glist.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 8. 收集Seagate SATA硬盘的Plist */
    pd_log->SATADevice.seagate_plist.log_type = PD_LOG_SATA_SEAGATE_PLIST;
    pd_log->SATADevice.seagate_plist.max_raw_data_size.sectors = PD_LOG_SATA_SEAGATE_PLIST_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.seagate_plist,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.seagate_plist.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    if (pd_log->pd_media_type == PD_MEDIA_TYPE_ROTATIONAL) {
        /* 9. 收集Seagate SATA HDD硬盘的Critical Event Log */
        pd_log->SATADevice.seagate_critical_event.log_type = PD_LOG_SATA_SEAGATE_CRITICAL_EVENT;
        pd_log->SATADevice.seagate_critical_event.max_raw_data_size.sectors =
            PD_LOG_SATA_SEAGATE_CR_EVENT_MAX_SECTORS;

        pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.seagate_critical_event,
            PD_LOG_COLLECT_TIMEOUT);
        if (pd_log->SATADevice.seagate_critical_event.result == SML_ERR_PD_SCSI_TIMEOUT) {
            return RET_OK;
        }

        /* 10. 收集Seagate SATA HDD硬盘的FARM Log */
        if (TRUE == pd_log_check_farm_supported(pd_log)) {
            pd_log->SATADevice.seagate_farm.log_type = PD_LOG_SATA_SEAGATE_FARM;
            pd_log->SATADevice.seagate_farm.max_raw_data_size.sectors = PD_LOG_SATA_SEAGATE_FARM_MAX_SECTORS;

            pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.seagate_farm,
                PD_FARM_LOG_COLLECT_TIMEOUT);
            if (pd_log->SATADevice.seagate_farm.result == SML_ERR_PD_SCSI_TIMEOUT) {
                return RET_OK;
            }
            pd_log->SATADevice.seagate_factory_farm.log_type = PD_LOG_SATA_SEAGATE_FACTORY_FARM;
            pd_log->SATADevice.seagate_factory_farm.max_raw_data_size.sectors = PD_LOG_SATA_SEAGATE_FARM_MAX_SECTORS;
            pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.seagate_factory_farm,
                PD_FARM_LOG_COLLECT_TIMEOUT);
            if (pd_log->SATADevice.seagate_factory_farm.result == SML_ERR_PD_SCSI_TIMEOUT) {
                return RET_OK;
            }
        }
    }

    return RET_OK;
}

/*
 * Description: 带外获取单个SATA盘的日志
 * 1. 收集原始数据，如果SCSI命令超时，则不再收集其它的日志;
 * 2. 每收集一种日志，检查系统是否发生重启或下电，如果是，则终止本次收集;
 * History: 1.2018年1月9日
 * 新生成函数
 * 2.2018年9月15日,
 * 新增FARM Log日志收集
 * 添加调用pd_log_collect_raw_data_from_obb函数的超时参数
 */
gint32 pd_log_collect_sata_from_oob(guint8 ctrl_index, guint16 pd_device_id, PD_LOG_S *pd_log)
{
    if (pd_log == NULL) {
        return RET_ERR;
    }

    /* 1. 收集SATA硬盘的SMART Attribute */
    pd_log->SATADevice.smart_attribute.log_type = PD_LOG_SATA_SMART_ATTRIBUTE;
    pd_log->SATADevice.smart_attribute.max_raw_data_size.sectors = PD_LOG_SATA_SMART_ATTR_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.smart_attribute,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.smart_attribute.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 2. 收集SATA硬盘的SMART Attribute Threshold */
    pd_log->SATADevice.smart_attribute_threshold.log_type = PD_LOG_SATA_SMART_ATTRIBUTE_THRESHOLD;
    pd_log->SATADevice.smart_attribute_threshold.max_raw_data_size.sectors = PD_LOG_SATA_SMART_ATTR_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.smart_attribute_threshold,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.smart_attribute_threshold.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 3. 收集SATA硬盘的SMART Error Log */
    pd_log->SATADevice.error.log_type = PD_LOG_SATA_ERROR;
    pd_log->SATADevice.error.max_raw_data_size.sectors = PD_LOG_SATA_ERROR_LOG_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.error, PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.error.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 4. 收集SATA硬盘的SMART Extent Error Log */
    pd_log->SATADevice.extent_error.log_type = PD_LOG_SATA_EXTENT_ERROR;
    pd_log->SATADevice.extent_error.max_raw_data_size.sectors = PD_LOG_SATA_EXTENT_ERROR_LOG_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.extent_error,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.extent_error.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 5. 收集SATA硬盘的SMART Extended Selftest Log */
    pd_log->SATADevice.extended_selftest.log_type = PD_LOG_SATA_EXTENDED_SELF_TEST;
    pd_log->SATADevice.extended_selftest.max_raw_data_size.sectors = PD_LOG_SATA_EXTENDED_SELF_TEST_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.extended_selftest,
        PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.extended_selftest.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    /* 6. 收集SATA硬盘的PHY Event */
    pd_log->SATADevice.phy_event.log_type = PD_LOG_SATA_PHY_EVENT;
    pd_log->SATADevice.phy_event.max_raw_data_size.sectors = PD_LOG_SATA_PHY_EVENT_LOG_MAX_SECTORS;

    pd_log_collect_raw_data_from_oob(ctrl_index, pd_device_id, &pd_log->SATADevice.phy_event, PD_LOG_COLLECT_TIMEOUT);
    if (pd_log->SATADevice.phy_event.result == SML_ERR_PD_SCSI_TIMEOUT) {
        return RET_OK;
    }

    if (strstr(pd_log->pd_manufacturer, PD_VENDOR_NAME_SEAGATE) != NULL) {
        return pd_log_collect_seagate_sata_from_oob(ctrl_index, pd_device_id, pd_log);
    }

    return RET_OK;
}

/*
 * Description: 添加event log到json对象中。
 */
static void pd_log_add_sata_event_log(ATA_SMART_CRITICALEVENT_ITEM_S item, Json *out_put_jso)
{
    Json *node_jso = NULL;
    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};

    if (JsonObjectCreate(&node_jso) != JSON_OK) {
        return;
    }
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%hu", item.POT);
    Json *str_obj = NULL;
    JsonStringCreate(tmp_str, &str_obj);
    JsonObjectItemSet(node_jso, "pot", str_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%x", item.type);
    Json *str_type_obj = NULL;
    JsonStringCreate(tmp_str, &str_type_obj);
    JsonObjectItemSet(node_jso, "type", str_type_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%08x", item.LBA);
    Json *str_lba_obj = NULL;
    JsonStringCreate(tmp_str, &str_lba_obj);
    JsonObjectItemSet(node_jso, "lba", str_lba_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%08x", item.R);
    Json *str_cylinder_obj = NULL;
    JsonStringCreate(tmp_str, &str_cylinder_obj);
    JsonObjectItemSet(node_jso, "cylinder", str_cylinder_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%04x", item.T);
    Json *str_head_obj = NULL;
    JsonStringCreate(tmp_str, &str_head_obj);
    JsonObjectItemSet(node_jso, "head", str_head_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%02x", item.Z);
    Json *str_sector_obj = NULL;
    JsonStringCreate(tmp_str, &str_sector_obj);
    JsonObjectItemSet(node_jso, "sector", str_sector_obj);

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%04x", item.index);
    Json *str_index_obj = NULL;
    JsonStringCreate(tmp_str, &str_index_obj);
    JsonObjectItemSet(node_jso, "index", str_index_obj);

    guint32 array_size = 0;
    JsonArraySizeGet(out_put_jso, &array_size);
    JsonArrayItemInsert(out_put_jso, array_size, node_jso);
    return;
}

/*
 * Description: 处理希捷sata盘的critical event数据
 * History: 1.2018年4月13日
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_critical_event(FILE *file, PD_LOG_S *pd_log, void *out_put,
    Json *pd_log_jso)
{
    guint32 i = 0;
    guint32 j = 0;
    gint32 find_flag = 0;
    gchar *desc = NULL;
    gchar  tmp_str[ATA_LOG_STRING_LENGTH] = {0};
    ATA_SMART_CRITICALEVENT_ITEM_S *item = NULL;
    Json *event_log_array = NULL;
    gint32 event_count = 0;

    if (NULL == pd_log || NULL == pd_log_jso) {
        return;
    }

    if (SML_SUCCESS != pd_log->SATADevice.seagate_critical_event.result ||
        NULL == pd_log->SATADevice.seagate_critical_event.data ||
        0 == pd_log->SATADevice.seagate_critical_event.data_length) {
        return;
    }

    item = (ATA_SMART_CRITICALEVENT_ITEM_S *)pd_log->SATADevice.seagate_critical_event.data;

    pd_log_fprintf(file, "  TYPE - Critical Event Type (Hex)       POT - Power On Time (Hours)\n"
        "  TS - Time Stamp (Ticks) (Hex)          EC - Error Code (Hex)\n"
        "  RT - Raw Temperature (Hex)             LBA - Block (Hex)\n"
        "  RTZ - Location (Radius-Theta-Z) (Hex)   CMD - ATA Command(Hex)\n\n"
        "Critical Event Log entries:\n");
    pd_log_fprintf(file,
        "TYPE Description                           POT   TS           LBA      CHS              EC       RT CMD "
        "Index\n"
        "---- ------------------------------        ----- ------------ -------- ---------------- -------- -- --- ---- "
        "\n");

    if (JsonArrayCreate(&event_log_array) != JSON_OK) {
        return;
    }

    for (j = 0; j < pd_log->SATADevice.seagate_critical_event.max_raw_data_size.sectors * ATA_LOG_SEAGATE_CE_NUM; j++) {
        if (item[j].index == 0) {
            continue;
        }

        find_flag = 0;

        for (i = 0; i < GET_ARRAY_ITEMS(g_seagate_ce_log_desc); i++) {
            if (item[j].type == g_seagate_ce_log_desc[i].status) {
                desc = g_seagate_ce_log_desc[i].desc;
                find_flag = 1;
                break;
            }
        }

        if (0 == find_flag) {
            desc = "Unknow                    ";
        }

        pd_log_format_time(item[j].timestamp, tmp_str, sizeof(tmp_str));
        pd_log_fprintf(file, "%4x %-37s %-5d %s %08x %08x-%04x-%02x %08x %02d %02x %04x\n", item[j].type, desc,
            item[j].POT, tmp_str, item[j].LBA, item[j].R, item[j].T, item[j].Z, item[j].EC, item[j].temp & 0x00FF,
            ((item[j].unknow2 & 0xff00) >> 8), item[j].index);
        event_count++;
        pd_log_add_sata_event_log(item[j], event_log_array);
    }

    (void)memset_s(tmp_str, ATA_LOG_STRING_LENGTH, 0, ATA_LOG_STRING_LENGTH);
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%d", event_count);
    Json *str_obj = NULL;
    JsonStringCreate(tmp_str, &str_obj);
    JsonObjectItemSet(pd_log_jso, "critical_event_count", str_obj);
    JsonObjectItemSet(pd_log_jso, "critical_event_log", event_log_array);
    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page0的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static gint32 pd_log_handle_sata_seagate_fram_page0(FILE *file, guint8 *data, void *out_put)
{
#define SEAGATE_FARM_LOG_SIGNATURE 0x00004641524D4552ULL

    if (NULL == data) {
        return RET_ERR;
    }

    ATA_SEAGATE_FARM_HEADER_S *header = (ATA_SEAGATE_FARM_HEADER_S *)data;

    /* 获取的数据最高字节为0xC0，无效数据，需要转为0x00后进行解析 */
    guint64 signature = header->signature & 0x00FFFFFFFFFFFFFFULL;

    /* 检查Signature是否匹配 */
    if (SEAGATE_FARM_LOG_SIGNATURE != signature) {
        pd_log_fprintf(file, "Invalid Signature = 0x%llX", signature);
        return RET_ERR;
    }

    pd_log_fprintf(file, "FARM Log :\n\tHeader :\n");
    pd_log_fprintf(file, "\t\tLog Signature : 0x%llX\n", signature);
    pd_log_fprintf(file, "\t\tMajor Revision : %lld\n", header->majorRev & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tMinor Revision : %lld\n", header->minorRev & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tPages Supported : %lld\n", header->pageNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLog Size : %lld\n", header->logSize & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tPage Size : %lld\n", header->pageSize & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHeads Supported : %lld\n", header->headSupport & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Copies : %lld\n", header->copiesNum & 0x00FFFFFFFFFFFFFFULL);

    return RET_OK;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page1的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_fram_page1(FILE *file, guint8 *data, void *out_put)
{
    gint32 i, j;
    gchar sn[9] = {0};
    gchar device_interface[9] = {0};
    gchar fw_rev[9] = {0};
    gchar *dp = NULL;

    if (NULL == data) {
        return;
    }

    ATA_SEAGATE_FARM_DRIVE_INFO_S *drive_info = (ATA_SEAGATE_FARM_DRIVE_INFO_S *)data;

    pd_log_fprintf(file, "\tDrive Information :\n");
    pd_log_fprintf(file, "\t\tCopy Number : %lld\n", drive_info->copyNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tPower On Hour : %lld\n", drive_info->powerOnHour & 0x00FFFFFFFFFFFFFFULL);

    /* 硬盘SN号 */
    sn[0] = drive_info->serialNumHi[1];
    sn[1] = drive_info->serialNumHi[0];
    sn[2] = drive_info->serialNumHi[3];
    sn[3] = drive_info->serialNumHi[2];
    sn[4] = drive_info->serialNumLow[1];
    sn[5] = drive_info->serialNumLow[0];
    sn[6] = drive_info->serialNumLow[3];
    sn[7] = drive_info->serialNumLow[2];
    sn[8] = '\0';
    pd_log_fprintf(file, "\t\tSerial Number : %s\n", sn);

    pd_log_fprintf(file, "\t\tWorld Wide Name : 0x%llX%llX\n", drive_info->wwnHi & 0x00000000FFFFFFFFULL,
        drive_info->wwnLow & 0x00000000FFFFFFFFUL);
    /* 硬盘接口类型，原始数据 A T A S 00 00 00 C0 或 S A S 00 00 00 00 C0，
        先将最高位C0转换为00，然后从后往前解析，遇到不为0x00的开始记录字符 */
    dp = drive_info->interfaceType;
    dp[7] = 0x00;
    j = 0;
    for (i = 7; i >= 0; i--) {
        if (dp[i] != 0x00) {
            device_interface[j] = dp[i];
            j++;
        }
    }
    device_interface[j] = '\0';
    pd_log_fprintf(file, "\t\tDevice Interface : %s\n", device_interface);

    pd_log_fprintf(file, "\t\tDevice Capacity in Sectors : %lld\n", drive_info->capacity & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tPhysical Sector Size : %lld\n", drive_info->pSectorSize & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLogical Sector Size : %lld\n", drive_info->lSectorSize & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tDevice Buffer Size : %lld\n", drive_info->bufferSize & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of heads : %lld\n", drive_info->headNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tDevice form factor : %lld\n", drive_info->formFactor & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tRotation Rate : %lld\n", drive_info->rotationRate & 0x00FFFFFFFFFFFFFFULL);

    /* Firmware Revision */
    fw_rev[0] = drive_info->fwRevHi[1];
    fw_rev[1] = drive_info->fwRevHi[0];
    fw_rev[2] = drive_info->fwRevHi[3];
    fw_rev[3] = drive_info->fwRevHi[2];
    fw_rev[4] = drive_info->fwRevLow[1];
    fw_rev[5] = drive_info->fwRevLow[0];
    fw_rev[6] = drive_info->fwRevLow[3];
    fw_rev[7] = drive_info->fwRevLow[2];
    fw_rev[8] = '\0';
    pd_log_fprintf(file, "\t\tFirmware Revision : %s\n", fw_rev);

    pd_log_fprintf(file, "\t\tATA Security State (ID Word 128) : %lld\n",
        drive_info->ataSecurityState & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tATA Features Supported (ID Word 78) : %lld\n",
        drive_info->ataFeaturesSupported & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tATA Features Enabled (ID Word 79) : %lld\n",
        drive_info->ataFeaturesEnabled & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpindle Power on hours : %lld\n", drive_info->spindlePowerOnHour & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHead Flight Hours : %lld\n", drive_info->headFlightHour & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHead Load Events : %lld\n", drive_info->headLoadEvent & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tPower Cycle count : %lld\n", drive_info->powerCycleCount & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHardware Reset count : %lld\n", drive_info->hardwareResetCount & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpin-up Time : %lld\n", drive_info->spinupTime & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNVC Status on Power-on : %lld\n", drive_info->NVCStatusPowerOn & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTime Available to save : %lld\n",
        drive_info->timeAvailableToSave & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTime Stamp (Milliseconds) start : %lld\n",
        drive_info->startTimeStamp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTime Stamp (Milliseconds) end : %lld\n",
        drive_info->endTimeStamp & 0x00FFFFFFFFFFFFFFULL);

    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page2的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_fram_page2(FILE *file, guint8 *data, void *out_put)
{
    if (NULL == data) {
        return;
    }

    ATA_SEAGATE_FARM_WORKLOAD_STAT_S *work_load = (ATA_SEAGATE_FARM_WORKLOAD_STAT_S *)data;

    pd_log_fprintf(file, "\tWork Load :\n");
    pd_log_fprintf(file, "\t\tCopy Number : %lld\n", work_load->copyNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tRated Workload Percentaged : %lld\n", work_load->ratedWP & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Number of Read Commands : %lld\n", work_load->readCmdNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Number of Write Commands : %lld\n", work_load->writeCmdNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Number of Random Read Cmds : %lld\n",
        work_load->rReadCmdNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Number of Random Write Cmds : %lld\n",
        work_load->rWriteCmdNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Number of Other Commands : %lld\n", work_load->otherCmdNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLogical Sectors Written : %lld\n", work_load->lSectorWritten & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLogical Sectors Read : %lld\n", work_load->lSectorRead & 0x00FFFFFFFFFFFFFFULL);

    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page3的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_fram_page3(FILE *file, guint8 *data, void *out_put)
{
    if (NULL == data) {
        return;
    }

    ATA_SEAGATE_FARM_ERROR_STAT_S *error = (ATA_SEAGATE_FARM_ERROR_STAT_S *)data;

    pd_log_fprintf(file, "\tError Information :\n");
    pd_log_fprintf(file, "\t\tCopy Number : %lld\n", error->copyNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tUnrecoverable Read Errors : %lld\n", error->unrecoverReadErrors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tUnrecoverable Write Errors : %lld\n",
        error->unrecoverWriteErrors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Reallocated Sectors : %lld\n",
        error->reallocatedSectors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Read Recovery Attempts : %lld\n",
        error->readRecoveryAttempts & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Mechanical Start Failures : %lld\n",
        error->mechanicalStartFailures & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Reallocated Candidate Sectors : %lld\n",
        error->reallocatedCandidateSectors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of ASR Events : %lld\n", error->ASREvents & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Interface CRC Errors : %lld\n",
        error->interfaceCRCErrors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpin Retry Count : %lld\n", error->spinRetryCount & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpin Retry Count Normalized : %lld\n",
        error->spinRetryCountNormalized & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpin Retry Count Worst : %lld\n", error->spinRetryCountWorst & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of IOEDC Errors (Raw) : %lld\n", error->IOEDCErrors & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tCTO Count Total : %lld\n", error->CTOTotal & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tCTO Count Over 5s : %lld\n", error->CTOOver5s & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tCTO Count Over 7.5s : %lld\n", error->CTOOver7_5s & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTotal Flash LED (Assert) Events : %lld\n", error->flashLEDEvents & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tFlash LED (Assert) Code and Address : %lld\n",
        error->flashLEDCodeAddress & 0x00FFFFFFFFFFFFFFULL);

    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page4的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_fram_page4(FILE *file, guint8 *data, void *out_put)
{
    if (NULL == data) {
        return;
    }

    ATA_SEAGATE_FARM_ENV_STAT_S *env = (ATA_SEAGATE_FARM_ENV_STAT_S *)data;

    pd_log_fprintf(file, "\tEnvironment :\n");
    pd_log_fprintf(file, "\t\tCopy Number : %lld\n", env->copyNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tCurrent Temperature : %lld\n", env->currentTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHighest Temperature : %lld\n", env->highestTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLowest Temperature : %lld\n", env->lowestTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tAverage Short Term Temperature : %lld\n", env->avgShortTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tAverage Long Term Temperatures : %lld\n", env->avgLongTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHighest Average Short Term Temperature : %lld\n",
        env->highestAvgShortTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLowest Average Short Term Temperature : %lld\n",
        env->lowestAvgShortTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHighest Average Long Term Temperature : %lld\n",
        env->highestAvgLongTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tLowest Average Long Term Temperature : %lld\n",
        env->lowestAvgLongTermTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTime In Over Temperature : %lld\n", env->overTempTime & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTime In Under Temperature : %lld\n", env->underTempTime & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpecified Max Operating Temperature : %lld\n",
        env->maxOperatTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSpecified Min Operating Temperature : %lld\n",
        env->minOperatTemp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tOver-Limit Shock Events Count(Raw) : %lld\n",
        env->overLimitShockEvents & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHigh Fly Write Count (Raw) : %lld\n", env->highFlyWriteCount & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tCurrent Relative Humidity : %.2f\n",
        (gfloat)(env->currentRelativeHumidity & 0x00FFFFFFFFFFFFFFULL) / 10);
    pd_log_fprintf(file, "\t\tHumidity Mixed Ratio : %.2f\n",
        (gfloat)(env->humidityMixedRatio & 0x00FFFFFFFFFFFFFFULL) / 8);
    pd_log_fprintf(file, "\t\tCurrent Motor Power : %lld\n", env->currentMotorPower & 0x00FFFFFFFFFFFFFFULL);

    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log page5的数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_fram_page5(FILE *file, guint8 *data, void *out_put)
{
    gint32 i;
    gint16 whole_part;
    guint32 decimal_part;
    gfloat decimal;
    gint32 array_size;

    if (NULL == data) {
        return;
    }

    ATA_SEAGATE_FARM_RELIA_STAT_S *relia = (ATA_SEAGATE_FARM_RELIA_STAT_S *)data;

    pd_log_fprintf(file, "\tReliability :\n");
    pd_log_fprintf(file, "\t\tCopy Number : %lld\n", relia->copyNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tTimestamp of last IDD test : %lld\n", relia->lastIDDTimeStamp & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSub-command of last IDD test : %lld\n", relia->lastIDDSubCmd & 0x00FFFFFFFFFFFFFFULL);

    /* 浮点数解析，整数部分5:4字节(带符号位)，小数部分3:0字节(得到的值除以10000) */
    array_size = (gint32)G_N_ELEMENTS(relia->discSlip);
    for (i = 0; i < array_size; i++) {
        whole_part = (gint16)((relia->discSlip[i] >> 32) & 0x000000000000FFFFULL);
        decimal_part = (guint32)(relia->discSlip[i] & 0x00000000FFFFFFFFULL);
        decimal = whole_part >= 0 ? (gfloat)whole_part + (gfloat)(decimal_part * 1.0 / 10000) :
                                    (gfloat)whole_part - (gfloat)(decimal_part * 1.0 / 10000);
        pd_log_fprintf(file, "\t\tDisc Slip in micro-inches by Head %d : %.4f\n", i, decimal);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->errorRateOfZone0);
    for (i = 0; i < array_size; i++) {
        whole_part = (gint16)((relia->errorRateOfZone0[i] >> 32) & 0x000000000000FFFFULL);
        decimal_part = (guint32)(relia->errorRateOfZone0[i] & 0x00000000FFFFFFFFULL);
        decimal = whole_part >= 0 ? (gfloat)whole_part + (gfloat)(decimal_part * 1.0 / 10000) :
                                    (gfloat)whole_part - (gfloat)(decimal_part * 1.0 / 10000);
        pd_log_fprintf(file, "\t\tBit Error Rate of Zone 0 by Head %d : %.4f\n", i, decimal);
    }

    pd_log_fprintf(file, "\t\tNumber of G-List Reclamations : %lld\n",
        relia->GListReclamationsNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tServo Status : %lld\n", relia->servoStatus & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tAlts List Entries Before IDD Scan : %lld\n",
        relia->altsListBeforeIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tAltz List Entries After IDD Scan : %lld\n",
        relia->altsListAfterIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tResident G-List Entries Before IDD Scan : %lld\n",
        relia->residentGlistBeforeIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tResident G-List Entries After IDD Scan : %lld\n",
        relia->residentGlistAfterIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tScrubs List Entries Before IDD Scan : %lld\n",
        relia->scrubsListBeforeIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tScrubs List Entries After IDD Scan : %lld\n",
        relia->scrubsListAfterIDD & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of DOS Scans Performed : %lld\n",
        relia->DOSScansPerformedNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of LBAs Corrected by ISP : %lld\n",
        relia->LBAsCorrectedByISPNum & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tNumber of Valid Parity Sectors : %lld\n",
        relia->validParitySectorsNum & 0x00FFFFFFFFFFFFFFULL);

    array_size = (gint32)G_N_ELEMENTS(relia->DOSWriteRefreshCount);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tDOS Write Refresh Count Head %d : %lld\n", i,
            relia->DOSWriteRefreshCount[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    pd_log_fprintf(file, "\t\tNumber of RAW Operations : %lld\n", relia->RAWOperationsNum & 0x00FFFFFFFFFFFFFFULL);

    array_size = (gint32)G_N_ELEMENTS(relia->DVGASkipWriteDetect);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tDVGA Skip Write Detect by Head %d : %lld\n", i,
            relia->DVGASkipWriteDetect[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->RVGASkipWriteDetect);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tRVGA Skip Write Detect by Head %d : %lld\n", i,
            relia->RVGASkipWriteDetect[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->FVGASkipWriteDetect);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tFVGA Skip Write Detect by Head %d : %lld\n", i,
            relia->FVGASkipWriteDetect[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->skipWriteDetectThred);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tSkip Write Detect Threshold Exceeded Head %d : %lld\n", i,
            relia->skipWriteDetectThred[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    pd_log_fprintf(file, "\t\tError Rate (SMART Attribute 1 Raw) : %lld\n",
        relia->errorRateRaw & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tError Rate (SMART Attribute 1 Normalized) : %lld\n",
        relia->errorRateNormalized & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tError Rate (SMART Attribute 1 Worst) : %lld\n",
        relia->errorRateWorst & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSeek Error Rate (SMART Attr 7 Raw) : %lld\n",
        relia->seekErrorRateRaw & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSeek Error Rate (SMART Attr 7 Normalized) : %lld\n",
        relia->seekErrorRateNormalized & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tSeek Error Rate (SMART Attr 7 Worst) : %lld\n",
        relia->seekErrorRateWorst & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tHigh Priority Unload Events (Raw) : %lld\n",
        relia->highPriorityUnloadEvents & 0x00FFFFFFFFFFFFFFULL);
    pd_log_fprintf(file, "\t\tMicro Actuator Lock-out accumulated : %lld\n",
        relia->microActuatorLockoutAccumulated & 0x00FFFFFFFFFFFFFFULL);

    array_size = (gint32)G_N_ELEMENTS(relia->ACFFSine1X);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tACFF Sine 1X for Head %d : %lld\n", i, relia->ACFFSine1X[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->ACFFCosine1X);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tACFF Cosine 1X for Head %d : %lld\n", i,
            relia->ACFFCosine1X[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->PZTCalibration);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tPZT Calibration for Head %d : %lld\n", i,
            relia->PZTCalibration[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->MRHeadResistance);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tMR Head Resistance from Head %d : %lld\n", i,
            relia->MRHeadResistance[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->TMDNum);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tNumber of TMD for Head %d : %lld\n", i, relia->TMDNum[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->velocityObserver);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tVelocity Observer by Head %d : %lld\n", i,
            relia->velocityObserver[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->velocityObserverNum);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tNumber of Velocity Observer by Head %d : %lld\n", i,
            relia->velocityObserverNum[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)(sizeof(relia->flyheightClearanceDelta) / (sizeof(relia->flyheightClearanceDelta[0][0]) * 3));
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tFly height clearance delta by Head %d inner : %lld\n", i,
            relia->flyheightClearanceDelta[i][1] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tFly height clearance delta by Head %d middle : %lld\n", i,
            relia->flyheightClearanceDelta[i][2] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tFly height clearance delta by Head %d outer : %lld\n", i,
            relia->flyheightClearanceDelta[i][0] & 0x00FFFFFFFFFFFFFFULL);
    }

    pd_log_fprintf(file, "\t\tNumber of Disc Slip Recalibrations Performed : %lld\n",
        relia->discSlipRecalibrationPerformed & 0x00FFFFFFFFFFFFFFULL);

    array_size = (gint32)(sizeof(relia->currentH2SATTrimmedMeanBitsInError) /
        (sizeof(relia->currentH2SATTrimmedMeanBitsInError[0][0]) * 3));
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT trimmed mean bits in error by Head %d inner : %lld\n", i,
            relia->currentH2SATTrimmedMeanBitsInError[i][1] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT trimmed mean bits in error by Head %d middle : %lld\n", i,
            relia->currentH2SATTrimmedMeanBitsInError[i][2] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT trimmed mean bits in error by Head %d outer : %lld\n", i,
            relia->currentH2SATTrimmedMeanBitsInError[i][0] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)(sizeof(relia->currentH2SATIterationsToConverge) /
        (sizeof(relia->currentH2SATIterationsToConverge[0][0]) * 3));
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT iterations to converge by Head %d inner : %lld\n", i,
            relia->currentH2SATIterationsToConverge[i][1] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT iterations to converge by Head %d middle : %lld\n", i,
            relia->currentH2SATIterationsToConverge[i][2] & 0x00FFFFFFFFFFFFFFULL);
    }
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT iterations to converge by Head %d outer : %lld\n", i,
            relia->currentH2SATIterationsToConverge[i][0] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->currentH2SATCodewordsAtIterationLevel);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT percentage of codewords at iteration level by Head %d : %lld\n", i,
            relia->currentH2SATCodewordsAtIterationLevel[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->H2SATAmplitude);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT amplitude by Head %d : %lld\n", i,
            relia->H2SATAmplitude[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    array_size = (gint32)G_N_ELEMENTS(relia->H2SATAsymmetry);
    for (i = 0; i < array_size; i++) {
        pd_log_fprintf(file, "\t\tCurrent H2SAT asymmetry by Head %d : %lld\n", i,
            relia->H2SATAsymmetry[i] & 0x00FFFFFFFFFFFFFFULL);
    }

    return;
}

/*
 * Description: 处理希捷SATA盘的FARM Log数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_farm(FILE *file, PD_LOG_S *pd_log, void *out_put)
{
    gint32 ret = 0;
    guint8 *data = NULL;
    /* 每个log_page的size为32个sector，每个sector为512字节 */
    const guint32 page_size = 32 * PD_BLOCK_SIZE_512;

    if (NULL == pd_log) {
        return;
    }

    if (SML_SUCCESS != pd_log->SATADevice.seagate_farm.result || NULL == pd_log->SATADevice.seagate_farm.data ||
        0 == pd_log->SATADevice.seagate_farm.data_length) {
        return;
    }

    data = pd_log->SATADevice.seagate_farm.data;

    ret = pd_log_handle_sata_seagate_fram_page0(file, data, out_put);
    if (RET_OK != ret) {
        return;
    }

    pd_log_handle_sata_seagate_fram_page1(file, data + page_size, out_put);

    pd_log_handle_sata_seagate_fram_page2(file, data + page_size * 2, out_put);

    pd_log_handle_sata_seagate_fram_page3(file, data + page_size * 3, out_put);

    pd_log_handle_sata_seagate_fram_page4(file, data + page_size * 4, out_put);

    pd_log_handle_sata_seagate_fram_page5(file, data + page_size * 5, out_put);

    return;
}

/*
 * Description: 处理希捷SATA盘FARM Log数据
 * History: 1.2018年9月15日, 			AR.SR.SFEA02130924.009.007
 * 新生成函数
 */
static void pd_log_handle_sata_seagate_farm_all(PD_LOG_S *pd_log)
{
    gint32 iRet = -1;
    gchar log_file[MAX_FILEPATH_LENGTH] = {0};
    FILE *fp_w = NULL;     // 解析日志文件指针
    gint32 ret = 0;
    guint8 rotate_num = 7;

    if (NULL == pd_log) {
        return;
    }

    /* 将DeviceName中的空格删除 */
    string_clear_blank(pd_log->pd_device_name, sizeof(pd_log->pd_device_name));

    /* 检查硬盘日志的路径 */
    if (RET_ERR == pd_log_check_file_path(pd_log->pd_device_name)) {
        debug_log(DLOG_ERROR, "Handle physical drive log failed, the log path is not exist.");
        return;
    }

    /* 拼接日志及原始数据的文件名 */
    iRet = snprintf_s(log_file, sizeof(log_file), sizeof(log_file) - 1, "%s/%s/%s", PD_LOG_BASE_PATH,
        pd_log->pd_device_name, PD_LOG_SEAGATE_FARM_LOG_FILE);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
        return;
    }

    /* 根据已转存文件及天数，更改日志及原始数据文件的后缀名 */
    check_log_file_rotate(log_file, NULL, rotate_num);

    /* 打开解析日志文件的指针 */
    fp_w = fopen_s(log_file, "w+", log_file);
    if (NULL == fp_w) {
        debug_log(DLOG_ERROR, "Open physical drive farm log file failed.");
        return;
    }
    (void)fchmod(fileno(fp_w), 0640);

    /* 写入解析日志的Header */
    pd_log_write_header(fp_w, pd_log);

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));

    /* 判断数据是否获取ok */
    ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.seagate_farm.result,
        pd_log->SATADevice.seagate_farm.scsi_status_code, pd_log->SATADevice.seagate_farm.data,
        pd_log->SATADevice.seagate_farm.data_length, PD_FARM_LOG_COLLECT_TIMEOUT);
    /* 如果数据获取不成功，将缓冲区错误信息同步到文件，关闭文件指针 */
    if (RET_OK != ret) {
        (void)fflush(fp_w);
        (void)fsync(fileno(fp_w));
        (void)fclose_s(fp_w);
        return;
    }

    /* 解析日志 */
    pd_log_handle_sata_seagate_farm(fp_w, pd_log, NULL);

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));
    (void)fclose_s(fp_w);

    return;
}

/*
 * Description: 处理SATA盘的日志数据，包括解析并输出到日志文件
 * History: 1.2018年1月10日
 * 新生成函数
 * 2.2018年4月13日,
 * 增加oob数据的日志解析 AR.SR.SFEA02130924.009.001
 * 3.2018年5月22日,              AR.SR.SFEA02130924.009.003
 * oob获取日志解析并删除原始数据打印
 * 4.2018年9月15日, 				AR.SR.SFEA02130924.009.007
 * 增加FARM Log日志解析，添加pd_log_check_raw_data的超时参数
 */
void pd_log_handle_sata(PD_LOG_S *pd_log, Json *pd_log_jso)
{
    gint32 iRet = -1;
    gchar log_file[MAX_FILEPATH_LENGTH] = {0};
    FILE *fp_w = NULL;
    gint32 ret = 0;
    struct stat file_stat;

    if (NULL == pd_log || NULL == pd_log_jso) {
        return;
    }

    /* 将DeviceName中的空格删除 */
    string_clear_blank(pd_log->pd_device_name, sizeof(pd_log->pd_device_name));

    /* 检查硬盘日志的路径 */
    if (RET_ERR == pd_log_check_file_path(pd_log->pd_device_name)) {
        debug_log(DLOG_ERROR, "Handle physical drive log failed, the log path is not exist.");
        return;
    }

    iRet = snprintf_s(log_file, sizeof(log_file), sizeof(log_file) - 1, "%s/%s/%s", PD_LOG_BASE_PATH,
        pd_log->pd_device_name, PD_LOG_SATA_LOG_FILE);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
    }

    fp_w = fopen_s(log_file, "w+", log_file);
    if (fp_w == NULL) {
        debug_log(DLOG_ERROR, "Open physical drive log file failed.");
        return;
    }

    (void)fchmod(fileno(fp_w), 0640);

    pd_log_write_header(fp_w, pd_log);

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));

    if (PD_POWER_STATE_ACTIVE != pd_log->pd_power_state) {
        g_fprintf(fp_w, "The drive is not active.\n");
        (void)fclose_s(fp_w);
        return;
    }

    g_fprintf(fp_w, "\nError Log:\n");
    ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.error.result, pd_log->SATADevice.error.scsi_status_code,
        pd_log->SATADevice.error.data, pd_log->SATADevice.error.data_length, PD_LOG_COLLECT_TIMEOUT);
    if (RET_OK == ret) {
        pd_log_handle_sata_error(fp_w, pd_log, NULL, pd_log_jso);
    }

    g_fprintf(fp_w, "\nExtent Error Log:\n");
    ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.extent_error.result,
        pd_log->SATADevice.extent_error.scsi_status_code, pd_log->SATADevice.extent_error.data,
        pd_log->SATADevice.extent_error.data_length, PD_LOG_COLLECT_TIMEOUT);
    if (RET_OK == ret) {
        pd_log_handle_sata_ext_error(fp_w, pd_log, NULL, pd_log_jso);
    }

    g_fprintf(fp_w, "\nExtended Self Test Log:\n");
    ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.extended_selftest.result,
        pd_log->SATADevice.extended_selftest.scsi_status_code, pd_log->SATADevice.extended_selftest.data,
        pd_log->SATADevice.extended_selftest.data_length, PD_LOG_COLLECT_TIMEOUT);
    if (RET_OK == ret) {
        pd_log_handle_sata_ext_self_test(fp_w, pd_log, NULL, pd_log_jso);
    }
    g_fprintf(fp_w, "\nPHY Event Log:\n");
    ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.phy_event.result,
        pd_log->SATADevice.phy_event.scsi_status_code, pd_log->SATADevice.phy_event.data,
        pd_log->SATADevice.phy_event.data_length, PD_LOG_COLLECT_TIMEOUT);
    if (RET_OK == ret) {
        pd_log_handle_sata_phy_event(fp_w, pd_log, NULL, pd_log_jso);
    }

    if (NULL != strstr(pd_log->pd_manufacturer, PD_VENDOR_NAME_SEAGATE)) {
        g_fprintf(fp_w, "\nGList (%s):\n", PD_VENDOR_NAME_SEAGATE);
        ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.seagate_glist.result,
            pd_log->SATADevice.seagate_glist.scsi_status_code, pd_log->SATADevice.seagate_glist.data,
            pd_log->SATADevice.seagate_glist.data_length, PD_LOG_COLLECT_TIMEOUT);
        if (RET_OK == ret) {
            if (0 == strcmp(pd_log->pd_model, "ST3750640NS") || 0 == strcmp(pd_log->pd_model, "ST3500630NS") ||
                0 == strcmp(pd_log->pd_model, "ST31000340NS") || 0 == strcmp(pd_log->pd_model, "ST3750330NS")) {
                g_fprintf(fp_w, "Invalid Grown Defect List data.");
            } else {
                pd_log_handle_sata_seagate_glist(fp_w, pd_log, NULL, pd_log_jso);
            }
        }

        g_fprintf(fp_w, "\nPList (%s):\n", PD_VENDOR_NAME_SEAGATE);
        ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.seagate_plist.result,
            pd_log->SATADevice.seagate_plist.scsi_status_code, pd_log->SATADevice.seagate_plist.data,
            pd_log->SATADevice.seagate_plist.data_length, PD_LOG_COLLECT_TIMEOUT);
        if (RET_OK == ret) {
            pd_log_handle_sata_seagate_plist(fp_w, pd_log, NULL, pd_log_jso);
        }

        if (PD_MEDIA_TYPE_ROTATIONAL == pd_log->pd_media_type) {
            g_fprintf(fp_w, "\nCritical Event Log (%s):\n", PD_VENDOR_NAME_SEAGATE);
            ret = pd_log_check_raw_data(fp_w, pd_log->SATADevice.seagate_critical_event.result,
                pd_log->SATADevice.seagate_critical_event.scsi_status_code,
                pd_log->SATADevice.seagate_critical_event.data,
                pd_log->SATADevice.seagate_critical_event.data_length, PD_LOG_COLLECT_TIMEOUT);
            if (RET_OK == ret) {
                if (0 == strcmp(pd_log->pd_model, "ST3750640NS") || 0 == strcmp(pd_log->pd_model, "ST3500630NS") ||
                    0 == strcmp(pd_log->pd_model, "ST31000340NS") || 0 == strcmp(pd_log->pd_model, "ST3750330NS")) {
                    g_fprintf(fp_w, "Invalid Critical Event Log data.");
                } else {
                    pd_log_handle_sata_seagate_critical_event(fp_w, pd_log, NULL, pd_log_jso);
                }
            }

            /* 处理FARM Log数据 */
            if (TRUE == pd_log_check_farm_supported(pd_log) && PD_LOG_SOURCE_BMA != pd_log->log_source) {
                pd_log_handle_sata_seagate_farm_all(pd_log);
            }
        }
    }

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));
    (void)fclose_s(fp_w);

    /* 单独处理SMART Attribute数据 */
    iRet = snprintf_s(log_file, sizeof(log_file), sizeof(log_file) - 1, "%s/%s/%s", PD_LOG_BASE_PATH,
        pd_log->pd_device_name, PD_LOG_SATA_SMART_ATTR_FILE);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
    }
    if (stat_s(log_file, &file_stat) >= 0) {
        check_log_file_rotate(log_file, NULL, pd_log->log_rotate_num);
    }

    fp_w = fopen_s(log_file, "w+", log_file);
    if (NULL == fp_w) {
        debug_log(DLOG_ERROR, "Open physical drive log file failed.");
        return;
    }

    (void)fchmod(fileno(fp_w), 0640);

    pd_log_write_header(fp_w, pd_log);

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));

    /* 解析SMART Attribute */
    pd_log_handle_sata_smart(fp_w, pd_log, NULL);

    (void)fflush(fp_w);
    (void)fsync(fileno(fp_w));
    (void)fclose_s(fp_w);

    return;
}

/*
 * Description: 创建亚健康信息日志文件文件并写入文件头
 */
LOCAL gint32 create_subhealthy_record_file(const gchar *log_file_name)
{
    if (log_file_name == NULL) {
        return RET_ERR;
    }

    // 创建文件
    FILE *fp = fopen_s(log_file_name, "w+", log_file_name);
    if (fp == NULL) {
        debug_log(DLOG_ERROR, "[%s]Create file failed", __FUNCTION__);
        return RET_ERR;
    }

    // 写入文件头
    g_fprintf(fp, "%-40s%-30s%-30s\n", "Timestamp,", "EstimatedRemainingLifespan,", "WriteAmplificationFactor");
    // 修改生成的文件权限为0640
    (void)fchmod(fileno(fp), 0640);

    // 强制刷新文件内容到存储设备上，否则异常掉电可能会导致文件内容没有写入
    (void)fflush(fp);
    (void)fsync(fileno(fp));
    (void)fclose_s(fp);

    return RET_OK;
}

/*
 * Description: subhealthy_record日志文件进行插入操作
 */
static gint32 subhealthy_log_buf_insert_record(gchar *buf, guint32 buf_size, guint32 *p_content_size,
    guint32 est_lfsp_value, guint32 write_amp_value)
{
    if (buf == NULL || buf_size == 0 || p_content_size == NULL) {
        debug_log(DLOG_ERROR, "%s: Invalid input parameter.", __FUNCTION__);
        return RET_ERR;
    }

    guint32 record_pos = *p_content_size;
    gchar cur_tm_stamp[PROP_VAL_LENGTH] = {0};
    gchar est_lfsp_str[PROP_VAL_LENGTH] = {0};
    gchar write_amp_str[PROP_VAL_LENGTH] = {0};
    gchar str_new_record[SUBHEALTHY_RECORD_CONTENT_SIZE] = {0};
    if (buf_size < *p_content_size) {
        debug_log(DLOG_ERROR, "%s: p_content_size greater than buf_size.", __FUNCTION__);
        return RET_ERR;
    }
    // 拼接需要插入的日志内容
    if (est_lfsp_value == STORAGE_INFO_INVALID_DWORD) {
        (void)snprintf_s(est_lfsp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "null,");
    } else if (est_lfsp_value == STORAGE_INFO_UNSUPPORT_DWORD) {
        (void)snprintf_s(est_lfsp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "--,");
    } else {
        (void)snprintf_s(est_lfsp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "%u,", est_lfsp_value);
    }

    if (write_amp_value == STORAGE_INFO_INVALID_DWORD) {
        (void)snprintf_s(write_amp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "null");
    } else if (write_amp_value == STORAGE_INFO_UNSUPPORT_DWORD) {
        (void)snprintf_s(write_amp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "--");
    } else {
        (void)snprintf_s(write_amp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "%u", write_amp_value);
    }

    (void)get_current_time_stamp(cur_tm_stamp, PROP_VAL_LENGTH);
    gint32 ret = snprintf_s(str_new_record, SUBHEALTHY_RECORD_CONTENT_SIZE, SUBHEALTHY_RECORD_CONTENT_SIZE - 1,
        "%-40s%-30s%-30s\n", cur_tm_stamp, est_lfsp_str, write_amp_str);
    if (ret <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, ret);
        return RET_ERR;
    }
    // 在缓冲区的最后插入新增日志内容
    ret = pd_log_buf_insert(buf, buf_size, record_pos, str_new_record, p_content_size);
    if (ret != RET_OK) {
        debug_log(DLOG_ERROR, "%s: insert str_new_record into buf failed.", __FUNCTION__);
        return RET_ERR;
    }

    guint32 per_line_len = (guint32)strlen(str_new_record);
    // 当文件记录已经达到最大条数，删除第一条有效数据
    if (*p_content_size > per_line_len * SUBHEALTHY_FILE_MAX_LINES) {
        // per_line_len + 1为文件头下方的第一条数据的开始位置
        ret = pd_log_buf_delete(buf, buf_size, per_line_len + 1, per_line_len, p_content_size);
        if (ret != RET_OK) {
            debug_log(DLOG_ERROR, "%s: delete the earliest record from buf failed.", __FUNCTION__);
            return RET_ERR;
        }
    }

    return RET_OK;
}

static void write_data_into_subhealthy_file(const gchar *file_path, guint32 est_lfsp_value, guint32 write_amp_value)
{
    guint32 content_size = 0;
    gboolean log_file_content_changed = FALSE;
    guint32 buf_size = SUBHEALTHY_RECORD_CONTENT_SIZE * SUBHEALTHY_FILE_MAX_LINES;
    gchar *file_buf = (gchar *)g_malloc0(buf_size);
    if (file_buf == NULL) {
        debug_log(DLOG_ERROR, "[%s]Malloc file buffer failed\n", __FUNCTION__);
        return;
    }
    gint32 retval = pd_log_read_file(file_path, file_buf, buf_size, &content_size);
    if (retval == RET_OK) {
        retval = subhealthy_log_buf_insert_record(file_buf, buf_size, &content_size, est_lfsp_value, write_amp_value);
        if (retval == RET_OK) {
            log_file_content_changed = TRUE;
        }
    }

    if (log_file_content_changed == TRUE) {
        debug_log(DLOG_INFO, "[%s]subhealthy record data changed", __FUNCTION__);
        retval = pd_log_write_file(file_path, file_buf, content_size);
        if (retval != RET_OK) {
            debug_log(DLOG_ERROR, "[%s]Write subhealthy record file failed", __FUNCTION__);
        }
    }
    g_free(file_buf);
}

/*
 * Description: 记录subhealthy相关的属性值
*/
void pd_log_ssd_save_subhealthy_record_file(char *device_name, guint32 est_lfsp_value, guint32 write_amp_value)
{
    if (device_name == NULL) {
        debug_log(DLOG_ERROR, "%s: Invalid input parameter.", __FUNCTION__);
        return;
    }

    gchar log_file_path[MAX_FILEPATH_LENGTH] = {0};
    struct stat file_stat;
    string_clear_blank(device_name, strlen(device_name));

    if (pd_log_check_file_path(device_name) == RET_ERR) {
        debug_log(DLOG_ERROR, "Handle %s drive log failed, the log path is not exist.", device_name);
        return;
    }

    gint32 ret = snprintf_s(log_file_path, sizeof(log_file_path), sizeof(log_file_path) - 1, "%s/%s/%s.%s",
        PD_LOG_BASE_PATH, device_name, PD_LOG_SUBHEALTHYT_RECORD_FILE, PD_LOG_EXT_NAME);
    if (ret <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s log_file_path fail, file_name: %s.%s  ret = %d", __FUNCTION__,
            PD_LOG_SUBHEALTHYT_RECORD_FILE, PD_LOG_EXT_NAME, ret);
        return;
    }

    if (stat_s(log_file_path, &file_stat) >= 0) {
        write_data_into_subhealthy_file(log_file_path, est_lfsp_value, write_amp_value);
    } else {
        debug_log(DLOG_INFO, "[%s]Subhealthy record log file not enxist, create it now", __FUNCTION__);
        (void)create_subhealthy_record_file(log_file_path);
    }

    return;
}
