/*
 * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * @file
 * @brief NVIDIA GPU-specific CPER definitions and APIs
 *
 * This header provides GPU-specific extensions to the CPER library including:
 * - NVIDIA-specific notification type GUIDs for GPU events
 * - NVIDIA vendor-specific CPER section format structures
 * - GPU event section API
 */

#ifndef GPU_CPER_H
#define GPU_CPER_H

#include <stddef.h>

#include "cper.h"

/*
 * ============================================================================
 * NVIDIA CPER GUIDs
 * ============================================================================
 */

/*
 * NVIDIA CPER GUID Namespace
 * This value is used as the namespace for all NVIDIA-specific CPER GUIDs (v5).
 * UUID: ea219640-18b9-4c91-8e5c-58eeacd9b33f
 */
#define NV_CPER_NAMESPACE \
    NV_CPER_GUID_INIT(0xEA219640, 0x18B9, 0x4C91, 0x8E, 0x5C, 0x58, 0xEE, 0xAC, 0xD9, 0xB3, 0x3F)

/*!
 * NVIDIA GPU Notification Type GUIDs
 *
 * These GUIDs indicate HOW an error was discovered/reported, not what the error is.
 * The section data describes the error itself; the notification type describes
 * the mechanism by which the error was surfaced to the CPER producer.
 */

/*!
 * GPU Internal Interrupt
 *
 * Error was reported via a GPU hardware interrupt to the host or a microcontroller.
 * This indicates the GPU hardware itself detected and signaled the condition.
 *
 * UUID: 0eeaf365-3740-5271-ae58-10f3b7c09c4a
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-interrupt"
 */
#define NV_CPER_NOTIFY_NVIDIA_GPU_INTERRUPT_GUID \
    NV_CPER_GUID_INIT(0x0EEAF365, 0x3740, 0x5271, 0xAE, 0x58, 0x10, 0xF3, 0xB7, 0xC0, 0x9C, 0x4A)

/*!
 * GPU Firmware Fault
 *
 * Error was detected by on-device firmware (FSP, GSP, PMU, SEC2, etc.) via its
 * internal fault handling mechanism. The firmware detected an anomalous condition
 * and reported it to the host or logged it for retrieval.
 *
 * UUID: e0fd0b2d-ba62-59c1-9744-9dc8bf313650
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-firmware-fault"
 */
#define NV_CPER_NOTIFY_NVIDIA_GPU_FW_FAULT_GUID \
    NV_CPER_GUID_INIT(0xE0FD0B2D, 0xBA62, 0x59C1, 0x97, 0x44, 0x9D, 0xC8, 0xBF, 0x31, 0x36, 0x50)

/*!
 * GPU Timeout
 *
 * Error condition was inferred due to a timeout waiting for an expected response
 * from GPU hardware or firmware (e.g., RPC timeout, doorbell timeout, engine idle
 * timeout).
 *
 * UUID: 3a90eac6-481d-5cd7-b57d-0a92315bff8f
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-timeout"
 */
#define NV_CPER_NOTIFY_NVIDIA_GPU_TIMEOUT_GUID \
    NV_CPER_GUID_INIT(0x3A90EAC6, 0x481D, 0x5CD7, 0xB5, 0x7D, 0x0A, 0x92, 0x31, 0x5B, 0xFF, 0x8F)

/*!
 * System Software Check/Assertion
 *
 * Error was detected by system software through explicit validation, consistency
 * checks, or assertion failures (e.g., invalid state detected, invariant violation,
 * unexpected return value).
 *
 * UUID: cb2668a9-0508-5e36-bbc9-4d6c7d2dc808
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-software-check"
 */
#define NV_CPER_NOTIFY_NVIDIA_GPU_SW_CHECK_GUID \
    NV_CPER_GUID_INIT(0xCB2668A9, 0x0508, 0x5E36, 0xBB, 0xC9, 0x4D, 0x6C, 0x7D, 0x2D, 0xC8, 0x08)

