📄 z90main.c
字号:
PDEBUG("function: %04x\n", function); rv = build_caller(we_p, function); PDEBUG("rv from build_caller = %d\n", rv); return rv;}static inline intz90crypt_prepare(struct work_element *we_p, unsigned int funccode, const char __user *buffer){ int rv; we_p->devindex = -1; if (funccode == ICARSAMODEXPO) we_p->buff_size = sizeof(struct ica_rsa_modexpo); else we_p->buff_size = sizeof(struct ica_rsa_modexpo_crt); if (copy_from_user(we_p->buffer, buffer, we_p->buff_size)) return -EFAULT; we_p->audit[0] |= FP_COPYFROM; SET_RDWRMASK(we_p->status[0], STAT_WRITTEN); we_p->funccode = funccode; we_p->devtype = -1; we_p->audit[0] |= FP_BUFFREQ; rv = get_crypto_request_buffer(we_p); switch (rv) { case 0: we_p->audit[0] |= FP_BUFFGOT; break; case SEN_USER_ERROR: rv = -EINVAL; break; case SEN_QUEUE_FULL: rv = 0; break; case SEN_RELEASED: rv = -EFAULT; break; case REC_NO_RESPONSE: rv = -ENODEV; break; case SEN_NOT_AVAIL: rv = -EGETBUFF; break; default: PRINTK("rv = %d\n", rv); rv = -EGETBUFF; break; } if (CHK_RDWRMASK(we_p->status[0]) == STAT_WRITTEN) SET_RDWRMASK(we_p->status[0], STAT_DEFAULT); return rv;}static inline voidpurge_work_element(struct work_element *we_p){ struct list_head *lptr; spin_lock_irq(&queuespinlock); list_for_each(lptr, &request_list) { if (lptr == &we_p->liste) { list_del(lptr); requestq_count--; break; } } list_for_each(lptr, &pending_list) { if (lptr == &we_p->liste) { list_del(lptr); pendingq_count--; break; } } spin_unlock_irq(&queuespinlock);}/** * Build the request and send it. */static inline intz90crypt_rsa(struct priv_data *private_data_p, pid_t pid, unsigned int cmd, unsigned long arg){ struct work_element *we_p; int rv; if ((rv = allocate_work_element(&we_p, private_data_p, pid))) { PDEBUG("PID %d: allocate_work_element returned ENOMEM\n", pid); return rv; } if ((rv = z90crypt_prepare(we_p, cmd, (const char __user *)arg))) PDEBUG("PID %d: rv = %d from z90crypt_prepare\n", pid, rv); if (!rv) if ((rv = z90crypt_send(we_p, (const char *)arg))) PDEBUG("PID %d: rv %d from z90crypt_send.\n", pid, rv); if (!rv) { we_p->audit[0] |= FP_ASLEEP; wait_event(we_p->waitq, atomic_read(&we_p->alarmrung)); we_p->audit[0] |= FP_AWAKE; rv = we_p->retcode; } if (!rv) rv = z90crypt_process_results(we_p, (char __user *)arg); if ((we_p->status[0] & STAT_FAILED)) { switch (rv) { /** * EINVAL *after* receive is almost always padding * error issued by a PCICC or PCIXCC. We convert this * return value to -EGETBUFF which should trigger a * fallback to software. */ case -EINVAL: if ((we_p->devtype == PCICC) || (we_p->devtype == PCIXCC)) rv = -EGETBUFF; break; case -ETIMEOUT: if (z90crypt.mask.st_count > 0) rv = -ERESTARTSYS; // retry with another else rv = -ENODEV; // no cards left /* fall through to clean up request queue */ case -ERESTARTSYS: case -ERELEASED: switch (CHK_RDWRMASK(we_p->status[0])) { case STAT_WRITTEN: purge_work_element(we_p); break; case STAT_READPEND: case STAT_NOWORK: default: break; } break; default: we_p->status[0] ^= STAT_FAILED; break; } } free_page((long)we_p); return rv;}/** * This function is a little long, but it's really just one large switch * statement. */static intz90crypt_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ struct priv_data *private_data_p = filp->private_data; unsigned char *status; unsigned char *qdepth; unsigned int *reqcnt; struct ica_z90_status *pstat; int ret, i, loopLim, tempstat; static int deprecated_msg_count = 0; PDEBUG("filp %p (PID %d), cmd 0x%08X\n", filp, PID(), cmd); PDEBUG("cmd 0x%08X: dir %s, size 0x%04X, type 0x%02X, nr 0x%02X\n", cmd, !_IOC_DIR(cmd) ? "NO" : ((_IOC_DIR(cmd) == (_IOC_READ|_IOC_WRITE)) ? "RW" : ((_IOC_DIR(cmd) == _IOC_READ) ? "RD" : "WR")), _IOC_SIZE(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd)); if (_IOC_TYPE(cmd) != Z90_IOCTL_MAGIC) { PRINTK("cmd 0x%08X contains bad magic\n", cmd); return -ENOTTY; } ret = 0; switch (cmd) { case ICARSAMODEXPO: case ICARSACRT: if (quiesce_z90crypt) { ret = -EQUIESCE; break; } ret = -ENODEV; // Default if no devices loopLim = z90crypt.hdware_info->hdware_mask.st_count - (z90crypt.hdware_info->hdware_mask.disabled_count + z90crypt.hdware_info->hdware_mask.user_disabled_count); for (i = 0; i < loopLim; i++) { ret = z90crypt_rsa(private_data_p, PID(), cmd, arg); if (ret != -ERESTARTSYS) break; } if (ret == -ERESTARTSYS) ret = -ENODEV; break; case Z90STAT_TOTALCOUNT: tempstat = get_status_totalcount(); if (copy_to_user((int __user *)arg, &tempstat,sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_PCICACOUNT: tempstat = get_status_PCICAcount(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_PCICCCOUNT: tempstat = get_status_PCICCcount(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_PCIXCCCOUNT: tempstat = get_status_PCIXCCcount(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_REQUESTQ_COUNT: tempstat = get_status_requestq_count(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_PENDINGQ_COUNT: tempstat = get_status_pendingq_count(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_TOTALOPEN_COUNT: tempstat = get_status_totalopen_count(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_DOMAIN_INDEX: tempstat = get_status_domain_index(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; case Z90STAT_STATUS_MASK: status = kmalloc(Z90CRYPT_NUM_APS, GFP_KERNEL); if (!status) { PRINTK("kmalloc for status failed!\n"); ret = -ENOMEM; break; } get_status_status_mask(status); if (copy_to_user((char __user *) arg, status, Z90CRYPT_NUM_APS) != 0) ret = -EFAULT; kfree(status); break; case Z90STAT_QDEPTH_MASK: qdepth = kmalloc(Z90CRYPT_NUM_APS, GFP_KERNEL); if (!qdepth) { PRINTK("kmalloc for qdepth failed!\n"); ret = -ENOMEM; break; } get_status_qdepth_mask(qdepth); if (copy_to_user((char __user *) arg, qdepth, Z90CRYPT_NUM_APS) != 0) ret = -EFAULT; kfree(qdepth); break; case Z90STAT_PERDEV_REQCNT: reqcnt = kmalloc(sizeof(int) * Z90CRYPT_NUM_APS, GFP_KERNEL); if (!reqcnt) { PRINTK("kmalloc for reqcnt failed!\n"); ret = -ENOMEM; break; } get_status_perdevice_reqcnt(reqcnt); if (copy_to_user((char __user *) arg, reqcnt, Z90CRYPT_NUM_APS * sizeof(int)) != 0) ret = -EFAULT; kfree(reqcnt); break; /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ case ICAZ90STATUS: if (deprecated_msg_count < 100) { PRINTK("deprecated call to ioctl (ICAZ90STATUS)!\n"); deprecated_msg_count++; if (deprecated_msg_count == 100) PRINTK("No longer issuing messages related to " "deprecated call to ICAZ90STATUS.\n"); } pstat = kmalloc(sizeof(struct ica_z90_status), GFP_KERNEL); if (!pstat) { PRINTK("kmalloc for pstat failed!\n"); ret = -ENOMEM; break; } pstat->totalcount = get_status_totalcount(); pstat->leedslitecount = get_status_PCICAcount(); pstat->leeds2count = get_status_PCICCcount(); pstat->requestqWaitCount = get_status_requestq_count(); pstat->pendingqWaitCount = get_status_pendingq_count(); pstat->totalOpenCount = get_status_totalopen_count(); pstat->cryptoDomain = get_status_domain_index(); get_status_status_mask(pstat->status); get_status_qdepth_mask(pstat->qdepth); if (copy_to_user((struct ica_z90_status __user *) arg, pstat, sizeof(struct ica_z90_status)) != 0) ret = -EFAULT; kfree(pstat); break; case Z90QUIESCE: if (current->euid != 0) { PRINTK("QUIESCE fails: euid %d\n", current->euid); ret = -EACCES; } else { PRINTK("QUIESCE device from PID %d\n", PID()); quiesce_z90crypt = 1; } break; default: /* user passed an invalid IOCTL number */ PDEBUG("cmd 0x%08X contains invalid ioctl code\n", cmd); ret = -ENOTTY; break; } return ret;}static inline intsprintcl(unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, i; hl = 0; for (i = 0; i < len; i++) hl += sprintf(outaddr+hl, "%01x", (unsigned int) addr[i]); hl += sprintf(outaddr+hl, " "); return hl;}static inline intsprintrw(unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, inl, c, cx; hl = sprintf(outaddr, " "); inl = 0; for (c = 0; c < (len / 16); c++) { hl += sprintcl(outaddr+hl, addr+inl, 16); inl += 16; } cx = len%16; if (cx) { hl += sprintcl(outaddr+hl, addr+inl, cx); inl += cx; } hl += sprintf(outaddr+hl, "\n"); return hl;}static inline intsprinthx(unsigned char *title, unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, inl, r, rx; hl = sprintf(outaddr, "\n%s\n", title); inl = 0; for (r = 0; r < (len / 64); r++) { hl += sprintrw(outaddr+hl, addr+inl, 64); inl += 64; } rx = len % 64; if (rx) { hl += sprintrw(outaddr+hl, addr+inl, rx); inl += rx; } hl += sprintf(outaddr+hl, "\n"); return hl;}static inline intsprinthx4(unsigned char *title, unsigned char *outaddr, unsigned int *array, unsigned int len){ int hl, r; hl = sprintf(outaddr, "\n%s\n", title); for (r = 0; r < len; r++) { if ((r % 8) == 0) hl += sprintf(outaddr+hl, " "); hl += sprintf(outaddr+hl, "%08X ", array[r]); if ((r % 8) == 7) hl += sprintf(outaddr+hl, "\n"); } hl += sprintf(outaddr+hl, "\n"); return hl;}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 count: %d\n", get_status_PCIXCCcount()); 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 means PCICA, 2 means PCICC, 3 means PCIXCC", 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 inline intscan_char(unsigned char *bf, unsigned int len, unsigned int *offs, unsigned int *p_eof, unsigned char c){ unsigned int i, found; found = 0; for (i = 0; i < len; i++) { if (bf[i] == c) { found = 1; break; } if (bf[i] == '\0') { *p_eof = 1; break; } if (bf[i] == '\n') { break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -