Add README and doc comments

Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: Ie4cf762558b181139e1456887a0e4687b0243564
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e969932
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+# Arm Firmware Framework for Arm A-profile (FF-A) support library
+
+[Arm Firmware Framework for Arm A-profile (FF-A) specification](https://developer.arm.com/documentation/den0077/latest/)
+
+[FF-A Memory Management Protocol specification](https://developer.arm.com/documentation/den0140/latest/)
+
+Library for handling common FF-A related functionality, create and parse interfaces and descriptors
+defined by FF-A.
+
+## Design goals
+  * Keep the code exception level agnostic by default. If exception level specific parts are
+    inevitable, make it optional via a feature flag.
+  * Keep the code no_std compatible. Use only core by default, make parts using alloc optional via
+    a feature flag.
+  * The interface towards the library's users should be ergonomic Rust and following Rust
+    best-practices where possible.
+    * Incorrect usage of this library when creating/packing/serializing data structures provided by
+      this library is seen as a programmer error and the library will panic.
+    * Parsing/unpacking/deserializing data structures provided by this library from a buffer is seen
+      as runtime "user input data", and the library should make all necessary checks to validate the
+      data. In this case the library should never panic, but return rich error types (preferably use
+      `thiserror`) so the library user knows what's wrong.
+  * The FF-A descriptors, packed structs and bit shifting magic should be private for the library,
+    never exposed to the library user (i.e. `ffa_v1_1` and later modules).
+    * The implementation of such data structures should strictly follow the FF-A specification.
+    * Preferably write a doc comment for each such definition that specifies where it comes from in
+      the spec (i.e. Table x.y or chapter x.y.z)
+    * The data structures should derive the necessary `zerocopy` traits.
+
+## Implemented features
+
+  * Supports converting FF-A interface types between Rust types and the FF-A register ABI.
+  * Memory transaction descriptor handling for `FFA_MEM_*` interfaces (partial).
+  * FF-A v1.1+ boot information protocol.
+  * FF-A partiton information descriptor.
+
+## Future plans
+
+  * Implement missing features from FF-A v1.1 and later. Implementing FF-A v1.0 features that are
+    deprecated by v1.1 are low priority for now.
+  * Create more detailed documentation to capture which parts of FF-A are currently supported.
+
+## License
+
+The project is MIT and Apache-2.0 dual licensed, see `LICENSE-APACHE` and `LICENSE-MIT`.
+
+## Maintainers
+
+arm-ffa is a trustedfirmware.org maintained project. All contributions are ultimately merged by the
+maintainers listed below.
+
+* Bálint Dobszay <balint.dobszay@arm.com>
+  [balint-dobszay-arm](https://github.com/balint-dobszay-arm)
+* Imre Kis <imre.kis@arm.com>
+  [imre-kis-arm](https://github.com/imre-kis-arm)
+* Sandrine Afsa <sandrine.afsa@arm.com>
+  [sandrine-bailleux-arm](https://github.com/sandrine-bailleux-arm)
+
+## Contributing
+
+Please follow the directions of the [Trusted Firmware Processes](https://trusted-firmware-docs.readthedocs.io/en/latest/generic_processes/index.html)
+
+Contributions are handled through [review.trustedfirmware.org](https://review.trustedfirmware.org/q/project:rust-spmc/arm-ffa).
+
+## Reporting Security Issues
+
+Please follow the directions of the [Trusted Firmware Security Center](https://trusted-firmware-docs.readthedocs.io/en/latest/security_center/index.html)
+
+--------------
+
+*Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>*
+
+*Arm is a registered trademark of Arm Limited (or its subsidiaries or affiliates).*
diff --git a/src/boot_info.rs b/src/boot_info.rs
index 30850e5..446ff08 100644
--- a/src/boot_info.rs
+++ b/src/boot_info.rs
@@ -1,6 +1,21 @@
 // SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
+//! Implementation of the FF-A Boot information protocol.
+//!
+//! An SP or SPMC could rely on boot information for their initialization e.g. a flattened device
+//! tree with nodes to describe the devices and memory regions assigned to the SP or SPMC. FF-A
+//! specifies a protocol that can be used by a producer to pass boot information to a consumer at a
+//! Secure FF-A instance. The Framework assumes that the boot information protocol is used by a
+//! producer and consumer pair that reside at adjacent exception levels as listed below.
+//! - SPMD (producer) and an SPMC (consumer) in either S-EL1 or S-EL2.
+//! - An SPMC (producer) and SP (consumer) pair listed below.
+//!   - EL3 SPMC and a Logical S-EL1 SP.
+//!   - S-EL2 SPMC and Physical S-EL1 SP.
+//!   - EL3 SPMC and a S-EL0 SP.
+//!   - S-EL2 SPMC and a S-EL0 SP.
+//!   - S-EL1 SPMC and a S-EL0 SP.
+
 use crate::{
     ffa_v1_1::{boot_info_descriptor, boot_info_header},
     Version,
@@ -10,6 +25,8 @@
 use uuid::Uuid;
 use zerocopy::{FromBytes, IntoBytes};
 
+/// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used
+/// with the `FFA_ERROR` interface.
 #[derive(Debug, Error)]
 pub enum Error {
     #[error("Invalid standard type {0}")]
@@ -42,12 +59,14 @@
     }
 }
 
+/// Name of boot information descriptor.
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum BootInfoName<'a> {
     NullTermString(&'a CStr),
     Uuid(Uuid),
 }
 
+/// ID for supported standard boot information types.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 #[repr(u8)]
 pub enum BootInfoStdId {
@@ -72,6 +91,7 @@
     const HOB: u8 = 1;
 }
 
+/// ID for implementation defined boot information type.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct BootInfoImpdefId(pub u8);
 
@@ -81,6 +101,7 @@
     }
 }
 
+/// Boot information type.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum BootInfoType {
     Std(BootInfoStdId),
@@ -122,6 +143,7 @@
     const ID_MASK: u8 = 0b0111_1111;
 }
 
+/// Boot information contents.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum BootInfoContents<'a> {
     Address { content_buf: &'a [u8] },
@@ -208,6 +230,7 @@
     }
 }
 
+/// Boot information descriptor.
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct BootInfo<'a> {
     pub name: BootInfoName<'a>,
@@ -216,10 +239,15 @@
 }
 
 impl BootInfo<'_> {
+    /// Serialize a list of boot information descriptors into a buffer. The `mapped_addr` parameter
+    /// should contain the address of the buffer in the consumers translation regime (typically a
+    /// virtual address where the buffer is mapped to). This is necessary since there are
+    /// self-references within the serialized data structure which must be described with an
+    /// absolute address according to the FF-A spec.
     pub fn pack(descriptors: &[BootInfo], buf: &mut [u8], mapped_addr: Option<usize>) {
         // Offset from the base of the header to the first element in the boot info descriptor array
         // Must be 8 byte aligned, but otherwise we're free to choose any value here.
-        // Let's just  pack the array right after the header.
+        // Let's just pack the array right after the header.
         const DESC_ARRAY_OFFSET: usize = size_of::<boot_info_header>().next_multiple_of(8);
         const DESC_SIZE: usize = size_of::<boot_info_descriptor>();
 
@@ -365,11 +393,10 @@
         Ok(header_raw)
     }
 
-    /// Get the size of the boot information blob spanning contiguous memory.
-    ///
-    /// This enables a consumer to map all of the boot information blob in its translation regime
-    /// or copy it to another memory location without parsing each element in the boot information
-    /// descriptor array.
+    /// Get the size of the boot information blob spanning contiguous memory. This enables a
+    /// consumer to map all of the boot information blob in its translation regime or copy it to
+    /// another memory location without parsing each element in the boot information descriptor
+    /// array.
     pub fn get_blob_size(buf: &[u8]) -> Result<usize, Error> {
         let header_raw = Self::get_header(buf)?;
 
@@ -377,6 +404,7 @@
     }
 }
 
+/// Iterator of boot information descriptors.
 pub struct BootInfoIterator<'a> {
     buf: &'a [u8],
     offset: usize,
@@ -385,6 +413,7 @@
 }
 
 impl<'a> BootInfoIterator<'a> {
+    /// Create an iterator of boot information descriptors from a buffer.
     pub fn new(buf: &'a [u8]) -> Result<Self, Error> {
         let header_raw = BootInfo::get_header(buf)?;
 
diff --git a/src/lib.rs b/src/lib.rs
index 6f353f3..d4855b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,9 @@
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
 #![cfg_attr(not(test), no_std)]
+#![deny(clippy::undocumented_unsafe_blocks)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![doc = include_str!("../README.md")]
 
 use core::fmt::{self, Debug, Display, Formatter};
 use num_enum::{IntoPrimitive, TryFromPrimitive};
@@ -13,10 +16,12 @@
 pub mod memory_management;
 pub mod partition_info;
 
-// On many occasions the FF-A spec defines memory size as count of 4K pages,
-// regardless of the current translation granule
+/// Constant for 4K page size. On many occasions the FF-A spec defines memory size as count of 4K
+/// pages, regardless of the current translation granule.
 pub const FFA_PAGE_SIZE_4K: usize = 4096;
 
+/// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used
+/// with the `FFA_ERROR` interface.
 #[derive(Debug, Error)]
 pub enum Error {
     #[error("Unrecognised FF-A function ID {0}")]
@@ -38,13 +43,16 @@
     }
 }
 
+/// An FF-A instance is a valid combination of two FF-A components at an exception level boundary.
 #[derive(PartialEq, Clone, Copy)]
 pub enum Instance {
+    /// The instance between the SPMC and SPMD.
     SecurePhysical,
+    /// The instance between the SPMC and a physical SP (contains the SP's endpoint ID).
     SecureVirtual(u16),
 }
 
-/// FF-A v1.1: Function IDs
+/// Function IDs of the various FF-A interfaces.
 #[derive(Clone, Copy, Debug, Eq, IntoPrimitive, PartialEq, TryFromPrimitive)]
 #[num_enum(error_type(name = Error, constructor = Error::UnrecognisedFunctionId))]
 #[repr(u32)]
@@ -91,7 +99,7 @@
     ConsoleLog64 = 0xc400008a,
 }
 
-/// FF-A v1.1, Table 12.2: Error status codes
+/// Error status codes used by the `FFA_ERROR` interface.
 #[derive(Clone, Copy, Debug, Eq, Error, IntoPrimitive, PartialEq, TryFromPrimitive)]
 #[num_enum(error_type(name = Error, constructor = Error::UnrecognisedErrorCode))]
 #[repr(i32)]
@@ -116,6 +124,7 @@
     NoData = -9,
 }
 