static NV_INLINE const char *
cperNvidiaNotifyTypeToString(const NV_CPER_GUID *pNotifyType)
{
    static const NV_CPER_GUID notifyInterrupt = NV_CPER_NOTIFY_NVIDIA_GPU_INTERRUPT_GUID;
    static const NV_CPER_GUID notifyFwFault   = NV_CPER_NOTIFY_NVIDIA_GPU_FW_FAULT_GUID;
    static const NV_CPER_GUID notifyTimeout   = NV_CPER_NOTIFY_NVIDIA_GPU_TIMEOUT_GUID;
    static const NV_CPER_GUID notifySwCheck   = NV_CPER_NOTIFY_NVIDIA_GPU_SW_CHECK_GUID;

    if (pNotifyType == NULL)
        return "Unknown";

    if (cperGuidEqual(pNotifyType, &notifyTimeout))
        return "GPU Timeout";
    if (cperGuidEqual(pNotifyType, &notifyInterrupt))
        return "GPU Interrupt";
    if (cperGuidEqual(pNotifyType, &notifyFwFault))
        return "GPU Firmware Fault";
    if (cperGuidEqual(pNotifyType, &notifySwCheck))
        return "GPU Software Check";

    return "Unknown";
}

/*
 * NVIDIA GPU Driver Creator IDs
 */

/*!
 * NVIDIA GPU Driver Creator ID (Physical RM)
 *
 * UUID: 7d3f1537-bfc6-583a-997b-a754778e60c4
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-driver-physical"
 */
#define NV_CPER_CREATOR_NVIDIA_GPU_PF_GSP_FW_GUID \
    NV_CPER_GUID_INIT(0x7D3F1537, 0xBFC6, 0x583A, 0x99, 0x7B, 0xA7, 0x54, 0x77, 0x8E, 0x60, 0xC4)

/*!
 * NVIDIA GPU Driver Creator ID (Kernel RM)
 *
 * UUID: 5a572ae4-9a04-5e55-a86f-dbfdfc0165e8
 * Generated by:
 *   $ uuidgen --sha1 --namespace ea219640-18b9-4c91-8e5c-58eeacd9b33f \
 *             --name "gpu-driver-kernel"
 */
#define NV_CPER_CREATOR_NVIDIA_GPU_PF_DRIVER_GUID \
    NV_CPER_GUID_INIT(0x5A572AE4, 0x9A04, 0x5E55, 0xA8, 0x6F, 0xDB, 0xFD, 0xFC, 0x01, 0x65, 0xE8)

static NV_INLINE const char *
cperNvidiaCreatorIdToString(const NV_CPER_GUID *pCreatorId)
{
    static const NV_CPER_GUID creatorPfGspFw = NV_CPER_CREATOR_NVIDIA_GPU_PF_GSP_FW_GUID;
    static const NV_CPER_GUID creatorPfDrv   = NV_CPER_CREATOR_NVIDIA_GPU_PF_DRIVER_GUID;

    if (pCreatorId == NULL)
        return "Unknown";

    if (cperGuidEqual(pCreatorId, &creatorPfDrv))
        return "NVIDIA GPU PF Driver";
    if (cperGuidEqual(pCreatorId, &creatorPfGspFw))
        return "NVIDIA GPU PF GSP Firmware";

    return "Unknown";
}

/*
 * ============================================================================
 * NVIDIA Vendor-Specific CPER Section Format
 * ============================================================================
 */

/*
 * NVIDIA Event Section Type GUID
 * Used in section descriptor's sectionType field
 */
#define NV_CPER_SECTION_NVIDIA_EVENT_GUID \
    NV_CPER_GUID_INIT(0x9068E568, 0x6CA0, 0x11F0, 0xAE, 0xAF, 0x15, 0x93, 0x43, 0x59, 0x1E, 0xAC)

/*
 * NVIDIA Event Section Source Device Types
 */
typedef NvU8 NV_CPER_NV_SOURCE_DEVICE_TYPE;
#define NV_CPER_NV_SOURCE_DEVICE_TYPE_GPU 1

