diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1995-05-11 17:39:37 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1995-05-11 17:39:37 +0000 |
commit | ac7d5ef06a6d6e8d84abbd1f0b82162725f98326 (patch) | |
tree | 9304cf759a73f2a1c6fd3191948f00e870af3787 | |
download | rtems-ac7d5ef06a6d6e8d84abbd1f0b82162725f98326.tar.bz2 |
Initial revision
1683 files changed, 189788 insertions, 0 deletions
diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000000..2dcc27f9c5 --- /dev/null +++ b/INSTALL @@ -0,0 +1,56 @@ +# +# $Id$ +# + +NOTE: The string <release> should be replaced with + the appropriate release number of RTEMS. + +This file only discusses the installation of .tgz files. +For more detailed information on the installation of RTEMS, +refer to the Release Notes manual in the file +/pub/rtems/releases/<release>/doc/c_or_ada/relnotes.tgz on +lancelot.gcs.redstone.army.mil. + +UNCOMPRESSING .tgz FILES +=========================== +Many of the files found in this directory and its subdirectories +are gzip'ed, tar archive files. These files have the ".tgz" +extension. They were compressed with gzip version 1.2.4. + +Use a command sequence similar to the following to uncompress each +file: + + gzcat FILE.tgz | tar xvof - + +where FILE.tgz is the file to be installed. This procedure will +extract the files in the archive into the current directory. +All of the .tgz files associated with this release RTEMS will +place their contents in a subdirectory rtems-<release> in the current +directory. + +If you are unsure of what is in an RTEMS archive file, then use +the following command sequence to get a listing of the contents: + + gzcat FILE.tgz | tar tvf - + +NOTES: + +(1) The "-o" option to tar is included on the tar command line + so that the user extracting the tar archive will own the extracted + files. + +(2) gzcat is sometimes installed as zcat. Be warned that on many + (most) UNIX machines, zcat is associated with compress (.Z files). + +(3) If you do not have gzip 1.2.4, it is available from numerous sites + including this one. Other sites include prep.ai.mit.edu and + gatekeeper.dec.com. + +(4) The GNU archive files included in this distribution are packaged + exactly like they are on official GNU ftp sites. When extracting + GNU archives, they will not extract under a rtems-<version> + directory. They will extract themselves under a directory which + is the name and version of the tool in question. For example, + gcc-2.5.8.tgz will extract its contents into the subdirectory + gcc-2.5.8. + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..8bdab676b4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,118 @@ +# +# $Id$ +# + LICENSE INFORMATION + +For the purposes of this document the Real Time Executive for +Missile Systems (RTEMS) is defined to include all source code, +documentation, shell utilities developed by On-Line Applications +Research Corporation (OAR) under contract of the U.S. Army +Missile Command. OAR obtained the copyright for RTEMS and +subsequently assigned ownership of said copyright to the +U.S. Government. As part of this transfer, OAR waived all +claims of ownership for RTEMS. Since OAR no longer makes claims +of ownership of RTEMS, OAR in no event shall be held liable +for damages including any general, special, incidental or +consequential damages arising out of the use or inability +to use the RTEMS software or documentation or of the support +services provided (including but not limited to loss of data or +data being rendered inaccurate or losses sustained by you or +third parties or a failure of the program to operate with any +other programs), even if advised of the possibility of such damages. + +Simply stated any file containing the U.S. Government +copyright notice or relocatables derived from one or more of +these files are covered by this agreement. + +RTEMS may be reproduced by or for the U.S. Government pursuant +to the copyright license under the clause at DFARS 252.227-7013. +The following notice must appear in all copies of RTEMS and its +derivatives: + + COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + On-Line Applications Research Corporation (OAR). + All rights assigned to U.S. Government, 1994. + + This material may be reproduced by or for the U.S. Government + pursuant to the copyright license under the clause at DFARS + 252.227-7013. This notice must appear in all copies of this + material and its derivatives. + +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 and documentation 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. + Redistributions in binary form must contain or make available the + RTEMS source code. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed for the U.S. Government + by On-Line Applications Research Corp. + + 4. Neither the name of the author nor the U.S. Government may be used to + endorse or promote products derived from this software without specific + prior written permission. + + +RTEMS is provided "AS IS" without warranty of any kind, either +expressed or implied, including, but not limited to, the implied +warranties of merchantability, title and fitness for a +particular purpose. The U.S. Government does not warrant that +the RTEMS software or documentation will satisfy your requirements +or that the software and documentation are without defect or error +or that the operation of the software will be uninterrupted. + +The U.S. Government shall in no event shall be held liable for +damages including any general, special, incidental or consequential +damages arising out of the use or inability to use the RTEMS software +or documentation or of the support services provided (including +but not limited to loss of data or data being rendered +inaccurate or losses sustained by you or third parties or a +failure of the program to operate with any other programs), even +if the U.S. Government has been advised of the possibility of such damages. + +The U.S. Government reserves the right to revise this material +and to make changes from time to time in the content hereof without +obligation to notify anyone or any organization of such revision +or changes. + +OAR remains the sole organization authorized by contract to +distribute or provide support and training for the Real-Time +Executive for Military Systems (RTEMS). + +In order to promote future research activities within the U.S. +Government, we request that potential users of RTEMS notify us +as to the systems that RTEMS is being utilized. This will allow +us to publicize our Dual-Use / Reuse capabilities in support of +the current administration's goals. This can be accomplished by +calling the RTEMS phone numbers published in the documentation +or by electronic mail to "rtems@redstone-emh2.army.mil". Your +cooperation is greatly appreciated. Again, thank you for using +RTEMS. + +RTEMS +U.S. ARMY Missile Command +ATTN: AMSMI-RD-GC-S +Redstone Arsenal, AL 35898-5254 +Voice: (205) 842-6906 +FAX: (205) 842-6917 +EMAIL: rtems@redstone.army.mil + + +On-Line Applications Research Corporation. +2227 Drake Avenue SW +Suite 10-F +Huntsville, AL 35805 +(205) 883-0131 + + + + diff --git a/README b/README new file mode 100644 index 0000000000..02931b8bcb --- /dev/null +++ b/README @@ -0,0 +1,93 @@ +# +# $Id$ +# + +Directory Overview +================== + +This is the top level of the RTEMS directory structure. The following +is a description of the files and directories in this directory: + + INSTALL + Rudimentary installation instructions. For more detailed + information please see the Release Notes. The Postscript + version of this manual can be found in the file + c_or_ada/doc/relnotes.tgz. + + LICENSE + Required legalese. + + README + This file. + + c + This directory contains the source code for the C + implementation of RTEMS as well as the test suites, sample + applications, Board Support Packages, Device Drivers, and + support libraries. + + doc + This directory contains the PDL for the RTEMS executive. + +Ada versus C +============ + +There are two implementations of RTEMS in this source tree -- +in Ada and in C. These two implementations are functionally +and structurally equivalent. The C implementation follows +the packaging conventions and hiearchical nature of the Ada +implementation. In addition, a style has been followed which +allows one to easily find the corresponding Ada and C +implementations. + +File names in C and code placement was carefully designed to insure +a close mapping to the Ada implementation. The following file name +extensions are used: + + .adb - Ada body + .ads - Ada specification + .adp - Ada body requiring preprocessing + .inc - include file for .adp files + + .c - C body (non-inlined routines) + .inl - C body (inlined routines) + .h - C specification + +In the executive source, XYZ.c and XYZ.inl correspond directly to a +single XYZ.adb or XYZ.adp file. A .h file corresponds directly to +the .ads file. There are only a handful of .inc files in the +Ada source and these are used to insure that the desired simple +inline textual expansion is performed. This avoids scoping and +calling convention side-effects in carefully constructed tests +which usually test context switch behavior. + +In addition, in Ada code and data name references are always fully +qualified as PACKAGE.NAME. In C, this convention is followed +by having the package name as part of the name itself and using a +capital letter to indicate the presence of a "." level. So we have +PACKAGE.NAME in Ada and _Package_Name in C. The leading "_" in C +is used to avoid naming conflicts between RTEMS and user variables. +By using these conventions, one can easily compare the C and Ada +implementations. + +The most noticeable difference between the C and Ada83 code is +the inability to easily obtain a "typed pointer" in Ada83. +Using the "&" operator in C yields a pointer with a specific type. +The 'Address attribute is the closest feature in Ada83. This +returns a System.Address and this must be coerced via Unchecked_Conversion +into an access type of the desired type. It is easy to view +System.Address as similar to a "void *" in C, but this is not the case. +A "void *" can be assigned to any other pointer type without an +explicit conversion. + +The solution adopted to this problem was to provide two routines for +each access type in the Ada implementation -- one to convert from +System.Address to the access type and another to go the opposite +direction. This results in code which accomplishes the same thing +as the corresponding C but it is easier to get lost in the clutter +of the apparent subprogram invocations than the "less bulky" +C equivalent. + +A related difference is the types which are only in Ada which are used +for pointers to arrays. These types do not exist and are not needed +in the C implementation. diff --git a/SUPPORT b/SUPPORT new file mode 100644 index 0000000000..6d64a4d0e3 --- /dev/null +++ b/SUPPORT @@ -0,0 +1,18 @@ +# +# $Id$ +# + +For support and training contact: + +On-Line Applications Research +2227 Drake Avenue SW Suite 10-F +Huntsville AL 35805 +(205) 883-0131 + +OAR offers support and classes for RTEMS as well as custom +development services such as ports to new processors and +the development of custom board support packages and device +drivers. + +OAR developed RTEMS under contract to the U.S. Army Missile Command. + diff --git a/c/ACKNOWLEDGEMENTS b/c/ACKNOWLEDGEMENTS new file mode 100644 index 0000000000..63438d82ac --- /dev/null +++ b/c/ACKNOWLEDGEMENTS @@ -0,0 +1,51 @@ +# +# $Id$ +# + +RTEMS was developed by On-Line Applications Research (OAR) under +contract to the U.S. Army Missile Command. Other than the +contributions listed in this document, all code and documentation +was developed by OAR for the Army. + +The RTEMS project would like to thank those who have made +contributions to the project. Together we make RTEMS a +much better product. + +The following persons/organizations have made contributions: + ++ Dr. Mikhail (Misha) Savitski (mms@eiscathq.irf.se) of the EISCAT Scientific + Association submitted the BSP and other miscellaneous support for the + Motorola MVME162 (M68040LC CPU) VMEbus single board computer. + ++ Division Inc. of Chapel Hill, NC for sponsoring On-Line Applications + Research to port RTEMS to the Hewlett-Packard PA-RISC architecture (V1.1) + and the addition of HP-UX as a development host. Tony Bennett + (tbennett@divnc.com) was assisted in this effort by Joel Sherrill + (jsherril@redstone.army.mil). Tony also deserves a big pat on the + back for contributing significantly to the overall organization + of the development environment and directory structure. RTEMS + is much easier to build because of Tony. + ++ Greg Allen of Division Inc. of Chapel Hill, NC for + porting RTEMS to HP-UX. This port treats a UNIX computer as simply + another RTEMS target processor. This port can be used to develop + and test code which will ultimately run on the embedded platform. + ++ Doug McBride (mcbride@rodin.colorado.edu) of the Colorado Space Grant + College at the University of Colorado at Boulder submitted the BSP + for the Motorola IDP board (M68EC040 CPU) single board computer. The + BSP leverages heavily off of the existing RTEMS BSP framework, the + examples in the back of the IDP user's manual, and the libgloss example + support for the IDP board from the newlib/libgloss distribution. + +Finally, the RTEMS project would like to thank those who have contributed +to the other free software efforts which RTEMS utilizes. The primary RTEMS +development environment is from the Free Software Foundation (the GNU +project). The "newlib" C library was put together by Cygnus and is +a collaboration of the efforts of numerous individuals and organizations. + +We would like to see your name here. BSPs and ports are always welcome. +Useful libraries which support RTEMS applications are also an important +part of providing a strong foundation for the development of real-time +embedded applications and are welcome as submission. + diff --git a/c/PROBLEMS b/c/PROBLEMS new file mode 100644 index 0000000000..b8e75dc58b --- /dev/null +++ b/c/PROBLEMS @@ -0,0 +1,39 @@ +# +# $Id$ +# + +This is the list of outstanding problems in this release. + +1. The m68000 support is not complete. Someone with target hardware + needs to complete the missing gaps. Look for ifdef's based on the + M68K_* macros defined in c/make/cpu/m68k.cfg. Most of the code + is present but none of it is tested. An attempt was made to insert + "#warnings" preprocessor directives in the appropriate places. + So these are a good starting spot. + +2. The only i960 family member tested is the CA. No support for the + floating point support found in other family members is present. + This also implies that RTEMS may "think" of something as generic + across the i960 family when in fact it is specific to the CA. + +3. The __read() system call in all of the BSPs using single + character input/output needs to be smarter. The following + issues need to be addressed: + + + echoing of characters on input + + CR/NL echoing + + backspaces + + tabs + +4. Solaris 2.3 port notes: + + + Some of the tests run correctly when run interactively but + the screen and output do not match when the output is + redirected to a file. + + + sometimes a stray SIGALRM is reported as spfatal completes. + +5. Some of the tests may execute correctly and not produce the exact + ordering of lines in the screen file. This appears to be a combination + of a number of factors including buffering, processor speed, IO + device overhead, and clock interrupt rate. diff --git a/c/README b/c/README new file mode 100644 index 0000000000..99eac9de18 --- /dev/null +++ b/c/README @@ -0,0 +1,45 @@ +# +# $Id$ +# + +This is the top level of the RTEMS directory structure. The following +is a description of the files and directories in this directory: + + LICENSE + Required legalese. + + Makefile + The top-level Make command file used to build the C implementation + of RTEMS. [RTEMS assumes the use of GNU make.] + + Modules + Example Modules command files used to configure the user's environment + for RTEMS. These require the Modules system administration package + available from numerous ftp sites. + + README + This file. + + REQUIRES + A list of the other tools which are assumed to be installed + before RTEMS is built. + + SUPPORT + Information on third-party support for RTEMS. + + build-tools + This directory contains the source for various utilities + needed to build RTEMS. + + make + Make command files "included" from those in the source distribution. + [RTEMS assumes the use of GNU make.] + + patches + This directory contains patches for this release of RTEMS. + + src + This directory contains the source code for the C + implementation of RTEMS as well as the test suites, sample + applications, Board Support Packages, Device Drivers, and + support libraries. diff --git a/c/REQUIRES b/c/REQUIRES new file mode 100644 index 0000000000..196cf5b070 --- /dev/null +++ b/c/REQUIRES @@ -0,0 +1,13 @@ +# +# $Id$ +# + +1. The installation procedure assumes that "gcc" is installed + and is in your path for the installation of local tools. + +2. gcc 2.6.3 with crossgcc patches (ftp.cygnus.com:/pub/embedded) + +3. binutils 2.5.2 + +4. newlib with RTEMS configurations. + diff --git a/c/UPDATE_HELP b/c/UPDATE_HELP new file mode 100644 index 0000000000..cf6feffff0 --- /dev/null +++ b/c/UPDATE_HELP @@ -0,0 +1,17 @@ +# +# $Id$ +# + +In the directory "update_tools", there are a set of tools to aid in +making the application source changes necessary to address some +of the changes in the RTEMS API between release 3.1.0 and 3.2.0. + +The primary change addressed by these tools is the addition of +"rtems_" or "RTEMS_" as a prefix on EVERY user visible RTEMS +provided constant and routine. The primary factor in the decision +to make such a sweeping change was conflicts between the +the RTEMS and POSIX API's. + +WARNING: These tools modify the files IN PLACE!!! Backup your + source before using these tools. + diff --git a/c/build-tools/README b/c/build-tools/README new file mode 100644 index 0000000000..0436fc958d --- /dev/null +++ b/c/build-tools/README @@ -0,0 +1,32 @@ +# +# $Id$ +# + +Misc. support tools for RTEMS workspaces. +More will be added later as they are converted from Teamware +to CVS. + +install-if-change + Smart install script that also can append suffixes as it + installs (suffixes used for debug and profile variants). + Requires bash or ksh. + +rcs-clean + deletes all files from the current directory that can be + re-created from RCS. Careful to not delete locked files. + May be used by 'gmake clobber' + +lock-directory +unlock-directory + traverse a directory structure making it unwritable. + Useful to keep people from accidentally overwriting + "released" trees if they get confused about which + module they have loaded. + +rtems-glom + glom together all the rtems libraries in order to simplify + the link line used by applications. + Produces rtems.rel. + Not used by the RTEMS src tree at all. + Strictly optional. + diff --git a/c/build-tools/cklength.c b/c/build-tools/cklength.c new file mode 100644 index 0000000000..48801e1559 --- /dev/null +++ b/c/build-tools/cklength.c @@ -0,0 +1,364 @@ +/* + * cklength - check the length of lines in a file + * + * This program check to see if the files passed to it on the command line + * contain a line which exceeds the maximum allowable length. The default + * maximum line length is 80. + * + * usage: cklength [ -v ] [ arg ... ] files... + * -l length -- maximum line length + * -v -- verbose + * + * $Id$ + * $Log$ + */ + +#define GETOPTARGS "l:nNv" + +char *USAGE = "\ +usage: cklength [ -v ] [ arg ... ] files... \n\ + -l length -- maximum line length\n\ + -n -- report line numbers for offending lines\n\ + -N -- report line numbers and length for offending lines\n\ + -v -- verbose\n\ +\n\ +Print the name of files which have at least 1 line which exceeds the\n\ +maximum line length. The default maximum line length is 80.\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> + +#define BUFFER_SIZE 512 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int report_line_numbers = FALSE; /* report line numbers of offenders */ +int report_line_length = FALSE; /* report line length of offenders */ + +int line_length = 80; /* maximum allowable line length */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; +extern int errno; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int +main(int argc, char **argv, char **env) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 'l': /* line length */ + line_length = atoi( optarg ); + if ( line_length < 0 || line_length > BUFFER_SIZE ) + error(ERR_FATAL, "(%d) is illegal line length\n",line_length); + break; + + case 'n': /* toggle report_line_numbers */ + report_line_numbers = ! report_line_numbers; + break; + + case 'N': /* toggle both reports */ + report_line_numbers = ! report_line_numbers; + report_line_length = ! report_line_length; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int line_number; + int length; + int count; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + count = 0; + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( length <= line_length ) + continue; + + if ( count == 0 ) { + fprintf( stderr, "%s\n", arg ); + if ( !report_line_numbers ) + break; + } + + if ( verbose ) + fprintf( stderr, "TOO LONG:%d: %s\n", line_number, buffer ); + + if ( report_line_numbers ) { + if ( report_line_length ) + fprintf( stderr, "%d: %d\n" , line_number, length ); + else + fprintf( stderr, "%d\n" , line_number ); + } + + count++; + + } + + fclose( in ); + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/c/build-tools/eolstrip.c b/c/build-tools/eolstrip.c new file mode 100644 index 0000000000..0fa7af15d4 --- /dev/null +++ b/c/build-tools/eolstrip.c @@ -0,0 +1,351 @@ +/* + * eolstrip - strip white space from end of lines + * + * This program strips the white space from the end of every line in the + * specified program. + * + * usage: eolstrip [ -v ] [ arg ... ] files... + * -v -- verbose + * + * $Id$ + * $Log$ + */ + +#define GETOPTARGS "vt" + +char *USAGE = "\ +usage: cklength [ -v ] [ arg ... ] files... \n\ + -v -- verbose\n\ + -t -- test only .. DO NOT OVERWRITE FILE!!!\n\ +\n\ +Strip the white space from the end of every line on the list of files.\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> + +#define BUFFER_SIZE 2048 +#define MAX_PATH 2048 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int test_only = FALSE; /* test only */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; +extern int errno; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int +main(int argc, char **argv, char **env) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 't': /* toggle test only mode */ + test_only = ! test_only; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + FILE *out = (FILE *) 0; + char outname[ MAX_PATH ]; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int length; + int line_number; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + if ( !test_only ) { + sprintf( outname, "%s.eoltmp", arg ); + + out = fopen( outname, "w" ); + if (!out) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + } + + if ( verbose ) + fprintf( stderr, "Processing %s\n", arg ); + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( buffer[ length ] != '\n' ) + error(ERR_ERRNO|ERR_FATAL, "Line %d too long in %s\n", line_number, arg); + + while ( isspace( buffer[ length ] ) ) + buffer[ length-- ] = '\0'; + + if ( test_only ) { + fprintf( stderr, "%s\n", arg ); + break; + } + + fprintf( out, "%s\n", buffer ); + } + + fclose( in ); + if ( !test_only ) { + fclose( out ); + rename( outname, arg ); + } + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/c/build-tools/packhex.c b/c/build-tools/packhex.c new file mode 100644 index 0000000000..ddd010c4a9 --- /dev/null +++ b/c/build-tools/packhex.c @@ -0,0 +1,513 @@ + +/***** P A C K H E X . C ************************************************ + * + * Packhex is a hex-file compaction utility. It attempts to concatenate + * hex records to produce more size-efficient packaging. + * + * Limitations: Input files must be correctly formatted. This utility + * is not robust enough to detect hex-record formatting + * errors. + * + * Published: 5/93 Embedded Systems magazine + * + * Compiler: Microsoft C 6.0 + * cl /F 1000 packhex.c + * + * + * $Id$ + * + **************************************************************************/ + + +/* #define SMALLER_RECORDS */ +#ifdef SMALLER_RECORDS +#define MAX_LEN_S1_RECS 128 +#define MAX_LEN_S2_RECS 128 +#define MAX_LEN_S3_RECS 128 +#else +#define MAX_LEN_S1_RECS 252 +#define MAX_LEN_S2_RECS 251 +#define MAX_LEN_S3_RECS 250 +#endif + + +/*--------------------------------- includes ---------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(__unix__) && !defined(EXIT_FAILURE) +#define EXIT_FAILURE -1 +#define EXIT_SUCCESS 0 +#endif + +/*--------------------------------- defines ----------------------------------*/ + +#define YES 1 +#define MAX_LINE_SIZE 600 +#define EOS '\0' + + +/*---------------------------------- macros ----------------------------------*/ + +/* Convert ASCII hexadecimal digit to value. */ + +#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF ) + + +/*--------------------------------- typedefs ---------------------------------*/ + +typedef unsigned char Boolean; +typedef unsigned char Uchar; +typedef unsigned int Uint; +typedef unsigned long Ulong; + +typedef struct /* Functions and constant returning Hex-record vital stats. */ +{ + Boolean ( *is_data_record )( char * ); + Ulong ( *get_address )( char * ); + Uint ( *get_data_count )( char * ); + const Uint max_data_count; + char *( *get_data_start )( char * ); + void ( *put_data_record )( Uint, Ulong, char * ); +} Rec_vitals; + + +/*--------------------------- function prototypes ----------------------------*/ + +Rec_vitals * identify_first_data_record( char * ); +Ulong get_ndigit_hex( char *, int ); + + +/*----------------------------- Intel Hex format -----------------------------*/ + +/* + * Intel Hex data-record layout + * + * :aabbbbccd...dee + * + * : - header character + * aa - record data byte count, a 2-digit hex value + * bbbb - record address, a 4-digit hex value + * cc - record type, a 2-digit hex value: + * "00" is a data record + * "01" is an end-of-data record + * "02" is an extended-address record + * "03" is a start record + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 2's complement + * [ (sum of bytes: aabbbbccd...d) modulo 256 ] + */ + + +Boolean is_intel_data_rec( char * rec_str ) +{ + return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) ); +} + +Uint get_intel_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) ); +} + +Ulong get_intel_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 3, 4 ) ); +} + +char * get_intel_rec_data_start( char * rec_str ) +{ + return( rec_str + 9 ); +} + +void put_intel_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + ":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff + ); +} + + +Rec_vitals intel_hex = +{ + is_intel_data_rec, + get_intel_rec_address, + get_intel_rec_data_count, + 255, /* Maximum data bytes in a record. */ + get_intel_rec_data_start, + put_intel_data_rec +}; + + +/*------------------------- Motorola S1-record format ------------------------*/ + +/* + * Motorola S-record data-record layout + * + * Sabbc...cd...dee + * + * S - header character + * a - record type, a 1-digit value: + * "0" is a header record + * "1" is a 2-byte-address data record + * "2" is a 3-byte-address data record + * "3" is a 4-byte-address data record + * "7" is a 4-byte-address end-of-data record + * "8" is a 3-byte-address end-of-data record + * "9" is a 2-byte-address end-of-data record + * bb - record length in bytes, a 2-digit hex value + * (record length doesn't count the header/type + * chars and checksum byte) + * c...c - record address, a 4-, 6-, or 8-digit value, + * depending on record type + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 1's complement + * [ (sum of all bytes: bbc..cd...d) modulo 256 ] + */ + +#define S1_COUNT_OFFSET 3 + + +Boolean is_moto_s1_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) ); +} + +Uint get_moto_s1_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET ); +} + +Ulong get_moto_s1_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 4 ) ); +} + +char * get_moto_s1_rec_data_start( char * rec_str ) +{ + return( rec_str + 8 ); +} + +void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S1_COUNT_OFFSET + count + + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S1%02X%04lX%s%02X\n", + count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s1_rec = +{ + is_moto_s1_data_rec, + get_moto_s1_rec_address, + get_moto_s1_rec_data_count, + MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */ + get_moto_s1_rec_data_start, + put_moto_s1_data_rec +}; + + +/*------------------------- Motorola S2-record format ------------------------*/ + +#define S2_COUNT_OFFSET 4 + +Boolean is_moto_s2_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) ); +} + +Uint get_moto_s2_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET ); +} + +Ulong get_moto_s2_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 6 ) ); +} + +char * get_moto_s2_rec_data_start( char * rec_str ) +{ + return( rec_str + 10 ); +} + +void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S2%02X%06lX%s%02X\n", + count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s2_rec = +{ + is_moto_s2_data_rec, + get_moto_s2_rec_address, + get_moto_s2_rec_data_count, + MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */ + get_moto_s2_rec_data_start, + put_moto_s2_data_rec +}; + + +/*------------------------- Motorola S3-record format ------------------------*/ + +#define S3_COUNT_OFFSET 5 + +Boolean is_moto_s3_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) ); +} + +Uint get_moto_s3_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET ); +} + +Ulong get_moto_s3_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 8 ) ); +} + +char * get_moto_s3_rec_data_start( char * rec_str ) +{ + return( rec_str + 12 ); +} + +void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) + + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S3%02X%08lX%s%02X\n", + count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s3_rec = +{ + is_moto_s3_data_rec, + get_moto_s3_rec_address, + get_moto_s3_rec_data_count, + MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */ + get_moto_s3_rec_data_start, + put_moto_s3_data_rec +}; + + +/*-------------------- Put your favorite hex format here ---------------------*/ + +/* + * * * * The following is a template for an additional hex format: * * * + * + * + * Boolean is_X_data_rec( char * rec_str ) {} + * + * Uint get_X_rec_data_count( char * rec_str ) {} + * + * Ulong get_X_rec_address( char * rec_str ) {} + * + * char * get_X_rec_data_start( char * rec_str ) {} + * + * void put_X_data_rec( Uint count, Ulong address, char * data_str ) {} + * + * Rec_vitals X_rec = + * { + * is_X_data_rec, + * get_X_rec_address, + * get_X_rec_data_count, + * MAXIMUM DATA BYTES IN A RECORD, + * get_X_rec_data_start, + * put_X_data_rec + * }; + * + */ + +/*----------------------------------------------------------------------------*/ + + +/* + * Put address of additional Rec_vitals structures + * in this array, before the NULL entry. + */ + +Rec_vitals *formats[] = +{ + &intel_hex, + &motorola_s1_rec, + &motorola_s2_rec, + &motorola_s3_rec, + ( Rec_vitals * ) NULL +}; + + +/**** main ***************************************************************** +* +* +* Expects: Nothing (no command-line parameters). +* +* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE). +* +* Reads hex records on the standard input and attempts to +* splice adjacent data fields together. Results appear on +* the standard output. +* +*******************************************************************************/ + +void main( void ) +{ + + char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ]; + char *in_dptr, *out_dptr; + int d_total, d_count, d_excess, n; + Ulong in_rec_addr, out_rec_addr = 0; + Rec_vitals *rptr; + + + /* Sift through file until first hex record is identified. */ + if ( ( rptr = identify_first_data_record( inbuff ) ) == NULL ) + { + fputs( "No hex records found.\n", stderr ); + exit( EXIT_FAILURE ); + } + + + /* Attempt data-record splicing until end-of-file is reached. */ + d_total = 0; + do + { + if ( rptr->is_data_record( inbuff ) == YES ) + { /* Input record is a data record. */ + d_count = rptr->get_data_count( inbuff ); + in_rec_addr = rptr->get_address( inbuff ); + in_dptr = rptr->get_data_start( inbuff ); + + if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total ) + { /* Begin a new output record. */ + if ( d_total != 0 ) + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + out_dptr = outbuff; + n = d_total = d_count; + out_rec_addr = in_rec_addr; + } + else if + ( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 ) + { /* Output a maximum-length record, then start a new record. */ + strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) ); + rptr->put_data_record( + rptr->max_data_count, out_rec_addr, outbuff + ); + in_dptr += 2 * ( d_count - d_excess ); + out_dptr = outbuff; + n = d_total = d_excess; + out_rec_addr += rptr->max_data_count; + } + else + { /* Append input record's data field with accumulated data. */ + out_dptr = outbuff + ( 2 * d_total ); + d_total += n = d_count; + } + strncpy( out_dptr, in_dptr, 2 * n ); + out_dptr[ 2 * n ] = EOS; + } + else + { /* Not a data record; + * flush accumulated data then echo non-data record. + */ + if ( d_total != 0 ) + { + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + d_total = 0; + } + puts( inbuff ); + } + } while ( gets( inbuff ) != NULL ); + + + exit( EXIT_SUCCESS ); + +} + + +/**** identify_first_data_record ******************************************* +* +* Expects: Pointer to hex-record line buffer. +* +* Returns: Pointer to hex-record structure (NULL if no match found). +* +* Reads the standard input, line by line, searching for a valid +* record header character. If a valid header is found, a pointer +* to the hex-record's type structure is returned, otherwise NULL. +* +* The input-stream pointer is left pointing to the first valid hex record. +* +*******************************************************************************/ + +Rec_vitals * identify_first_data_record( char * buff_ptr ) +{ + Rec_vitals ** ptr; + + while ( gets( buff_ptr ) != NULL ) + { + for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ ) + if ( ( *ptr )->is_data_record( buff_ptr ) == YES ) + return( *ptr ); /* Successful return. */ + + puts( buff_ptr ); /* Echo non-hex-record line. */ + } + + return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */ +} + + +/**** get_ndigit_hex ******************************************************* +* +* Expects: Pointer to first ASCII hexadecimal digit, number of digits. +* +* Returns: Value of hexadecimal string as an unsigned long. +* +*******************************************************************************/ + +Ulong get_ndigit_hex( char * cptr, int digits ) +{ + Ulong value; + + for ( value = 0 ; --digits >= 0 ; cptr++ ) + value = ( value * 16L ) + HEX_DIGIT( *cptr ); + + return( value ); +} diff --git a/c/build-tools/scripts/README b/c/build-tools/scripts/README new file mode 100644 index 0000000000..0436fc958d --- /dev/null +++ b/c/build-tools/scripts/README @@ -0,0 +1,32 @@ +# +# $Id$ +# + +Misc. support tools for RTEMS workspaces. +More will be added later as they are converted from Teamware +to CVS. + +install-if-change + Smart install script that also can append suffixes as it + installs (suffixes used for debug and profile variants). + Requires bash or ksh. + +rcs-clean + deletes all files from the current directory that can be + re-created from RCS. Careful to not delete locked files. + May be used by 'gmake clobber' + +lock-directory +unlock-directory + traverse a directory structure making it unwritable. + Useful to keep people from accidentally overwriting + "released" trees if they get confused about which + module they have loaded. + +rtems-glom + glom together all the rtems libraries in order to simplify + the link line used by applications. + Produces rtems.rel. + Not used by the RTEMS src tree at all. + Strictly optional. + diff --git a/c/build-tools/src/cklength.c b/c/build-tools/src/cklength.c new file mode 100644 index 0000000000..48801e1559 --- /dev/null +++ b/c/build-tools/src/cklength.c @@ -0,0 +1,364 @@ +/* + * cklength - check the length of lines in a file + * + * This program check to see if the files passed to it on the command line + * contain a line which exceeds the maximum allowable length. The default + * maximum line length is 80. + * + * usage: cklength [ -v ] [ arg ... ] files... + * -l length -- maximum line length + * -v -- verbose + * + * $Id$ + * $Log$ + */ + +#define GETOPTARGS "l:nNv" + +char *USAGE = "\ +usage: cklength [ -v ] [ arg ... ] files... \n\ + -l length -- maximum line length\n\ + -n -- report line numbers for offending lines\n\ + -N -- report line numbers and length for offending lines\n\ + -v -- verbose\n\ +\n\ +Print the name of files which have at least 1 line which exceeds the\n\ +maximum line length. The default maximum line length is 80.\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> + +#define BUFFER_SIZE 512 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int report_line_numbers = FALSE; /* report line numbers of offenders */ +int report_line_length = FALSE; /* report line length of offenders */ + +int line_length = 80; /* maximum allowable line length */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; +extern int errno; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int +main(int argc, char **argv, char **env) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 'l': /* line length */ + line_length = atoi( optarg ); + if ( line_length < 0 || line_length > BUFFER_SIZE ) + error(ERR_FATAL, "(%d) is illegal line length\n",line_length); + break; + + case 'n': /* toggle report_line_numbers */ + report_line_numbers = ! report_line_numbers; + break; + + case 'N': /* toggle both reports */ + report_line_numbers = ! report_line_numbers; + report_line_length = ! report_line_length; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int line_number; + int length; + int count; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + count = 0; + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( length <= line_length ) + continue; + + if ( count == 0 ) { + fprintf( stderr, "%s\n", arg ); + if ( !report_line_numbers ) + break; + } + + if ( verbose ) + fprintf( stderr, "TOO LONG:%d: %s\n", line_number, buffer ); + + if ( report_line_numbers ) { + if ( report_line_length ) + fprintf( stderr, "%d: %d\n" , line_number, length ); + else + fprintf( stderr, "%d\n" , line_number ); + } + + count++; + + } + + fclose( in ); + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/c/build-tools/src/eolstrip.c b/c/build-tools/src/eolstrip.c new file mode 100644 index 0000000000..0fa7af15d4 --- /dev/null +++ b/c/build-tools/src/eolstrip.c @@ -0,0 +1,351 @@ +/* + * eolstrip - strip white space from end of lines + * + * This program strips the white space from the end of every line in the + * specified program. + * + * usage: eolstrip [ -v ] [ arg ... ] files... + * -v -- verbose + * + * $Id$ + * $Log$ + */ + +#define GETOPTARGS "vt" + +char *USAGE = "\ +usage: cklength [ -v ] [ arg ... ] files... \n\ + -v -- verbose\n\ + -t -- test only .. DO NOT OVERWRITE FILE!!!\n\ +\n\ +Strip the white space from the end of every line on the list of files.\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <stdarg.h> + +#define BUFFER_SIZE 2048 +#define MAX_PATH 2048 + +#define SUCCESS 0 +#define FAILURE -1 +#define Failed(x) (((int) (x)) == FAILURE) +#define TRUE 1 +#define FALSE 0 +#define STREQ(a,b) (strcmp(a,b) == 0) +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * Definitions for unsigned "ints"; especially for use in data structures + * that will be shared among (potentially) different cpu's (we punt on + * byte ordering problems tho) + */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * vars controlled by command line options + */ + +int verbose = FALSE; /* be verbose */ +int test_only = FALSE; /* test only */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind, opterr; +extern int errno; + +char *progname; /* for error() */ + +int process(char *arg); +void error(int errn, ...); +long getparm(char *s, long min, long max, char *msg); + +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) +int Open(), Read(), Write(); + +int +main(int argc, char **argv, char **env) +{ + register int c; + int showusage = FALSE; /* usage error? */ + int rc = 0; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + opterr = 0; /* we'll report all errors */ + while ((c = getopt(argc, argv, GETOPTARGS)) != EOF) + switch (c) + { + case 't': /* toggle test only mode */ + test_only = ! test_only; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + /* + * traverse and process the arguments + */ + + for ( ; argv[optind]; optind++) + if (Failed(process(argv[optind]))) + rc = FAILURE; + + return rc; +} + + +/* + * process(arg) + */ + +int +process(char *arg) +{ + FILE *in; + FILE *out = (FILE *) 0; + char outname[ MAX_PATH ]; + char *bptr; + char buffer[ BUFFER_SIZE ]; + int length; + int line_number; + int rc = SUCCESS; /* succeed by default */ + + in = fopen( arg, "r" ); + if (!in) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + + if ( !test_only ) { + sprintf( outname, "%s.eoltmp", arg ); + + out = fopen( outname, "w" ); + if (!out) + error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg ); + } + + if ( verbose ) + fprintf( stderr, "Processing %s\n", arg ); + + for ( line_number=1 ; ; line_number++ ) { + bptr = fgets( buffer, BUFFER_SIZE, in ); + if (!bptr) + break; + + /* + * Don't count the carriage return. + */ + + length = strlen( buffer ) - 1; + + if ( buffer[ length ] != '\n' ) + error(ERR_ERRNO|ERR_FATAL, "Line %d too long in %s\n", line_number, arg); + + while ( isspace( buffer[ length ] ) ) + buffer[ length-- ] = '\0'; + + if ( test_only ) { + fprintf( stderr, "%s\n", arg ); + break; + } + + fprintf( out, "%s\n", buffer ); + } + + fclose( in ); + if ( !test_only ) { + fclose( out ); + rename( outname, arg ); + } + return rc; +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_FATAL bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + +long +getparm(char *s, + long min, + long max, + char *msg) +{ + long val; + + if ( ! strchr("0123456789-", *s)) + { + error(ERR_FATAL, "'%s' is not a number", s); + return min; + } + + val = strtol(s, (char **) NULL, 0); + if ((val < min) || (val > max)) + { + if (min == max) + error(ERR_FATAL, "%s can only be %ld", s, min); + else + error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max); + } + + return val; +} + + +/* + * Open() + * Perform open(2), returning the file descriptor. Prints + * error message if open fails. + */ + +int +Open(char *file, + int oflag, + int mode) +{ + int O_fd; + + if (Failed(O_fd = open(file, oflag, mode))) + error( + ERR_ERRNO | ERR_FATAL, + "open('%s', 0x%x, 0%o) failed", file, oflag, mode + ); + + return O_fd; +} + +/* + * Read() + * Perform read(2); prints error message if fails. + */ + +int +Read(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = read(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "read(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} + +/* + * Write() + * Perform write(2); prints error message if fails. + */ + +int +Write(int file, + char *buffer, + unsigned int count) +{ + int nbytes; + + if (Failed(nbytes = write(file, buffer, count))) + error( + ERR_ERRNO | ERR_FATAL, + "write(%d, 0x%x, %d) failed", file, buffer, count + ); + + return nbytes; +} diff --git a/c/build-tools/src/packhex.c b/c/build-tools/src/packhex.c new file mode 100644 index 0000000000..ddd010c4a9 --- /dev/null +++ b/c/build-tools/src/packhex.c @@ -0,0 +1,513 @@ + +/***** P A C K H E X . C ************************************************ + * + * Packhex is a hex-file compaction utility. It attempts to concatenate + * hex records to produce more size-efficient packaging. + * + * Limitations: Input files must be correctly formatted. This utility + * is not robust enough to detect hex-record formatting + * errors. + * + * Published: 5/93 Embedded Systems magazine + * + * Compiler: Microsoft C 6.0 + * cl /F 1000 packhex.c + * + * + * $Id$ + * + **************************************************************************/ + + +/* #define SMALLER_RECORDS */ +#ifdef SMALLER_RECORDS +#define MAX_LEN_S1_RECS 128 +#define MAX_LEN_S2_RECS 128 +#define MAX_LEN_S3_RECS 128 +#else +#define MAX_LEN_S1_RECS 252 +#define MAX_LEN_S2_RECS 251 +#define MAX_LEN_S3_RECS 250 +#endif + + +/*--------------------------------- includes ---------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(__unix__) && !defined(EXIT_FAILURE) +#define EXIT_FAILURE -1 +#define EXIT_SUCCESS 0 +#endif + +/*--------------------------------- defines ----------------------------------*/ + +#define YES 1 +#define MAX_LINE_SIZE 600 +#define EOS '\0' + + +/*---------------------------------- macros ----------------------------------*/ + +/* Convert ASCII hexadecimal digit to value. */ + +#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF ) + + +/*--------------------------------- typedefs ---------------------------------*/ + +typedef unsigned char Boolean; +typedef unsigned char Uchar; +typedef unsigned int Uint; +typedef unsigned long Ulong; + +typedef struct /* Functions and constant returning Hex-record vital stats. */ +{ + Boolean ( *is_data_record )( char * ); + Ulong ( *get_address )( char * ); + Uint ( *get_data_count )( char * ); + const Uint max_data_count; + char *( *get_data_start )( char * ); + void ( *put_data_record )( Uint, Ulong, char * ); +} Rec_vitals; + + +/*--------------------------- function prototypes ----------------------------*/ + +Rec_vitals * identify_first_data_record( char * ); +Ulong get_ndigit_hex( char *, int ); + + +/*----------------------------- Intel Hex format -----------------------------*/ + +/* + * Intel Hex data-record layout + * + * :aabbbbccd...dee + * + * : - header character + * aa - record data byte count, a 2-digit hex value + * bbbb - record address, a 4-digit hex value + * cc - record type, a 2-digit hex value: + * "00" is a data record + * "01" is an end-of-data record + * "02" is an extended-address record + * "03" is a start record + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 2's complement + * [ (sum of bytes: aabbbbccd...d) modulo 256 ] + */ + + +Boolean is_intel_data_rec( char * rec_str ) +{ + return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) ); +} + +Uint get_intel_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) ); +} + +Ulong get_intel_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 3, 4 ) ); +} + +char * get_intel_rec_data_start( char * rec_str ) +{ + return( rec_str + 9 ); +} + +void put_intel_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + ":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff + ); +} + + +Rec_vitals intel_hex = +{ + is_intel_data_rec, + get_intel_rec_address, + get_intel_rec_data_count, + 255, /* Maximum data bytes in a record. */ + get_intel_rec_data_start, + put_intel_data_rec +}; + + +/*------------------------- Motorola S1-record format ------------------------*/ + +/* + * Motorola S-record data-record layout + * + * Sabbc...cd...dee + * + * S - header character + * a - record type, a 1-digit value: + * "0" is a header record + * "1" is a 2-byte-address data record + * "2" is a 3-byte-address data record + * "3" is a 4-byte-address data record + * "7" is a 4-byte-address end-of-data record + * "8" is a 3-byte-address end-of-data record + * "9" is a 2-byte-address end-of-data record + * bb - record length in bytes, a 2-digit hex value + * (record length doesn't count the header/type + * chars and checksum byte) + * c...c - record address, a 4-, 6-, or 8-digit value, + * depending on record type + * d...d - data (always an even number of chars) + * ee - record checksum, a 2-digit hex value + * checksum = 1's complement + * [ (sum of all bytes: bbc..cd...d) modulo 256 ] + */ + +#define S1_COUNT_OFFSET 3 + + +Boolean is_moto_s1_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) ); +} + +Uint get_moto_s1_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET ); +} + +Ulong get_moto_s1_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 4 ) ); +} + +char * get_moto_s1_rec_data_start( char * rec_str ) +{ + return( rec_str + 8 ); +} + +void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S1_COUNT_OFFSET + count + + ( address >> 8 & 0xff ) + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S1%02X%04lX%s%02X\n", + count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s1_rec = +{ + is_moto_s1_data_rec, + get_moto_s1_rec_address, + get_moto_s1_rec_data_count, + MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */ + get_moto_s1_rec_data_start, + put_moto_s1_data_rec +}; + + +/*------------------------- Motorola S2-record format ------------------------*/ + +#define S2_COUNT_OFFSET 4 + +Boolean is_moto_s2_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) ); +} + +Uint get_moto_s2_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET ); +} + +Ulong get_moto_s2_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 6 ) ); +} + +char * get_moto_s2_rec_data_start( char * rec_str ) +{ + return( rec_str + 10 ); +} + +void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S2%02X%06lX%s%02X\n", + count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s2_rec = +{ + is_moto_s2_data_rec, + get_moto_s2_rec_address, + get_moto_s2_rec_data_count, + MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */ + get_moto_s2_rec_data_start, + put_moto_s2_data_rec +}; + + +/*------------------------- Motorola S3-record format ------------------------*/ + +#define S3_COUNT_OFFSET 5 + +Boolean is_moto_s3_data_rec( char * rec_str ) +{ + return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) ); +} + +Uint get_moto_s3_rec_data_count( char * rec_str ) +{ + return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET ); +} + +Ulong get_moto_s3_rec_address( char * rec_str ) +{ + return( get_ndigit_hex( rec_str + 4, 8 ) ); +} + +char * get_moto_s3_rec_data_start( char * rec_str ) +{ + return( rec_str + 12 ); +} + +void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str ) +{ + char *ptr; + Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) + + ( address >> 16 & 0xff ) + + ( address >> 8 & 0xff ) + + ( address & 0xff ); + + for ( ptr = data_str ; *ptr != EOS ; ptr += 2 ) + sum += ( Uint ) get_ndigit_hex( ptr, 2 ); + + printf( + "S3%02X%08lX%s%02X\n", + count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff + ); +} + + +Rec_vitals motorola_s3_rec = +{ + is_moto_s3_data_rec, + get_moto_s3_rec_address, + get_moto_s3_rec_data_count, + MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */ + get_moto_s3_rec_data_start, + put_moto_s3_data_rec +}; + + +/*-------------------- Put your favorite hex format here ---------------------*/ + +/* + * * * * The following is a template for an additional hex format: * * * + * + * + * Boolean is_X_data_rec( char * rec_str ) {} + * + * Uint get_X_rec_data_count( char * rec_str ) {} + * + * Ulong get_X_rec_address( char * rec_str ) {} + * + * char * get_X_rec_data_start( char * rec_str ) {} + * + * void put_X_data_rec( Uint count, Ulong address, char * data_str ) {} + * + * Rec_vitals X_rec = + * { + * is_X_data_rec, + * get_X_rec_address, + * get_X_rec_data_count, + * MAXIMUM DATA BYTES IN A RECORD, + * get_X_rec_data_start, + * put_X_data_rec + * }; + * + */ + +/*----------------------------------------------------------------------------*/ + + +/* + * Put address of additional Rec_vitals structures + * in this array, before the NULL entry. + */ + +Rec_vitals *formats[] = +{ + &intel_hex, + &motorola_s1_rec, + &motorola_s2_rec, + &motorola_s3_rec, + ( Rec_vitals * ) NULL +}; + + +/**** main ***************************************************************** +* +* +* Expects: Nothing (no command-line parameters). +* +* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE). +* +* Reads hex records on the standard input and attempts to +* splice adjacent data fields together. Results appear on +* the standard output. +* +*******************************************************************************/ + +void main( void ) +{ + + char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ]; + char *in_dptr, *out_dptr; + int d_total, d_count, d_excess, n; + Ulong in_rec_addr, out_rec_addr = 0; + Rec_vitals *rptr; + + + /* Sift through file until first hex record is identified. */ + if ( ( rptr = identify_first_data_record( inbuff ) ) == NULL ) + { + fputs( "No hex records found.\n", stderr ); + exit( EXIT_FAILURE ); + } + + + /* Attempt data-record splicing until end-of-file is reached. */ + d_total = 0; + do + { + if ( rptr->is_data_record( inbuff ) == YES ) + { /* Input record is a data record. */ + d_count = rptr->get_data_count( inbuff ); + in_rec_addr = rptr->get_address( inbuff ); + in_dptr = rptr->get_data_start( inbuff ); + + if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total ) + { /* Begin a new output record. */ + if ( d_total != 0 ) + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + out_dptr = outbuff; + n = d_total = d_count; + out_rec_addr = in_rec_addr; + } + else if + ( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 ) + { /* Output a maximum-length record, then start a new record. */ + strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) ); + rptr->put_data_record( + rptr->max_data_count, out_rec_addr, outbuff + ); + in_dptr += 2 * ( d_count - d_excess ); + out_dptr = outbuff; + n = d_total = d_excess; + out_rec_addr += rptr->max_data_count; + } + else + { /* Append input record's data field with accumulated data. */ + out_dptr = outbuff + ( 2 * d_total ); + d_total += n = d_count; + } + strncpy( out_dptr, in_dptr, 2 * n ); + out_dptr[ 2 * n ] = EOS; + } + else + { /* Not a data record; + * flush accumulated data then echo non-data record. + */ + if ( d_total != 0 ) + { + rptr->put_data_record( d_total, out_rec_addr, outbuff ); + d_total = 0; + } + puts( inbuff ); + } + } while ( gets( inbuff ) != NULL ); + + + exit( EXIT_SUCCESS ); + +} + + +/**** identify_first_data_record ******************************************* +* +* Expects: Pointer to hex-record line buffer. +* +* Returns: Pointer to hex-record structure (NULL if no match found). +* +* Reads the standard input, line by line, searching for a valid +* record header character. If a valid header is found, a pointer +* to the hex-record's type structure is returned, otherwise NULL. +* +* The input-stream pointer is left pointing to the first valid hex record. +* +*******************************************************************************/ + +Rec_vitals * identify_first_data_record( char * buff_ptr ) +{ + Rec_vitals ** ptr; + + while ( gets( buff_ptr ) != NULL ) + { + for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ ) + if ( ( *ptr )->is_data_record( buff_ptr ) == YES ) + return( *ptr ); /* Successful return. */ + + puts( buff_ptr ); /* Echo non-hex-record line. */ + } + + return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */ +} + + +/**** get_ndigit_hex ******************************************************* +* +* Expects: Pointer to first ASCII hexadecimal digit, number of digits. +* +* Returns: Value of hexadecimal string as an unsigned long. +* +*******************************************************************************/ + +Ulong get_ndigit_hex( char * cptr, int digits ) +{ + Ulong value; + + for ( value = 0 ; --digits >= 0 ; cptr++ ) + value = ( value * 16L ) + HEX_DIGIT( *cptr ); + + return( value ); +} diff --git a/c/build-tools/src/unhex.c b/c/build-tools/src/unhex.c new file mode 100644 index 0000000000..540095d6f4 --- /dev/null +++ b/c/build-tools/src/unhex.c @@ -0,0 +1,719 @@ +/* + * unhex + * convert a hex file to binary equivalent. If more than one file name + * is given, then the output will be logically concatenated together. + * stdin and stdout are defaults. Verbose will enable checksum output. + * + * Supported input formats are Intel hex, Motorola S records, and TI 'B' + * records. + * + * Intel hex input format is + * Byte + * 1 Colon : + * 2..3 Record length, eg: "20" + * 4..7 load address nibbles + * 8..9 record type: "00" (data) or "02" base addr + * 10..x data bytes in ascii-hex + * x+1..x+2 cksum (2's compl of (len+addr+data)) + * x+3 \n -- newline + */ + +char *USAGE = "\ +usage: unhex [-va] [ -o file ] [ file [file ... ] ]\n\ + -v -- verbose\n\ + -a base -- 1st byte of output corresponds to this address\n\ + -l -- linear, just writes data out\n\ + -o file -- output file; must not be input file\n\ + -F k_bits -- \"holes\" in input will be filled with 0xFF's\n\ + up to \"k_bits\" * 1024 bits\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> + +#define OK 0 +#define FAILURE (-1) +#define Failed(x) ((x) == FAILURE) +#define TRUE 1 +#define FALSE 0 +typedef char bool; +#define STREQ(a,b) (strcmp(a,b) == 0) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * Pick out designated bytes + */ + +#define B0(x) ((x) & 0xff) +#define B1(x) B0((x) >> 8) +#define B2(x) B0((x) >> 16) +#define B3(x) B0((x) >> 24) + +typedef struct buffer_rec { + u32 dl_destaddr; + u32 dl_jumpaddr; + int dl_count; + u8 dl_buf[512]; +} buffer_rec; + +/* + * vars controlled by command line options + */ + +bool verbose = FALSE; /* be verbose */ +bool linear = FALSE; /* just write out linear data */ +char *outfilename = "-"; /* default output is stdout */ +u32 base = 0L; /* base address */ +u32 FFfill = 0L; /* how far to fill w 0xFF's */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind; +extern int errno; + +char *progname; /* for error() */ + +void error(int errn, ...); +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* error is fatal; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* error is fatal; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) + +int unhex(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_Intel_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_S_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_TI_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +void write_record(buffer_rec *tb, FILE *fp); +int getnibble(char **p); +int getbyte(char **p); +long getNbytes(char **p, int n); +void badformat(char *s, char *fname, char *msg); + +#define get1bytes(p) ((int) getbyte(p)) +#define get2bytes(p) ((int) getNbytes(p, 2)) +#define get3bytes(p) getNbytes(p, 3) +#define get4bytes(p) getNbytes(p, 4) + +char *BADADDR = "Invalid record address"; +char *BADLEN = "Invalid record length"; +char *BADBASE = "Bad base or starting address"; +char *BADFMT = "Unrecognized record type"; +char *BADDATA = "Invalid data byte"; +char *BADCSUM = "Invalid checksum"; +char *MISCSUM = "Checksum mismatch"; +char *BADTYPE = "Unrecognized record type"; +char *MISTYPE = "Incompatible record types"; + +int +main(argc, argv) +int argc; +char **argv; +{ + register int c; + bool showusage = FALSE; /* usage error? */ + int rc = 0; + FILE *outfp, *infp; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + progname = argv[0]; + while ((c = getopt(argc, argv, "F:a:o:vl")) != EOF) + switch (c) + { + case 'a': /* base address */ + base = stol(optarg); + break; + + case 'l': /* linear output */ + linear = TRUE; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case 'o': /* output file */ + outfilename = optarg; + break; + + case 'F': /* 0xFF fill amount (bytes) */ + FFfill = stol(optarg) * 1024L / 8L; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + if (linear && (base != 0)) + { + error(0, "-l and -a may not be specified in combination"); + exit(1); + } + + if (STREQ(outfilename, "-")) + { + outfp = stdout; + outfilename = "stdout"; + } + else + if ((outfp = fopen(outfilename, "w")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for output", outfilename); + exit(1); + } + + /* + * Now process the input files (or stdin, if none specified) + */ + + if (argv[optind] == (char *) NULL) /* just stdin */ + exit(unhex(stdin, "stdin", outfp, outfilename)); + else + for (; (optarg = argv[optind]); optind++) + { + if (STREQ(optarg, "-")) + rc += unhex(stdin, "stdin", outfp, outfilename); + else + { + if ((infp = fopen(optarg, "r")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for input", optarg); + exit(1); + } + rc += unhex(infp, optarg, outfp, outfilename); + } + } + + return(rc); +} + +u16 filesum; + +int +unhex(FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + int c; + + filesum = 0; + + /* + * Make sure holes will be filled with 0xFF's if requested. We + * do this the easy way by just filling the file with FF's before + * getting started. To do it more optimally would be quite a bit + * more difficult since the user can skip around as much as he/she + * likes in the input hex file addressing. + * + * We'll clean this up later (after this program has run) with + * 'stripffs' + */ + + if (FFfill) + { + (void) fseek(ofp, 0, 0); + for (c = FFfill; c > 0; c--) + (void) fputc(0xFF, ofp); + } + + /* + * Read the first char from file and determine record types + */ + + if ((c = getc(ifp)) != EOF) + { + ungetc(c, ifp); + switch(c) + { + case 'S': + convert_S_records(ifp, inm, ofp, onm); + break; + + case ':': + convert_Intel_records(ifp, inm, ofp, onm); + break; + + case '9': + case 'B': + convert_TI_records(ifp, inm, ofp, onm); + break; + + default: + { + char tmp[2]; + tmp[0] = c; tmp[1] = 0; + badformat(tmp, inm, BADFMT); + } + } + } + + if (verbose) + fprintf(stderr, "'%s' checksum is 0x%04x\n", inm, filesum); + + return 0; +} + +int +convert_Intel_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int rectype; /* record type */ + int len; /* data length of current line */ + u32 addr; + u32 base_address = 0; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != ':') + badformat(p, inm, BADFMT); + p++; + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + + if ((addr = get2bytes(&p)) == -1L) /* record addr */ + badformat(buff, inm, BADADDR); + + rectype = getbyte(&p); + + cksum = len + B0(addr) + B1(addr) + rectype; + + switch (rectype) + { + case 0x00: /* normal data record */ + tb.dl_destaddr = base_address + addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x01: /* execution start address */ + base_address = addr; + endrecord = TRUE; + break; + + case 0x02: /* new base */ + if ((base_address = get2bytes(&p)) == -1L) + badformat(buff, inm, BADBASE); + cksum += B0(base_address) + B1(base_address); + base_address <<= 4; + break; + + case 0x03: /* seg/off execution start address */ + { + u32 seg, off; + + seg = get2bytes(&p); + off = get2bytes(&p); + if ((seg == -1L) || (off == -1L)) + badformat(buff, inm, BADADDR); + + cksum += B0(seg) + B1(seg) + B0(off) + B1(off); + + tb.dl_jumpaddr = (seg << 4) + off; + break; + } + + default: + error(0, "unknown Intel-hex record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (-cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_S_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int len; /* data length of current line */ + int rectype; /* record type */ + u32 addr; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != 'S') + badformat(p, inm, BADFMT); + p++; + + if ((rectype = getnibble(&p)) == -1) /* record type */ + badformat(buff, inm, BADTYPE); + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + cksum = len; + + switch (rectype) + { + case 0x00: /* comment field, ignored */ + goto write_it; + + case 0x01: /* data record, 16 bit addr */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 3; + goto doit; + + case 0x02: /* ... 24 bit addr */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 4; + goto doit; + + case 0x03: /* ... 32 bit addr */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 5; + doit: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + + tb.dl_destaddr = addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x07: /* 32 bit end record */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x08: /* 24 bit end record */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x09: /* 16 bit end record */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + +end_rec: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + tb.dl_jumpaddr = addr; + break; + + default: + error(0, "unknown Motorola-S record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + break; + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (~cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + +write_it: + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_TI_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + int c; + bool endrecord = FALSE; + bool eol; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + p = &buff[0]; + eol = FALSE; + while ( ! eol && ! endrecord) + { + switch (*p++) + { + case '9': + if (tb.dl_count) + write_record(&tb, ofp); + tb.dl_destaddr = get2bytes(&p); + break; + + case 'B': + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + break; + + case 'F': + eol = TRUE; + break; + + case ':': + endrecord = TRUE; + break; + + default: + badformat(p, inm, BADFMT); + } + } + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +void +write_record(buffer_rec *tb, + FILE *fp) +{ + if ( ! linear) + { + if (tb->dl_destaddr < base) + error(ERR_FATAL, "record at address 0x%x precedes base of 0x%x", + tb->dl_destaddr, base); + (void) fseek(fp, tb->dl_destaddr - base, 0); + } + + (void) fwrite(tb->dl_buf, tb->dl_count, 1, fp); + tb->dl_destaddr += tb->dl_count; + tb->dl_count = 0; +} + +int +getnibble(char **p) +{ + register int val; + + **p = toupper(**p); + switch (**p) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + val = **p - '0'; + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + val = 10 + (**p - 'A'); + break; + + default: + return(-1); + } + *p += 1; + + return(val & 0x0f); +} + +int +getbyte(char **p) +{ + int n0, n1; + + if ((n0 = getnibble(p)) == -1) + return(-1); + if ((n1 = getnibble(p)) == -1) + return(-1); + + return(((n0 << 4) + n1) & 0xff); +} + +long +getNbytes(char **p, + int n) +{ + int t; + u32 val = 0; + + while (n--) + { + if ((t = getbyte(p)) == -1) + return(-1L); + val <<= 8; + val += t; + } + + return(val); +} + +void +badformat(char *s, + char *fname, + char *msg) +{ + if (s[strlen(s)-1] == '\n') /* get rid of newline */ + s[strlen(s)-1] = '\0'; + error(0, "line '%s'::\n\tfrom file '%s'; %s", s, fname, msg); + exit(1); +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_EXIT bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + diff --git a/c/build-tools/unhex.c b/c/build-tools/unhex.c new file mode 100644 index 0000000000..540095d6f4 --- /dev/null +++ b/c/build-tools/unhex.c @@ -0,0 +1,719 @@ +/* + * unhex + * convert a hex file to binary equivalent. If more than one file name + * is given, then the output will be logically concatenated together. + * stdin and stdout are defaults. Verbose will enable checksum output. + * + * Supported input formats are Intel hex, Motorola S records, and TI 'B' + * records. + * + * Intel hex input format is + * Byte + * 1 Colon : + * 2..3 Record length, eg: "20" + * 4..7 load address nibbles + * 8..9 record type: "00" (data) or "02" base addr + * 10..x data bytes in ascii-hex + * x+1..x+2 cksum (2's compl of (len+addr+data)) + * x+3 \n -- newline + */ + +char *USAGE = "\ +usage: unhex [-va] [ -o file ] [ file [file ... ] ]\n\ + -v -- verbose\n\ + -a base -- 1st byte of output corresponds to this address\n\ + -l -- linear, just writes data out\n\ + -o file -- output file; must not be input file\n\ + -F k_bits -- \"holes\" in input will be filled with 0xFF's\n\ + up to \"k_bits\" * 1024 bits\n\ +"; + +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> + +#define OK 0 +#define FAILURE (-1) +#define Failed(x) ((x) == FAILURE) +#define TRUE 1 +#define FALSE 0 +typedef char bool; +#define STREQ(a,b) (strcmp(a,b) == 0) + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +/* + * Pick out designated bytes + */ + +#define B0(x) ((x) & 0xff) +#define B1(x) B0((x) >> 8) +#define B2(x) B0((x) >> 16) +#define B3(x) B0((x) >> 24) + +typedef struct buffer_rec { + u32 dl_destaddr; + u32 dl_jumpaddr; + int dl_count; + u8 dl_buf[512]; +} buffer_rec; + +/* + * vars controlled by command line options + */ + +bool verbose = FALSE; /* be verbose */ +bool linear = FALSE; /* just write out linear data */ +char *outfilename = "-"; /* default output is stdout */ +u32 base = 0L; /* base address */ +u32 FFfill = 0L; /* how far to fill w 0xFF's */ + +extern char *optarg; /* getopt(3) control vars */ +extern int optind; +extern int errno; + +char *progname; /* for error() */ + +void error(int errn, ...); +#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define ERR_FATAL (ERR_ERRNO / 2) /* error is fatal; no return */ +#define ERR_ABORT (ERR_ERRNO / 4) /* error is fatal; abort */ +#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */ + +#define stol(p) strtol(p, (char **) NULL, 0) + +int unhex(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_Intel_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_S_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +int convert_TI_records(FILE *ifp, char *inm, FILE *ofp, char *onm); +void write_record(buffer_rec *tb, FILE *fp); +int getnibble(char **p); +int getbyte(char **p); +long getNbytes(char **p, int n); +void badformat(char *s, char *fname, char *msg); + +#define get1bytes(p) ((int) getbyte(p)) +#define get2bytes(p) ((int) getNbytes(p, 2)) +#define get3bytes(p) getNbytes(p, 3) +#define get4bytes(p) getNbytes(p, 4) + +char *BADADDR = "Invalid record address"; +char *BADLEN = "Invalid record length"; +char *BADBASE = "Bad base or starting address"; +char *BADFMT = "Unrecognized record type"; +char *BADDATA = "Invalid data byte"; +char *BADCSUM = "Invalid checksum"; +char *MISCSUM = "Checksum mismatch"; +char *BADTYPE = "Unrecognized record type"; +char *MISTYPE = "Incompatible record types"; + +int +main(argc, argv) +int argc; +char **argv; +{ + register int c; + bool showusage = FALSE; /* usage error? */ + int rc = 0; + FILE *outfp, *infp; + + /* + * figure out invocation leaf-name + */ + + if ((progname = strrchr(argv[0], '/')) == (char *) NULL) + progname = argv[0]; + else + progname++; + + argv[0] = progname; /* for getopt err reporting */ + + /* + * Check options and arguments. + */ + + progname = argv[0]; + while ((c = getopt(argc, argv, "F:a:o:vl")) != EOF) + switch (c) + { + case 'a': /* base address */ + base = stol(optarg); + break; + + case 'l': /* linear output */ + linear = TRUE; + break; + + case 'v': /* toggle verbose */ + verbose = ! verbose; + break; + + case 'o': /* output file */ + outfilename = optarg; + break; + + case 'F': /* 0xFF fill amount (bytes) */ + FFfill = stol(optarg) * 1024L / 8L; + break; + + case '?': + showusage = TRUE; + } + + if (showusage) + { + (void) fprintf(stderr, "%s", USAGE); + exit(1); + } + + if (linear && (base != 0)) + { + error(0, "-l and -a may not be specified in combination"); + exit(1); + } + + if (STREQ(outfilename, "-")) + { + outfp = stdout; + outfilename = "stdout"; + } + else + if ((outfp = fopen(outfilename, "w")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for output", outfilename); + exit(1); + } + + /* + * Now process the input files (or stdin, if none specified) + */ + + if (argv[optind] == (char *) NULL) /* just stdin */ + exit(unhex(stdin, "stdin", outfp, outfilename)); + else + for (; (optarg = argv[optind]); optind++) + { + if (STREQ(optarg, "-")) + rc += unhex(stdin, "stdin", outfp, outfilename); + else + { + if ((infp = fopen(optarg, "r")) == (FILE *) NULL) + { + error(-1, "couldn't open '%s' for input", optarg); + exit(1); + } + rc += unhex(infp, optarg, outfp, outfilename); + } + } + + return(rc); +} + +u16 filesum; + +int +unhex(FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + int c; + + filesum = 0; + + /* + * Make sure holes will be filled with 0xFF's if requested. We + * do this the easy way by just filling the file with FF's before + * getting started. To do it more optimally would be quite a bit + * more difficult since the user can skip around as much as he/she + * likes in the input hex file addressing. + * + * We'll clean this up later (after this program has run) with + * 'stripffs' + */ + + if (FFfill) + { + (void) fseek(ofp, 0, 0); + for (c = FFfill; c > 0; c--) + (void) fputc(0xFF, ofp); + } + + /* + * Read the first char from file and determine record types + */ + + if ((c = getc(ifp)) != EOF) + { + ungetc(c, ifp); + switch(c) + { + case 'S': + convert_S_records(ifp, inm, ofp, onm); + break; + + case ':': + convert_Intel_records(ifp, inm, ofp, onm); + break; + + case '9': + case 'B': + convert_TI_records(ifp, inm, ofp, onm); + break; + + default: + { + char tmp[2]; + tmp[0] = c; tmp[1] = 0; + badformat(tmp, inm, BADFMT); + } + } + } + + if (verbose) + fprintf(stderr, "'%s' checksum is 0x%04x\n", inm, filesum); + + return 0; +} + +int +convert_Intel_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int rectype; /* record type */ + int len; /* data length of current line */ + u32 addr; + u32 base_address = 0; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != ':') + badformat(p, inm, BADFMT); + p++; + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + + if ((addr = get2bytes(&p)) == -1L) /* record addr */ + badformat(buff, inm, BADADDR); + + rectype = getbyte(&p); + + cksum = len + B0(addr) + B1(addr) + rectype; + + switch (rectype) + { + case 0x00: /* normal data record */ + tb.dl_destaddr = base_address + addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x01: /* execution start address */ + base_address = addr; + endrecord = TRUE; + break; + + case 0x02: /* new base */ + if ((base_address = get2bytes(&p)) == -1L) + badformat(buff, inm, BADBASE); + cksum += B0(base_address) + B1(base_address); + base_address <<= 4; + break; + + case 0x03: /* seg/off execution start address */ + { + u32 seg, off; + + seg = get2bytes(&p); + off = get2bytes(&p); + if ((seg == -1L) || (off == -1L)) + badformat(buff, inm, BADADDR); + + cksum += B0(seg) + B1(seg) + B0(off) + B1(off); + + tb.dl_jumpaddr = (seg << 4) + off; + break; + } + + default: + error(0, "unknown Intel-hex record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (-cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_S_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + u8 cksum; + int incksum; + int c; + int len; /* data length of current line */ + int rectype; /* record type */ + u32 addr; + bool endrecord = FALSE; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + p = &buff[0]; + + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + if (*p != 'S') + badformat(p, inm, BADFMT); + p++; + + if ((rectype = getnibble(&p)) == -1) /* record type */ + badformat(buff, inm, BADTYPE); + + if ((len = getbyte(&p)) == -1) /* record len */ + badformat(buff, inm, BADLEN); + cksum = len; + + switch (rectype) + { + case 0x00: /* comment field, ignored */ + goto write_it; + + case 0x01: /* data record, 16 bit addr */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 3; + goto doit; + + case 0x02: /* ... 24 bit addr */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 4; + goto doit; + + case 0x03: /* ... 32 bit addr */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + len -= 5; + doit: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + + tb.dl_destaddr = addr; + while (len--) + { + if ((c = getbyte(&p)) == -1) + badformat(buff, inm, BADDATA); + cksum += c; + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + } + break; + + case 0x07: /* 32 bit end record */ + if ((addr = get4bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x08: /* 24 bit end record */ + if ((addr = get3bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + goto end_rec; + + case 0x09: /* 16 bit end record */ + if ((addr = get2bytes(&p)) == -1L) + badformat(buff, inm, BADADDR); + +end_rec: + cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr); + tb.dl_jumpaddr = addr; + break; + + default: + error(0, "unknown Motorola-S record type: 0x%02x", rectype); + badformat(buff, inm, BADTYPE); + break; + } + + /* + * Verify checksums are correct in file. + */ + + cksum = (~cksum) & 0xff; + if ((incksum = getbyte(&p)) == -1) + badformat(buff, inm, BADCSUM); + if (((u8) incksum) != cksum) + badformat(buff, inm, MISCSUM); + +write_it: + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +int +convert_TI_records( + FILE *ifp, + char *inm, + FILE *ofp, + char *onm) +{ + char buff[512]; + char *p; + int c; + bool endrecord = FALSE; + bool eol; + buffer_rec tb; + + while ( ! endrecord && (fgets(buff, sizeof(buff), ifp))) + { + if (p[strlen(p)-1] == '\n') /* get rid of newline */ + p[strlen(p)-1] = '\0'; + + if (p[strlen(p)-1] == '\r') /* get rid of any CR */ + p[strlen(p)-1] = '\0'; + + tb.dl_count = 0; + + p = &buff[0]; + eol = FALSE; + while ( ! eol && ! endrecord) + { + switch (*p++) + { + case '9': + if (tb.dl_count) + write_record(&tb, ofp); + tb.dl_destaddr = get2bytes(&p); + break; + + case 'B': + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + c = getbyte(&p); + filesum += c; + tb.dl_buf[tb.dl_count++] = c; + break; + + case 'F': + eol = TRUE; + break; + + case ':': + endrecord = TRUE; + break; + + default: + badformat(p, inm, BADFMT); + } + } + if (tb.dl_count) + write_record(&tb, ofp); + } + return 0; +} + +void +write_record(buffer_rec *tb, + FILE *fp) +{ + if ( ! linear) + { + if (tb->dl_destaddr < base) + error(ERR_FATAL, "record at address 0x%x precedes base of 0x%x", + tb->dl_destaddr, base); + (void) fseek(fp, tb->dl_destaddr - base, 0); + } + + (void) fwrite(tb->dl_buf, tb->dl_count, 1, fp); + tb->dl_destaddr += tb->dl_count; + tb->dl_count = 0; +} + +int +getnibble(char **p) +{ + register int val; + + **p = toupper(**p); + switch (**p) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + val = **p - '0'; + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + val = 10 + (**p - 'A'); + break; + + default: + return(-1); + } + *p += 1; + + return(val & 0x0f); +} + +int +getbyte(char **p) +{ + int n0, n1; + + if ((n0 = getnibble(p)) == -1) + return(-1); + if ((n1 = getnibble(p)) == -1) + return(-1); + + return(((n0 << 4) + n1) & 0xff); +} + +long +getNbytes(char **p, + int n) +{ + int t; + u32 val = 0; + + while (n--) + { + if ((t = getbyte(p)) == -1) + return(-1L); + val <<= 8; + val += t; + } + + return(val); +} + +void +badformat(char *s, + char *fname, + char *msg) +{ + if (s[strlen(s)-1] == '\n') /* get rid of newline */ + s[strlen(s)-1] = '\0'; + error(0, "line '%s'::\n\tfrom file '%s'; %s", s, fname, msg); + exit(1); +} + +/* + * error(errn, arglist) + * report an error to stderr using printf(3) conventions. + * Any output is preceded by '<progname>: ' + * + * Uses ERR_EXIT bit to request exit(errn) + * ERR_ABORT to request abort() + * ERR_ERRNO to indicate use of errno instead of argument. + * + * If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its + * associated error message is appended to the output. + */ + +/*VARARGS*/ + +void +error(int error_flag, ...) +{ + va_list arglist; + register char *format; + extern char *sys_errlist[]; + extern int sys_nerr; + int local_errno; + + extern int errno; + + (void) fflush(stdout); /* in case stdout/stderr same */ + + local_errno = error_flag & ~ERR_MASK; + if (error_flag & ERR_ERRNO) /* use errno? */ + local_errno = errno; + + va_start(arglist, error_flag); + format = va_arg(arglist, char *); + (void) fprintf(stderr, "%s: ", progname); + (void) vfprintf(stderr, format, arglist); + va_end(arglist); + + if (local_errno) + if ((local_errno > 0) && (local_errno < sys_nerr)) + (void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]); + else + (void) fprintf(stderr, " (unknown errno=%d)\n", local_errno); + else + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (ERR_FATAL | ERR_ABORT)) + { + if (error_flag & ERR_FATAL) + { + error(0, local_errno ? "fatal error, exiting" : "exiting"); + exit(local_errno); + } + else + { + error(0, "fatal error, aborting"); + abort(); + } + } +} + diff --git a/c/src/README b/c/src/README new file mode 100644 index 0000000000..3e242504dc --- /dev/null +++ b/c/src/README @@ -0,0 +1,27 @@ +# +# $Id$ +# + +This is the top level directory of the C RTEMS environment. The +following is a description of the contents of each file and +subdirectory directly in this directory: + + tests + + This directory contains the RTEMS Test Suites. Currently + this includes the following suites: + + + Single Processor Test Suite + + Multiprocessor Test Suite + + Timing Test Suite + + Sample Application Suite + + lib + + This directory contains src for RTEMS libraries: + libc, board support (including drivers) and libcpu. + + exec + + This directory contains the source code for the RTEMS executive. + diff --git a/c/src/exec/libcsupport/include/clockdrv.h b/c/src/exec/libcsupport/include/clockdrv.h new file mode 100644 index 0000000000..aad9bd6d3b --- /dev/null +++ b/c/src/exec/libcsupport/include/clockdrv.h @@ -0,0 +1,58 @@ +/* clock.h + * + * This file describes the Clock Driver for all boards. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __CLOCK_DRIVER_h +#define __CLOCK_DRIVER_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* variables */ + +extern volatile rtems_unsigned32 Clock_driver_ticks; + +/* functions */ + +rtems_task Exit_task(); +void exit_task_init(); + +void Install_clock( rtems_isr_entry ); +void ReInstall_clock( rtems_isr_entry ); +void Clock_exit(); + +rtems_isr Clock_isr( + rtems_vector_number +); + +/* driver entries */ + +#define CLOCK_DRIVER_TABLE_ENTRY \ + { Clock_initialize, NULL, NULL, NULL, NULL, NULL } + +rtems_device_driver Clock_initialize( + rtems_device_major_number, + rtems_device_minor_number, + void *, + rtems_id, + rtems_unsigned32 * +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/libcsupport/include/console.h b/c/src/exec/libcsupport/include/console.h new file mode 100644 index 0000000000..d102c6a1b1 --- /dev/null +++ b/c/src/exec/libcsupport/include/console.h @@ -0,0 +1,40 @@ +/* console.h + * + * This file describes the Console Device Driver for all boards. + * This driver provides support for the standard C Library. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef _CONSOLE_DRIVER_h +#define _CONSOLE_DRIVER_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONSOLE_DRIVER_TABLE_ENTRY \ + { console_initialize, NULL, NULL, NULL, NULL, NULL } + +rtems_device_driver console_initialize( + rtems_device_major_number, + rtems_device_minor_number, + void *, + rtems_id, + rtems_unsigned32 * +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/libcsupport/include/iosupp.h b/c/src/exec/libcsupport/include/iosupp.h new file mode 100644 index 0000000000..5f4a83b8ca --- /dev/null +++ b/c/src/exec/libcsupport/include/iosupp.h @@ -0,0 +1,44 @@ +/* iosupp.h + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __IOSUPP_h +#define __IOSUPP_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* character constants */ + +#define BS 0x08 /* backspace */ +#define LF 0x0a /* line feed */ +#define CR 0x0d /* carriage return */ +#define XON 0x11 /* control-Q */ +#define XOFF 0x13 /* control-S */ + +/* structures */ + +#ifdef IOSUPP_INIT +#define IOSUPP_EXTERN +#else +#undef IOSUPP_EXTERN +#define IOSUPP_EXTERN extern +#endif + +/* functions */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/exec/libcsupport/include/rtems/libcsupport.h b/c/src/exec/libcsupport/include/rtems/libcsupport.h new file mode 100644 index 0000000000..2b199707f8 --- /dev/null +++ b/c/src/exec/libcsupport/include/rtems/libcsupport.h @@ -0,0 +1,47 @@ +/* libcsupport.h + * + * This include file contains the information regarding the + * RTEMS specific support for the standard C library. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __LIBC_SUPPORT_h +#define __LIBC_SUPPORT_h + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +void RTEMS_Malloc_Initialize( + void *start, + size_t length, + size_t sbrk_amount +); + +extern void libc_init(int reentrant); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/libcsupport/include/spurious.h b/c/src/exec/libcsupport/include/spurious.h new file mode 100644 index 0000000000..428e826164 --- /dev/null +++ b/c/src/exec/libcsupport/include/spurious.h @@ -0,0 +1,38 @@ +/* spurious.h + * + * This file describes the Spurious Interrupt Driver for all boards. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993. + * On-Line Applications Research Corporation (OAR). + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __SPURIOUS_h +#define __SPURIOUS_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPURIOUS_DRIVER_TABLE_ENTRY \ + { Spurious_Initialize, NULL, NULL, NULL, NULL, NULL } + +rtems_device_driver Spurious_Initialize( + rtems_device_major_number, + rtems_device_minor_number, + void *, + rtems_id, + rtems_unsigned32 * +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/libcsupport/include/timerdrv.h b/c/src/exec/libcsupport/include/timerdrv.h new file mode 100644 index 0000000000..d091b62410 --- /dev/null +++ b/c/src/exec/libcsupport/include/timerdrv.h @@ -0,0 +1,40 @@ +/* timerdrv.h + * + * This file describes the Timer Driver for all boards. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __TIMER_DRIVER_h +#define __TIMER_DRIVER_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* functions */ + +void Timer_initialize( void ); + +rtems_unsigned32 Read_timer( void ); + +rtems_status_code Empty_function( void ); + +void Set_find_average_overhead( + rtems_boolean find_flag +); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/libcsupport/include/vmeintr.h b/c/src/exec/libcsupport/include/vmeintr.h new file mode 100644 index 0000000000..6148114ce8 --- /dev/null +++ b/c/src/exec/libcsupport/include/vmeintr.h @@ -0,0 +1,58 @@ +/* + * vmeintr.h + * + * This file is the specification for the VMEbus interface library + * which should be provided by all BSPs for VMEbus Single Board + * Computers but currently only a few do so. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __VME_INTERRUPT_h +#define __VME_INTERRUPT_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This defines the mask which is used to determine which + * interrupt levels are affected by a call to this package. + * The LSB corresponds to VME interrupt 0 and the MSB + * to VME interrupt 7. + * + */ + +typedef rtems_unsigned8 VME_interrupt_Mask; + +/* + * VME_interrupt_Disable + * + */ + +void VME_interrupt_Disable ( + VME_interrupt_Mask mask /* IN */ +); + +/* + * VME_interrupt_Disable + * + */ + +void VME_interrupt_Enable ( + VME_interrupt_Mask mask /* IN */ +); + +#ifdef __cplusplus +} +#endif + +#endif /* end of include file */ diff --git a/c/src/exec/libcsupport/src/README b/c/src/exec/libcsupport/src/README new file mode 100644 index 0000000000..ee7a90501e --- /dev/null +++ b/c/src/exec/libcsupport/src/README @@ -0,0 +1,37 @@ +-- +-- $Id$ +-- + +Overview of newlib support (newlib is from CYGNUS) + Each task can have its own libc state including: + open stdio files + strtok + multi precision arithmetic state + etc. + + This is implemented by a reentrancy data structure for each task. + + When a task is "started" (in RTEMS sense) the reentrancy structure + is allocated. Its address is stored in notepad[NOTEPAD_LAST]. + + When task is switched to, the value of global variable _impure_ptr + is changed to the value of the new tasks reentrancy structure. + + When a task is deleted + atexit() processing (for that task) happens + task's stdio buffers are flushed + + When exit(3) is called + calling task's atexit processing done + global libc state atexit processing done + (this will include any atexit routines installed by drivers) + executive is shutdown + causes a context switch back to bsp land + + +NOTE: + libc extension are installed by bsp_libc_init() + iff we are using clock interrupts. + This hack is necessary to allow the tmtests to avoid + timing the extensions. + diff --git a/c/src/exec/libcsupport/src/__brk.c b/c/src/exec/libcsupport/src/__brk.c new file mode 100644 index 0000000000..6fb15342fe --- /dev/null +++ b/c/src/exec/libcsupport/src/__brk.c @@ -0,0 +1,40 @@ +/* + * RTEMS "Broken" __brk/__sbrk Implementation + * + * NOTE: sbrk is BSP provided. + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include <rtems.h> + +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#ifdef RTEMS_NEWLIB +#include <reent.h> +#endif +#include <unistd.h> + +/* we use RTEMS for memory management. We don't need sbrk */ + +void * __sbrk(int incr) +{ + errno = EINVAL; + return (void *)0; +} + +int __brk( const void *endds ) +{ + errno = EINVAL; + return -1; +} diff --git a/c/src/exec/libcsupport/src/__gettod.c b/c/src/exec/libcsupport/src/__gettod.c new file mode 100644 index 0000000000..a1ab9776c8 --- /dev/null +++ b/c/src/exec/libcsupport/src/__gettod.c @@ -0,0 +1,84 @@ +#if !defined(RTEMS_UNIX) +/* + * RTEMS gettimeofday Implementation + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include <rtems.h> + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#endif +#include <time.h> +#include <sys/time.h> +#include <errno.h> +#include <assert.h> + +/* + * NOTE: The solaris gettimeofday does not have a second parameter. + */ + +int gettimeofday( + struct timeval *tp, + struct timezone *tzp +) +{ + rtems_status_code status; + rtems_clock_time_value time; + + if ( !tp || !tzp ) { + errno = EFAULT; + return -1; + } + + /* "POSIX" does not seem to allow for not having a TOD */ + status = rtems_clock_get( RTEMS_CLOCK_GET_TIME_VALUE, &time ); + if ( status != RTEMS_SUCCESSFUL ) { + assert( 0 ); + return -1; + } + + tp->tv_sec = time.seconds; + tp->tv_usec = time.microseconds; + +#if 0 + tzp->minuteswest = timezone / 60; /* from seconds to minutes */ + tzp->dsttime = daylight; +#endif + + /* + * newlib does not have timezone and daylight savings time + * yet. When it does this needs to be fixed. + */ + + tzp->tz_minuteswest = 0; /* at UTC */ + tzp->tz_dsttime = 0; /* no daylight savings */ + return 0; +} + +/* + * "Reentrant" versions of the above routines implemented above. + */ + +#if 0 +int _gettimeofday_r( + struct _reent *ignored_reentrancy_stuff, + struct timeval *tp, + struct timezone *tzp +) +{ + return gettimeofday( tp, tzp ); +} +#endif + +#endif diff --git a/c/src/exec/libcsupport/src/__times.c b/c/src/exec/libcsupport/src/__times.c new file mode 100644 index 0000000000..12fd9241fe --- /dev/null +++ b/c/src/exec/libcsupport/src/__times.c @@ -0,0 +1,65 @@ +/* + * RTEMS _times Implementation + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include <rtems.h> + +#include <sys/times.h> +#include <time.h> +#include <sys/time.h> +#include <errno.h> +#include <assert.h> + +clock_t _times( + struct tms *ptms +) +{ + rtems_status_code status; + rtems_interval ticks_since_boot; + + if ( !ptms ) { + errno = EFAULT; + return -1; + } + + /* "POSIX" does not seem to allow for not having a TOD */ + status = rtems_clock_get( + RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, + &ticks_since_boot + ); + if ( status != RTEMS_SUCCESSFUL ) { + assert( 0 ); + return -1; + } + + /* + * RTEMS has no notion of system versus user time and does + * not (as of 3.2.0) keep track of CPU usage on a per task basis. + */ + + ptms->tms_utime = ticks_since_boot; + ptms->tms_stime = 0; + ptms->tms_cutime = 0; + ptms->tms_cstime = 0; + + return 0; +} + +clock_t times( + struct tms *ptms +) +{ + return _times( ptms ); +} + diff --git a/c/src/exec/libcsupport/src/malloc.c b/c/src/exec/libcsupport/src/malloc.c new file mode 100644 index 0000000000..7d0ba04143 --- /dev/null +++ b/c/src/exec/libcsupport/src/malloc.c @@ -0,0 +1,280 @@ +/* + * RTEMS Malloc Family Implementation + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include <rtems.h> +#ifdef RTEMS_LIBC +#include <memory.h> +#endif +#include "libcsupport.h" +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> +#include <string.h> + +/* + * XXX: Do we really need to duplicate these? It appears that they + * only cause typing problems. + */ + +#if 0 +void *malloc(size_t); +void *calloc(size_t, size_t); +void *realloc(void *, size_t); +void free(void *); +void *sbrk(size_t); +#endif + +rtems_id RTEMS_Malloc_Heap; +size_t RTEMS_Malloc_Sbrk_amount; + +void RTEMS_Malloc_Initialize( + void *start, + size_t length, + size_t sbrk_amount +) +{ + rtems_status_code status; + void *starting_address; + rtems_unsigned32 u32_address; + + /* + * If the starting address is 0 then we are to attempt to + * get length worth of memory using sbrk. Make sure we + * align the address that we get back. + */ + + starting_address = start; + + if (!starting_address) { + u32_address = (unsigned int)sbrk(length); + + if (u32_address == -1) { + rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); + /* DOES NOT RETURN!!! */ + } + + if (u32_address & (CPU_ALIGNMENT-1)) { + u32_address = (u32_address + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); + /* XXX: if we do any alignment .. then length should be shortened */ + } + + starting_address = (void *)u32_address; + } + + /* + * Unfortunately we cannot use assert if this fails because if this + * has failed we do not have a heap and if we do not have a heap + * STDIO cannot work because there will be no buffers. + */ + + status = rtems_region_create( + rtems_build_name( 'H', 'E', 'A', 'P' ), + starting_address, + length, + 8, /* XXX : use CPU dependent RTEMS constant */ + RTEMS_DEFAULT_ATTRIBUTES, + &RTEMS_Malloc_Heap + ); + if ( status != RTEMS_SUCCESSFUL ) + rtems_fatal_error_occurred( status ); +} + +void *malloc( + size_t size +) +{ + void *return_this; + void *starting_address; + rtems_unsigned32 the_size; + rtems_unsigned32 sbrk_amount; + rtems_status_code status; + + if ( !size ) + return (void *) 0; + + /* + * Try to give a segment in the current region if there is not + * enough space then try to grow the region using rtems_region_extend(). + * If this fails then return a NULL pointer. + */ + + status = rtems_region_get_segment( + RTEMS_Malloc_Heap, + size, + RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT, + &return_this + ); + + if ( status != RTEMS_SUCCESSFUL ) { + /* + * Round to the "requested sbrk amount" so hopefully we won't have + * to grow again for a while. This effectively does sbrk() calls + * in "page" amounts. + */ + + sbrk_amount = RTEMS_Malloc_Sbrk_amount; + + if ( sbrk_amount == 0 ) + return (void *) 0; + + the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount); + + if (((rtems_unsigned32)starting_address = sbrk(the_size)) == -1) + return (void *) 0; + + /* + fprintf(stderr, "Extended the C heap starting at 0x%x for %d bytes\n", + (unsigned32)starting_address, the_size); + */ + + status = rtems_region_extend( + RTEMS_Malloc_Heap, + starting_address, + the_size + ); + if ( status != RTEMS_SUCCESSFUL ) { + sbrk(-the_size); + return(FALSE); + errno = ENOMEM; + return (void *) 0; + } + status = rtems_region_get_segment( + RTEMS_Malloc_Heap, + size, + RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT, + &return_this + ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = ENOMEM; + return (void *) 0; + } + } + + return return_this; +} + +void *calloc( + size_t nelem, + size_t elsize +) +{ + register char *cptr; + int length; + + length = nelem * elsize; + cptr = malloc( length ); + if ( cptr ) + memset( cptr, '\0', length ); + + return cptr; +} + +void *realloc( + void *ptr, + size_t size +) +{ + rtems_unsigned32 old_size; + rtems_status_code status; + char *new_area; + + if ( !ptr ) + return malloc( size ); + + if ( !size ) { + free( ptr ); + return (void *) 0; + } + + status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + return (void *) 0; + } + + new_area = malloc( size ); + if ( !new_area ) { + free( ptr ); + return (void *) 0; + } + + memcpy( new_area, ptr, (size < old_size) ? size : old_size ); + free( ptr ); + + return new_area; + +} + +void free( + void *ptr +) +{ + rtems_status_code status; + + if ( !ptr ) + return; + + status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + assert( 0 ); + } +} + +/* + * "Reentrant" versions of the above routines implemented above. + */ + +#ifdef RTEMS_NEWLIB +void *malloc_r( + struct _reent *ignored, + size_t size +) +{ + return malloc( size ); +} + +void *calloc_r( + size_t nelem, + size_t elsize +) +{ + return calloc( nelem, elsize ); +} + +void *realloc_r( + void *ptr, + size_t size +) +{ + return realloc_r( ptr, size ); +} + +void free_r( + void *ptr +) +{ + free( ptr ); +} +#endif + diff --git a/c/src/exec/libcsupport/src/newlibc.c b/c/src/exec/libcsupport/src/newlibc.c new file mode 100644 index 0000000000..3c5e58b67c --- /dev/null +++ b/c/src/exec/libcsupport/src/newlibc.c @@ -0,0 +1,292 @@ +/* + * @(#)newlibc.c 1.8 - 95/04/25 + * + */ + +#if defined(RTEMS_NEWLIB) + +/* + * File: $RCSfile$ + * Project: PixelFlow + * Created: 94/12/7 + * Revision: $Revision$ + * Last Mod: $Date$ + * + * COPYRIGHT (c) 1994 by Division Incorporated + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Division Incorporated not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Division Incorporated makes no representations about the + * suitability of this software for any purpose. + * + * Description: + * Implementation of hooks for the CYGNUS newlib libc + * These hooks set things up so that: + * '_REENT' is switched at task switch time. + * + * + * TODO: + * + * NOTE: + * + * $Id$ + * + */ + +#include <rtems.h> +#include <libcsupport.h> +#include <stdlib.h> /* for free() */ +#include <string.h> /* for memset() */ + +#include <sys/reent.h> /* for extern of _REENT (aka _impure_ptr) */ + +#include "internal.h" + +#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST + + +int libc_reentrant; /* do we think we are reentrant? */ +struct _reent libc_global_reent = _REENT_INIT(libc_global_reent);; + +/* + * CYGNUS newlib routine that does atexit() processing and flushes + * stdio streams + * undocumented + */ + +extern void _wrapup_reent(struct _reent *); +extern void _reclaim_reent(struct _reent *); + +void +libc_wrapup(void) +{ + _wrapup_reent(0); + if (_REENT != &libc_global_reent) + { + _wrapup_reent(&libc_global_reent); +#if 0 + /* don't reclaim this one, just in case we do printfs */ + /* on our way out to ROM */ + _reclaim_reent(&libc_global_reent); +#endif + _REENT = &libc_global_reent; + } +} + + +rtems_extension +libc_create_hook(rtems_tcb *current_task, + rtems_tcb *creating_task) +{ + MY_task_set_note(creating_task, LIBC_NOTEPAD, 0); +} + +/* + * Called for all user TASKS (system tasks are SYSI and IDLE) + */ + +rtems_extension +libc_start_hook(rtems_tcb *current_task, + rtems_tcb *starting_task) +{ + struct _reent *ptr; + + /* NOTE: our malloc is reentrant without a reent ptr since + * it is based on region manager + */ + + ptr = (struct _reent *) malloc(sizeof(struct _reent)); + + /* GCC extension: structure constants */ + *ptr = (struct _reent) _REENT_INIT((*ptr)); + + MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr); +} + +rtems_extension +libc_switch_hook(rtems_tcb *current_task, + rtems_tcb *heir_task) +{ + rtems_unsigned32 impure_value; + + /* XXX We can't use rtems_task_set_note() here since SYSI task has a + * tid of 0, which is treated specially (optimized, actually) + * by rtems_task_set_note + */ + + impure_value = (rtems_unsigned32) _REENT; + MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value); + + _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD); + +} + +/* + * Function: libc_delete_hook + * Created: 94/12/10 + * + * Description: + * Called when a task is deleted. + * Must restore the new lib reentrancy state for the new current + * task. + * + * Parameters: + * + * + * Returns: + * + * + * Side Effects: + * + * Notes: + * + * + * Deficiencies/ToDo: + * + * + */ +rtems_extension +libc_delete_hook(rtems_tcb *current_task, + rtems_tcb *deleted_task) +{ + struct _reent *ptr; + + /* + * The reentrancy structure was allocated by newlib using malloc() + */ + + if (current_task == deleted_task) + { + ptr = _REENT; + } + else + { + ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD); + } + + if (ptr) + { + _wrapup_reent(ptr); + _reclaim_reent(ptr); + } + + MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0); + + /* + * Require the switch back to another task to install its own + */ + + if (current_task == deleted_task) + { + _REENT = 0; + } +} + +/* + * Function: libc_init + * Created: 94/12/10 + * + * Description: + * Init libc for CYGNUS newlib + * Set up _REENT to use our global libc_global_reent. + * (newlib provides a global of its own, but we prefer our + * own name for it) + * + * If reentrancy is desired (which it should be), then + * we install the task extension hooks to maintain the + * newlib reentrancy global variable _REENT on task + * create, delete, switch, exit, etc. + * + * Parameters: + * reentrant non-zero if reentrant library desired. + * + * Returns: + * + * Side Effects: + * installs libc extensions if reentrant. + * + * Notes: + * + * + * Deficiencies/ToDo: + * + */ + +void +libc_init(int reentrant) +{ + rtems_extensions_table libc_extension; + rtems_id extension_id; + rtems_status_code rc; + + _REENT = &libc_global_reent; + + if (reentrant) + { + memset(&libc_extension, 0, sizeof(libc_extension)); + + libc_extension.rtems_task_create = libc_create_hook; + libc_extension.rtems_task_start = libc_start_hook; + libc_extension.task_switch = libc_switch_hook; + libc_extension.rtems_task_delete = libc_delete_hook; + + rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'), + &libc_extension, &extension_id); + if (rc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(rc); + + libc_reentrant = reentrant; + } +} + + +void +exit(int status) +{ + libc_wrapup(); + rtems_shutdown_executive(status); +} + + +/* + * Function: _exit + * Created: 94/12/10 + * + * Description: + * Called from exit() after it does atexit() processing and stdio fflush's + * + * called from bottom of exit() to really delete the task. + * If we are using reentrant libc, then let the delete extension + * do all the work, otherwise if a shutdown is in progress, + * then just do it. + * + * Parameters: + * exit status + * + * Returns: + * does not return + * + * Side Effects: + * + * Notes: + * + * + * Deficiencies/ToDo: + * + * + */ + +#ifndef RTEMS_UNIX +void _exit(int status) +{ + rtems_shutdown_executive(status); +} +#endif + +#endif diff --git a/c/src/exec/libcsupport/src/no_libc.c b/c/src/exec/libcsupport/src/no_libc.c new file mode 100644 index 0000000000..43a91eb30e --- /dev/null +++ b/c/src/exec/libcsupport/src/no_libc.c @@ -0,0 +1,45 @@ +#if !defined(RTEMS_LIBC) && !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX) + +/* no_libc.h + * + * This file contains stubs for the reentrancy hooks when + * an unknown C library is used. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + + +#include <rtems.h> + +#include "libcsupport.h" +#include "internal.h" + +#include <stdlib.h> /* for free() */ + +void +libc_init(int reentrant) +{ +} + +void libc_suspend_main(void) +{ +} + + +void libc_global_exit(rtems_unsigned32 code) +{ +} + +void _exit(int status) +{ +} + +#endif diff --git a/c/src/exec/libcsupport/src/unixlibc.c b/c/src/exec/libcsupport/src/unixlibc.c new file mode 100644 index 0000000000..74b4eea360 --- /dev/null +++ b/c/src/exec/libcsupport/src/unixlibc.c @@ -0,0 +1,7 @@ +#if defined(RTEMS_UNIXLIB) + +void libc_init(int reentrant) +{ +} + +#endif diff --git a/c/src/exec/rtems/headers/asr.h b/c/src/exec/rtems/headers/asr.h new file mode 100644 index 0000000000..44d03f2802 --- /dev/null +++ b/c/src/exec/rtems/headers/asr.h @@ -0,0 +1,177 @@ +/* asr.h + * + * This include file contains all the constants and structures associated + * with the Asynchronous Signal Handler. This Handler provides the low-level + * support required by the Signal Manager. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __RTEMS_ASR_h +#define __RTEMS_ASR_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/modes.h> + +/* + * + * The following type defines the control block used to manage + * each signal set. + */ + +typedef unsigned32 rtems_signal_set; + +/* + * Return type for ASR Handler + */ + +typedef void rtems_asr; + +/* + * The following type corresponds to the applications asynchronous + * signal processing routine. + */ + +typedef rtems_asr ( *rtems_asr_entry )( + rtems_signal_set + ); + +/* + * + * The following defines the control structure used to manage + * signals. Each thread has a copy of this record. + */ + +typedef struct { + rtems_asr_entry handler; /* address of RTEMS_ASR */ + rtems_mode mode_set; /* RTEMS_ASR mode */ + rtems_signal_set signals_posted; /* signal set */ + rtems_signal_set signals_pending; /* pending signal set */ + unsigned32 nest_level; /* nest level of RTEMS_ASR */ +} ASR_Information; + +/* + * The following constants define the individual signals which may + * be used to compose a signal set. + */ + +#define RTEMS_SIGNAL_0 0x00000001 +#define RTEMS_SIGNAL_1 0x00000002 +#define RTEMS_SIGNAL_2 0x00000004 +#define RTEMS_SIGNAL_3 0x00000008 +#define RTEMS_SIGNAL_4 0x00000010 +#define RTEMS_SIGNAL_5 0x00000020 +#define RTEMS_SIGNAL_6 0x00000040 +#define RTEMS_SIGNAL_7 0x00000080 +#define RTEMS_SIGNAL_8 0x00000100 +#define RTEMS_SIGNAL_9 0x00000200 +#define RTEMS_SIGNAL_10 0x00000400 +#define RTEMS_SIGNAL_11 0x00000800 +#define RTEMS_SIGNAL_12 0x00001000 +#define RTEMS_SIGNAL_13 0x00002000 +#define RTEMS_SIGNAL_14 0x00004000 +#define RTEMS_SIGNAL_15 0x00008000 +#define RTEMS_SIGNAL_16 0x00010000 +#define RTEMS_SIGNAL_17 0x00020000 +#define RTEMS_SIGNAL_18 0x00040000 +#define RTEMS_SIGNAL_19 0x00080000 +#define RTEMS_SIGNAL_20 0x00100000 +#define RTEMS_SIGNAL_21 0x00200000 +#define RTEMS_SIGNAL_22 0x00400000 +#define RTEMS_SIGNAL_23 0x00800000 +#define RTEMS_SIGNAL_24 0x01000000 +#define RTEMS_SIGNAL_25 0x02000000 +#define RTEMS_SIGNAL_26 0x04000000 +#define RTEMS_SIGNAL_27 0x08000000 +#define RTEMS_SIGNAL_28 0x10000000 +#define RTEMS_SIGNAL_29 0x20000000 +#define RTEMS_SIGNAL_30 0x40000000 +#define RTEMS_SIGNAL_31 0x80000000 + +/* + * _ASR_Initialize + * + * DESCRIPTION: + * + * This routine initializes the given RTEMS_ASR information record. + */ + +STATIC INLINE void _ASR_Initialize ( + ASR_Information *information +); + +/* + * _ASR_Swap_signals + * + * DESCRIPTION: + * + * This routine atomically swaps the pending and posted signal + * sets. This is done when the thread alters its mode in such a + * way that the RTEMS_ASR disable/enable flag changes. + */ + +STATIC INLINE void _ASR_Swap_signals ( + ASR_Information *information +); + +/* + * _ASR_Is_null_handler + * + * DESCRIPTION: + * + * This function returns TRUE if the given asr_handler is NULL and + * FALSE otherwise. + */ + +STATIC INLINE boolean _ASR_Is_null_handler ( + rtems_asr_entry asr_handler +); + +/* + * _ASR_Are_signals_pending + * + * DESCRIPTION: + * + * This function returns TRUE if there are signals pending in the + * given RTEMS_ASR information record and FALSE otherwise. + */ + +STATIC INLINE boolean _ASR_Are_signals_pending ( + ASR_Information *information +); + +/* + * _ASR_Post_signals + * + * DESCRIPTION: + * + * This routine posts the given signals into the signal_set + * passed in. The result is returned to the user in signal_set. + * + * NOTE: This must be implemented as a macro. + */ + +STATIC INLINE void _ASR_Post_signals( + rtems_signal_set signals, + rtems_signal_set *signal_set +); + +#include <rtems/asr.inl> + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/rtems/headers/attr.h b/c/src/exec/rtems/headers/attr.h new file mode 100644 index 0000000000..1c59c98dcd --- /dev/null +++ b/c/src/exec/rtems/headers/attr.h @@ -0,0 +1,188 @@ +/* attr.h + * + * This include file contains all information about the Object Attributes + * Handler. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __RTEMS_ATTRIBUTES_h +#define __RTEMS_ATTRIBUTES_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* types */ + +typedef unsigned32 rtems_attribute; + +/* constants */ + +#define RTEMS_DEFAULT_ATTRIBUTES 0x00000000 + +#define RTEMS_NO_FLOATING_POINT 0x00000000 /* don't use FP HW */ +#define RTEMS_FLOATING_POINT 0x00000001 /* utilize coprocessor */ + +#define RTEMS_LOCAL 0x00000000 /* local resource */ +#define RTEMS_GLOBAL 0x00000002 /* global resource */ + +#define RTEMS_FIFO 0x00000000 /* process RTEMS_FIFO */ +#define RTEMS_PRIORITY 0x00000004 /* process by priority */ + +#define RTEMS_NO_LIMIT 0x00000000 /* unlimited Q entries */ +#define RTEMS_LIMIT 0x00000008 /* limit Q entries */ + +#define RTEMS_COUNTING_SEMAPHORE 0x00000000 +#define RTEMS_BINARY_SEMAPHORE 0x00000010 + +#define RTEMS_NO_INHERIT_PRIORITY 0x00000000 +#define RTEMS_INHERIT_PRIORITY 0x00000020 + +#if ( CPU_HARDWARE_FP == TRUE ) +#define ATTRIBUTES_NOT_SUPPORTED 0 +#else +#define ATTRIBUTES_NOT_SUPPORTED RTEMS_FLOATING_POINT +#endif + +#if ( CPU_ALL_TASKS_ARE_FP == TRUE ) +#define ATTRIBUTES_REQUIRED RTEMS_FLOATING_POINT +#else +#define ATTRIBUTES_REQUIRED 0 +#endif + +/* + * _Attributes_Handler_initialization + * + * DESCRIPTION: + * + * This routine performs initialization for this handler. + * + * NOTE: There is no initialization required in C. Conditional compilation + * takes care of this in C. + */ + +#define _Attributes_Handler_initialization() + +/* + * _Attributes_Set + * + * DESCRIPTION: + * + * This function sets the requested new_attributes in the attribute_set + * passed in. The result is returned to the user. + */ + +STATIC INLINE rtems_attribute _Attributes_Set ( + rtems_attribute new_attributes, + rtems_attribute attribute_set +); + +/* + * _Attributes_Clear + * + * DESCRIPTION: + * + * This function clears the requested new_attributes in the attribute_set + * passed in. The result is returned to the user. + */ + +STATIC INLINE rtems_attribute _Attributes_Clear ( + rtems_attribute attribute_set, + rtems_attribute mask +); + +/* + * _Attributes_Is_floating_point + * + * DESCRIPTION: + * + * This function returns TRUE if the floating point attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_floating_point( + rtems_attribute attribute_set +); + +/* + * _Attributes_Is_global + * + * DESCRIPTION: + * + * This function returns TRUE if the global object attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_global( + rtems_attribute attribute_set +); + +/* + * _Attributes_Is_priority + * + * DESCRIPTION: + * + * This function returns TRUE if the priority attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_priority( + rtems_attribute attribute_set +); + +/* + * _Attributes_Is_limit + * + * DESCRIPTION: + * + * This function returns TRUE if the limited attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_limit( + rtems_attribute attribute_set +); + +/* + * _Attributes_Is_binary_semaphore + * + * DESCRIPTION: + * + * This function returns TRUE if the binary semaphore attribute is + * enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_binary_semaphore( + rtems_attribute attribute_set +); + +/* + * _Attributes_Is_inherit_priority + * + * DESCRIPTION: + * + * This function returns TRUE if the priority inheritance attribute + * is enabled in the attribute_set and FALSE otherwise. + */ + +STATIC INLINE boolean _Attributes_Is_inherit_priority( + rtems_attribute attribute_set +); + +#include <rtems/attr.inl> + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/rtems/headers/clock.h b/c/src/exec/rtems/headers/clock.h new file mode 100644 index 0000000000..e849ab4f40 --- /dev/null +++ b/c/src/exec/rtems/headers/clock.h @@ -0,0 +1,102 @@ +/* clock.h + * + * This include file contains all the constants and structures associated + * with the Clock Manager. This manager provides facilities to set, obtain, + * and continually update the current date and time. + * + * This manager provides directives to: + * + * + set the current date and time + * + obtain the current date and time + * + announce a clock tick + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __RTEMS_CLOCK_h +#define __RTEMS_CLOCK_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/tod.h> + +/* + * List of things which can be returned by the rtems_clock_get directive. + */ + +typedef enum { + RTEMS_CLOCK_GET_TOD, + RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH, + RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, + RTEMS_CLOCK_GET_TICKS_PER_SECOND, + RTEMS_CLOCK_GET_TIME_VALUE +} rtems_clock_get_options; + +/* + * Standard flavor style to return TOD in for a rtems_clock_get option. + */ + +typedef struct { + unsigned32 seconds; + unsigned32 microseconds; +} rtems_clock_time_value; + +/* + * rtems_clock_get + * + * DESCRIPTION: + * + * This routine implements the rtems_clock_get directive. It returns + * one of the following: + * + current time of day + * + seconds since epoch + * + ticks since boot + * + ticks per second + */ + +rtems_status_code rtems_clock_get( + rtems_clock_get_options option, + void *time_buffer +); + +/* + * rtems_clock_set + * + * DESCRIPTION: + * + * This routine implements the rtems_clock_set directive. It sets + * the current time of day to that in the time_buffer record. + */ + +rtems_status_code rtems_clock_set( + rtems_time_of_day *time_buffer +); + +/* + * rtems_clock_tick + * + * DESCRIPTION: + * + * This routine implements the rtems_clock_tick directive. It is invoked + * to inform RTEMS of the occurrence of a clock tick. + */ + +rtems_status_code rtems_clock_tick( void ); + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/rtems/headers/dpmem.h b/c/src/exec/rtems/headers/dpmem.h new file mode 100644 index 0000000000..669eb394d8 --- /dev/null +++ b/c/src/exec/rtems/headers/dpmem.h @@ -0,0 +1,210 @@ +/* dpmem.h + * + * This include file contains all the constants and structures associated + * with the Dual Ported Memory Manager. This manager provides a mechanism + * for converting addresses between internal and external representations + * for multiple dual-ported memory areas. + * + * Directives provided are: + * + * + create a port + * + get ID of a port + * + delete a port + * + convert external to internal address + * + convert internal to external address + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __RTEMS_DUAL_PORTED_MEMORY_h +#define __RTEMS_DUAL_PORTED_MEMORY_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems/object.h> + +/* + * The following structure defines the port control block. Each port + * has a control block associated with it. This control block contains + * all information required to support the port related operations. + */ + +typedef struct { + Objects_Control Object; + void *internal_base; /* base internal address */ + void *external_base; /* base external address */ + unsigned32 length; /* length of dual-ported area */ +} Dual_ported_memory_Control; + +/* + * The following define the internal Dual Ported Memory information. + */ + +EXTERN Objects_Information _Dual_ported_memory_Information; + +/* + * _Dual_ported_memory_Manager_initialization + * + * DESCRIPTION: + * + * This routine performs the initialization necessary for this manager. + */ + +void _Dual_ported_memory_Manager_initialization( + unsigned32 maximum_ports +); + +/* + * rtems_port_create + * + * DESCRIPTION: + * + * This routine implements the rtems_port_create directive. The port + * will have the name name. The port maps onto an area of dual ported + * memory of length bytes which has internal_start and external_start + * as the internal and external starting addresses, respectively. + * It returns the id of the created port in ID. + */ + +rtems_status_code rtems_port_create( + Objects_Name name, + void *internal_start, + void *external_start, + unsigned32 length, + Objects_Id *id +); + +/* + * rtems_port_ident + * + * DESCRIPTION: + * + * This routine implements the rtems_port_ident directive. This directive + * returns the port ID associated with name. If more than one port is + * named name, then the port to which the ID belongs is arbitrary. + */ + +rtems_status_code rtems_port_ident( + Objects_Name name, + Objects_Id *id +); + +/* + * rtems_port_delete + * + * DESCRIPTION: + * + * This routine implements the rtems_port_delete directive. It deletes + * the port associated with ID. + */ + +rtems_status_code rtems_port_delete( + Objects_Id id +); + +/* + * rtems_port_external_to_internal + * + * DESCRIPTION: + * + * This routine implements the rtems_port_external_to_internal directive. + * It returns the internal port address which maps to the provided + * external port address for the specified port ID. + */ + +rtems_status_code rtems_port_external_to_internal( + Objects_Id id, + void *external, + void **internal +); + +/* + * rtems_port_internal_to_external + * + * DESCRIPTION: + * + * This routine implements the Port_internal_to_external directive. + * It returns the external port address which maps to the provided + * internal port address for the specified port ID. + */ + +rtems_status_code rtems_port_internal_to_external( + Objects_Id id, + void *internal, + void **external +); + +/* + * _Dual_ported_memory_Allocate + * + * DESCRIPTION: + * + * This routine allocates a port control block from the inactive chain + * of free port control blocks. + */ + +STATIC INLINE Dual_ported_memory_Control + *_Dual_ported_memory_Allocate ( void ); + +/* + * _Dual_ported_memory_Free + * + * DESCRIPTION: + * + * This routine frees a port control block to the inactive chain + * of free port control blocks. + */ + +STATIC INLINE void _Dual_ported_memory_Free ( + Dual_ported_memory_Control *the_port +); + +/* + * _Dual_ported_memory_Get + * + * DESCRIPTION: + * + * This function maps port IDs to port control blocks. If ID + * corresponds to a local port, then it returns the_port control + * pointer which maps to ID and location is set to OBJECTS_LOCAL. + * Global ports are not supported, thus if ID does not map to a + * local port, location is set to OBJECTS_ERROR and the_port is + * undefined. + */ + +STATIC INLINE Dual_ported_memory_Control *_Dual_ported_memory_Get ( + Objects_Id id, + Objects_Locations *location +); + +/* + * _Dual_ported_memory_Is_null + * + * DESCRIPTION: + * + * This function returns TRUE if the_port is NULL and FALSE otherwise. + */ + +STATIC INLINE boolean _Dual_ported_memory_Is_null( + Dual_ported_memory_Control *the_port +); + +#include <rtems/dpmem.inl> + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/c/src/exec/rtems/headers/event.h b/c/src/exec/rtems/headers/event.h new file mode 100644 index 0000000000..aeb71b2abd --- /dev/null +++ b/c/src/exec/rtems/headers/event.h @@ -0,0 +1,158 @@ +/* event.h + * + * This include file contains the information pertaining to the Event + * Manager. This manager provides a high performance method of communication + * and synchronization. + * + * Directives provided are: + * + * + send an event set to a task + * + receive event condition + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * |