2 * fuc microcode for g98 sec engine
3 * Copyright (C) 2010 Marcin KoĆcielnicki
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 .section #g98_sec_data
27 ctx_query_address_high: .b32 0
28 ctx_query_address_low: .b32 0
29 ctx_query_counter: .b32 0
30 ctx_cond_address_high: .b32 0
31 ctx_cond_address_low: .b32 0
33 ctx_src_address_high: .b32 0
34 ctx_src_address_low: .b32 0
35 ctx_dst_address_high: .b32 0
36 ctx_dst_address_low: .b32 0
48 .b32 #ctx_query_address_high + 0x20000 ~0xff
49 .b32 #ctx_query_address_low + 0x20000 ~0xfffffff0
50 .b32 #ctx_query_counter + 0x20000 ~0xffffffff
51 .b32 #cmd_query_get + 0x00000 ~1
52 .b32 #ctx_cond_address_high + 0x20000 ~0xff
53 .b32 #ctx_cond_address_low + 0x20000 ~0xfffffff0
54 .b32 #cmd_cond_mode + 0x00000 ~7
55 .b32 #cmd_wrcache_flush + 0x00000 ~0
56 .equ #common_cmd_max 0x88
61 .b32 #ctx_key + 0x0 + 0x20000 ~0xffffffff
62 .b32 #ctx_key + 0x4 + 0x20000 ~0xffffffff
63 .b32 #ctx_key + 0x8 + 0x20000 ~0xffffffff
64 .b32 #ctx_key + 0xc + 0x20000 ~0xffffffff
65 .b32 #ctx_iv + 0x0 + 0x20000 ~0xffffffff
66 .b32 #ctx_iv + 0x4 + 0x20000 ~0xffffffff
67 .b32 #ctx_iv + 0x8 + 0x20000 ~0xffffffff
68 .b32 #ctx_iv + 0xc + 0x20000 ~0xffffffff
69 .b32 #ctx_src_address_high + 0x20000 ~0xff
70 .b32 #ctx_src_address_low + 0x20000 ~0xfffffff0
71 .b32 #ctx_dst_address_high + 0x20000 ~0xff
72 .b32 #ctx_dst_address_low + 0x20000 ~0xfffffff0
73 .b32 #sec_cmd_mode + 0x00000 ~0xf
74 .b32 #sec_cmd_length + 0x10000 ~0x0ffffff0
75 .equ #engine_cmd_max 0xce
79 .b16 #sec_copy_prep #sec_do_inout
80 .b16 #sec_store_prep #sec_do_out
81 .b16 #sec_ecb_e_prep #sec_do_inout
82 .b16 #sec_ecb_d_prep #sec_do_inout
83 .b16 #sec_cbc_e_prep #sec_do_inout
84 .b16 #sec_cbc_d_prep #sec_do_inout
85 .b16 #sec_pcbc_e_prep #sec_do_inout
86 .b16 #sec_pcbc_d_prep #sec_do_inout
87 .b16 #sec_cfb_e_prep #sec_do_inout
88 .b16 #sec_cfb_d_prep #sec_do_inout
89 .b16 #sec_ofb_prep #sec_do_inout
90 .b16 #sec_ctr_prep #sec_do_inout
91 .b16 #sec_cbc_mac_prep #sec_do_in
92 .b16 #sec_cmac_finish_complete_prep #sec_do_in
93 .b16 #sec_cmac_finish_partial_prep #sec_do_in
97 .section #g98_sec_code
99 // $r0 is always set to 0 in our code - this allows some space savings.
102 // set up the interrupt handler
106 // init stack pointer
109 // set interrupt dispatch - route timer, fifo, ctxswitch to i0, others to host
113 iowr I[$r2 + 0x300] $r1
115 // enable the interrupts
119 // enable fifo access and context switching
124 // enable i0 delivery
127 // sleep forver, waking only for interrupts.
135 // see which interrupts we got
136 iord $r1 I[$r0 + 0x200]
142 // context switch... prepare the regs for xfer
150 // read current channel
153 // if bit 30 set, it's active, so we have to unload it first.
158 // unload the current channel - save the context
161 // and clear bit 30, then write back
164 // tell PFIFO we unloaded
166 iowr I[$r3 + 0x200] $r4
171 // no channel loaded - perhaps we're requested to load one
172 iord $r4 I[$r3 + 0x100]
175 // if bit 30 of next channel not set, probably PFIFO is just
176 // killing a context. do a faux load, without the active bit.
179 // ok, do a real context load.
183 mov $r6 #dma_count - 1
185 ld b32 $r7 D[$r5 + $r6 * 4]
186 add b32 $r8 $r6 0x180
190 bra nc #ctxload_dma_loop
193 // tell PFIFO we're done
195 iowr I[$r3 + 0x200] $r5
202 // incoming fifo command.
204 iord $r2 I[$r3 + 0x100]
206 // extract the method
208 // shift the addr to proper position if we need to interrupt later
211 // mthd 0 and 0x100 [NAME, NOP]: ignore
216 mov $r5 #engine_cmd_dtable - 0xc0 * 8
217 mov $r6 #engine_cmd_max
220 mov $r5 #common_cmd_dtable - 0x80 * 8
221 mov $r6 #common_cmd_max
229 // mthd 0x140: PM_TRIGGER
237 // mthd 0x180...: DMA_*
238 cmpu b32 $r4 0x60+#dma_count
241 add b32 $r5 ((#ctx_dma - 0x60 * 4) & 0xffff)
244 add b32 $r4 0x180 - 0x60
254 ld b32 $r5 D[$r4 + 4]
257 bra ne #invalid_bitfield
259 ld b16 $r6 D[$r4 + 2]
262 ld b32 $r7 D[$r0 + #ctx_cond_off]
267 bra $p1 #dispatch_error
281 iowr I[$r4 + 0x100] $r3
286 iord $r4 I[$r0 + 0x200]
292 // remove the command from FIFO
298 // ack the processed interrupts
300 iowr I[$r0 + 0x100] $r1
304 // if bit 0 of param set, trigger interrupt afterwards.
308 // read PTIMER, beware of races...
311 iord $r6 I[$r4 + 0x100]
313 iord $r7 I[$r4 + 0x100]
317 // prepare the query structure
318 ld b32 $r4 D[$r0 + #ctx_query_counter]
319 st b32 D[$r0 + #swap + 0x0] $r4
320 st b32 D[$r0 + #swap + 0x4] $r0
321 st b32 D[$r0 + #swap + 0x8] $r5
322 st b32 D[$r0 + #swap + 0xc] $r6
324 // will use target 0, DMA_QUERY.
327 ld b32 $r4 D[$r0 + #ctx_query_address_high]
331 ld b32 $r4 D[$r0 + #ctx_query_address_low]
340 // if >= 5, INVALID_ENUM
346 // otherwise, no error.
349 // if < 2, no QUERY object is involved
351 bra nc #cmd_cond_mode_queryful
354 st b32 D[$r0 + #ctx_cond_off] $r3
358 cmd_cond_mode_queryful:
359 // ok, will need to pull a QUERY object, prepare offsets
360 ld b32 $r4 D[$r0 + #ctx_cond_address_high]
361 ld b32 $r5 D[$r0 + #ctx_cond_address_low]
369 // pull the first one
374 // if == 2, only a single QUERY is involved...
376 bra ne #cmd_cond_mode_double
379 ld b32 $r4 D[$r0 + #swap + 4]
382 st b32 D[$r0 + #ctx_cond_off] $r4
385 // ok, we'll need to pull second one too
386 cmd_cond_mode_double:
393 ld b32 $r5 D[$r0 + #swap + 0x00]
394 ld b32 $r6 D[$r0 + #swap + 0x10]
399 ld b32 $r5 D[$r0 + #swap + 0x04]
400 ld b32 $r6 D[$r0 + #swap + 0x14]
405 // and negate or not, depending on mode
409 st b32 D[$r0 + #ctx_cond_off] $r4
421 // if >= 0xf, INVALID_ENUM
425 bra nc #sec_cmd_mode_return
428 st b32 D[$r0 + #ctx_mode] $r3
434 // nop if length == 0
436 bra e #sec_cmd_mode_return
449 // prepare the targets
453 // prepare src address
454 ld b32 $r4 D[$r0 + #ctx_src_address_high]
455 ld b32 $r5 D[$r0 + #ctx_src_address_low]
461 // prepare dst address
462 ld b32 $r6 D[$r0 + #ctx_dst_address_high]
463 ld b32 $r7 D[$r0 + #ctx_dst_address_low]
469 // find the proper prep & do functions
470 ld b32 $r8 D[$r0 + #ctx_mode]
474 ld b16 $r9 D[$r8 + #sec_dtable]
478 ld b16 $r9 D[$r8 + #sec_dtable + 2]
486 // update src address
491 st b32 D[$r0 + #ctx_src_address_high] $r8
492 st b32 D[$r0 + #ctx_src_address_low] $r9
494 // update dst address
499 st b32 D[$r0 + #ctx_dst_address_high] $r8
500 st b32 D[$r0 + #ctx_dst_address_low] $r9
615 sec_cmac_finish_complete_prep:
626 sec_cmac_finish_partial_prep:
653 bra ne #sec_do_in_loop
672 bra ne #sec_do_out_loop
695 bra ne #sec_do_inout_loop