+/// Endpoint ID and vCPU ID pair, used by `FFA_ERROR`, `FFA_INTERRUPT` and `FFA_RUN` interfaces.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub struct TargetInfo {
     pub endpoint_id: u16,
@@ -137,12 +146,14 @@
     }
 }
 
+/// Arguments for the `FFA_SUCCESS` interface.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum SuccessArgs {
     Result32([u32; 6]),
     Result64([u64; 6]),
 }
 
+/// Version number of the FF-A implementation, `.0` is the major, `.1` is minor the version.
 #[derive(Clone, Copy, Eq, PartialEq)]
 pub struct Version(pub u16, pub u16);
 
@@ -170,6 +181,7 @@
     }
 }
 
+/// Feature IDs used by the `FFA_FEATURES` interface.
 #[derive(Clone, Copy, Debug, Eq, IntoPrimitive, PartialEq, TryFromPrimitive)]
 #[num_enum(error_type(name = Error, constructor = Error::UnrecognisedFeatureId))]
 #[repr(u8)]
@@ -179,6 +191,7 @@
     ManagedExitInterrupt = 0x3,
 }
 
+/// Arguments for the `FFA_FEATURES` interface.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum Feature {
     FuncId(FuncId),
@@ -208,36 +221,46 @@
     }
 }
 