static NV_INLINE const char *
cperNvidiaSourceDeviceTypeToString(NV_CPER_NV_SOURCE_DEVICE_TYPE deviceType)
{
    switch (deviceType)
    {
        case NV_CPER_NV_SOURCE_DEVICE_TYPE_GPU: return "GPU";
        default:                                return "Unknown";
    }
}

/*
 * GPU Event Originator values
 */
typedef enum NV_CPER_NV_GPU_EVENT_ORIGINATOR
{
    NV_CPER_NV_GPU_ORIGINATOR_INVALID        = 0,
    NV_CPER_NV_GPU_ORIGINATOR_PF_GSP_FW      = 2,
    NV_CPER_NV_GPU_ORIGINATOR_VF_GSP_FW      = 3,
    NV_CPER_NV_GPU_ORIGINATOR_PF_DRIVER      = 4,
    NV_CPER_NV_GPU_ORIGINATOR_VF_DRIVER      = 5,
} NV_CPER_NV_GPU_EVENT_ORIGINATOR;

static NV_INLINE const char *
cperNvidiaGpuEventOriginatorToString(NV_CPER_NV_GPU_EVENT_ORIGINATOR originator)
{
    switch (originator)
    {
        case NV_CPER_NV_GPU_ORIGINATOR_INVALID:   return "Invalid";
        case NV_CPER_NV_GPU_ORIGINATOR_PF_GSP_FW: return "PF GSP FW";
        case NV_CPER_NV_GPU_ORIGINATOR_VF_GSP_FW: return "VF GSP FW";
        case NV_CPER_NV_GPU_ORIGINATOR_PF_DRIVER: return "PF Driver";
        case NV_CPER_NV_GPU_ORIGINATOR_VF_DRIVER: return "VF Driver";
        default:                                  return "Unknown";
    }
}

/*
 * GPU Recovery Actions
 */
typedef enum NV_CPER_NV_GPU_RECOVERY_ACTION
{
    NV_CPER_NV_GPU_RECOVERY_IGNORE          = 0,
    NV_CPER_NV_GPU_RECOVERY_DRIVER_RELOAD   = 1,
    NV_CPER_NV_GPU_RECOVERY_FLR             = 2,  // Function-Level Reset
    NV_CPER_NV_GPU_RECOVERY_HOT_RESET       = 3,
    NV_CPER_NV_GPU_RECOVERY_WARM_RESET      = 4,
    NV_CPER_NV_GPU_RECOVERY_COLD_RESET      = 5,
    NV_CPER_NV_GPU_RECOVERY_NODE_RESET      = 6
} NV_CPER_NV_GPU_RECOVERY_ACTION;

/*
 * GPU Recommended Actions Flags
 */
#define NV_CPER_NV_GPU_REC_FLAG_ALREADY_RECOVERED      NVBIT(0)
#define NV_CPER_NV_GPU_REC_FLAG_IMMEDIATE_SERVICE      NVBIT(1)
#define NV_CPER_NV_GPU_REC_FLAG_MORE_ANALYSIS_REQUIRED NVBIT(2)

/*
 * ============================================================================
 * NVIDIA Event Section Binary Structures
 * ============================================================================
 */

/*
 * NVIDIA Event Section Header
 * Total size: 32 bytes (fixed) + variable EVENT_INFO + variable EVENT_CONTEXTs
 */
#define NV_CPER_NV_EVENT_HEADER_VERSION     1
#define NV_CPER_NV_MODULE_SIGNATURE_LEN     16

#pragma pack(1)
typedef struct NV_CPER_NV_EVENT_HEADER
{
    NvU8  version;                                        // Version of this header (currently 1)
    NvU8  eventContextCount;                              // Number of EVENT_CONTEXT structures
    NvU8  sourceDeviceType;                               // NV_CPER_NV_SOURCE_DEVICE_TYPE
    NvU8  reserved;                                       // Reserved, set to 0
    NvU16 eventType;                                      // Top-level event type
    NvU16 eventSubType;                                   // Event sub-type
    NvU64 eventLinkId;                                    // Links related events (0 if unused)
    NvU8  sourceModuleSignature[NV_CPER_NV_MODULE_SIGNATURE_LEN]; // NUL-terminated ASCII module name
} NV_CPER_NV_EVENT_HEADER;
#pragma pack()

