- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

# drivers/aes/aes.c

Go to the documentation of this file.

    00001
    00047 #include <assert.h>
    00048 #include <debug.h>
    00049 #include <malloc.h>
    00050 #include <status-codes.h>
    00051 #include <string.h>
    00052 #include <interrupt.h>
    00053 #include <chip/memory-map.h>
    00054 #include <aes.h>
    00055
    00056 #include "aes_regs.h"
    00057
    00068 void aes_init(struct aes_module *module, uint32_t mode)
    00069 {
    00070         assert(module);
    00071
    00072         module->port = (void *)AES_BASE;
    00073         module->mode = mode | AES_MR_START_MODE_DMA;
    00074
    00075         aes_write_reg(module->port, CR, AES_CR_SWRST);
    00076         aes_write_reg(module->port, MR, module->mode);
    00077
    00078         module->dma_rx_channel = dmac_aes_alloc_rx_channel();
    00079         module->dma_tx_channel = dmac_aes_alloc_tx_channel();
    00080
    00081         module->counter = 0;
    00082 }
    00083
    00092 void aes_free(struct aes_module *module)
    00093 {
    00094         assert(module);
    00095
    00096         module->port = NULL;
    00097         dmac_aes_free_channel(module->dma_rx_channel);
    00098         dmac_aes_free_channel(module->dma_tx_channel);
    00099 }
    00100
    00110 void aes_set_cipher(struct aes_module *module, uint32_t mode)
    00111 {
    00112         assert(module);
    00113
    00114         module->mode = (module->mode & ~AES_MR_CIPHER_MASK) |
    00115                         (mode & AES_MR_CIPHER_MASK);
    00116
    00117         aes_write_reg(module->port, CR, AES_CR_SWRST);
    00118         aes_write_reg(module->port, MR, module->mode);
    00119 }
    00120
    00129 uint32_t aes_get_cipher(struct aes_module *module)
    00130 {
    00131         assert(module);
    00132
    00133         return (module->mode & AES_MR_CIPHER_MASK);
    00134 }
    00135
    00145 void aes_load_init_vector(struct aes_module *module, const uint32_t *vector)
    00146 {
    00147         int i;
    00148
    00149         assert(module);
    00150         assert(vector);
    00151
    00152         for (i = 0; i < 4; i++)
    00153                 aes_write_init_reg(module->port, i, *vector++);
    00154 }
    00155
    00167 void aes_load_key(struct aes_module *module, const uint32_t *key)
    00168 {
    00169         int i;
    00170         int key_length = 0;
    00171
    00172         assert(module);
    00173         assert(key);
    00174
    00175         switch (module->mode & AES_KEYSIZE_MASK) {
    00176         case AES_KEYSIZE_128:
    00177                 key_length = 4;
    00178                 break;
    00179         case AES_KEYSIZE_192:
    00180                 key_length = 6;
    00181                 break;
    00182         case AES_KEYSIZE_256:
    00183                 key_length = 8;
    00184                 break;
    00185         default:
    00186                 unhandled_case(module->mode);
    00187         }
    00188
    00189         for (i = 0; i < key_length; i++)
    00190                 aes_write_key_reg(module->port, i, *key++);
    00191 }
    00192
    00201 void aes_free_duplicate_buffers(struct slist *buf_list)
    00202 {
    00203         struct buffer *buf;
    00204
    00205         assert(buf_list);
    00206
    00207         while (!slist_is_empty(buf_list)) {
    00208                 buf = slist_pop_head(buf_list, struct buffer, node);
    00209                 buffer_free(buf);
    00210         }
    00211 }
    00212
    00228 int aes_duplicate_buffer_refs(struct slist *copy, struct slist *original)
    00229 {
    00230         struct buffer *buf;
    00231         struct buffer *temp;
    00232
    00233         assert(copy);
    00234         assert(original);
    00235
    00236         slist_for_each(original, buf, node) {
    00237                 temp = buffer_alloc();
    00238                 if (unlikely(!temp))
    00239                         goto ret_error;
    00240                 temp->addr.ptr = buf->addr.ptr;
    00241                 temp->addr.phys = buf->addr.phys;
    00242                 temp->len = buf->len;
    00243                 slist_insert_tail(copy, &temp->node);
    00244         }
    00245         return 0;
    00246
    00247 ret_error:
    00248         aes_free_duplicate_buffers(copy);
    00249         return -1;
    00250 }
    00251
    00252 static void aes_dma_tx_done(struct dmac_channel *chan,
    00253                 struct dmac_request *req)
    00254 {
    00255         struct aes_request *areq = req->context;
    00256
    00257         aes_free_duplicate_buffers(&req->buf_list);
    00258         free(req);
    00259
    00260         if (++areq->done_counter >= 2 && areq->req_done)
    00261                 areq->req_done(areq, &areq->rx_buf_list, areq->context);
    00262 }
    00263
    00264 static void aes_dma_rx_done(struct dmac_channel *chan,
    00265                 struct dmac_request *req)
    00266 {
    00267         struct aes_request *areq = req->context;
    00268         unsigned int iflags;
    00269
    00270         assert(req);
    00271         assert(areq);
    00272
    00273         iflags = cpu_irq_save();
    00274         if (!slist_is_empty(&req->buf_list))
    00275                 slist_move_to_tail(&areq->rx_buf_list, &req->buf_list);
    00276         cpu_irq_restore(iflags);
    00277
    00278         free(req);
    00279
    00280         if (++areq->done_counter >= 2 && areq->req_done)
    00281                 areq->req_done(areq, &areq->rx_buf_list, areq->context);
    00282 }
    00283
    00284 static void aes_dma_req_init(struct dmac_request *req,
    00285                 struct aes_request *areq, enum dma_direction dir)
    00286 {
    00287         memset(req, 0, sizeof(struct dmac_request));
    00288         dmac_req_init(req);
    00289         req->direction = dir;
    00290
    00291         switch (dir) {
    00292         case DMA_TO_DEVICE:
    00293                 req->req_done = aes_dma_tx_done;
    00294                 break;
    00295
    00296         case DMA_FROM_DEVICE:
    00297                 req->req_done = aes_dma_rx_done;
    00298                 break;
    00299
    00300         default:
    00301                 unhandled_case(dir);
    00302         }
    00303
    00304         req->reg_width = DMAC_REG_WIDTH_32BIT;
    00305         req->burst_length = DMAC_BURST_LENGTH_4;
    00306         req->context = areq;
    00307 }
    00308
    00320 void aes_submit_request(struct aes_request *req)
    00321 {
    00322         struct dmac_request *tx_req = &req->tx_req;
    00323         struct dmac_request *rx_req = &req->rx_req;
    00324
    00325         assert(req);
    00326
    00327         aes_dma_req_init(tx_req, req, DMA_TO_DEVICE);
    00328         aes_dma_req_init(rx_req, req, DMA_FROM_DEVICE);
    00329         req->done_counter = 0;
    00330
    00331         if (!slist_is_empty(&req->tx_buf_list)) {
    00332                 /* Move buffers to DMA requests. */
    00333                 slist_move_to_tail(&tx_req->buf_list, &req->tx_buf_list);
    00334                 slist_move_to_tail(&rx_req->buf_list, &req->rx_buf_list);
    00335
    00336                 /* Submit DMA requests to the DMA controller. */
    00337                 dmac_chan_submit_request(req->module->dma_rx_channel, rx_req);
    00338                 dmac_chan_submit_request(req->module->dma_tx_channel, tx_req);
    00339         } else {
    00340                 /* Empty request; skip actual encryption, clean up and
    00341                  * run callback. */
    00342                 aes_dma_tx_done(req->module->dma_tx_channel, tx_req);
    00343                 aes_dma_rx_done(req->module->dma_rx_channel, rx_req);
    00344         }
    00345 }
    00346
    00356 struct aes_request *aes_alloc_request(struct aes_module *module)
    00357 {
    00358         struct aes_request *req;
    00359
    00360         assert(module);
    00361         /* Try to catch AES usage without running init first. */
    00362         assert(module->port);
    00363
    00364         req = malloc(sizeof(struct aes_request));
    00365         assert(req);
    00366         req->module = module;
    00367
    00368         return req;
    00369 }
    00370
    00378 void aes_free_request(struct aes_request *req)
    00379 {
    00380         assert(slist_is_empty(&req->tx_buf_list));
    00381         assert(slist_is_empty(&req->rx_buf_list));
    00382
    00383         free(req);
    00384 }
    00385
    00399 void aes_prepare_request(struct aes_request *req, struct slist *buf_list)
    00400 {
    00401         slist_init(&req->tx_buf_list);
    00402         slist_init(&req->rx_buf_list);
    00403
    00404         if (!slist_is_empty(buf_list)) {
    00405                 assert(!aes_duplicate_buffer_refs(
    00406                                 &req->rx_buf_list, buf_list));
    00407                 slist_move_to_tail(&req->tx_buf_list, buf_list);
    00408         }
    00409 }