📄 z90main.c
字号:
} *offs = i+1; return found;}static inline intscan_string(unsigned char *bf, unsigned int len, unsigned int *offs, unsigned int *p_eof, unsigned char *s){ unsigned int temp_len, temp_offs, found, eof; temp_len = temp_offs = found = eof = 0; while (!eof && !found) { found = scan_char(bf+temp_len, len-temp_len, &temp_offs, &eof, *s); temp_len += temp_offs; if (eof) { found = 0; break; } if (found) { if (len >= temp_offs+strlen(s)) { found = !strncmp(bf+temp_len-1, s, strlen(s)); if (found) { *offs = temp_len+strlen(s)-1; break; } } else { found = 0; *p_eof = 1; break; } } } return found;}static intz90crypt_status_write(struct file *file, const char __user *buffer, unsigned long count, void *data){ int i, j, len, offs, found, eof; unsigned char *lbuf; unsigned int local_count;#define LBUFSIZE 600 lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); if (!lbuf) { PRINTK("kmalloc failed!\n"); return 0; } if (count <= 0) return 0; local_count = UMIN((unsigned int)count, LBUFSIZE-1); if (copy_from_user(lbuf, buffer, local_count) != 0) { kfree(lbuf); return -EFAULT; } lbuf[local_count-1] = '\0'; len = 0; eof = 0; found = 0; while (!eof) { found = scan_string(lbuf+len, local_count-len, &offs, &eof, "Online devices"); len += offs; if (found == 1) break; } if (eof) { kfree(lbuf); return count; } if (found) found = scan_char(lbuf+len, local_count-len, &offs, &eof, '\n'); if (!found || eof) { kfree(lbuf); return count; } len += offs; j = 0; for (i = 0; i < 80; i++) { switch (*(lbuf+len+i)) { case '\t': case ' ': break; case '\n': default: eof = 1; break; case '0': case '1': case '2': case '3': j++; break; case 'd': case 'D': disable_card(j); j++; break; case 'e': case 'E': enable_card(j); j++; break; } if (eof) break; } kfree(lbuf); return count;}/** * Functions that run under a timer, with no process id * * The task functions: * z90crypt_reader_task * helper_send_work * helper_handle_work_element * helper_receive_rc * z90crypt_config_task * z90crypt_cleanup_task * * Helper functions: * z90crypt_schedule_reader_timer * z90crypt_schedule_reader_task * z90crypt_schedule_config_task * z90crypt_schedule_cleanup_task */static inline intreceive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, unsigned char *buff, unsigned char __user **dest_p_p){ int dv, rv; struct device *dev_ptr; struct caller *caller_p; struct ica_rsa_modexpo *icaMsg_p; struct list_head *ptr, *tptr; memcpy(psmid, NULL_psmid, sizeof(NULL_psmid)); if (z90crypt.terminating) return REC_FATAL_ERROR; caller_p = 0; dev_ptr = z90crypt.device_p[index]; rv = 0; do { PDEBUG("Dequeue called for device %d\n", index); if (!dev_ptr || dev_ptr->disabled) { rv = REC_NO_RESPONSE; break; } if (dev_ptr->dev_self_x != index) { PRINTK("Corrupt dev ptr in receive_from_AP\n"); z90crypt.terminating = 1; rv = REC_FATAL_ERROR; break; } if (!dev_ptr->dev_resp_l || !dev_ptr->dev_resp_p) { dv = DEV_REC_EXCEPTION; PRINTK("dev_resp_l = %d, dev_resp_p = %p\n", dev_ptr->dev_resp_l, dev_ptr->dev_resp_p); } else { dv = receive_from_AP(index, z90crypt.cdx, dev_ptr->dev_resp_l, dev_ptr->dev_resp_p, psmid); } switch (dv) { case DEV_REC_EXCEPTION: rv = REC_FATAL_ERROR; z90crypt.terminating = 1; PRINTKC("Exception in receive from device %d\n", index); break; case DEV_ONLINE: rv = 0; break; case DEV_EMPTY: rv = REC_EMPTY; break; case DEV_NO_WORK: rv = REC_NO_WORK; break; case DEV_BAD_MESSAGE: case DEV_GONE: case REC_HARDWAR_ERR: default: rv = REC_NO_RESPONSE; break; } if (rv) break; if (dev_ptr->dev_caller_count <= 0) { rv = REC_USER_GONE; break; } list_for_each_safe(ptr, tptr, &dev_ptr->dev_caller_list) { caller_p = list_entry(ptr, struct caller, caller_liste); if (!memcmp(caller_p->caller_id, psmid, sizeof(caller_p->caller_id))) { if (!list_empty(&caller_p->caller_liste)) { list_del(ptr); dev_ptr->dev_caller_count--; INIT_LIST_HEAD(&caller_p->caller_liste); break; } } caller_p = 0; } if (!caller_p) { rv = REC_USER_GONE; break; } PDEBUG("caller_p after successful receive: %p\n", caller_p); rv = convert_response(dev_ptr->dev_resp_p, caller_p->caller_buf_p, buff_len_p, buff); switch (rv) { case REC_OPERAND_INV: PDEBUG("dev %d: user error %d\n", index, rv); break; case WRONG_DEVICE_TYPE: case REC_HARDWAR_ERR: case REC_BAD_MESSAGE: PRINTK("dev %d: hardware error %d\n", index, rv); rv = REC_NO_RESPONSE; break; case REC_RELEASED: PDEBUG("dev %d: REC_RELEASED = %d\n", index, rv); break; default: PDEBUG("dev %d: rv = %d\n", index, rv); break; } } while (0); switch (rv) { case 0: PDEBUG("Successful receive from device %d\n", index); icaMsg_p = (struct ica_rsa_modexpo *)caller_p->caller_buf_p; *dest_p_p = icaMsg_p->outputdata; if (*buff_len_p == 0) PRINTK("Zero *buff_len_p\n"); break; case REC_NO_RESPONSE: remove_device(dev_ptr); break; } if (caller_p) unbuild_caller(dev_ptr, caller_p); return rv;}static inline voidhelper_send_work(int index){ struct work_element *rq_p; int rv; if (list_empty(&request_list)) return; requestq_count--; rq_p = list_entry(request_list.next, struct work_element, liste); list_del(&rq_p->liste); rq_p->audit[1] |= FP_REMREQUEST; if (rq_p->devtype == SHRT2DEVPTR(index)->dev_type) { rq_p->devindex = SHRT2LONG(index); rv = send_to_crypto_device(rq_p); if (rv == 0) { rq_p->requestsent = jiffies; rq_p->audit[0] |= FP_SENT; list_add_tail(&rq_p->liste, &pending_list); ++pendingq_count; rq_p->audit[0] |= FP_PENDING; } else { switch (rv) { case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: rq_p->retcode = -EINVAL; break; case SEN_NOT_AVAIL: case SEN_RETRY: case REC_NO_RESPONSE: default: if (z90crypt.mask.st_count > 1) rq_p->retcode = -ERESTARTSYS; else rq_p->retcode = -ENODEV; break; } rq_p->status[0] |= STAT_FAILED; rq_p->audit[1] |= FP_AWAKENING; atomic_set(&rq_p->alarmrung, 1); wake_up(&rq_p->waitq); } } else { if (z90crypt.mask.st_count > 1) rq_p->retcode = -ERESTARTSYS; else rq_p->retcode = -ENODEV; rq_p->status[0] |= STAT_FAILED; rq_p->audit[1] |= FP_AWAKENING; atomic_set(&rq_p->alarmrung, 1); wake_up(&rq_p->waitq); }}static inline voidhelper_handle_work_element(int index, unsigned char psmid[8], int rc, int buff_len, unsigned char *buff, unsigned char __user *resp_addr){ struct work_element *pq_p; struct list_head *lptr, *tptr; pq_p = 0; list_for_each_safe(lptr, tptr, &pending_list) { pq_p = list_entry(lptr, struct work_element, liste); if (!memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id))) { list_del(lptr); pendingq_count--; pq_p->audit[1] |= FP_NOTPENDING; break; } pq_p = 0; } if (!pq_p) { PRINTK("device %d has work but no caller exists on pending Q\n", SHRT2LONG(index)); return; } switch (rc) { case 0: pq_p->resp_buff_size = buff_len; pq_p->audit[1] |= FP_RESPSIZESET; if (buff_len) { pq_p->resp_addr = resp_addr; pq_p->audit[1] |= FP_RESPADDRCOPIED; memcpy(pq_p->resp_buff, buff, buff_len); pq_p->audit[1] |= FP_RESPBUFFCOPIED; } break; case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: PDEBUG("-EINVAL after application error %d\n", rc); pq_p->retcode = -EINVAL; pq_p->status[0] |= STAT_FAILED; break; case REC_NO_RESPONSE: default: if (z90crypt.mask.st_count > 1) pq_p->retcode = -ERESTARTSYS; else pq_p->retcode = -ENODEV; pq_p->status[0] |= STAT_FAILED; break; } if ((pq_p->status[0] != STAT_FAILED) || (pq_p->retcode != -ERELEASED)) { pq_p->audit[1] |= FP_AWAKENING; atomic_set(&pq_p->alarmrung, 1); wake_up(&pq_p->waitq); }}/** * return TRUE if the work element should be removed from the queue */static inline inthelper_receive_rc(int index, int *rc_p, int *workavail_p){ switch (*rc_p) { case 0: case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: return 1; case REC_BUSY: case REC_NO_WORK: case REC_EMPTY: case REC_RETRY_DEV: case REC_FATAL_ERROR: break; case REC_NO_RESPONSE: *workavail_p = 0; break; default: PRINTK("rc %d, device %d\n", *rc_p, SHRT2LONG(index)); *rc_p = REC_NO_RESPONSE; *workavail_p = 0; break; } return 0;}static inline voidz90crypt_schedule_reader_timer(void){ if (timer_pending(&reader_timer)) return; if (mod_timer(&reader_timer, jiffies+(READERTIME*HZ/1000)) != 0) PRINTK("Timer pending while modifying reader timer\n");}static voidz90crypt_reader_task(unsigned long ptr){ int workavail, remaining, index, rc, buff_len; unsigned char psmid[8]; unsigned char __user *resp_addr; static unsigned char buff[1024]; PDEBUG("jiffies %ld\n", jiffies); /** * we use workavail = 2 to ensure 2 passes with nothing dequeued before * exiting the loop. If remaining == 0 after the loop, there is no work * remaining on the queues. */ resp_addr = 0; workavail = 2; remaining = 0; buff_len = 0; while (workavail) { workavail--; rc = 0; spin_lock_irq(&queuespinlock); memset(buff, 0x00, sizeof(buff)); /* Dequeue once from each device in round robin. */ for (index = 0; index < z90crypt.mask.st_count; index++) { PDEBUG("About to receive.\n"); rc = receive_from_crypto_device(SHRT2LONG(index), psmid, &buff_len, buff, &resp_addr); PDEBUG("Dequeued: rc = %d.\n", rc); if (helper_receive_rc(index, &rc, &workavail)) { if (rc != REC_NO_RESPONSE) { helper_send_work(index); workavail = 2; } helper_handle_work_element(index, psmid, rc, buff_len, buff, resp_addr); } if (rc == REC_FATAL_ERROR) remaining = 0; else if (rc != REC_NO_RESPONSE) remaining += SHRT2DEVPTR(index)->dev_caller_count; } spin_unlock_irq(&queuespinlock); } if (remaining) { spin_lock_irq(&queuespinlock); z90crypt_schedule_reader_timer(); spin_unlock_irq(&queuespinlock); }}static inline voidz90crypt_schedule_config_task(unsigned int expiration){ if (timer_pending(&config_timer)) return; if (mod_timer(&config_timer, jiffies+(expiration*HZ)) != 0) PRINTK("Timer pending while modifying config timer\n");}static voidz90crypt_config_task(unsigned long ptr){ int rc; PDEBUG("jiffies %ld\n", jiffies); if ((rc = refresh_z90crypt(&z90crypt.cdx))) PRINTK("Error %d detected in refr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -