Commit 46168810 authored by Erik Arfvidson's avatar Erik Arfvidson Committed by Greg Kroah-Hartman

staging: unisys: move parser.[ch] functionality into visorchipset

This patch moves includes files and functions from parser.[ch] into
visorchipset.
Signed-off-by: default avatarErik Arfvidson <erik.arfvidson@unisys.com>
Signed-off-by: default avatarBenjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e3420ed6
......@@ -2040,7 +2040,7 @@ visorbus_init(void)
POSTCODE_LINUX_3(DRIVER_ENTRY_PC, rc, POSTCODE_SEVERITY_INFO);
bus_device_info_init(&clientbus_driverinfo,
"clientbus", MYDRVNAME,
"clientbus", "visorbus",
VERSION, NULL);
/* process module options */
......
......@@ -4,7 +4,7 @@
obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset.o
visorchipset-y := visorchipset_main.o parser.o
visorchipset-y := visorchipset_main.o
ccflags-y += -Idrivers/staging/unisys/include
ccflags-y += -Idrivers/staging/unisys/uislib
......
/* parser.c
*
* Copyright (C) 2010 - 2013 UNISYS CORPORATION
* All rights reserved.
*
* 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, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*/
#include "parser.h"
#include "memregion.h"
#include "controlvmchannel.h"
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/uuid.h>
#define MYDRVNAME "visorchipset_parser"
#define CURRENT_FILE_PC VISOR_CHIPSET_PC_parser_c
/* We will refuse to allocate more than this many bytes to copy data from
* incoming payloads. This serves as a throttling mechanism.
*/
#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
static unsigned long controlvm_payload_bytes_buffered;
struct parser_context {
unsigned long allocbytes;
unsigned long param_bytes;
u8 *curr;
unsigned long bytes_remaining;
bool byte_stream;
char data[0];
};
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((unsigned long) (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;
}
struct parser_context *
parser_init(u64 addr, u32 bytes, bool local, bool *retry)
{
return parser_init_guts(addr, bytes, local, true, retry);
}
/* Call this instead of parser_init() if the payload area consists of just
* a sequence of bytes, rather than a struct spar_controlvm_parameters_header
* structures. Afterwards, you can call parser_simpleString_get() or
* parser_byteStream_get() to obtain the data.
*/
struct parser_context *
parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
{
return parser_init_guts(addr, bytes, local, false, retry);
}
/* Obtain '\0'-terminated copy of string in payload area.
*/
char *
parser_simpleString_get(struct parser_context *ctx)
{
if (!ctx->byte_stream)
return NULL;
return ctx->data; /* note this IS '\0'-terminated, because of
* the num of bytes we alloc+clear in
* parser_init_byteStream() */
}
/* Obtain a copy of the buffer in the payload area.
*/
void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes)
{
if (!ctx->byte_stream)
return NULL;
if (nbytes)
*nbytes = ctx->param_bytes;
return (void *)ctx->data;
}
uuid_le
parser_id_get(struct parser_context *ctx)
{
struct spar_controlvm_parameters_header *phdr = NULL;
if (ctx == NULL)
return NULL_UUID_LE;
phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
return phdr->id;
}
void
parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string)
{
struct spar_controlvm_parameters_header *phdr = NULL;
if (ctx == NULL)
goto Away;
phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
switch (which_string) {
case PARSERSTRING_INITIATOR:
ctx->curr = ctx->data + phdr->initiator_offset;
ctx->bytes_remaining = phdr->initiator_length;
break;
case PARSERSTRING_TARGET:
ctx->curr = ctx->data + phdr->target_offset;
ctx->bytes_remaining = phdr->target_length;
break;
case PARSERSTRING_CONNECTION:
ctx->curr = ctx->data + phdr->connection_offset;
ctx->bytes_remaining = phdr->connection_length;
break;
case PARSERSTRING_NAME:
ctx->curr = ctx->data + phdr->name_offset;
ctx->bytes_remaining = phdr->name_length;
break;
default:
break;
}
Away:
return;
}
void
parser_done(struct parser_context *ctx)
{
if (!ctx)
return;
controlvm_payload_bytes_buffered -= ctx->param_bytes;
kfree(ctx);
}
/** Return length of string not counting trailing spaces. */
static int
string_length_no_trail(char *s, int len)
{
int i = len - 1;
while (i >= 0) {
if (!isspace(s[i]))
return i + 1;
i--;
}
return 0;
}
/** Grab the next name and value out of the parameter buffer.
* The entire parameter buffer looks like this:
* <name>=<value>\0
* <name>=<value>\0
* ...
* \0
* If successful, the next <name> value is returned within the supplied
* <nam> buffer (the value is always upper-cased), and the corresponding
* <value> is returned within a kmalloc()ed buffer, whose pointer is
* provided as the return value of this function.
* (The total number of bytes allocated is strlen(<value>)+1.)
*
* NULL is returned to indicate failure, which can occur for several reasons:
* - all <name>=<value> pairs have already been processed
* - bad parameter
* - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
* the confines of the parameter buffer)
* - the <nam> buffer is not large enough to hold the <name> of the next
* parameter
*/
void *
parser_param_get(struct parser_context *ctx, char *nam, int namesize)
{
u8 *pscan, *pnam = nam;
unsigned long nscan;
int value_length = -1, orig_value_length = -1;
void *value = NULL;
int i;
int closing_quote = 0;
if (!ctx)
return NULL;
pscan = ctx->curr;
nscan = ctx->bytes_remaining;
if (nscan == 0)
return NULL;
if (*pscan == '\0')
/* This is the normal return point after you have processed
* all of the <name>=<value> pairs in a syntactically-valid
* parameter buffer.
*/
return NULL;
/* skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
while (*pscan != ':') {
if (namesize <= 0)
return NULL;
*pnam = toupper(*pscan);
pnam++;
namesize--;
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
if (namesize <= 0)
return NULL;
*pnam = '\0';
nam[string_length_no_trail(nam, strlen(nam))] = '\0';
/* point to char immediately after ":" in "<name>:<value>" */
pscan++;
nscan--;
/* skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
if (nscan == 0)
return NULL;
if (*pscan == '\'' || *pscan == '"') {
closing_quote = *pscan;
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
/* look for a separator character, terminator character, or
* end of data
*/
for (i = 0, value_length = -1; i < nscan; i++) {
if (closing_quote) {
if (pscan[i] == '\0')
return NULL;
if (pscan[i] == closing_quote) {
value_length = i;
break;
}
} else
if (pscan[i] == ',' || pscan[i] == ';'
|| pscan[i] == '\0') {
value_length = i;
break;
}
}
if (value_length < 0) {
if (closing_quote)
return NULL;
value_length = nscan;
}
orig_value_length = value_length;
if (closing_quote == 0)
value_length = string_length_no_trail(pscan, orig_value_length);
value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
if (value == NULL)
return NULL;
memcpy(value, pscan, value_length);
((u8 *) (value))[value_length] = '\0';
pscan += orig_value_length;
nscan -= orig_value_length;
/* skip past separator or closing quote */
if (nscan > 0) {
if (*pscan != '\0') {
pscan++;
nscan--;
}
}
if (closing_quote && (nscan > 0)) {
/* we still need to skip around the real separator if present */
/* first, skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
break;
}
if (nscan > 0) {
if (*pscan == ',' || *pscan == ';') {
pscan++;
nscan--;
} else if (*pscan != '\0') {
kfree(value);
value = NULL;
return NULL;
}
}
}
ctx->curr = pscan;
ctx->bytes_remaining = nscan;
return value;
}
void *
parser_string_get(struct parser_context *ctx)
{
u8 *pscan;
unsigned long nscan;
int value_length = -1;
void *value = NULL;
int i;
if (!ctx)
return NULL;
pscan = ctx->curr;
nscan = ctx->bytes_remaining;
if (nscan == 0)
return NULL;
if (!pscan)
return NULL;
for (i = 0, value_length = -1; i < nscan; i++)
if (pscan[i] == '\0') {
value_length = i;
break;
}
if (value_length < 0) /* '\0' was not included in the length */
value_length = nscan;
value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
if (value == NULL)
return NULL;
if (value_length > 0)
memcpy(value, pscan, value_length);
((u8 *) (value))[value_length] = '\0';
return value;
}
/* parser.h
*
* Copyright (C) 2010 - 2013 UNISYS CORPORATION
* All rights reserved.
*
* 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, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*/
#ifndef __PARSER_H__
#define __PARSER_H__
#include <linux/uuid.h>
#include "channel.h"
typedef enum {
PARSERSTRING_INITIATOR,
PARSERSTRING_TARGET,
PARSERSTRING_CONNECTION,
PARSERSTRING_NAME,
} PARSER_WHICH_STRING;
struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal,
bool *tryAgain);
struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local,
bool *retry);
void parser_param_start(struct parser_context *ctx,
PARSER_WHICH_STRING which_string);
void *parser_param_get(struct parser_context *ctx, char *nam, int namesize);
void *parser_string_get(struct parser_context *ctx);
uuid_le parser_id_get(struct parser_context *ctx);
char *parser_simpleString_get(struct parser_context *ctx);
void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes);
void parser_done(struct parser_context *ctx);
#endif
......@@ -22,17 +22,37 @@
#include "channel.h"
#include "controlvmchannel.h"
#include "parser.h"
#include "procobjecttree.h"
#include "vbusdeviceinfo.h"
#include "vbushelper.h"
#define MYDRVNAME "visorchipset"
#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000
/** Describes the state from the perspective of which controlvm messages have
* been received for a bus or device.
*/
enum PARSER_WHICH_STRING {
PARSERSTRING_INITIATOR,
PARSERSTRING_TARGET,
PARSERSTRING_CONNECTION,
PARSERSTRING_NAME,
};
struct visorchannel;
struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal,
bool *tryAgain);
struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local,
bool *retry);
void parser_param_start(struct parser_context *ctx,
PARSER_WHICH_STRING which_string);
void *parser_param_get(struct parser_context *ctx, char *nam, int namesize);
void *parser_string_get(struct parser_context *ctx);
uuid_le parser_id_get(struct parser_context *ctx);
char *parser_simpleString_get(struct parser_context *ctx);
void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes);
void parser_done(struct parser_context *ctx);
struct visorchipset_state {
u32 created:1;
u32 attached:1;
......
......@@ -15,16 +15,19 @@
* details.
*/
#include "memregion.h"
#include "controlvmchannel.h"
#include "version.h"
#include "procobjecttree.h"
#include "visorbus.h"
#include "periodic_work.h"
#include "parser.h"
#include "uisutils.h"
#include "controlvmcompletionstatus.h"
#include "guestlinuxdebug.h"
#include "visorchipset.h"
#include <linux/ctype.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/nls.h>
......@@ -45,6 +48,7 @@
#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
/*
* Module parameters
*/
......@@ -57,6 +61,7 @@ static int visorchipset_clientregwait = 1; /* default is on */
static int visorchipset_testteardown;
static int visorchipset_disable_controlvm;
static int visorchipset_holdchipsetready;
static unsigned long controlvm_payload_bytes_buffered;
static int
visorchipset_open(struct inode *inode, struct file *file)
......@@ -89,6 +94,15 @@ static int clientregistered;
#define MAX_CHIPSET_EVENTS 2
static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 };
struct parser_context {
unsigned long allocbytes;
unsigned long param_bytes;
u8 *curr;
unsigned long bytes_remaining;
bool byte_stream;
char data[0];
};
static struct delayed_work periodic_controlvm_work;
static struct workqueue_struct *periodic_controlvm_workqueue;
static DEFINE_SEMAPHORE(notifier_lock);
......@@ -367,6 +381,397 @@ static void controlvm_respond_physdev_changestate(
struct controlvm_message_header *msg_hdr, int response,
struct spar_segment_state state);
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((unsigned long) (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;
}
struct parser_context *
parser_init(u64 addr, u32 bytes, bool local, bool *retry)
{
return parser_init_guts(addr, bytes, local, true, retry);
}
/* Call this instead of parser_init() if the payload area consists of just
* a sequence of bytes, rather than a struct spar_controlvm_parameters_header
* structures. Afterwards, you can call parser_simpleString_get() or
* parser_byteStream_get() to obtain the data.
*/
struct parser_context *
parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
{
return parser_init_guts(addr, bytes, local, false, retry);
}
/* Obtain '\0'-terminated copy of string in payload area.
*/
char *
parser_simpleString_get(struct parser_context *ctx)
{
if (!ctx->byte_stream)
return NULL;
return ctx->data; /* note this IS '\0'-terminated, because of
* the num of bytes we alloc+clear in
* parser_init_byteStream() */
}
/* Obtain a copy of the buffer in the payload area.
*/
void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes)
{
if (!ctx->byte_stream)
return NULL;
if (nbytes)
*nbytes = ctx->param_bytes;
return (void *)ctx->data;
}
uuid_le
parser_id_get(struct parser_context *ctx)
{
struct spar_controlvm_parameters_header *phdr = NULL;
if (ctx == NULL)
return NULL_UUID_LE;
phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
return phdr->id;
}
void
parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string)
{
struct spar_controlvm_parameters_header *phdr = NULL;
if (ctx == NULL)
goto Away;
phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
switch (which_string) {
case PARSERSTRING_INITIATOR:
ctx->curr = ctx->data + phdr->initiator_offset;
ctx->bytes_remaining = phdr->initiator_length;
break;
case PARSERSTRING_TARGET:
ctx->curr = ctx->data + phdr->target_offset;
ctx->bytes_remaining = phdr->target_length;
break;
case PARSERSTRING_CONNECTION:
ctx->curr = ctx->data + phdr->connection_offset;
ctx->bytes_remaining = phdr->connection_length;
break;
case PARSERSTRING_NAME:
ctx->curr = ctx->data + phdr->name_offset;
ctx->bytes_remaining = phdr->name_length;
break;
default:
break;
}
Away:
return;
}
void
parser_done(struct parser_context *ctx)
{
if (!ctx)
return;
controlvm_payload_bytes_buffered -= ctx->param_bytes;
kfree(ctx);
}
/** Return length of string not counting trailing spaces. */
static int
string_length_no_trail(char *s, int len)
{
int i = len - 1;
while (i >= 0) {
if (!isspace(s[i]))
return i + 1;
i--;
}
return 0;
}
/** Grab the next name and value out of the parameter buffer.
* The entire parameter buffer looks like this:
* <name>=<value>\0
* <name>=<value>\0
* ...
* \0
* If successful, the next <name> value is returned within the supplied
* <nam> buffer (the value is always upper-cased), and the corresponding
* <value> is returned within a kmalloc()ed buffer, whose pointer is
* provided as the return value of this function.
* (The total number of bytes allocated is strlen(<value>)+1.)
*
* NULL is returned to indicate failure, which can occur for several reasons:
* - all <name>=<value> pairs have already been processed
* - bad parameter
* - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
* the confines of the parameter buffer)
* - the <nam> buffer is not large enough to hold the <name> of the next
* parameter
*/
void *
parser_param_get(struct parser_context *ctx, char *nam, int namesize)
{
u8 *pscan, *pnam = nam;
unsigned long nscan;
int value_length = -1, orig_value_length = -1;
void *value = NULL;
int i;
int closing_quote = 0;
if (!ctx)
return NULL;
pscan = ctx->curr;
nscan = ctx->bytes_remaining;
if (nscan == 0)
return NULL;
if (*pscan == '\0')
/* This is the normal return point after you have processed
* all of the <name>=<value> pairs in a syntactically-valid
* parameter buffer.
*/
return NULL;
/* skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
while (*pscan != ':') {
if (namesize <= 0)
return NULL;
*pnam = toupper(*pscan);
pnam++;
namesize--;
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
if (namesize <= 0)
return NULL;
*pnam = '\0';
nam[string_length_no_trail(nam, strlen(nam))] = '\0';
/* point to char immediately after ":" in "<name>:<value>" */
pscan++;
nscan--;
/* skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
if (nscan == 0)
return NULL;
if (*pscan == '\'' || *pscan == '"') {
closing_quote = *pscan;
pscan++;
nscan--;
if (nscan == 0)
return NULL;
}
/* look for a separator character, terminator character, or
* end of data
*/
for (i = 0, value_length = -1; i < nscan; i++) {
if (closing_quote) {
if (pscan[i] == '\0')
return NULL;
if (pscan[i] == closing_quote) {
value_length = i;
break;
}
} else
if (pscan[i] == ',' || pscan[i] == ';'
|| pscan[i] == '\0') {
value_length = i;
break;
}
}
if (value_length < 0) {
if (closing_quote)
return NULL;
value_length = nscan;
}
orig_value_length = value_length;
if (closing_quote == 0)
value_length = string_length_no_trail(pscan, orig_value_length);
value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
if (value == NULL)
return NULL;
memcpy(value, pscan, value_length);
((u8 *) (value))[value_length] = '\0';
pscan += orig_value_length;
nscan -= orig_value_length;
/* skip past separator or closing quote */
if (nscan > 0) {
if (*pscan != '\0') {
pscan++;
nscan--;
}
}
if (closing_quote && (nscan > 0)) {
/* we still need to skip around the real separator if present */
/* first, skip whitespace */
while (isspace(*pscan)) {
pscan++;
nscan--;
if (nscan == 0)
break;
}
if (nscan > 0) {
if (*pscan == ',' || *pscan == ';') {
pscan++;
nscan--;
} else if (*pscan != '\0') {
kfree(value);
value = NULL;
return NULL;
}
}
}
ctx->curr = pscan;
ctx->bytes_remaining = nscan;
return value;
}
void *
parser_string_get(struct parser_context *ctx)
{
u8 *pscan;
unsigned long nscan;
int value_length = -1;
void *value = NULL;
int i;
if (!ctx)
return NULL;
pscan = ctx->curr;
nscan = ctx->bytes_remaining;
if (nscan == 0)
return NULL;
if (!pscan)
return NULL;
for (i = 0, value_length = -1; i < nscan; i++)
if (pscan[i] == '\0') {
value_length = i;
break;
}
if (value_length < 0) /* '\0' was not included in the length */
value_length = nscan;
value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
if (value == NULL)
return NULL;
if (value_length > 0)
memcpy(value, pscan, value_length);
((u8 *) (value))[value_length] = '\0';
return value;
}
static ssize_t toolaction_show(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -2274,13 +2679,13 @@ visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
cdev_init(&file_cdev, &visorchipset_fops);
file_cdev.owner = THIS_MODULE;
if (MAJOR(major_dev) == 0) {
rc = alloc_chrdev_region(&major_dev, 0, 1, MYDRVNAME);
rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
/* dynamic major device number registration required */
if (rc < 0)
return rc;
} else {
/* static major device number registration required */
rc = register_chrdev_region(major_dev, 1, MYDRVNAME);
rc = register_chrdev_region(major_dev, 1, "visorchipset");
if (rc < 0)
return rc;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment