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