1 // SPDX-License-Identifier: GPL-2.0 2 // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 //! MCTP/NVDM protocol types for NVIDIA GPU firmware communication. 5 //! 6 //! MCTP (Management Component Transport Protocol) carries NVDM (NVIDIA 7 //! Data Model) messages between the kernel driver and GPU firmware processors 8 //! such as FSP and GSP. 9 10 use kernel::{ 11 bitfield, 12 pci::Vendor, 13 prelude::*, // 14 }; 15 16 use crate::{ 17 bounded_enum, 18 num, // 19 }; 20 21 bounded_enum! { 22 /// NVDM message type identifiers carried over MCTP. 23 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 24 pub(crate) enum NvdmType with TryFrom<Bounded<u32, 8>> { 25 /// Chain of Trust boot message. 26 Cot = 0x14, 27 /// FSP command response. 28 FspResponse = 0x15, 29 } 30 } 31 32 bitfield! { 33 /// MCTP transport header for NVIDIA firmware messages. 34 pub(crate) struct MctpHeader(u32) { 35 /// Start-of-message bit. 36 31:31 som; 37 /// End-of-message bit. 38 30:30 eom; 39 /// Packet sequence number. 40 29:28 seq; 41 /// Source endpoint ID. 42 23:16 seid; 43 } 44 } 45 46 impl MctpHeader { 47 /// Builds a single-packet MCTP header (`SOM=1`, `EOM=1`, `SEQ=0`, `SEID=0`). 48 pub(crate) fn single_packet() -> Self { 49 Self::zeroed().with_som(true).with_eom(true) 50 } 51 52 /// Returns whether this is a complete single-packet message (`SOM=1` and `EOM=1`). 53 pub(crate) fn is_single_packet(self) -> bool { 54 self.som().into_bool() && self.eom().into_bool() 55 } 56 } 57 58 /// MCTP message type for PCI vendor-defined messages. 59 const MSG_TYPE_VENDOR_PCI: u8 = 0x7e; 60 61 bitfield! { 62 /// NVIDIA Vendor-Defined Message header over MCTP. 63 pub(crate) struct NvdmHeader(u32) { 64 /// NVDM message type. 65 31:24 nvdm_type ?=> NvdmType; 66 /// PCI vendor ID. 67 23:8 vendor_id; 68 /// MCTP vendor-defined message type. 69 6:0 msg_type; 70 } 71 } 72 73 impl NvdmHeader { 74 /// Builds an NVDM header for the given message type. 75 pub(crate) fn new(nvdm_type: NvdmType) -> Self { 76 Self::zeroed() 77 .with_const_msg_type::<{ num::u8_as_u32(MSG_TYPE_VENDOR_PCI) }>() 78 .with_vendor_id(Vendor::NVIDIA.as_raw()) 79 .with_nvdm_type(nvdm_type) 80 } 81 82 /// Validates this header against the expected NVIDIA NVDM format and type. 83 pub(crate) fn validate(self, expected_type: NvdmType) -> bool { 84 u8::from(self.msg_type()) == MSG_TYPE_VENDOR_PCI 85 && u16::from(self.vendor_id()) == Vendor::NVIDIA.as_raw() 86 && matches!(self.nvdm_type(), Ok(nvdm_type) if nvdm_type == expected_type) 87 } 88 } 89