📄 z90main.c
字号:
static intz90crypt_status(char *resp_buff, char **start, off_t offset, int count, int *eof, void *data){ unsigned char *workarea; int len; /* resp_buff is a page. Use the right half for a work area */ workarea = resp_buff+2000; len = 0; len += sprintf(resp_buff+len, "\nz90crypt version: %d.%d.%d\n", z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT); len += sprintf(resp_buff+len, "Cryptographic domain: %d\n", get_status_domain_index()); len += sprintf(resp_buff+len, "Total device count: %d\n", get_status_totalcount()); len += sprintf(resp_buff+len, "PCICA count: %d\n", get_status_PCICAcount()); len += sprintf(resp_buff+len, "PCICC count: %d\n", get_status_PCICCcount()); len += sprintf(resp_buff+len, "PCIXCC MCL2 count: %d\n", get_status_PCIXCCMCL2count()); len += sprintf(resp_buff+len, "PCIXCC MCL3 count: %d\n", get_status_PCIXCCMCL3count()); len += sprintf(resp_buff+len, "CEX2C count: %d\n", get_status_CEX2Ccount()); len += sprintf(resp_buff+len, "requestq count: %d\n", get_status_requestq_count()); len += sprintf(resp_buff+len, "pendingq count: %d\n", get_status_pendingq_count()); len += sprintf(resp_buff+len, "Total open handles: %d\n\n", get_status_totalopen_count()); len += sprinthx( "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), " "4: PCIXCC (MCL3), 5: CEX2C", resp_buff+len, get_status_status_mask(workarea), Z90CRYPT_NUM_APS); len += sprinthx("Waiting work element counts", resp_buff+len, get_status_qdepth_mask(workarea), Z90CRYPT_NUM_APS); len += sprinthx4( "Per-device successfully completed request counts", resp_buff+len, get_status_perdevice_reqcnt((unsigned int *)workarea), Z90CRYPT_NUM_APS); *eof = 1; memset(workarea, 0, Z90CRYPT_NUM_APS * sizeof(unsigned int)); return len;}static inline voiddisable_card(int card_index){ struct device *devp; devp = LONG2DEVPTR(card_index); if (!devp || devp->user_disabled) return; devp->user_disabled = 1; z90crypt.hdware_info->hdware_mask.user_disabled_count++; if (devp->dev_type == -1) return; z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count++;}static inline voidenable_card(int card_index){ struct device *devp; devp = LONG2DEVPTR(card_index); if (!devp || !devp->user_disabled) return; devp->user_disabled = 0; z90crypt.hdware_info->hdware_mask.user_disabled_count--; if (devp->dev_type == -1) return; z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--;}static intz90crypt_status_write(struct file *file, const char __user *buffer, unsigned long count, void *data){ int j, eol; unsigned char *lbuf, *ptr; unsigned int local_count;#define LBUFSIZE 1200 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] = '\0'; ptr = strstr(lbuf, "Online devices"); if (ptr == 0) { PRINTK("Unable to parse data (missing \"Online devices\")\n"); kfree(lbuf); return count; } ptr = strstr(ptr, "\n"); if (ptr == 0) { PRINTK("Unable to parse data (missing newline after \"Online devices\")\n"); kfree(lbuf); return count; } ptr++; if (strstr(ptr, "Waiting work element counts") == NULL) { PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n"); kfree(lbuf); return count; } j = 0; eol = 0; while ((j < 64) && (*ptr != '\0')) { switch (*ptr) { case '\t': case ' ': break; case '\n': default: eol = 1; break; case '0': // no device case '1': // PCICA case '2': // PCICC case '3': // PCIXCC_MCL2 case '4': // PCIXCC_MCL3 case '5': // CEX2C j++; break; case 'd': case 'D': disable_card(j); j++; break; case 'e': case 'E': enable_card(j); j++; break; } if (eol) break; ptr++; } 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 { if (!dev_ptr || dev_ptr->disabled) { rv = REC_NO_WORK; // a disabled device can't return work break; } if (dev_ptr->dev_self_x != index) { PRINTKC("Corrupt dev ptr\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 { PDEBUG("Dequeue called for device %d\n", index); 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_init(ptr); dev_ptr->dev_caller_count--; break; } } caller_p = 0; } if (!caller_p) { PRINTKW("Unable to locate PSMID %02X%02X%02X%02X%02X" "%02X%02X%02X in device list\n", psmid[0], psmid[1], psmid[2], psmid[3], psmid[4], psmid[5], psmid[6], psmid[7]); 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_USE_PCICA: break; case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: PDEBUG("device %d: 'user error' %d\n", index, rv); break; case WRONG_DEVICE_TYPE: case REC_HARDWAR_ERR: case REC_BAD_MESSAGE: PRINTKW("device %d: hardware error %d\n", index, rv); rv = REC_NO_RESPONSE; break; default: PDEBUG("device %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: PRINTKW("Removing device %d from availability\n", index); 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_init(&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_init(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_USE_PCICA: pq_p->retcode = -ERESTARTSYS; 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){ switch (*rc_p) { case 0: case REC_OPERAND_INV: case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: case REC_USE_PCICA: break; case REC_BUSY: case REC_NO_WORK: case REC_EMPTY: case REC_RETRY_DEV: case REC_FATAL_ERROR: return 0; case REC_NO_RESPONSE: break; default: PRINTK("rc %d, device %d converted to REC_NO_RESPONSE\n", *rc_p, SHRT2LONG(index)); *rc_p = REC_NO_RESPONSE; break; } return 1;}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, index, rc, buff_len; unsigned char psmid[8]; unsigned char __user *resp_addr; static unsigned char buff[1024]; /** * we use workavail = 2 to ensure 2 passes with nothing dequeued before *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -