diff -Naur linux-2.4.17.ORG/Documentation/Configure.help linux-2.4.17.evlog_patched/Documentation/Configure.help
--- linux-2.4.17.ORG/Documentation/Configure.help	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/Documentation/Configure.help	Tue Mar 12 09:39:58 2002
@@ -112,6 +112,25 @@
   like MGA monitors that you are very unlikely to see on today's
   systems.
 
+Enterprise event logging
+CONFIG_EVLOG
+  This enables support for enterprise level event logging based upon
+  the draft POSIX 1003.25 standard. Enabling this feature does not affect
+  the operation of the sysklogd package in any way. In order to fully
+  utilize this feature user must also install the companion evlog package
+  in user-space.
+
+  For more information see http://evlog.sourceforge.net
+
+  If you don't know what to do here, say N.
+
+Forward printk messages to enterpise event log
+CONFIG_EVLOG_FWPRINTK
+  This option forwards printk log messages to the enterpise event log.
+  Printk messages still log to /var/log/messages (or where syslog.conf specifies)
+
+  If you don't know what to do here, say N.
+  
 Symmetric Multi-Processing support
 CONFIG_SMP
   This enables support for systems with more than one CPU. If you have
diff -Naur linux-2.4.17.ORG/arch/i386/config.in linux-2.4.17.evlog_patched/arch/i386/config.in
--- linux-2.4.17.ORG/arch/i386/config.in	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/arch/i386/config.in	Tue Mar 12 09:39:58 2002
@@ -198,7 +198,11 @@
 comment 'General setup'
 
 bool 'Networking support' CONFIG_NET
-
+bool 'Enterprise event logging support' CONFIG_EVLOG
+if [ "$CONFIG_EVLOG" != "n" ]; then
+   int 'Eventlog buffer size (in K bytes)' CONFIG_EVLOG_BUFSIZE 128
+   bool 'Forward printk messages to enterprise event log' CONFIG_EVLOG_FWPRINTK
+fi
 # Visual Workstation support is utterly broken.
 # If you want to see it working mail an VW540 to hch@infradead.org 8)
 #bool 'SGI Visual Workstation support' CONFIG_VISWS
diff -Naur linux-2.4.17.ORG/arch/ppc/config.in linux-2.4.17.evlog_patched/arch/ppc/config.in
--- linux-2.4.17.ORG/arch/ppc/config.in	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/arch/ppc/config.in	Tue Mar 12 09:39:58 2002
@@ -153,6 +153,11 @@
 fi
 
 bool 'Networking support' CONFIG_NET
+bool 'Enterprise event logging support' CONFIG_EVLOG
+if [ "$CONFIG_EVLOG" != "n" ]; then
+   int 'Eventlog buffer size (in K bytes)' CONFIG_EVLOG_BUFSIZE 128
+   bool 'Forward printk messages to enterprise event log' CONFIG_EVLOG_FWPRINTK
+fi
 bool 'Sysctl support' CONFIG_SYSCTL
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
diff -Naur linux-2.4.17.ORG/arch/s390/config.in linux-2.4.17.evlog_patched/arch/s390/config.in
--- linux-2.4.17.ORG/arch/s390/config.in	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/arch/s390/config.in	Tue Mar 12 09:39:58 2002
@@ -44,6 +44,11 @@
            vm_reader              CONFIG_IPL_VM" tape
 fi
 bool 'Networking support' CONFIG_NET
+bool 'Enterprise event logging support' CONFIG_EVLOG
+if [ "$CONFIG_EVLOG" != "n" ]; then
+   int 'Eventlog buffer size (in K bytes)' CONFIG_EVLOG_BUFSIZE 128
+   bool 'Forward printk messages to enterprise event log' CONFIG_EVLOG_FWPRINTK
+fi
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
diff -Naur linux-2.4.17.ORG/arch/s390x/config.in linux-2.4.17.evlog_patched/arch/s390x/config.in
--- linux-2.4.17.ORG/arch/s390x/config.in	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/arch/s390x/config.in	Tue Mar 12 09:39:58 2002
@@ -47,6 +47,11 @@
            vm_reader              CONFIG_IPL_VM" tape
 fi
 bool 'Networking support' CONFIG_NET
+bool 'Enterprise event logging support' CONFIG_EVLOG
+if [ "$CONFIG_EVLOG" != "n" ]; then
+   int 'Eventlog buffer size (in K bytes)' CONFIG_EVLOG_BUFSIZE 128
+   bool 'Forward printk messages to enterprise event log' CONFIG_EVLOG_FWPRINTK
+fi
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
diff -Naur linux-2.4.17.ORG/include/linux/evl_log.h linux-2.4.17.evlog_patched/include/linux/evl_log.h
--- linux-2.4.17.ORG/include/linux/evl_log.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4.17.evlog_patched/include/linux/evl_log.h	Tue Mar 12 09:39:58 2002
@@ -0,0 +1,196 @@
+/*
+ * Linux Event Logging for the Enterprise
+ * Copyright (c) International Business Machines Corp., 2001
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Please send e-mail to lkessler@users.sourceforge.net if you have
+ *  questions or comments.
+ *
+ *  Project Website:  http://evlog.sourceforge.net/
+ *
+ */
+
+#ifndef _LINUX_EVL_LOG_H
+#define _LINUX_EVL_LOG_H
+
+#ifndef __KERNEL__
+#ifdef _POSIX_THREADS
+#include <pthread.h>
+#endif
+#endif
+
+/* Values for log_flags member */
+#define POSIX_LOG_TRUNCATE  0x1
+#define EVL_KERNEL_EVENT	0x2
+#define EVL_INITIAL_BOOT_EVENT 	0x4
+#define EVL_KERNTIME_LOCAL	0x8
+
+/* Formats for optional portion of record. */
+#define POSIX_LOG_NODATA    0
+#define POSIX_LOG_BINARY    1
+#define POSIX_LOG_STRING    2
+
+/* Maximum length of variable portion of record */
+#define POSIX_LOG_ENTRY_MAXLEN      (8 * 1024)
+
+/* Maximum length for a string returned by posix_log_memtostr */
+/* Thus also the max length of a facility name */
+#define POSIX_LOG_MEMSTR_MAXLEN	128
+
+typedef unsigned int posix_log_facility_t;
+typedef int posix_log_severity_t;
+typedef int posix_log_recid_t;
+typedef int posix_log_procid_t;
+
+#define EVL_INVALID_FACILITY ((posix_log_facility_t)-1)
+
+struct posix_log_entry {
+	unsigned int            log_magic;
+        posix_log_recid_t   	log_recid;
+        size_t          	log_size;
+        int             	log_format;
+        int             	log_event_type;
+        posix_log_facility_t 	log_facility;
+        posix_log_severity_t    log_severity;
+        uid_t           	log_uid;
+        gid_t           	log_gid;
+        pid_t           	log_pid;
+        pid_t           	log_pgrp;
+        struct timespec 	log_time;
+        unsigned int    	log_flags;
+#ifdef __KERNEL__
+        unsigned long int	log_thread;
+#else
+#ifdef _POSIX_THREADS
+	pthread_t		log_thread;
+#else
+	unsigned long int	log_thread;
+#endif
+#endif
+        posix_log_procid_t	log_processor;
+}; 
+
+typedef struct posix_log_entry rec_hdr_t;
+typedef struct evl_buf_rec {
+        struct posix_log_entry  rechdr;
+        char                    varbuf[1];
+} evl_buf_rec_t;
+
+
+#define LOGFILE_MAGIC   0xbeefface
+#define LOGREC_MAGIC    0xfeefface
+#define REC_HDR_SIZE    sizeof(struct posix_log_entry)
+
+/*
+ * Reserved Event Types
+ */
+#define EVL_SYSLOG_MESSAGE      0x1
+#define EVL_PRINTK_MESSAGE      0x2
+#define EVL_BUFFER_OVERRUN      0x6
+#define EVL_DUPS_DISCARDED      0x7
+
+/*
+ * A record of type (LOG_LOGMGMT, EVLOG_REGISTER_FAC) is generated by
+ * evl_register_facility().
+ */
+#define EVLOG_REGISTER_FAC 40
+
+#define LOG_LOGMGMT              (12<<3)	/* EVL Facility */
+
+/*
+ * The optional portion of a record of type (LOG_LOGMGMT, EVLOG_REGISTER_FAC)
+ * is an evl_facreg_rq object followed by a string (the facility name).
+ * evlogd intercepts this record and does the requested registration, if needed.
+ *
+ * fr_kernel_fac_code is the facility code generated by the kernel's call
+ * to evl_register_facility().  This field is filled in by the kernel.
+ *
+ * fr_registry_fac_code is the facility code that appears in the registry.
+ * (This should match fr_kernel_fac_code.)  This field is filled in by
+ * evlogd after it intercepts and executes this request.
+ *
+ * fr_rq_status is the request's status:
+ *	frst_kernel_failed: Set by the kernel to indicate that it could not
+ *		generate a valid facility code for the given name.
+ *	frst_kernel_ok: Set by the kernel to indicate success so far.
+ * evlogd replaces the frst_kernel_ok value with one of the following:
+ *	frst_already_registered: No need to register the facility.  It's
+ *		already registered, and the code matches.
+ *	frst_registered_ok: We registered it, with the expected results.
+ *	frst_registration_failed: We tried to register it, but couldn't.
+ *	frst_faccode_mismatch: A facility by that name is in the registry,
+ *		but its code doesn't match fr_kernel_fac_code.
+ */
+typedef enum {
+	frst_kernel_failed = -1,
+	frst_kernel_ok = 0,
+	frst_already_registered,
+	frst_registered_ok,
+	frst_registration_failed,
+	frst_faccode_mismatch
+} evl_facreg_rq_status_t;
+
+struct evl_facreg_rq {
+	posix_log_facility_t	fr_kernel_fac_code;
+	posix_log_facility_t	fr_registry_fac_code;
+	evl_facreg_rq_status_t	fr_rq_status;
+};
+
+#ifdef __KERNEL__
+/*
+ * Reserved Facilities
+ */
+#define LOG_KERN        (0<<3)  /* Kernel Facility */
+#define LOG_AUTHPRIV    (10<<3) /* security/authorization messages (private) */
+/*
+ * priorities (these are ordered)
+ */
+#define LOG_EMERG   0   /* system is unusable */
+#define LOG_ALERT   1   /* action must be taken immediately */
+#define LOG_CRIT    2   /* critical conditions */
+#define LOG_ERR     3   /* error conditions */
+#define LOG_WARNING 4   /* warning conditions */
+#define LOG_NOTICE  5   /* normal but significant condition */
+#define LOG_INFO    6   /* informational */
+#define LOG_DEBUG   7   /* debug-level messages */
+
+extern int evl_writek(posix_log_facility_t facility, int event_type, 
+		     posix_log_severity_t severity, unsigned int flags, ...);
+		
+extern int evl_vwritek(posix_log_facility_t facility, int event_type,
+		     posix_log_severity_t severity, unsigned int flags,va_list args);
+		
+extern int posix_log_printf(posix_log_facility_t facility, int event_type, 
+		posix_log_severity_t severity, unsigned int flags, 
+		const char *fmt, ...);
+
+extern int posix_log_vprintf(posix_log_facility_t facility, int event_type,
+		posix_log_severity_t severity, unsigned int flags,
+		const char *fmt, va_list args);
+		
+extern int posix_log_write(posix_log_facility_t facility, int event_type,
+         	posix_log_severity_t severity, const void *buf,
+        	size_t len, int format, unsigned int flags);
+
+extern int evl_gen_facility_code(const char *fname,
+		posix_log_facility_t *fcode);
+
+extern int evl_register_facility(const char *fname,
+		posix_log_facility_t *fcode);
+#endif
+
+#endif
diff -Naur linux-2.4.17.ORG/kernel/Makefile linux-2.4.17.evlog_patched/kernel/Makefile
--- linux-2.4.17.ORG/kernel/Makefile	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/kernel/Makefile	Tue Mar 12 09:39:58 2002
@@ -9,12 +9,13 @@
 
 O_TARGET := kernel.o
 
