/* Copyright Statement:
 *
 * This software/firmware and related documentation ("MediaTek Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
 * the prior written permission of MediaTek inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of MediaTek Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * Copyright  (C) [2020]  MediaTek Inc. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
 * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
 * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
 *
 * The following software/firmware and/or related documentation ("MediaTek
 * Software") have been modified by MediaTek Inc. All revisions are subject to
 * any receiver's applicable license agreements with MediaTek Inc.
 */

#include <command.h>
#include <common.h>
#include <vsprintf.h>
#include <debug_impl.h>
#include <romtblo_impl.h>
#include <utility.h>
#include <mtk_romtblo.h>

#define FLAG_LENGTH     (1)
#define COMMAND_OPTION_MAX_NUM     (2)

int do_romtbl_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    unsigned int address;
    unsigned long *romtbl;
    int ret;

    if(argc > 2 || argc == 1)
    {
        return CMD_RET_USAGE;
    }

    romtbl = (unsigned long *)CONFIG_ROM_TABLE_ADDRESS;
    init_rom_table((char *)romtbl);
    ret = check_rom_table_header();
    if( ret == ROMTBL_FAILED || ret == ROMTBL_NOT_INITED )
    {
        UBOOT_ERROR("ROM table header is not match. Check memory address 0x%X\n",CONFIG_ROM_TABLE_ADDRESS);
        return CMD_RET_FAILURE;
    }
    else if( ret == ROMTBL_NO_NEEDED )
    {
        UBOOT_DEBUG("No need to do rom table overlay\n");
        return CMD_RET_SUCCESS;
    }

    if(strncmp(argv[1], "K", FLAG_LENGTH) == 0 || strncmp(argv[1], "k", FLAG_LENGTH) == 0)
    {
        address = simple_strtoul(argv[2], NULL, 16);
        ret = romtbl_overlay(address);
    }
    else if(strncmp(argv[1], "U", FLAG_LENGTH) == 0 || strncmp(argv[1], "u", FLAG_LENGTH) == 0)
    {
        ret = romtbl_overlay_to_uboot_dtb();
    }
    else
    {
        UBOOT_ERROR("Command do_romtbl_overlay input argument wrong, please check command usage.\n");
        return CMD_RET_FAILURE;
    }

    if(ret != 0)
    {
        UBOOT_ERROR("Rom table overlay failure.\n");
        return CMD_RET_FAILURE;
    }
    return CMD_RET_SUCCESS;
}

U_BOOT_CMD(
    romtbl, CONFIG_SYS_MAXARGS, 1,    do_romtbl_overlay,
    "romtbl   - Do rom table overlay for u-boot dtb or kernel dtb\n",
    "command: romtbl <flag>\n"
    "<flag> : u/U for uboot dtb, k/K for kernel dtb\n"
);

int do_chip_id_add_to_bootargs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    int ret;
    unsigned int chip = 0;
    char buffer[BUFFER_SIZE] = { 0 };
    int snprintf_len;
    unsigned long *romtbl;

    romtbl = (unsigned long *)CONFIG_ROM_TABLE_ADDRESS;
    init_rom_table((char *)romtbl);
    ret = check_rom_table_header();
    if( ret == ROMTBL_FAILED || ret == ROMTBL_NOT_INITED )
    {
        UBOOT_ERROR("ROM table header is not match. Check memory address 0x%X\n",CONFIG_ROM_TABLE_ADDRESS);
        return CMD_RET_FAILURE;
    }

    if(argc == 1)
    {
        chip = romtbl_get_chip_id_info_dec();
        if(chip != 0)
        {
            snprintf_len = snprintf(buffer, BUFFER_SIZE, "%s=mt%d", CHIP_HARDWARE_KEY, chip);
            if (snprintf_len >= BUFFER_SIZE)
            {
                UBOOT_ERROR("The array size is too small(%d), snprintf fail '%s'\n", BUFFER_SIZE, buffer);
                return CMD_RET_SUCCESS;
            }
        }
        else
        {
            UBOOT_ERROR("Get CHIP ID failure, rom table does not exist\n");
        }

        ret = add_bootargs(CHIP_HARDWARE_KEY,buffer,0);
        if(ret == -1)
            UBOOT_ERROR("Add %s to bootargs failure\n",CHIP_HARDWARE_KEY);
    }
    else if(argc == COMMAND_OPTION_MAX_NUM)
    {
        if(strstr(argv[1], "c") != 0)
        {
            chip = romtbl_get_chip_id_info_dec();
            if(chip == 0)
                printf("Chip id get failure, Please check %x address\n",CONFIG_ROM_TABLE_ADDRESS);
            else
                printf("Chip id: MT%d\n",chip);
        }
        else
            printf("Command option is not support\n");
    }
    else
        printf("Command option is not support\n");

    return CMD_RET_SUCCESS;
}

U_BOOT_CMD(
    chipid, CONFIG_SYS_MAXARGS, 1,    do_chip_id_add_to_bootargs,
    "chipid   - Do add chip id to bootargs\n",
    "command: chipid\n"
);

int do_chip_revision_add_to_bootargs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    int ret;
    unsigned int revision = 0;
    char buffer[BUFFER_SIZE] = { 0 };
    int snprintf_len;
    unsigned long *romtbl;

    romtbl = (unsigned long *)CONFIG_ROM_TABLE_ADDRESS;
    init_rom_table((char *)romtbl);
    ret = check_rom_table_header();
    if( ret == ROMTBL_FAILED || ret == ROMTBL_NOT_INITED )
    {
        UBOOT_ERROR("ROM table header is not match. Check memory address 0x%X\n",CONFIG_ROM_TABLE_ADDRESS);
        return CMD_RET_FAILURE;
    }

    if(argc == 1)
    {
        revision = romtbl_get_chip_revision_info();
        if(revision != 0)
        {
            snprintf_len = snprintf(buffer, BUFFER_SIZE, "%s=%s%d", CHIP_HARDWAREREV_KEY, CHIP_REVISION_CHAR, revision);
            if (snprintf_len >= BUFFER_SIZE)
            {
                UBOOT_ERROR("The array size is too small(%d), snprintf fail '%s'\n", BUFFER_SIZE, buffer);
                return CMD_RET_SUCCESS;
            }
        }
        else
        {
            UBOOT_ERROR("Get CHIP REVISION failure, rom table does not exist\n");
        }

        ret = add_bootargs(CHIP_HARDWAREREV_KEY,buffer,0);
        if(ret == -1)
            UBOOT_ERROR("Add %s to bootargs failure\n",CHIP_HARDWAREREV_KEY);
    }
    else if(argc == COMMAND_OPTION_MAX_NUM)
    {
        if(strstr(argv[1], "r") != 0)
        {
            revision = romtbl_get_chip_revision_info();
            if(revision == 0)
                printf("Chip revision get failure, Please check %x address\n",CONFIG_ROM_TABLE_ADDRESS);
            else
                printf("Chip revision: E%d\n",revision);
        }
        else
            printf("Command option is not support\n");
    }
    else
        printf("Command option is not support\n");

    return CMD_RET_SUCCESS;
}

U_BOOT_CMD(
    revisionid, CONFIG_SYS_MAXARGS, 1,    do_chip_revision_add_to_bootargs,
    "revisionid   - Do add revision id to bootargs\n",
    "command: revisionid\n"
);
