Files
2026-07-30 11:19:44 +05:30

249 lines
6.1 KiB
C

/****************************************************************************
* sec2_ioctl.c - Driver service hooks for the SEC2.x security core
****************************************************************************
* Copyright (c) Certicom Corp. 1996-2002. All rights reserved
* Copyright (c) 2003-2005 Freescale Semiconductor
* All Rights Reserved. Proprietary and Confidential.
*
* NOTICE: The information contained in this file is proprietary
* to Freescale Semiconductor, and is being made available to
* Freescale's customers under strict license agreements.
* Use or disclosure of this information is permissible only
* under the terms of the existing license agreement.
***************************************************************************/
/* Revision History:
* 1.0 Aug 24,2003 dgs - adapted from the final version of mpc18x
* 1.1.0 Nov 22,2003 sec - merge in changes from Linux fork
* 1.1.1 Dev 15,2004 sec - remove old diagnostics
* 1.2 Jan 27,2005 sec - fix minor compiler warnings
*/
#include "Sec2Driver.h"
/* Interpeak begin */
#undef NUM_CHANNELS
#define NUM_CHANNELS (num_channels)
extern int num_channels;
/* Interpeak end */
/* Interpeak begin */
#ifdef __KERNEL__
Ctx_queue_header ctx_done_queue = { NULL, NULL };
Ctx_queue_header ctx_error_queue = { NULL, NULL };
static inline Ctx_queue_element *ctx_element_dequeue(Ctx_queue_header *hdr, int pid)
{
register Ctx_queue_element *element;
register Ctx_queue_element *prev = NULL;
for(element = hdr->head; element != NULL; element = element->next)
{
if (element->pid == pid)
{
if (prev == NULL)
{
/* Matched the first element */
hdr->head = element->next;
if (!hdr->head)
{
/* Queue is now empty */
hdr->tail = NULL;
}
}
else
{
prev->next = element->next;
if (prev->next == NULL)
{
/* Matched the last element */
hdr->tail = prev;
}
}
break;
}
prev = element;
}
return element;
}
#endif
/* Interpeak end */
#ifdef __KERNEL__
int SEC2Open(struct inode *nd, struct file *fil)
{
SEC2Dump(DBGTXT_SETRQ, ("SEC2Open() called, inode 0x%08x, file 0x%08x\n", (unsigned int)nd, (unsigned int)fil));
MOD_INC_USE_COUNT;
return 0;
}
#endif
#ifdef VXWORKS
int SEC2Open(DEV_HDR *pDevHdr, int mode, int flags)
{
return((int)pDevHdr);
}
#endif
#ifdef __KERNEL__
int SEC2Close(struct inode *nd, struct file *fil)
#else
int SEC2Close(int devDesc)
#endif
{
int channel;
QUEUE_ENTRY *QueueEntry;
int callingTaskId = (int)taskIdSelf();
SEC2Dump(DBGTXT_SETRQ, ("SEC2Close() called\n"));
QueueEntry = ProcessQueueTop;
while (QueueEntry->pReq != NULL)
{
if (QueueEntry->requestingTaskId == callingTaskId)
{
((GENERIC_REQ*)QueueEntry->pReq)->status = SEC2_CANCELLED_REQUEST;
QueueEntry->pReq = NULL;
}
QueueEntry = QueueEntry->next;
}
IOLockChannelAssignment();
/* release any leftover reserved channels associated with this descriptor */
for (channel=0; channel<NUM_CHANNELS; channel++)
if (ChannelAssignments[channel].ownerTaskId == callingTaskId)
/* release this channel */
ReleaseChannel(channel+1, callingTaskId, TRUE);
IOUnLockChannelAssignment();
ScheduleNext();
#ifdef __KERNEL__
MOD_DEC_USE_COUNT;
#endif
return SEC2_SUCCESS;
}
#ifdef __KERNEL__
int SEC2_ioctl(struct inode *nd,
struct file *fil,
unsigned int ioctlCode,
unsigned long param)
#else
int SEC2_ioctl(int devDesc, register int ioctlCode, register void *param)
#endif
{
int status;
#ifdef __KERNEL__
MALLOC_REQ *mem;
/* Interpeak begin */
Ctx_queue_element *item;
/* Interpeak end */
#endif
status = SEC2_SUCCESS;
switch (ioctlCode)
{
case IOCTL_PROC_REQ:
if (param == (int)NULL)
{
status = SEC2_INVALID_ADDRESS;
break;
}
status = ProcessRequest((GENERIC_REQ *)param, (int)taskIdSelf());
break;
case IOCTL_GET_STATUS:
GetStatus((STATUS_REQ *)param, (int)taskIdSelf());
break;
#ifdef __KERNEL__
case IOCTL_MALLOC:
if ((((MALLOC_REQ *)param)->ptr = malloc(((MALLOC_REQ *)param)->sz)) == 0) {
status = SEC2_MALLOC_FAILED;
break;
}
memset(((MALLOC_REQ *)param)->ptr, 0, ((MALLOC_REQ *)param)->sz);
status = SEC2_SUCCESS;
break;
case IOCTL_COPYFROM:
mem = (MALLOC_REQ *)param;
mem->pid = current->pid;
copy_from_user(mem->to, mem->from, mem->sz);
status = SEC2_SUCCESS;
break;
case IOCTL_COPYTO:
mem = (MALLOC_REQ *)param;
mem->pid = current->pid;
copy_to_user(mem->to, mem->from, mem->sz);
status = SEC2_SUCCESS;
break;
case IOCTL_FREE:
free((void *)param);
break;
#endif
/* Interpeak begin */
#ifdef __KERNEL__
case IOCTL_GET_DONE:
IOLockChannelAssignment();
item = ctx_element_dequeue(&ctx_done_queue, (int)taskIdSelf());
if(item)
{
status = put_user(item->ctx, (void **)param);
kfree(item);
}
else
{
status = put_user(0, (void **)param);
}
IOUnLockChannelAssignment();
break;
case IOCTL_GET_ERROR:
IOLockChannelAssignment();
item = ctx_element_dequeue(&ctx_error_queue, (int)taskIdSelf());
if(item)
{
status = put_user(item->ctx, (void **)param);
kfree(item);
}
else
{
status = put_user(0, (void **)param);
}
IOUnLockChannelAssignment();
break;
#endif
/* Interpeak end */
default:
/* invalide IOCTL code, return an error */
/* need OS-specific error value here */
return (S_ioLib_UNKNOWN_REQUEST);
} /* end switch (ioctlCode) */
return (status);
}