249 lines
6.1 KiB
C
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);
|
|
}
|