From 844c7f1ae7c401414056a2457471a4282ffe8f98 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 31 Mar 2011 04:23:17 +0000 Subject: Add mksyscall tool git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3446 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/tools/Makefile.host | 7 + nuttx/tools/README.txt | 32 +++- nuttx/tools/mksyscall.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 467 insertions(+), 5 deletions(-) create mode 100644 nuttx/tools/mksyscall.c (limited to 'nuttx/tools') diff --git a/nuttx/tools/Makefile.host b/nuttx/tools/Makefile.host index a5a83d4ae..95cf64c68 100644 --- a/nuttx/tools/Makefile.host +++ b/nuttx/tools/Makefile.host @@ -35,12 +35,19 @@ all: mkconfig mksyscall default: mkconfig mksyscall +.PHONY: clean + +# Add CFLAGS=-g on the make command line build debug versions CFLAGS = -O2 -Wall +# mkconfig - Convert a .config file into a C config.h file + mkconfig: mkconfig.c @gcc $(CFLAGS) -o mkconfig mkconfig.c +# mksyscall - Convert a CSV file into syscall stubs and proxies + mksyscall: mksyscall.c @gcc $(CFLAGS) -o mksyscall mksyscall.c diff --git a/nuttx/tools/README.txt b/nuttx/tools/README.txt index 5e7edaf4f..76ec3a66f 100755 --- a/nuttx/tools/README.txt +++ b/nuttx/tools/README.txt @@ -31,17 +31,39 @@ mkconfig.c into include/nuttx/config.h. config.h is a another version of the NuttX configuration that can be included by C files. +mksyscall.c + + This is C file that is used to build mksyscall program. The mksyscall + program is used during the initial NuttX build by the logic in the top- + level syscall/ directory. + + If you build NuttX as a separately compiled, monolithic kernel and separate + applications, then there is a syscall layer that is used to get from the + user application space to the NuttX kernel space. In the user application + "proxies" for each of the kernel functions are provided. The proxies have + the same function signature as the kernel function, but only execute a + system call. + + Within the kernel, there are "stubs" for each of the system calls. The + stubs receive the marshalled system call data, and perform the actually + kernel function call (in kernel-mode) on behalf of the proxy function. + + Information about the stubs and proxies is maintained in a comma separated + value (CSV) file in the syscall/ directory. The mksyscall program will + accept this CVS file as input and generate all of the required proxy or + stub files as output. See syscall/README.txt for additonal information. + +Makefile.host + + This is the makefile that is used to make the mkconfig program from + the mkconfig.c C file or the mksyscall program from the mksyscall.c file. + mkromfsimg.sh This script may be used to automate the generate of a ROMFS file system image. It accepts an rcS script "template" and generates and image that may be mounted under /etc in the NuttX pseudo file system. -Makefile.mkconfig - - This is the makefile that is used to make the mkconfig program from - the mkconfig.c C file. - mkdeps.sh mknulldeps.sh diff --git a/nuttx/tools/mksyscall.c b/nuttx/tools/mksyscall.c new file mode 100644 index 000000000..10eb65ac3 --- /dev/null +++ b/nuttx/tools/mksyscall.c @@ -0,0 +1,433 @@ +/**************************************************************************** + * tools/mksyscall.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define LINESIZE (PATH_MAX > 256 ? PATH_MAX : 256) + +#define MAX_FIELDS 16 +#define MAX_PARMSIZE 128 +#define NAME_INDEX 0 +#define HEADER_INDEX 1 +#define RETTYPE_INDEX 2 +#define PARM1_INDEX 3 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool g_debug; +static char g_line[LINESIZE+1]; +static char g_parm[MAX_FIELDS][MAX_PARMSIZE]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static char *skip_space(char *ptr) +{ + while (*ptr && isspace(*ptr)) ptr++; + return ptr; +} + +static char *read_line(FILE *stream) +{ + char *ptr; + + for (;;) + { + g_line[LINESIZE] = '\0'; + if (!fgets(g_line, LINESIZE, stream)) + { + return NULL; + } + else + { + if (g_debug) + { + printf("Line: %s\n", g_line); + } + + ptr = skip_space(g_line); + if (*ptr && *ptr != '#' && *ptr != '\n') + { + return ptr; + } + } + } +} + +static char *copy_parm(char *src, char *dest) +{ + char *start = src; + int i; + + for (i = 0; i < MAX_PARMSIZE; i++) + { + if (*src == '"') + { + *dest = '\0'; + return src; + } + else if (*src == '\n' || *src == '\0') + { + fprintf(stderr, "Unexpected end of line: \"%s\"\n", start); + exit(4); + } + else + { + *dest++ = *src++; + } + } + + fprintf(stderr, "Parameter too long: \"%s\"\n", start); + exit(3); +} + +static char *find_parm(char *ptr) +{ + char *start = ptr; + + if (*ptr != '"') + { + fprintf(stderr, "I'm confused: \"%s\"\n", start); + exit(5); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr == '\n' || *ptr == '\0') + { + return NULL; + } + else if (*ptr != ',') + { + fprintf(stderr, "Expected ',': \"%s\"\n", start); + exit(6); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr != '"') + { + fprintf(stderr, "Expected \": \"%s\"\n", start); + exit(7); + } + ptr++; + + return ptr; +} + +static int parse_csvline(char *ptr) +{ + int nparms; + int i; + + /* Format "arg1","arg2","arg3",... Spaces will be tolerated outside of the + * quotes. Any initial spaces have already been skipped so the first thing + * should be '"'. + */ + + if (*ptr != '"') + { + fprintf(stderr, "Bad line: \"%s\"\n", g_line); + exit(2); + } + + ptr++; + nparms = 0; + + do + { + ptr = copy_parm(ptr, &g_parm[nparms][0]); + nparms++; + ptr = find_parm(ptr); + } + while (ptr); + + if (g_debug) + { + printf("Parameters: %d\n", nparms); + for (i = 0; i < nparms; i++) + { + printf(" Parm%d: \"%s\"\n", i+1, g_parm[i]); + } + } + return nparms; +} + +static FILE *open_proxy(void) +{ + char filename[MAX_PARMSIZE+4]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+3, "%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+3] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(10); + } + return stream; +} + +static void generate_proxy(int nparms) +{ + FILE *stream = open_proxy(); + int i; + + fprintf(stream, "/* Auto-generated %s proxy file -- do not edit */\n\n", g_parm[NAME_INDEX]); + fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]); + + fprintf(stream, "%s %s(", g_parm[RETTYPE_INDEX], g_parm[NAME_INDEX]); + + if (nparms <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", %s parm%d", g_parm[PARM1_INDEX+i], i+1); + } + else + { + fprintf(stream, "%s parm%d", g_parm[PARM1_INDEX+i], i+1); + } + } + } + + fprintf(stream, ")\n{\n"); + fprintf(stream, " return (%s)sys_call%d(", g_parm[RETTYPE_INDEX], nparms); + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", (uintptr_t)parm%d", i+1); + } + else + { + fprintf(stream, "(uintptr_t)parm%d", i+1); + } + } + fprintf(stream, ");\n}\n"); + fclose(stream); +} + +static FILE *open_stub(void) +{ + char filename[MAX_PARMSIZE+8]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+7, "STUB_%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+7] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(9); + } + return stream; +} + +static void generate_stub(int nparms) +{ + FILE *stream = open_stub(); + int i; + + fprintf(stream, "/* Auto-generated %s stub file -- do not edit */\n\n", g_parm[0]); + fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]); + fprintf(stream, "uintptr_t STUB_%s(", g_parm[NAME_INDEX]); + + if (nparms <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", uintptr_t parm%d", i+1); + } + else + { + fprintf(stream, "uintptr_t parm%d", i+1); + } + } + } + + fprintf(stream, ")\n{\n"); + fprintf(stream, " return (uintptr_t)%s(", g_parm[NAME_INDEX]); + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", (%s)parm%d", g_parm[PARM1_INDEX+i], i+1); + } + else + { + fprintf(stream, "(%s)parm%d", g_parm[PARM1_INDEX+i], i+1); + } + } + fprintf(stream, ");\n}\n"); + fclose(stream); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s [-p|s] \n", progname); + exit(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + char *csvpath; + bool proxies = false; + FILE *stream; + char *ptr; + int ch; + + /* Parse command line options */ + + g_debug = false; + + while ((ch = getopt(argc, argv, ":dps")) > 0) + { + switch (ch) + { + case 'd' : + g_debug = true; + break; + + case 'p' : + proxies = true; + break; + + case 's' : + proxies = false; + break; + + case '?' : + fprintf(stderr, "Unrecognized option: %c\n", optopt); + show_usage(argv[0]); + + case ':' : + fprintf(stderr, "Missing option argument, option: %c\n", optopt); + show_usage(argv[0]); + + break; + fprintf(stderr, "Unexpected option: %c\n", ch); + show_usage(argv[0]); + } + } + + if (optind >= argc) + { + fprintf(stderr, "Missing \n"); + show_usage(argv[0]); + } + + csvpath = argv[optind]; + if (++optind < argc) + { + fprintf(stderr, "Unexpected garbage at the end of the line\n"); + show_usage(argv[0]); + } + + /* Open the CSV file */ + + stream= fopen(csvpath, "r"); + if (!stream) + { + fprintf(stderr, "open %s failed: %s\n", csvpath, strerror(errno)); + exit(3); + } + + /* Process each line in the CVS file */ + + while ((ptr = read_line(stream)) != NULL) + { + /* Parse the line from the CVS file */ + + int nargs = parse_csvline(ptr); + if (nargs < 3) + { + fprintf(stderr, "Only %d arguments found: %s\n", nargs, g_line); + exit(8); + } + + if (proxies) + { + generate_proxy(nargs-3); + } + else + { + generate_stub(nargs-3); + } + } + + /* Close the CSV file */ + + fclose(stream); + return 0; +} -- cgit v1.2.3