/*
 * GPU EVENT_INFO structure (Version 1.0)
 * Total size: 16 bytes
 */
#define NV_CPER_NV_GPU_EVENT_INFO_VERSION_MAJOR  1
#define NV_CPER_NV_GPU_EVENT_INFO_VERSION_MINOR  0
#define NV_CPER_NV_GPU_EVENT_INFO_VERSION        \
    ((NV_CPER_NV_GPU_EVENT_INFO_VERSION_MINOR) | (NV_CPER_NV_GPU_EVENT_INFO_VERSION_MAJOR << 8))
#define NV_CPER_NV_GPU_EVENT_INFO_SIZE           16

#pragma pack(1)
typedef struct NV_CPER_NV_GPU_EVENT_INFO
{
    NvU16 version;           // Format version (1.0 = 0x0100)
    NvU8  size;              // Size of this structure (16)
    NvU8  eventOriginator;   // NV_CPER_NV_GPU_EVENT_ORIGINATOR
    NvU16 sourcePartition;   // GPU instance (for MIG)
    NvU16 sourceSubPartition;// Compute instance (for MIG)
    NvU64 pdi;               // Per-Device Identifier (globally unique)
} NV_CPER_NV_GPU_EVENT_INFO;
#pragma pack()

/*
 * EVENT_CONTEXT Data Format Types
 */
typedef enum NV_CPER_NV_CONTEXT_DATA_FORMAT
{
    // Common data format types (bit 15 = 0)
    NV_CPER_NV_DATA_FORMAT_OPAQUE            = 0x0000,
    NV_CPER_NV_DATA_FORMAT_KEY_VALUE_64      = 0x0001,
    NV_CPER_NV_DATA_FORMAT_KEY_VALUE_32      = 0x0002,
    NV_CPER_NV_DATA_FORMAT_VALUES_64         = 0x0003,
    NV_CPER_NV_DATA_FORMAT_VALUES_32         = 0x0004,

    // GPU-specific data format types (bit 15 = 1)
    NV_CPER_NV_DATA_FORMAT_GPU_INIT_METADATA = 0x8000,
    NV_CPER_NV_DATA_FORMAT_GPU_LEGACY_XID    = 0x8001,
    NV_CPER_NV_DATA_FORMAT_GPU_REC_ACTIONS   = 0x8002,
} NV_CPER_NV_CONTEXT_DATA_FORMAT;

/*
 * EVENT_CONTEXT Header structure
 */
#define NV_CPER_NV_EVENT_CONTEXT_VERSION_MAJOR  0
#define NV_CPER_NV_EVENT_CONTEXT_VERSION_MINOR  0
#define NV_CPER_NV_EVENT_CONTEXT_VERSION        \
    ((NV_CPER_NV_EVENT_CONTEXT_VERSION_MINOR) | (NV_CPER_NV_EVENT_CONTEXT_VERSION_MAJOR << 8))

#pragma pack(1)
typedef struct NV_CPER_NV_EVENT_CONTEXT_HEADER
{
    NvU32 contextSize;       // Total size including header, data, and padding (multiple of 16)
    NvU16 version;           // Header version (0.0 = 0x0000)
    NvU16 reserved;          // Reserved, set to 0
    NvU16 dataFormatType;    // NV_CPER_NV_CONTEXT_DATA_FORMAT
    NvU16 dataFormatVersion; // Version of the data format
    NvU32 dataSize;          // Size of data in bytes
} NV_CPER_NV_EVENT_CONTEXT_HEADER;
#pragma pack()

/*
 * GPU Initialization Metadata (Data Format Type 0x8000, Version 1.0)
 * Total size: 192 bytes
 */
#define NV_CPER_NV_GPU_INIT_META_VERSION_MAJOR  1
#define NV_CPER_NV_GPU_INIT_META_VERSION_MINOR  0
#define NV_CPER_NV_GPU_INIT_META_VERSION        \
    ((NV_CPER_NV_GPU_INIT_META_VERSION_MINOR) | (NV_CPER_NV_GPU_INIT_META_VERSION_MAJOR << 8))
