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 */
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
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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
#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;
* 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>
#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
/*
* Module parameters
*/
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)
#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);
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)
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;
}