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_Tag {
38 ulong bytes_remaining;
43 static PARSER_CONTEXT *
44 parser_init_guts(u64 addr, u32 bytes, BOOL isLocal,
45 BOOL hasStandardPayloadHeader, BOOL *tryAgain)
47 int allocbytes = sizeof(PARSER_CONTEXT) + bytes;
48 PARSER_CONTEXT *rc = NULL;
49 PARSER_CONTEXT *ctx = NULL;
50 MEMREGION *rgn = NULL;
51 struct spar_controlvm_parameters_header *phdr = NULL;
55 if (!hasStandardPayloadHeader)
56 /* alloc and 0 extra byte to ensure payload is
60 if ((Controlvm_Payload_Bytes_Buffered + bytes)
61 > MAX_CONTROLVM_PAYLOAD_BYTES) {
62 ERRDRV("%s (%s:%d) - prevented allocation of %d bytes to prevent exceeding throttling max (%d)",
63 __func__, __FILE__, __LINE__, allocbytes,
64 MAX_CONTROLVM_PAYLOAD_BYTES);
70 ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY);
72 ERRDRV("%s (%s:%d) - failed to allocate %d bytes",
73 __func__, __FILE__, __LINE__, allocbytes);
80 ctx->allocbytes = allocbytes;
81 ctx->param_bytes = bytes;
83 ctx->bytes_remaining = 0;
84 ctx->byte_stream = FALSE;
88 if (addr > virt_to_phys(high_memory - 1)) {
89 ERRDRV("%s - bad local address (0x%-16.16Lx for %lu)",
91 (unsigned long long) addr, (ulong) bytes);
95 p = __va((ulong) (addr));
96 memcpy(ctx->data, p, bytes);
98 rgn = visor_memregion_create(addr, bytes);
103 if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) {
108 if (!hasStandardPayloadHeader) {
109 ctx->byte_stream = TRUE;
113 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
114 if (phdr->total_length != bytes) {
115 ERRDRV("%s - bad total length %lu (should be %lu)",
117 (ulong) (phdr->total_length), (ulong) (bytes));
121 if (phdr->total_length < phdr->header_length) {
122 ERRDRV("%s - total length < header length (%lu < %lu)",
124 (ulong) (phdr->total_length),
125 (ulong) (phdr->header_length));
129 if (phdr->header_length <
130 sizeof(struct spar_controlvm_parameters_header)) {
131 ERRDRV("%s - header is too small (%lu < %lu)",
133 (ulong) (phdr->header_length),
135 struct spar_controlvm_parameters_header)));
143 visor_memregion_destroy(rgn);
147 Controlvm_Payload_Bytes_Buffered += ctx->param_bytes;
158 parser_init(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain)
160 return parser_init_guts(addr, bytes, isLocal, TRUE, tryAgain);
163 /* Call this instead of parser_init() if the payload area consists of just
164 * a sequence of bytes, rather than a struct spar_controlvm_parameters_header
165 * structures. Afterwards, you can call parser_simpleString_get() or
166 * parser_byteStream_get() to obtain the data.
169 parser_init_byteStream(u64 addr, u32 bytes, BOOL isLocal, BOOL *tryAgain)
171 return parser_init_guts(addr, bytes, isLocal, FALSE, tryAgain);
174 /* Obtain '\0'-terminated copy of string in payload area.
177 parser_simpleString_get(PARSER_CONTEXT *ctx)
179 if (!ctx->byte_stream)
181 return ctx->data; /* note this IS '\0'-terminated, because of
182 * the num of bytes we alloc+clear in
183 * parser_init_byteStream() */
186 /* Obtain a copy of the buffer in the payload area.
189 parser_byteStream_get(PARSER_CONTEXT *ctx, ulong *nbytes)
191 if (!ctx->byte_stream)
194 *nbytes = ctx->param_bytes;
195 return (void *) ctx->data;
199 parser_id_get(PARSER_CONTEXT *ctx)
201 struct spar_controlvm_parameters_header *phdr = NULL;
204 ERRDRV("%s (%s:%d) - no context",
205 __func__, __FILE__, __LINE__);
208 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
213 parser_param_start(PARSER_CONTEXT *ctx, PARSER_WHICH_STRING which_string)
215 struct spar_controlvm_parameters_header *phdr = NULL;
218 ERRDRV("%s (%s:%d) - no context",
219 __func__, __FILE__, __LINE__);
222 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
223 switch (which_string) {
224 case PARSERSTRING_INITIATOR:
225 ctx->curr = ctx->data + phdr->initiator_offset;
226 ctx->bytes_remaining = phdr->initiator_length;
228 case PARSERSTRING_TARGET:
229 ctx->curr = ctx->data + phdr->target_offset;
230 ctx->bytes_remaining = phdr->target_length;
232 case PARSERSTRING_CONNECTION:
233 ctx->curr = ctx->data + phdr->connection_offset;
234 ctx->bytes_remaining = phdr->connection_length;
236 case PARSERSTRING_NAME:
237 ctx->curr = ctx->data + phdr->name_offset;
238 ctx->bytes_remaining = phdr->name_length;
241 ERRDRV("%s - bad which_string %d", __func__, which_string);
250 parser_done(PARSER_CONTEXT *ctx)
254 Controlvm_Payload_Bytes_Buffered -= ctx->param_bytes;
258 /** Return length of string not counting trailing spaces. */
260 string_length_no_trail(char *s, int len)
272 /** Grab the next name and value out of the parameter buffer.
273 * The entire parameter buffer looks like this:
278 * If successful, the next <name> value is returned within the supplied
279 * <nam> buffer (the value is always upper-cased), and the corresponding
280 * <value> is returned within a kmalloc()ed buffer, whose pointer is
281 * provided as the return value of this function.
282 * (The total number of bytes allocated is strlen(<value>)+1.)
284 * NULL is returned to indicate failure, which can occur for several reasons:
285 * - all <name>=<value> pairs have already been processed
287 * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within
288 * the confines of the parameter buffer)
289 * - the <nam> buffer is not large enough to hold the <name> of the next
293 parser_param_get(PARSER_CONTEXT *ctx, char *nam, int namesize)
295 u8 *pscan, *pnam = nam;
297 int value_length = -1, orig_value_length = -1;
300 int closing_quote = 0;
305 nscan = ctx->bytes_remaining;
309 /* This is the normal return point after you have processed
310 * all of the <name>=<value> pairs in a syntactically-valid
315 /* skip whitespace */
316 while (isspace(*pscan)) {
323 while (*pscan != ':') {
325 ERRDRV("%s - name too big", __func__);
328 *pnam = toupper(*pscan);
334 ERRDRV("%s - unexpected end of input parsing name",
340 ERRDRV("%s - name too big", __func__);
344 nam[string_length_no_trail(nam, strlen(nam))] = '\0';
346 /* point to char immediately after ":" in "<name>:<value>" */
349 /* skip whitespace */
350 while (isspace(*pscan)) {
354 ERRDRV("%s - unexpected end of input looking for value",
360 ERRDRV("%s - unexpected end of input looking for value",
364 if (*pscan == '\'' || *pscan == '"') {
365 closing_quote = *pscan;
369 ERRDRV("%s - unexpected end of input after %c",
370 __func__, closing_quote);
375 /* look for a separator character, terminator character, or
378 for (i = 0, value_length = -1; i < nscan; i++) {
380 if (pscan[i] == '\0') {
381 ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
384 if (pscan[i] == closing_quote) {
389 if (pscan[i] == ',' || pscan[i] == ';'
390 || pscan[i] == '\0') {
395 if (value_length < 0) {
397 ERRDRV("%s - unexpected end of input parsing quoted value", __func__);
400 value_length = nscan;
402 orig_value_length = value_length;
403 if (closing_quote == 0)
404 value_length = string_length_no_trail(pscan, orig_value_length);
405 value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
408 memcpy(value, pscan, value_length);
409 ((u8 *) (value))[value_length] = '\0';
411 pscan += orig_value_length;
412 nscan -= orig_value_length;
414 /* skip past separator or closing quote */
416 if (*pscan != '\0') {
422 if (closing_quote && (nscan > 0)) {
423 /* we still need to skip around the real separator if present */
424 /* first, skip whitespace */
425 while (isspace(*pscan)) {
432 if (*pscan == ',' || *pscan == ';') {
435 } else if (*pscan != '\0') {
436 ERRDRV("%s - missing separator after quoted string", __func__);
444 ctx->bytes_remaining = nscan;
449 parser_string_get(PARSER_CONTEXT *ctx)
453 int value_length = -1;
460 nscan = ctx->bytes_remaining;
465 for (i = 0, value_length = -1; i < nscan; i++)
466 if (pscan[i] == '\0') {
470 if (value_length < 0) /* '\0' was not included in the length */
471 value_length = nscan;
472 value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY);
475 if (value_length > 0)
476 memcpy(value, pscan, value_length);
477 ((u8 *) (value))[value_length] = '\0';