#define NV_CPER_NV_GPU_INIT_META_SIZE           192

#pragma pack(1)
typedef struct NV_CPER_NV_GPU_INIT_METADATA
{
    NvU8  deviceName[48];
    NvU8  firmwareVersion[16];
    NvU8  pfDriverMicrocodeVersion[16];
    NvU8  pfDriverVersion[16];
    NvU8  vfDriverVersion[16];
    NvU64 configuration;
    NvU64 pdi;
    NvU32 architectureId;
    NvU8  hardwareInfoType;
    NvU8  pciClass;
    NvU8  pciSubclass;
    NvU8  pciRev;
    NvU16 pciVendorId;
    NvU16 pciDeviceId;
    NvU16 pciSubsystemVendorId;
    NvU16 pciSubsystemId;
    NvU64 bar0Start;
    NvU64 bar0Size;
    NvU64 bar1Start;
    NvU64 bar1Size;
    NvU64 bar2Start;
    NvU64 bar2Size;
} NV_CPER_NV_GPU_INIT_METADATA;
#pragma pack()

/*
 * GPU Legacy Xid (Data Format Type 0x8001, Version 1.0)
 */
#define NV_CPER_NV_GPU_LEGACY_XID_VERSION_MAJOR  1
#define NV_CPER_NV_GPU_LEGACY_XID_VERSION_MINOR  0
#define NV_CPER_NV_GPU_LEGACY_XID_VERSION        \
    ((NV_CPER_NV_GPU_LEGACY_XID_VERSION_MINOR) | (NV_CPER_NV_GPU_LEGACY_XID_VERSION_MAJOR << 8))
#define NV_CPER_NV_GPU_LEGACY_XID_MAX_MSG_LEN    236

//
// MSVC warning C4200 on "NV_CPER_NV_GPU_LEGACY_XID::message": zero-sized array in struct/union
// Ignore the warning on VS2013+
//
#pragma pack(1)
typedef struct NV_CPER_NV_GPU_LEGACY_XID
{
    NvU32 xidCode;
    char message[];
} NV_CPER_NV_GPU_LEGACY_XID;
#pragma pack()

/*
 * GPU Recommended Actions (Data Format Type 0x8002, Version 1.0)
 * Total size: 16 bytes
 */
#define NV_CPER_NV_GPU_REC_ACTIONS_VERSION_MAJOR  1
#define NV_CPER_NV_GPU_REC_ACTIONS_VERSION_MINOR  0
#define NV_CPER_NV_GPU_REC_ACTIONS_VERSION        \
    ((NV_CPER_NV_GPU_REC_ACTIONS_VERSION_MINOR) | (NV_CPER_NV_GPU_REC_ACTIONS_VERSION_MAJOR << 8))
#define NV_CPER_NV_GPU_REC_ACTIONS_SIZE           16

#pragma pack(1)
typedef struct NV_CPER_NV_GPU_RECOMMENDED_ACTIONS
{
    NvU8  flags;
    NvU8  reserved[3];
    NvU16 recoveryAction;
    NvU16 diagnosticFlow;
    NvU8  reserved2[8];
} NV_CPER_NV_GPU_RECOMMENDED_ACTIONS;
#pragma pack()

/*
 * ============================================================================
 * NVIDIA GPU Event Section API
 * ============================================================================
 */

/**
 * @brief Handle for an NVIDIA GPU event section
 *
 * This handle is returned by cperAddNvidiaEventSection() and used to
 * incrementally add context data to the section.
 */
typedef struct NV_CPER_NV_EVENT_SECTION_STATE
{
    NV_CPER_SECTION_STATE section;         ///< Underlying section handle
    NvU32                  nextContextOffset; ///< Offset where next context should be written
} NV_CPER_NV_EVENT_SECTION_STATE;

/**
 * @brief Parameters for adding an NVIDIA GPU event section
 */
