3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
19 #include "memregion.h"
20 #include "controlvmchannel.h"
21 #include <linux/ctype.h>
23 #include <linux/uuid.h>
25 #define MYDRVNAME "visorchipset_parser"
26 #define CURRENT_FILE_PC VISOR_CHIPSET_PC_parser_c
28 /* We will refuse to allocate more than this many bytes to copy data from
29 * incoming payloads. This serves as a throttling mechanism.
31 #define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
32 static ulong controlvm_payload_bytes_buffered;
34 struct parser_context {
38 ulong bytes_remaining;
43 static struct parser_context *
44 parser_init_guts(u64 addr, u32 bytes, BOOL local,
45 BOOL standard_payload_header, BOOL *retry)
47 int allocbytes = sizeof(struct parser_context) + bytes;
48 struct parser_context *rc = NULL;
49 struct parser_context *ctx = NULL;
50 struct memregion *rgn = NULL;
51 struct spar_controlvm_parameters_header *phdr = NULL;
55 if (!standard_payload_header)
56 /* alloc and 0 extra byte to ensure payload is
60 if ((controlvm_payload_bytes_buffered + bytes)
61 > MAX_CONTROLVM_PAYLOAD_BYTES) {
67 ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY);
75 ctx->allocbytes = allocbytes;
76 ctx->param_bytes = bytes;
78 ctx->bytes_remaining = 0;
79 ctx->byte_stream = FALSE;
83 if (addr > virt_to_phys(high_memory - 1)) {
87 p = __va((ulong) (addr));
88 memcpy(ctx->data, p, bytes);
90 rgn = visor_memregion_create(addr, bytes);
95 if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) {
100 if (!standard_payload_header) {
101 ctx->byte_stream = TRUE;
105 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
106 if (phdr->total_length != bytes) {
110 if (phdr->total_length < phdr->header_length) {
114 if (phdr->header_length <
115 sizeof(struct spar_controlvm_parameters_header)) {
123 visor_memregion_destroy(rgn);
127 controlvm_payload_bytes_buffered += ctx->param_bytes;
137 struct parser_context *
138 parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry)
140 return parser_init_guts(addr, bytes, local, TRUE, retry);
143 /* Call this instead of parser_init() if the payload area consists of just
144 * a sequence of bytes, rather than a struct spar_controlvm_parameters_header
145 * structures. Afterwards, you can call parser_simpleString_get() or
146 * parser_byteStream_get() to obtain the data.
148 struct parser_context *
149 parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, BOOL *retry)
151 return parser_init_guts(addr, bytes, local, FALSE, retry);
154 /* Obtain '\0'-terminated copy of string in payload area.
157 parser_simpleString_get(struct parser_context *ctx)
159 if (!ctx->byte_stream)
161 return ctx->data; /* note this IS '\0'-terminated, because of
162 * the num of bytes we alloc+clear in
163 * parser_init_byteStream() */
166 /* Obtain a copy of the buffer in the payload area.
168 void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes)
170 if (!ctx->byte_stream)
173 *nbytes = ctx->param_bytes;
174 return (void *)ctx->data;
178 parser_id_get(struct parser_context *ctx)
180 struct spar_controlvm_parameters_header *phdr = NULL;
184 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
189 parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string)
191 struct spar_controlvm_parameters_header *phdr = NULL;
195 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
196 switch (which_string) {
197 case PARSERSTRING_INITIATOR:
198 ctx->curr = ctx->data + phdr->initiator_offset;
199 ctx->bytes_remaining = phdr->initiator_length;
201 case PARSERSTRING_TARGET:
202 ctx->curr = ctx->data + phdr->target_offset;
203 ctx->bytes_remaining = phdr->target_length;
205 case PARSERSTRING_CONNECTION:
206 ctx->curr = ctx->data + phdr->connection_offset;
207 ctx->bytes_remaining = phdr->connection_length;
209 case PARSERSTRING_NAME:
210 ctx->curr = ctx->data + phdr->name_offset;
211 ctx->bytes_remaining = phdr->name_length;
222 parser_done(struct parser_context *ctx)
226 controlvm_payload_bytes_buffered -= ctx->param_bytes;
230 /** Return length of string not counting trailing spaces. */
232 string_length_no_trail(char *s, int len)
244 /** Grab the next name and value out of the parameter buffer.
245 * The entire parameter buffer looks like this:
250 * If successful, the next <name> value is returned within the supplied
251 * <nam> buffer (the value is always upper-cased), and the corresponding
252 * <value> is returned within a kmalloc()ed buffer, whose pointer is
253 * provided as the return value of this function.
254 * (The total number of bytes allocated is strlen(<value>)+1.)
256 * NULL is returned to indicate failure, which can occur for several reasons:
257 * - all <name>=<value> pairs have already been processed
259 * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
260 * the confines of the parameter buffer)
261 * - the <nam> buffer is not large enough to hold the <name> of the next
265 parser_param_get(struct parser_context *ctx, char *nam, int namesize)
267 u8 *pscan, *pnam = nam;
269 int value_length = -1, orig_value_length = -1;
272 int closing_quote = 0;
277 nscan = ctx->bytes_remaining;
281 /* This is the normal return point after you have processed
282 * all of the <name>=<value> pairs in a syntactically-valid
287 /* skip whitespace */
288 while (isspace(*pscan)) {
295 while (*pscan != ':') {
298 *pnam = toupper(*pscan);
309 nam[string_length_no_trail(nam, strlen(nam))] = '\0';
311 /* point to char immediately after ":" in "<name>:<value>" */
314 /* skip whitespace */
315 while (isspace(*pscan)) {
323 if (*pscan == '\'' || *pscan == '"') {
324 closing_quote = *pscan;
331 /* look for a separator character, terminator character, or
334 for (i = 0, value_length = -1; i < nscan; i++) {
336 if (pscan[i] == '\0')
338 if (pscan[i] == closing_quote) {
343 if (pscan[i] == ',' || pscan[i] == ';'
344 || pscan[i] == '\0') {
349 if (value_length < 0) {
352 value_length = nscan;
354 orig_value_length = value_length;
355 if (closing_quote == 0)
356 value_length = string_length_no_trail(pscan, orig_value_length);
357 value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
360 memcpy(value, pscan, value_length);
361 ((u8 *) (value))[value_length] = '\0';
363 pscan += orig_value_length;
364 nscan -= orig_value_length;
366 /* skip past separator or closing quote */
368 if (*pscan != '\0') {
374 if (closing_quote && (nscan > 0)) {
375 /* we still need to skip around the real separator if present */
376 /* first, skip whitespace */
377 while (isspace(*pscan)) {
384 if (*pscan == ',' || *pscan == ';') {
387 } else if (*pscan != '\0') {
395 ctx->bytes_remaining = nscan;
400 parser_string_get(struct parser_context *ctx)
404 int value_length = -1;
411 nscan = ctx->bytes_remaining;
416 for (i = 0, value_length = -1; i < nscan; i++)
417 if (pscan[i] == '\0') {
421 if (value_length < 0) /* '\0' was not included in the length */
422 value_length = nscan;
423 value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
426 if (value_length > 0)
427 memcpy(value, pscan, value_length);
428 ((u8 *) (value))[value_length] = '\0';