static PARSER_CONTEXT * parser_init_guts(u64 addr, u32 bytes, BOOL isLocal, BOOL hasStandardPayloadHeader, BOOL *tryAgain) { int allocbytes = sizeof(PARSER_CONTEXT) + bytes; PARSER_CONTEXT *rc = NULL; PARSER_CONTEXT *ctx = NULL; struct memregion *rgn = NULL; struct spar_controlvm_parameters_header *phdr = NULL; if (tryAgain) *tryAgain = FALSE; if (!hasStandardPayloadHeader) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated */ allocbytes++; if ((Controlvm_Payload_Bytes_Buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)", __func__, __FILE__, __LINE__, allocbytes, MAX_CONTROLVM_PAYLOAD_BYTES); if (tryAgain) *tryAgain = TRUE; rc = NULL; goto Away; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (ctx == NULL) { ERRDRV("%s (%s:%d) - failed to allocate %d bytes", __func__, __FILE__, __LINE__, allocbytes); if (tryAgain) *tryAgain = TRUE; rc = NULL; goto Away; } ctx->allocbytes = allocbytes; ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; ctx->byte_stream = FALSE; if (isLocal) { void *p; if (addr > virt_to_phys(high_memory - 1)) { ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)", __func__, (unsigned long long) addr, (ulong) bytes); rc = NULL; goto Away; } p = __va((ulong) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); if (!rgn) { rc = NULL; goto Away; } if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { rc = NULL; goto Away; } } if (!hasStandardPayloadHeader) { ctx->byte_stream = TRUE; rc = ctx; goto Away; } phdr = (struct spar_controlvm_parameters_header *)(ctx->data); if (phdr->total_length != bytes) { ERRDRV("%s - bad total length %lu (should be %lu)", __func__, (ulong) (phdr->total_length), (ulong) (bytes)); rc = NULL; goto Away; } if (phdr->total_length < phdr->header_length) { ERRDRV("%s - total length < header length (%lu < %lu)", __func__, (ulong) (phdr->total_length), (ulong) (phdr->header_length)); rc = NULL; goto Away; } if (phdr->header_length < sizeof(struct spar_controlvm_parameters_header)) { ERRDRV("%s - header is too small (%lu < %lu)", __func__, (ulong) (phdr->header_length), (ulong)(sizeof( struct spar_controlvm_parameters_header))); rc = NULL; goto Away; } rc = ctx; Away: if (rgn) { visor_memregion_destroy(rgn); rgn = NULL; } if (rc) Controlvm_Payload_Bytes_Buffered += ctx->param_bytes; else { if (ctx) { parser_done(ctx); ctx = NULL; } } return rc; }
static struct parser_context * parser_init_guts(u64 addr, u32 bytes, BOOL local, BOOL standard_payload_header, BOOL *retry) { int allocbytes = sizeof(struct parser_context) + bytes; struct parser_context *rc = NULL; struct parser_context *ctx = NULL; struct memregion *rgn = NULL; struct spar_controlvm_parameters_header *phdr = NULL; if (retry) *retry = FALSE; if (!standard_payload_header) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated */ allocbytes++; if ((controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) *retry = TRUE; rc = NULL; goto cleanup; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (!ctx) { if (retry) *retry = TRUE; rc = NULL; goto cleanup; } ctx->allocbytes = allocbytes; ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; ctx->byte_stream = FALSE; if (local) { void *p; if (addr > virt_to_phys(high_memory - 1)) { rc = NULL; goto cleanup; } p = __va((ulong) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); if (!rgn) { rc = NULL; goto cleanup; } if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { rc = NULL; goto cleanup; } } if (!standard_payload_header) { ctx->byte_stream = TRUE; rc = ctx; goto cleanup; } phdr = (struct spar_controlvm_parameters_header *)(ctx->data); if (phdr->total_length != bytes) { rc = NULL; goto cleanup; } if (phdr->total_length < phdr->header_length) { rc = NULL; goto cleanup; } if (phdr->header_length < sizeof(struct spar_controlvm_parameters_header)) { rc = NULL; goto cleanup; } rc = ctx; cleanup: if (rgn) { visor_memregion_destroy(rgn); rgn = NULL; } if (rc) { controlvm_payload_bytes_buffered += ctx->param_bytes; } else { if (ctx) { parser_done(ctx); ctx = NULL; } } return rc; }