Rust for Linux List
 help / color / mirror / Atom feed
From: Timur Tabi <ttabi@nvidia.com>
To: "ojeda@kernel.org" <ojeda@kernel.org>,
	"dakr@kernel.org" <dakr@kernel.org>
Cc: John Hubbard <jhubbard@nvidia.com>,
	"gary@garyguo.net" <gary@garyguo.net>,
	Eliot Courtney <ecourtney@nvidia.com>, Zhi Wang <zhiw@nvidia.com>,
	"russ.weight@linux.dev" <russ.weight@linux.dev>,
	"mcgrof@kernel.org" <mcgrof@kernel.org>,
	"rust-for-linux@vger.kernel.org" <rust-for-linux@vger.kernel.org>,
	Alexandre Courbot <acourbot@nvidia.com>,
	"driver-core@lists.linux.dev" <driver-core@lists.linux.dev>,
	"nova-gpu@lists.linux.dev" <nova-gpu@lists.linux.dev>
Subject: Re: [PATCH v7 3/8] gpu: nova-core: add TLV parser for firmware files
Date: Mon, 3 Aug 2026 22:05:24 +0000	[thread overview]
Message-ID: <0c53c38adec26bc5df6b4658d3da53075001d93a.camel@nvidia.com> (raw)
In-Reply-To: <DKFMSHHGF3DE.2SUUP3FB7WXTK@kernel.org>

On Mon, 2026-08-03 at 23:36 +0200, Danilo Krummrich wrote:
> @Miguel: One consideration for you below.
> 
> On Fri Jul 31, 2026 at 10:10 PM CEST, Timur Tabi wrote:
> > +impl<'a> Tlv<'a> {
> > +    const MAGIC: &'static [u8; 4] = b"NVFW";
> > +
> > +    /// Parses `data` as a TLV firmware image, returning [`EINVAL`] if the image is
> > malformed.
> > +    pub(crate) fn new(data: &'a [u8]) -> Result<Self> {
> > +        // Verify that the magic bytes exist and are the correct value
> > +        let magic_len = Self::MAGIC.len();
> > +        if data
> > +            .get(..magic_len)
> > +            .is_none_or(|magic| magic != Self::MAGIC)
> > +        {
> > +            return Err(EINVAL);
> > +        }
> > +
> > +        // The payload is the contiguous sequence of TLV blocks after the magic.
> > +        let payload = data.get(magic_len..).ok_or(EINVAL)?;
> > +
> > +        if payload.is_empty() {
> > +            // Reject empty TLV files
> > +            return Err(ENODATA);
> > +        }
> 
> This seems redundant, if payload is empty the below loop wouldn't execute and
> the !has_vers check would return EINVAL. Which seems consistent, since empty
> data is kinda invalid.

I frequently struggle to find the right error code in kernel code, especially for situations
where some data structure is not quite right.

> > +        // The spec says every TLV must have a VERS tag.
> > +        let mut has_vers = false;
> > +
> > +        let mut rest = payload;
> > +        while !rest.is_empty() {
> > +            // Validate and extract the header (type, length).
> > +            let Some(header): Option<TlvBlockHeader> = rest
> > +                .get(..TlvBlockHeader::SIZE)
> > +                .and_then(TlvBlockHeader::parse)
> > +            else {
> > +                return Err(EINVAL);
> > +            };
> > +
> > +            has_vers |= header.tag == *b"VERS";
> > +
> > +            // The `length` field of a TLV block contains the actual byte length of the
> > +            // value, but each TLV block is aligned to a 4-byte boundary.
> > +            let Some(stored_size) = header.length.checked_next_multiple_of(4) else {
> > +                return Err(EINVAL);
> > +            };
> > +
> > +            let length = TlvBlockHeader::SIZE
> > +                .checked_add(stored_size)
> > +                .ok_or(EINVAL)?;
> > +
> > +            rest = rest.split_at_checked(length).ok_or(EINVAL)?.1;
> > +        }
> > +
> > +        if !has_vers {
> > +            return Err(EINVAL);
> > +        }
> 
> [...]
> 
> > +    fn find(&self, tag: &[u8; 4]) -> Result<TlvBlock<'a>> {
> > +        self.iter().find(|b| b.tag == *tag).ok_or(EINVAL)
> > +    }
> 
> NIT: Do we really know the tag is invalid just because it wasn't found?

Well, maybe this is where we should return ENODATA?

I am expecting future Nova code to handle tags that may be legitimately absent, so maybe having
it return ENODATA if the tag is missing, and EINVAL in all other situations is better.

> > +    /// Return a slice of bytes.  Returns ENODATA if the value is empty.
> > +    pub(crate) fn get_bytes(&self, tag: &[u8; 4]) -> Result<&'a [u8]> {
> > +        let tlv = self.find(tag)?;
> > +
> > +        // Treat empty value as an error, to avoid trying to parse nothing.
> > +        if tlv.value.is_empty() {
> > +            return Err(ENODATA);
> > +        }
> 
> This one seems resonable; but we don't have the error code in place. The commit
> message says the series depends on [1], but this likely goes through the Rust
> tree.

Can't you just pick it up from the Rust tree and put it in drm-rust-next?

> Either we just add this single error code in a separate patch or Miguel provides
> a signed tag for [1].
> 
> Since this is a perfectly trivial conflict, I'd go for the former.

The latter seems simpler to me, and would avoid an annoying merge conflict.

  parent reply	other threads:[~2026-08-03 22:05 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31 20:10 [PATCH v7 0/8] Transition Nova Core to TLV firmware images Timur Tabi
2026-07-31 20:10 ` [PATCH v7 1/8] rust: alloc: add Vec::zeroed method Timur Tabi
2026-08-03 21:22   ` Danilo Krummrich
2026-07-31 20:10 ` [PATCH v7 2/8] rust: firmware: add request_into_buf() Timur Tabi
2026-07-31 20:10 ` [PATCH v7 3/8] gpu: nova-core: add TLV parser for firmware files Timur Tabi
2026-08-03 21:36   ` Danilo Krummrich
2026-08-03 21:38     ` Danilo Krummrich
2026-08-03 22:05     ` Timur Tabi [this message]
2026-08-03 22:21       ` Danilo Krummrich
2026-08-04 17:10         ` Timur Tabi
2026-07-31 20:10 ` [PATCH v7 4/8] gpu: nova-core: transition booter to TLV images Timur Tabi
2026-07-31 20:10 ` [PATCH v7 5/8] gpu: nova-core: transition gsp " Timur Tabi
2026-07-31 20:10 ` [PATCH v7 6/8] gpu: nova-core: transition gen_bootloader " Timur Tabi
2026-07-31 20:10 ` [PATCH v7 7/8] gpu: nova-core: transition fsp " Timur Tabi
2026-07-31 20:10 ` [PATCH v7 8/8] gpu: nova-core: update firmware module info for " Timur Tabi
2026-08-03 13:51 ` [PATCH v7 0/8] Transition Nova Core to TLV firmware images Alexandre Courbot
2026-08-06  0:12 ` Danilo Krummrich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0c53c38adec26bc5df6b4658d3da53075001d93a.camel@nvidia.com \
    --to=ttabi@nvidia.com \
    --cc=acourbot@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=driver-core@lists.linux.dev \
    --cc=ecourtney@nvidia.com \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=mcgrof@kernel.org \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ojeda@kernel.org \
    --cc=russ.weight@linux.dev \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=zhiw@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox