From 4616881022a1ea98738966a6cbefab0ea1c085a9 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Tue, 5 May 2015 18:36:14 -0400 Subject: [PATCH] staging: unisys: move parser.[ch] functionality into visorchipset This patch moves includes files and functions from parser.[ch] into visorchipset. Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorbus/visorbus_main.c | 2 +- drivers/staging/unisys/visorchipset/Makefile | 2 +- drivers/staging/unisys/visorchipset/parser.c | 430 ------------------ drivers/staging/unisys/visorchipset/parser.h | 45 -- .../unisys/visorchipset/visorchipset.h | 24 +- .../unisys/visorchipset/visorchipset_main.c | 411 ++++++++++++++++- 6 files changed, 432 insertions(+), 482 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/parser.c delete mode 100644 drivers/staging/unisys/visorchipset/parser.h diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 13a270dc9b65..d7ca1163c1b1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -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 */ diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile index 6886cb7bd397..e9168d8d69a5 100644 --- a/drivers/staging/unisys/visorchipset/Makefile +++ b/drivers/staging/unisys/visorchipset/Makefile @@ -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 diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c deleted file mode 100644 index 6ca6da8772a8..000000000000 --- a/drivers/staging/unisys/visorchipset/parser.c +++ /dev/null @@ -1,430 +0,0 @@ -/* 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 -#include -#include - -#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: - * =\0 - * =\0 - * ... - * \0 - * If successful, the next value is returned within the supplied - * buffer (the value is always upper-cased), and the corresponding - * 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()+1.) - * - * NULL is returned to indicate failure, which can occur for several reasons: - * - all = 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 buffer is not large enough to hold the 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 = 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 ":" */ - 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; -} diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h deleted file mode 100644 index 3fe17c0c64d2..000000000000 --- a/drivers/staging/unisys/visorchipset/parser.h +++ /dev/null @@ -1,45 +0,0 @@ -/* 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 - -#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 diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 93763ee8258b..264a3e9226ea 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -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; diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index d5bd1a11ad88..dc9f1dc18306 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -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 #include #include #include @@ -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: + * =\0 + * =\0 + * ... + * \0 + * If successful, the next value is returned within the supplied + * buffer (the value is always upper-cased), and the corresponding + * 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()+1.) + * + * NULL is returned to indicate failure, which can occur for several reasons: + * - all = 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 buffer is not large enough to hold the 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 = 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 ":" */ + 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; } -- 2.20.1