static inline void HandleListRemove(struct PVRSRV_HANDLE_BASE *psBase, u32 ui32EntryIndex, struct sHandleList *psEntry, size_t uiEntryOffset, size_t uiParentOffset) { if (!HandleListIsEmpty(ui32EntryIndex, psEntry)) { struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psBase, psEntry-> hParent), uiParentOffset, uiEntryOffset); struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psBase, psEntry-> hParent), uiParentOffset, uiEntryOffset); PVR_ASSERT(psEntry->hParent != NULL); psPrev->ui32Next = psEntry->ui32Next; psNext->ui32Prev = psEntry->ui32Prev; HandleListInit(ui32EntryIndex, psEntry, NULL); } }
/*! ****************************************************************************** @Function GetHandleData @Description Get the data associated with the given handle @Input psBase - Pointer to handle base structure hHandle - Handle from which data should be retrieved ppvData - Points to a void data pointer @Output ppvData - Points to a void data pointer @Return Error code or PVRSRV_OK ******************************************************************************/ static PVRSRV_ERROR GetHandleData(HANDLE_IMPL_BASE *psBase, IMG_HANDLE hHandle, IMG_VOID **ppvData) { IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle); HANDLE_IMPL_DATA *psHandleData; PVR_ASSERT(psBase); PVR_ASSERT(ppvData); /* Check handle index is in range */ if (!INDEX_IS_VALID(psBase, ui32Index)) { PVR_DPF((PVR_DBG_ERROR, "%s: Handle index out of range (%u >= %u)", __FUNCTION__, ui32Index, psBase->ui32TotalHandCount)); OSDumpStack(); return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE; } psHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32Index); *ppvData = psHandleData->pvData; return PVRSRV_OK; }
static void nbd_coroutine_end(BDRVNBDState *s, struct nbd_request *request) { int i = HANDLE_TO_INDEX(s, request->handle); s->recv_coroutine[i] = NULL; if (s->in_flight-- == MAX_NBD_REQUESTS) { qemu_co_mutex_unlock(&s->free_sema); } }
static INLINE IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild) { IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent); PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psBase, psParent)); HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psBase, psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent); }
static void nbd_coroutine_end(BlockDriverState *bs, NBDRequest *request) { NBDClientSession *s = nbd_get_client_session(bs); int i = HANDLE_TO_INDEX(s, request->handle); s->recv_coroutine[i] = NULL; s->in_flight--; qemu_co_queue_next(&s->free_sema); /* Kick the read_reply_co to get the next reply. */ if (s->read_reply_co) { aio_co_wake(s->read_reply_co); } }
static coroutine_fn void nbd_read_reply_entry(void *opaque) { NBDClientSession *s = opaque; uint64_t i; int ret = 0; Error *local_err = NULL; while (!s->quit) { assert(s->reply.handle == 0); ret = nbd_receive_reply(s->ioc, &s->reply, &local_err); if (ret < 0) { error_report_err(local_err); } if (ret <= 0) { break; } /* There's no need for a mutex on the receive side, because the * handler acts as a synchronization point and ensures that only * one coroutine is called until the reply finishes. */ i = HANDLE_TO_INDEX(s, s->reply.handle); if (i >= MAX_NBD_REQUESTS || !s->requests[i].coroutine || !s->requests[i].receiving) { break; } /* We're woken up again by the request itself. Note that there * is no race between yielding and reentering read_reply_co. This * is because: * * - if the request runs on the same AioContext, it is only * entered after we yield * * - if the request runs on a different AioContext, reentering * read_reply_co happens through a bottom half, which can only * run after we yield. */ aio_co_wake(s->requests[i].coroutine); qemu_coroutine_yield(); } s->quit = true; nbd_recv_coroutines_wake_all(s); s->read_reply_co = NULL; }
static inline void AdoptChild(struct PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild) { u32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent); PVR_ASSERT(ui32Parent == (u32) HANDLE_PTR_TO_INDEX(psBase, psParent)); HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psBase, psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent); }
NTSTATUS DereferenceIoHandle( IN PCONSOLE_PER_PROCESS_DATA ProcessData, IN HANDLE Handle, IN ULONG HandleType, IN ACCESS_MASK Access, OUT PHANDLE_DATA *HandleData ) /*++ Routine Description: This routine verifies a handle's validity, then returns a pointer to the handle data structure. Arguments: ProcessData - Pointer to per process data structure. Handle - Handle to dereference. HandleData - On return, pointer to handle data structure. Return Value: --*/ { ULONG Index; if (!((ULONG)Handle & CONSOLE_HANDLE_SIGNATURE)) { return STATUS_INVALID_HANDLE; } Index = (ULONG)HANDLE_TO_INDEX(Handle); if ((Index >= ProcessData->HandleTableSize) || (ProcessData->HandleTablePtr[Index].HandleType == CONSOLE_FREE_HANDLE) || !(ProcessData->HandleTablePtr[Index].HandleType & HandleType) || !(ProcessData->HandleTablePtr[Index].Access & Access) ) { return STATUS_INVALID_HANDLE; } *HandleData = &ProcessData->HandleTablePtr[Index]; return STATUS_SUCCESS; }
ULONG SrvVerifyConsoleIoHandle( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus ) /*++ Routine Description: This routine verifies that a console io handle is valid. Arguments: ApiMessageData - Points to parameter structure. Return Value: --*/ { PCONSOLE_VERIFYIOHANDLE_MSG a = (PCONSOLE_VERIFYIOHANDLE_MSG)&m->u.ApiMessageData; PCONSOLE_INFORMATION Console; NTSTATUS Status; PHANDLE_DATA HandleData; PCONSOLE_PER_PROCESS_DATA ProcessData; UNREFERENCED_PARAMETER(ReplyStatus); Status = ApiPreamble(a->ConsoleHandle, &Console ); if (NT_SUCCESS(Status)) { ProcessData = CONSOLE_PERPROCESSDATA(); Status = DereferenceIoHandleNoCheck(ProcessData, HANDLE_TO_INDEX(a->Handle), &HandleData ); UnlockConsole(Console); } a->Valid = (NT_SUCCESS(Status)); return STATUS_SUCCESS; }
static void nbd_reply_ready(void *opaque) { BlockDriverState *bs = opaque; NbdClientSession *s = nbd_get_client_session(bs); uint64_t i; int ret; if (!s->ioc) { /* Already closed */ return; } if (s->reply.handle == 0) { /* No reply already in flight. Fetch a header. It is possible * that another thread has done the same thing in parallel, so * the socket is not readable anymore. */ ret = nbd_receive_reply(s->ioc, &s->reply); if (ret == -EAGAIN) { return; } if (ret < 0) { s->reply.handle = 0; goto fail; } } /* There's no need for a mutex on the receive side, because the * handler acts as a synchronization point and ensures that only * one coroutine is called until the reply finishes. */ i = HANDLE_TO_INDEX(s, s->reply.handle); if (i >= MAX_NBD_REQUESTS) { goto fail; } if (s->recv_coroutine[i]) { qemu_coroutine_enter(s->recv_coroutine[i], NULL); return; } fail: nbd_teardown_connection(bs); }
static void nbd_reply_ready(void *opaque) { BDRVNBDState *s = opaque; uint64_t i; int ret; if (s->reply.handle == 0) { /* No reply already in flight. Fetch a header. It is possible * that another thread has done the same thing in parallel, so * the socket is not readable anymore. */ ret = nbd_receive_reply(s->sock, &s->reply); if (ret == -EAGAIN) { return; } if (ret < 0) { s->reply.handle = 0; goto fail; } } /* There's no need for a mutex on the receive side, because the * handler acts as a synchronization point and ensures that only * one coroutine is called until the reply finishes. */ i = HANDLE_TO_INDEX(s, s->reply.handle); if (i >= MAX_NBD_REQUESTS) { goto fail; } if (s->recv_coroutine[i]) { qemu_coroutine_enter(s->recv_coroutine[i], NULL); return; } fail: for (i = 0; i < MAX_NBD_REQUESTS; i++) { if (s->recv_coroutine[i]) { qemu_coroutine_enter(s->recv_coroutine[i], NULL); } } }
static void nbd_co_receive_reply(NBDClientSession *s, NBDRequest *request, NBDReply *reply, QEMUIOVector *qiov) { int i = HANDLE_TO_INDEX(s, request->handle); /* Wait until we're woken up by nbd_read_reply_entry. */ s->requests[i].receiving = true; qemu_coroutine_yield(); s->requests[i].receiving = false; *reply = s->reply; if (reply->handle != request->handle || !s->ioc || s->quit) { reply->error = EIO; } else { if (qiov && reply->error == 0) { assert(request->len == iov_size(qiov->iov, qiov->niov)); if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { reply->error = EIO; s->quit = true; } } /* Tell the read handler to read another header. */ s->reply.handle = 0; } s->requests[i].coroutine = NULL; /* Kick the read_reply_co to get the next reply. */ if (s->read_reply_co) { aio_co_wake(s->read_reply_co); } qemu_co_mutex_lock(&s->send_mutex); s->in_flight--; qemu_co_queue_next(&s->free_sema); qemu_co_mutex_unlock(&s->send_mutex); }
static INLINE IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset) { if (!HandleListIsEmpty(ui32EntryIndex, psEntry)) { struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset); struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset); PVR_ASSERT(psEntry->hParent != IMG_NULL); psPrev->ui32Next = psEntry->ui32Next; psNext->ui32Prev = psEntry->ui32Prev; HandleListInit(ui32EntryIndex, psEntry, IMG_NULL); } }
TPM_RESULT TPM_LoadContext(TPM_HANDLE entityHandle, BOOL keepHandle, UINT32 contextSize, TPM_CONTEXT_BLOB *contextBlob, TPM_HANDLE *handle) { TPM_CONTEXT_SENSITIVE context; BYTE *context_buf; TPM_SESSION_DATA *session; TPM_DAA_SESSION_DATA *sessionDAA; TPM_KEY_DATA *key; TPM_DIGEST digest; int i = 0; info("TPM_LoadContext()"); if (decrypt_context(contextBlob->additionalData, contextBlob->additionalSize, contextBlob->sensitiveData, contextBlob->sensitiveSize, &context, &context_buf)) return TPM_DECRYPT_ERROR; /* validate structure */ if (compute_context_digest(contextBlob, &digest) || memcmp(&digest, &contextBlob->integrityDigest, sizeof(TPM_DIGEST))) { tpm_free(context_buf); return TPM_BADCONTEXT; } if (contextBlob->resourceType == TPM_RT_KEY) { /* check contextNonce */ if (context.internalData.key.parentPCRStatus || (context.internalData.key.keyFlags & TPM_KEY_FLAG_VOLATILE)) { if (memcmp(&context.contextNonce, &tpmData.stclear.data.contextNonceKey, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } } /* check handle */ key = tpm_get_key_slot(entityHandle); if (key == NULL || !key->payload) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_key(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } key = &tpmData.permanent.data.keys[HANDLE_TO_INDEX(*handle)]; } else { *handle = entityHandle; } /* reload resource */ memcpy(key, &context.internalData.key, sizeof(TPM_KEY_DATA)); tpm_rsa_copy_key(&key->key, &context.internalData.key.key); } else if (contextBlob->resourceType == TPM_RT_DAA_TPM) { /* check contextNonce */ if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } /* check context list */ for (i = 0; i < TPM_MAX_SESSION_LIST; i++) if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break; if (i >= TPM_MAX_SESSION_LIST) { tpm_free(context_buf); return TPM_BADCONTEXT; } tpmData.stany.data.contextList[i] = 0; /* check handle */ info("entityHandle = %08x, keepHandle = %d", entityHandle, keepHandle); sessionDAA = tpm_get_daa_slot(entityHandle); if (sessionDAA == NULL) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else if (sessionDAA->type != TPM_ST_INVALID) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else { if (HANDLE_TO_RT(entityHandle) != TPM_RT_DAA_TPM) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_daa_session(); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)]; } else *handle = entityHandle; } /* reload resource */ tpmData.stany.data.currentDAA = *handle; info("stany.data.currentDAA := %.8x", *handle); memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA)); memcpy(sessionDAA, &context.internalData.sessionDAA, context.internalSize); } else { /* check contextNonce */ if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, sizeof(TPM_NONCE)) != 0) { tpm_free(context_buf); return TPM_BADCONTEXT; } if (context.internalData.session.type == TPM_ST_OSAP && tpm_get_key(context.internalData.session.handle) == NULL) { tpm_free(context_buf); return TPM_RESOURCEMISSING; } /* check context list */ for (i = 0; i < TPM_MAX_SESSION_LIST; i++) if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break; if (i >= TPM_MAX_SESSION_LIST) { tpm_free(context_buf); return TPM_BADCONTEXT; } tpmData.stany.data.contextList[i] = 0; /* check handle */ session = tpm_get_session_slot(entityHandle); if (session == NULL || session->type != TPM_ST_INVALID) { if (keepHandle) { tpm_free(context_buf); return TPM_BAD_HANDLE; } *handle = tpm_get_free_session(context.internalData.session.type); if (*handle == TPM_INVALID_HANDLE) { tpm_free(context_buf); return TPM_RESOURCES; } session = &tpmData.stany.data.sessions[HANDLE_TO_INDEX(*handle)]; } else { *handle = entityHandle; } /* reload resource */ memcpy(session, &context.internalData.session, sizeof(TPM_SESSION_DATA)); } tpm_free(context_buf); return TPM_SUCCESS; }
/*! ****************************************************************************** @Function ReleaseHandle @Description Release a handle that is no longer needed. @Input psBase - Pointer to handle base structure hHandle - Handle to release ppvData - Points to a void data pointer @Output ppvData - Points to a void data pointer @Return PVRSRV_OK or PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR ReleaseHandle(HANDLE_IMPL_BASE *psBase, IMG_HANDLE hHandle, IMG_VOID **ppvData) { IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle); HANDLE_IMPL_DATA *psHandleData; IMG_VOID *pvData; PVR_ASSERT(psBase); /* Check handle index is in range */ if (!INDEX_IS_VALID(psBase, ui32Index)) { PVR_DPF((PVR_DBG_ERROR, "%s: Handle index out of range (%u >= %u)", __FUNCTION__, ui32Index, psBase->ui32TotalHandCount)); return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE; } psHandleData = INDEX_TO_HANDLE_DATA(psBase, ui32Index); pvData = psHandleData->pvData; psHandleData->pvData = IMG_NULL; /* No free list management if purging is enabled */ if (!psBase->bPurgingEnabled) { if (psBase->ui32TotalFreeHandCount == 0) { PVR_ASSERT(psBase->ui32FirstFreeIndex == 0); PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0); psBase->ui32FirstFreeIndex = ui32Index; } else { /* * Put the handle pointer on the end of the the free * handle pointer linked list. */ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0); PVR_ASSERT(INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0); INDEX_TO_HANDLE_DATA(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1; } PVR_ASSERT(psHandleData->ui32NextIndexPlusOne == 0); /* Update the end of the free handle linked list */ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1; } psBase->ui32TotalFreeHandCount++; INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32Index)++; PVR_ASSERT(INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE); #if defined(DEBUG) { IMG_UINT32 ui32BlockedIndex; IMG_UINT32 ui32TotalFreeHandCount = 0; for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE) { ui32TotalFreeHandCount += INDEX_TO_BLOCK_FREE_HAND_COUNT(psBase, ui32BlockedIndex); } PVR_ASSERT(ui32TotalFreeHandCount == psBase->ui32TotalFreeHandCount); } #endif /* defined(DEBUG) */ if (ppvData) { *ppvData = pvData; } #if defined(DEBUG_HANDLEALLOC_KM) PVR_DPF((PVR_DBG_MESSAGE, "Handle release base %p hdl %p", psBase, hHandle)); #endif return PVRSRV_OK; }