1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 
9 /************* Include Files ****************/
10 
11 #include "cc_common.h"
12 #include "cc_common_math.h"
13 #include "cc_common_error.h"
14 #include "cc_pal_mem.h"
15 #include "cc_bitops.h"
16 
17 /************************ Defines ******************************/
18 
19 /************************ Enums ********************************/
20 
21 /************************ Typedefs *****************************/
22 
23 /************************ Global Data **************************/
24 
25 /************* Private function prototype **********************/
26 
27 /************************ Public Functions *********************/
28 
29 /***********************************************************************
30  **
31  * @brief This function executes a reverse bytes copying from one buffer to another buffer.
32  *
33  *        Overlapping of buffers is not allowed, excluding the case, when destination and source
34  *        buffers are the same.
35  *        Example of a 5 byte buffer:
36  *
37  *        dst_ptr[4] = src_ptr[0]
38  *        dst_ptr[3] = src_ptr[1]
39  *        dst_ptr[2] = src_ptr[2]
40  *        dst_ptr[1] = src_ptr[3]
41  *        dst_ptr[0] = src_ptr[4]
42  *
43  * @param[in] dst_ptr - The pointer to destination buffer.
44  * @param[in] src_ptr - The pointer to source buffer.
45  * @param[in] size    - The size in bytes.
46  *
47  */
CC_CommonReverseMemcpy(uint8_t * dst_ptr,uint8_t * src_ptr,uint32_t size)48 CCError_t CC_CommonReverseMemcpy( uint8_t *dst_ptr , uint8_t *src_ptr , uint32_t size )
49 {
50         /* FUNCTION DECLARATIONS */
51 
52         /* loop variable */
53         uint32_t i;
54 
55         /* FUNCTION LOGIC */
56 
57         /* check overlapping */
58         if ((dst_ptr > src_ptr && dst_ptr < (src_ptr + size)) ||
59             (dst_ptr < src_ptr && (dst_ptr + size) >= src_ptr)) {
60                 return CC_COMMON_DATA_OUT_DATA_IN_OVERLAP_ERROR;
61         }
62 
63 
64         /* execute the reverse copy in case of different buffers */
65         if (dst_ptr != src_ptr) {
66                 for (i = 0 ; i < size ; i++)
67                         dst_ptr[i] = src_ptr[size - 1 - i];
68         }
69 
70         /* execute the reverse copy in the same place */
71         else {
72                 uint8_t  temp;
73 
74                 for (i = 0; i < size / 2; i++) {
75                         temp = src_ptr[i];
76                         src_ptr[i] = src_ptr[size - 1 - i];
77                         src_ptr[size - 1 - i] = temp;
78                 }
79         }
80 
81         return CC_OK;
82 
83 }/* END OF CC_CommonReverseMemcpy */
84 
85 
86 #ifndef DX_OEM_FW
87 
88 /***********************************************************************/
89 /**
90  * @brief This function converts in place words byffer to bytes buffer with
91  *        reversed endianity of output array.
92  *
93  *        The function can convert:
94  *           - big endian bytes array to words array with little endian order
95  *             of words and backward.
96  *
97  *      Note:
98  *      1. Endianness of each word in words buffer should be set allways
99  *      according to processor used.
100  *      2. Implementation is given for both big and little endianness of
101  *      processor.
102  *
103  * @param[in]  buf_ptr - The 32-bits pointer to input/output buffer.
104  * @param[in]  sizeWords - The size in words (sizeWords > 0).
105  *
106  * @return - no return value.
107  */
CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(uint32_t * buf_ptr,uint32_t sizeWords)108 void CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(
109                                                         uint32_t *buf_ptr,
110                                                         uint32_t  sizeWords)
111 {
112         /* FUNCTION DECLARATIONS */
113 
114         uint32_t i, tmp;
115 
116         /* FUNCTION logic */
117 
118 #ifndef BIG__ENDIAN
119         /* If sizeWords is odd revert middle word */
120         if (sizeWords & 1UL) {
121                 buf_ptr[sizeWords/2] = CC_COMMON_REVERSE32(buf_ptr[sizeWords/2]);
122         }
123 #endif
124 
125                 /* Reverse order of words and order of bytes in each word.    *
126                 *  Note: Condition (sizeWords >= 2) inserted inside for() to  *
127                 *        prevent wrong false positive warnings.               *
128                 *                                                             */
129                 for (i = 0; ((i < sizeWords/2) && (sizeWords >= 2)); i++) {
130 #ifndef BIG__ENDIAN
131                         tmp = CC_COMMON_REVERSE32(buf_ptr[i]);
132                         buf_ptr[i] = CC_COMMON_REVERSE32(buf_ptr[sizeWords-i-1]);
133 #else
134                         tmp = buf_ptr[i];
135                         buf_ptr[i] = buf_ptr[sizeWords-i-1];
136 #endif
137                         buf_ptr[sizeWords-i-1] = tmp;
138                 }
139 
140         return;
141 
142 }/* End of CC_CommonInPlaceConvertBytesWordsAndArrayEndianness */
143 
144 
145 /***********************************************************************/
146 /**
147 * @brief This function converts big endianness bytes array to aligned words
148 *        array with words order according to little endian.
149 *
150 *            1. Assumed, that input bytes order is set according
151 *         to big endianness: MS Byte is most left, i.e. order is from
152 *         Msb to Lsb.
153 *            2. Output words array should set according to
154 *         little endianness words order: LSWord is most left, i.e. order
155 *         is from Lsw to Msw. Order bytes in each word - according to
156 *         processor endianness.
157 *            3. Owerlapping of buffers is not allowed, besides in
158 *         place operation and size aligned to full words.
159 *            4. Implementation is given for both big and little
160 *         endianness of processor.
161 *
162 * @param[out] out32_ptr - The 32-bits pointer to output buffer.
163 * @param[in] sizeOutBuffBytes - The size in bytes of output buffer, must be
164 *            aligned to 4 bytes and not less than inpSizeInBytes.
165 * @param[in] in8_ptr - The pointer to input buffer.
166 * @param[in] inpSizeInBytes - The size in bytes of input data, where
167 *                  0 < inpSizeInBytes < UINT32_MAX - CC_32BIT_WORD_SIZE.
168 *
169 * @return CCError_t - On success CC_OK is returned, on failure a
170 *                        value MODULE_* as defined in .
171 */
CC_CommonConvertMsbLsbBytesToLswMswWords(uint32_t * out32_ptr,uint32_t sizeOutBuffBytes,const uint8_t * in8_ptr,uint32_t inpSizeInBytes)172 CCError_t CC_CommonConvertMsbLsbBytesToLswMswWords(
173                                                   uint32_t *out32_ptr,
174                                                   uint32_t  sizeOutBuffBytes,
175                                                   const uint8_t  *in8_ptr,
176                                                   uint32_t  inpSizeInBytes)
177 {
178         /* FUNCTION DECLARATIONS */
179 
180         /* the rounded up size of the input data in bytes */
181         uint32_t roundedInpSizeInBytes;
182 
183         /* FUNCTION LOGIC */
184 
185         /* Check pointers and size */
186         if ((in8_ptr == NULL) || (out32_ptr == NULL))
187                 return CC_COMMON_DATA_IN_POINTER_INVALID_ERROR;
188 
189         /*  Check the size and in place operation:       *
190         *   the size must be > 0 and aligned to words    */
191         if ((inpSizeInBytes == 0) || (inpSizeInBytes >= UINT32_MAX - CC_32BIT_WORD_SIZE) ||
192             (sizeOutBuffBytes & 3) || (inpSizeInBytes > sizeOutBuffBytes)) {
193                 return CC_COMMON_DATA_SIZE_ILLEGAL;
194         }
195 
196         /* Size of input data in words rounded up */
197         roundedInpSizeInBytes = ROUNDUP_BYTES_TO_32BIT_WORD(inpSizeInBytes);
198 
199         if (roundedInpSizeInBytes > sizeOutBuffBytes)
200                 return CC_COMMON_OUTPUT_BUFF_SIZE_ILLEGAL;
201 
202         /*  If the conversion is not "in place" or data size not aligned to
203             words, then copy the data into output buffer and zeroe leading bytes */
204         if (((CCVirtAddr_t)out32_ptr != (CCVirtAddr_t)in8_ptr) || (inpSizeInBytes & 3)) {
205                 CC_PalMemMove((uint8_t*)out32_ptr + roundedInpSizeInBytes - inpSizeInBytes, in8_ptr, inpSizeInBytes);
206                 /* set leading zeros in output buffer */
207                 if (roundedInpSizeInBytes > inpSizeInBytes)
208                         CC_PalMemSetZero((uint8_t*)out32_ptr, roundedInpSizeInBytes - inpSizeInBytes); /*leading zeros*/
209         }
210 
211         /* set tailing zeros in output buffer */
212         CC_PalMemSetZero((uint8_t*)out32_ptr + roundedInpSizeInBytes,
213                          sizeOutBuffBytes - roundedInpSizeInBytes); /*tailing zeros*/
214 
215         /* Reverse words order and set endianness of each word */
216         CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(out32_ptr, CALC_32BIT_WORDS_FROM_BYTES(inpSizeInBytes));
217 
218         return CC_OK;
219 }
220 
221 
222 /***********************************************************************/
223 /**
224 * @brief This function converts LE 32bit-words array to BE bytes array.
225 *
226 *            1. Assumed, that output bytes order is according
227 *         to big endianness: MS Byte is most left, i.e. order is from
228 *         Msb to Lsb.
229 *            2. Input words array should be set according to
230 *         little endianness words order: LSWord is most left, i.e. order
231 *         is from Lsw to Msw. Bytes order in each word - according to
232 *         processor endianness.
233 *            3. Owerlapping of buffers is not allowed, besides in
234 *         place operation and size aligned to full words.
235 *            4. Implementation is given for both big and little
236 *         endianness of processor.
237 *
238 * @param[in] out32_ptr - The 32-bits pointer to output buffer.
239 * @param[in] sizeOutBuffBytes - The size in bytes of output buffer, must be
240 *       not less than inpSizeInBytes.
241 * @param[out] in8_ptr - The pointer to input buffer.
242 * @param[in] sizeInBytes - The size in bytes. The size must be not 0 and
243 *       aligned to 4 bytes word.
244 *
245 * @return CCError_t - On success CC_OK is returned, on failure a
246 *                        value MODULE_* as defined in .
247 */
CC_CommonConvertLswMswWordsToMsbLsbBytes(uint8_t * out8_ptr,size_t sizeOutBuffBytes,uint32_t * in32_ptr,uint32_t sizeInBytes)248 CCError_t CC_CommonConvertLswMswWordsToMsbLsbBytes(
249                                                   uint8_t  *out8_ptr,
250                                                   size_t   sizeOutBuffBytes,
251                                                   uint32_t *in32_ptr,
252                                                   uint32_t  sizeInBytes)
253 {
254         /* FUNCTION DECLARATIONS */
255 
256         uint32_t sizeInWords;
257 
258         /* FUNCTION LOGIC */
259 
260         /* Check pointers and size */
261         if ((in32_ptr == NULL) || (out8_ptr == NULL))
262                 return CC_COMMON_DATA_IN_POINTER_INVALID_ERROR;
263 
264         /* Size in words rounded up */
265         sizeInWords = (sizeInBytes + 3) / 4;
266 
267         if ((sizeInBytes == 0) || (sizeOutBuffBytes < sizeInBytes))
268                 return CC_COMMON_DATA_SIZE_ILLEGAL;
269 
270         /* Check in place operation: the size must be aligned to word */
271         if (((CCVirtAddr_t)in32_ptr == (CCVirtAddr_t)out8_ptr) && (sizeInBytes & 3UL))
272                 return CC_COMMON_DATA_SIZE_ILLEGAL;
273 
274         /* Reverse words order and bytes according to endianness of CPU */
275         CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(in32_ptr, sizeInWords);
276 
277         /* Copy output buffer */
278         if ((CCVirtAddr_t)out8_ptr != (CCVirtAddr_t)in32_ptr) {
279 
280                 /* Check overlapping */
281                 if (((CCVirtAddr_t)out8_ptr > (CCVirtAddr_t)in32_ptr && (CCVirtAddr_t)out8_ptr < ((CCVirtAddr_t)in32_ptr + sizeInBytes)) ||
282                     ((CCVirtAddr_t)out8_ptr < (CCVirtAddr_t)in32_ptr && ((CCVirtAddr_t)out8_ptr + sizeInBytes) > (CCVirtAddr_t)in32_ptr))
283                         return CC_COMMON_DATA_OUT_DATA_IN_OVERLAP_ERROR;
284 
285                 CC_PalMemCopy(out8_ptr, (uint8_t *)in32_ptr + ((4 - (sizeInBytes & 3UL)) & 3UL), sizeInBytes);
286                 /* Revert the input buffer to previous state */
287                 CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(in32_ptr, sizeInWords);
288         }
289 
290         return CC_OK;
291 }
292 
293 
294 /***********************************************************************/
295 /**
296  * @brief This function converts bytes array with little endian (LE) order of
297  *        bytes to 32-bit words array with little endian order of words and bytes.
298  *
299  *   Assuming:  No owerlapping of buffers; in/out pointers and sizes are not equall to NULL.
300  *              If is in-place conversion, then the size must be multiple of 4 bytes.
301  * @param[out] out32Le - The 32-bits pointer to output buffer. The buffer size must be
302  *                       not less, than input data size.
303  * @param[in] in8Le - The pointer to input buffer.
304  * @param[in] sizeInBytes - The size in bytes of input data(sizeBytes > 0).
305  *
306  * @return CCError_t - On success CC_OK is returned, on failure a
307  *                        value MODULE_* as defined in .
308  */
CC_CommonConvertLsbMsbBytesToLswMswWords(uint32_t * out32Le,const uint8_t * in8Le,size_t sizeInBytes)309 void CC_CommonConvertLsbMsbBytesToLswMswWords(
310                                              uint32_t *out32Le,
311                                              const uint8_t  *in8Le,
312                                              size_t  sizeInBytes)
313 {
314 
315         uint32_t sizeInWords;
316 
317         /* Size in words rounded up */
318         sizeInWords = (sizeInBytes + 3)/4;
319 
320         /* if not in place, then zero empty bytes of MS word and copy data */
321         if ((uint8_t*)out32Le != in8Le) {
322                 out32Le[sizeInWords-1] = 0;
323                 CC_PalMemCopy((uint8_t*)out32Le, in8Le, sizeInBytes);
324         }
325 
326 #ifdef BIG__ENDIAN
327         /* Reverse endianness of each word */
328         {
329                 uint32_t i;
330                 for (i = 0; i < sizeInWords; i++) {
331                         CC_COMMON_REVERSE32(out32Le[i]);
332                 }
333         }
334 #endif
335         return;
336 }
337 
338 /***********************************************************************/
339 /**
340 * @brief This function converts 32-bit words array with little endian
341 *        order of words to bytes array with little endian (LE) order of bytes.
342 *
343 *    Assuming: no buffers overlapping, in/out pointers and sizes not equall to NULL,
344                the buffer size must be not less, than input data size.
345 *
346 * @param[out] out8Le - The bytes pointer to output buffer.
347 * @param[in] in32Le - The pointer to input 32-bit words buffer.
348 * @param[in] sizeInWords - The size in words of input data (sizeWords >= 0).
349 *
350 * @return CCError_t - On success CC_OK is returned, on failure a
351 *                        value MODULE_* as defined in .
352 */
CC_CommonConvertLswMswWordsToLsbMsbBytes(uint8_t * out8Le,const uint32_t * in32Le,size_t sizeInWords)353 void CC_CommonConvertLswMswWordsToLsbMsbBytes(
354                                              uint8_t *out8Le,
355                                              const uint32_t  *in32Le,
356                                              size_t  sizeInWords)
357 {
358         /* FUNCTION LOGIC */
359 
360 #ifndef BIG__ENDIAN
361         if (out8Le != (uint8_t*)in32Le) {
362                 CC_PalMemCopy(out8Le, (uint8_t*)in32Le, sizeInWords*sizeof(uint32_t));
363         }
364 #else
365         /* Reverse endianness of each word and copy it to output */
366         size_t i;
367 
368         for (i = 0; i < sizeInWords; i++) {
369                 if (out8Le != (uint8_t*)in32Le) {
370                         uint32_t tmp;
371                         tmp = in32Le[i / sizeof(uint32_t)];
372                         CC_COMMON_REVERSE32(tmp);
373                         out8Le[i*sizeof(uint32_t) + 0] = tmp & 0xFF;
374                         out8Le[i*sizeof(uint32_t) + 1] = (tmp >>  8) & 0xFF;
375                         out8Le[i*sizeof(uint32_t) + 2] = (tmp >> 16) & 0xFF;
376                         out8Le[i*sizeof(uint32_t) + 3] = (tmp >> 24) & 0xFF;
377                 } else {
378                         CC_COMMON_REVERSE32(in32Le[i]);
379                 }
380         }
381 
382 #endif
383         return;
384 }
385 
386 #endif
387