// SPDX-License-Identifier: MPL-2.0
//
// Do NOT modify or remove this copyright and license
//
// Copyright (c) 2012-2025 Seagate Technology LLC and/or its Affiliates, All Rights Reserved
//
// This software is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// ******************************************************************************************
//
// \file ata_Security.h
// \brief This file defines the function calls for performing some ATA Security operations

#pragma once

#include "operations_Common.h"

#if defined(__cplusplus)
extern "C"
{
#endif

// This is a password defined in this MSDN article for performing secure erase in Windows PE.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/storage/security-group-commands
// This can only be used for the user password during an erase in WinPE.
#define WINDOWS_PE_ATA_SECURITY_PASSWORD "AutoATAWindowsString12345678901"

    typedef enum eATASecurityPasswordTypeEnum
    {
        ATA_PASSWORD_USER,
        ATA_PASSWORD_MASTER
    } eATASecurityPasswordType;

    typedef enum eATASecurityMasterPasswordCapabilityEnum
    {
        ATA_MASTER_PASSWORD_HIGH,
        ATA_MASTER_PASSWORD_MAXIMUM
    } eATASecurityMasterPasswordCapability;

    typedef enum eATASecurityZacOptionsEnum
    {
        ATA_ZAC_ERASE_EMPTY_ZONES = 0,
        ATA_ZAC_ERASE_FULL_ZONES  = 1
    } eATASecurityZacOptions;

    typedef enum eATASecurityEraseTypeEnum
    {
        ATA_SECURITY_ERASE_STANDARD_ERASE,
        ATA_SECURITY_ERASE_ENHANCED_ERASE
    } eATASecurityEraseType;

    typedef struct s_ataSecurityPassword
    {
        // set this to true when setting/using the master password.
        eATASecurityPasswordType passwordType;
        // When set to true, this means setting the master password capability bit to maximum. zero is high. (Only for
        // setting the password!!!) If this is set to high, user and master password can unlock the drive. If this is
        // set to maximum, then the master can only be used to erase the drive
        eATASecurityMasterPasswordCapability masterCapability;
        // ZAC drives only and only on Secure Erase command. This is used to specify if zone conditions are set to empty
        // (0-false) or full (1-true)
        eATASecurityZacOptions zacSecurityOption;
        // must be between 1 and FFFEh. zero and FFFFh will be ignored by the drive. This is only a reference used for
        // when the master password is changed, someone could look it up.
        uint16_t masterPWIdentifier;
        // 32 bytes. These are not required to be ASCII in the spec.
        uint8_t password[ATA_SECURITY_MAX_PW_LENGTH];
        // This is here in case of using an empty password so that we know when placing it in the buffer what we are
        // setting. Max length is 32bytes. Anything larger in this value is ignored.
        uint8_t passwordLength;
    } ataSecurityPassword, *ptrATASecurityPassword;

    //-----------------------------------------------------------------------------
    //
    //  sat_ATA_Security_Protocol_Supported(const tDevice *device)
    //
    //! \brief   Description:  Checks if the SAT ATA Security protocol is supportd or not.
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!
    //  Exit:
    //!   \return true = SATL supports ATA Security protocol, false = not supported.
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1) OPENSEA_OPERATIONS_API bool sat_ATA_Security_Protocol_Supported(const tDevice* device);

    typedef struct s_ataSecurityStatus
    {
        uint16_t masterPasswordIdentifier;
        bool     masterPasswordCapability; // false = high, true = maximum
        bool     enhancedEraseSupported;
        bool     securityCountExpired;
        bool     securityFrozen;
        bool     securityLocked;
        bool     securityEnabled;
        bool     securitySupported;
        bool     extendedTimeFormat; // this bool lets a caller know if the time was reported by the drive in extended
                                     // format or normal format.
        uint16_t          securityEraseUnitTimeMinutes;
        uint16_t          enhancedSecurityEraseUnitTimeMinutes;
        eATASecurityState securityState;
        bool restrictedSanitizeOverridesSecurity; // If this is true, then a sanitize command can be run and clear the
                                                  // user password. (See ACS4 for more details)
        bool encryptAll;                          // Set to true means the device encrypts all user data on the drive.
    } ataSecurityStatus, *ptrATASecurityStatus;

    //-----------------------------------------------------------------------------
    //
    //  get_ATA_Security_Info()
    //
    //! \brief   Description:  Fills in the struct with information about what is supported by the drive for ATA
    //! security. This uses the device->drive_info.IdentifyData.ata.ata to fill this in. Performing an identify command
    //! before calling this will update the data
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[out] securityStatus = pointer to the structure to fill in with security information
    //!   \param[in] useSAT = set to true to attempt commands using the SAT spec security protocol for ATA security.
    //!   This is recommended for non-ata interfaces if the SATL supports it since it allows the SATL to control the
    //!   erase and incomming commands.
    //!
    //  Exit:
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1, 2)
    M_PARAM_RO(1)
    M_PARAM_WO(2)
    OPENSEA_OPERATIONS_API
    void get_ATA_Security_Info(const tDevice* device, ptrATASecurityStatus securityStatus, bool useSAT);

    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API
    void print_ATA_Security_Info(ptrATASecurityStatus securityStatus, bool satSecurityProtocolSupported);

    //-----------------------------------------------------------------------------
    //
    //  set_ATA_Security_Password_In_Buffer()
    //
    //! \brief   Description:  Sets the password for ATA security in the buffer
    //
    //  Entry:
    //!   \param[out] ptrData = pointer to the buffer to set the password in
    //!   \param[in] ataPassword = pointer to the structure that holds all the relevent information to put the password
    //!   in the buffer. Allows for empty passwords and non-ascii characters
    //! \param[in] setPassword = Set to true when
    //!   using the buffer to send the security set password command so that the master password identifier and
    //!   capability fields will be set.
    //! \param[in] eraseUnit = set to true when using the buffer to send the security
    //!   erase command so that the zac options bit can be set.
    //! \param[in] useSAT = set to true to attempt commands
    //!   using the SAT spec security protocol for ATA security. This is recommended for non-ata interfaces if the SATL
    //!   supports it since it allows the SATL to control the erase and incoming commands.
    //!
    //  Exit:
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1, 2)
    M_PARAM_WO(1)
    M_PARAM_RO(2)
    OPENSEA_OPERATIONS_API void set_ATA_Security_Password_In_Buffer(uint8_t*               ptrData,
                                                                    ptrATASecurityPassword ataPassword,
                                                                    bool                   setPassword,
                                                                    bool                   eraseUnit,
                                                                    bool                   useSAT);

    //-----------------------------------------------------------------------------
    //
    //  set_ATA_Security_Erase_Type_In_Buffer()
    //
    //! \brief   Description:  sets the bits telling whether this is a enhanced erase or not
    //
    //  Entry:
    //!   \param[out] ptrData = pointer to the buffer to set the password in
    //!   \param[in] eraseType = enhanced or normal ATA Security erase.
    //!   \param[in] useSAT = set to true when using SAT security protocol to issue the erase
    //!
    //  Exit:
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RW(1)
    OPENSEA_OPERATIONS_API
    void set_ATA_Security_Erase_Type_In_Buffer(uint8_t* ptrData, eATASecurityEraseType eraseType, bool useSAT);

    //-----------------------------------------------------------------------------
    //
    //  disable_ATA_Security_Password()
    //
    //! \brief   Description:  takes a password and sends the disable ATA Security password command
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword = structure holding password information.
    //!   \param[in] useSAT = set to true to attempt commands using the SAT spec security protocol for ATA security.
    //!   This is recommended for non-ata interfaces if the SATL supports it.
    //!
    //  Exit:
    //!   \return SUCCESS = pass, FAILURE = fail
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues disable_ATA_Security_Password(const tDevice*      device,
                                                                       ataSecurityPassword ataPassword,
                                                                       bool                useSAT);

    //-----------------------------------------------------------------------------
    //
    //  set_ATA_Security_Password()
    //
    //! \brief   Description:  takes a password and sends the set ATA Security password command
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword = structure holding password information.
    //!   \param[in] useSAT = set to true to attempt commands using the SAT spec security protocol for ATA security.
    //!   This is recommended for non-ata interfaces if the SATL supports it.
    //!
    //  Exit:
    //!   \return SUCCESS = pass, FAILURE = fail
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues set_ATA_Security_Password(const tDevice*      device,
                                                                   ataSecurityPassword ataPassword,
                                                                   bool                useSAT);

    //-----------------------------------------------------------------------------
    //
    //  unlock_ATA_Security()
    //
    //! \brief   Description:  takes a password and sends the unlock ATA Security password command
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword = structure holding password information.
    //!   \param[in] useSAT = set to true to attempt commands using the SAT spec security protocol for ATA security.
    //!   This is recommended for non-ata interfaces if the SATL supports it.
    //!
    //  Exit:
    //!   \return SUCCESS = pass, FAILURE = fail
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues unlock_ATA_Security(const tDevice*      device,
                                                             ataSecurityPassword ataPassword,
                                                             bool                useSAT);

    //-----------------------------------------------------------------------------
    //
    //  start_ATA_Security_Erase()
    //
    //! \brief   Description:  takes a password and sends the erase prepare and erase unit commands. WARNING! This
    //! function may appear to hang on drives that have a long timeout for this function! Strongly suggest using
    //! multithreaded code with this function!
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword = structure holding password information.
    //!   \param[in] eraseType = set to the enum value specifying which erase to perform on the drive.
    //!   \param[in] timeout = timeout value to use for the ata security erase unit command. This should be the value
    //!   returned from the ATA identify data or greater (in seconds). \param[in] useSAT = set to true to attempt
    //!   commands using the SAT spec security protocol for ATA security. This is recommended for non-ata interfaces if
    //!   the SATL supports it.
    //!
    //  Exit:
    //!   \return SUCCESS = pass, FAILURE = fail
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues start_ATA_Security_Erase(const tDevice*        device,
                                                                  ataSecurityPassword   ataPassword,
                                                                  eATASecurityEraseType eraseType,
                                                                  uint32_t              timeout,
                                                                  bool                  useSAT);

    //-----------------------------------------------------------------------------
    //
    //  run_ATA_Security_Erase()
    //
    //! \brief   Description:  Function to send a ATA Spec Secure Erase chosen device
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] eraseType = set to enum value for type of erase to perform
    //!   \param[in] ataPassword - structure holding password information.
    //!   \param[in] forceSATValid = when true, the force SAT variable is checked and used to force the type of command
    //!   used to do the erase. \param[in] forceSAT = checked when above bool is true. When this is true, use SAT
    //!   security protocol commands. When false, use ata security protocol commands (may be wrapped in SAT ATA
    //!   Pass-through command which is different from sending security protocol and letting the SATL translate)
    //!
    //  Exit:
    //!   \return SUCCESS = pass, FAILURE = fail
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues run_ATA_Security_Erase(const tDevice*        device,
                                                                eATASecurityEraseType eraseType,
                                                                ataSecurityPassword   ataPassword,
                                                                bool                  forceSATvalid,
                                                                bool                  forceSAT);

    //-----------------------------------------------------------------------------
    //
    //  run_Disable_ATA_Security_Password( tDevice * device )
    //
    //! \brief   Disable the ATA security password. This is useful if the ATA security erase was interrupted and a
    //! password is still set on the drive. Note that this takes the ASCII password sent in and uses it, but a BIOS may
    //! do a hash or something else when setting a password so this may not work for passwords other than those set by
    //! this code base
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword - structure holding password information.
    //!   \param[in] forceSATValid = when true, the force SAT variable is checked and used to force the type of command
    //!   used to do the erase. \param[in] forceSAT = checked when above bool is true. When this is true, use SAT
    //!   security protocol commands. When false, use ata security protocol commands (may be wrapped in SAT ATA
    //!   Pass-through command which is different from sending security protocol and letting the SATL translate)
    //!
    //  Exit:
    //!   \return SUCCESS = good, !SUCCESS something went wrong see error codes
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues run_Disable_ATA_Security_Password(const tDevice*      device,
                                                                           ataSecurityPassword ataPassword,
                                                                           bool                forceSATvalid,
                                                                           bool                forceSAT);

    //-----------------------------------------------------------------------------
    //
    //  run_Set_ATA_Security_Password(const tDevice *device, ataSecurityPassword ataPassword, bool forceSATvalid, bool
    //  forceSAT)
    //
    //! \brief   Sets an ATA security password. NOTE: This is not recommended from software since some systems may not
    //! even boot with a locked drive,
    //!          or may not encode the password the same way as this software.
    //!          NOTE2: Some SATLs don't seem to properly handle locked ATA security drives, so you may not be able to
    //!          unlock them or remove the password without retrying multiple times from software. It is strongly
    //!          recommended that passwords only be set from the BIOS or host controller option rom.
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword - structure holding password information.
    //!   \param[in] forceSATValid = when true, the force SAT variable is checked and used to force the type of command
    //!   used to do the erase. \param[in] forceSAT = checked when above bool is true. When this is true, use SAT
    //!   security protocol commands. When false, use ata security protocol commands (may be wrapped in SAT ATA
    //!   Pass-through command which is different from sending security protocol and letting the SATL translate)
    //!
    //  Exit:
    //!   \return SUCCESS = good, !SUCCESS something went wrong see error codes
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues run_Set_ATA_Security_Password(const tDevice*      device,
                                                                       ataSecurityPassword ataPassword,
                                                                       bool                forceSATvalid,
                                                                       bool                forceSAT);

    //-----------------------------------------------------------------------------
    //
    //  run_Unlock_ATA_Security(const tDevice *device, ataSecurityPassword ataPassword, bool forceSATvalid, bool
    //  forceSAT)
    //
    //! \brief   Unlocks ATA security with the provided password. This is useful if the ATA security erase was
    //! interrupted and a password is still set on the drive. Note that this takes the ASCII password sent in and uses
    //! it, but a BIOS may do a hash or something else when setting a password so this may not work for passwords other
    //! than those set by this code base
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] ataPassword - structure holding password information.
    //!   \param[in] forceSATValid = when true, the force SAT variable is checked and used to force the type of command
    //!   used to do the erase. \param[in] forceSAT = checked when above bool is true. When this is true, use SAT
    //!   security protocol commands. When false, use ata security protocol commands (may be wrapped in SAT ATA
    //!   Pass-through command which is different from sending security protocol and letting the SATL translate)
    //!
    //  Exit:
    //!   \return SUCCESS = good, !SUCCESS something went wrong see error codes
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues run_Unlock_ATA_Security(const tDevice*      device,
                                                                 ataSecurityPassword ataPassword,
                                                                 bool                forceSATvalid,
                                                                 bool                forceSAT);

    //-----------------------------------------------------------------------------
    //
    //  run_Freeze_ATA_Security(const tDevice *device, bool forceSATvalid, bool forceSAT)
    //
    //! \brief   Freezes ATA security with the freezelock command. This is used to prevent other ATA security commands
    //! from being processed by the drive.
    //
    //  Entry:
    //!   \param[in] device = file descriptor
    //!   \param[in] forceSATValid = when true, the force SAT variable is checked and used to force the type of command
    //!   used to do the erase. \param[in] forceSAT = checked when above bool is true. When this is true, use SAT
    //!   security protocol commands. When false, use ata security protocol commands (may be wrapped in SAT ATA
    //!   Pass-through command which is different from sending security protocol and letting the SATL translate)
    //!
    //  Exit:
    //!   \return SUCCESS = good, !SUCCESS something went wrong see error codes
    //
    //-----------------------------------------------------------------------------
    M_NONNULL_PARAM_LIST(1)
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues run_Freeze_ATA_Security(const tDevice* device,
                                                                 bool           forceSATvalid,
                                                                 bool           forceSAT);

#if defined(__cplusplus)
}
#endif