+/// RXTX buffer descriptor, used by `FFA_RXTX_MAP`.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum RxTxAddr {
     Addr32 { rx: u32, tx: u32 },
     Addr64 { rx: u64, tx: u64 },
 }
 
+/// Arguments for the `FFA_MSG_SEND_DIRECT_{REQ,RESP}` interfaces.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum DirectMsgArgs {
     Args32([u32; 5]),
     Args64([u64; 5]),
 }
 
+/// Descriptor for a dynamically allocated memory buffer that contains the memory transaction
+/// descriptor. Used by `FFA_MEM_{DONATE,LEND,SHARE,RETRIEVE_REQ}` interfaces, only when the TX
+/// buffer is not used to transmit the transaction descriptor.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum MemOpBuf {
     Buf32 { addr: u32, page_cnt: u32 },
     Buf64 { addr: u64, page_cnt: u32 },
 }
 
+/// Memory address argument for `FFA_MEM_PERM_{GET,SET}` interfaces.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum MemAddr {
     Addr32(u32),
     Addr64(u64),
 }
 
+/// Argument for the `FFA_CONSOLE_LOG` interface. Currently only supports x0..x7 instead of x0..x17.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum ConsoleLogChars {
     Reg32([u32; 6]),
     Reg64([u64; 6]),
 }
 
