1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 *
3 * Copyright 2008-2016 Freescale Semiconductor Inc.
4 * Copyright 2016,2019 NXP
5 */
6
7 #ifndef __RTA_FIFO_LOAD_STORE_CMD_H__
8 #define __RTA_FIFO_LOAD_STORE_CMD_H__
9
10 extern enum rta_sec_era rta_sec_era;
11
12 static const uint32_t fifo_load_table[][2] = {
13 /*1*/ { PKA0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_A0 },
14 { PKA1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_A1 },
15 { PKA2, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_A2 },
16 { PKA3, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_A3 },
17 { PKB0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_B0 },
18 { PKB1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_B1 },
19 { PKB2, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_B2 },
20 { PKB3, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_B3 },
21 { PKA, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_A },
22 { PKB, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_B },
23 { PKN, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_PK_N },
24 { SKIP, FIFOLD_CLASS_SKIP },
25 { MSG1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG },
26 { MSG2, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG },
27 { MSGOUTSNOOP, FIFOLD_CLASS_BOTH | FIFOLD_TYPE_MSG1OUT2 },
28 { MSGINSNOOP, FIFOLD_CLASS_BOTH | FIFOLD_TYPE_MSG },
29 { IV1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_IV },
30 { IV2, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_IV },
31 { AAD1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_AAD },
32 { ICV1, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_ICV },
33 { ICV2, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_ICV },
34 { BIT_DATA, FIFOLD_TYPE_BITDATA },
35 /*23*/ { IFIFO, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_NOINFOFIFO }
36 };
37
38 /*
39 * Allowed FIFO_LOAD input data types for each SEC Era.
40 * Values represent the number of entries from fifo_load_table[] that are
41 * supported.
42 */
43 static const unsigned int fifo_load_table_sz[] = {22, 22, 23, 23,
44 23, 23, 23, 23,
45 23, 23};
46
47 static inline int
rta_fifo_load(struct program * program,uint32_t src,uint64_t loc,uint32_t length,uint32_t flags)48 rta_fifo_load(struct program *program, uint32_t src,
49 uint64_t loc, uint32_t length, uint32_t flags)
50 {
51 uint32_t opcode = 0;
52 uint32_t ext_length = 0, val = 0;
53 int ret = -EINVAL;
54 bool is_seq_cmd = false;
55 unsigned int start_pc = program->current_pc;
56
57 /* write command type field */
58 if (flags & SEQ) {
59 opcode = CMD_SEQ_FIFO_LOAD;
60 is_seq_cmd = true;
61 } else {
62 opcode = CMD_FIFO_LOAD;
63 }
64
65 /* Parameters checking */
66 if (is_seq_cmd) {
67 if ((flags & IMMED) || (flags & SGF)) {
68 pr_err("SEQ FIFO LOAD: Invalid command\n");
69 goto err;
70 }
71 if ((flags & VLF) && ((flags & EXT) || (length >> 16))) {
72 pr_err("SEQ FIFO LOAD: Invalid usage of VLF\n");
73 goto err;
74 }
75 } else {
76 if (src == SKIP) {
77 pr_err("FIFO LOAD: Invalid src\n");
78 goto err;
79 }
80 if ((flags & AIDF) || (flags & VLF)) {
81 pr_err("FIFO LOAD: Invalid command\n");
82 goto err;
83 }
84 if ((flags & IMMED) && (flags & SGF)) {
85 pr_err("FIFO LOAD: Invalid usage of SGF and IMM\n");
86 goto err;
87 }
88 if ((flags & IMMED) && ((flags & EXT) || (length >> 16))) {
89 pr_err("FIFO LOAD: Invalid usage of EXT and IMM\n");
90 goto err;
91 }
92 }
93
94 /* write input data type field */
95 ret = __rta_map_opcode(src, fifo_load_table,
96 fifo_load_table_sz[rta_sec_era], &val);
97 if (ret < 0) {
98 pr_err("FIFO LOAD: Source value is not supported. SEC Program Line: %d\n",
99 program->current_pc);
100 goto err;
101 }
102 opcode |= val;
103
104 if (flags & CLASS1)
105 opcode |= FIFOLD_CLASS_CLASS1;
106 if (flags & CLASS2)
107 opcode |= FIFOLD_CLASS_CLASS2;
108 if (flags & BOTH)
109 opcode |= FIFOLD_CLASS_BOTH;
110
111 /* write fields: SGF|VLF, IMM, [LC1, LC2, F1] */
112 if (flags & FLUSH1)
113 opcode |= FIFOLD_TYPE_FLUSH1;
114 if (flags & LAST1)
115 opcode |= FIFOLD_TYPE_LAST1;
116 if (flags & LAST2)
117 opcode |= FIFOLD_TYPE_LAST2;
118 if (!is_seq_cmd) {
119 if (flags & SGF)
120 opcode |= FIFOLDST_SGF;
121 if (flags & IMMED)
122 opcode |= FIFOLD_IMM;
123 } else {
124 if (flags & VLF)
125 opcode |= FIFOLDST_VLF;
126 if (flags & AIDF)
127 opcode |= FIFOLD_AIDF;
128 }
129
130 /*
131 * Verify if extended length is required. In case of BITDATA, calculate
132 * number of full bytes and additional valid bits.
133 */
134 if ((flags & EXT) || (length >> 16)) {
135 opcode |= FIFOLDST_EXT;
136 if (src == BIT_DATA) {
137 ext_length = (length / 8);
138 length = (length % 8);
139 } else {
140 ext_length = length;
141 length = 0;
142 }
143 }
144 opcode |= (uint16_t) length;
145
146 __rta_out32(program, opcode);
147 program->current_instruction++;
148
149 /* write pointer or immediate data field */
150 if (flags & IMMED)
151 __rta_inline_data(program, loc, flags & __COPY_MASK, length);
152 else if (!is_seq_cmd)
153 __rta_out64(program, program->ps, loc);
154
155 /* write extended length field */
156 if (opcode & FIFOLDST_EXT)
157 __rta_out32(program, ext_length);
158
159 return (int)start_pc;
160
161 err:
162 program->first_error_pc = start_pc;
163 program->current_instruction++;
164 return ret;
165 }
166
167 static const uint32_t fifo_store_table[][2] = {
168 /*1*/ { PKA0, FIFOST_TYPE_PKHA_A0 },
169 { PKA1, FIFOST_TYPE_PKHA_A1 },
170 { PKA2, FIFOST_TYPE_PKHA_A2 },
171 { PKA3, FIFOST_TYPE_PKHA_A3 },
172 { PKB0, FIFOST_TYPE_PKHA_B0 },
173 { PKB1, FIFOST_TYPE_PKHA_B1 },
174 { PKB2, FIFOST_TYPE_PKHA_B2 },
175 { PKB3, FIFOST_TYPE_PKHA_B3 },
176 { PKA, FIFOST_TYPE_PKHA_A },
177 { PKB, FIFOST_TYPE_PKHA_B },
178 { PKN, FIFOST_TYPE_PKHA_N },
179 { PKE, FIFOST_TYPE_PKHA_E_JKEK },
180 { RNG, FIFOST_TYPE_RNGSTORE },
181 { RNGOFIFO, FIFOST_TYPE_RNGFIFO },
182 { AFHA_SBOX, FIFOST_TYPE_AF_SBOX_JKEK },
183 { MDHA_SPLIT_KEY, FIFOST_CLASS_CLASS2KEY | FIFOST_TYPE_SPLIT_KEK },
184 { MSG, FIFOST_TYPE_MESSAGE_DATA },
185 { KEY1, FIFOST_CLASS_CLASS1KEY | FIFOST_TYPE_KEY_KEK },
186 { KEY2, FIFOST_CLASS_CLASS2KEY | FIFOST_TYPE_KEY_KEK },
187 { OFIFO, FIFOST_TYPE_OUTFIFO_KEK},
188 { SKIP, FIFOST_TYPE_SKIP },
189 /*22*/ { METADATA, FIFOST_TYPE_METADATA},
190 { MSG_CKSUM, FIFOST_TYPE_MESSAGE_DATA2 }
191 };
192
193 /*
194 * Allowed FIFO_STORE output data types for each SEC Era.
195 * Values represent the number of entries from fifo_store_table[] that are
196 * supported.
197 */
198 static const unsigned int fifo_store_table_sz[] = {21, 21, 21, 21,
199 22, 22, 22, 23,
200 23, 23};
201
202 static inline int
rta_fifo_store(struct program * program,uint32_t src,uint32_t encrypt_flags,uint64_t dst,uint32_t length,uint32_t flags)203 rta_fifo_store(struct program *program, uint32_t src,
204 uint32_t encrypt_flags, uint64_t dst,
205 uint32_t length, uint32_t flags)
206 {
207 uint32_t opcode = 0;
208 uint32_t val = 0;
209 int ret = -EINVAL;
210 bool is_seq_cmd = false;
211 unsigned int start_pc = program->current_pc;
212
213 /* write command type field */
214 if (flags & SEQ) {
215 opcode = CMD_SEQ_FIFO_STORE;
216 is_seq_cmd = true;
217 } else {
218 opcode = CMD_FIFO_STORE;
219 }
220
221 /* Parameter checking */
222 if (is_seq_cmd) {
223 if ((flags & VLF) && ((length >> 16) || (flags & EXT))) {
224 pr_err("SEQ FIFO STORE: Invalid usage of VLF\n");
225 goto err;
226 }
227 if (dst) {
228 pr_err("SEQ FIFO STORE: Invalid command\n");
229 goto err;
230 }
231 if ((src == METADATA) && (flags & (CONT | EXT))) {
232 pr_err("SEQ FIFO STORE: Invalid flags\n");
233 goto err;
234 }
235 } else {
236 if (((src == RNGOFIFO) && ((dst) || (flags & EXT))) ||
237 (src == METADATA)) {
238 pr_err("FIFO STORE: Invalid destination\n");
239 goto err;
240 }
241 }
242
243 /* write output data type field */
244 ret = __rta_map_opcode(src, fifo_store_table,
245 fifo_store_table_sz[rta_sec_era], &val);
246 if (ret < 0) {
247 pr_err("FIFO STORE: Source type not supported. SEC Program Line: %d\n",
248 program->current_pc);
249 goto err;
250 }
251 opcode |= val;
252
253 if (encrypt_flags & TK)
254 opcode |= (0x1 << FIFOST_TYPE_SHIFT);
255 if (encrypt_flags & EKT) {
256 opcode |= (0x10 << FIFOST_TYPE_SHIFT);
257 opcode &= (uint32_t)~(0x20 << FIFOST_TYPE_SHIFT);
258 }
259
260 /* write flags fields */
261 if (flags & CONT)
262 opcode |= FIFOST_CONT;
263 if ((flags & VLF) && (is_seq_cmd))
264 opcode |= FIFOLDST_VLF;
265 if ((flags & SGF) && (!is_seq_cmd))
266 opcode |= FIFOLDST_SGF;
267 if (flags & CLASS1)
268 opcode |= FIFOST_CLASS_CLASS1KEY;
269 if (flags & CLASS2)
270 opcode |= FIFOST_CLASS_CLASS2KEY;
271 if (flags & BOTH)
272 opcode |= FIFOST_CLASS_BOTH;
273
274 /* Verify if extended length is required */
275 if ((length >> 16) || (flags & EXT))
276 opcode |= FIFOLDST_EXT;
277 else
278 opcode |= (uint16_t) length;
279
280 __rta_out32(program, opcode);
281 program->current_instruction++;
282
283 /* write pointer field */
284 if ((!is_seq_cmd) && (dst))
285 __rta_out64(program, program->ps, dst);
286
287 /* write extended length field */
288 if (opcode & FIFOLDST_EXT)
289 __rta_out32(program, length);
290
291 return (int)start_pc;
292
293 err:
294 program->first_error_pc = start_pc;
295 program->current_instruction++;
296 return ret;
297 }
298
299 #endif /* __RTA_FIFO_LOAD_STORE_CMD_H__ */
300