/* 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 "platform.h"
#include "sml.h"
#include "sml_errcodes.h"
#include "pd_log_process.h"
#include "sata_seagate_log_parse.h"

/*
 * Description: 添加sata盘的glist或plist到json对象中
 */
static void pd_log_add_sata_glist_plist(void *list_item, guint32 pot_valid, Json *out_put_jso)
{
    Json *list_log_node = NULL;
    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};
    ATA_SMART_SEAGATEGLIST_ITEM_S *p_item = (ATA_SMART_SEAGATEGLIST_ITEM_S *)list_item;

    if (JsonObjectCreate(&list_log_node) != JSON_OK) {
        return;
    }

    if (pot_valid) {
        (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, "%hu", p_item->POT);
        Json *str_obj = NULL;
        JsonStringCreate(tmp_str, &str_obj);
        JsonObjectItemSet(list_log_node, "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, "%04x", p_item->LBA);
        Json *str_lba_obj = NULL;
        JsonStringCreate(tmp_str, &str_lba_obj);
        JsonObjectItemSet(list_log_node, "lba", str_lba_obj);
    } else {
        JsonObjectItemSet(list_log_node, "pot", NULL);
        (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, "%0x04x%08x", p_item->POT,
            p_item->LBA);
        Json *str_lba2_obj = NULL;
        JsonStringCreate(tmp_str, &str_lba2_obj);
        JsonObjectItemSet(list_log_node, "lba", str_lba2_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", p_item->R);
    Json *str_r_obj = NULL;
    JsonStringCreate(tmp_str, &str_r_obj);
    JsonObjectItemSet(list_log_node, "r", str_r_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", p_item->T);
    Json *str_t_obj = NULL;
    JsonStringCreate(tmp_str, &str_t_obj);
    JsonObjectItemSet(list_log_node, "t", str_t_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", p_item->Z);
    Json *str_z_obj = NULL;
    JsonStringCreate(tmp_str, &str_z_obj);
    JsonObjectItemSet(list_log_node, "z", str_z_obj);

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

/*
 * Description: 处理希捷sata盘的glist数据
 * History: 1.2018年4月13日
 * 新生成函数
 */
void pd_log_handle_sata_seagate_glist(FILE *file, PD_LOG_S *pd_log, void *out_put, Json *pd_log_jso)
{
    guint32 i, j, num = 0;
    ATA_SMART_SEAGATEGLIST_S *glist = NULL;
    gint32 pot_valid = 0;
    gint32 flag = 0;
    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};
    Json *glist_log_array = NULL;

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

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

    glist = (ATA_SMART_SEAGATEGLIST_S *)pd_log->SATADevice.seagate_glist.data;

    // 判断如果第一个Glist和第二个Glist同时为0，则表示该Glist为空(如果有且只有一个Glist,且该Glist为全0扇区，则无法打印)
    flag = (0 == glist->items[0].POT) && (0 == glist->items[0].LBA) && (0 == glist->items[0].Z) &&
        (0 == glist->items[0].T) && (0 == glist->items[0].R) && (0 == glist->items[1].Z) && (0 == glist->items[1].T) &&
        (0 == glist->items[1].R);

    if (flag) {
        pd_log_fprintf(file, "Grown Defect List is empty...\n");
        return;
    }

    pd_log_fprintf(file, "Grown List Version: %u\n", glist->reserved0[0]);
    flag = (0x01 == glist->reserved0[0]) || (0x00 == glist->reserved0[0]);
    if (flag) {
        pd_log_fprintf(file, "Grown Defect Entries\n"
            "\t POT        LBA      RTZ\n"
            "\t-----  --------  ------------\n");
        pot_valid = 1;
    } else {
        pd_log_fprintf(file, "Grown Defect Entries\n"
            "\t       LBA             RTZ\n"
            "\t---------------  ------------\n");
        pot_valid = 0;
    }

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

    for (i = 0; i < pd_log->SATADevice.seagate_critical_event.max_raw_data_size.sectors; i++) {
        for (j = 0; j < ATA_LOG_SEAGATE_GLIST_NUM; j++) { // 每个Glist占16个字节
            flag = (0 == glist->items[j].POT) && (0 == glist->items[j].LBA) && (0 == glist->items[j].Z) &&
                (0 == glist->items[j].T) && (0 == glist->items[j].R);

            if (flag) {
                // 因为Glist为0必定在Glist的第一个，所以当第31个为0时就表明Glist已经结尾了
                if ((ATA_LOG_SEAGATE_GLIST_NUM - 1) == j) {
                    goto exit;
                }

                // 判断下一个Glist是否都为0，如果是则结束
                // 如果Glist中的HEAD大于10，则表明是乱码
                flag = (0 == glist->items[j + 1].LBA) || (glist->items[j + 1].Z >= 10);
                if (flag) {
                    goto exit;
                }

                if (pot_valid) { // POT有效(LBA用4字节直接表示)，则打印
                    pd_log_fprintf(file, "\t%5d  %08x  %04x-%04x-%02x\n", glist->items[j].POT, glist->items[j].LBA,
                        glist->items[j].R, glist->items[j].T, glist->items[j].Z);
                } else { // POT无效，表示LBA高字节(LBA用6字节直接表示)
                    pd_log_fprintf(file, "\t0x%04x%08x  %04x-%04x-%02x\n", glist->items[j].POT, glist->items[j].LBA,
                        glist->items[j].R, glist->items[j].T, glist->items[j].Z);
                }

                num++; // 统计g-list个数
                pd_log_add_sata_glist_plist((void *)&glist->items[j], pot_valid, glist_log_array);
            } else if (glist->items[j].Z >= 10) { // 如果Glist中的HEAD大于10，则表明是乱码，退出并打印Glist个数
                goto exit;
            } else {
                if (pot_valid) { // POT有效(LBA用4字节直接表示)，则打印
                    pd_log_fprintf(file, "\t%5d  %08x  %04x-%04x-%02x\n", glist->items[j].POT, glist->items[j].LBA,
                        glist->items[j].R, glist->items[j].T, glist->items[j].Z);
                } else { // POT无效，表示LBA高字节(LBA用6字节直接表示)
                    pd_log_fprintf(file, "\t0x%04x%08x  %04x-%04x-%02x\n", glist->items[j].POT, glist->items[j].LBA,
                        glist->items[j].R, glist->items[j].T, glist->items[j].Z);
                }

                num++; // 统计g-list个数
                pd_log_add_sata_glist_plist((void *)&glist->items[j], pot_valid, glist_log_array);
            }
        }

        glist++;
    }

exit:
    pd_log_fprintf(file, "Glist Entries=%d\n", num); // 输出G-list长度
    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%u", num);
    Json *str_obj = NULL;
    JsonStringCreate(tmp_str, &str_obj);
    (void)JsonObjectItemSet(pd_log_jso, "glist_count", str_obj);
    (void)JsonObjectItemSet(pd_log_jso, "glist", glist_log_array);
    return;
}

/*
 * Description: 处理希捷sata盘的plist数据
 * History: 1.2018年4月13日
 * 新生成函数
 */
void pd_log_handle_sata_seagate_plist(FILE *file, PD_LOG_S *pd_log, void *out_put, Json *pd_log_jso)
{
    gint32 j = 0;
    ATA_SMART_SEAGATEPLIST_S *plist = NULL;
    gint32 pot_valid = 0;
    gint32 flag = 0;
    gchar tmp_str[ATA_LOG_STRING_LENGTH] = {0};
    Json *plist_log_array = NULL;

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

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

    plist = (ATA_SMART_SEAGATEPLIST_S *)pd_log->SATADevice.seagate_plist.data;

    flag = (plist->items[0].POT == 0) && (plist->items[0].LBA == 0) && (plist->items[0].R == 0) &&
        (plist->items[0].T == 0) && (plist->items[0].Z == 0) && (0 == plist->items[1].Z) && (0 == plist->items[1].T) &&
        (0 == plist->items[1].R);

    if (flag) {
        pd_log_fprintf(file, "Pending Sector Table is empty...\n");
        return;
    }

    pd_log_fprintf(file, "Pending List Version: %u\n", plist->reserved0[0]);

    flag = (0x01 == plist->reserved0[0]) || (0x00 == plist->reserved0[0]);
    if (flag) {
        pd_log_fprintf(file, "Pending Sector Table Entries\n"
            "\t POT      LBA         RTZ\n"
            "\t-----  --------  ------------\n");
        pot_valid = 1;
    } else {
        pd_log_fprintf(file, "Pending Sector Table Entries\n"
            "\t    LBA             RTZ\n"
            "\t--------------  ------------\n");
        pot_valid = 0;
    }

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

    for (j = 0; j < ATA_LOG_SEAGATE_PLIST_NUM; j++) {
        flag = (plist->items[j].POT == 0) && (plist->items[j].LBA == 0) && (plist->items[j].R == 0) &&
            (plist->items[j].T == 0) && (plist->items[j].Z == 0);
        if (flag) {
            if ((ATA_LOG_SEAGATE_PLIST_NUM - 1) == j) {
                break;
            }

            if ((0 == plist->items[j + 1].LBA) || (plist->items[j + 1].Z >= 10)) {
                break;
            }

            if (pot_valid) {
                pd_log_fprintf(file, "\t%5d  %08x  %04x-%04x-%02x\n", plist->items[j].POT, plist->items[j].LBA,
                    plist->items[j].R, plist->items[j].T, plist->items[j].Z);
            } else {
                pd_log_fprintf(file, "\t0x%04x%08x  %04x-%04x-%02x\n", plist->items[j].POT, plist->items[j].LBA,
                    plist->items[j].R, plist->items[j].T, plist->items[j].Z);
            }
        } else {
            if (pot_valid) {
                pd_log_fprintf(file, "\t%5d  %08x  %04x-%04x-%02x\n", plist->items[j].POT, plist->items[j].LBA,
                    plist->items[j].R, plist->items[j].T, plist->items[j].Z);
            } else {
                pd_log_fprintf(file, "\t0x%04x%08x  %04x-%04x-%02x\n", plist->items[j].POT, plist->items[j].LBA,
                    plist->items[j].R, plist->items[j].T, plist->items[j].Z);
            }
        }
        pd_log_add_sata_glist_plist((void *)&plist->items[j], pot_valid, plist_log_array);
    }

    (void)snprintf_s(tmp_str, ATA_LOG_STRING_LENGTH, ATA_LOG_STRING_LENGTH - 1, "%d", j);
    Json *str_obj = NULL;
    JsonStringCreate(tmp_str, &str_obj);
    JsonObjectItemSet(pd_log_jso, "plist_count", str_obj);
    JsonObjectItemSet(pd_log_jso, "plist", plist_log_array);
    return;
}