1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   Pictbridge Application                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_pictbridge.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_pictbridge_object_tag_line_add                  PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function adds a tag line into the target xml object            */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    pima_object_buffer                    Pointer to object buffer      */
48 /*    object_length                         Length of the object          */
49 /*    tag_element                           Tag to insert                 */
50 /*    tag_flag                              Flags                         */
51 /*    tag_variable                          Variable if any               */
52 /*    tag_variable_value                    Variable value if any         */
53 /*    tag_element                           element to insert after tag   */
54 /*    pima_object_buffer_updated            Updated Address of the object */
55 /*    object_length_updated                 Updated length                */
56 /*                                                                        */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    Completion Status                                                   */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _ux_pictbridge_dpshost_object_get                                   */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
74 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            verified memset and memcpy  */
76 /*                                            cases,                      */
77 /*                                            resulting in version 6.1    */
78 /*                                                                        */
79 /**************************************************************************/
_ux_pictbridge_object_tag_line_add(UCHAR * pima_object_buffer,ULONG object_length,UCHAR * tag_element_string,ULONG tag_flag,UCHAR * tag_variable,ULONG tag_variable_value,VOID * tag_element,UCHAR ** pima_object_buffer_updated,ULONG * object_length_updated)80 UINT _ux_pictbridge_object_tag_line_add(UCHAR *pima_object_buffer,
81                                                  ULONG object_length,
82                                                  UCHAR *tag_element_string,
83                                                  ULONG tag_flag,
84                                                  UCHAR *tag_variable,
85                                                  ULONG  tag_variable_value,
86                                                  VOID  *tag_element,
87                                                  UCHAR **pima_object_buffer_updated,
88                                                  ULONG *object_length_updated)
89 {
90 
91 UINT                                element_length = 0;
92 ULONG                               value_index;
93 UINT                                status;
94 
95     /* Check if we need to insert a beginning tag.  */
96     if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
97     {
98 
99         /* Going to add '<'.  */
100         object_length += 1;
101 
102         /* Calculate the length of the element.  */
103         status = _ux_utility_string_length_check(tag_element_string, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
104         if (status != UX_SUCCESS)
105 
106             /* Bad element.  */
107             return(status);
108 
109         /* Going to add element.  */
110         object_length += element_length;
111 
112         /* Do bounds-checking.  */
113         if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
114             return(UX_MEMORY_INSUFFICIENT);
115 
116         /* Insert a "<".  */
117         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_START_BRACKET;
118 
119         /* Create the element string.  */
120        _ux_utility_memory_copy(pima_object_buffer, tag_element_string, element_length); /* Use case of memcpy is verified. */
121 
122         /* Update the object pointer position.  */
123         pima_object_buffer += element_length;
124 
125         /* Do we have a variable to insert after the opening tag ?  */
126         if (tag_variable != UX_NULL)
127         {
128 
129             /* Going to add " ".  */
130             object_length += 1;
131 
132             /* Insert the variable.  First calculate the length of the variable.  */
133             status = _ux_utility_string_length_check(tag_variable, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
134             if (status != UX_SUCCESS)
135 
136                 /* Bad element.  */
137                 return(status);
138 
139             /* Going to add element.  */
140             object_length += element_length;
141 
142             /* Going to insert "=".  */
143             object_length += 1;
144 
145             /* Going to insert a quote.  */
146             object_length += 1;
147 
148             /* Going to insert 8 hex chars.  */
149             object_length += 8;
150 
151             /* Going to insert a quote.  */
152             object_length += 1;
153 
154             /* Do bounds-checking.  */
155             if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
156                 return(UX_MEMORY_INSUFFICIENT);
157 
158             /* Insert a " ".  */
159             *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
160 
161             /* Create the variable string.  */
162             _ux_utility_memory_copy(pima_object_buffer, tag_variable, element_length); /* Use case of memcpy is verified. */
163 
164             /* Update the object pointer position.  */
165             pima_object_buffer += element_length;
166 
167             /* Insert a "=".  */
168             *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_EQUAL;
169 
170             /* Insert a quote.  */
171             *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_QUOTE;
172 
173             /* Insert a value in between the quote.  This value is always of type hexa.  */
174             status = _ux_pictbridge_hexa_to_element(tag_variable_value, pima_object_buffer);
175             if (status != UX_SUCCESS)
176 
177                 /* Bad element.  */
178                 return(status);
179 
180             /* Update the object pointer position.  */
181             pima_object_buffer += 8;
182 
183             /* Insert a quote.  */
184             *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_QUOTE;
185         }
186 
187         /* Check if we need to insert a slash at the end of the tag.   */
188         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_FORCE_SLASH_AT_END)
189         {
190 
191             /* Going to insert a "/".  */
192             object_length += 1;
193 
194             /* Do bounds-checking.  */
195             if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
196                 return(UX_MEMORY_INSUFFICIENT);
197 
198             /* Insert a "/".  */
199             *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SLASH;
200         }
201 
202         /* Going to insert a ">".  */
203         object_length += 1;
204 
205         /* Do bounds-checking.  */
206         if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
207             return(UX_MEMORY_INSUFFICIENT);
208 
209         /* Insert a ">".  */
210         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_END_BRACKET;
211     }
212 
213     /* Is there a tag element to add between the begin tag and end tag ?  */
214     /* We do have something to insert, this element can have multiple format and
215        can be a single value or an array of values.  */
216     if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE)
217     {
218 
219         /* We have a single variable.  Check its nature.  Is it hexa ? */
220         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_HEXA)
221         {
222 
223             /*  Going to insert 8 hex chars. Do bounds-checking.  */
224             if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
225                 return(UX_MEMORY_INSUFFICIENT);
226 
227             /* We have a single hexa value to insert.  */
228             status = _ux_pictbridge_hexa_to_element((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer);
229             if (status != UX_SUCCESS)
230 
231                 /* Bad element.  */
232                 return(status);
233             element_length = 8;
234         }
235 
236         /* Is it decimal ?  */
237         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_DECIMAL)
238         {
239 
240             /* Going to insert at maximum 8 chars. Do bounds-checking.  */
241             if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
242                 return(UX_MEMORY_INSUFFICIENT);
243 
244             /* We have a single decimal value to insert.  */
245             status = _ux_pictbridge_hexa_to_decimal_string((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_OFF, 8);
246             if (status != UX_SUCCESS)
247 
248                 /* Bad element.  */
249                 return(status);
250             _ux_utility_string_length_check(pima_object_buffer, &element_length, 8);
251         }
252 
253         /* Is it 3 decimal with leading zeroes ?  */
254         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_DECIMAL_3DIGITS)
255         {
256 
257             /* Going to insert at maximum 3 chars. Do bounds-checking.  */
258             if (object_length + 3 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
259                 return(UX_MEMORY_INSUFFICIENT);
260 
261             /* We have a single decimal value to insert but 3 digits only and leading zeroes.  */
262             status = _ux_pictbridge_hexa_to_decimal_string((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_ON, 3);
263             if (status != UX_SUCCESS)
264 
265                 /* Bad element.  */
266                 return(status);
267             element_length = 3;
268         }
269 
270         /* Is it in the form 00.00 ?  */
271         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_MAJOR_MINOR)
272         {
273 
274             /* Going to insert at maximum 5 chars. Do bounds-checking.  */
275             if (object_length + 5 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
276                 return(UX_MEMORY_INSUFFICIENT);
277 
278             /* We have a major minor value to insert.  */
279             status = _ux_pictbridge_hexa_to_major_minor((ULONG)(ALIGN_TYPE) tag_element, pima_object_buffer);
280             if (status != UX_SUCCESS)
281 
282                 /* Bad element.  */
283                 return(status);
284             element_length = 5;
285         }
286 
287         /* Is it a ascii string ?  */
288         if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_STRING)
289         {
290 
291             /* Calculate the length of the element to be inserted.  */
292             status = _ux_utility_string_length_check((UCHAR *) tag_element, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
293             if (status != UX_SUCCESS)
294 
295                 /* Bad element.  */
296                 return(status);
297 
298             /* Going to insert element. Do bounds-checking.  */
299             if (object_length + element_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
300                 return(UX_MEMORY_INSUFFICIENT);
301 
302             /* We have a string to insert.  */
303             _ux_utility_memory_copy(pima_object_buffer, (UCHAR *) tag_element, element_length); /* Use case of memcpy is verified. */
304         }
305 
306         /* Update the object pointer position.  */
307         pima_object_buffer += element_length;
308 
309         object_length += element_length;
310     }
311 
312     /* Is there an array to insert ? */
313     if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY)
314     {
315 
316         /* We have an array to insert.  First reset the value index.  */
317         value_index =  0;
318 
319         /* Parse all qualities supported and insert their values.  */
320         while( *((ULONG *)tag_element + value_index) != 0)
321         {
322 
323             /* If this value is not the first, we must use a space separator.  */
324             if (value_index != 0)
325             {
326 
327                 /* Going to insert a space.  */
328                 object_length += 1;
329 
330                 /* Do bounds-checking.  */
331                 if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
332                     return(UX_MEMORY_INSUFFICIENT);
333 
334                 /* Insert a space.  */
335                 *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
336             }
337 
338             /* We have a array variable.  Check its nature.  Is it hexa ? */
339             if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_HEXA)
340             {
341 
342                 /*  Going to insert 8 hex chars. Do bounds-checking.  */
343                 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
344                     return(UX_MEMORY_INSUFFICIENT);
345 
346                 /* We have a single hexa value to insert.  */
347                 status = _ux_pictbridge_hexa_to_element( *((ULONG *) tag_element + value_index), pima_object_buffer);
348                 if (status != UX_SUCCESS)
349 
350                     /* Bad element.  */
351                     return(status);
352                 element_length = 8;
353             }
354 
355             /* Is it decimal ?  */
356             if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_DECIMAL)
357             {
358 
359                 /* Going to insert at maximum 8 chars. Do bounds-checking.  */
360                 if (object_length + 8 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
361                     return(UX_MEMORY_INSUFFICIENT);
362 
363                 /* We have a array of decimal value to insert.  */
364                 status = _ux_pictbridge_hexa_to_decimal_string( *((ULONG *)tag_element + value_index), pima_object_buffer, UX_PICTBRIDGE_LEADING_ZERO_OFF, 8);
365                 if (status != UX_SUCCESS)
366 
367                     /* Bad element.  */
368                     return(status);
369                 _ux_utility_string_length_check(pima_object_buffer, &element_length, 8);
370             }
371 
372             /* Is it in the form 00.00 ?  */
373             if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_MAJOR_MINOR)
374             {
375 
376                 /* Going to insert at maximum 5 chars. Do bounds-checking.  */
377                 if (object_length + 5 > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
378                     return(UX_MEMORY_INSUFFICIENT);
379 
380                 /* We have a array of major minor value to insert.  */
381                 status = _ux_pictbridge_hexa_to_major_minor( *((ULONG *) tag_element + value_index), pima_object_buffer);
382                 if (status != UX_SUCCESS)
383 
384                     /* Bad element.  */
385                     return(status);
386                 element_length = 5;
387             }
388 
389             /* Is it a ascii string ?  */
390             if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_VARIABLE_ARRAY_STRING)
391             {
392 
393                 /* Calculate the length of the element to be inserted.  */
394                 status = _ux_utility_string_length_check((UCHAR *) (*((ALIGN_TYPE *)tag_element)), &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
395                 if (status != UX_SUCCESS)
396 
397                     /* Bad element.  */
398                     return(status);
399 
400                 /* Going to insert element. Do bounds-checking.  */
401                 if (object_length + element_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
402                     return(UX_MEMORY_INSUFFICIENT);
403 
404                 /* We have a string to insert.  */
405                 _ux_utility_memory_copy(pima_object_buffer, (UCHAR *) (*((ALIGN_TYPE *)tag_element)), element_length); /* Use case of memcpy is verified. */
406             }
407 
408             /* Update the object pointer position.  */
409             pima_object_buffer += element_length;
410 
411             /* And update the cumulated length of the object.  */
412             object_length += element_length;
413 
414             /* Next index value.  */
415             value_index++;
416         }
417     }
418 
419     /* Check if we need to insert an end tag.  */
420     if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_END)
421     {
422 
423         /* Going to insert a "<".  */
424         object_length += 1;
425 
426         /* Going to insert a "/".  */
427         object_length += 1;
428 
429         /* Calculate the length of the element.  */
430         status = _ux_utility_string_length_check(tag_element_string, &element_length, UX_PICTBRIDGE_MAX_ELEMENT_SIZE);
431         if (status != UX_SUCCESS)
432 
433             /* Bad element.  */
434             return(status);
435 
436         /* Going to insert element.  */
437         object_length += element_length;
438 
439         /* Going to insert a ">".  */
440         object_length += 1;
441 
442         /* Going to insert a LF.  */
443         object_length += 1;
444 
445         /* Do bounds-checking.  */
446         if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
447             return(UX_MEMORY_INSUFFICIENT);
448 
449         /* Insert a "<".  */
450         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_START_BRACKET;
451 
452         /* Insert a "/".  */
453         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_SLASH;
454 
455         /* Create the element string.  */
456        _ux_utility_memory_copy(pima_object_buffer, tag_element_string, element_length); /* Use case of memcpy is verified. */
457 
458         /* Update the object pointer position.  */
459         pima_object_buffer += element_length;
460 
461         /* Insert a ">".  */
462         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_END_BRACKET;
463 
464         /* Insert a LF.  */
465         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_LF;
466     }
467 
468     /* Check if we need to force a LF at end.  */
469     if (tag_flag & UX_PICTBRIDGE_TAG_FLAG_FORCE_LF)
470     {
471 
472         /* Going to insert a LF.  */
473         object_length += 1;
474 
475         /* Do bounds-checking.  */
476         if (object_length > UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER)
477             return(UX_MEMORY_INSUFFICIENT);
478 
479         /* Insert a LF.  */
480         *pima_object_buffer++ = UX_PICTBRIDGE_TAG_CHAR_LF;
481     }
482 
483     /* Update the caller's object position.  */
484     *pima_object_buffer_updated = pima_object_buffer;
485 
486     /* Update the caller's object length .  */
487     *object_length_updated = object_length;
488 
489     /* Return completion status.  */
490     return(UX_SUCCESS);
491 }
492