+/// FF-A "message types", the terminology used by the spec is "interfaces". The interfaces are used
+/// by FF-A components for communication at an FF-A instance. The spec also describes the valid FF-A
+/// instances and conduits for each interface.
 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
 pub enum Interface {
     Error {
@@ -743,6 +766,7 @@
         }
     }
 
+    /// Create register contents for an interface.
     pub fn copy_to_array(&self, a: &mut [u64; 8]) {
         a.fill(0);
         if let Some(function_id) = self.function_id() {
@@ -1001,7 +1025,7 @@
         }
     }
 
-    /// Helper function to create an FFA_SUCCESS interface without any arguments
+    /// Helper function to create an `FFA_SUCCESS` interface without any arguments.
     pub fn success32_noargs() -> Self {
         Self::Success {
             target_info: 0,
@@ -1009,7 +1033,7 @@
         }
     }
 
-    /// Helper function to create an FFA_ERROR interface without any arguments
+    /// Helper function to create an `FFA_ERROR` interface with an error code.
     pub fn error(error_code: FfaError) -> Self {
         Self::Error {
             target_info: TargetInfo {
@@ -1021,9 +1045,15 @@
     }
 }
 
-pub const CONSOLE_LOG_32_MAX_MSG_LEN: u8 = 24;
-pub const CONSOLE_LOG_64_MAX_MSG_LEN: u8 = 48;
+/// Maximum number of characters transmitted in a single `FFA_CONSOLE_LOG32` message.
+pub const CONSOLE_LOG_32_MAX_CHAR_CNT: u8 = 24;
+/// Maximum number of characters transmitted in a single `FFA_CONSOLE_LOG64` message. Note: this
+/// value currently differs from the spec because the library currently only supports parsing 8
+/// registers instead of 18.
+pub const CONSOLE_LOG_64_MAX_CHAR_CNT: u8 = 48;
 
+/// Helper function to convert the "Tightly packed list of characters" format used by the
+/// `FFA_CONSOLE_LOG` interface into a byte slice.
 pub fn parse_console_log(
     char_cnt: u8,
     char_lists: &ConsoleLogChars,
@@ -1031,7 +1061,7 @@
 ) -> Result<(), FfaError> {
     match char_lists {
         ConsoleLogChars::Reg32(regs) => {
-            if !(1..=CONSOLE_LOG_32_MAX_MSG_LEN).contains(&char_cnt) {
+            if !(1..=CONSOLE_LOG_32_MAX_CHAR_CNT).contains(&char_cnt) {
                 return Err(FfaError::InvalidParameters);
             }
             for (i, reg) in regs.iter().enumerate() {
@@ -1039,7 +1069,7 @@
             }
         }
         ConsoleLogChars::Reg64(regs) => {
-            if !(1..=CONSOLE_LOG_64_MAX_MSG_LEN).contains(&char_cnt) {
+            if !(1..=CONSOLE_LOG_64_MAX_CHAR_CNT).contains(&char_cnt) {
                 return Err(FfaError::InvalidParameters);
             }
             for (i, reg) in regs.iter().enumerate() {
diff --git a/src/memory_management.rs b/src/memory_management.rs
index 777a399..e81a5ca 100644
--- a/src/memory_management.rs
+++ b/src/memory_management.rs
@@ -1,6 +1,17 @@
 // SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
+//! Implementation of the FF-A Memory Management protocol.
+//!
+//! FF-A describes mechanisms and interfaces that enable FF-A components to manage access and
+//! ownership of memory regions in the physical address space. FF-A components can use a combination
+//! of Framework and Partition messages to manage memory regions in the following ways:
+//! - The Owner of a memory region can transfer its ownership to another FF-A endpoint.
+//! - The Owner of a memory region can transfer its access to one or more FF-A endpoints.
+//! - The Owner of a memory region can share access to it with one or more FF-A endpoints.
+//! - The Owner can reclaim access to a memory region after the FF-A endpoints that were granted
+//!   access to that memory region have relinquished their access.
+
 use crate::ffa_v1_1::{
     composite_memory_region_descriptor, constituent_memory_region_descriptor,
     endpoint_memory_access_descriptor, memory_access_permission_descriptor,
@@ -10,6 +21,8 @@
 use thiserror::Error;
 use zerocopy::{FromBytes, IntoBytes};
 
+/// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used
+/// with the `FFA_ERROR` interface.
 #[derive(Debug, Error)]
 pub enum Error {
     #[error("Invalid cacheability attribute {0}")]
@@ -42,6 +55,7 @@
     }
 }
 
+/// Memory region handle, used to identify a composite memory region description.
 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Handle(pub u64);
 
@@ -61,6 +75,7 @@
     pub const INVALID: u64 = 0xffff_ffff_ffff_ffff;
 }
 
+/// Cacheability attribute of a memory region. Only valid for normal memory.
 #[derive(Debug, Default, Clone, Copy, PartialEq)]
 #[repr(u16)]
 pub enum Cacheability {
@@ -88,6 +103,7 @@
     const WRITE_BACK: u16 = 0b11;
 }
 
+/// Shareability attribute of a memory region. Only valid for normal memory.
 #[derive(Debug, Default, Clone, Copy, PartialEq)]
 #[repr(u16)]
 pub enum Shareability {
@@ -118,6 +134,7 @@
     const INNER: u16 = 0b11;
 }
 
+/// Device memory attributes.
 #[derive(Debug, Default, Clone, Copy)]
 #[repr(u16)]
 pub enum DeviceMemAttributes {
@@ -151,6 +168,7 @@
     const DEV_GRE: u16 = 0b11;
 }
 
+/// Memory region type.
 #[derive(Debug, Default, Clone, Copy)]
 pub enum MemType {
     #[default]
@@ -199,6 +217,7 @@
     const NORMAL: u16 = 0b10;
 }
 
+/// Memory region security attribute.
 #[derive(Debug, Default, Clone, Copy, PartialEq)]
 #[repr(u16)]
 pub enum MemRegionSecurity {
@@ -224,6 +243,7 @@
     const NON_SECURE: u16 = 0b1;
 }
 
+/// Memory region attributes descriptor.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct MemRegionAttributes {
     pub security: MemRegionSecurity,
@@ -252,6 +272,7 @@
     }
 }
 
+/// Instruction access permissions of a memory region.
 #[derive(Debug, Default, Clone, Copy)]
 #[repr(u8)]
 pub enum InstuctionAccessPerm {
@@ -282,6 +303,7 @@
     const EXECUTABLE: u8 = 0b10;
 }
 
+/// Data access permissions of a memory region.
 #[derive(Debug, Default, Clone, Copy)]
 #[repr(u8)]
 pub enum DataAccessPerm {
@@ -312,6 +334,7 @@
     const READ_WRITE: u8 = 0b10;
 }
 
+/// Endpoint memory access permissions descriptor.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct MemAccessPerm {
     pub endpoint_id: u16,
@@ -320,6 +343,7 @@
     pub flags: u8, // TODO
 }
 
+/// Iterator of endpoint memory access permission descriptors.
 pub struct MemAccessPermIterator<'a> {
     buf: &'a [u8],
     offset: usize,
@@ -327,6 +351,7 @@
 }
 
 impl<'a> MemAccessPermIterator<'a> {
+    /// Create an iterator of endpoint memory access permission descriptors from a buffer.
     fn new(buf: &'a [u8], count: usize, offset: usize) -> Result<Self, Error> {
         let Some(total_size) = count
             .checked_mul(size_of::<endpoint_memory_access_descriptor>())
@@ -390,12 +415,14 @@
     }
 }
 
+/// Constituent memory region descriptor.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct ConstituentMemRegion {
     pub address: u64,
     pub page_cnt: u32,
 }
 
+/// Iterator of constituent memory region descriptors.
 pub struct ConstituentMemRegionIterator<'a> {
     buf: &'a [u8],
     offset: usize,
@@ -403,6 +430,7 @@
 }
 
 impl<'a> ConstituentMemRegionIterator<'a> {
+    /// Create an iterator of constituent memory region descriptors from a buffer.
     fn new(buf: &'a [u8], count: usize, offset: usize) -> Result<Self, Error> {
         let Some(total_size) = count
             .checked_mul(size_of::<constituent_memory_region_descriptor>())
@@ -446,6 +474,7 @@
     }
 }
 