typedef struct NV_CPER_NV_EVENT_PARAMS
{
    // Section descriptor fields
    NV_CPER_SEVERITY   severity;               ///< Section severity
    NvU32              sectionFlags;           ///< Section flags (NV_CPER_SECTION_FLAG_*)
    const NV_CPER_GUID *pFruId;                ///< FRU ID (GPU UUID), NULL if not available
    const char         *pFruText;              ///< FRU text description, NULL if not available

    // Event header fields
    NvU16              eventType;              ///< Event type code
    NvU16              eventSubType;           ///< Event sub-type code
    const char        *pModuleSignature;       ///< Module name (max 15 chars), NULL for empty
    NvU64              eventLinkId;            ///< Event link ID (0 if unused)

    // GPU event info
    NV_CPER_NV_GPU_EVENT_ORIGINATOR originator;///< Who originated the event
    NvU64              pdi;                    ///< Per-Device Identifier
    NvU16              sourcePartition;        ///< MIG GPU instance (0 if not MIG)
    NvU16              sourceSubPartition;     ///< MIG compute instance (0 if not MIG)
} NV_CPER_NV_EVENT_PARAMS;

/**
 * @brief Add an NVIDIA GPU event section to an existing CPER record
 *
 * This function adds an NVIDIA vendor-specific event section to an existing
 * CPER record. The section includes the event header and GPU event info,
 * but no context data initially. Use cperNvidiaEventSectionAddContext() to
 * add context data after this call.
 *
 * @param[in,out] pBuffer      Buffer containing the CPER record
 * @param[in]     bufferSize   Total size of the buffer in bytes
 * @param[in]     pParams      Event section parameters
 * @param[out]    pState       State for the created section (used to add contexts)
 *
 * @return NV_OK on success
 * @return NV_ERR_INVALID_ARGUMENT if any required parameter is NULL
 * @return NV_ERR_BUFFER_TOO_SMALL if buffer is too small
 * @return NV_ERR_INVALID_STATE if buffer doesn't contain a valid CPER header
 */
NV_STATUS cperAddNvidiaEventSection(
    void                           *pBuffer,
    NvU32                           bufferSize,
    const NV_CPER_NV_EVENT_PARAMS  *pParams,
    NV_CPER_NV_EVENT_SECTION_STATE *pState
);

/**
 * @brief Add a context to an NVIDIA GPU event section
 *
 * This function adds a context header to the section and returns a pointer
 * to the data area where the caller can write context data directly.
 *
 * @param[in,out] pState            State from cperAddNvidiaEventSection()
 * @param[in]     dataFormatType    Context data format type (NV_CPER_NV_DATA_FORMAT_*)
 * @param[in]     dataFormatVersion Version of the data format
 * @param[in]     dataSize          Size of context data in bytes
 * @param[out]    ppData            Pointer to the data area (caller writes here)
 *
 * @return NV_OK on success
 * @return NV_ERR_INVALID_ARGUMENT if pState or ppData is NULL
 * @return NV_ERR_BUFFER_TOO_SMALL if buffer is too small for the context
 */
NV_STATUS cperNvidiaEventSectionAddContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    NvU16                           dataFormatType,
    NvU16                           dataFormatVersion,
    NvU32                           dataSize,
    void                          **ppData
);

/**
 * @brief Adjust the data size of the last added context
 *
 * Use this to shrink-wrap a context after writing variable-length data
 * (e.g., a string shorter than the initially allocated size).
 *
 * @param[in,out] pState       State from cperAddNvidiaEventSection()
 * @param[in]     pData        Pointer returned by cperNvidiaEventSectionAddContext()
 * @param[in]     newDataSize  New data size (must be <= original size)
 *
 * @return NV_OK on success
 * @return NV_ERR_INVALID_ARGUMENT if pState or pData is NULL
 * @return NV_ERR_INVALID_ARGUMENT if newDataSize > original size
 */
NV_STATUS cperNvidiaEventSectionSetContextDataSize(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    void                           *pData,
    NvU32                           newDataSize
);

/*
 * ============================================================================
 * Typed Context Addition Functions
 * ============================================================================
 */

