1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2019, 2021 NXP
4 *
5 * Brief Scatter-Gatter Table management utilities.
6 */
7 #include <caam_common.h>
8 #include <caam_io.h>
9 #include <caam_utils_mem.h>
10 #include <caam_utils_sgt.h>
11 #include <caam_trace.h>
12 #include <mm/core_memprot.h>
13 #include <mm/core_mmu.h>
14 #include <string.h>
15 #include <tee/cache.h>
16 #include <util.h>
17
caam_sgt_cache_op(enum utee_cache_operation op,struct caamsgtbuf * insgt,size_t length)18 void caam_sgt_cache_op(enum utee_cache_operation op, struct caamsgtbuf *insgt,
19 size_t length)
20 {
21 unsigned int idx = 0;
22 size_t op_size = 0;
23 size_t rem_length = length;
24
25 cache_operation(TEE_CACHECLEAN, (void *)insgt->sgt,
26 ROUNDUP(insgt->number, CFG_CAAM_SGT_ALIGN) *
27 sizeof(union caamsgt));
28
29 SGT_TRACE("SGT @%p %d entries", insgt, insgt->number);
30 for (idx = 0; idx < insgt->number && rem_length; idx++) {
31 op_size = MIN(rem_length, insgt->buf[idx].length);
32 if (!insgt->buf[idx].nocache)
33 cache_operation(op, (void *)insgt->buf[idx].data,
34 op_size);
35 rem_length -= op_size;
36 }
37 }
38
caam_sgt_fill_table(struct caamsgtbuf * sgt)39 void caam_sgt_fill_table(struct caamsgtbuf *sgt)
40 {
41 unsigned int idx = 0;
42
43 SGT_TRACE("Create %d SGT entries", sgt->number);
44
45 for (idx = 0; idx < sgt->number - 1; idx++) {
46 CAAM_SGT_ENTRY(&sgt->sgt[idx], sgt->buf[idx].paddr,
47 sgt->buf[idx].length);
48 sgt_entry_trace(idx, sgt);
49 }
50
51 CAAM_SGT_ENTRY_FINAL(&sgt->sgt[idx], sgt->buf[idx].paddr,
52 sgt->buf[idx].length);
53 sgt_entry_trace(idx, sgt);
54 }
55
caam_sgt_derive(struct caamsgtbuf * sgt,const struct caamsgtbuf * from,size_t offset,size_t length)56 enum caam_status caam_sgt_derive(struct caamsgtbuf *sgt,
57 const struct caamsgtbuf *from, size_t offset,
58 size_t length)
59 {
60 enum caam_status retstatus = CAAM_FAILURE;
61 unsigned int idx = 0;
62 unsigned int st_idx = 0;
63 size_t off = offset;
64 size_t rlength = length;
65
66 SGT_TRACE("Derive from %p - offset %zu, %d SGT entries", from, offset,
67 from->number);
68
69 if (from->length - offset < length) {
70 SGT_TRACE("From SGT/Buffer too short (%zu)", from->length);
71 return CAAM_SHORT_BUFFER;
72 }
73
74 for (; idx < from->number && off >= from->buf[idx].length; idx++)
75 off -= from->buf[idx].length;
76
77 st_idx = idx;
78 sgt->number = 1;
79 rlength -= MIN(rlength, from->buf[idx].length - off);
80
81 for (idx++; idx < from->number && rlength; idx++) {
82 rlength -= MIN(rlength, from->buf[idx].length);
83 sgt->number++;
84 }
85
86 sgt->sgt_type = (sgt->number > 1) ? true : false;
87
88 /* Allocate a new SGT/Buffer object */
89 retstatus = caam_sgtbuf_alloc(sgt);
90 SGT_TRACE("Allocate %d SGT entries ret 0x%" PRIx32, sgt->number,
91 retstatus);
92 if (retstatus != CAAM_NO_ERROR)
93 return retstatus;
94
95 memcpy(sgt->buf, &from->buf[st_idx], sgt->number * sizeof(*sgt->buf));
96
97 if (sgt->sgt_type) {
98 memcpy(sgt->sgt, &from->sgt[st_idx],
99 sgt->number * sizeof(*sgt->sgt));
100
101 /* Set the offset of the first sgt entry */
102 sgt_entry_offset(sgt->sgt, off);
103
104 /*
105 * Push the SGT Table into memory now because
106 * derived objects are not pushed.
107 */
108 cache_operation(TEE_CACHECLEAN, sgt->sgt,
109 sgt->number * sizeof(*sgt->sgt));
110
111 sgt->paddr = virt_to_phys(sgt->sgt);
112 } else {
113 sgt->paddr = sgt->buf->paddr + off;
114 }
115
116 sgt->length = length;
117
118 return CAAM_NO_ERROR;
119 }
120
caam_sgtbuf_free(struct caamsgtbuf * data)121 void caam_sgtbuf_free(struct caamsgtbuf *data)
122 {
123 if (data->sgt_type)
124 caam_free(data->sgt);
125 else
126 caam_free(data->buf);
127
128 data->sgt = NULL;
129 data->buf = NULL;
130 }
131
caam_sgtbuf_alloc(struct caamsgtbuf * data)132 enum caam_status caam_sgtbuf_alloc(struct caamsgtbuf *data)
133 {
134 unsigned int nb_sgt = 0;
135
136 if (!data || !data->number)
137 return CAAM_BAD_PARAM;
138
139 if (data->sgt_type) {
140 nb_sgt = ROUNDUP(data->number, CFG_CAAM_SGT_ALIGN);
141 data->sgt = caam_calloc(nb_sgt * (sizeof(union caamsgt) +
142 sizeof(struct caambuf)));
143 data->buf = (void *)(((uint8_t *)data->sgt) +
144 (nb_sgt * sizeof(union caamsgt)));
145 } else {
146 data->buf = caam_calloc(data->number * sizeof(struct caambuf));
147 data->sgt = NULL;
148 }
149
150 if (!data->buf || (!data->sgt && data->sgt_type)) {
151 caam_sgtbuf_free(data);
152 return CAAM_OUT_MEMORY;
153 }
154
155 return CAAM_NO_ERROR;
156 }
157