xref: /aosp_15_r20/external/libopenapv/src/oapv_metadata.c (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  * All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  *   this list of conditions and the following disclaimer in the documentation
13  *   and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the copyright owner, nor the names of its contributors
16  *   may be used to endorse or promote products derived from this software
17  *   without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "oapv_def.h"
33 #include "oapv_metadata.h"
34 
meta_id_to_ctx(oapvm_t id)35 static oapvm_ctx_t *meta_id_to_ctx(oapvm_t id)
36 {
37     oapvm_ctx_t *ctx;
38     oapv_assert_rv(id, NULL);
39     ctx = (oapvm_ctx_t *)id;
40     oapv_assert_rv(ctx->magic == OAPVM_MAGIC_CODE, NULL);
41     return ctx;
42 }
43 
meta_mdp_find_last_with_check(oapv_md_t * md,int type,unsigned char * uuid)44 static oapv_mdp_t **meta_mdp_find_last_with_check(oapv_md_t *md, int type, unsigned char *uuid)
45 {
46     oapv_mdp_t **last_mdp = &md->md_payload;
47 
48     while((*last_mdp) != NULL) {
49         if((*last_mdp) == NULL)
50             break;
51         if((*last_mdp)->pld_type == type) {
52             if(type == OAPV_METADATA_USER_DEFINED) {
53                 if(oapv_mcmp(uuid, (*last_mdp)->pld_data, 16) == 0) {
54                     return NULL;
55                 }
56             }
57             else {
58                 return NULL;
59             }
60         }
61         last_mdp = &((*last_mdp)->next);
62     }
63     return last_mdp;
64 }
65 
meta_md_find_mdp(oapv_md_t * md,int mdt)66 static oapv_mdp_t *meta_md_find_mdp(oapv_md_t *md, int mdt)
67 {
68     oapv_mdp_t *mdp = md->md_payload;
69 
70     while(mdp != NULL) {
71         if(mdp->pld_type == mdt) {
72             break;
73         }
74         mdp = mdp->next;
75     }
76 
77     return mdp;
78 }
79 
meta_md_free_mdp(oapv_mdp_t * mdp)80 static int meta_md_free_mdp(oapv_mdp_t *mdp)
81 {
82     oapv_mfree(mdp->pld_data);
83     return OAPV_OK;
84 }
85 
meta_md_rm_mdp(oapv_md_t * md,int mdt)86 static int meta_md_rm_mdp(oapv_md_t *md, int mdt)
87 {
88     oapv_mdp_t *mdp = md->md_payload;
89     oapv_mdp_t *mdp_prev = NULL;
90 
91     while(mdp->pld_type != mdt && mdp->next != NULL) {
92         mdp_prev = mdp;
93         mdp = mdp->next;
94     }
95 
96     if(mdp->pld_type == mdt) {
97         if(mdp_prev == NULL) {
98             md->md_payload = NULL;
99         }
100         else {
101             mdp_prev->next = mdp->next;
102         }
103         meta_md_free_mdp(mdp);
104         md->md_num--;
105         return OAPV_OK;
106     }
107 
108     return OAPV_ERR_NOT_FOUND;
109 }
110 
meta_md_rm_usd(oapv_md_t * md,unsigned char * uuid)111 static int meta_md_rm_usd(oapv_md_t *md, unsigned char *uuid)
112 {
113     oapv_mdp_t *mdp = md->md_payload;
114     oapv_mdp_t *mdp_prev = NULL;
115     while(mdp != NULL) {
116         if(mdp->pld_type == OAPV_METADATA_USER_DEFINED) {
117             if(oapv_mcmp(uuid, mdp->pld_data, 16) == 0) {
118                 if(mdp_prev == NULL) {
119                     md->md_payload = NULL;
120                 }
121                 else {
122                     mdp_prev->next = mdp->next;
123                 }
124                 oapv_assert_rv(md->md_size >= mdp->pld_size, OAPV_ERR_UNEXPECTED);
125                 md->md_size -= mdp->pld_size;
126                 meta_md_free_mdp(mdp);
127                 md->md_num--;
128                 return OAPV_OK;
129             }
130         }
131         mdp_prev = mdp;
132         mdp = mdp->next;
133     }
134 
135     return OAPV_ERR_NOT_FOUND;
136 }
137 
meta_md_find_usd(oapv_md_t * md,unsigned char * uuid)138 static oapv_mdp_t *meta_md_find_usd(oapv_md_t *md, unsigned char *uuid)
139 {
140     oapv_mdp_t *mdp = md->md_payload;
141     while(mdp != NULL) {
142         if(mdp->pld_type == OAPV_METADATA_USER_DEFINED) {
143             oapv_md_usd_t *usd = (oapv_md_usd_t *)mdp->pld_data;
144             if(oapv_mcmp(uuid, usd->uuid, 16) == 0) {
145                 return mdp;
146             }
147         }
148         mdp = mdp->next;
149     }
150 
151     return NULL;
152 }
153 
meta_verify_mdp_data(int type,int size,u8 * data)154 static int meta_verify_mdp_data(int type, int size, u8 *data)
155 {
156     if(type == OAPV_METADATA_ITU_T_T35) {
157         if(size == 0) {
158             return OAPV_ERR_INVALID_ARGUMENT;
159         }
160         if(*data == 0xFF) {
161             if(size == 1) {
162                 return OAPV_ERR_INVALID_ARGUMENT;
163             }
164         }
165     }
166     else if(type == OAPV_METADATA_MDCV) {
167         if(size != 24) {
168             return OAPV_ERR_INVALID_ARGUMENT;
169         }
170     }
171     else if(type == OAPV_METADATA_CLL) {
172         if(size != 4) {
173             return OAPV_ERR_INVALID_ARGUMENT;
174         }
175     }
176     else if(type == OAPV_METADATA_USER_DEFINED) {
177         if(size < 16) {
178             return OAPV_ERR_INVALID_ARGUMENT;
179         }
180     }
181     else {
182         return OAPV_OK;
183     }
184     return OAPV_OK;
185 }
186 
meta_free_md(oapv_md_t * md)187 static void meta_free_md(oapv_md_t *md)
188 {
189     oapv_mdp_t *mdp = md->md_payload;
190     while(mdp != NULL) {
191         oapv_mdp_t *tmp_mdp = mdp;
192         mdp = mdp->next;
193         if(tmp_mdp->pld_data != NULL) {
194             oapv_mfree(tmp_mdp->pld_data);
195         }
196         oapv_mfree(tmp_mdp);
197     }
198 }
199 
oapvm_set(oapvm_t mid,int group_id,int type,void * data,int size,unsigned char * uuid)200 int oapvm_set(oapvm_t mid, int group_id, int type, void *data, int size, unsigned char *uuid)
201 {
202     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
203 
204     int          ret = meta_verify_mdp_data(type, size, (u8 *)data);
205     oapv_assert_rv(OAPV_SUCCEEDED(ret), ret);
206 
207     int md_list_idx = 0;
208     while(md_list_idx < md_list->num) {
209         if(md_list->group_ids[md_list_idx] == group_id) {
210             break;
211         }
212         md_list_idx++;
213     }
214     if(md_list_idx == md_list->num) {
215         md_list->num++;
216     }
217     md_list->group_ids[md_list_idx] = group_id;
218     oapv_mdp_t **last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], type,
219                                                           (type == OAPV_METADATA_USER_DEFINED) ? uuid : NULL);
220     while(last_ptr == NULL) {
221         oapvm_rem(mid, group_id, type, uuid);
222         last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], type,
223                                                  (type == OAPV_METADATA_USER_DEFINED) ? uuid : NULL);
224     }
225     oapv_mdp_t *tmp_mdp = oapv_malloc(sizeof(oapv_mdp_t));
226     oapv_assert_rv(tmp_mdp != NULL, OAPV_ERR_OUT_OF_MEMORY);
227 
228     oapv_mset(tmp_mdp, 0, sizeof(oapv_mdp_t));
229     tmp_mdp->pld_size = size;
230     tmp_mdp->pld_type = type;
231     tmp_mdp->pld_data = data;
232     *last_ptr = tmp_mdp;
233 
234     /* calculate length of payload type */
235     int tmp_mpt = type;
236     while(tmp_mpt >= 255) {
237         tmp_mpt -= 255;
238         md_list->md_arr[md_list_idx].md_size += 1;
239     }
240     md_list->md_arr[md_list_idx].md_size += 1;
241 
242     /*  calculate length of payload data size */
243     int tmp_mps = size;
244     while(tmp_mps >= 255) {
245         tmp_mps -= 255;
246         md_list->md_arr[md_list_idx].md_size += 1;
247     }
248     md_list->md_arr[md_list_idx].md_size += 1;
249 
250     md_list->md_arr[md_list_idx].md_size += tmp_mdp->pld_size;
251     md_list->md_arr[md_list_idx].md_num++;
252     return OAPV_OK;
253 }
254 
oapvm_get(oapvm_t mid,int group_id,int type,void ** data,int * size,unsigned char * uuid)255 int oapvm_get(oapvm_t mid, int group_id, int type, void **data, int *size, unsigned char *uuid)
256 {
257     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
258     for(int i = 0; i < md_list->num; i++) {
259         if(group_id != md_list->group_ids[i]) {
260             continue;
261         }
262         oapv_mdp_t *mdp = (type == OAPV_METADATA_USER_DEFINED) ? meta_md_find_usd(&md_list->md_arr[i], uuid) : meta_md_find_mdp(&md_list->md_arr[i], type);
263         if(mdp != NULL) {
264             *data = mdp->pld_data;
265             *size = mdp->pld_size;
266             return OAPV_OK;
267         }
268     }
269 
270     return OAPV_ERR_NOT_FOUND;
271 }
oapvm_rem(oapvm_t mid,int group_id,int type,unsigned char * uuid)272 int oapvm_rem(oapvm_t mid, int group_id, int type, unsigned char *uuid)
273 {
274     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
275     int          md_list_idx = 0;
276     while(md_list_idx < md_list->num) {
277         if(md_list->group_ids[md_list_idx] == group_id) {
278             break;
279         }
280         md_list_idx++;
281     }
282     oapv_assert_rv(md_list_idx < md_list->num, OAPV_ERR_NOT_FOUND);
283     if(type == OAPV_METADATA_USER_DEFINED) {
284         return meta_md_rm_usd(&md_list->md_arr[md_list_idx], uuid);
285     }
286     return meta_md_rm_mdp(&md_list->md_arr[md_list_idx], type);
287 }
288 
oapvm_set_all(oapvm_t mid,oapvm_payload_t * pld,int num_plds)289 int oapvm_set_all(oapvm_t mid, oapvm_payload_t *pld, int num_plds)
290 {
291     int          ret;
292     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
293     for(int i = 0; i < num_plds; i++) {
294         ret = meta_verify_mdp_data(pld[i].type, pld[i].data_size, (u8 *)pld[i].data);
295         oapv_assert_g(OAPV_SUCCEEDED(ret), ERR);
296 
297         int md_list_idx = 0;
298         while(md_list_idx < md_list->num) {
299             if(md_list->group_ids[md_list_idx] == pld[i].group_id) {
300                 break;
301             }
302             md_list_idx++;
303         }
304         if(md_list_idx == md_list->num) {
305             md_list->num++;
306         }
307 
308         md_list->group_ids[md_list_idx] = pld[i].group_id;
309         md_list->md_arr[md_list_idx].md_num++;
310         oapv_mdp_t **last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], pld[i].type,
311                                                               (pld[i].type == OAPV_METADATA_USER_DEFINED) ? pld[i].uuid : NULL);
312         while(last_ptr == NULL) {
313             oapvm_rem(mid, pld[i].group_id, pld[i].type, pld[i].uuid);
314             last_ptr = meta_mdp_find_last_with_check(&md_list->md_arr[md_list_idx], pld[i].type,
315                                                      (pld[i].type == OAPV_METADATA_USER_DEFINED) ? pld[i].uuid : NULL);
316         }
317         oapv_mdp_t *tmp_mdp = oapv_malloc(sizeof(oapv_mdp_t));
318         oapv_assert_rv(tmp_mdp != NULL, OAPV_ERR_OUT_OF_MEMORY);
319         oapv_mset(tmp_mdp, 0, sizeof(oapv_mdp_t));
320         tmp_mdp->pld_size = pld[i].data_size;
321         tmp_mdp->pld_type = pld[i].type;
322         tmp_mdp->pld_data = pld[i].data;
323         md_list->md_arr[md_list_idx].md_size += tmp_mdp->pld_size;
324 
325         *last_ptr = tmp_mdp;
326     }
327     return OAPV_OK;
328 
329 ERR:
330     return ret;
331 }
332 
oapvm_get_all(oapvm_t mid,oapvm_payload_t * pld,int * num_plds)333 int oapvm_get_all(oapvm_t mid, oapvm_payload_t *pld, int *num_plds)
334 {
335     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
336     if(pld == NULL) {
337         int num_payload = 0;
338         for(int i = 0; i < md_list->num; i++) {
339             num_payload += md_list->md_arr[i].md_num;
340         }
341         *num_plds = num_payload;
342         return OAPV_OK;
343     }
344     int p_cnt = 0;
345     for(int i = 0; i < md_list->num; i++) {
346         int         group_id = md_list->group_ids[i];
347         oapv_mdp_t *mdp = md_list->md_arr[i].md_payload;
348         while(mdp != NULL) {
349             oapv_assert_rv(p_cnt < *num_plds, OAPV_ERR_REACHED_MAX);
350             pld[p_cnt].group_id = group_id;
351             pld[p_cnt].data_size = mdp->pld_size;
352             pld[p_cnt].data = mdp->pld_data;
353             pld[p_cnt].type = mdp->pld_type;
354             if(pld[p_cnt].type == OAPV_METADATA_USER_DEFINED) {
355                 oapv_mcpy(pld[p_cnt].uuid, mdp->pld_data, 16);
356             }
357             else {
358                 oapv_mset(pld[p_cnt].uuid, 0, 16);
359             }
360             p_cnt++;
361             mdp = mdp->next;
362         }
363     }
364     *num_plds = p_cnt;
365     return OAPV_OK;
366 }
367 
oapvm_rem_all(oapvm_t mid)368 void oapvm_rem_all(oapvm_t mid)
369 {
370 
371     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
372     for(int i = 0; i < md_list->num; i++) {
373         meta_free_md(&md_list->md_arr[i]);
374         oapv_mset(&md_list->md_arr[i], 0, sizeof(oapv_md_t));
375     }
376     md_list->num = 0;
377 }
378 
oapvm_create(int * err)379 oapvm_t oapvm_create(int *err)
380 {
381     oapvm_ctx_t *md_list;
382     md_list = oapv_malloc(sizeof(oapvm_ctx_t));
383     if(md_list == NULL) {
384         *err = OAPV_ERR_OUT_OF_MEMORY;
385         return NULL;
386     }
387     oapv_mset(md_list, 0, sizeof(oapvm_ctx_t));
388 
389     md_list->magic = OAPVM_MAGIC_CODE;
390     return md_list;
391 }
392 
oapvm_delete(oapvm_t mid)393 void oapvm_delete(oapvm_t mid)
394 {
395     oapvm_ctx_t *md_list = meta_id_to_ctx(mid);
396     for(int i = 0; i < md_list->num; i++) {
397         meta_free_md(&md_list->md_arr[i]);
398     }
399     oapv_mfree(md_list);
400 }
401