+/// Flags of a memory management transaction.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct MemTransactionFlags(pub u32);
 
@@ -463,6 +492,8 @@
     pub const HINT_VALID: u32 = 0b1 << 9;
 }
 
+/// Memory transaction decriptor. Used by an Owner/Lender and a Borrower/Receiver in a transaction
+/// to donate, lend or share a memory region.
 #[derive(Debug, Default)]
 pub struct MemTransactionDesc {
     pub sender_id: u16,
@@ -483,6 +514,8 @@
     // region descriptor
     const CONSTITUENT_ARRAY_OFFSET: usize = size_of::<composite_memory_region_descriptor>();
 
+    /// Serialize a memory transaction descriptor and the related constituent memory region
+    /// descriptors and endpoint memory access permission descriptors into a buffer.
     pub fn pack(
         &self,
         constituents: &[ConstituentMemRegion],
@@ -562,6 +595,9 @@
         offset
     }
 
+    /// Deserialize a memory transaction descriptor from a buffer and return an interator of the
+    /// related endpoint memory access permission descriptors and constituent memory region
+    /// descriptors, if any.
     pub fn unpack(
         buf: &[u8],
     ) -> Result<
@@ -663,6 +699,7 @@
     }
 }
 
+/// Descriptor to relinquish a memory region. Currently only supports specifying a single endpoint.
 #[derive(Debug, Default)]
 pub struct MemRelinquishDesc {
     pub handle: Handle,
diff --git a/src/partition_info.rs b/src/partition_info.rs
index a8025b3..781f299 100644
--- a/src/partition_info.rs
+++ b/src/partition_info.rs
@@ -1,11 +1,15 @@
 // SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 // SPDX-License-Identifier: MIT OR Apache-2.0
 
+//! Implementation of FF-A partition discovery data structures.
+
 use crate::ffa_v1_1::partition_info_descriptor;
 use thiserror::Error;
 use uuid::Uuid;
 use zerocopy::{FromBytes, IntoBytes};
 
+/// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used
+/// with the `FFA_ERROR` interface.
 #[derive(Debug, Error)]
 pub enum Error {
     #[error("Invalid buffer size")]
@@ -20,11 +24,18 @@
     }
 }
 
