/**
 * @file        scp_sanity.c
 * @brief       Global sanity checks for the SCP driver.
 *
 * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of NVIDIA CORPORATION nor the names of its
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if !NVRISCV_FEATURE_SCP
#error "Attempting to build scp_sanity.c but the SCP driver is disabled!"
#endif // NVRISCV_FEATURE_SCP


/* Compiler headers */

/* Early FSP headers */
#include <misc/ct-assert.h>             // for HEADER_CHECK

/* Hardware headers */

/* Late FSP headers */
#include <misc/nvmisc_drf.h>            // for DRF macros (for scp_direct.h)

/* Module-specific FSP headers */
#include <scp/scp_common.h>             // for scp_register_index_t, etc.
#include <scp/scp_crypt.h>              // for SCP_BLOCK_SIZE, SCP_KEY_SIZE
#include <scp/scp_direct.h>             // for SCP_REGISTER_SIZE
#include <scp/scp_private.h>            // for SCP_SECRET_INDEX_CLEAR
#include <scp/scp_rand.h>               // for SCP_RAND_SIZE

/*
 * Compile-time check for FSP header files
 *   Each FSP header file contains a signature unique to that file, and the
 *   FSP project.  The HEADER_CHECK macro (contained in misc/ct-assert.h) can
 *   check for this signature.  If it does not exist, then the build will
 *   abort.
 *
 *   This is a trap for projects which have their own include files of the
 *   same names, but different contents.  This trap ensures that only the
 *   files from the FSP project, are built into the FSP source code.
 */
HEADER_CHECK(FSP__MISC__NVMISC_DRF_H)
HEADER_CHECK(FSP__SCP__SCP_COMMON_H)
HEADER_CHECK(FSP__SCP__SCP_CRYPT_H)
HEADER_CHECK(FSP__SCP__SCP_DIRECT_H)
HEADER_CHECK(FSP__SCP__SCP_PRIVATE_H)
HEADER_CHECK(FSP__SCP__SCP_RAND_H)


//
// Keeping these constants distinct helps insulate external clients against
// future hardware changes, but also complicates the internal driver logic
// somewhat. To get around this, we simply assume them to be equivalent for
// now and defer any complicated logic updates until that assumption no longer
// holds.
//
_Static_assert((SCP_BLOCK_SIZE       == SCP_REGISTER_SIZE) &&
               (SCP_BUFFER_ALIGNMENT == SCP_REGISTER_SIZE) &&
               (SCP_KEY_SIZE         == SCP_REGISTER_SIZE) &&
               (SCP_RAND_SIZE        == SCP_REGISTER_SIZE) ,
    "One or more of the core size constants used by the SCP driver no longer "
    "match the SCP register size. Substantial updates may need to be made to "
    "the internal driver logic to accommodate."
);

//
// The enumeration constants for the SCP GPRs have both short- and long-form
// names as a compromise between the stylistic consistency perferred by some
// clients and the brevity preferred by others. This check loosely ensures that
// the two formats remain in sync with each other.
//
_Static_assert(SCP_RCOUNT == SCP_REGISTER_INDEX_COUNT,
    "Mismatch detected between the short and long forms of the "
    "scp_register_index_t enumeration constants."
);

//
// The specific value of this constant is mandated by the microcode security
// bar and is also assumed by the SCP driver in order to simplify certain input
// -validation checks. It should therefore only be changed with care and prior
// approval.
//
_Static_assert(SCP_SECRET_INDEX_CLEAR == 0U,
    "The secret index selected by the SCP driver for clearing registers in "
    "secure mode does not match the value mandated by the microcode security "
    "bar. Please ensure that you have received the proper prior approvals "
    "before making this change, and remember to update all affected input-"
    "validation routines and API documentation accordingly."
);