-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o \
+		evl_cmd.o
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
 	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o
+	    signal.o sys.o kmod.o context.o evl_buf.o evl_cmd.o
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff -Naur linux-2.4.17.ORG/kernel/evl_buf.c linux-2.4.17.evlog_patched/kernel/evl_buf.c
--- linux-2.4.17.ORG/kernel/evl_buf.c	Wed Dec 31 16:00:00 1969
+++ linux-2.4.17.evlog_patched/kernel/evl_buf.c	Tue Mar 12 09:39:58 2002
@@ -0,0 +1,735 @@
+/*
+ * Linux Event Logging for the Enterprise
+ * Copyright (c) International Business Machines Corp., 2001
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Please send e-mail to lkessler@users.sourceforge.net if you have
+ *  questions or comments.
+ *
+ *  Project Website:  http://evlog.sourceforge.net/
+ *
+ */
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/malloc.h> /* kmalloc() */
+#include <linux/fs.h>     /* everything... */
+#include <linux/spinlock.h>  /* spinlock_t */
+#include <linux/time.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#ifdef __i386__
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
+#endif
+
+#include <asm/bitops.h>
+#include <asm/smp.h>
+
+#include <linux/evl_log.h>
+
+#ifdef CONFIG_EVLOG
+
+#define EVL_BUF_SIZE    (CONFIG_EVLOG_BUFSIZE * 1024)  	/* EVL buffer size */
+#define EVL_BUF_FREESPACE  (64 * 1024) 	/* free space reqd. after buff overrun */
+				  	/* to start writing events again.     */
+#define FALSE 0
+#define TRUE 1
+
+struct cbuf {
+        char          *bf_buf;        /* base buffer address */
+        unsigned int  bf_len;         /* buffer length */
+        unsigned int  bf_dropped;     /* (internal) dropped/trunc flag */
+        char          *bf_head;       /* head-pointer for circ. buf */
+        char          *bf_tail;       /* tail-pointer for circ. buf */
+        char          *bf_curr;       /* (internal) current write ptr */
+        char 	      *bf_end;	      /* end buffer address */
+};
+ 
+static long evl_buffer[(EVL_BUF_SIZE / sizeof(long)) + 1];
+                /* Evl Kernel buffer */
+
+static struct cbuf evl_ebuf = {
+        (char *) evl_buffer, EVL_BUF_SIZE, 0,
+        (char *) evl_buffer, (char *) evl_buffer, (char *) evl_buffer,
+	(char *)((char *)evl_buffer + EVL_BUF_SIZE)
+};
+
+#define min(a,b) (((a)<(b))?(a):(b))
+
+/*
+ * This is for the serialisation of reads from the kernel buffer.
+ */
+static DECLARE_MUTEX(evl_read_sem);
+DECLARE_WAIT_QUEUE_HEAD(readq);
+spinlock_t ebuf_lock = SPIN_LOCK_UNLOCKED;
+
+extern void mk_rec_header(struct posix_log_entry *rechdr,
+    posix_log_facility_t facility, int event_type,
+    posix_log_severity_t severity, size_t recsize,
+    uint recflags, uint format);
+
+extern char *copy_attr_data(va_list, char *, char *, char *, int *, int *);
+
+extern void evl_console_print(posix_log_facility_t facility, int event_type,
+					   posix_log_severity_t severity, int format, uint rec_len, 
+					   const char * databuf);
+extern int console_loglevel;
+extern struct console *console_drivers;
+
+
+/*
+ * FUNCTION     : cbufwrap
+ * ARGUMENTS    : bf_curr - Pointer to the current buffer 
+ *	        	: len - offset from bf_curr
+ * RETURN       : bf_curr if buffer has sufficient space to hold len bytes of 
+ *                data after buffer wraparound (if needed). else NULL.
+ */
+char *
+cbufwrap(char *bf_curr, size_t len, int do_wrap_hdr)
+{
+	register char *h, *end;
+	char *wrapbuf = bf_curr;
+
+	end = bf_curr + len;
+    	h = evl_ebuf.bf_head;      /* snapshot for consistency */
+    	/*
+     	 * wraparound if buffer cannot hold the header structure.
+     	 */
+
+    	if (bf_curr < h && end >= h) {
+    		/*
+         	 * insufficient space in buffer, drop record
+         	 */
+        	return NULL;
+    	}
+    	if (end > evl_ebuf.bf_end) {
+		if (do_wrap_hdr  && 
+		   ((char *)(bf_curr + REC_HDR_SIZE) > evl_ebuf.bf_end)) {
+			wrapbuf = evl_ebuf.bf_buf;
+		} else {
+           		len -= (size_t)((char *)evl_ebuf.bf_end - bf_curr);
+		}
+
+    		/*
+     	 	 * recalculate end
+     	 	 */
+     		end = evl_ebuf.bf_buf + len;
+        	if (end >= h) {
+        		/*
+             		 * insufficient space in buffer, drop record
+             		 */
+           		return NULL;
+      		}
+	}
+    	return wrapbuf;
+}
+
+/*
+ * FUNCTION     : cbufwrite
+ * ARGUMENTS    : The pointer in cbuf to write at,
+ *                the buffer to write,
+ *                the number of bytes to write
+ * RETURN       : The pointer in cbuf after the write
+ *      bf_head is owned by the drainer. bf_curr is allowed to be equal to
+ *      bf_head only when buffer is empty indicated by drainer. It is never
+ *      set to be equal by writer.
+ *
+ */
+char *
+cbufwrite(char *bufp, char *s, size_t len)
+{
+	register char *e;
+	register size_t n, lw;
+
+    	if ((bufp == (char *)NULL) || (s == (char *)NULL)) {
+    		return NULL;
+	}
+    	e = bufp + len;
+    	n = len;
+
+    	/* 
+	 * Test buffer wrap 
+	 */
+    	if (e > evl_ebuf.bf_end) {
+    		lw = (size_t)(evl_ebuf.bf_end - bufp);
+        	n -= lw;
+        	e = evl_ebuf.bf_buf + n;
+        	memcpy(bufp, s, lw);
+        	memcpy(evl_ebuf.bf_buf, s + lw, n);
+        	return e;
+     	} else {
+        	memcpy(bufp, s, n);
+        	return (e == evl_ebuf.bf_end) ? evl_ebuf.bf_buf : e;
+     	}
+}
+
+/*
+ * FUNCTION     : cbufptr
+ * ARGUMENTS    : starting pointer in cbuf,
+ *                offset in bytes from pointer
+ * RETURN       : The pointer in circular buf that is offset bytes from
+ *                starting pointer.
+ *                Returns NULL if cbuf_ptr is NULL or
+ *                if new pointer causes buffer overflow
+ */
+char *
+cbufptr(char *cbuf_ptr, size_t offset)
+{
+   	register char *e, *h = NULL;
+   	register size_t n, lw;
+
+	if ((cbuf_ptr < evl_ebuf.bf_buf) && (cbuf_ptr > evl_ebuf.bf_end)) {
+		printk("cbufptr: Invalid record start pointer\n"); 
+		return NULL;
+	}
+	if (offset >= (int)evl_ebuf.bf_len) {
+		printk("cbufptr: Invalid offset\n"); 
+		return NULL;
+	}
+   	h = evl_ebuf.bf_head;      /* snapshot for consistency */
+    
+   	/* 
+	 * insist on cbuf_ptr being an address within the prf buffer 
+	 */
+   	e = cbuf_ptr + offset;
+   	n = offset;
+   	/* check buffer wrap around */
+   	if (e >= evl_ebuf.bf_end) {
+   		lw = (size_t)(evl_ebuf.bf_end - cbuf_ptr);
+       		n -= lw;
+       		e = evl_ebuf.bf_buf + n;
+		return e;
+   	} else {
+       		return e;
+   	}
+}
+
+/*
+ * FUNCTION     : copy_data_to_cbuf
+ * ARGUMENTS    : Record header
+ *                pointer to varaible data
+ */
+int
+copy_data_to_cbuf(struct posix_log_entry *rhdr, char *vbuf)
+{
+
+   	memcpy(evl_ebuf.bf_curr, (char *)rhdr, REC_HDR_SIZE);
+   	evl_ebuf.bf_curr += REC_HDR_SIZE;
+
+   	if (rhdr->log_size > 0) {
+		evl_ebuf.bf_curr = 
+			cbufwrite(evl_ebuf.bf_curr, vbuf, rhdr->log_size);
+   	}
+	
+	return 0;
+}
+				
+/*
+ * FUNCTION     : evl_check_buf
+ * ARGUMENTS    : NONE
+ * RETURN       : -1 for failure, ie. insufficient buffer space
+ *                 0 for success
+ * If buffer free space is greater than the applicable water-mark,
+ * returns 0.  If not, return failure.
+ *
+ * Once the high water mark is hit and failure is returned (discarded
+ * messages) it sets a substantial low water mark before permitting
+ * messages to be bufferred again.  It counts the number of discards
+ * in the meantime and reports them when restarted.  If the water
+ * marks were equivalent, then there could be a thrashing of stops
+ * and starts, making the discarded message reporting annoying.
+ *
+ */
+int
+evl_check_buf(void)
+{
+	char *head;
+    	int water_mark, avail;
+
+    	head    = evl_ebuf.bf_head;
+    	avail   = (head <= evl_ebuf.bf_tail) ?
+              (int)(evl_ebuf.bf_len - ( evl_ebuf.bf_tail - head)) :
+              (int)(head - evl_ebuf.bf_tail);
+
+    	if (evl_ebuf.bf_dropped != 0)
+    		/*Apply the low water mark */
+        	water_mark = (int)(min(EVL_BUF_FREESPACE, evl_ebuf.bf_len / 2));
+    	else
+		water_mark = REC_HDR_SIZE;
+
+    	if (avail >= water_mark) {
+      		/*
+         	 * There's enough free buffer space -
+         	 * return success
+         	 */
+        	evl_ebuf.bf_curr = evl_ebuf.bf_tail;
+        	if (evl_ebuf.bf_dropped != 0) {
+			char sbuf[255];
+			struct posix_log_entry drechdr;
+		   	size_t vbuflen;
+           		int d = evl_ebuf.bf_dropped;
+			char *oldcur = evl_ebuf.bf_curr;
+
+           		evl_ebuf.bf_dropped = 0;
+	    		sprintf((char *)sbuf, 
+			"%d event records dropped due to EVL buffer overflow.", 
+				d);
+			vbuflen = strlen(sbuf) + 1;
+			mk_rec_header(&drechdr, LOG_KERN, EVL_BUFFER_OVERRUN, 
+				LOG_INFO, vbuflen, 0, POSIX_LOG_STRING);
+			evl_ebuf.bf_curr = cbufwrap(evl_ebuf.bf_curr, 
+				REC_HDR_SIZE + vbuflen, 1);
+			if (evl_ebuf.bf_curr != (char *)NULL) {
+				copy_data_to_cbuf(&drechdr, (char *)sbuf);
+			} else {
+				evl_ebuf.bf_curr = oldcur;
+				return -1;
+			}
+           		/*
+           	 	 * EVL circular buffer had been full and caused
+           	 	 * later messages to be dropped. Now the buffer
+           	 	 * has space. Still it is better to identify the
+           	 	 * cause so it doesn't repeat. The buffer gets full
+           	 	 * if the rate of incoming messages is much higher
+           	 	 * than can be drained. This could happen if
+           	 	 * messages are repeated at an excessively high rate
+				 * or the daemon in user-space is not running.
+           	 	 */
+
+		}
+       		return 0;       /* return successfully */
+	}
+
+   	/*
+   	 * fail for not enough free buffer space.
+   	 */
+	return -1;   
+}
+
+/*
+ * FUNCTION     : evl_getnext_rec
+ * ARGUMENTS    : rec is a pointer to the log event record.
+ *                If rec is NULL then the first Non wrap record from
+ *                bf_head is returned, else the record following rec is
+ *                returned.
+ *                The next record pointer mustn't be beyond tail.
+ * RETURN       : This function returns a pointer to the next record in the 
+ *                circular buffer. 
+ */
+evl_buf_rec_t
+*evl_getnext_rec(evl_buf_rec_t *rec, char *tail)
+{
+	char *e;
+
+   	if (rec == (evl_buf_rec_t *)NULL) {
+       		rec = (evl_buf_rec_t *)(evl_ebuf.bf_head);
+   	} else {
+		e = cbufptr((char *)rec, REC_HDR_SIZE + rec->rechdr.log_size);
+       		rec = (evl_buf_rec_t *)e;
+	}
+	if (rec) {
+       		if ((char *)rec == tail) return rec;
+       		/* 
+	 	 * Check for wrap 
+		 */
+       		if (((char *)rec + REC_HDR_SIZE) > evl_ebuf.bf_end) {
+      			rec = (evl_buf_rec_t *)evl_ebuf.bf_buf;
+       		}
+   	}
+   	return rec;
+}
+
+#if 0
+/*
+ * FUNCTION     : evl_uwrite_buf - Used to write user space messages.
+ * ARGUMENTS    : buf is a pointer to buffer that needs to be written into the
+ *	 	          EVL kernel buffer.
+ *	        	: buflen is length of the buffer to be written.
+ * RETURN       : 0 if writing to buffer is successful, else -ve value.
+ * USAGE        : This function acquires the circular buffer lock and copies the
+ *                event record and data to buffer.
+ * 
+ * NOTE:  		This function is left over from earlier event logging releases
+ *  			when user events were passed into the kernel buffer (instead of 
+ *  			being passed directly to the evlogd daemon via socket in the
+ *  			later release).  For some environments, using this function 
+ *  			could be the preferred method (and thus it was left in for now).
+ */
+
+int
+evl_uwrite_buf(char *buf, uint buflen)
+{
+    	int error = 0, recsize;
+    	register char *old_cur = NULL;
+    	evl_buf_rec_t *rec;
+	char *kbuf;
+	char *oldtail = evl_ebuf.bf_tail; /* Used to wake the read call if it sleeps */
+	long iflags;
+
+	if (buflen < REC_HDR_SIZE) {
+		return -EINVAL;
+	}
+	kbuf = kmalloc(buflen, GFP_KERNEL);
+	if (kbuf == (char *)NULL) {
+		return -ENOMEM;
+	} 
+	error = copy_from_user(kbuf, buf, buflen);
+	if (error) {
+		kfree(kbuf); 
+		return -EINVAL;
+	} 
+	rec = (evl_buf_rec_t *)kbuf;
+	if (buflen != (REC_HDR_SIZE + rec->rechdr.log_size)) {
+		kfree(kbuf); 
+		return -EINVAL;
+	}
+	/*
+	 * An event came from user space but has pretended to be
+	 * from kernel space. We just return with EPERM
+	 */
+	if (rec->rechdr.log_flags & EVL_KERNEL_EVENT) {
+		kfree(kbuf);
+		return -EPERM;
+	}
+	rec->rechdr.log_processor = smp_processor_id();
+
+	spin_lock_irqsave(&ebuf_lock, iflags);
+   	if (evl_check_buf() < 0) {
+		evl_ebuf.bf_dropped++;
+		spin_unlock_irqrestore(&ebuf_lock, iflags);
+		kfree(kbuf);
+		return -ENOSPC;
+   	}
+
+   	/* store off buf_curr to restore if necessary */
+   	old_cur = evl_ebuf.bf_curr;
+
+   	/*
+   	 * The buffer must have enough space to store the core structure
+   	 */
+   	recsize = REC_HDR_SIZE + rec->rechdr.log_size;
+
+   	/* 
+ 	 *If insufficient space in buffer after wrap around, drop record
+   	 */
+   	if ((evl_ebuf.bf_curr = cbufwrap(evl_ebuf.bf_curr, recsize, 1)) 
+		!= (char *)NULL) {
+		copy_data_to_cbuf(&(rec->rechdr),(char *)(kbuf + REC_HDR_SIZE));
+	}
+	if (evl_ebuf.bf_curr == (char *)NULL){
+		error = -ENOSPC;
+		evl_ebuf.bf_dropped++;
+		evl_ebuf.bf_curr = old_cur;
+	} else {
+		evl_ebuf.bf_tail = evl_ebuf.bf_curr;
+		if ((evl_ebuf.bf_head == oldtail) &&
+                	(evl_ebuf.bf_head  != evl_ebuf.bf_tail)) {
+                	wake_up_interruptible(&readq);
+        	}
+	}
+
+	spin_unlock_irqrestore(&ebuf_lock, iflags);
+	kfree(kbuf); 
+	return error;
+}
+#endif
+
+
+/*
+ * FUNCTION     : evl_kbufread - Used to read event records from the EVL
+ *		  circular buffer.
+ * ARGUMENTS    : retbuf is a pointer to buffer needs to be filled with the
+ *                event records.
+ *              : bufsize is length of the buffer allocated by the user.
+ * RETURN       : Number of bytes copied if read is successful, else -ve value.
+ *                event record and data to buffer.
+ */
+
+int
+evl_kbufread(char *retbuf, size_t bufsize)
+{
+	evl_buf_rec_t *rec;
+   	register size_t rec_size;
+   	int error = 0;
+   	int retbuflen = 0;
+   	char *tail, *buf = retbuf;
+
+   	/*
+  	 * the read request size must be at least rec_hdr_t size
+   	 */
+   	if (bufsize < REC_HDR_SIZE) {
+       		return -EINVAL;
+   	}
+	/* 
+	 * Serialize all reads, just in case someone got sneaky 
+	 */
+   	error = down_interruptible(&evl_read_sem);
+   	if (error == -EINTR) {
+   		return -EINTR;
+   	}
+	/*
+	 * Go to sleep if the buffer is empty.
+	 */
+	error = wait_event_interruptible(readq, 
+		(evl_ebuf.bf_head != evl_ebuf.bf_tail));
+	if (error) {
+		up(&evl_read_sem);
+		return error;
+	}
+	/*
+     	 * Assemble message(s) into the user buffer, as many as will
+     	 * fit.  On running out of space in the buffer, try to copy
+     	 * the header for the overflowing message.  This means that
+     	 * there will always be at least a header returned.  The caller
+     	 * must compare the numbers of bytes returned (remaining) with
+     	 * the length of the message to see if the entire message is
+     	 * present.  A subsequent read will get the entire message,
+     	 * including the header (again).
+     	 */
+	tail = (char *)(evl_ebuf.bf_tail);
+    	rec = evl_getnext_rec((evl_buf_rec_t *)NULL, tail);
+	if (rec == (evl_buf_rec_t *)NULL) { 
+		/*
+		 * Should not happen. Buffer must have atleast one record.
+		 */
+		error = -EFAULT;
+		goto out;
+	}
+    	do {
+    		uint lw = 0;
+		rec_size = REC_HDR_SIZE + rec->rechdr.log_size;
+
+		if (bufsize < REC_HDR_SIZE) {
+           		/* user buffer is smaller than header */
+           		break;
+        	}
+        	if (bufsize < rec_size) {
+       			/* 
+			 * Copyout only the header 'cause user buffer can't
+           	 	 * hold full record.
+           	 	 */
+           		error = copy_to_user(buf, (char *)rec, REC_HDR_SIZE);
+           		if (error) {
+           			error = -EFAULT;
+               			break;
+            		}
+           		bufsize -= REC_HDR_SIZE;
+           		retbuflen += REC_HDR_SIZE;
+           		break;
+       		}
+       		if ((char *)rec + rec_size > evl_ebuf.bf_end) {
+       			lw = (size_t)(evl_ebuf.bf_end - (char *)rec);
+       		}
+		if (lw > 0) {
+       			error = copy_to_user(buf, (char *)rec, lw);
+       			if (!error) {
+       				error = copy_to_user(((caddr_t)buf + lw),
+                   			(caddr_t)evl_ebuf.bf_buf, 
+					((size_t)(rec_size - lw))); 
+           		}
+       		} else {
+       			error = copy_to_user(buf, (char *)rec, rec_size);
+       		}
+		if (error) {
+       			error = -EFAULT;
+       			break;
+       		}
+       		rec = evl_getnext_rec( rec, tail);
+		buf += rec_size;
+       		bufsize -= rec_size;
+       		retbuflen += rec_size;
+   	} while ((char *)rec != tail);
+	if (error == 0) {
+		evl_ebuf.bf_head = (char *)rec;
+		error = retbuflen;
+	}
+
+out:
+	up(&evl_read_sem);
+	return(error);
+}
+
+/*
+ * FUNCTION     : evl_kwrite_buf - Used to write kernel level messages.
+ * RETURN       : 0 if writing to buffer is successful, else -ve value.
+ */
+
+int
+evl_kwrite_buf(posix_log_facility_t    fac,
+          	int          	       ev_type,
+          	posix_log_severity_t   sev,
+          	int          	       format,
+          	char  	               *recbuf,
+          	uint        	       var_rec_len,
+          	uint				   flags,
+          	va_list                args)	/* Used only for evl_writek */
+          	
+{
+
+	register char *old_cur = NULL;
+   	uint recflags = flags;
+   	uint recsize;
+	struct posix_log_entry rec_hdr, *rec;
+   	int error = 0;
+	char *oldtail = evl_ebuf.bf_tail; /* Used to wake the read call if it sleeps */ 
+	long iflags;
+
+	if (sev > LOG_DEBUG) {
+		return -EINVAL;
+	}
+	
+	recflags |= EVL_KERNEL_EVENT;	/* kernel mesagge */	
+   	mk_rec_header(&rec_hdr, fac, ev_type, sev, var_rec_len, recflags, format);
+	spin_lock_irqsave(&ebuf_lock, iflags);
+   	if (evl_check_buf() < 0) {
+		evl_ebuf.bf_dropped++;
+		spin_unlock_irqrestore(&ebuf_lock, iflags);
+		return -ENOSPC;
+   	}
+   	old_cur = evl_ebuf.bf_curr;
+
+   	if (args) {
+       	/*
+       	 * This function is called from evl_writek.
+       	 */
+ 		if ((evl_ebuf.bf_curr = 
+			cbufwrap(evl_ebuf.bf_curr, REC_HDR_SIZE, 1))
+			!= (char *)NULL) {
+			
+			char * prev_bf_curr;
+			rec = (struct posix_log_entry *)evl_ebuf.bf_curr;
+			memcpy(evl_ebuf.bf_curr, &rec_hdr, REC_HDR_SIZE);
+			evl_ebuf.bf_curr += REC_HDR_SIZE;
+			prev_bf_curr = evl_ebuf.bf_curr;
+			evl_ebuf.bf_curr = copy_attr_data(args, evl_ebuf.bf_buf,
+				evl_ebuf.bf_end, evl_ebuf.bf_curr,
+				&var_rec_len, &error);
+			if (evl_ebuf.bf_curr != (char *)NULL) {
+               	rec->log_size = var_rec_len;
+				if (var_rec_len == 0) {
+         	    	rec->log_format = POSIX_LOG_NODATA;
+              	} else if (var_rec_len > POSIX_LOG_ENTRY_MAXLEN) {
+                   	rec->log_size = POSIX_LOG_ENTRY_MAXLEN;
+                   	rec->log_flags |= POSIX_LOG_TRUNCATE;
+                }
+			}
+
+			if (evl_ebuf.bf_curr == (char *)NULL) {
+		   		evl_ebuf.bf_dropped ++;
+		   		evl_ebuf.bf_curr = old_cur;
+				if (error == 0) {
+		   			error = -ENOSPC;
+				}
+		   	} else {	
+				evl_ebuf.bf_tail = evl_ebuf.bf_curr;
+				if ((evl_ebuf.bf_head == oldtail) &&
+		               		(evl_ebuf.bf_head  != evl_ebuf.bf_tail)) {
+		        	wake_up_interruptible(&readq);
+		       	}
+			}
+
+			spin_unlock_irqrestore(&ebuf_lock, iflags);
+		 
+			/* print to console */
+			if (sev < console_loglevel && console_drivers) {
+				/* 
+				 * For binary data we only want to print to console 16 bytes,
+				 * copy 16 bytes from the evl kernel buffer.
+				 */
+				if (rec->log_format != POSIX_LOG_NODATA ) {
+					if ((prev_bf_curr + 16) < evl_ebuf.bf_end) {	
+						evl_console_print(fac, ev_type, sev, rec->log_format, var_rec_len, 
+											prev_bf_curr);
+					} else  {
+						char consolebuf[16];
+						char *tmp_ptr;
+						int n = evl_ebuf.bf_end - prev_bf_curr;
+						tmp_ptr = consolebuf;
+						if (n  > var_rec_len) {
+							memcpy(tmp_ptr, prev_bf_curr, var_rec_len);
+						} else {
+							memcpy(tmp_ptr, prev_bf_curr, n);
+							tmp_ptr+=n;
+							if (var_rec_len >= 16) {
+								memcpy(tmp_ptr, evl_ebuf.bf_buf, 16 - n);
+							} else {
+								memcpy(tmp_ptr, evl_ebuf.bf_buf, var_rec_len - n);	
+							}
+						}
+						evl_console_print(fac, ev_type, sev, rec->log_format, var_rec_len, consolebuf);
+					}
+				} else {
+						evl_console_print(fac, ev_type, sev, POSIX_LOG_NODATA, 0, NULL);
+				}
+			}
+			/* end of print to console */
+			return error;
+		}	
+	} else {
+		if (var_rec_len > POSIX_LOG_ENTRY_MAXLEN) {
+			rec_hdr.log_size = POSIX_LOG_ENTRY_MAXLEN;
+			rec_hdr.log_flags |= POSIX_LOG_TRUNCATE;
+		}
+		recsize = REC_HDR_SIZE + rec_hdr.log_size;
+
+       		/*
+       	 	 * If insufficient space in buffer after wrap around,
+       	 	 * drop record.
+       	 	 */
+		if ((evl_ebuf.bf_curr = cbufwrap(evl_ebuf.bf_curr, recsize, 1))
+				!= (char *)NULL) { 
+			rec = (struct posix_log_entry *)evl_ebuf.bf_curr;
+			copy_data_to_cbuf(&rec_hdr, recbuf);
+			/*
+			 * Write the NULL character if the varaible data
+			 * format is string and if it is truncated.
+			 */
+			if ((rec->log_flags == POSIX_LOG_TRUNCATE) &&
+       				(rec->log_format == POSIX_LOG_STRING)) {
+       			if (evl_ebuf.bf_curr != evl_ebuf.bf_buf) {
+       				*(evl_ebuf.bf_curr - 1) = '\0';
+       			} else {
+       				*(evl_ebuf.bf_end - 1) = '\0';
+       			}
+			}
+    	}
+	}
+	if (evl_ebuf.bf_curr == (char *)NULL) {
+   		evl_ebuf.bf_dropped ++;
+   		evl_ebuf.bf_curr = old_cur;
+		if (error == 0) {
+   			error = -ENOSPC;
+		}
+   	} else {	
+		evl_ebuf.bf_tail = evl_ebuf.bf_curr;
+		if ((evl_ebuf.bf_head == oldtail) &&
+               		(evl_ebuf.bf_head  != evl_ebuf.bf_tail)) {
+        	wake_up_interruptible(&readq);
+       	}
+	}
+	spin_unlock_irqrestore(&ebuf_lock, iflags);
+   	return error;
+}
+
+#endif	/* ifdef CONFIG_EVLOG */
diff -Naur linux-2.4.17.ORG/kernel/evl_cmd.c linux-2.4.17.evlog_patched/kernel/evl_cmd.c
--- linux-2.4.17.ORG/kernel/evl_cmd.c	Wed Dec 31 16:00:00 1969
+++ linux-2.4.17.evlog_patched/kernel/evl_cmd.c	Tue Mar 12 09:39:58 2002
@@ -0,0 +1,1007 @@
+/*
+ * Linux Event Logging for the Enterprise
+ * Copyright (c) International Business Machines Corp., 2001
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Please send e-mail to lkessler@users.sourceforge.net if you have
+ *  questions or comments.
+ *
+ *  Project Website:  http://evlog.sourceforge.net/
+ *
+ */
+ 
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/malloc.h> /* kmalloc() */
+#include <linux/fs.h>     /* everything... */
+#include <linux/spinlock.h>  /* spinlock_t */
+#include <linux/time.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/nls.h>
+#include <linux/sched.h>
+#include <linux/ctype.h>
+#include <linux/console.h>
+#include <linux/smp_lock.h>
+#include <linux/evl_log.h>
+
+#ifdef CONFIG_EVLOG
+char * copy_to_buf(char *bufp, char *data, size_t len, size_t * totalbytes);
+char * packString(char *d, char *s, size_t *reclen, char *bf_start,
+				  char *bf_end, int * bufsz);
+void evl_console_print(posix_log_facility_t facility, int event_type,
+					   posix_log_severity_t severity, int format, uint rec_len, 
+					   const char * databuf);
+void _evl_console_print(const char * s);
+static char *formatbytes(const char *dp, const char *dend, char *bp);
+static posix_log_facility_t getLinuxFacCodeByName(const char *name);
+static const char * getLinuxFacNameByCode(posix_log_facility_t code);
+static int _evlGenCanonicalFacilityName(const unsigned char *facName,
+			unsigned char *canonical);
+static unsigned int crc32(const unsigned char *data, int len);
+
+extern int evl_kwrite_buf(posix_log_facility_t, int, posix_log_severity_t,
+						  int, char *, uint, uint, va_list);
+extern char * cbufwrite(char *bufp, char *s, int len);
+extern char * cbufwrap(char *bufp, int len, int dowraphdr);
+
+extern int console_loglevel;
+extern struct semaphore console_sem;
+extern struct timezone sys_tz;
+
+static char evl_pdata[POSIX_LOG_ENTRY_MAXLEN + 1]; /* Used only for posix_log_printf call */
+
+spinlock_t pxlog_printf_lck = SPIN_LOCK_UNLOCKED;
+
+typedef enum base_type {
+		TY_NONE,        /* absence of value */
+		TY_CHAR,
+		TY_UCHAR,
+		TY_SHORT,
+		TY_USHORT,
+		TY_INT,
+		TY_UINT,
+		TY_LONG,
+		TY_ULONG,
+		TY_LONGLONG,
+		TY_ULONGLONG,
+		TY_STRING,
+		TY_ADDRESS
+} base_type_t;
+
+static struct type_info {
+		size_t  ti_size;
+		char    *ti_name;
+} type_info[] = {
+		{0,                     "none"},
+		{sizeof(char),          "char"},
+		{sizeof(unsigned char), "uchar"},
+		{sizeof(short),         "short"},
+		{sizeof(unsigned short),"ushort"},
+		{sizeof(int),           "int"},
+		{sizeof(unsigned int),  "uint"},
+		{sizeof(long),          "long"},
+		{sizeof(unsigned long), "ulong"},
+		{sizeof(long long),     "longlong"},
+		{sizeof(unsigned long long),    "ulonglong"},
+		{0,                     "string"},
+		{sizeof(void*),			"address"},
+		{0,                     NULL}
+};
+
+struct att_type_info {
+		base_type_t     at_type;    /* TY_INT for "int" or "int[]" or "2*int" */
+		int             at_nelements;   /* 5 for "5*int */
+		int             at_array;       /* 1 (true) for "int[]" */
+};
+#endif
+
+
+/*
+ *    These functions are used for logging events with log_format of
+ *    POSIX_LOG_BINARY.  See event logging specification at 
+ *    http://evlog.sourceforge.net/linuxEvlog.html 
+ *    for details.
+ */
+int evl_writek(posix_log_facility_t facility, int event_type,
+			   posix_log_severity_t severity, unsigned int flags, ...)
+{
+#ifdef CONFIG_EVLOG
+	va_list args;
+	int ret = 0;
+
+	va_start(args, flags);
+	ret = evl_vwritek(facility, event_type, severity, flags, args);
+	va_end(args);
+
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+}
+
+int evl_vwritek(posix_log_facility_t facility, int event_type,
+				posix_log_severity_t severity, unsigned int flags, va_list args)
+{
+#ifdef CONFIG_EVLOG
+	return evl_kwrite_buf(facility, event_type, severity, POSIX_LOG_BINARY,
+						  (char *)NULL, 0, flags, args);
+#else
+	return -ENOSYS;
+#endif
+}
+
+/*
+ *    These functions are used for logging events with log_format of
+ *	  POSIX_LOG_STRING.  See event logging specification at	
+ *    http://evlog.sourceforge.net/linuxEvlog.html 
+ *    for details.
+ */
+int posix_log_printf(posix_log_facility_t facility, int event_type,
+	posix_log_severity_t severity, unsigned int flags, const char *fmt, ...)
+{
+#ifdef CONFIG_EVLOG
+	int ret = 0;
+	va_list args;
+
+	if (fmt == (char *)NULL) {
+			
+		ret = evl_kwrite_buf(facility, event_type, severity, POSIX_LOG_NODATA,
+				(char *)NULL, 0, flags, (void *)NULL);
+		if (severity < console_loglevel && console_drivers) {
+			evl_console_print(facility, event_type, severity, POSIX_LOG_NODATA, 0, NULL);
+		}
+		return ret;
+	}
+	
+	va_start(args, fmt);
+	ret = posix_log_vprintf(facility, event_type, severity, flags, fmt, args);	
+	va_end(args);
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+}
+
+int posix_log_vprintf(posix_log_facility_t facility, int event_type,
+	posix_log_severity_t severity, unsigned int flags, const char *fmt, va_list args)
+{
+#ifdef CONFIG_EVLOG
+	uint recsize = 0;
+	int ret = 0;
+	long iflags;
+
+	if (fmt == (char *)NULL || args == NULL) {
+			
+		ret = evl_kwrite_buf(facility, event_type, severity, POSIX_LOG_NODATA,
+				(char *)NULL, 0, flags, (void *)NULL);
+		if (severity < console_loglevel && console_drivers) {
+			evl_console_print(facility, event_type, severity, POSIX_LOG_NODATA, 0, NULL);
+		}
+		return ret;
+	}
+	
+	spin_lock_irqsave(&pxlog_printf_lck, iflags);
+	vsprintf(evl_pdata, fmt, args);	
+	
+	recsize = strlen(evl_pdata) + 1;
+	
+	ret = evl_kwrite_buf(facility, event_type, severity, POSIX_LOG_STRING,
+				evl_pdata, recsize, flags, (void *)NULL);
+	if (severity < console_loglevel && console_drivers) {
+		evl_console_print(facility, event_type, severity, POSIX_LOG_STRING,
+					  recsize, evl_pdata);
+	}
+	spin_unlock_irqrestore(&pxlog_printf_lck, iflags);
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+}
+/*
+ *	This is the standard POSIX function for writing events to the event log,
+ *	See event logging specification at:
+ *	http://evlog.sourceforge.net/linuxEvlog.html
+ */
+int posix_log_write(posix_log_facility_t facility, int event_type,
+		posix_log_severity_t severity, const void *buf,
+		size_t recsize, int format, unsigned int flags)
+{
+	#ifdef CONFIG_EVLOG
+	int ret = 0;
+
+	if ((buf == (void *)NULL) && (recsize > 0)) {
+		return -EINVAL;
+	}
+	if (recsize == 0 && format != POSIX_LOG_NODATA) {
+		return -EINVAL;
+	}
+	if (format == POSIX_LOG_STRING) {
+                if (strlen((const char*)buf) != recsize-1) {
+                        return -EBADMSG;
+                }
+        }
+
+
+	
+	ret = evl_kwrite_buf(facility, event_type, severity, format,
+				(char *)buf, recsize, flags, (void *)NULL);
+	if (severity < console_loglevel && console_drivers) {
+		evl_console_print(facility, event_type, severity, format, recsize, buf);
+	}
+
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+
+}
+
+/*
+ * Set *fcode to the canonical facility code that corresponds to the facility
+ * name fname.  Return 0 on success.
+ *
+ * If fname is the upper or lower case name of a standard Linux facility,
+ * return the corresponding facility code.
+ *
+ * Otherwise, compute the facility code as the CRC of the name.  If the
+ * resulting code is the same as a reserved code (either a Linux code or
+ * EVL_INVALID_FACILITY), we return -EEXIST.
+ */
+int
+evl_gen_facility_code(const char *fname, posix_log_facility_t *fcode)
+{
+#ifdef CONFIG_EVLOG
+	posix_log_facility_t facNum;
+	size_t nameLen;
+	char canonical[POSIX_LOG_MEMSTR_MAXLEN];
+
+	if (!fname || !fcode) {
+		return -EINVAL;
+	}
+
+	nameLen = strlen(fname);
+	if (nameLen == 0 || nameLen >= POSIX_LOG_MEMSTR_MAXLEN) {
+		return -EINVAL;
+	}
+
+	(void) _evlGenCanonicalFacilityName(fname, canonical);
+
+	facNum = getLinuxFacCodeByName(canonical);
+	if (facNum != EVL_INVALID_FACILITY) {
+		/* fname names a standard Linux facility. */
+		*fcode = facNum;
+		return 0;
+	}
+
+	facNum = crc32(canonical, strlen(canonical));
+	if (facNum == EVL_INVALID_FACILITY) {
+		/* CRC happens to match EVL_INVALID_FACILITY */
+		return -EEXIST;
+	}
+	if (getLinuxFacNameByCode(facNum) != NULL) {
+		/*
+		 * CRC happens to match the Linux facility whose name is
+		 * posixName.
+		 */
+		return -EEXIST;
+	}
+	*fcode = facNum;
+	return 0;
+#else
+	return -ENOSYS;
+#endif
+}
+
+/*
+ * Compute the appropriate facility code for the facility whose name is fname.
+ * To ensure that this facility is registered in the facility registry, log
+ * a special event with facility = LOG_LOGMGMT and event type =
+ * EVLOG_REGISTER_FAC.  evlogd will intercept this event record and, if
+ * the facility is not already registered, register it.
+ *
+ * If the facility code we compute for fname collides with a reserved code
+ * (and fname is not the corresponding reserved name), we return -EEXIST
+ * and set *fcode to EVL_INVALID_FACILITY.  But we still log the event.
+ */
+int
+evl_register_facility(const char *fname, posix_log_facility_t *fcode)
+{
+#ifdef CONFIG_EVLOG
+	int status;
+	int ret;
+	struct evl_facreg_rq rq;
+	posix_log_severity_t sev;
+
+	/* evlogd will set this value eventually. */
+	rq.fr_registry_fac_code = EVL_INVALID_FACILITY;
+	
+	status = evl_gen_facility_code(fname, fcode);
+	if (status == -EINVAL) {
+		return -EINVAL;
+	} else if (status == 0) {
+		rq.fr_kernel_fac_code = *fcode;
+		rq.fr_rq_status = frst_kernel_ok;
+		sev = LOG_INFO;
+		ret = 0;
+	} else {
+		/* *fcode must conflict with a reserved facility code. */
+		*fcode = EVL_INVALID_FACILITY;
+		rq.fr_kernel_fac_code = EVL_INVALID_FACILITY;
+		rq.fr_rq_status = frst_kernel_failed;
+		sev = LOG_ERR;
+		ret = -EEXIST;
+	}
+
+	/* Log the event no matter whether evl_gen_facility_code() succeeded. */
+	status = evl_writek(LOG_LOGMGMT, EVLOG_REGISTER_FAC, sev, 0,
+		"char[]", sizeof(rq), &rq,
+		"string", fname,
+		"endofdata");
+	if (status != 0) {
+		return status;
+	}
+	return ret;
+#else
+	return -ENOSYS;
+#endif
+}
+
+#ifdef CONFIG_EVLOG
+/*
+ * FUNCTION		: mk_rec_header 
+ * ARGS			: rec_hdr - the record header stucture
+ *			: facility - 
+ *			: event_type -
+ *			: severity -
+ *			: recsize
+ *			: flags -
+ *			: format - indicates string or binary format or no data
+ * RETURN	: void
+ */
+void mk_rec_header(struct posix_log_entry *rec_hdr, 
+		   posix_log_facility_t   facility,
+		   int 			  event_type, 
+		   posix_log_severity_t   severity,
+		   size_t		  recsize, 
+		   uint 		  flags, 
+		   uint 		  format)
+{
+
+	rec_hdr->log_size	    	=  recsize;
+	rec_hdr->log_format		=  format;
+	rec_hdr->log_event_type 	=  event_type;
+	rec_hdr->log_facility   	=  facility;
+	rec_hdr->log_severity   	=  severity;
+	rec_hdr->log_uid		=  current->uid;
+	rec_hdr->log_gid		=  current->gid;
+	rec_hdr->log_pid		=  current->pid;
+	rec_hdr->log_pgrp		=  current->pgrp;
+	rec_hdr->log_flags		=  flags;
+	rec_hdr->log_thread		=  0;
+	rec_hdr->log_processor		=  smp_processor_id();
+
+	if (CURRENT_TIME == 0) {
+		rec_hdr->log_flags |= EVL_INITIAL_BOOT_EVENT;
+	} else {
+#if defined(__i386__)
+		if (sys_tz.tz_minuteswest == 0) { 
+			/* localtime */
+			rec_hdr->log_flags |= EVL_KERNTIME_LOCAL;
+		} 
+#endif
+	}
+	rec_hdr->log_time.tv_sec  = CURRENT_TIME;
+}
+
+#if 0
+/* We do not support wide-character in the kernel */
+/* Return length of Wide-character string S.  */
+size_t
+evl_wcslen (s)
+	 wchar_t *s;
+{
+  size_t len = 0;
+
+  while (s[len] != 0x00)
+	{
+	  if (s[++len] == 0x00)
+		return len;
+	  ++len;
+	}
+
+  return len;
+}
+#endif
+
+static base_type_t
+get_type_by_name(const char *name)
+{
+		base_type_t i;
+		for (i = TY_NONE+1; type_info[i].ti_name; i++) {
+				if (!strcmp(name, type_info[i].ti_name)) {
+						return i;
+				}
+		}
+		return TY_NONE;
+}
+
+/*
+ * att_type should be a type spec such as "int", "int[]", or "5*int".  Parse it
+ * and fill in *ti accordingly.  Returns 0 on success, -1 on failure.
+ */
+static int
+parse_att_type(const char *att_type, struct att_type_info *ti)
+{
+		const char *s, *left_bracket;
+		const char *type_name;
+#define MAX_TYPE_NAME_LEN 20
+		char name_buf[MAX_TYPE_NAME_LEN+1];
+
+		if (isdigit(att_type[0])) {
+				/* "5*int" */
+				ti->at_nelements = (int) simple_strtoul(att_type, (char**) &s, 10);
+				if (*s != '*') {
+						return -1;
+				}
+				type_name = s+1;
+				ti->at_array = 0;
+		} else if ((left_bracket = strchr(att_type, '[')) != NULL) {
+				/* int[] */
+				size_t name_len;
+				ti->at_array = 1;
+				ti->at_nelements = 0;
+				if (0 != strcmp(left_bracket, "[]")) {
+						return -1;
+				}
+				/* Copy the name to name_buf and point type_name at it. */
+				type_name = name_buf;
+				name_len = left_bracket - att_type;
+				if (name_len == 0 || name_len > MAX_TYPE_NAME_LEN) {
+						return -1;
+				}
+				(void) memcpy(name_buf, att_type, name_len);
+				name_buf[name_len] = '\0';
+		} else {
+				/* "int" */
+				type_name = att_type;
+				ti->at_array = 0;
+				ti->at_nelements = 1;
+		}
+		ti->at_type = get_type_by_name(type_name);
+		return (ti->at_type == TY_NONE ? -1 : 0);
+}
+
+/*
+ * Pack a null-terminated string into the data buffer.  If there's room
+ * for at least one byte, but not for the whole string, we copy in what
+ * we can and null-terminate it.
+ * param d	destination: The string will be copied to here.
+ * param s	source: The string to be copied.
+ * param reclen	points to the record length that is being accumulated by
+ *		the caller.  It is updated to contain what the new
+ *		record length would be if the buffer were sufficiently big.
+ * return	the destination pointer, updated to point past the null
+ *		at the end of the string we just added
+ */
+char *
+packString(char *d, char *s, size_t *reclen,
+		   char *bf_start, char *bf_end, int * bufsz)
+{
+	size_t slen = strlen(s) + 1;
+	size_t prevrlen = *reclen;
+	
+	d = copy_to_buf(d, s, slen, reclen);
+	if (d == (char *)NULL) {
+		return NULL;
+	}
+	if (*reclen > POSIX_LOG_ENTRY_MAXLEN) {
+		/*
+	 	 * if record length limit is not
+	 	 * reached in the previous arg,
+	 	 * copy the NULL character at
+	 	 * the end the record.
+	 	 */
+		if (prevrlen >= POSIX_LOG_ENTRY_MAXLEN) {
+			*bufsz = *reclen;
+			return d;
+		}
+		if (d != bf_start) {
+			*(d - 1) = '\0';
+		} else {
+			*(bf_end - 1) = '\0';
+		}
+	}
+    return d;
+}
+
+/*
+ * If the record length is not reached the MAX_REC_SIZE, determine
+ * whether the circular buffer has space to copy. If so, copy it.
+ */
+char *
+copy_to_buf(char *dest, char *src, size_t n, size_t *reclen)
+{
+	size_t nb = n;
+	size_t temp_rlen = *reclen + n;
+
+	if (temp_rlen > POSIX_LOG_ENTRY_MAXLEN) {
+		if (*reclen < POSIX_LOG_ENTRY_MAXLEN) {
+			nb = POSIX_LOG_ENTRY_MAXLEN - *reclen;
+		} else {
+			*reclen = temp_rlen;
+			return dest;
+		}
+	}
+	*reclen = temp_rlen;
+	if ((dest = cbufwrap(dest, nb, 0)) == (char *)NULL) {
+		return NULL;
+	}
+	return cbufwrite(dest, src, nb);
+}
+
+/*
+ * COPYARGS copies n args of type lt (little type) from the stack using
+ * memcpyex.  bt (big type) is the type of the arg as it appears on the stack.
+ */
+#define COPYARGS(lt,bt) \
+{ \
+	while(n-- > 0) { \
+		lt v=(lt)va_arg(args,bt); \
+		d = copy_to_buf(d, (char *)&v, sizeof(lt), &reclen); \
+		if (d == (char *)NULL) { \
+			return NULL; \
+		} \
+	} \
+}
+
+/*
+ * Packing attributes data onto a circular buffer if the space is available.
+ *
+ * ARGUMENTS:   args - the variable arguments list.
+ *		bf_start - Starting pointer to the circular buffer
+ *		bf_end   - End pointer to the circular buffer
+ *              databuf - the event record buffer
+ *              bufsz - Returns the size of the buffer copied.
+ *		error - Return the errno if it fails.
+ * return       pointer to the data buffer to write the next record.
+ *              NULL for fail.
+ */
+char *
+copy_attr_data(va_list args, char *bf_start, char *bf_end, 
+		char *databuf, int *bufsz, int *error)
+{
+		char *att_type;
+#if 0
+		size_t wcharsz = sizeof(wchar_t);
+#endif
+		char *d = databuf;                      /* next data goes here */
+		size_t reclen = 0;
+	
+		while ((att_type = va_arg(args, char*)) &&
+			(0 != strcmp(att_type, "endofdata"))) {
+			struct att_type_info ti;
+			if (parse_att_type(att_type, &ti) == -1) {
+				*error = -EINVAL;
+					return NULL;
+			}
+			if (ti.at_array) {
+				char *array, *a;
+				size_t size = type_info[ti.at_type].ti_size;
+				int n;
+
+				/* Next arg is the array size. */
+				n = va_arg(args, int);
+				/* Next arg is the array address. */
+				array = (char*) va_arg(args, void*);
+				
+				switch (ti.at_type) {
+					case TY_STRING:
+			    	{
+						/* array points to an array of char* */
+						char **sarray = (char**)array;
+						int i;
+						for (i = 0; i < n; i++) {
+							d = packString(d, sarray[i], &reclen, bf_start, bf_end, bufsz);
+						}
+						break;
+			    	}
+					default:
+                       	for (a = array; n > 0; a += size, n--) {
+                           	d = copy_to_buf(d, a, size, &reclen);
+							if (d == (char *)NULL) {
+								return NULL;
+							}
+                       	}
+                       	break;
+				}
+			} else {
+				/*
+				 * One or more args of the same type.
+				 */
+				int n = ti.at_nelements;
+                switch (ti.at_type) {
+					case TY_CHAR:
+					case TY_UCHAR:
+					#if defined(CONFIG_ARCH_S390X)   			/* 64bits s390x */
+						COPYARGS(char, long)
+					#else
+						COPYARGS(char, int)
+					#endif
+						break;
+					case TY_SHORT:
+					case TY_USHORT:
+					#if defined(CONFIG_ARCH_S390X)
+						COPYARGS(short, long)
+					#else
+						COPYARGS(short, int)
+					#endif
+						break;
+					case TY_INT:
+					case TY_UINT:
+					#if defined(CONFIG_ARCH_S390X)
+						COPYARGS(int, long)
+					#else
+						COPYARGS(int, int)
+					#endif
+						break;
+					case TY_LONG:
+					case TY_ULONG:
+						COPYARGS(long, long)
+						break;
+					case TY_LONGLONG:
+					case TY_ULONGLONG:
+						COPYARGS(long long, long long)
+
+						break;
+					case TY_ADDRESS:
+						COPYARGS(void*, void*)
+						break;
+					case TY_STRING:
+					{
+						char *s;
+						while (n-- > 0) {
+							s = (char *) va_arg(args, char*);
+							d = packString(d, s, &reclen, bf_start, bf_end, bufsz);
+						}
+					break;
+					}
+#if 0
+					case TY_WCHAR:
+						COPYARGS(wchar_t, wchar_t)
+						break;
+					case TY_WSTRING:
+					{
+						size_t slen;
+						wchar_t *s;
+						while (n-- > 0) {
+							s = (wchar_t *) va_arg(args, wchar_t*);
+							slen = wcslen(s) * wcharsz;
+							d = copy_to_buf(d, s, slen, &reclen);
+							if (d == (char *)NULL) {
+								return NULL;
+							}
+						}
+					} /* end of TY_WSTRING case */
+#endif
+			default:
+				break;
+			} /* end of switch */
+		} /* not array */
+	} /* next att_type */
+		
+	*bufsz = reclen;
+	
+	return d;
+}
+
+/*
+ * FUNCTION	: printk_evlog_write - writes printk messages as events to event 
+ *            buffer.
+ * ARGS		: buf - pointer to printk message 
+ *
+ * RETURN	: return 0 for success, otherwise return a negative
+ *			  error code.
+ */
+static char prtk_msgbuf[POSIX_LOG_ENTRY_MAXLEN + 1];
+static int msgbuf_idx = 0;
+int
+printk_evlog_write(const char *buf)
+{
+	char *recbuf= (char*)buf;
+	char *p; 
+	uint recsize = 0, sev = LOG_NOTICE;
+	int ret = 0;
+	int format = POSIX_LOG_NODATA;
+	
+	if (buf == (char *)NULL) {
+		return -EINVAL;
+	}
+	
+	if ((strlen(buf) > 2) && (msgbuf_idx == 0)) {
+		if (buf[0] == '<' && buf[1] >= '0' && buf[1] <= '7' && buf[2] == '>') {
+			sev = buf[1] - '0';
+			recbuf += 3;
+		}
+	} 
+	
+	for (p = recbuf; *p; p++) {
+		prtk_msgbuf[msgbuf_idx]= *p;
+		msgbuf_idx++;
+		if (msgbuf_idx >= POSIX_LOG_ENTRY_MAXLEN-1) {	
+			 /* Message apperently bigger than the buffer */
+			prtk_msgbuf[msgbuf_idx++] = '\n';	
+			break;
+		}	
+	}
+
+	if (prtk_msgbuf[msgbuf_idx-1] != '\n') {
+		/* Message does not completed yet - return for more */
+		return;
+	}
+
+	/* Message completed - terminate it with a null and reset the msgbuf index */
+	prtk_msgbuf[msgbuf_idx] = '\0';
+	msgbuf_idx = 0;
+	
+	if (prtk_msgbuf[0] != '\0') {
+		recsize = strlen(prtk_msgbuf) + 1;
+		format = POSIX_LOG_STRING;
+	}
+
+	ret = evl_kwrite_buf(LOG_KERN, EVL_PRINTK_MESSAGE, sev, format,
+			   prtk_msgbuf, recsize, 0, (void *)NULL);
+
+	return ret;
+}
+
+/*
+ * print evlog message to the console
+ */
+
+void evl_console_print(posix_log_facility_t facility, int event_type,
+					   posix_log_severity_t severity, int format, uint rec_len, 
+					   const char * databuf)
+{
+	char s[256 + 41];		/* print buffer - only print first 256 chars  */
+	char b[36+1];			/* (16 bytes x 2) + 4 spaces + null */ 	
+	
+	if (format == POSIX_LOG_STRING) {
+		if (rec_len >= 256) {
+			int h = 0;
+			sprintf(s, "F%04d:T%04d:S: ", facility, event_type);
+			h = strlen(s);
+			memcpy(s+h, databuf, 254);
+			s[h + 254] = '\n';
+			s[h + 255] = '\0';
+		} else {
+			sprintf(s, "F%04d:T%04d:S: %s\n", facility, 
+					event_type, databuf);
+		}
+	} else if (format == POSIX_LOG_BINARY) {
+		char *tmp = b;
+		if (rec_len >= 16 ) {
+			formatbytes(databuf, databuf+16, tmp);
+			sprintf(s, "F%04d:T%04d:B: <%s...> %d more bytes\n", facility, 
+				event_type, b, rec_len - 16);
+		} else {
+			formatbytes(databuf, databuf+rec_len, tmp);
+			sprintf(s, "F%04d:T%04d:B: <%s>\n", facility, 
+				event_type, b);
+		}			
+	} else {
+		sprintf(s, "F%04d:T%04d:N: <no data>\n", facility, 
+				event_type);
+	}
+	_evl_console_print(s);
+	
+}
+
+void _evl_console_print(const char * s) 
+{
+	struct console *con;
+
+	down(&console_sem);
+	for (con = console_drivers; con; con = con->next) {
+		if ((con->flags & CON_ENABLED) && con->write)
+			con->write(con, s, strlen(s));
+	}
+	up(&console_sem);	
+}
+	
+
+
+static char *hexDigits = "0123456789ABCDEF";
+
+static char *formatbytes(const char *dp, const char *dend, char *bp)
+{
+	char *oldbp = bp;
+	int i;
+	int nbytes = dend - dp;
+	int n = 0;
+	for (i = 1; i <= nbytes; i++, dp++, bp += 2) {
+		if (dp <= dend) {
+			bp[0] = hexDigits[(*dp >> 4) & 0xF];
+			bp[1] = hexDigits[*dp & 0xF];
+			n++;
+			if (n >= 4) {
+				bp[2] = ' ';
+				bp++;
+				n = 0;
+			} 	
+		}
+	}
+	*bp='\0';
+	return oldbp;
+}
+
+/*** Facility registration functions start here. ***/
+
+struct nvPair {
+	int	nv_value;
+	char	*nv_name;
+};
+
+/*
+ * This should look a lot like the DEFAULT version of the facility registry,
+ * /var/evlog/facility_registry.  DO NOT UPDATE THIS TABLE when you add a
+ * new facility.
+ */
+static struct nvPair linuxFacilities[] = {
+	{ 0, "kern" },
+	{ 8, "user" },
+	{ 16, "mail" },
+	{ 24, "daemon" },
+	{ 32, "auth" },
+	{ 40, "syslog" },
+	{ 48, "lpr" },
+	{ 56, "news" },
+	{ 64, "uucp" },
+	{ 72, "cron" },
+	{ 80, "authpriv" },
+	{ 88, "ftp" },
+	{ 96, "logmgmt" },
+	{ 128, "local0" },
+	{ 136, "local1" },
+	{ 144, "local2" },
+	{ 152, "local3" },
+	{ 160, "local4" },
+	{ 168, "local5" },
+	{ 176, "local6" },
+	{ 184, "local7" },
+	{ -1, NULL }
+};
+
+static posix_log_facility_t
+getLinuxFacCodeByName(const char *name)
+{
+	struct nvPair *nv;
+	for (nv = linuxFacilities; nv->nv_name; nv++) {
+		if (!strcmp(name, nv->nv_name)) {
+			return (posix_log_facility_t) nv->nv_value;
+		}
+	}
+	return EVL_INVALID_FACILITY;
+}
+
+static const char *
+getLinuxFacNameByCode(posix_log_facility_t code)
+{
+	struct nvPair *nv;
+	for (nv = linuxFacilities; nv->nv_name; nv++) {
+		if (code == (posix_log_facility_t) (nv->nv_value)) {
+			return nv->nv_name;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Copy facName to canonical, converting characters as necessary so that
+ * canonical is the canonical version of facility name facName.  Returns
+ * -EINVAL if facName is null or empty, or if canonical is null; 0 otherwise.
+ *
+ * Here are the rules for forming a canonical name:
+ * 1. The following bytes are passed through unchanged: ASCII digits,
+ * ASCII lowercase letters, period, underscore, and any bytes outside
+ * the ASCII code set.
+ * 2. Uppercase ASCII letters are converted to lowercase.
+ * 3. A space character is converted to an underscore.
+ * 4. Any other ASCII character is converted to a period.
+ */
+static int
+_evlGenCanonicalFacilityName(const unsigned char *facName,
+	unsigned char *canonical)
+{
+	const unsigned char *f;
+	unsigned char *c;
+
+	if (!facName || !canonical || facName[0] == '\0') {
+		return -EINVAL;
+	}
+
+	for (f=facName, c=canonical; *f; f++, c++) {
+		unsigned int uf = *f;
+		if ('A' <= uf && uf <= 'Z') {
+			*c = uf | 0x20;		/* ASCII toupper(uf) */
+		} else if (uf > 0x7f
+		    || ('a' <= uf && uf <= 'z')
+		    || ('0' <= uf && uf <= '9')
+		    || uf == '.'
+		    || uf == '_') {
+			*c = uf;
+		} else if (uf == ' ') {
+			*c = '_';
+		} else {
+			*c = '.';
+		}
+	}
+	*c = '\0';
+
+	/* "." and ".." are reserved directory names, so we convert them. */
+	if (!strcmp(canonical, ".") || !strcmp(canonical, "..")) {
+		canonical[0] = '_';
+	}
+	return 0;
+}
+
+/*
+ * This is the code for CRC algorithm #1 from
+ * http://www.cl.cam.ac.uk/Research/SRG/bluebook/21/crc/node6.html.
+ * It was chosen for simplicity rather than efficiency, since we don't expect
+ * it to be called much.
+ */
+
+#define QUOTIENT 0x04c11db7
+
+static unsigned int
+crc32(const unsigned char *data, int len)
+{
+	unsigned int	result;
+	int		i,j;
+	unsigned char	octet;
+    
+	result = -1;
+    
+	for (i=0; i<len; i++) {
+		octet = *(data++);
+		for (j=0; j<8; j++) {
+			if ((octet >> 7) ^ (result >> 31)) {
+				result = (result << 1) ^ QUOTIENT;
+			} else {
+				result = (result << 1);
+			}
+			octet <<= 1;
+		}
+	}
+ 
+	return ~result;	/* The complement of the remainder */
+}
+
+
+
+#endif 	/* ifdef CONFIG_EVLOG */
+EXPORT_SYMBOL(evl_writek);
+EXPORT_SYMBOL(evl_vwritek);
+EXPORT_SYMBOL(posix_log_write);
+EXPORT_SYMBOL(posix_log_printf);
+EXPORT_SYMBOL(posix_log_vprintf);
+EXPORT_SYMBOL(evl_gen_facility_code);
+EXPORT_SYMBOL(evl_register_facility);
diff -Naur linux-2.4.17.ORG/kernel/printk.c linux-2.4.17.evlog_patched/kernel/printk.c
--- linux-2.4.17.ORG/kernel/printk.c	Mon Feb 11 14:31:37 2002
+++ linux-2.4.17.evlog_patched/kernel/printk.c	Tue Mar 12 09:39:58 2002
@@ -64,7 +64,7 @@
  * provides serialisation for access to the entire console
  * driver system.
  */
-static DECLARE_MUTEX(console_sem);
+DECLARE_MUTEX(console_sem);
 struct console *console_drivers;
 
 /*
@@ -88,6 +88,13 @@
 
 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
 static int preferred_console = -1;
+#ifdef CONFIG_EVLOG
+#if 0
+extern int evl_uwrite_buf(char *, uint);
+#endif
+extern int evl_kbufread(char *, size_t);
+extern int printk_evlog_write(const char *);
+#endif
 
 /* Flag: console code may call schedule() */
 static int console_may_schedule;
@@ -160,6 +167,7 @@
  * 	7 -- Enable printk's to console
  *	8 -- Set level of messages printed to console
  *	9 -- Return number of unread characters in the log buffer
+ * 20 -- Read from event logging buffer	
  */
 int do_syslog(int type, char * buf, int len)
 {
@@ -280,6 +288,31 @@
 		error = log_end - log_start;
 		spin_unlock_irq(&logbuf_lock);
 		break;
+	case 20:
+#ifdef CONFIG_EVLOG
+		error = verify_area(VERIFY_WRITE, buf, len);
+		if (error) {
+			goto out;
+		} 
+		error = evl_kbufread(buf, len);
+#else
+		error = -EIO;
+#endif
+		break;
+#if 0  /* left over from early event logging release when user events were written 
+		  to the kernel buffer +*/
+	case 21:
+#ifdef CONFIG_EVLOG
+		error = verify_area(VERIFY_READ, buf, len);
+		if (error) {
+			goto out;
+		} 
+		error = evl_uwrite_buf(buf, len);
+#else
+        error = -EIO;
+#endif
+		break;
+#endif
 	default:
 		error = -EINVAL;
 		break;
@@ -423,7 +456,10 @@
 	va_start(args, fmt);
 	printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 	va_end(args);
-
+	
+#ifdef CONFIG_EVLOG_FWPRINTK
+	(void)printk_evlog_write(printk_buf);
+#endif
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
 	 * appropriate log level tags, we insert them here
