@@ -7,6 +7,7 @@ use crate::protocol::base::{
77
88use crate :: pldm_completion_code;
99
10+ use crate :: codec:: { PldmCodec , PldmCodecError , PldmCodecWithLifetime } ;
1011use crate :: protocol:: firmware_update:: { FwUpdateCmd , FwUpdateCompletionCode } ;
1112use zerocopy:: { FromBytes , Immutable , IntoBytes } ;
1213
@@ -53,9 +54,11 @@ pldm_completion_code! {
5354 }
5455}
5556
56- #[ derive( Debug , Clone , FromBytes , IntoBytes , Immutable , PartialEq ) ]
57- #[ repr( C , packed) ]
58- pub struct GetPackageDataResponse < ' a > {
57+ const MAX_PORTION_DATA_SIZE : usize = 0xff ;
58+ #[ derive( Debug , Clone , PartialEq , FromBytes ) ]
59+ #[ repr( C ) ]
60+ /// GetPackageDataResponse is parameterized over the portion package data size.
61+ pub struct GetPackageDataResponse {
5962 pub hdr : PldmMsgHeader < [ u8 ; PLDM_MSG_HEADER_LEN ] > ,
6063
6164 /// PLDM_BASE_CODES, COMMAND_NOT_EXPECTED, NO_PACKAGE_DATA,
@@ -69,17 +72,26 @@ pub struct GetPackageDataResponse<'a> {
6972 /// If the FD provided a value in the GetPackageDataMaximumTransferSize field, then the UA should
7073 /// select the amount of data to return such that the byte length for this field, except when TransferFlag
7174 /// = End or StartAndEnd, is equal to or less than that value.
72- pub portion_of_package_data : & ' a [ u8 ] ,
75+ pub portion_of_package_data : [ u8 ; MAX_PORTION_DATA_SIZE ] ,
76+
77+ // Non-spec field. Since the spec tells us that this can vary in unknown size,
78+ // we save the max and keep track of the actual size in this var.
79+ // When encoding this into byte form, we have to omit this field and only
80+ // encode as many bytes of [portion_of_package] as [portion_of_package_data_len]
81+ // tells us to.
82+ portion_of_package_data_len : usize ,
7383}
7484
75- impl < ' a > GetPackageDataResponse < ' a > {
85+ impl GetPackageDataResponse {
7686 pub fn new (
7787 instance_id : InstanceId ,
7888 completion_code : GetPackageDataCode ,
7989 next_data_transfer_handle : u32 ,
8090 transfer_flag : TransferOperationFlag ,
81- portion_of_package_data : & ' a [ u8 ] ,
91+ portion_of_package_data : & [ u8 ] ,
8292 ) -> Self {
93+ let mut pdata: [ u8 ; MAX_PORTION_DATA_SIZE ] = [ 0x00 ; MAX_PORTION_DATA_SIZE ] ;
94+ pdata[ 0 ..portion_of_package_data. len ( ) ] . copy_from_slice ( portion_of_package_data) ;
8395 GetPackageDataResponse {
8496 hdr : PldmMsgHeader :: new (
8597 instance_id,
@@ -90,11 +102,101 @@ impl<'a> GetPackageDataResponse<'a> {
90102 completion_code : completion_code. into ( ) ,
91103 next_data_transfer_handle,
92104 transfer_flag : transfer_flag as u8 ,
93- portion_of_package_data,
105+ portion_of_package_data : pdata,
106+ portion_of_package_data_len : portion_of_package_data. len ( ) ,
94107 }
95108 }
96109}
97110
111+ // See: src/message/firmware_update/get_fw_params.rs for manual decode etc
112+ impl PldmCodec for GetPackageDataResponse {
113+ fn encode ( & self , buffer : & mut [ u8 ] ) -> Result < usize , crate :: codec:: PldmCodecError > {
114+ if buffer. len ( )
115+ < core:: mem:: size_of :: < GetPackageDataResponse > ( )
116+ - MAX_PORTION_DATA_SIZE
117+ - core:: mem:: size_of_val ( & self . portion_of_package_data_len )
118+ + self . portion_of_package_data_len
119+ {
120+ return Err ( PldmCodecError :: BufferTooShort ) ;
121+ }
122+
123+ dbg ! ( core:: mem:: size_of:: <GetPackageDataResponse >( ) ) ;
124+
125+ let mut offset = 0 ;
126+ buffer[ offset..offset + std:: mem:: size_of_val ( & self . hdr . 0 ) ] . copy_from_slice ( & self . hdr . 0 ) ;
127+ offset += std:: mem:: size_of_val ( & self . hdr . 0 ) ;
128+ dbg ! ( offset) ;
129+
130+ buffer[ offset] = self . completion_code ;
131+ offset += 1 ;
132+
133+ buffer[ offset..offset + std:: mem:: size_of_val ( & self . next_data_transfer_handle ) ]
134+ . copy_from_slice ( self . next_data_transfer_handle . as_bytes ( ) ) ;
135+ offset += std:: mem:: size_of_val ( & self . next_data_transfer_handle ) ;
136+
137+ buffer[ offset] = self . transfer_flag ;
138+ offset += 1 ;
139+
140+ buffer[ offset..offset + self . portion_of_package_data_len ] . copy_from_slice (
141+ self . portion_of_package_data [ 0 ..self . portion_of_package_data_len ] . as_bytes ( ) ,
142+ ) ;
143+
144+ offset += self . portion_of_package_data_len ;
145+ dbg ! ( & buffer, & buffer. len( ) , & self . portion_of_package_data_len) ;
146+ dbg ! ( self . portion_of_package_data_len) ;
147+
148+ Ok ( offset)
149+ }
150+
151+ fn decode ( buffer : & [ u8 ] ) -> Result < Self , crate :: codec:: PldmCodecError > {
152+ const MIN_LEN : usize = core:: mem:: size_of :: < GetPackageDataResponse > ( )
153+ - core:: mem:: size_of :: < usize > ( )
154+ - core:: mem:: size_of :: < u8 > ( ) * MAX_PORTION_DATA_SIZE ;
155+
156+ if buffer. len ( ) < MIN_LEN {
157+ return Err ( PldmCodecError :: BufferTooShort ) ;
158+ }
159+
160+ let mut offset = 0 ;
161+
162+ let mut hdr_bytes = [ 0u8 ; PLDM_MSG_HEADER_LEN ] ;
163+ hdr_bytes. copy_from_slice ( & buffer[ offset..offset + PLDM_MSG_HEADER_LEN ] ) ;
164+
165+ let hdr = PldmMsgHeader ( hdr_bytes) ;
166+ offset += PLDM_MSG_HEADER_LEN ;
167+
168+ let completion_code = GetPackageDataCode :: try_from ( buffer[ offset] )
169+ . map_err ( |_| PldmCodecError :: Unsupported ) ?;
170+ offset += 1 ;
171+
172+ let next_data_transfer_handle = u32:: from_le_bytes ( [
173+ buffer[ offset] ,
174+ buffer[ offset + 1 ] ,
175+ buffer[ offset + 2 ] ,
176+ buffer[ offset + 3 ] ,
177+ ] ) ;
178+ offset += 4 ;
179+
180+ let transfer_flag = TransferOperationFlag :: try_from ( buffer[ offset] )
181+ . map_err ( |_| PldmCodecError :: Unsupported ) ?;
182+ offset += 1 ;
183+
184+ let portion_len = buffer. len ( ) - offset;
185+ if portion_len > MAX_PORTION_DATA_SIZE {
186+ return Err ( PldmCodecError :: BufferTooShort ) ;
187+ }
188+
189+ let portion_data = & buffer[ offset..] ;
190+ Ok ( Self :: new (
191+ hdr. instance_id ( ) ,
192+ completion_code,
193+ next_data_transfer_handle,
194+ transfer_flag,
195+ portion_data,
196+ ) )
197+ }
198+ }
199+
98200/// The UA sends this command to acquire optional data that the FD shall transfer to the UA prior to
99201/// beginning the transfer of component images. This command is only used if the FD has indicated in the
100202/// RequestUpdate command response that it has data that shall be retrieved and restored by the UA. The
@@ -264,11 +366,75 @@ impl<'a> GetMetaDataResponse<'a> {
264366 }
265367}
266368
369+ impl < ' a > PldmCodecWithLifetime < ' a > for GetMetaDataResponse < ' a > {
370+ fn encode ( & self , buffer : & mut [ u8 ] ) -> Result < usize , PldmCodecError > {
371+ let size = core:: mem:: size_of :: < Self > ( ) - core:: mem:: size_of :: < & ' a [ u8 ] > ( ) ;
372+ if buffer. len ( ) < size + self . portion_of_device_metadata . len ( ) {
373+ return Err ( PldmCodecError :: BufferTooShort ) ;
374+ }
375+
376+ let mut offset = 0 ;
377+ self . hdr
378+ . write_to_prefix ( & mut buffer[ offset..] )
379+ . map_err ( |_| PldmCodecError :: BufferTooShort ) ?;
380+ offset += PLDM_MSG_HEADER_LEN ;
381+
382+ buffer[ offset] = self . completion_code ;
383+ offset += 1 ;
384+
385+ buffer[ offset..offset + 4 ] . copy_from_slice ( & self . next_data_transfer_handle . to_le_bytes ( ) ) ;
386+ offset += 4 ;
387+
388+ buffer[ offset] = self . transfer_flag ;
389+ offset += 1 ;
390+
391+ buffer[ offset..offset + self . portion_of_device_metadata . len ( ) ]
392+ . copy_from_slice ( self . portion_of_device_metadata ) ;
393+
394+ Ok ( size)
395+ }
396+
397+ fn decode ( buffer : & ' a [ u8 ] ) -> Result < Self , PldmCodecError > {
398+ let size = core:: mem:: size_of :: < Self > ( ) - core:: mem:: size_of :: < & ' a [ u8 ] > ( ) ;
399+ if buffer. len ( ) < size {
400+ return Err ( PldmCodecError :: BufferTooShort ) ;
401+ }
402+
403+ let mut offset = 0 ;
404+
405+ let hdr = PldmMsgHeader :: read_from_prefix ( & buffer[ offset..] )
406+ . map_err ( |_| PldmCodecError :: BufferTooShort ) ?
407+ . 0 ;
408+ offset += PLDM_MSG_HEADER_LEN ;
409+
410+ let completion_code = buffer[ offset] ;
411+ offset += 1 ;
412+
413+ let next_data_transfer_handle = u32:: from_le_bytes (
414+ buffer[ offset..offset + 4 ]
415+ . try_into ( )
416+ . map_err ( |_| PldmCodecError :: BufferTooShort ) ?,
417+ ) ;
418+ offset += 4 ;
419+
420+ let transfer_flag = buffer[ offset] ;
421+ offset += 1 ;
422+
423+ let portion_of_device_metadata = & buffer[ offset..] ;
424+
425+ Ok ( Self {
426+ hdr,
427+ completion_code,
428+ next_data_transfer_handle,
429+ transfer_flag,
430+ portion_of_device_metadata,
431+ } )
432+ }
433+ }
434+
267435#[ cfg( test) ]
268436mod tests {
269437 use super :: * ;
270- use crate :: protocol;
271-
272438 use crate :: codec:: PldmCodec ;
273439
274440 #[ test]
@@ -288,31 +454,69 @@ mod tests {
288454 }
289455
290456 #[ test]
291- fn test_get_data_response ( ) {
457+ fn test_get_package_data_response ( ) {
458+ const PORTION_LEN : usize = 10 ;
459+
292460 let instance_id: InstanceId = 0x01 ;
293461 let next_data_transfer_handle: u32 = 0x12345678 ;
294462 let transfer_operation_flag = TransferOperationFlag :: GetFirstPart ;
295- let portion = [ 0u8 ; 0xff ] ;
463+ let portion = [ 22u8 ; PORTION_LEN ] ;
296464
297- let _ = GetPackageDataResponse :: new (
465+ let resp = GetPackageDataResponse :: new (
298466 instance_id,
299467 GetPackageDataCode :: BaseCodes ( PldmBaseCompletionCode :: Success ) ,
300468 next_data_transfer_handle,
301469 transfer_operation_flag,
302470 & portion,
303471 ) ;
304472
305- //TODO: encoding for response does not work atm due to unknown sizes
306- // let mut buffer = [0u8; core::mem::size_of::<GetPackageDataResponse>()];
307- // request.encode(&mut buffer).unwrap();
308- // let decoded = GetPackageDataResponse::decode(&buffer).unwrap();
473+ let mut buffer_fitted = [ 0u8 ; core:: mem:: size_of :: < GetPackageDataResponse > ( )
474+ - MAX_PORTION_DATA_SIZE
475+ - core:: mem:: size_of :: < usize > ( )
476+ + PORTION_LEN ] ;
477+
478+ dbg ! ( & buffer_fitted. len( ) ) ;
309479
310- // assert_eq!(request, decoded);
480+ resp. encode ( & mut buffer_fitted) . unwrap ( ) ;
481+ let decoded = GetPackageDataResponse :: decode ( & buffer_fitted) . unwrap ( ) ;
482+ assert_eq ! ( resp, decoded) ;
311483 }
312484
313485 #[ test]
314- fn test_get_device_metadata_request ( ) { }
486+ fn test_get_device_metadata_request ( ) {
487+ let instance_id: InstanceId = 0x01 ;
488+ let data_transfer_handle = 0x12345678 ;
489+ let req = GetMetaDataRequest :: new (
490+ instance_id,
491+ data_transfer_handle,
492+ TransferOperationFlag :: GetFirstPart ,
493+ ) ;
494+
495+ let mut buffer = [ 0u8 ; core:: mem:: size_of :: < GetMetaDataRequest > ( ) ] ;
496+ req. encode ( & mut buffer) . unwrap ( ) ;
497+
498+ let decoded = GetMetaDataRequest :: decode ( & buffer) . unwrap ( ) ;
499+ assert_eq ! ( req, decoded) ;
500+ }
315501
316502 #[ test]
317- fn test_get_device_metadata_reponse ( ) { }
503+ fn test_get_device_metadata_response ( ) {
504+ let instance_id: InstanceId = 0x01 ;
505+ let data_transfer_handle = 0x12345678 ;
506+ let payload = [ 11u8 ; 20 ] ;
507+
508+ let resp = GetMetaDataResponse :: new (
509+ instance_id,
510+ GetMetaDataCode :: BaseCodes ( PldmBaseCompletionCode :: Success ) ,
511+ data_transfer_handle,
512+ TransferOperationFlag :: GetFirstPart ,
513+ & payload,
514+ ) ;
515+
516+ let mut buffer = [ 0u8 ; 9 + 20 ] ;
517+ resp. encode ( & mut buffer) . unwrap ( ) ;
518+
519+ let decoded = GetMetaDataResponse :: decode ( & mut buffer) . unwrap ( ) ;
520+ assert_eq ! ( resp, decoded) ;
521+ }
318522}
0 commit comments