+/// Type of partition identified by the partition ID.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum PartitionIdType {
+    /// Partition ID is a PE endpoint ID. Contains the number of execution contexts implemented by
+    /// this partition.
     PeEndpoint { execution_ctx_count: u16 },
+    /// Partition ID is a SEPID for an independent peripheral device.
     SepidIndep,
+    /// Partition ID is a SEPID for an dependent peripheral device. Contains the ID of the proxy
+    /// endpoint for a dependent peripheral device.
     SepidDep { proxy_endpoint_id: u16 },
+    /// Partition ID is an auxiliary ID.
     Aux,
 }
 
@@ -37,21 +48,22 @@
     const AUX: u32 = 0b11;
 }
 
+/// Properties of a partition.
 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
 pub struct PartitionProperties {
-    /// Supports receipt of direct requests
+    /// The partition supports receipt of direct requests.
     pub support_direct_req_rec: bool,
-    /// Can send direct requests
+    /// The partition can send direct requests.
     pub support_direct_req_send: bool,
-    /// Can send and receive indirect messages
+    /// The partition can send and receive indirect messages.
     pub support_indirect_msg: bool,
-    /// Supports receipt of notifications
+    /// The partition supports receipt of notifications.
     pub support_notif_rec: bool,
-    /// Must be informed about each VM that is created by the Hypervisor
+    /// The partition must be informed about each VM that is created by the Hypervisor.
     pub subscribe_vm_created: bool,
-    /// Must be informed about each VM that is destroyed by the Hypervisor
+    /// The partition must be informed about each VM that is destroyed by the Hypervisor.
     pub subscribe_vm_destroyed: bool,
-    /// Partition runs in the AArch64 execution state
+    /// The partition runs in the AArch64 execution state.
     pub is_aarch64: bool,
 }
 