/**
 * @brief Add GPU initialization metadata context
 *
 * @param[in,out] pState     State from cperAddNvidiaEventSection()
 * @param[in]     pMetadata  Pointer to init metadata to copy
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAddGpuInitMetadataContext(
    NV_CPER_NV_EVENT_SECTION_STATE     *pState,
    const NV_CPER_NV_GPU_INIT_METADATA *pMetadata
);

/**
 * @brief Add GPU legacy Xid context
 *
 * @param[in,out] pState     State from cperAddNvidiaEventSection()
 * @param[in]     xidCode    Xid error code
 * @param[in]     pMessage   Optional NUL-terminated message (may be NULL)
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAddGpuLegacyXidContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    NvU32                           xidCode,
    const char                     *pMessage
);

/**
 * @brief Add GPU recommended actions context
 *
 * @param[in,out] pState     State from cperAddNvidiaEventSection()
 * @param[in]     pActions   Pointer to recommended actions to copy
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAddGpuRecActionsContext(
    NV_CPER_NV_EVENT_SECTION_STATE          *pState,
    const NV_CPER_NV_GPU_RECOMMENDED_ACTIONS *pActions
);

/**
 * @brief Add opaque binary data context
 *
 * @param[in,out] pState   State from cperAddNvidiaEventSection()
 * @param[in]     pData    Pointer to data to copy
 * @param[in]     dataSize Size of data in bytes
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAddOpaqueContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    const void                     *pData,
    NvU32                           dataSize
);

/**
 * @brief Add 64-bit key-value pairs context (8BKV)
 *
 * @param[in,out] pState      State from cperAddNvidiaEventSection()
 * @param[in]     pKeyValues  Array of key-value pairs (key: NvU64, value: NvU64)
 * @param[in]     count       Number of key-value pairs
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAdd8BKVContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    const NvU64                    *pKeyValues,
    NvU32                           count
);

/**
 * @brief Add 32-bit key-value pairs context (4BKV)
 *
 * @param[in,out] pState      State from cperAddNvidiaEventSection()
 * @param[in]     pKeyValues  Array of key-value pairs (key: NvU32, value: NvU32)
 * @param[in]     count       Number of key-value pairs
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAdd4BKVContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    const NvU32                    *pKeyValues,
    NvU32                           count
);

/**
 * @brief Add 64-bit values context (8BV)
 *
 * @param[in,out] pState   State from cperAddNvidiaEventSection()
 * @param[in]     pValues  Array of 64-bit values
 * @param[in]     count    Number of values
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAdd8BVContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    const NvU64                    *pValues,
    NvU32                           count
);

/**
 * @brief Add 32-bit values context (4BV)
 *
 * @param[in,out] pState   State from cperAddNvidiaEventSection()
 * @param[in]     pValues  Array of 32-bit values
 * @param[in]     count    Number of values
 *
 * @return NV_OK on success
 */
NV_STATUS cperNvidiaEventAdd4BVContext(
    NV_CPER_NV_EVENT_SECTION_STATE *pState,
    const NvU32                    *pValues,
    NvU32                           count
);

/*
 * ============================================================================
 * Dump/Decode Helpers (Logging)
 * ============================================================================
 */

/*!
 * @brief Dump NVIDIA CPER record header fields (notify/creator/severity)
 */
void cperNvidiaEventDumpRecordHeader(
    const NV_CPER_RECORD_HEADER *pHdr,
    NvU32                        seq,
    const char                  *pLogPrefix
);

/*!
 * @brief Dump an NVIDIA event section (NV_CPER_SECTION_NVIDIA_EVENT_GUID)
 */
void cperNvidiaEventDumpSection(
    NvU32                           eventIdx,
    const NV_CPER_RECORD_HEADER    *pHdr,
    const NV_CPER_SECTION_DESCRIPTOR *pDesc,
    const NvU8                     *pSection,
    NvU32                           sectionLength,
    NvU32                           seq,
    const char                     *pLogPrefix
);

#endif /* GPU_CPER_H */
