699 lines · plain
1/*2 * fuc microcode for g98 sec engine3 * Copyright (C) 2010 Marcin Kościelnicki4 *5 * This program is free software; you can redistribute it and/or modify6 * it under the terms of the GNU General Public License as published by7 * the Free Software Foundation; either version 2 of the License, or8 * (at your option) any later version.9 *10 * This program is distributed in the hope that it will be useful,11 * but WITHOUT ANY WARRANTY; without even the implied warranty of12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13 * GNU General Public License for more details.14 *15 * You should have received a copy of the GNU General Public License16 * along with this program; if not, write to the Free Software17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 */19 20.section #g98_sec_data21 22ctx_dma:23ctx_dma_query: .b32 024ctx_dma_src: .b32 025ctx_dma_dst: .b32 026.equ #dma_count 327ctx_query_address_high: .b32 028ctx_query_address_low: .b32 029ctx_query_counter: .b32 030ctx_cond_address_high: .b32 031ctx_cond_address_low: .b32 032ctx_cond_off: .b32 033ctx_src_address_high: .b32 034ctx_src_address_low: .b32 035ctx_dst_address_high: .b32 036ctx_dst_address_low: .b32 037ctx_mode: .b32 038.align 1639ctx_key: .skip 1640ctx_iv: .skip 1641 42.align 0x8043swap:44.skip 3245 46.align 847common_cmd_dtable:48.b32 #ctx_query_address_high + 0x20000 ~0xff49.b32 #ctx_query_address_low + 0x20000 ~0xfffffff050.b32 #ctx_query_counter + 0x20000 ~0xffffffff51.b32 #cmd_query_get + 0x00000 ~152.b32 #ctx_cond_address_high + 0x20000 ~0xff53.b32 #ctx_cond_address_low + 0x20000 ~0xfffffff054.b32 #cmd_cond_mode + 0x00000 ~755.b32 #cmd_wrcache_flush + 0x00000 ~056.equ #common_cmd_max 0x8857 58 59.align 860engine_cmd_dtable:61.b32 #ctx_key + 0x0 + 0x20000 ~0xffffffff62.b32 #ctx_key + 0x4 + 0x20000 ~0xffffffff63.b32 #ctx_key + 0x8 + 0x20000 ~0xffffffff64.b32 #ctx_key + 0xc + 0x20000 ~0xffffffff65.b32 #ctx_iv + 0x0 + 0x20000 ~0xffffffff66.b32 #ctx_iv + 0x4 + 0x20000 ~0xffffffff67.b32 #ctx_iv + 0x8 + 0x20000 ~0xffffffff68.b32 #ctx_iv + 0xc + 0x20000 ~0xffffffff69.b32 #ctx_src_address_high + 0x20000 ~0xff70.b32 #ctx_src_address_low + 0x20000 ~0xfffffff071.b32 #ctx_dst_address_high + 0x20000 ~0xff72.b32 #ctx_dst_address_low + 0x20000 ~0xfffffff073.b32 #sec_cmd_mode + 0x00000 ~0xf74.b32 #sec_cmd_length + 0x10000 ~0x0ffffff075.equ #engine_cmd_max 0xce76 77.align 478sec_dtable:79.b16 #sec_copy_prep #sec_do_inout80.b16 #sec_store_prep #sec_do_out81.b16 #sec_ecb_e_prep #sec_do_inout82.b16 #sec_ecb_d_prep #sec_do_inout83.b16 #sec_cbc_e_prep #sec_do_inout84.b16 #sec_cbc_d_prep #sec_do_inout85.b16 #sec_pcbc_e_prep #sec_do_inout86.b16 #sec_pcbc_d_prep #sec_do_inout87.b16 #sec_cfb_e_prep #sec_do_inout88.b16 #sec_cfb_d_prep #sec_do_inout89.b16 #sec_ofb_prep #sec_do_inout90.b16 #sec_ctr_prep #sec_do_inout91.b16 #sec_cbc_mac_prep #sec_do_in92.b16 #sec_cmac_finish_complete_prep #sec_do_in93.b16 #sec_cmac_finish_partial_prep #sec_do_in94 95.align 0x10096 97.section #g98_sec_code98 99 // $r0 is always set to 0 in our code - this allows some space savings.100 clear b32 $r0101 102 // set up the interrupt handler103 mov $r1 #ih104 mov $iv0 $r1105 106 // init stack pointer107 mov $sp $r0108 109 // set interrupt dispatch - route timer, fifo, ctxswitch to i0, others to host110 movw $r1 0xfff0111 sethi $r1 0112 mov $r2 0x400113 iowr I[$r2 + 0x300] $r1114 115 // enable the interrupts116 or $r1 0xc117 iowr I[$r2] $r1118 119 // enable fifo access and context switching120 mov $r1 3121 mov $r2 0x1200122 iowr I[$r2] $r1123 124 // enable i0 delivery125 bset $flags ie0126 127 // sleep forver, waking only for interrupts.128 bset $flags $p0129 spin:130 sleep $p0131 bra #spin132 133// i0 handler134ih:135 // see which interrupts we got136 iord $r1 I[$r0 + 0x200]137 138 and $r2 $r1 0x8139 cmpu b32 $r2 0140 bra e #noctx141 142 // context switch... prepare the regs for xfer143 mov $r2 0x7700144 mov $xtargets $r2145 mov $xdbase $r0146 // 128-byte context.147 mov $r2 0148 sethi $r2 0x50000149 150 // read current channel151 mov $r3 0x1400152 iord $r4 I[$r3]153 // if bit 30 set, it's active, so we have to unload it first.154 shl b32 $r5 $r4 1155 cmps b32 $r5 0156 bra nc #ctxload157 158 // unload the current channel - save the context159 xdst $r0 $r2160 xdwait161 // and clear bit 30, then write back162 bclr $r4 0x1e163 iowr I[$r3] $r4164 // tell PFIFO we unloaded165 mov $r4 1166 iowr I[$r3 + 0x200] $r4167 168 bra #noctx169 170 ctxload:171 // no channel loaded - perhaps we're requested to load one172 iord $r4 I[$r3 + 0x100]173 shl b32 $r15 $r4 1174 cmps b32 $r15 0175 // if bit 30 of next channel not set, probably PFIFO is just176 // killing a context. do a faux load, without the active bit.177 bra nc #dummyload178 179 // ok, do a real context load.180 xdld $r0 $r2181 xdwait182 mov $r5 #ctx_dma183 mov $r6 #dma_count - 1184 ctxload_dma_loop:185 ld b32 $r7 D[$r5 + $r6 * 4]186 add b32 $r8 $r6 0x180187 shl b32 $r8 8188 iowr I[$r8] $r7189 sub b32 $r6 1190 bra nc #ctxload_dma_loop191 192 dummyload:193 // tell PFIFO we're done194 mov $r5 2195 iowr I[$r3 + 0x200] $r5196 197 noctx:198 and $r2 $r1 0x4199 cmpu b32 $r2 0200 bra e #nocmd201 202 // incoming fifo command.203 mov $r3 0x1900204 iord $r2 I[$r3 + 0x100]205 iord $r3 I[$r3]206 // extract the method207 and $r4 $r2 0x7ff208 // shift the addr to proper position if we need to interrupt later209 shl b32 $r2 0x10210 211 // mthd 0 and 0x100 [NAME, NOP]: ignore212 and $r5 $r4 0x7bf213 cmpu b32 $r5 0214 bra e #cmddone215 216 mov $r5 #engine_cmd_dtable - 0xc0 * 8217 mov $r6 #engine_cmd_max218 cmpu b32 $r4 0xc0219 bra nc #dtable_cmd220 mov $r5 #common_cmd_dtable - 0x80 * 8221 mov $r6 #common_cmd_max222 cmpu b32 $r4 0x80223 bra nc #dtable_cmd224 cmpu b32 $r4 0x60225 bra nc #dma_cmd226 cmpu b32 $r4 0x50227 bra ne #illegal_mthd228 229 // mthd 0x140: PM_TRIGGER230 mov $r2 0x2200231 clear b32 $r3232 sethi $r3 0x20000233 iowr I[$r2] $r3234 bra #cmddone235 236 dma_cmd:237 // mthd 0x180...: DMA_*238 cmpu b32 $r4 0x60+#dma_count239 bra nc #illegal_mthd240 shl b32 $r5 $r4 2241 add b32 $r5 ((#ctx_dma - 0x60 * 4) & 0xffff)242 bset $r3 0x1e243 st b32 D[$r5] $r3244 add b32 $r4 0x180 - 0x60245 shl b32 $r4 8246 iowr I[$r4] $r3247 bra #cmddone248 249 dtable_cmd:250 cmpu b32 $r4 $r6251 bra nc #illegal_mthd252 shl b32 $r4 3253 add b32 $r4 $r5254 ld b32 $r5 D[$r4 + 4]255 and $r5 $r3256 cmpu b32 $r5 0257 bra ne #invalid_bitfield258 ld b16 $r5 D[$r4]259 ld b16 $r6 D[$r4 + 2]260 cmpu b32 $r6 2261 bra e #cmd_setctx262 ld b32 $r7 D[$r0 + #ctx_cond_off]263 and $r6 $r7264 cmpu b32 $r6 1265 bra e #cmddone266 call $r5267 bra $p1 #dispatch_error268 bra #cmddone269 270 cmd_setctx:271 st b32 D[$r5] $r3272 bra #cmddone273 274 275 invalid_bitfield:276 or $r2 1277 dispatch_error:278 illegal_mthd:279 mov $r4 0x1000280 iowr I[$r4] $r2281 iowr I[$r4 + 0x100] $r3282 mov $r4 0x40283 iowr I[$r0] $r4284 285 im_loop:286 iord $r4 I[$r0 + 0x200]287 and $r4 0x40288 cmpu b32 $r4 0289 bra ne #im_loop290 291 cmddone:292 // remove the command from FIFO293 mov $r3 0x1d00294 mov $r4 1295 iowr I[$r3] $r4296 297 nocmd:298 // ack the processed interrupts299 and $r1 $r1 0xc300 iowr I[$r0 + 0x100] $r1301iret302 303cmd_query_get:304 // if bit 0 of param set, trigger interrupt afterwards.305 setp $p1 $r3306 or $r2 3307 308 // read PTIMER, beware of races...309 mov $r4 0xb00310 ptimer_retry:311 iord $r6 I[$r4 + 0x100]312 iord $r5 I[$r4]313 iord $r7 I[$r4 + 0x100]314 cmpu b32 $r6 $r7315 bra ne #ptimer_retry316 317 // prepare the query structure318 ld b32 $r4 D[$r0 + #ctx_query_counter]319 st b32 D[$r0 + #swap + 0x0] $r4320 st b32 D[$r0 + #swap + 0x4] $r0321 st b32 D[$r0 + #swap + 0x8] $r5322 st b32 D[$r0 + #swap + 0xc] $r6323 324 // will use target 0, DMA_QUERY.325 mov $xtargets $r0326 327 ld b32 $r4 D[$r0 + #ctx_query_address_high]328 shl b32 $r4 0x18329 mov $xdbase $r4330 331 ld b32 $r4 D[$r0 + #ctx_query_address_low]332 mov $r5 #swap333 sethi $r5 0x20000334 xdst $r4 $r5335 xdwait336 337 ret338 339cmd_cond_mode:340 // if >= 5, INVALID_ENUM341 bset $flags $p1342 or $r2 2343 cmpu b32 $r3 5344 bra nc #return345 346 // otherwise, no error.347 bclr $flags $p1348 349 // if < 2, no QUERY object is involved350 cmpu b32 $r3 2351 bra nc #cmd_cond_mode_queryful352 353 xor $r3 1354 st b32 D[$r0 + #ctx_cond_off] $r3355 return:356 ret357 358 cmd_cond_mode_queryful:359 // ok, will need to pull a QUERY object, prepare offsets360 ld b32 $r4 D[$r0 + #ctx_cond_address_high]361 ld b32 $r5 D[$r0 + #ctx_cond_address_low]362 and $r6 $r5 0xff363 shr b32 $r5 8364 shl b32 $r4 0x18365 or $r4 $r5366 mov $xdbase $r4367 mov $xtargets $r0368 369 // pull the first one370 mov $r5 #swap371 sethi $r5 0x20000372 xdld $r6 $r5373 374 // if == 2, only a single QUERY is involved...375 cmpu b32 $r3 2376 bra ne #cmd_cond_mode_double377 378 xdwait379 ld b32 $r4 D[$r0 + #swap + 4]380 cmpu b32 $r4 0381 xbit $r4 $flags z382 st b32 D[$r0 + #ctx_cond_off] $r4383 ret384 385 // ok, we'll need to pull second one too386 cmd_cond_mode_double:387 add b32 $r6 0x10388 add b32 $r5 0x10389 xdld $r6 $r5390 xdwait391 392 // compare COUNTERs393 ld b32 $r5 D[$r0 + #swap + 0x00]394 ld b32 $r6 D[$r0 + #swap + 0x10]395 cmpu b32 $r5 $r6396 xbit $r4 $flags z397 398 // compare RESen399 ld b32 $r5 D[$r0 + #swap + 0x04]400 ld b32 $r6 D[$r0 + #swap + 0x14]401 cmpu b32 $r5 $r6402 xbit $r5 $flags z403 and $r4 $r5404 405 // and negate or not, depending on mode406 cmpu b32 $r3 3407 xbit $r5 $flags z408 xor $r4 $r5409 st b32 D[$r0 + #ctx_cond_off] $r4410 ret411 412cmd_wrcache_flush:413 bclr $flags $p1414 mov $r2 0x2200415 clear b32 $r3416 sethi $r3 0x10000417 iowr I[$r2] $r3418 ret419 420sec_cmd_mode:421 // if >= 0xf, INVALID_ENUM422 bset $flags $p1423 or $r2 2424 cmpu b32 $r3 0xf425 bra nc #sec_cmd_mode_return426 427 bclr $flags $p1428 st b32 D[$r0 + #ctx_mode] $r3429 430 sec_cmd_mode_return:431 ret432 433sec_cmd_length:434 // nop if length == 0435 cmpu b32 $r3 0436 bra e #sec_cmd_mode_return437 438 // init key, IV439 cxset 3440 mov $r4 #ctx_key441 sethi $r4 0x70000442 xdst $r0 $r4443 mov $r4 #ctx_iv444 sethi $r4 0x60000445 xdst $r0 $r4446 xdwait447 ckeyreg $c7448 449 // prepare the targets450 mov $r4 0x2100451 mov $xtargets $r4452 453 // prepare src address454 ld b32 $r4 D[$r0 + #ctx_src_address_high]455 ld b32 $r5 D[$r0 + #ctx_src_address_low]456 shr b32 $r8 $r5 8457 shl b32 $r4 0x18458 or $r4 $r8459 and $r5 $r5 0xff460 461 // prepare dst address462 ld b32 $r6 D[$r0 + #ctx_dst_address_high]463 ld b32 $r7 D[$r0 + #ctx_dst_address_low]464 shr b32 $r8 $r7 8465 shl b32 $r6 0x18466 or $r6 $r8467 and $r7 $r7 0xff468 469 // find the proper prep & do functions470 ld b32 $r8 D[$r0 + #ctx_mode]471 shl b32 $r8 2472 473 // run prep474 ld b16 $r9 D[$r8 + #sec_dtable]475 call $r9476 477 // do it478 ld b16 $r9 D[$r8 + #sec_dtable + 2]479 call $r9480 cxset 1481 xdwait482 cxset 0x61483 xdwait484 xdwait485 486 // update src address487 shr b32 $r8 $r4 0x18488 shl b32 $r9 $r4 8489 add b32 $r9 $r5490 adc b32 $r8 0491 st b32 D[$r0 + #ctx_src_address_high] $r8492 st b32 D[$r0 + #ctx_src_address_low] $r9493 494 // update dst address495 shr b32 $r8 $r6 0x18496 shl b32 $r9 $r6 8497 add b32 $r9 $r7498 adc b32 $r8 0499 st b32 D[$r0 + #ctx_dst_address_high] $r8500 st b32 D[$r0 + #ctx_dst_address_low] $r9501 502 // pull updated IV503 cxset 2504 mov $r4 #ctx_iv505 sethi $r4 0x60000506 xdld $r0 $r4507 xdwait508 509 ret510 511 512sec_copy_prep:513 cs0begin 2514 cxsin $c0515 cxsout $c0516 ret517 518sec_store_prep:519 cs0begin 1520 cxsout $c6521 ret522 523sec_ecb_e_prep:524 cs0begin 3525 cxsin $c0526 cenc $c0 $c0527 cxsout $c0528 ret529 530sec_ecb_d_prep:531 ckexp $c7 $c7532 cs0begin 3533 cxsin $c0534 cdec $c0 $c0535 cxsout $c0536 ret537 538sec_cbc_e_prep:539 cs0begin 4540 cxsin $c0541 cxor $c6 $c0542 cenc $c6 $c6543 cxsout $c6544 ret545 546sec_cbc_d_prep:547 ckexp $c7 $c7548 cs0begin 5549 cmov $c2 $c6550 cxsin $c6551 cdec $c0 $c6552 cxor $c0 $c2553 cxsout $c0554 ret555 556sec_pcbc_e_prep:557 cs0begin 5558 cxsin $c0559 cxor $c6 $c0560 cenc $c6 $c6561 cxsout $c6562 cxor $c6 $c0563 ret564 565sec_pcbc_d_prep:566 ckexp $c7 $c7567 cs0begin 5568 cxsin $c0569 cdec $c1 $c0570 cxor $c6 $c1571 cxsout $c6572 cxor $c6 $c0573 ret574 575sec_cfb_e_prep:576 cs0begin 4577 cenc $c6 $c6578 cxsin $c0579 cxor $c6 $c0580 cxsout $c6581 ret582 583sec_cfb_d_prep:584 cs0begin 4585 cenc $c0 $c6586 cxsin $c6587 cxor $c0 $c6588 cxsout $c0589 ret590 591sec_ofb_prep:592 cs0begin 4593 cenc $c6 $c6594 cxsin $c0595 cxor $c0 $c6596 cxsout $c0597 ret598 599sec_ctr_prep:600 cs0begin 5601 cenc $c1 $c6602 cadd $c6 1603 cxsin $c0604 cxor $c0 $c1605 cxsout $c0606 ret607 608sec_cbc_mac_prep:609 cs0begin 3610 cxsin $c0611 cxor $c6 $c0612 cenc $c6 $c6613 ret614 615sec_cmac_finish_complete_prep:616 cs0begin 7617 cxsin $c0618 cxor $c6 $c0619 cxor $c0 $c0620 cenc $c0 $c0621 cprecmac $c0 $c0622 cxor $c6 $c0623 cenc $c6 $c6624 ret625 626sec_cmac_finish_partial_prep:627 cs0begin 8628 cxsin $c0629 cxor $c6 $c0630 cxor $c0 $c0631 cenc $c0 $c0632 cprecmac $c0 $c0633 cprecmac $c0 $c0634 cxor $c6 $c0635 cenc $c6 $c6636 ret637 638// TODO639sec_do_in:640 add b32 $r3 $r5641 mov $xdbase $r4642 mov $r9 #swap643 sethi $r9 0x20000644 sec_do_in_loop:645 xdld $r5 $r9646 xdwait647 cxset 0x22648 xdst $r0 $r9649 cs0exec 1650 xdwait651 add b32 $r5 0x10652 cmpu b32 $r5 $r3653 bra ne #sec_do_in_loop654 cxset 1655 xdwait656 ret657 658sec_do_out:659 add b32 $r3 $r7660 mov $xdbase $r6661 mov $r9 #swap662 sethi $r9 0x20000663 sec_do_out_loop:664 cs0exec 1665 cxset 0x61666 xdld $r7 $r9667 xdst $r7 $r9668 cxset 1669 xdwait670 add b32 $r7 0x10671 cmpu b32 $r7 $r3672 bra ne #sec_do_out_loop673 ret674 675sec_do_inout:676 add b32 $r3 $r5677 mov $r9 #swap678 sethi $r9 0x20000679 sec_do_inout_loop:680 mov $xdbase $r4681 xdld $r5 $r9682 xdwait683 cxset 0x21684 xdst $r0 $r9685 cs0exec 1686 cxset 0x61687 mov $xdbase $r6688 xdld $r7 $r9689 xdst $r7 $r9690 cxset 1691 xdwait692 add b32 $r5 0x10693 add b32 $r7 0x10694 cmpu b32 $r5 $r3695 bra ne #sec_do_inout_loop696 ret697 698.align 0x100699