@@ -172,6 +184,7 @@
     }
 }
 
+/// Partition information descriptor, returned by the `FFA_PARTITION_INFO_GET` interface.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct PartitionInfo {
     pub uuid: Uuid,
@@ -181,8 +194,10 @@
 }
 
 impl PartitionInfo {
-    pub const DESC_SIZE: usize = size_of::<partition_info_descriptor>();
+    const DESC_SIZE: usize = size_of::<partition_info_descriptor>();
 
+    /// Serialize a list of partition information descriptors into a buffer. The `fill_uuid`
+    /// parameter controls whether the UUID field of the descriptor will be filled.
     pub fn pack(descriptors: &[PartitionInfo], buf: &mut [u8], fill_uuid: bool) {
         let mut offset = 0;
 
@@ -207,6 +222,7 @@
     }
 }
 
+/// Iterator of partition information descriptors.
 pub struct PartitionInfoIterator<'a> {
     buf: &'a [u8],
     offset: usize,
@@ -214,6 +230,7 @@
 }
 
 impl<'a> PartitionInfoIterator<'a> {
+    /// Create an iterator of partition information descriptors from a buffer.
     pub fn new(buf: &'a [u8], count: usize) -> Result<Self, Error> {
         let Some(total_size) = count.checked_mul(PartitionInfo::DESC_SIZE) else {
             return Err(Error::InvalidBufferSize);