44//! to be loaded into a given execution unit.
55
66use core:: marker:: PhantomData ;
7+ use core:: ops:: Deref ;
78
89use kernel:: {
910 device,
@@ -15,7 +16,10 @@ use kernel::{
1516
1617use crate :: {
1718 dma:: DmaObject ,
18- falcon:: FalconFirmware ,
19+ falcon:: {
20+ FalconFirmware ,
21+ FalconLoadTarget , //
22+ } ,
1923 gpu,
2024 num:: {
2125 FromSafeCast ,
@@ -43,6 +47,46 @@ fn request_firmware(
4347 . and_then ( |path| firmware:: Firmware :: request ( & path, dev) )
4448}
4549
50+ /// Structure used to describe some firmwares, notably FWSEC-FRTS.
51+ #[ repr( C ) ]
52+ #[ derive( Debug , Clone ) ]
53+ pub ( crate ) struct FalconUCodeDescV2 {
54+ /// Header defined by 'NV_BIT_FALCON_UCODE_DESC_HEADER_VDESC*' in OpenRM.
55+ hdr : u32 ,
56+ /// Stored size of the ucode after the header, compressed or uncompressed
57+ stored_size : u32 ,
58+ /// Uncompressed size of the ucode. If store_size == uncompressed_size, then the ucode
59+ /// is not compressed.
60+ pub ( crate ) uncompressed_size : u32 ,
61+ /// Code entry point
62+ pub ( crate ) virtual_entry : u32 ,
63+ /// Offset after the code segment at which the Application Interface Table headers are located.
64+ pub ( crate ) interface_offset : u32 ,
65+ /// Base address at which to load the code segment into 'IMEM'.
66+ pub ( crate ) imem_phys_base : u32 ,
67+ /// Size in bytes of the code to copy into 'IMEM'.
68+ pub ( crate ) imem_load_size : u32 ,
69+ /// Virtual 'IMEM' address (i.e. 'tag') at which the code should start.
70+ pub ( crate ) imem_virt_base : u32 ,
71+ /// Virtual address of secure IMEM segment.
72+ pub ( crate ) imem_sec_base : u32 ,
73+ /// Size of secure IMEM segment.
74+ pub ( crate ) imem_sec_size : u32 ,
75+ /// Offset into stored (uncompressed) image at which DMEM begins.
76+ pub ( crate ) dmem_offset : u32 ,
77+ /// Base address at which to load the data segment into 'DMEM'.
78+ pub ( crate ) dmem_phys_base : u32 ,
79+ /// Size in bytes of the data to copy into 'DMEM'.
80+ pub ( crate ) dmem_load_size : u32 ,
81+ /// "Alternate" Size of data to load into IMEM.
82+ pub ( crate ) alt_imem_load_size : u32 ,
83+ /// "Alternate" Size of data to load into DMEM.
84+ pub ( crate ) alt_dmem_load_size : u32 ,
85+ }
86+
87+ // SAFETY: all bit patterns are valid for this type, and it doesn't use interior mutability.
88+ unsafe impl FromBytes for FalconUCodeDescV2 { }
89+
4690/// Structure used to describe some firmwares, notably FWSEC-FRTS.
4791#[ repr( C ) ]
4892#[ derive( Debug , Clone ) ]
@@ -76,13 +120,164 @@ pub(crate) struct FalconUCodeDescV3 {
76120 _reserved : u16 ,
77121}
78122
79- impl FalconUCodeDescV3 {
123+ // SAFETY: all bit patterns are valid for this type, and it doesn't use
124+ // interior mutability.
125+ unsafe impl FromBytes for FalconUCodeDescV3 { }
126+
127+ /// Enum wrapping the different versions of Falcon microcode descriptors.
128+ ///
129+ /// This allows handling both V2 and V3 descriptor formats through a
130+ /// unified type, providing version-agnostic access to firmware metadata
131+ /// via the [`FalconUCodeDescriptor`] trait.
132+ #[ derive( Debug , Clone ) ]
133+ pub ( crate ) enum FalconUCodeDesc {
134+ V2 ( FalconUCodeDescV2 ) ,
135+ V3 ( FalconUCodeDescV3 ) ,
136+ }
137+
138+ impl Deref for FalconUCodeDesc {
139+ type Target = dyn FalconUCodeDescriptor ;
140+
141+ fn deref ( & self ) -> & Self :: Target {
142+ match self {
143+ FalconUCodeDesc :: V2 ( v2) => v2,
144+ FalconUCodeDesc :: V3 ( v3) => v3,
145+ }
146+ }
147+ }
148+
149+ /// Trait providing a common interface for accessing Falcon microcode descriptor fields.
150+ ///
151+ /// This trait abstracts over the different descriptor versions ([`FalconUCodeDescV2`] and
152+ /// [`FalconUCodeDescV3`]), allowing code to work with firmware metadata without needing to
153+ /// know the specific descriptor version. Fields not present return zero.
154+ pub ( crate ) trait FalconUCodeDescriptor {
155+ fn hdr ( & self ) -> u32 ;
156+ fn imem_load_size ( & self ) -> u32 ;
157+ fn interface_offset ( & self ) -> u32 ;
158+ fn dmem_load_size ( & self ) -> u32 ;
159+ fn pkc_data_offset ( & self ) -> u32 ;
160+ fn engine_id_mask ( & self ) -> u16 ;
161+ fn ucode_id ( & self ) -> u8 ;
162+ fn signature_count ( & self ) -> u8 ;
163+ fn signature_versions ( & self ) -> u16 ;
164+
80165 /// Returns the size in bytes of the header.
81- pub ( crate ) fn size ( & self ) -> usize {
166+ fn size ( & self ) -> usize {
167+ let hdr = self . hdr ( ) ;
168+
82169 const HDR_SIZE_SHIFT : u32 = 16 ;
83170 const HDR_SIZE_MASK : u32 = 0xffff0000 ;
171+ ( ( hdr & HDR_SIZE_MASK ) >> HDR_SIZE_SHIFT ) . into_safe_cast ( )
172+ }
84173
85- ( ( self . hdr & HDR_SIZE_MASK ) >> HDR_SIZE_SHIFT ) . into_safe_cast ( )
174+ fn imem_sec_load_params ( & self ) -> FalconLoadTarget ;
175+ fn imem_ns_load_params ( & self ) -> Option < FalconLoadTarget > ;
176+ fn dmem_load_params ( & self ) -> FalconLoadTarget ;
177+ }
178+
179+ impl FalconUCodeDescriptor for FalconUCodeDescV2 {
180+ fn hdr ( & self ) -> u32 {
181+ self . hdr
182+ }
183+ fn imem_load_size ( & self ) -> u32 {
184+ self . imem_load_size
185+ }
186+ fn interface_offset ( & self ) -> u32 {
187+ self . interface_offset
188+ }
189+ fn dmem_load_size ( & self ) -> u32 {
190+ self . dmem_load_size
191+ }
192+ fn pkc_data_offset ( & self ) -> u32 {
193+ 0
194+ }
195+ fn engine_id_mask ( & self ) -> u16 {
196+ 0
197+ }
198+ fn ucode_id ( & self ) -> u8 {
199+ 0
200+ }
201+ fn signature_count ( & self ) -> u8 {
202+ 0
203+ }
204+ fn signature_versions ( & self ) -> u16 {
205+ 0
206+ }
207+
208+ fn imem_sec_load_params ( & self ) -> FalconLoadTarget {
209+ FalconLoadTarget {
210+ src_start : 0 ,
211+ dst_start : self . imem_sec_base ,
212+ len : self . imem_sec_size ,
213+ }
214+ }
215+
216+ fn imem_ns_load_params ( & self ) -> Option < FalconLoadTarget > {
217+ Some ( FalconLoadTarget {
218+ src_start : 0 ,
219+ dst_start : self . imem_phys_base ,
220+ len : self . imem_load_size . checked_sub ( self . imem_sec_size ) ?,
221+ } )
222+ }
223+
224+ fn dmem_load_params ( & self ) -> FalconLoadTarget {
225+ FalconLoadTarget {
226+ src_start : self . dmem_offset ,
227+ dst_start : self . dmem_phys_base ,
228+ len : self . dmem_load_size ,
229+ }
230+ }
231+ }
232+
233+ impl FalconUCodeDescriptor for FalconUCodeDescV3 {
234+ fn hdr ( & self ) -> u32 {
235+ self . hdr
236+ }
237+ fn imem_load_size ( & self ) -> u32 {
238+ self . imem_load_size
239+ }
240+ fn interface_offset ( & self ) -> u32 {
241+ self . interface_offset
242+ }
243+ fn dmem_load_size ( & self ) -> u32 {
244+ self . dmem_load_size
245+ }
246+ fn pkc_data_offset ( & self ) -> u32 {
247+ self . pkc_data_offset
248+ }
249+ fn engine_id_mask ( & self ) -> u16 {
250+ self . engine_id_mask
251+ }
252+ fn ucode_id ( & self ) -> u8 {
253+ self . ucode_id
254+ }
255+ fn signature_count ( & self ) -> u8 {
256+ self . signature_count
257+ }
258+ fn signature_versions ( & self ) -> u16 {
259+ self . signature_versions
260+ }
261+
262+ fn imem_sec_load_params ( & self ) -> FalconLoadTarget {
263+ FalconLoadTarget {
264+ src_start : 0 ,
265+ dst_start : self . imem_phys_base ,
266+ len : self . imem_load_size ,
267+ }
268+ }
269+
270+ fn imem_ns_load_params ( & self ) -> Option < FalconLoadTarget > {
271+ // Not used on V3 platforms
272+ None
273+ }
274+
275+ fn dmem_load_params ( & self ) -> FalconLoadTarget {
276+ FalconLoadTarget {
277+ src_start : self . imem_load_size ,
278+ dst_start : self . dmem_phys_base ,
279+ len : self . dmem_load_size ,
280+ }
86281 }
87282}
88283
0 commit comments