/* * arch/arm/mach-tegra/nvaes_user.c * * User-land access to AES Cryptographic engine. * * Copyright (c) 2008-2009, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include static NvRtHandle s_hRt = NULL; NvError NvDdkAes_Dispatch( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx ); static int nvaes_user_open(struct inode *inode, struct file *file) { NvRtClientHandle hClient = (NvRtClientHandle)NULL; NvError e = NvRtRegisterClient(s_hRt, &hClient); if (NvSuccess != e) { printk(KERN_INFO "nvaes_user_open: NvRtRegisterClient returned error 0x%x.\n", e); return -1; } file->private_data = (void*)hClient; printk(KERN_INFO "nvaes_user_open: hClient = 0x%x.\n", hClient); return 0; } static int nvaes_user_release(struct inode *inode, struct file *file) { NvRtClientHandle hClient = (NvRtClientHandle)file->private_data; if (NvRtUnregisterClient(s_hRt, hClient)) { NvDispatchCtx dctx; NvOsMemset(&dctx, 0, sizeof(NvDispatchCtx)); dctx.Rt = s_hRt; dctx.Client = hClient; for (;;) { void* ptr = NvRtFreeObjRef(&dctx, NvRtObjType_NvDdkAes_NvDdkAesHandle, NULL); if (!ptr) break; NvDdkAesClose((NvDdkAesHandle)ptr); } if (NvRtUnregisterClient(s_hRt, hClient)) panic("nvaes_user_release: Unable to free resourceTracker client!\n"); } return 0; } static long nvaes_user_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { NvError e = NvSuccess; NvOsIoctlParams IoctlParams; NvU32 size = 0; NvU32 SmallBuf[8]; void *ptr = NULL; NvBool IsAlloc = NV_FALSE; long status = 0; switch (cmd) { case NvDdkAesKernelIoctls_Generic: { NvDispatchCtx dctx; dctx.Rt = s_hRt; dctx.Client = (NvRtClientHandle)file->private_data; dctx.PackageIdx = 0; e = NvOsCopyIn(&IoctlParams, (void *)arg, sizeof(IoctlParams)); if (e != NvSuccess) { printk("NvDdkAesKernelIoctls_Generic: copy in failed\n"); goto fail; } size = IoctlParams.InBufferSize + IoctlParams.InOutBufferSize + IoctlParams.OutBufferSize; if (size <= sizeof(SmallBuf)) { ptr = SmallBuf; } else { ptr = NvOsAlloc(size); if (!ptr) { printk("NvDdkAesKernelIoctls_Generic: alloc err\n"); goto fail; } IsAlloc = NV_TRUE; } e = NvOsCopyIn(ptr, IoctlParams.pBuffer, IoctlParams.InBufferSize + IoctlParams.InOutBufferSize); if (e != NvSuccess) { printk("NvDdkAesKernelIoctls_Generic: copy in failure\n"); goto fail; } e = NvDdkAes_Dispatch(ptr, IoctlParams.InBufferSize + IoctlParams.InOutBufferSize, ((NvU8 *)ptr) + IoctlParams.InBufferSize, IoctlParams.InOutBufferSize + IoctlParams.OutBufferSize, &dctx); if (e != NvSuccess) { printk("NvDdkAesKernelIoctls_Generic: dispatch failure, err = 0x%x\n", e); goto fail; } if (IoctlParams.InOutBufferSize || IoctlParams.OutBufferSize) { e = NvOsCopyOut( ((NvU8 *)((NvOsIoctlParams *)arg)->pBuffer) + IoctlParams.InBufferSize, ((NvU8 *)ptr) + IoctlParams.InBufferSize, IoctlParams.InOutBufferSize + IoctlParams.OutBufferSize); if (e != NvSuccess) { printk("NvDdkAesKernelIoctls_Generic: copyout err\n"); goto fail; } } break; } default: printk("unknown ioctl code\n"); goto fail; } goto clean; fail: status = -EINVAL; clean: if (IsAlloc) NvOsFree(ptr); return status; } #define DEVICE_NAME "nvaes" static const struct file_operations nvaes_user_fops = { .owner = THIS_MODULE, .open = nvaes_user_open, .release = nvaes_user_release, .unlocked_ioctl = nvaes_user_unlocked_ioctl, }; static struct miscdevice nvaes_user_dev = { .name = DEVICE_NAME, .fops = &nvaes_user_fops, .minor = MISC_DYNAMIC_MINOR, }; static int __init nvaes_user_init(void) { NvU32 NumTypes = NvRtObjType_NvDdkAes_Num; printk(KERN_INFO "Loading nvaes.ko.\n"); NV_ASSERT(s_hRt == NULL); if (NvSuccess != NvRtCreate(1, &NumTypes, &s_hRt)) { printk(KERN_INFO "nvaes_user_init: NvRtCreate returned error.\n"); goto fail2; } if (misc_register(&nvaes_user_dev)) { printk(KERN_INFO "nvaes_user_init: misc_register returned error.\n"); goto fail; } printk(KERN_INFO "Loading nvaes.ko SUCCESS.\n"); return 0; fail: NvRtDestroy(s_hRt); s_hRt = NULL; fail2: return -1; } static void __exit nvaes_user_cleanup(void) { printk(KERN_INFO "Unloading nvaes.ko.\n"); misc_deregister(&nvaes_user_dev); if (s_hRt) { NvRtDestroy(s_hRt); s_hRt = NULL; } printk(KERN_INFO "Unloaded nvaes.ko.\n"); } module_init(nvaes_user_init); module_exit(nvaes_user_cleanup); MODULE_LICENSE("GPL");