44//!
55//! C header: [`include/linux/property.h`](srctree/include/linux/property.h)
66
7- use core:: ptr;
7+ use core:: { mem :: MaybeUninit , ptr} ;
88
99use crate :: {
10+ alloc:: KVec ,
1011 bindings,
11- str:: CStr ,
12+ error:: { to_result, Result } ,
13+ prelude:: * ,
14+ private:: Sealed ,
15+ str:: { CStr , CString } ,
1216 types:: { ARef , Opaque } ,
1317} ;
1418
@@ -88,6 +92,104 @@ impl FwNode {
8892 // SAFETY: By the invariant of `CStr`, `name` is null-terminated.
8993 unsafe { bindings:: fwnode_property_present ( self . as_raw ( ) . cast_const ( ) , name. as_char_ptr ( ) ) }
9094 }
95+
96+ /// Returns firmware property `name` boolean value.
97+ pub fn property_read_bool ( & self , name : & CStr ) -> bool {
98+ // SAFETY:
99+ // - `name` is non-null and null-terminated.
100+ // - `self.as_raw()` is valid because `self` is valid.
101+ unsafe { bindings:: fwnode_property_read_bool ( self . as_raw ( ) , name. as_char_ptr ( ) ) }
102+ }
103+
104+ /// Returns the index of matching string `match_str` for firmware string
105+ /// property `name`.
106+ pub fn property_match_string ( & self , name : & CStr , match_str : & CStr ) -> Result < usize > {
107+ // SAFETY:
108+ // - `name` and `match_str` are non-null and null-terminated.
109+ // - `self.as_raw` is valid because `self` is valid.
110+ let ret = unsafe {
111+ bindings:: fwnode_property_match_string (
112+ self . as_raw ( ) ,
113+ name. as_char_ptr ( ) ,
114+ match_str. as_char_ptr ( ) ,
115+ )
116+ } ;
117+ to_result ( ret) ?;
118+ Ok ( ret as usize )
119+ }
120+
121+ /// Returns firmware property `name` integer array values in a [`KVec`].
122+ pub fn property_read_array_vec < ' fwnode , ' name , T : PropertyInt > (
123+ & ' fwnode self ,
124+ name : & ' name CStr ,
125+ len : usize ,
126+ ) -> Result < PropertyGuard < ' fwnode , ' name , KVec < T > > > {
127+ let mut val: KVec < T > = KVec :: with_capacity ( len, GFP_KERNEL ) ?;
128+
129+ let res = T :: read_array_from_fwnode_property ( self , name, val. spare_capacity_mut ( ) ) ;
130+ let res = match res {
131+ Ok ( _) => {
132+ // SAFETY:
133+ // - `len` is equal to `val.capacity - val.len`, because
134+ // `val.capacity` is `len` and `val.len` is zero.
135+ // - All elements within the interval [`0`, `len`) were initialized
136+ // by `read_array_from_fwnode_property`.
137+ unsafe { val. inc_len ( len) }
138+ Ok ( val)
139+ }
140+ Err ( e) => Err ( e) ,
141+ } ;
142+ Ok ( PropertyGuard {
143+ inner : res,
144+ fwnode : self ,
145+ name,
146+ } )
147+ }
148+
149+ /// Returns integer array length for firmware property `name`.
150+ pub fn property_count_elem < T : PropertyInt > ( & self , name : & CStr ) -> Result < usize > {
151+ T :: read_array_len_from_fwnode_property ( self , name)
152+ }
153+
154+ /// Returns the value of firmware property `name`.
155+ ///
156+ /// This method is generic over the type of value to read. The types that
157+ /// can be read are strings, integers and arrays of integers.
158+ ///
159+ /// Reading a [`KVec`] of integers is done with the separate
160+ /// method [`Self::property_read_array_vec`], because it takes an
161+ /// additional `len` argument.
162+ ///
163+ /// Reading a boolean is done with the separate method
164+ /// [`Self::property_read_bool`], because this operation is infallible.
165+ ///
166+ /// For more precise documentation about what types can be read, see
167+ /// the [implementors of Property][Property#implementors] and [its
168+ /// implementations on foreign types][Property#foreign-impls].
169+ ///
170+ /// # Examples
171+ ///
172+ /// ```
173+ /// # use kernel::{c_str, device::{Device, property::FwNode}, str::CString};
174+ /// fn examples(dev: &Device) -> Result {
175+ /// let fwnode = dev.fwnode().ok_or(ENOENT)?;
176+ /// let b: u32 = fwnode.property_read(c_str!("some-number")).required_by(dev)?;
177+ /// if let Some(s) = fwnode.property_read::<CString>(c_str!("some-str")).optional() {
178+ /// // ...
179+ /// }
180+ /// Ok(())
181+ /// }
182+ /// ```
183+ pub fn property_read < ' fwnode , ' name , T : Property > (
184+ & ' fwnode self ,
185+ name : & ' name CStr ,
186+ ) -> PropertyGuard < ' fwnode , ' name , T > {
187+ PropertyGuard {
188+ inner : T :: read_from_fwnode_property ( self , name) ,
189+ fwnode : self ,
190+ name,
191+ }
192+ }
91193}
92194
93195// SAFETY: Instances of `FwNode` are always reference-counted.
@@ -105,6 +207,155 @@ unsafe impl crate::types::AlwaysRefCounted for FwNode {
105207 }
106208}
107209
210+ /// Implemented for types that can be read as properties.
211+ ///
212+ /// This is implemented for strings, integers and arrays of integers. It's used
213+ /// to make [`FwNode::property_read`] generic over the type of property being
214+ /// read. There are also two dedicated methods to read other types, because they
215+ /// require more specialized function signatures:
216+ /// - [`property_read_bool`](FwNode::property_read_bool)
217+ /// - [`property_read_array_vec`](FwNode::property_read_array_vec)
218+ ///
219+ /// It must be public, because it appears in the signatures of other public
220+ /// functions, but its methods shouldn't be used outside the kernel crate.
221+ pub trait Property : Sized + Sealed {
222+ /// Used to make [`FwNode::property_read`] generic.
223+ fn read_from_fwnode_property ( fwnode : & FwNode , name : & CStr ) -> Result < Self > ;
224+ }
225+
226+ impl Sealed for CString { }
227+
228+ impl Property for CString {
229+ fn read_from_fwnode_property ( fwnode : & FwNode , name : & CStr ) -> Result < Self > {
230+ let mut str: * mut u8 = ptr:: null_mut ( ) ;
231+ let pstr: * mut _ = & mut str;
232+
233+ // SAFETY:
234+ // - `name` is non-null and null-terminated.
235+ // - `fwnode.as_raw` is valid because `fwnode` is valid.
236+ let ret = unsafe {
237+ bindings:: fwnode_property_read_string ( fwnode. as_raw ( ) , name. as_char_ptr ( ) , pstr. cast ( ) )
238+ } ;
239+ to_result ( ret) ?;
240+
241+ // SAFETY:
242+ // - `pstr` is a valid pointer to a NUL-terminated C string.
243+ // - It is valid for at least as long as `fwnode`, but it's only used
244+ // within the current function.
245+ // - The memory it points to is not mutated during that time.
246+ let str = unsafe { CStr :: from_char_ptr ( * pstr) } ;
247+ Ok ( str. try_into ( ) ?)
248+ }
249+ }
250+
251+ /// Implemented for all integers that can be read as properties.
252+ ///
253+ /// This helper trait is needed on top of the existing [`Property`]
254+ /// trait to associate the integer types of various sizes with their
255+ /// corresponding `fwnode_property_read_*_array` functions.
256+ ///
257+ /// It must be public, because it appears in the signatures of other public
258+ /// functions, but its methods shouldn't be used outside the kernel crate.
259+ pub trait PropertyInt : Copy + Sealed {
260+ /// Reads a property array.
261+ fn read_array_from_fwnode_property < ' a > (
262+ fwnode : & FwNode ,
263+ name : & CStr ,
264+ out : & ' a mut [ MaybeUninit < Self > ] ,
265+ ) -> Result < & ' a mut [ Self ] > ;
266+
267+ /// Reads the length of a property array.
268+ fn read_array_len_from_fwnode_property ( fwnode : & FwNode , name : & CStr ) -> Result < usize > ;
269+ }
270+ // This macro generates implementations of the traits `Property` and
271+ // `PropertyInt` for integers of various sizes. Its input is a list
272+ // of pairs separated by commas. The first element of the pair is the
273+ // type of the integer, the second one is the name of its corresponding
274+ // `fwnode_property_read_*_array` function.
275+ macro_rules! impl_property_for_int {
276+ ( $( $int: ty: $f: ident) ,* $( , ) ?) => { $(
277+ impl Sealed for $int { }
278+ impl <const N : usize > Sealed for [ $int; N ] { }
279+
280+ impl PropertyInt for $int {
281+ fn read_array_from_fwnode_property<' a>(
282+ fwnode: & FwNode ,
283+ name: & CStr ,
284+ out: & ' a mut [ MaybeUninit <Self >] ,
285+ ) -> Result <& ' a mut [ Self ] > {
286+ // SAFETY:
287+ // - `fwnode`, `name` and `out` are all valid by their type
288+ // invariants.
289+ // - `out.len()` is a valid bound for the memory pointed to by
290+ // `out.as_mut_ptr()`.
291+ // CAST: It's ok to cast from `*mut MaybeUninit<$int>` to a
292+ // `*mut $int` because they have the same memory layout.
293+ let ret = unsafe {
294+ bindings:: $f(
295+ fwnode. as_raw( ) ,
296+ name. as_char_ptr( ) ,
297+ out. as_mut_ptr( ) . cast( ) ,
298+ out. len( ) ,
299+ )
300+ } ;
301+ to_result( ret) ?;
302+ // SAFETY: Transmuting from `&'a mut [MaybeUninit<Self>]` to
303+ // `&'a mut [Self]` is sound, because the previous call to a
304+ // `fwnode_property_read_*_array` function (which didn't fail)
305+ // fully initialized the slice.
306+ Ok ( unsafe { core:: mem:: transmute( out) } )
307+ }
308+
309+ fn read_array_len_from_fwnode_property( fwnode: & FwNode , name: & CStr ) -> Result <usize > {
310+ // SAFETY:
311+ // - `fwnode` and `name` are valid by their type invariants.
312+ // - It's ok to pass a null pointer to the
313+ // `fwnode_property_read_*_array` functions if `nval` is zero.
314+ // This will return the length of the array.
315+ let ret = unsafe {
316+ bindings:: $f(
317+ fwnode. as_raw( ) ,
318+ name. as_char_ptr( ) ,
319+ ptr:: null_mut( ) ,
320+ 0 ,
321+ )
322+ } ;
323+ to_result( ret) ?;
324+ Ok ( ret as usize )
325+ }
326+ }
327+
328+ impl Property for $int {
329+ fn read_from_fwnode_property( fwnode: & FwNode , name: & CStr ) -> Result <Self > {
330+ let val: [ _; 1 ] = <[ $int; 1 ] >:: read_from_fwnode_property( fwnode, name) ?;
331+ Ok ( val[ 0 ] )
332+ }
333+ }
334+
335+ impl <const N : usize > Property for [ $int; N ] {
336+ fn read_from_fwnode_property( fwnode: & FwNode , name: & CStr ) -> Result <Self > {
337+ let mut val: [ MaybeUninit <$int>; N ] = [ const { MaybeUninit :: uninit( ) } ; N ] ;
338+
339+ <$int>:: read_array_from_fwnode_property( fwnode, name, & mut val) ?;
340+
341+ // SAFETY: `val` is always initialized when
342+ // `fwnode_property_read_*_array` is successful.
343+ Ok ( val. map( |v| unsafe { v. assume_init( ) } ) )
344+ }
345+ }
346+ ) * } ;
347+ }
348+ impl_property_for_int ! {
349+ u8 : fwnode_property_read_u8_array,
350+ u16 : fwnode_property_read_u16_array,
351+ u32 : fwnode_property_read_u32_array,
352+ u64 : fwnode_property_read_u64_array,
353+ i8 : fwnode_property_read_u8_array,
354+ i16 : fwnode_property_read_u16_array,
355+ i32 : fwnode_property_read_u32_array,
356+ i64 : fwnode_property_read_u64_array,
357+ }
358+
108359/// A helper for reading device properties.
109360///
110361/// Use [`Self::required_by`] if a missing property is considered a bug and
0 commit comments