diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-12-01 09:51:44 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-12-01 09:51:44 +1100 |
commit | aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f (patch) | |
tree | dfffc0d8f3d21f6736b7f09219c95e2370052d8a /lib | |
download | SLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.zip SLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.tar.gz SLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.tar.bz2 |
Initial import of slof-JX-1.7.0-4
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'lib')
91 files changed, 5430 insertions, 0 deletions
diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..34d3c23 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,35 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf + + +all: subdirs + +.PHONY : subdirs $(SUBDIRS) clean distclean + + +subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ $(MAKEARG) + +# Rules for making clean: +clean: + @for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir clean || exit 1; \ + done + +distclean: + @for dir in $(SUBDIRS); do \ + $(MAKE) -C $$dir distclean || exit 1; \ + done diff --git a/lib/libbases/Makefile b/lib/libbases/Makefile new file mode 100644 index 0000000..add4ed1 --- /dev/null +++ b/lib/libbases/Makefile @@ -0,0 +1,40 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +TOPCMNDIR ?= ../.. + +include $(TOPCMNDIR)/make.rules + +ASFLAGS = $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames +CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) -I. -I../../include +LDFLAGS = -nostdlib + +all: + +clean: + $(RM) $(TARGET) $(OBJS) + +distclean: clean + $(RM) Makefile.dep + + +# Rules for creating the dependency file: +depend: + $(RM) Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile + + +# Include dependency file if available: +-include Makefile.dep + diff --git a/lib/libbases/libbases.code b/lib/libbases/libbases.code new file mode 100644 index 0000000..7dc941d --- /dev/null +++ b/lib/libbases/libbases.code @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#include <southbridge.h> + +// : get-nvram-base ( -- base ) +PRIM(get_X2d_nvram_X2d_base) + PUSH; + TOS.u = SB_NVRAM_adr; +MIRP + +// : get-nvram-size ( -- size ) +PRIM(get_X2d_nvram_X2d_size) + PUSH; + TOS.u = NVRAM_LENGTH; +MIRP + +// : get-flash-base ( -- base ) +PRIM(get_X2d_flash_X2d_base) + PUSH; + TOS.u = SB_FLASH_adr; +MIRP + +// : get-flash-size ( -- size ) +PRIM(get_X2d_flash_X2d_size) + PUSH; + TOS.u = FLASH_LENGTH; +MIRP + +// : get-mbx-base ( -- base ) +PRIM(get_X2d_mbx_X2d_base) + PUSH; + TOS.u = SB_MAILBOX_adr; +MIRP diff --git a/lib/libbases/libbases.in b/lib/libbases/libbases.in new file mode 100644 index 0000000..844a55d --- /dev/null +++ b/lib/libbases/libbases.in @@ -0,0 +1,17 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +cod(get-nvram-base) +cod(get-nvram-size) +cod(get-flash-base) +cod(get-flash-size) +cod(get-mbx-base) diff --git a/lib/libbootmsg/Makefile b/lib/libbootmsg/Makefile new file mode 100644 index 0000000..6804b8d --- /dev/null +++ b/lib/libbootmsg/Makefile @@ -0,0 +1,69 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +TOPCMNDIR ?= ../.. + +ASFLAGS = $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames +CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) -I. -I../../include +LDFLAGS = -nostdlib + +TARGET = ../libbootmsg.a + + +all: $(TARGET) + +ifeq ($(CPUARCH),cbea) +SRCS = +SRCSS = bootmsg_lvl.S +else +ifeq ($(CPUARCH),ppc970) +SRCS = +SRCSS = bootmsg_lvl.S +else +ifeq ($(CPUARCH),p5) +SRCS = +SRCSS = bootmsg_lvl.S +else +SRCS = bootmsg.c +SRCSS = +endif +endif +endif + + +OBJS = $(SRCS:%.c=%.o) $(SRCSS:%.S=%.o) + +$(TARGET): $(OBJS) + $(AR) -rc $@ $(OBJS) + $(RANLIB) $@ + +%.o: %.S + $(CC) $(CPPFLAGS) $(ASFLAGS) -c $< -o $@ + +clean: + $(RM) $(TARGET) $(OBJS) + +distclean: clean + $(RM) Makefile.dep + + +# Rules for creating the dependency file: +depend: + $(RM) Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile + $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(SRCS) $(SRCSS) > Makefile.dep + +# Include dependency file if available: +-include Makefile.dep + diff --git a/lib/libbootmsg/bootmsg.code b/lib/libbootmsg/bootmsg.code new file mode 100644 index 0000000..ae370af --- /dev/null +++ b/lib/libbootmsg/bootmsg.code @@ -0,0 +1,61 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#include <libbootmsg.h> + +// : cp ( cp-id -- ) +PRIM(bootmsg_X2d_cp) + int cpid = TOS.n; POP; + bootmsg_cp(cpid); +MIRP + +// : bootmsg-warning ( cp-id lvl pstr -- ) +PRIM(bootmsg_X2d_warning) + char* str = TOS.a; POP; + short lvl = TOS.n; POP; + short cpid = TOS.n; POP; + bootmsg_warning(cpid, (const char*)str, lvl); +MIRP + +// : bootmsg-error ( cp-id pstr -- ) +PRIM(bootmsg_X2d_error) + char* str = TOS.a; POP; + short cpid = TOS.n; POP; + bootmsg_error(cpid, (const char*)str); +MIRP + +// : bootmsg-debugcp ( cp-id lvl pstr -- ) +PRIM(bootmsg_X2d_debugcp) + char* str = TOS.a; POP; + short lvl = TOS.n; POP; + short cpid = TOS.n; POP; + bootmsg_debugcp(cpid, (const char*)str, lvl); +MIRP + +// : bootmsg-setlevel ( area lvl -- ) +PRIM(bootmsg_X2d_setlevel) + char lvl = TOS.n; POP; + short area = TOS.n; POP; + bootmsg_setlevel(area, lvl); +MIRP + +// : bootmsg-checklevel ( area lvl -- [true|false] ) +PRIM(bootmsg_X2d_checklevel) + char lvl = TOS.n; POP; + short area = TOS.n; POP; + PUSH; + TOS.n = (bootmsg_checklevel(area, lvl)) ? -1 : 0; +MIRP + +// : bootmsg-nvupdate ( -- ) +PRIM(bootmsg_X2d_nvupdate) + bootmsg_nvupdate(); +MIRP diff --git a/lib/libbootmsg/bootmsg.in b/lib/libbootmsg/bootmsg.in new file mode 100644 index 0000000..73e01e3 --- /dev/null +++ b/lib/libbootmsg/bootmsg.in @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +cod(bootmsg-cp) +cod(bootmsg-warning) +cod(bootmsg-error) +cod(bootmsg-debugcp) +cod(bootmsg-setlevel) +cod(bootmsg-nvupdate) +cod(bootmsg-checklevel) diff --git a/lib/libbootmsg/bootmsg_lvl.S b/lib/libbootmsg/bootmsg_lvl.S new file mode 100644 index 0000000..04ace12 --- /dev/null +++ b/lib/libbootmsg/bootmsg_lvl.S @@ -0,0 +1,199 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#define _ASM_ +#include "macros.h" +#include "southbridge.h" +#include "nvramlog.h" + +#define bootmsg_area_size 128 + + .text + .align 3 + +// Declare the warning level for all 128 possibilities of AC/pCKG kombinations + WRNG_LVL: + .rept bootmsg_area_size + .byte 0x0 + .endr + + +//***************************************************************************** +// Check UserWarningLevel against SystemWarningLevel +// input : r3=cp-id, r5=level +// change: r6,r7 +// output: CR0 ( compared user vs system level ) +// example: +// bl GET_WRNG_LVL +// ble print_warning +// bgt do_not_print_warning +ENTRY(GET_WRNG_LVL) + mflr r7 // save linkage register + bl 0f // get current +0: mflr r6 // Instruction Address + mtlr r7 // restore linkage register + addi r6,r6,WRNG_LVL-0b // calc addr of WRNG_LVL array + rldic r7,r3,56,57 // calc index into array + lbzux r7,r6,r7 // read the warning level + cmpw r5,r7 // and compare it + blr + +//***************************************************************************** +// Print CheckPoint +// input : r3=cp-id +// change: r3, r4, r5, r6, r7, r11 +// output: none +ENTRY(bootmsg_cp) + mflr r11 + mr r9, r3 // save checkpoint ID + li r3, 'C' + bl io_putchar // print character + mr r3, r9 + bl io_printhex16 // print checkpoint ID + .rept 5 + li r3,'\b' + bl io_putchar // print backspaces + .endr + mtlr r11 + blr + +//***************************************************************************** +// Print a general BootMessage +// input : r3=cp-id, r4=string, r5=char (type C,W,E) +// change: r3,r4,r5,r6,r7,r9,r10,r11,r12 +// output: none +ENTRY(print_msg) + mflr r11 // Save linkage register + mr r9, r3 // Save ID + mr r10, r4 // Save ptr to string + mr r12, r5 // Save type (char [CWE]) + li r3, '\n' // make it a new line + bl io_putchar + li r3, '\r' + bl io_putchar + mr r3, r12 // restore type + bl io_putchar // print character + mr r3, r9 // restore ID + bl io_printhex16 // print checkpoint ID + li r3, ' ' // print a space + bl io_putchar + mr r3, r10 // restore ptr to string + bl io_print // print message + li r3, '\n' // add a new line + bl io_putchar + li r3, '\r' + bl io_putchar + mtlr r11 // restore linkage register + blr + +//***************************************************************************** +// Print an Error Boot Message +// input : r3=cp-id, r4=string-ptr +// change : r3,r4,r5,r6,r7,r9,r10,r11,r12 +// output : none +ENTRY(bootmsg_error) + li r5, 'E' // E is for Error + b print_msg // and print this message + +//***************************************************************************** +// Print a Warning Boot Message +// input : r3=cp-id, r4=string-ptr, r5=level +// change : r3,r4,r5,r6,r7,r9,r10,r11,r12 +// output : none +ENTRY(bootmsg_warning) + mflr r11 // save linkage register + bl GET_WRNG_LVL // check UserLevel against SystemLevel + mtlr r11 // restore linkage register + li r5, 'W' // 'W' is for Warning + ble print_msg // if UserLevel<=SystemLevel print and return + blr // else return + +//***************************************************************************** +// Print a Debug Checkpoint +// input : r3=cp-id, r4=string-ptr, r5=level +// change : r3,r4,r5,r6,r7,r9,r10,r11,r12 +// output : none +// r3=cp-id, r4=string, r5=level +ENTRY(bootmsg_debugcp) + mflr r11 // save linkage register + addi r5,r5,0x20 // add checkpoint offset + bl GET_WRNG_LVL // check UserLevel against SystemLevel + mtlr r11 // restore linkage register + li r5, 'D' // 'D' is for Debug CheckPoint + ble print_msg // if UserLevel<=SystemLevel print and return + blr // else return + +//***************************************************************************** +// Check warning level +// input : r3=cp-id, r4=level +// change : r3,r4,r5,r6,r7,r9,r10,r11 +// output : r3 (true, false) +// r3=cp-id, r4=level +ENTRY(bootmsg_checklevel) + mflr r11 + mr r5, r4 + slwi r3, r3, 8 + bl GET_WRNG_LVL // check UserLevel against SystemLevel + li r3, 0 // return 0 + bgt 0f // IF ( UserLevel < SystemLevel ) + li r3, 1 // | return 1 +0: mtlr r11 // FI + blr + +// r3=area|pkg, r4=level +ENTRY(bootmsg_setlevel) + mflr r5 + bl WarningMsg // calc current IA + WarningMsg: + mflr r6 // get current IA + addi r6,r6,WRNG_LVL-WarningMsg + andi. r3, r3, 0x7F + add r6,r3,r6 // address | + stb r4,0(r6) // store level |_ stwbrx r4,r3,r6 + LOAD64(r6, SB_NVRAM_FWONLY_adr + 8 ) + add r6,r6,r3 + stb r4,0(r6) + mtlr r5 + blr + +ENTRY(bootmsg_nvupdate) + mflr r10 + LOAD64(r3, SB_NVRAM_FWONLY_adr) + lwz r4, 0(r3) + cmpwi r4, 0x424E // find bootmsg area header + bne 0f + + LOAD64(r5, bootmsg_area_size/8) + mtctr r5 + bl WngMsg + WngMsg: + mflr r5 + addi r5,r5,WRNG_LVL-WngMsg-8 + +1: + ldu r4, 8(r3) + stdu r4, 8(r5) + bdnz+ 1b + b 2f + +0: + LOAD64(r5, bootmsg_area_size) + mtctr r5 + li r4, 0x424E // clear bootmsg log area + stw r4, 0(r3) + li r4, 0 + +1: stdu r4, 8(r3) + bdnz+ 1b + +2: // the end + mtlr r10 + blr diff --git a/lib/libbootmsg/libbootmsg.h b/lib/libbootmsg/libbootmsg.h new file mode 100644 index 0000000..9d0bd15 --- /dev/null +++ b/lib/libbootmsg/libbootmsg.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#ifndef _LIBBOOTMSG_H +#define _LIBBOOTMSG_H +void bootmsg_cp(short p); +void bootmsg_error(short p, const char *str); +void bootmsg_warning(short p, const char *str, short lvl); +void bootmsg_debugcp(short p, const char *str, short lvl); +void bootmsg_setlevel(short p, short level); +int bootmsg_checklevel(short p, short level); +void *bootmsg_nvupdate(void); +#endif /* _LIBBOOTMSG_H */ diff --git a/lib/libc/Makefile b/lib/libc/Makefile new file mode 100644 index 0000000..0c762ec --- /dev/null +++ b/lib/libc/Makefile @@ -0,0 +1,61 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +TOPCMNDIR ?= ../.. + +LIBCCMNDIR = $(shell pwd) +STRINGCMNDIR = $(LIBCCMNDIR)/string +CTYPECMNDIR = $(LIBCCMNDIR)/ctype +STDLIBCMNDIR = $(LIBCCMNDIR)/stdlib +STDIOCMNDIR = $(LIBCCMNDIR)/stdio +GETOPTCMNDIR = $(LIBCCMNDIR)/getopt + +include $(TOPCMNDIR)/make.rules + + +CPPFLAGS = -I$(LIBCCMNDIR)/include +LDFLAGS= -nostdlib + +TARGET = ../libc.a + + +all: $(TARGET) + +# Use the following target to build a native version of the lib +# (for example for debugging purposes): +native: + $(MAKE) CROSS="" CC=$(HOSTCC) NATIVEBUILD=1 + + +include $(STRINGCMNDIR)/Makefile.inc +include $(CTYPECMNDIR)/Makefile.inc +include $(STDLIBCMNDIR)/Makefile.inc +include $(STDIOCMNDIR)/Makefile.inc +include $(GETOPTCMNDIR)/Makefile.inc + +OBJS = $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) $(GETOPT_OBJS) + +ifneq ($(NATIVEBUILD),1) +# These parts of the libc use assembler, so they can only be compiled when +# we are _not_ building a native version. +endif + + +$(TARGET): $(OBJS) + $(AR) -rc $@ $(OBJS) + $(RANLIB) $@ + + +clean: + $(RM) $(TARGET) $(OBJS) + +distclean: clean diff --git a/lib/libc/README.txt b/lib/libc/README.txt new file mode 100644 index 0000000..eaafdf4 --- /dev/null +++ b/lib/libc/README.txt @@ -0,0 +1,49 @@ + + Standard C library for the SLOF firmware project + ================================================ + +To use this library, link your target against the "libc.a" archive. + +However, there are some prerequisites before you can use certain parts of the +library: + +1) If you want to use malloc() and the like, you have to supply an implemen- + tation of sbrk() in your own code. malloc() uses sbrk() to get new, free + memory regions. + + Prototype: void *sbrk(int incr); + Description: sbrk() increments the available data space by incr bytes and + returns a pointer to the start of the new area. + + See the man-page of sbrk for details about this function. + +2) Before you can use the stdio output functions like printf(), puts() and the + like, you have to provide a standard write() function in your code. + printf() and the like use write() to print out the strings to the standard + output. + + Prototype: ssize_t write(int fd, const void *buf, size_t cnt); + Description: Write cnt byte from the buffer buf to the stream associated + with the file descriptor fd. + + The stdio functions will print their output to the stdout channel which is + assigned with the file descriptor 1 by default. Note that the stdio + functions will not use open() before calling write(), so if the stdout + cannel needs to be opened first, you should do that in your start-up code + before using the libc functions for the first time. + +3) Before you can use the stdio input functions like scanf() and the + like, you have to provide a standard read() function in your code. + scanf() and the like use read() to get the characters from the standard + input. + + Prototype: ssize_t read(int fd, void *buf, size_t cnt); + Description: Read cnt byte from the stream associated with the file + descriptor fd and put them into the buffer buf. + + The stdio functions will get their input from the stdin channel which is + assigned with the file descriptor 0 by default. Note that the stdio + functions will not use open() before calling read(), so if the stdin + cannel needs to be opened first, you should do that in your start-up code + before using the libc functions for the first time. + diff --git a/lib/libc/ctype/Makefile.inc b/lib/libc/ctype/Makefile.inc new file mode 100644 index 0000000..25513a9 --- /dev/null +++ b/lib/libc/ctype/Makefile.inc @@ -0,0 +1,20 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + + +CTYPE_SRC_C = isdigit.c isprint.c isspace.c isxdigit.c tolower.c toupper.c +CTYPE_SRC_ASM = +CTYPE_SRCS = $(CTYPE_SRC_C:%=$(CTYPECMNDIR)/%) $(CTYPE_SRC_ASM:%=$(CTYPECMNDIR)/%) +CTYPE_OBJS = $(CTYPE_SRC_C:%.c=%.o) $(CTYPE_SRC_ASM:%.S=%.o) + +%.o : $(CTYPECMNDIR)/%.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/lib/libc/ctype/isdigit.c b/lib/libc/ctype/isdigit.c new file mode 100644 index 0000000..62d08a1 --- /dev/null +++ b/lib/libc/ctype/isdigit.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int isdigit(int ch) +{ + switch (ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return 1; + + default: + return 0; + } +} diff --git a/lib/libc/ctype/isprint.c b/lib/libc/ctype/isprint.c new file mode 100644 index 0000000..c74880f --- /dev/null +++ b/lib/libc/ctype/isprint.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int isprint(int ch) +{ + return (ch >= 32 && ch < 127); +} diff --git a/lib/libc/ctype/isspace.c b/lib/libc/ctype/isspace.c new file mode 100644 index 0000000..5123019 --- /dev/null +++ b/lib/libc/ctype/isspace.c @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int isspace(int ch) +{ + switch (ch) { + case ' ': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + return 1; + + default: + return 0; + } +} diff --git a/lib/libc/ctype/isxdigit.c b/lib/libc/ctype/isxdigit.c new file mode 100644 index 0000000..9d323f3 --- /dev/null +++ b/lib/libc/ctype/isxdigit.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int isxdigit(int ch) +{ + return ( + (ch >= '0' && ch <= '9') | + (ch >= 'A' && ch <= 'F') | + (ch >= 'a' && ch <= 'f') ); +} diff --git a/lib/libc/ctype/tolower.c b/lib/libc/ctype/tolower.c new file mode 100644 index 0000000..f775e90 --- /dev/null +++ b/lib/libc/ctype/tolower.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <ctype.h> + +int tolower(int c) +{ + return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c); +} diff --git a/lib/libc/ctype/toupper.c b/lib/libc/ctype/toupper.c new file mode 100644 index 0000000..9bcee52 --- /dev/null +++ b/lib/libc/ctype/toupper.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "ctype.h" + +int toupper (int cha) +{ + if((cha >= 'a') && (cha <= 'z')) + return(cha - 'a' + 'A'); + return(cha); +} diff --git a/lib/libc/getopt/Makefile.inc b/lib/libc/getopt/Makefile.inc new file mode 100644 index 0000000..8a2e32f --- /dev/null +++ b/lib/libc/getopt/Makefile.inc @@ -0,0 +1,17 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +GETOPT_SRC_C = getopt.c +GETOPT_OBJS = $(GETOPT_SRC_C:%.c=%.o) + +%.o : $(GETOPTCMNDIR)/%.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/lib/libc/getopt/getopt.c b/lib/libc/getopt/getopt.c new file mode 100644 index 0000000..be626dd --- /dev/null +++ b/lib/libc/getopt/getopt.c @@ -0,0 +1,470 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * includes + ******************************************************************************* + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> + +/* + * global variables, types & constants + * may be removed if already defined + ******************************************************************************* + */ +int opterr = 1; +int optopt = 0; +int optind = 1; +char *optarg = NULL; + +/* + * internal values needed by getopt + * DO NOT CHANGE or REMOVE + */ +enum { + OPTIONAL_ARG = 0, + MANDATORY_ARG = 1, + NO_ARG = 2 +}; + +/* + * variables needed by getopt & getopt_long! + * DO NOT REMOVE + */ +static char *optstart = NULL; + +int +getopt(int argc, char **argv, const char *options) +{ + char *optptr; + char *argptr; + int optman; + int idx; + int ret = 0; + int argpresent; + + /* + * reset used global values + */ + optopt = 0; + optarg = NULL; + + /* + * reset getopt if a new argv pointer is passed + */ + if (optstart != argv[0]) { + optopt = 0; + optind = 1; + optarg = NULL; + optstart = argv[0]; + } + + /* + * return if no more arguments are available + */ + if (optind >= argc) { + return -1; + } + + /* + * start parsing argv[optind] + */ + idx = 0; + + /* + * return if the option does not begin with a '-' or has more than 2 characters + */ + if (argv[optind][idx] != '-') { + + if (opterr != 0) { + printf("unknown option \'%s\', expecting \'-\'\n", + argv[optind]); + } + + optopt = (int) argv[optind][idx]; + optind++; + + return '?'; + } + + /* + * continue to the next character in argv[optind] + */ + idx++; + + /* + * identify the option + * make sure if an option contains a ':' to invalidate the option + */ + optptr = strchr(argv[optind], ':'); + + if (optptr == NULL) { + optptr = strchr(options, (int) argv[optind][idx]); + } else { + optptr = NULL; + } + + /* + * check whether the option is present + */ + if (optptr == NULL) { + /* + * unknown option detected + */ + if (opterr != 0) { + printf("unknown option \'%s\'\n", argv[optind]); + } + + optopt = (int) argv[optind][idx]; + optind++; + + return '?'; + } + + /* + * the option is present in the option string + * setup return value + */ + ret = (int) *optptr; + + /* + * get option argument if needed + */ + optptr++; + + /* + * determine between mandatory and optional argument + */ + optman = NO_ARG; + + if (*optptr == ':') { + optman--; // now set to MANDATORY_ARG + } + + if (optman == MANDATORY_ARG) { + optptr++; + + if (*optptr == ':') { + optman--; // now set to OPTIONAL_ARG + } + + } + + /* + * if strlen( argv[optind ) is greater than 2, + * the argument is in the same argv + */ + if (strlen(argv[optind]) > 2) { + argptr = &argv[optind][2]; + + /* + * do not allow '-' in an argument + */ + if (strchr(argptr, '-') != NULL) { + + if (opterr != 0) { + printf + ("illegal argument value \'%s\' for option \'-%c\'\n", + argptr, ret); + } + + optopt = ret; + + return '?'; + } + + } else { + /* + * move on to the next argv + * it now either contains an argument or the next option + */ + optind++; + + /* + * make sure not to overflow + */ + if (optind < argc) { + argptr = argv[optind]; + } else { + argptr = NULL; + } + + } + + /* + * do the needed actions for the argument state + */ + switch (optman) { + case OPTIONAL_ARG: + + if (argptr == NULL) { + break; + } + + if (*argptr != '-') { + /* + * argument present + */ + optarg = argptr; + optind++; + + } + + + break; + + case MANDATORY_ARG: + argpresent = (argptr != NULL); + + if (argpresent) { + argpresent = (*argptr != '-'); + } + + if (argpresent) { + /* + * argument present + */ + optarg = argptr; + optind++; + } else { + /* + * mandatory argument missing + */ + if (opterr != 0) { + printf + ("missing argument for option \'-%c\'\n", + ret); + } + + optopt = ret; + + /* + * if the first character of options is a ':' + * return a ':' instead of a '?' in case of + * a missing argument + */ + if (*options == ':') { + ret = ':'; + } else { + ret = '?'; + } + + } + + + break; + + case NO_ARG: + + if (strlen(argv[optind - 1]) > 2) { + + if (opterr != 0) { + printf + ("too many arguments for option \'-%c\'\n", + ret); + } + + optopt = ret; + ret = '?'; + } + + + break; + + } + + return ret; +} + +int +getopt_long(int argc, char **argv, const char *shortopts, + const struct option *longopts, int *indexptr) +{ + struct option *optptr = (struct option *) longopts; + int optidx = 0; + int idx; + int ret = 0; + int argpresent; + + /* + * reset used global values + */ + optopt = 0; + optarg = NULL; + + /* + * reset indexptr + */ + *indexptr = -1; + + /* + * reset getopt if a new argv pointer is passed + */ + if (optstart != argv[0]) { + optopt = 0; + optind = 1; + optarg = NULL; + optstart = argv[0]; + } + + /* + * return if no more arguments are available + */ + if (optind >= argc) { + return -1; + } + + /* + * start parsing argv[optind] + */ + idx = 0; + + /* + * return if the option does not begin with a '-' + */ + if (argv[optind][idx] != '-') { + printf("unknown option \'%s\', expecting \'-\'\n", + argv[optind]); + + optind++; + + return '?'; + } + + /* + * move on to the next character in argv[optind] + */ + idx++; + + /* + * return getopt() in case of a short option + */ + if (argv[optind][idx] != '-') { + return getopt(argc, argv, shortopts); + } + + /* + * handle a long option + */ + idx++; + + while (optptr->name != NULL) { + + if (strcmp(&argv[optind][idx], optptr->name) == 0) { + break; + } + + optptr++; + optidx++; + } + + /* + * no matching option found + */ + if (optptr->name == NULL) { + printf("unknown option \'%s\'\n", argv[optind]); + + optind++; + + return '?'; + } + + /* + * option was found, set up index pointer + */ + *indexptr = optidx; + + /* + * get argument + */ + optind++; + + switch (optptr->has_arg) { + case no_argument: + /* + * nothing to do + */ + + break; + + case required_argument: + argpresent = (optind != argc); + + if (argpresent) { + argpresent = (argv[optind][0] != '-'); + } + + if (argpresent) { + /* + * argument present + */ + optarg = argv[optind]; + optind++; + } else { + /* + * mandatory argument missing + */ + printf("missing argument for option \'%s\'\n", + argv[optind - 1]); + + ret = '?'; + } + + + break; + + case optional_argument: + + if (optind == argc) { + break; + } + + if (argv[optind][0] != '-') { + /* + * argument present + */ + optarg = argv[optind]; + optind++; + } + + + break; + + default: + printf("unknown argument option for option \'%s\'\n", + argv[optind - 1]); + + ret = '?'; + + break; + + } + + /* + * setup return values + */ + if (ret != '?') { + + if (optptr->flag == NULL) { + ret = optptr->val; + } else { + *optptr->flag = optptr->val; + ret = 0; + } + + } + + return ret; +} diff --git a/lib/libc/include/ctype.h b/lib/libc/include/ctype.h new file mode 100644 index 0000000..9051a75 --- /dev/null +++ b/lib/libc/include/ctype.h @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _CTYPE_H +#define _CTYPE_H + +int isdigit(int c); +int isxdigit(int c); +int isprint(int c); +int isspace(int c); + +int tolower(int c); +int toupper(int c); + +#endif diff --git a/lib/libc/include/errno.h b/lib/libc/include/errno.h new file mode 100644 index 0000000..d585934 --- /dev/null +++ b/lib/libc/include/errno.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +/* + * Error number definitions + */ +#define EPERM 1 /* not permitted */ +#define ENOENT 2 /* file or directory not found */ +#define EIO 5 /* input/output error */ +#define ENOMEM 12 /* not enough space */ +#define EACCES 13 /* permission denied */ +#define EFAULT 14 /* bad address */ +#define EBUSY 16 /* resource busy */ +#define EEXIST 17 /* file already exists */ +#define ENODEV 19 /* device not found */ +#define EINVAL 22 /* invalid argument */ +#define EDOM 33 /* math argument out of domain of func */ +#define ERANGE 34 /* math result not representable */ + +#endif diff --git a/lib/libc/include/getopt.h b/lib/libc/include/getopt.h new file mode 100644 index 0000000..5956986 --- /dev/null +++ b/lib/libc/include/getopt.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef GETOPT_H +#define GETOPT_H + +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +enum { + no_argument = 0, + required_argument, + optional_argument +}; + +int getopt(int argc, char **, const char *); +int getopt_long(int argc, char **, const char *, const struct option *, int *); + +#endif /* GETOPT_H */ diff --git a/lib/libc/include/limits.h b/lib/libc/include/limits.h new file mode 100644 index 0000000..4726835 --- /dev/null +++ b/lib/libc/include/limits.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define UCHAR_MAX 255 +#define SCHAR_MAX 127 +#define SCHAR_MIN (-128) + +#define USHRT_MAX 65535 +#define SHRT_MAX 32767 +#define SHRT_MIN (-32768) + +#define UINT_MAX (4294967295U) +#define INT_MAX 2147483647 +#define INT_MIN (-2147483648) + +#define ULONG_MAX ((unsigned long)-1L) +#define LONG_MAX (ULONG_MAX/2) +#define LONG_MIN ((-LONG_MAX)-1) + +#endif diff --git a/lib/libc/include/stdarg.h b/lib/libc/include/stdarg.h new file mode 100644 index 0000000..d3d12f7 --- /dev/null +++ b/lib/libc/include/stdarg.h @@ -0,0 +1,22 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDARG_H +#define _STDARG_H + +typedef __builtin_va_list va_list; + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_end(v) __builtin_va_end(v) + +#endif diff --git a/lib/libc/include/stddef.h b/lib/libc/include/stddef.h new file mode 100644 index 0000000..ba2d960 --- /dev/null +++ b/lib/libc/include/stddef.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDDEF_H +#define _STDDEF_H + + +#define NULL ((void *)0) + + +typedef unsigned int size_t; + + +#endif + + diff --git a/lib/libc/include/stdint.h b/lib/libc/include/stdint.h new file mode 100644 index 0000000..518a723 --- /dev/null +++ b/lib/libc/include/stdint.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +#endif diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h new file mode 100644 index 0000000..84cddea --- /dev/null +++ b/lib/libc/include/stdio.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDIO_H +#define _STDIO_H + +#include <stdarg.h> +#include "stddef.h" + +#define EOF (-1) + +#define _IONBF 0 +#define _IOLBF 1 +#define _IOFBF 2 +#define BUFSIZ 80 + +typedef struct { + int fd; + int mode; + int pos; + char *buf; + int bufsiz; +} FILE; + +extern FILE stdin_data; +extern FILE stdout_data; +extern FILE stderr_data; + +#define stdin (&stdin_data) +#define stdout (&stdout_data) +#define stderr (&stderr_data) + +int fileno(FILE *stream); +int printf(const char *format, ...) __attribute__((format (printf, 1, 2))); +int fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); +int sprintf(char *str, const char *format, ...) __attribute__((format (printf, 2, 3))); +int vfprintf(FILE *stream, const char *format, va_list); +int vsprintf(char *str, const char *format, va_list); +int vsnprintf(char *str, size_t size, const char *format, va_list); +void setbuf(FILE *stream, char *buf); +int setvbuf(FILE *stream, char *buf, int mode , size_t size); + +int putc(int ch, FILE *stream); +int putchar(int ch); +int puts(char *str); + +int scanf(const char *format, ...) __attribute__((format (scanf, 1, 2))); +int fscanf(FILE *stream, const char *format, ...) __attribute__((format (scanf, 2, 3))); +int vfscanf(FILE *stream, const char *format, va_list); +int vsscanf(const char *str, const char *format, va_list); +int getc(FILE *stream); +int getchar(void); + +#endif diff --git a/lib/libc/include/stdlib.h b/lib/libc/include/stdlib.h new file mode 100644 index 0000000..dff57f5 --- /dev/null +++ b/lib/libc/include/stdlib.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include "stddef.h" + +#define RAND_MAX 32767 + + +void *malloc(size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); +void *memalign(size_t boundary, size_t size); + +int atoi(const char *str); +long atol(const char *str); +unsigned long int strtoul(const char *nptr, char **endptr, int base); +long int strtol(const char *nptr, char **endptr, int base); + +int rand(void); + +#endif diff --git a/lib/libc/include/string.h b/lib/libc/include/string.h new file mode 100644 index 0000000..ebc7568 --- /dev/null +++ b/lib/libc/include/string.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _STRING_H +#define _STRING_H + +#include "stddef.h" + +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strcat(char *dest, const char *src); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +size_t strlen(const char *s); +char *strstr(const char *hay, const char *needle); + +void *memset(void *s, int c, size_t n); +void *memchr(const void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +#endif diff --git a/lib/libc/include/unistd.h b/lib/libc/include/unistd.h new file mode 100644 index 0000000..f1b1c62 --- /dev/null +++ b/lib/libc/include/unistd.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef _UNISTD_H +#define _UNISTD_H + +typedef long ssize_t; + +extern int open(const char *name, int flags); +extern int close(int fd); +extern ssize_t read(int fd, void *buf, size_t count); +extern ssize_t write(int fd, const void *buf, size_t count); +extern ssize_t lseek(int fd, long offset, int whence); + +extern void *sbrk(int increment); + +#endif diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc new file mode 100644 index 0000000..ac5302d --- /dev/null +++ b/lib/libc/stdio/Makefile.inc @@ -0,0 +1,23 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + + +STDIO_SRC_C = fscanf.c sprintf.c vfprintf.c vsnprintf.c vsprintf.c fprintf.c \ + printf.c setvbuf.c putc.c puts.c putchar.c scanf.c stdchnls.c \ + vfscanf.c vsscanf.c fileno.c + +STDIO_SRC_ASM = +STDIO_SRCS = $(STDIO_SRC_C:%=$(STDIOCMNDIR)/%) $(STDIO_SRC_ASM:%=$(STDIOCMNDIR)/%) +STDIO_OBJS = $(STDIO_SRC_C:%.c=%.o) $(STDIO_SRC_ASM:%.S=%.o) + +%.o : $(STDIOCMNDIR)/%.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c new file mode 100644 index 0000000..6e23951 --- /dev/null +++ b/lib/libc/stdio/fileno.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int +fileno(FILE *stream) +{ + return stream->fd; +} diff --git a/lib/libc/stdio/fprintf.c b/lib/libc/stdio/fprintf.c new file mode 100644 index 0000000..866df39 --- /dev/null +++ b/lib/libc/stdio/fprintf.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" + + +int fprintf(FILE *stream, const char* fmt, ...) +{ + int count; + va_list ap; + + va_start(ap, fmt); + count = vfprintf(stream, fmt, ap); + va_end(ap); + + return count; +} diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c new file mode 100644 index 0000000..321b163 --- /dev/null +++ b/lib/libc/stdio/fscanf.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int +fscanf(FILE *stream, const char *fmt, ...) +{ + int count; + va_list ap; + + va_start(ap, fmt); + count = vfscanf(stream, fmt, ap); + va_end(ap); + + return count; +} diff --git a/lib/libc/stdio/printf.c b/lib/libc/stdio/printf.c new file mode 100644 index 0000000..01f4592 --- /dev/null +++ b/lib/libc/stdio/printf.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" + + +int printf(const char* fmt, ...) +{ + int count; + va_list ap; + + va_start(ap, fmt); + count = vfprintf(stdout, fmt, ap); + va_end(ap); + + return count; +} + diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c new file mode 100644 index 0000000..230e9d1 --- /dev/null +++ b/lib/libc/stdio/putc.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "unistd.h" + +int +putc(int ch, FILE *stream) +{ + unsigned char outchar = ch; + + if (write(stream->fd, &outchar, 1) == 1) + return outchar; + else + return EOF; +} diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c new file mode 100644 index 0000000..5c750d9 --- /dev/null +++ b/lib/libc/stdio/putchar.c @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" + + +int +putchar(int ch) +{ + return putc(ch, stdout); +} diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c new file mode 100644 index 0000000..3f48dbf --- /dev/null +++ b/lib/libc/stdio/puts.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" +#include "string.h" +#include "unistd.h" + + +int +puts(char *str) +{ + int ret; + + ret = write(stdout->fd, str, strlen(str)); + write(stdout->fd, "\r\n", 2); + + return ret; +} diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c new file mode 100644 index 0000000..96b6399 --- /dev/null +++ b/lib/libc/stdio/scanf.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int +scanf(const char *fmt, ...) +{ + int count; + va_list ap; + + va_start(ap, fmt); + count = vfscanf(stdin, fmt, ap); + va_end(ap); + + return count; +} diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c new file mode 100644 index 0000000..9b62dd8 --- /dev/null +++ b/lib/libc/stdio/setvbuf.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + +int setvbuf(FILE *stream, char *buf, int mode , size_t size) +{ + if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) + return -1; + stream->buf = buf; + stream->mode = mode; + stream->bufsiz = size; + return 0; +} + +void setbuf(FILE *stream, char *buf) +{ + setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c new file mode 100644 index 0000000..9c4540e --- /dev/null +++ b/lib/libc/stdio/sprintf.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdio.h> + + +int sprintf(char *buff, const char *format, ...) +{ + va_list ar; + int count; + + if ((buff==NULL) || (format==NULL)) + return(-1); + + va_start(ar, format); + count = vsprintf(buff, format, ar); + va_end(ar); + + return(count); +} + diff --git a/lib/libc/stdio/stdchnls.c b/lib/libc/stdio/stdchnls.c new file mode 100644 index 0000000..41ed958 --- /dev/null +++ b/lib/libc/stdio/stdchnls.c @@ -0,0 +1,23 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdio.h" + +static char stdin_buffer[BUFSIZ], stdout_buffer[BUFSIZ]; + +FILE stdin_data = { .fd = 0, .mode = _IOLBF, .pos = 0, + .buf = stdin_buffer, .bufsiz = BUFSIZ }; +FILE stdout_data = { .fd = 1, .mode = _IOLBF, .pos = 0, + .buf = stdout_buffer, .bufsiz = BUFSIZ }; +FILE stderr_data = { .fd = 2, .mode = _IONBF, .pos = 0, + .buf = NULL, .bufsiz = 0 }; diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c new file mode 100644 index 0000000..765feea --- /dev/null +++ b/lib/libc/stdio/vfprintf.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "unistd.h" + + +int vfprintf(FILE *stream, const char *fmt, va_list ap) +{ + int count; + char buffer[320]; + + count = vsnprintf(buffer, sizeof(buffer), fmt, ap); + write(stream->fd, buffer, count); + + return count; +} + diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c new file mode 100644 index 0000000..4ddd210 --- /dev/null +++ b/lib/libc/stdio/vfscanf.c @@ -0,0 +1,266 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" +#include "ctype.h" +#include "stdlib.h" +#include "stdio.h" +#include "unistd.h" + + +static int +_getc(FILE * stream) +{ + int count; + char c; + + if (stream->mode == _IONBF || stream->buf == NULL) { + if (read(stream->fd, &c, 1) == 1) + return (int) c; + else + return EOF; + } + + if (stream->pos == 0 || stream->pos >= BUFSIZ || + stream->buf[stream->pos] == '\0') { + count = read(stream->fd, stream->buf, BUFSIZ); + if (count < 0) + count = 0; + if (count < BUFSIZ) + stream->buf[count] = '\0'; + stream->pos = 0; + } + + return stream->buf[stream->pos++]; +} + +static void +_ungetc(int ch, FILE * stream) +{ + if (stream->mode != _IONBF && stream->pos > 0) + stream->pos--; +} + +static int +_is_voidage(int ch) +{ + if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\0') + return 1; + else + return 0; +} + + +static int +_scanf(FILE * stream, const char *fmt, va_list * ap) +{ + int i = 0; + int length = 0; + + fmt++; + + while (*fmt != '\0') { + + char tbuf[256]; + char ch; + + switch (*fmt) { + case 'd': + case 'i': + ch = _getc(stream); + if (length == 0) { + while (!_is_voidage(ch) && isdigit(ch)) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } else { + while (!_is_voidage(ch) && i < length + && isdigit(ch)) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } + /* We tried to understand what this is good for... + * but we did not. We know for sure that it does not + * work on SLOF if this is active. */ + /* _ungetc(ch, stream); */ + tbuf[i] = '\0'; + + /* ch = _getc(stream); */ + if (!_is_voidage(ch)) + _ungetc(ch, stream); + + if (strlen(tbuf) == 0) + return 0; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10); + break; + case 'X': + case 'x': + ch = _getc(stream); + if (length == 0) { + while (!_is_voidage(ch) && isxdigit(ch)) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } else { + while (!_is_voidage(ch) && i < length + && isxdigit(ch)) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } + /* _ungetc(ch, stream); */ + tbuf[i] = '\0'; + + /* ch = _getc(stream); */ + if (!_is_voidage(ch)) + _ungetc(ch, stream); + + if (strlen(tbuf) == 0) + return 0; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16); + break; + case 'O': + case 'o': + ch = _getc(stream); + if (length == 0) { + while (!_is_voidage(ch) + && !(ch < '0' || ch > '7')) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } else { + while (!_is_voidage(ch) && i < length + && !(ch < '0' || ch > '7')) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } + /* _ungetc(ch, stream); */ + tbuf[i] = '\0'; + + /* ch = _getc(stream); */ + if (!_is_voidage(ch)) + _ungetc(ch, stream); + + if (strlen(tbuf) == 0) + return 0; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8); + break; + case 'c': + ch = _getc(stream); + while (_is_voidage(ch)) + ch = _getc(stream); + + *(va_arg(*ap, char *)) = ch; + + ch = _getc(stream); + if (!_is_voidage(ch)) + _ungetc(ch, stream); + + break; + case 's': + ch = _getc(stream); + if (length == 0) { + while (!_is_voidage(ch)) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } else { + while (!_is_voidage(ch) && i < length) { + tbuf[i] = ch; + ch = _getc(stream); + i++; + } + } + /* _ungetc(ch, stream); */ + tbuf[i] = '\0'; + + /* ch = _getc(stream); */ + if (!_is_voidage(ch)) + _ungetc(ch, stream); + + strcpy(va_arg(*ap, char *), tbuf); + break; + default: + if (*fmt >= '0' && *fmt <= '9') + length += *fmt - '0'; + break; + } + fmt++; + } + + return 1; +} + + + +int +vfscanf(FILE * stream, const char *fmt, va_list ap) +{ + int args = 0; + + while (*fmt != '\0') { + + if (*fmt == '%') { + + char formstr[20]; + int i = 0; + + do { + formstr[i] = *fmt; + fmt++; + i++; + } while (! + (*fmt == 'd' || *fmt == 'i' || *fmt == 'x' + || *fmt == 'X' || *fmt == 'p' || *fmt == 'c' + || *fmt == 's' || *fmt == '%' || *fmt == 'O' + || *fmt == 'o')); + formstr[i++] = *fmt; + formstr[i] = '\0'; + if (*fmt != '%') { + if (_scanf(stream, formstr, &ap) <= 0) + return args; + else + args++; + } + + } + + fmt++; + + } + + return args; +} + +int +getc(FILE * stream) +{ + return _getc(stream); +} + +int +getchar(void) +{ + return _getc(stdin); +} diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c new file mode 100644 index 0000000..e78fb3d --- /dev/null +++ b/lib/libc/stdio/vsnprintf.c @@ -0,0 +1,242 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" + +const static unsigned long long convert[] = { + 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL +}; + + + +static int +print_itoa(char **buffer,unsigned long value, unsigned short int base) +{ + const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + static char sign = 0; + + if(base <= 2 || base > 16) + return 0; + + if(value < 0) { + sign = 1; + value *= -1; + } + + if(value < base) { + if(sign) { + **buffer = '-'; + *buffer += 1; + sign = 0; + } + **buffer = zeichen[value]; + *buffer += 1; + } else { + print_itoa(buffer, value / base, base); + **buffer = zeichen[(value % base)]; + *buffer += 1; + } + + return 1; +} + + +static unsigned int +print_intlen(unsigned long value, unsigned short int base) +{ + int i = 0; + + while(value > 0) { + value /= base; + i++; + } + if(i == 0) i = 1; + return i; +} + + +static int +print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen) +{ + int i, sizei, len; + + sizei = strtoul(sizec, NULL, 10); + len = print_intlen(size, base) + optlen; + if(sizei > len) { + for(i = 0; i < (sizei - len); i++) { + **buffer = c; + *buffer += 1; + } + } + + return 0; +} + + +static int +print_format(char **buffer, const char *format, void *var) +{ + unsigned long start; + unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int); + unsigned long value = 0; + unsigned long signBit; + char *form, sizec[32]; + char sign = ' '; + + form = (char *) format; + start = (unsigned long) *buffer; + + form++; + if(*form == '0' || *form == '.') { + sign = '0'; + form++; + } + + while(*form != '\0') { + switch(*form) { + case 'u': + case 'd': + case 'i': + sizec[i] = '\0'; + value = (unsigned long) var; + signBit = 0x1ULL << (length_mod * 8 - 1); + if (signBit & value) { + **buffer = '-'; + *buffer += 1; + value = (-(unsigned long)value) & convert[length_mod]; + } + print_fill(buffer, sizec, value, 10, sign, 0); + print_itoa(buffer, value, 10); + break; + case 'X': + case 'x': + sizec[i] = '\0'; + value = (unsigned long) var & convert[length_mod]; + print_fill(buffer, sizec, value, 16, sign, 0); + print_itoa(buffer, value, 16); + break; + case 'O': + case 'o': + sizec[i] = '\0'; + value = (long int) var & convert[length_mod]; + print_fill(buffer, sizec, value, 8, sign, 0); + print_itoa(buffer, value, 8); + break; + case 'p': + sizec[i] = '\0'; + print_fill(buffer, sizec, (unsigned long) var, 16, ' ', 2); + **buffer = '0'; + *buffer += 1; + **buffer = 'x'; + *buffer += 1; + print_itoa(buffer,(unsigned long) var, 16); + break; + case 'c': + sizec[i] = '\0'; + print_fill(buffer, sizec, 1, 10, ' ', 0); + **buffer = (unsigned long) var; + *buffer += 1; + break; + case 's': + sizec[i] = '\0'; + sizei = strtoul(sizec, NULL, 10); + len = strlen((char *) var); + if(sizei > len) { + for(i = 0; i < (sizei - len); i++) { + **buffer = ' '; + *buffer += 1; + } + } + for(i = 0; i < strlen((char *) var); i++) { + **buffer = ((char *) var)[i]; + *buffer += 1; + } + break; + case 'l': + form++; + if(*form == 'l') { + length_mod = sizeof(long long int); + } else { + form--; + length_mod = sizeof(long int); + } + break; + case 'h': + form++; + if(*form == 'h') { + length_mod = sizeof(signed char); + } else { + form--; + length_mod = sizeof(short int); + } + break; + default: + if(*form >= '0' && *form <= '9') + sizec[i++] = *form; + } + form++; + } + + + return (long int) (*buffer - start); +} + + +/* + * The vsnprintf function prints a formated strings into a buffer. + * BUG: buffer size checking does not fully work yet + */ +int +vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg) +{ + char *ptr, *bstart; + + bstart = buffer; + ptr = (char *) format; + + while(*ptr != '\0' && (buffer - bstart) < bufsize) + { + if(*ptr == '%') { + char formstr[20]; + int i=0; + + do { + formstr[i] = *ptr; + ptr++; + i++; + } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X' + || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%' + || *ptr == 'O' || *ptr == 'o' )); + formstr[i++] = *ptr; + formstr[i] = '\0'; + if(*ptr == '%') { + *buffer++ = '%'; + } else { + print_format(&buffer, formstr, va_arg(arg, void *)); + } + ptr++; + } else { + + *buffer = *ptr; + + buffer++; + ptr++; + } + } + + *buffer = '\0'; + + return (buffer - bstart); +} diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c new file mode 100644 index 0000000..0dfd737 --- /dev/null +++ b/lib/libc/stdio/vsprintf.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" + +int +vsprintf(char *buffer, const char *format, va_list arg) +{ + return vsnprintf(buffer, 0x7fffffff, format, arg); +} diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c new file mode 100644 index 0000000..b9603e9 --- /dev/null +++ b/lib/libc/stdio/vsscanf.c @@ -0,0 +1,131 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" + + +static void +_scanf(const char **buffer, const char *fmt, va_list *ap) +{ + int i; + int length = 0; + + fmt++; + + while(*fmt != '\0') { + + char tbuf[256]; + + switch(*fmt) { + case 'd': + case 'i': + if(length == 0) length = 256; + + for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) { + tbuf[i] = **buffer; + *buffer += 1; + } + tbuf[i] = '\0'; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 10); + break; + case 'X': + case 'x': + if(length == 0) length = 256; + + for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) { + tbuf[i] = **buffer; + *buffer += 1; + } + tbuf[i] = '\0'; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 16); + break; + case 'O': + case 'o': + if(length == 0) length = 256; + + for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) { + tbuf[i] = **buffer; + *buffer += 1; + } + tbuf[i] = '\0'; + + *(va_arg(*ap, int *)) = strtol(tbuf, NULL, 8); + break; + case 'c': + *(va_arg(*ap, char *)) = **buffer; + *buffer += 1; + if(length > 1) + for(i = 1; i < length; i++) + *buffer += 1; + break; + case 's': + if(length == 0) length = 256; + + for(i = 0; **buffer != ' ' && **buffer != '\t' && **buffer != '\n' && i < length; i++) { + tbuf[i] = **buffer; + *buffer += 1; + } + + tbuf[i] = '\0'; + + strcpy(va_arg(*ap, char *), tbuf); + break; + default: + if(*fmt >= '0' && *fmt <= '9') + length += *fmt - '0'; + break; + } + fmt++; + } + +} + + +int +vsscanf(const char *buffer, const char *fmt, va_list ap) +{ + + while(*fmt != '\0') { + + if(*fmt == '%') { + + char formstr[20]; + int i=0; + + do { + formstr[i] = *fmt; + fmt++; + i++; + } while(!(*fmt == 'd' || *fmt == 'i' || *fmt == 'x' || *fmt == 'X' + || *fmt == 'p' || *fmt == 'c' || *fmt == 's' || *fmt == '%' + || *fmt == 'O' || *fmt == 'o' )); + formstr[i++] = *fmt; + formstr[i] = '\0'; + if(*fmt != '%') { + while(*buffer == ' ' || *buffer == '\t' || *buffer == '\n') + buffer++; + _scanf(&buffer, formstr, &ap); + } + + } + + fmt++; + + } + + return 0; +} + diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc new file mode 100644 index 0000000..702f6d7 --- /dev/null +++ b/lib/libc/stdlib/Makefile.inc @@ -0,0 +1,22 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + + +STDLIB_SRC_C = error.c atoi.c atol.c strtoul.c strtol.c rand.c \ + malloc.c memalign.c realloc.c free.c + +STDLIB_SRC_ASM = +STDLIB_SRCS = $(STDLIB_SRC_C:%=$(STDLIBCMNDIR)/%) $(STDLIB_SRC_ASM:%=$(STDLIBCMNDIR)/%) +STDLIB_OBJS = $(STDLIB_SRC_C:%.c=%.o) $(STDLIB_SRC_ASM:%.S=%.o) + +%.o : $(STDLIBCMNDIR)/%.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/lib/libc/stdlib/atoi.c b/lib/libc/stdlib/atoi.c new file mode 100644 index 0000000..d2fb33b --- /dev/null +++ b/lib/libc/stdlib/atoi.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +int atoi(const char *str) +{ + return strtol(str, NULL, 0); +} diff --git a/lib/libc/stdlib/atol.c b/lib/libc/stdlib/atol.c new file mode 100644 index 0000000..a6aa47b --- /dev/null +++ b/lib/libc/stdlib/atol.c @@ -0,0 +1,18 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + +long atol(const char *str) +{ + return strtol(str, NULL, 0); +} diff --git a/lib/libc/stdlib/error.c b/lib/libc/stdlib/error.c new file mode 100644 index 0000000..81020ca --- /dev/null +++ b/lib/libc/stdlib/error.c @@ -0,0 +1,15 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +int errno; + diff --git a/lib/libc/stdlib/free.c b/lib/libc/stdlib/free.c new file mode 100644 index 0000000..9005450 --- /dev/null +++ b/lib/libc/stdlib/free.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdlib.h" +#include "malloc_defs.h" + +void +free(void *ptr) +{ + struct chunk *header; + + header = (struct chunk *) ptr; + header--; + header->inuse = 0; + +} diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c new file mode 100644 index 0000000..b2a3138 --- /dev/null +++ b/lib/libc/stdlib/malloc.c @@ -0,0 +1,157 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stddef.h" +#include "stdlib.h" +#include "unistd.h" +#include "malloc_defs.h" + + +static int clean(void); + + +/* act points to the end of the initialized heap and the start of uninitialized heap */ +static char *act; + +/* Pointers to start and end of heap: */ +static char *heap_start, *heap_end; + + +/* + * Standard malloc function + */ +void * +malloc(size_t size) +{ + char *header; + void *data; + size_t blksize; /* size of memory block including the chunk */ + + blksize = size + sizeof(struct chunk); + + /* has malloc been called for the first time? */ + if (act == 0) { + size_t initsize; + /* add some space so we have a good initial playground */ + initsize = (blksize + 0x1000) & ~0x0fff; + /* get initial memory region with sbrk() */ + heap_start = sbrk(initsize); + if (heap_start == (void*)-1) + return NULL; + heap_end = heap_start + initsize; + act = heap_start; + } + + header = act; + data = act + sizeof(struct chunk); + + /* Check if there is space left in the uninitialized part of the heap */ + if (act + blksize > heap_end) { + //search at begin of heap + header = heap_start; + + while ((((struct chunk *) header)->inuse != 0 + || ((struct chunk *) header)->length < size) + && header < act) { + header = header + sizeof(struct chunk) + + ((struct chunk *) header)->length; + } + + // check if heap is full + if (header >= act) { + if (clean()) { + // merging of free blocks succeeded, so try again + return malloc(size); + } else if (sbrk(blksize) == heap_end) { + // succeeded to get more memory, so try again + heap_end += blksize; + return malloc(size); + } else { + // No more memory available + return 0; + } + } + + // Check if we need to split this memory block into two + if (((struct chunk *) header)->length > blksize) { + //available memory is too big + int alt; + + alt = ((struct chunk *) header)->length; + ((struct chunk *) header)->inuse = 1; + ((struct chunk *) header)->length = size; + data = header + sizeof(struct chunk); + + //mark the rest of the heap + header = data + size; + ((struct chunk *) header)->inuse = 0; + ((struct chunk *) header)->length = + alt - blksize; + } else { + //new memory matched exactly in available memory + ((struct chunk *) header)->inuse = 1; + data = header + sizeof(struct chunk); + } + + } else { + + ((struct chunk *) header)->inuse = 1; + ((struct chunk *) header)->length = size; + + act += blksize; + } + + return data; +} + + +/* + * Merge free memory blocks in initialized heap if possible + */ +static int +clean(void) +{ + char *header; + char *firstfree = 0; + char check = 0; + + header = heap_start; + //if (act == 0) // This should never happen + // act = heap_end; + + while (header < act) { + + if (((struct chunk *) header)->inuse == 0) { + if (firstfree == 0) { + /* First free block in a row, only save address */ + firstfree = header; + + } else { + /* more than one free block in a row, merge them! */ + ((struct chunk *) firstfree)->length += + ((struct chunk *) header)->length + + sizeof(struct chunk); + check = 1; + } + } else { + firstfree = 0; + + } + + header = header + sizeof(struct chunk) + + ((struct chunk *) header)->length; + + } + + return check; +} diff --git a/lib/libc/stdlib/malloc_defs.h b/lib/libc/stdlib/malloc_defs.h new file mode 100644 index 0000000..1933026 --- /dev/null +++ b/lib/libc/stdlib/malloc_defs.h @@ -0,0 +1,16 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +struct chunk { + unsigned inuse : 4; + unsigned length : 28; +} __attribute__((packed)); diff --git a/lib/libc/stdlib/memalign.c b/lib/libc/stdlib/memalign.c new file mode 100644 index 0000000..3b678aa --- /dev/null +++ b/lib/libc/stdlib/memalign.c @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdlib.h" + + +void * +memalign(size_t blocksize, size_t bytes) +{ + void *x; + + x = malloc(bytes + blocksize); + x = (void *) (((unsigned long) x + blocksize - 1) & ~(blocksize - 1)); + + return (void *) x; +} diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c new file mode 100644 index 0000000..87e3efd --- /dev/null +++ b/lib/libc/stdlib/rand.c @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdlib.h> + + +static unsigned long _rand = 1; + +int +rand(void) +{ + _rand = _rand * 25364735 + 34563; + + return ((unsigned int) (_rand << 16) & RAND_MAX); +} diff --git a/lib/libc/stdlib/realloc.c b/lib/libc/stdlib/realloc.c new file mode 100644 index 0000000..652e900 --- /dev/null +++ b/lib/libc/stdlib/realloc.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include "stdlib.h" +#include "string.h" +#include "malloc_defs.h" + +void * +realloc(void *ptr, size_t size) +{ + struct chunk *header; + char *newptr, *start; + + header = (struct chunk *) ptr; + header--; + + if (size <= header->length) + return ptr; + + newptr = (char *) malloc(size); + if (newptr == NULL) + return 0; + + start = newptr; + memcpy((void *) newptr, (const void *) ptr, header->length); + + header->inuse = 0; + + return start; +} diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c new file mode 100644 index 0000000..aae5e54 --- /dev/null +++ b/lib/libc/stdlib/strtol.c @@ -0,0 +1,113 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +long int strtol(const char *S, char **PTR,int BASE) +{ + long rval = 0; + short int negative = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == 0) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // check if S starts with "-" in which case the return value is negative + if (**PTR == '-') + { + negative = 1; + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + (*PTR)++; + (*PTR)++; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <= '9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + if (negative) + { + return rval * -1; + } + //else + return rval; +} diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c new file mode 100644 index 0000000..3a86c50 --- /dev/null +++ b/lib/libc/stdlib/strtoul.c @@ -0,0 +1,103 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +unsigned long int strtoul(const char *S, char **PTR,int BASE) +{ + unsigned long rval = 0; + short int digit; + // *PTR is S, unless PTR is NULL, in which case i override it with my own ptr + char* ptr; + if (PTR == 0) + { + //override + PTR = &ptr; + } + // i use PTR to advance through the string + *PTR = (char *) S; + //check if BASE is ok + if ((BASE < 0) || BASE > 36) + { + return 0; + } + // ignore white space at beginning of S + while ((**PTR == ' ') + || (**PTR == '\t') + || (**PTR == '\n') + || (**PTR == '\r') + ) + { + (*PTR)++; + } + // if BASE is 0... determine the base from the first chars... + if (BASE == 0) + { + // if S starts with "0x", BASE = 16, else 10 + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + BASE = 16; + (*PTR)++; + (*PTR)++; + } + else + { + BASE = 10; + } + } + if (BASE == 16) + { + // S may start with "0x" + if ((**PTR == '0') && (*((*PTR)+1) == 'x')) + { + (*PTR)++; + (*PTR)++; + } + } + //until end of string + while (**PTR) + { + if (((**PTR) >= '0') && ((**PTR) <='9')) + { + //digit (0..9) + digit = **PTR - '0'; + } + else if (((**PTR) >= 'a') && ((**PTR) <='z')) + { + //alphanumeric digit lowercase(a (10) .. z (35) ) + digit = (**PTR - 'a') + 10; + } + else if (((**PTR) >= 'A') && ((**PTR) <='Z')) + { + //alphanumeric digit uppercase(a (10) .. z (35) ) + digit = (**PTR - 'A') + 10; + } + else + { + //end of parseable number reached... + break; + } + if (digit < BASE) + { + rval = (rval * BASE) + digit; + } + else + { + //digit found, but its too big for current base + //end of parseable number reached... + break; + } + //next... + (*PTR)++; + } + //done + return rval; +} + diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc new file mode 100644 index 0000000..7ccf3c4 --- /dev/null +++ b/lib/libc/string/Makefile.inc @@ -0,0 +1,22 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + + +STRING_SRC_C = strcat.c strchr.c strcmp.c strcpy.c strlen.c strncmp.c \ + strncpy.c strstr.c memset.c memcpy.c memmove.c memchr.c \ + memcmp.c strcasecmp.c strncasecmp.c strtok.c +STRING_SRC_ASM = +STRING_SRCS = $(STRING_SRC_C:%=$(STRINGCMNDIR)/%) $(STRING_SRC_ASM:%=$(STRINGCMNDIR)/%) +STRING_OBJS = $(STRING_SRC_C:%.c=%.o) $(STRING_SRC_ASM:%.S=%.o) + +%.o : $(STRINGCMNDIR)/%.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/lib/libc/string/memchr.c b/lib/libc/string/memchr.c new file mode 100644 index 0000000..c3fe751 --- /dev/null +++ b/lib/libc/string/memchr.c @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" + + +void * +memchr(const void *ptr, int c, size_t n) +{ + unsigned char ch = (unsigned char)c; + const unsigned char *p = ptr; + + while (n-- > 0) { + if (*p == ch) + return (void *)p; + p += 1; + } + + return NULL; +} diff --git a/lib/libc/string/memcmp.c b/lib/libc/string/memcmp.c new file mode 100644 index 0000000..3b69cef --- /dev/null +++ b/lib/libc/string/memcmp.c @@ -0,0 +1,30 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" + + +int +memcmp(const void *ptr1, const void *ptr2, size_t n) +{ + const unsigned char *p1 = ptr1; + const unsigned char *p2 = ptr2; + + while (n-- > 0) { + if (*p1 != *p2) + return (*p1 - *p2); + p1 += 1; + p2 += 1; + } + + return 0; +} diff --git a/lib/libc/string/memcpy.c b/lib/libc/string/memcpy.c new file mode 100644 index 0000000..00f419b --- /dev/null +++ b/lib/libc/string/memcpy.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" + +void * +memcpy(void *dest, const void *src, size_t n) +{ + char *cdest; + const char *csrc = src; + + cdest = dest; + while (n-- > 0) { + *cdest++ = *csrc++; + } + + return dest; +} diff --git a/lib/libc/string/memmove.c b/lib/libc/string/memmove.c new file mode 100644 index 0000000..3acf1a9 --- /dev/null +++ b/lib/libc/string/memmove.c @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" + + +void * +memmove(void *dest, const void *src, size_t n) +{ + char *cdest; + const char *csrc; + int i; + + /* Do the buffers overlap in a bad way? */ + if (src < dest && src + n >= dest) { + /* Copy from end to start */ + cdest = dest + n - 1; + csrc = src + n - 1; + for (i = 0; i < n; i++) { + *cdest-- = *csrc--; + } + } + else { + /* Normal copy is possible */ + cdest = dest; + csrc = src; + for (i = 0; i < n; i++) { + *cdest++ = *csrc++; + } + } + + return dest; +} diff --git a/lib/libc/string/memset.c b/lib/libc/string/memset.c new file mode 100644 index 0000000..f8dfbf5 --- /dev/null +++ b/lib/libc/string/memset.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "string.h" + +void * +memset(void *dest, int c, size_t size) +{ + unsigned char *d = (unsigned char *)dest; + + while (size-- > 0) { + *d++ = (unsigned char)c; + } + + return dest; +} diff --git a/lib/libc/string/strcasecmp.c b/lib/libc/string/strcasecmp.c new file mode 100644 index 0000000..f75294f --- /dev/null +++ b/lib/libc/string/strcasecmp.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> +#include <ctype.h> + +int +strcasecmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return *s1 - *s2; +} + diff --git a/lib/libc/string/strcat.c b/lib/libc/string/strcat.c new file mode 100644 index 0000000..eb597a0 --- /dev/null +++ b/lib/libc/string/strcat.c @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strcat(char *dst, const char *src) +{ + int p; + + p = strlen(dst); + strcpy(&dst[p], src); + + return dst; +} diff --git a/lib/libc/string/strchr.c b/lib/libc/string/strchr.c new file mode 100644 index 0000000..528a319 --- /dev/null +++ b/lib/libc/string/strchr.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strchr(const char *s, int c) +{ + char cb = c; + + while (*s != 0) { + if (*s == cb) { + return (char *)s; + } + s += 1; + } + + return NULL; +} diff --git a/lib/libc/string/strcmp.c b/lib/libc/string/strcmp.c new file mode 100644 index 0000000..48eaed2 --- /dev/null +++ b/lib/libc/string/strcmp.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + + +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/lib/libc/string/strcpy.c b/lib/libc/string/strcpy.c new file mode 100644 index 0000000..48eb62c --- /dev/null +++ b/lib/libc/string/strcpy.c @@ -0,0 +1,25 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strcpy(char *dst, const char *src) +{ + char *ptr = dst; + + do { + *ptr++ = *src; + } while (*src++ != 0); + + return dst; +} diff --git a/lib/libc/string/strlen.c b/lib/libc/string/strlen.c new file mode 100644 index 0000000..37a1b78 --- /dev/null +++ b/lib/libc/string/strlen.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +size_t +strlen(const char *s) +{ + int len = 0; + + while (*s != 0) { + len += 1; + s += 1; + } + + return len; +} + diff --git a/lib/libc/string/strncasecmp.c b/lib/libc/string/strncasecmp.c new file mode 100644 index 0000000..4140931 --- /dev/null +++ b/lib/libc/string/strncasecmp.c @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> +#include <ctype.h> + + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (toupper(*s1) != toupper(*s2)) + break; + ++s1; + ++s2; + } + + return toupper(*s1) - toupper(*s2); +} + diff --git a/lib/libc/string/strncmp.c b/lib/libc/string/strncmp.c new file mode 100644 index 0000000..a886736 --- /dev/null +++ b/lib/libc/string/strncmp.c @@ -0,0 +1,31 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + if (n < 1) + return 0; + + while (*s1 != 0 && *s2 != 0 && --n > 0) { + if (*s1 != *s2) + break; + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c new file mode 100644 index 0000000..0f41f93 --- /dev/null +++ b/lib/libc/string/strncpy.c @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strncpy(char *dst, const char *src, size_t n) +{ + char *ret = dst; + + /* Copy string */ + while (*src != 0 && n > 0) { + *dst++ = *src++; + n -= 1; + } + + /* strncpy always clears the rest of destination string... */ + while (n > 0) { + *dst++ = 0; + n -= 1; + } + + return ret; +} diff --git a/lib/libc/string/strstr.c b/lib/libc/string/strstr.c new file mode 100644 index 0000000..3e090d2 --- /dev/null +++ b/lib/libc/string/strstr.c @@ -0,0 +1,37 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strstr(const char *hay, const char *needle) +{ + char *pos; + int hlen, nlen; + + if (hay == NULL || needle == NULL) + return NULL; + + hlen = strlen(hay); + nlen = strlen(needle); + if (nlen < 1) + return (char *)hay; + + for (pos = (char *)hay; pos < hay + hlen; pos++) { + if (strncmp(pos, needle, nlen) == 0) { + return pos; + } + } + + return NULL; +} + diff --git a/lib/libc/string/strtok.c b/lib/libc/string/strtok.c new file mode 100644 index 0000000..665c08d --- /dev/null +++ b/lib/libc/string/strtok.c @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> + +char * +strtok(char *src, const char *pattern) +{ + static char *nxtTok; + char *retVal = NULL; + + if (!src) + src = nxtTok; + + while (*src) { + const char *pp = pattern; + while (*pp) { + if (*pp == *src) { + break; + } + pp++; + } + if (!*pp) { + if (!retVal) + retVal = src; + else if (!src[-1]) + break; + } else + *src = '\0'; + src++; + } + + nxtTok = src; + + return retVal; +} diff --git a/lib/libelf/Makefile b/lib/libelf/Makefile new file mode 100644 index 0000000..82ef0bb --- /dev/null +++ b/lib/libelf/Makefile @@ -0,0 +1,47 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +TOPCMNDIR ?= ../.. + +include $(TOPCMNDIR)/make.rules + +CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) +LDFLAGS= -nostdlib + +TARGET = ../libelf.a + +all: $(TARGET) + +SRCS = elf.c + +OBJS = $(SRCS:%.c=%.o) + +$(TARGET): $(OBJS) + $(AR) -rc $@ $(OBJS) + $(RANLIB) $@ + +clean: + $(RM) $(TARGET) $(OBJS) + +distclean: clean + $(RM) Makefile.dep + +# Rules for creating the dependency file: +depend: + $(RM) Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile + $(CC) -MM $(CPPFLAGS) $(CFLAGS) $(SRCS) > Makefile.dep + +# Include dependency file if available: +-include Makefile.dep diff --git a/lib/libelf/elf.c b/lib/libelf/elf.c new file mode 100644 index 0000000..359f628 --- /dev/null +++ b/lib/libelf/elf.c @@ -0,0 +1,234 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* this is elf.fs rewritten in C */ + +#include <string.h> +#include <cpu.h> +#include <libelf.h> + +struct ehdr { + unsigned int ei_ident; + unsigned char ei_class; + unsigned char ei_data; + unsigned char ei_version; + unsigned char ei_pad[9]; + unsigned short e_type; + unsigned short e_machine; + unsigned int e_version; + unsigned int e_entry; + unsigned int e_phoff; + unsigned int e_shoff; + unsigned int e_flags; + unsigned short e_ehsize; + unsigned short e_phentsize; + unsigned short e_phnum; + unsigned short e_shentsize; + unsigned short e_shnum; + unsigned short e_shstrndx; +}; + +struct phdr { + unsigned int p_type; + unsigned int p_offset; + unsigned int p_vaddr; + unsigned int p_paddr; + unsigned int p_filesz; + unsigned int p_memsz; + unsigned int p_flags; + unsigned int p_align; +}; + +struct ehdr64 { + unsigned int ei_ident; + unsigned char ei_class; + unsigned char ei_data; + unsigned char ei_version; + unsigned char ei_pad[9]; + unsigned short e_type; + unsigned short e_machine; + unsigned int e_version; + unsigned long e_entry; + unsigned long e_phoff; + unsigned long e_shoff; + unsigned int e_flags; + unsigned short e_ehsize; + unsigned short e_phentsize; + unsigned short e_phnum; + unsigned short e_shentsize; + unsigned short e_shnum; + unsigned short e_shstrndx; +}; + +struct phdr64 { + unsigned int p_type; + unsigned int p_flags; + unsigned long p_offset; + unsigned long p_vaddr; + unsigned long p_paddr; + unsigned long p_filesz; + unsigned long p_memsz; + unsigned long p_align; +}; + +#define VOID(x) (void *)((unsigned long)x) + +static void +load_segment(unsigned long *file_addr, struct phdr *phdr) +{ + unsigned long src = phdr->p_offset + (unsigned long) file_addr; + /* copy into storage */ + memmove(VOID(phdr->p_vaddr), VOID(src), phdr->p_filesz); + + /* clear bss */ + memset(VOID(phdr->p_vaddr + phdr->p_filesz), 0, + phdr->p_memsz - phdr->p_filesz); + + if (phdr->p_memsz) { + flush_cache(VOID(phdr->p_vaddr), phdr->p_memsz); + } +} + +static unsigned int +load_segments(unsigned long *file_addr) +{ + struct ehdr *ehdr = (struct ehdr *) file_addr; + /* Calculate program header address */ + struct phdr *phdr = + (struct phdr *) (((unsigned char *) file_addr) + ehdr->e_phoff); + int i; + /* loop e_phnum times */ + for (i = 0; i <= ehdr->e_phnum; i++) { + /* PT_LOAD ? */ + if (phdr->p_type == 1) { + /* copy segment */ + load_segment(file_addr, phdr); + } + /* step to next header */ + phdr = + (struct phdr *) (((unsigned char *) phdr) + + ehdr->e_phentsize); + } + return ehdr->e_entry; +} + +static void +load_segment64(unsigned long *file_addr, struct phdr64 *phdr64) +{ + unsigned long src = phdr64->p_offset + (unsigned long) file_addr; + /* copy into storage */ + memmove(VOID(phdr64->p_vaddr), VOID(src), phdr64->p_filesz); + + /* clear bss */ + memset(VOID(phdr64->p_vaddr + phdr64->p_filesz), 0, + phdr64->p_memsz - phdr64->p_filesz); + + if (phdr64->p_memsz) { + flush_cache(VOID(phdr64->p_vaddr), phdr64->p_memsz); + } +} + +static unsigned long +load_segments64(unsigned long *file_addr) +{ + struct ehdr64 *ehdr64 = (struct ehdr64 *) file_addr; + /* Calculate program header address */ + struct phdr64 *phdr64 = + (struct phdr64 *) (((unsigned char *) file_addr) + ehdr64->e_phoff); + int i; + /* loop e_phnum times */ + for (i = 0; i <= ehdr64->e_phnum; i++) { + /* PT_LOAD ? */ + if (phdr64->p_type == 1) { + /* copy segment */ + load_segment64(file_addr, phdr64); + } + /* step to next header */ + phdr64 = + (struct phdr64 *) (((unsigned char *) phdr64) + + ehdr64->e_phentsize); + } + return ehdr64->e_entry; +} + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_be32(x) (x) +#else +#define cpu_to_be32(x) bswap_32(x) +#endif + +/** + * elf_check_file tests if the file at file_addr is + * a correct endian, ELF PPC executable + * @param file_addr pointer to the start of the ELF file + * @return the class (1 for 32 bit, 2 for 64 bit) + * -1 if it is not an ELF file + * -2 if it has the wrong endianess + * -3 if it is not an ELF executable + * -4 if it is not for PPC + */ +static int +elf_check_file(unsigned long *file_addr) +{ + struct ehdr *ehdr = (struct ehdr *) file_addr; + /* check if it is an ELF image at all */ + if (cpu_to_be32(ehdr->ei_ident) != 0x7f454c46) + return -1; + + /* endian check */ +#if __BYTE_ORDER == __BIG_ENDIAN + if (ehdr->ei_data != 2) + /* not a big endian image */ +#else + if (ehdr->ei_data == 2) + /* not a little endian image */ +#endif + return -2; + + /* check if it is an ELF executable */ + if (ehdr->e_type != 2) + return -3; + + /* check if it is a PPC ELF executable */ + if (ehdr->e_machine != 0x14 && ehdr->e_machine != 0x15) + return -4; + + return ehdr->ei_class; +} + +/** + * load_elf_file tries to load the ELF file specified in file_addr + * + * it first checks if the file is a PPC ELF executable and then loads + * the segments depending if it is a 64bit or 32 bit ELF file + * + * @param file_addr pointer to the start of the elf file + * @param entry pointer where the ELF loader will store + * the entry point + * @return 1 for a 32 bit file + * 2 for a 64 bit file + * anything else means an error during load + */ +int +load_elf_file(unsigned long *file_addr, unsigned long *entry) +{ + int type = elf_check_file(file_addr); + switch (type) { + case 1: + *entry = load_segments(file_addr); + break; + case 2: + *entry = load_segments64(file_addr); + break; + } + return type; +} diff --git a/lib/libelf/libelf.code b/lib/libelf/libelf.code new file mode 100644 index 0000000..6e019fc --- /dev/null +++ b/lib/libelf/libelf.code @@ -0,0 +1,21 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +int load_elf_file(unsigned long *file_addr, unsigned long *entry); + +PRIM(LOADELF) + void *file_addr = TOS.a; + int type; + unsigned long entry; + type = load_elf_file(file_addr, &entry); + TOS.u = entry; + PUSH; TOS.n = type; +MIRP diff --git a/lib/libelf/libelf.in b/lib/libelf/libelf.in new file mode 100644 index 0000000..1fea40c --- /dev/null +++ b/lib/libelf/libelf.in @@ -0,0 +1,12 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +cod(LOADELF) diff --git a/lib/libipmi/Makefile b/lib/libipmi/Makefile new file mode 100644 index 0000000..4777f9e --- /dev/null +++ b/lib/libipmi/Makefile @@ -0,0 +1,28 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2007 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +TOPCMNDIR ?= ../.. + +LIBIPMICMNDIR = $(shell pwd) + +include $(TOPCMNDIR)/make.rules + +TARGET = ../libipmi.a + +all: $(TARGET) + +$(TARGET): + cp libipmi.oco $@ + +clean: + +distclean: diff --git a/lib/libipmi/libipmi.code b/lib/libipmi/libipmi.code new file mode 100644 index 0000000..59c1244 --- /dev/null +++ b/lib/libipmi/libipmi.code @@ -0,0 +1,120 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <libipmi.h> + +// : ipmi-kcs-cmd ( in-buf in-len out-buf out-maxlen -- out-len errorcode ) +PRIM(IPMI_X2d_KCS_X2d_CMD) + cell maxlen = TOS; POP; + cell outbuf = TOS; POP; + int len = TOS.n; POP; + cell inbuf = TOS; + int retval; + retval = ipmi_kcs_cmd(inbuf.a, outbuf.a, maxlen.n, (uint32_t *) &len); + TOS.n = len; + PUSH; TOS.n = retval; +MIRP + + +PRIM(IPMI_X2d_SYSTEM_X2d_REBOOT) + ipmi_system_reboot(); +MIRP + + +PRIM(IPMI_X2d_POWER_X2d_OFF) + ipmi_power_off(); +MIRP + + +// : ipmi-oem-stop-bootwatchdog ( -- errorcode ) +PRIM(IPMI_X2d_OEM_X2d_STOP_X2d_BOOTWATCHDOG) + PUSH; + TOS.n = ipmi_oem_stop_bootwatchdog(); +MIRP + + +// : ipmi-oem-set-bootwatchdog ( seconds -- errorcode ) +PRIM(IPMI_X2d_OEM_X2d_SET_X2d_BOOTWATCHDOG) + int sec = TOS.n; + TOS.n = ipmi_oem_set_bootwatchdog(sec); +MIRP + + +// : ipmi-oem-reset-bootwatchdog ( -- errorcode ) +PRIM(IPMI_X2d_OEM_X2d_RESET_X2d_BOOTWATCHDOG) + PUSH; + TOS.n = ipmi_oem_reset_bootwatchdog(); +MIRP + + +// : ipmi-oem-led-set ( type instance state -- errorcode ) +PRIM(IPMI_X2d_OEM_X2d_LED_X2d_SET) + int state = TOS.n; POP; + int instance = TOS.n; POP; + int type = TOS.n; + TOS.n = ipmi_oem_led_set(type, instance, state); +MIRP + + +// : ipmi-oem-read-vpd ( offset length dst -- status ) +PRIM(IPMI_X2d_OEM_X2d_READ_X2d_VPD) + cell dest = TOS; POP; + int len = TOS.n; POP; + int offset = TOS.n; + TOS.n = ipmi_oem_read_vpd(dest.a, len, offset); +MIRP + +// : ipmi-oem-write-vpd ( offset length src -- status ) +PRIM(IPMI_X2d_OEM_X2d_WRITE_X2d_VPD) + cell src = TOS; POP; + int len = TOS.n; POP; + int offset = TOS.n; + TOS.n = ipmi_oem_write_vpd(src.a, len, offset); +MIRP + + +// : ipmi-oem-get-blade-descr ( buf maxlen -- len status ) +PRIM(IPMI_X2d_OEM_X2d_GET_X2d_BLADE_X2d_DESCR) + int maxlen = TOS.n; POP; + cell buf = TOS; + int len = 0; + int retval; + retval = ipmi_oem_get_blade_descr(buf.a, maxlen, (uint32_t *) &len); + TOS.n = len; + PUSH; TOS.n = retval; +MIRP + + +// : ipmi-oem-bios2sp ( str-ptr str-len swid type -- errorcode ) +PRIM(IPMI_X2d_OEM_X2d_BIOS2SP) + int type = TOS.n; POP; + int swid = TOS.n; POP; + int len = TOS.n; POP; + void* addr = TOS.a; + TOS.n = ipmi_oem_bios2sp(swid, type, addr, len); +MIRP + +// : ipmi-set-sensor ( param-1 ... param-n n command sensor - errorcode ) +PRIM(IPMI_X2d_SET_X2d_SENSOR) + int sensor = TOS.n; POP; + int cmd = TOS.n; POP; + int n = TOS.n; + int i = n; + uint8_t param[10]; + while (i>0) { + i--; + POP; param[i]=TOS.n; + }; + TOS.n = ipmi_set_sensor((cmd<<8)+sensor,n, + param[0],param[1],param[2],param[3],param[4], + param[5],param[6],param[7],param[8],param[9]); +MIRP diff --git a/lib/libipmi/libipmi.h b/lib/libipmi/libipmi.h new file mode 100644 index 0000000..9ac8308 --- /dev/null +++ b/lib/libipmi/libipmi.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __LIBIPMI_H +#define __LIBIPMI_H + +#include <stdint.h> + +extern int ipmi_kcs_cmd(uint8_t *, uint8_t *, uint32_t, uint32_t *); + +extern void ipmi_system_reboot(void); +extern void ipmi_power_off(void); +extern int ipmi_set_sensor(const int sensor, int number_of_args, ...); + +extern int ipmi_oem_stop_bootwatchdog(void); +extern int ipmi_oem_set_bootwatchdog(uint16_t seconds); +extern int ipmi_oem_reset_bootwatchdog(void); +extern int ipmi_oem_led_set(int type, int instance, int state); +extern uint32_t ipmi_oem_read_vpd(uint8_t *dst, uint32_t len, uint32_t offset); +extern uint32_t ipmi_oem_write_vpd(uint8_t *src, uint32_t len, uint32_t offset); +extern uint32_t ipmi_oem_get_blade_descr(uint8_t *dst, uint32_t maxlen, uint32_t *len); +extern int ipmi_oem_bios2sp(int swid, int type, char *data, int len); + +#endif diff --git a/lib/libipmi/libipmi.in b/lib/libipmi/libipmi.in new file mode 100644 index 0000000..5b0e0ec --- /dev/null +++ b/lib/libipmi/libipmi.in @@ -0,0 +1,24 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +cod(IPMI-KCS-CMD) +cod(IPMI-SYSTEM-REBOOT) +cod(IPMI-POWER-OFF) +cod(IPMI-OEM-STOP-BOOTWATCHDOG) +cod(IPMI-OEM-SET-BOOTWATCHDOG) +cod(IPMI-OEM-RESET-BOOTWATCHDOG) +cod(IPMI-OEM-LED-SET) +cod(IPMI-OEM-READ-VPD) +cod(IPMI-OEM-WRITE-VPD) +cod(IPMI-OEM-GET-BLADE-DESCR) +cod(IPMI-OEM-BIOS2SP) +cod(IPMI-SET-SENSOR) diff --git a/lib/libnvram/Makefile b/lib/libnvram/Makefile new file mode 100644 index 0000000..6c9ec84 --- /dev/null +++ b/lib/libnvram/Makefile @@ -0,0 +1,49 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +SRCS = nvram.c envvar.c + +TOPCMNDIR ?= ../.. + +ASFLAGS = $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames +CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) -I$(INCLCMNDIR)/$(CPUARCH) -I. -I../../include +LDFLAGS = -nostdlib + +TARGET = ../libnvram.a + +all: $(TARGET) + +OBJS = $(SRCS:%.c=%.o) + +$(TARGET): $(OBJS) + $(AR) -rc $@ $(OBJS) + $(RANLIB) $@ + + +clean: + $(RM) $(TARGET) $(OBJS) + +distclean: clean + $(RM) Makefile.dep + + +# Rules for creating the dependency file: +depend: + $(RM) Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile + + +# Include dependency file if available: +-include Makefile.dep + diff --git a/lib/libnvram/envvar.c b/lib/libnvram/envvar.c new file mode 100644 index 0000000..eec7db7 --- /dev/null +++ b/lib/libnvram/envvar.c @@ -0,0 +1,244 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include "../libc/include/stdio.h" +#include "../libc/include/string.h" +#include "../libc/include/stdlib.h" +#include "nvram.h" + +/* returns the offset of the first byte after the searched envvar */ +static int get_past_env_pos(partition_t part, char *envvar) +{ + int offset, len; + static char temp[256]; + uint8_t data; + + offset=part.addr; + + memset(temp, 0, 256); + + do { + len=0; + while((data=nvram_read_byte(offset++)) && len < 256) { + temp[len++]=data; + } + if (!strncmp(envvar, temp, strlen(envvar))) { + return offset; + } + } while (len); + + return -1; +} + +/** + * @param partition name of the envvar partition + * @param envvar name of the environment variable + * @return pointer to temporary string containing the value of envvar + */ + +char *get_env(partition_t part, char *envvar) +{ + static char temp[256+1]; + int len, offset; + uint8_t data; + + DEBUG("get_env %s... ", envvar); + if(!part.addr) { + /* ERROR: No environment variable partition */ + DEBUG("invalid partition.\n"); + return NULL; + } + + offset=part.addr; + + do { + len=0; + while((data=nvram_read_byte(offset++)) && len < 256) { + temp[len++]=data; + } + temp[len]=0; + + if (!strncmp(envvar, temp, strlen(envvar))) { + int pos=0; + while (temp[pos]!='=' && pos < len) pos++; + // DEBUG("value='%s'\n", temp+pos+1); + return temp+pos+1; + } + } while (len); + + DEBUG("not found\n"); + return NULL; +} + +static int find_last_envvar(partition_t part) +{ + uint8_t last, current; + int offset, len; + + offset=part.addr; + len=part.len; + + last=nvram_read_byte(part.addr); + + for (offset=part.addr; offset<(int)(part.addr+part.len); offset++) { + current=nvram_read_byte(offset); + if(!last && !current) + return offset; + + last=current; + } + + return -1; +} + +int add_env(partition_t part, char *envvar, char *value) +{ + int freespace, last, len, offset; + unsigned int i; + + /* Find offset where we can write */ + last = find_last_envvar(part); + + /* How much space do we have left? */ + freespace = part.addr+part.len-last; + + /* how long is the entry we want to write? */ + len = strlen(envvar) + strlen(value) + 2; + + if(freespace<len) { + // TODO try to increase partition size + return -1; + } + + offset=last; + + for(i=0; i<strlen(envvar); i++) + nvram_write_byte(offset++, envvar[i]); + + nvram_write_byte(offset++, '='); + + for(i=0; i<strlen(value); i++) + nvram_write_byte(offset++, value[i]); + + return 0; +} + +int del_env(partition_t part, char *envvar) +{ + int last, current, pos, i; + char *buffer; + + if(!part.addr) + return -1; + + last=find_last_envvar(part); + current = pos = get_past_env_pos(part, envvar); + + // TODO is this really required? + /* go back to non-0 value */ + current--; + + while (nvram_read_byte(current)) + current--; + + // TODO is this required? + current++; + + buffer=get_nvram_buffer(last-pos); + + for (i=0; i<last-pos; i++) + buffer[i]=nvram_read_byte(i+pos); + + for (i=0; i<last-pos; i++) + nvram_write_byte(i+current, buffer[i]); + + free_nvram_buffer(buffer); + + erase_nvram(last, current+last-pos); + + return 0; +} + +int set_env(partition_t part, char *envvar, char *value) +{ + char *oldvalue, *buffer; + int last, current, buffersize, i; + + DEBUG("set_env %lx[%lx]: %s=%s\n", part.addr, part.len, envvar, value); + + if(!part.addr) + return -1; + + /* Check whether the environment variable exists already */ + oldvalue = get_env(part, envvar); + + if(oldvalue==NULL) + return add_env(part, envvar, value); + + + /* The value did not change. So we succeeded! */ + if(!strncmp(oldvalue, value, strlen(value)+1)) + return 0; + + /* we need to overwrite environment variables, back them up first */ + + // DEBUG("overwriting existing environment variable\n"); + + /* allocate a buffer */ + last=find_last_envvar(part); + current=get_past_env_pos(part, envvar); + buffersize = last - current; + buffer=get_nvram_buffer(buffersize); + if(!buffer) + return -1; + + for (i=0; i<buffersize; i++) { + buffer[i] = nvram_read_byte(current+i); + } + + /* walk back until the = */ + while (nvram_read_byte(current)!='=') { + current--; + } + + /* Start at envvar= */ + current++; + + /* Write the new value */ + for(i=0; i<(int)strlen(value); i++) { + nvram_write_byte(current++, value[i]); + } + + /* Write end of string marker */ + nvram_write_byte(current++, 0); + + /* Copy back the buffer */ + for (i=0; i<buffersize; i++) { + nvram_write_byte(current++, buffer[i]); + } + + free_nvram_buffer(buffer); + + /* If the new environment variable content is shorter than the old one, + * we need to erase the rest of the bytes + */ + + if (current<last) { + for(i=current; i<last; i++) { + nvram_write_byte(i, 0); + } + } + + return 0; /* success */ +} + diff --git a/lib/libnvram/libnvram.code b/lib/libnvram/libnvram.code new file mode 100644 index 0000000..f1fd414 --- /dev/null +++ b/lib/libnvram/libnvram.code @@ -0,0 +1,279 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#include <nvram.h> + +#define STRING_INIT(str) \ + char str[255]; \ + char * str##_address; \ + int str##_length; + +#define STRING_FROM_STACK(str) \ + str##_length = TOS.u; POP; \ + str##_address = TOS.a; POP; \ + memcpy(str, str##_address, str##_length); \ + memset(str + str##_length, 0, 255 - str##_length); + +PRIM(nvram_X2d_c_X40) + unsigned int offset = TOS.u; + TOS.u=nvram_read_byte(offset); +MIRP + +PRIM(nvram_X2d_w_X40) + unsigned int offset = TOS.u; + TOS.u=nvram_read_word(offset); +MIRP + +PRIM(nvram_X2d_l_X40) + unsigned int offset = TOS.u; + TOS.u=nvram_read_dword(offset); +MIRP + +PRIM(nvram_X2d_x_X40) + unsigned int offset = TOS.u; + TOS.u=nvram_read_qword(offset); +MIRP + +PRIM(nvram_X2d_c_X21) + nvram_write_byte(TOS.u, NOS.u); + POP; POP; +MIRP + +PRIM(nvram_X2d_w_X21) + nvram_write_word(TOS.u, NOS.u); + POP; POP; +MIRP + +PRIM(nvram_X2d_l_X21) + nvram_write_dword(TOS.u, NOS.u); + POP; POP; +MIRP + +PRIM(nvram_X2d_x_X21) + nvram_write_qword(TOS.u, NOS.u); + POP; POP; +MIRP + +/* get-nvram-partition ( type -- addr len FAILED? ) */ +PRIM(get_X2d_nvram_X2d_partition) + partition_t partition; + unsigned int ptype = TOS.u; + partition = get_partition(ptype, NULL); + if(partition.len && partition.len != -1) { + TOS.u = partition.addr; + PUSH; + TOS.u = partition.len; + PUSH; + TOS.u = 0; // FALSE + } else { + TOS.u = -1; // TRUE + } +MIRP + +/* get-named-nvram-partition ( name.addr name.len -- addr len FAILED? ) */ +PRIM(get_X2d_named_X2d_nvram_X2d_partition) + STRING_INIT(name) + partition_t partition; + + STRING_FROM_STACK(name) + partition = get_partition(-1, name); + + if(partition.len && partition.len != -1) { + PUSH; + TOS.u = partition.addr; + PUSH; + TOS.u = partition.len; + PUSH; + TOS.u = 0; // FALSE + } else { + PUSH; + TOS.u = -1; // TRUE + } +MIRP + + + +/* new-nvram-partition ( type name.addr name.len len -- part.offs part.len FALSE | TRUE) */ +PRIM(new_X2d_nvram_X2d_partition) + int type, len, i, slen; + char name[12], *addr; + partition_t partition; + + len = TOS.u; POP; + slen = TOS.u; POP; + addr = (char *)TOS.u; POP; + type = TOS.u; POP; + + for (i=0; i<12; i++) { + if(slen>i) + name[i]=addr[i]; + else + name[i]=0; + } + + partition=new_nvram_partition(type, name, len); + + if(!partition.len) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = partition.addr; + PUSH; TOS.u = partition.len; + PUSH; TOS.u = 0; // FALSE + } +MIRP + +/* inrease-nvram-partition ( part.offs part.len new-len -- FALSE | TRUE ) */ +PRIM(increase_X2d_nvram_X2d_partition) + int len, ret; + partition_t partition; + + // FIXME + partition.addr = TOS.u; POP; + partition.len = TOS.u; POP; + len = TOS.u; POP; + + ret=increase_nvram_partition_size(partition, len); + + PUSH; + + if(!ret) + TOS.u=-1; // TRUE + else + TOS.u=0; // FALSE + +MIRP + +PRIM(internal_X2d_reset_X2d_nvram) + reset_nvram(); +MIRP + +PRIM(wipe_X2d_nvram) + wipe_nvram(); +MIRP + +PRIM(nvram_X2d_debug) + nvram_debug(); +MIRP + +// ( part.start part.len name.addr name.len -- var.addr var.len TRUE | false ) +PRIM(internal_X2d_get_X2d_env) + STRING_INIT(name) + partition_t part; + char *val; + + STRING_FROM_STACK(name) + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + val=get_env(part, name); + if(val) { + PUSH; TOS.a = val; + PUSH; TOS.u = strlen(val); + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } +MIRP + +// ( part.start part.len name.addr name.len val.addr val.len -- FALSE|TRUE) +PRIM(internal_X2d_add_X2d_env) + STRING_INIT(name) + STRING_INIT(value) + partition_t part; + int ret; + + STRING_FROM_STACK(value) + STRING_FROM_STACK(name) + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + ret=add_env(part, name, value); + if(ret) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } +MIRP + +// ( part.addr part.len name.addr name.len -- FALSE|TRUE) +PRIM(internal_X2d_del_X2d_env) + STRING_INIT(name) + partition_t part; + int ret; + + STRING_FROM_STACK(name); + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + ret=del_env(part, name); + if(ret) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } + +MIRP + +// internal-set-env ( part.addr part.len name.addr name.len val.addr val.len -- FALSE|TRUE) +PRIM(internal_X2d_set_X2d_env) + STRING_INIT(name) + STRING_INIT(value) + partition_t part; + int ret; + + STRING_FROM_STACK(value) + STRING_FROM_STACK(name) + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + ret=set_env(part, name, value); + if(ret) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } +MIRP + +// ( part.addr part.len -- FALSE|TRUE) +PRIM(erase_X2d_nvram_X2d_partition) + partition_t part; + int ret; + + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + ret=clear_nvram_partition(part); + if(ret) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } + +MIRP + +// ( part.addr part.len -- FALSE|TRUE) +PRIM(delete_X2d_nvram_X2d_partition) + partition_t part; + int ret; + + part.len = TOS.u; POP; + part.addr = TOS.u; POP; + + ret=delete_nvram_partition(part); + if(ret) { + PUSH; TOS.u = -1; // TRUE + } else { + PUSH; TOS.u = 0; // FALSE + } + +MIRP + + diff --git a/lib/libnvram/libnvram.in b/lib/libnvram/libnvram.in new file mode 100644 index 0000000..33ab3bc --- /dev/null +++ b/lib/libnvram/libnvram.in @@ -0,0 +1,41 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* NVRAM access primitives */ +cod(nvram-c@) +cod(nvram-c!) +cod(nvram-w@) +cod(nvram-w!) +cod(nvram-l@) +cod(nvram-l!) +cod(nvram-x@) +cod(nvram-x!) + +/* Generic NVRAM helpers */ +cod(internal-reset-nvram) +cod(nvram-debug) +cod(wipe-nvram) + +/* NVRAM Partition Handling */ +cod(get-nvram-partition) +cod(get-named-nvram-partition) +cod(new-nvram-partition) +cod(increase-nvram-partition) +cod(erase-nvram-partition) +cod(delete-nvram-partition) + +/* NVRAM environment access words */ +cod(internal-get-env) +cod(internal-add-env) +cod(internal-del-env) +cod(internal-set-env) + diff --git a/lib/libnvram/nvram.c b/lib/libnvram/nvram.c new file mode 100644 index 0000000..a31bb53 --- /dev/null +++ b/lib/libnvram/nvram.c @@ -0,0 +1,518 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include "cache.h" + +#include "../libc/include/stdio.h" +#include "../libc/include/string.h" +#include "../libc/include/stdlib.h" + +#include "nvram.h" + +#include <stdarg.h> +#include <string.h> +#include <southbridge.h> +#include <nvramlog.h> + +void asm_cout(long Character,long UART,long NVRAM); + +static volatile uint8_t *nvram=(volatile uint8_t *)SB_NVRAM_adr; + +/* This is extremely ugly, but still better than implementing + * another sbrk() around it. + */ +static char nvram_buffer[NVRAM_LENGTH]; +static uint8_t nvram_buffer_locked=0x00; + +/** + * producer for nvram access functions. Since these functions are + * basically all the same except for the used data types, produce + * them via the following macro to keep the code from bloating. + */ + +#define nvram_access(type,size,name) \ + type nvram_read_##name(unsigned int offset) \ + { \ + type *pos; \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return 0; \ + pos = (type *)(nvram+offset); \ + return ci_read_##size(pos); \ + } \ + void nvram_write_##name(unsigned int offset, type data) \ + { \ + type *pos; \ + if (offset > (NVRAM_LENGTH - sizeof(type))) \ + return; \ + pos = (type *)(nvram+offset); \ + ci_write_##size(pos, data); \ + } + +nvram_access(uint8_t, 8, byte) +nvram_access(uint16_t, 16, word) +nvram_access(uint32_t, 32, dword) +nvram_access(uint64_t, 64, qword) + +/** + * This function is a minimal abstraction for our temporary + * buffer. It should have been malloced, but since there is no + * usable malloc, we go this route. + * + * @return pointer to temporary buffer + */ + +char *get_nvram_buffer(int len) +{ + if(len>NVRAM_LENGTH) + return NULL; + + if(nvram_buffer_locked) + return NULL; + + nvram_buffer_locked = 0xff; + + return nvram_buffer; +} + +/** + * @param buffer pointer to the allocated buffer. This + * is unused, but nice in case we ever get a real malloc + */ + +void free_nvram_buffer(char *buffer __attribute__((unused))) +{ + nvram_buffer_locked = 0x00; +} + +/** + * @param fmt format string, like in printf + * @param ... variable number of arguments + */ + +int nvramlog_printf(const char* fmt, ...) +{ + char buff[256]; + int count, i; + va_list ap; + + va_start(ap, fmt); + count = vsprintf(buff, fmt, ap); + va_end(ap); + + for (i=0; i<count; i++) + asm_cout(buff[i], 0, 1); + + return count; +} + +/** + * @param offset start offset of the partition header + */ + +static uint8_t get_partition_type(int offset) +{ + return nvram_read_byte(offset); +} + +/** + * @param offset start offset of the partition header + */ + +static uint8_t get_partition_header_checksum(int offset) +{ + return nvram_read_byte(offset+1); +} + +/** + * @param offset start offset of the partition header + */ + +static uint16_t get_partition_len(int offset) +{ + return nvram_read_word(offset+2); +} + +/** + * @param offset start offset of the partition header + * @return static char array containing the partition name + * + * NOTE: If the partition name needs to be non-temporary, strdup + * and use the copy instead. + */ + +static char * get_partition_name(int offset) +{ + static char name[12]; + int i; + for (i=0; i<12; i++) + name[i]=nvram_read_byte(offset+4+i); + + // DEBUG("name: \"%s\"\n", name); + return name; +} + +static uint8_t calc_partition_header_checksum(int offset) +{ + uint16_t plainsum; + uint8_t checksum; + int i; + + plainsum = nvram_read_byte(offset); + + for (i=2; i<PARTITION_HEADER_SIZE; i++) + plainsum+=nvram_read_byte(offset+i); + + checksum=(plainsum>>8)+(plainsum&0xff); + + return checksum; +} + +static int calc_used_nvram_space(void) +{ + int walk, len; + + for (walk=0; walk<NVRAM_LENGTH;) { + if(get_partition_header_checksum(walk) != + calc_partition_header_checksum(walk)) { + /* If there's no valid entry, bail out */ + break; + } + + len=get_partition_len(walk); + // DEBUG("... part len=%x, %x\n", len, len*16); + + if(!len) { + /* If there's a partition type but no len, bail out. + * Don't bail out if type is 0. This can be used to + * find the offset of the first free byte. + */ + break; + } + + walk += len * 16; + } + DEBUG("used nvram space: %d\n", walk); + + return walk; +} + +/** + * + * @param type partition type. Set this to the partition type you are looking + * for. If there are several partitions with the same type, only + * the first partition with that type will be found. + * Set to -1 to ignore. Set to 0 to find free unpartitioned space. + * + * @param name partition name. Set this to the name of the partition you are + * looking for. If there are several partitions with the same name, + * only the first partition with that name will be found. + * Set to NULL to ignore. + * + * To disambiguate the partitions you should have a unique name if you plan to + * have several partitions of the same type. + * + */ + +partition_t get_partition(unsigned int type, char *name) +{ + partition_t ret={0,-1}; + int walk, len; + + for (walk=0; walk<NVRAM_LENGTH;) { + // DEBUG("get_partition: walk=%x\n", walk); + if(get_partition_header_checksum(walk) != + calc_partition_header_checksum(walk)) { + /* If there's no valid entry, bail out */ + break; + } + + len=get_partition_len(walk); + if(type && !len) { + /* If there's a partition type but no len, bail out. + * Don't bail out if type is 0. This can be used to + * find the offset of the first free byte. + */ + break; + } + + /* Check if either type or name or both do not match. */ + if ( (type!=(unsigned int)-1 && type != get_partition_type(walk)) || + (name && strncmp(get_partition_name(walk), name, 12)) ) { + /* We hit another partition. Continue + * at the end of this partition + */ + walk += len*16; + continue; + } + + ret.addr=walk+PARTITION_HEADER_SIZE; + ret.len=(len*16)-PARTITION_HEADER_SIZE; + break; + } + + return ret; +} + +void erase_nvram(int offset, int len) +{ + int i; + + for (i=offset; i<offset+len; i++) + nvram_write_byte(i, 0); +} + +void wipe_nvram(void) +{ + erase_nvram(0, NVRAM_LENGTH); +} + +/** + * @param partition partition structure pointing to the partition to wipe. + * @param header_only if header_only is != 0 only the partition header is + * nulled out, not the whole partition. + */ + +int wipe_partition(partition_t partition, int header_only) +{ + int pstart, len; + + pstart=partition.addr-PARTITION_HEADER_SIZE; + + len=PARTITION_HEADER_SIZE; + + if(!header_only) + len += partition.len; + + erase_nvram(pstart, len); + + return 0; +} + + +static partition_t create_nvram_partition(int type, const char *name, int len) +{ + partition_t ret = { 0, 0 }; + int offset, plen; + unsigned int i; + + plen = ALIGN(len+PARTITION_HEADER_SIZE, 16); + + DEBUG("Creating partition type=%x, name=%s, len=%d plen=%d\n", + type, name, len, plen); + + offset = calc_used_nvram_space(); + + if (NVRAM_LENGTH-(calc_used_nvram_space())<plen) { + DEBUG("Not enough free space.\n"); + return ret; + } + + DEBUG("Writing header."); + + nvram_write_byte(offset, type); + nvram_write_word(offset+2, plen/16); + + for (i=0; i<strlen(name); i++) + nvram_write_byte(offset+4+i, name[i]); + + nvram_write_byte(offset+1, calc_partition_header_checksum(offset)); + + ret.addr = offset+PARTITION_HEADER_SIZE; + ret.len = len; + + DEBUG("partition created: addr=%lx len=%lx\n", ret.addr, ret.len); + + return ret; +} + +static int create_free_partition(void) +{ + int free_space; + partition_t free_part; + + free_space = NVRAM_LENGTH - calc_used_nvram_space() - PARTITION_HEADER_SIZE; + free_part = create_nvram_partition(0x7f, "free space", free_space); + + return (free_part.addr != 0); +} + +partition_t new_nvram_partition(int type, char *name, int len) +{ + partition_t free_part, new_part = { 0, 0 }; + + /* NOTE: Assume all free space is consumed by the "free space" + * partition. This means a partition can not be increased in the middle + * of reset_nvram, which is obviously not a big loss. + */ + + free_part=get_partition(0x7f, NULL); + if( free_part.len && free_part.len != -1) + wipe_partition(free_part, 1); + + new_part = create_nvram_partition(type, name, len); + + if(new_part.len != len) { + new_part.len = 0; + new_part.addr = 0; + } + + create_free_partition(); + + return new_part; +} + +/** + * @param partition partition structure pointing to the partition to wipe. + */ + +int delete_nvram_partition(partition_t partition) +{ + int i; + partition_t free_part; + + if(!partition.len || partition.len == -1) + return 0; + + for (i=partition.addr+partition.len; i< NVRAM_LENGTH; i++) + nvram_write_byte(i - partition.len - PARTITION_HEADER_SIZE, nvram_read_byte(i)); + + erase_nvram(NVRAM_LENGTH-partition.len-PARTITION_HEADER_SIZE, + partition.len-PARTITION_HEADER_SIZE); + + free_part=get_partition(0x7f, NULL); + wipe_partition(free_part, 0); + create_free_partition(); + + return 1; +} + +int clear_nvram_partition(partition_t part) +{ + if(!part.addr) + return 0; + + erase_nvram(part.addr, part.len); + + return 1; +} + + +int increase_nvram_partition_size(partition_t partition, int newsize) +{ + partition_t free_part; + int free_offset, end_offset, i; + + /* We don't support shrinking partitions (yet) */ + if (newsize < partition.len) { + return 0; + } + + /* NOTE: Assume all free space is consumed by the "free space" + * partition. This means a partition can not be increased in the middle + * of reset_nvram, which is obviously not a big loss. + */ + + free_part=get_partition(0x7f, NULL); + + // FIXME: It could be 16 byte more. Also handle empty "free" partition. + if (free_part.len == -1 || free_part.len < newsize - partition.len ) { + return 0; + } + + free_offset=free_part.addr - PARTITION_HEADER_SIZE; // first unused byte + end_offset=partition.addr + partition.len; // last used byte of partition + 1 + + if(free_offset > end_offset) { + int j, bufferlen; + char *overlap_buffer; + + bufferlen=free_offset - end_offset; + + overlap_buffer=get_nvram_buffer(bufferlen); + if(!overlap_buffer) { + return 0; + } + + for (i=end_offset, j=0; i<free_offset; i++, j++) + overlap_buffer[j]=nvram_read_byte(i); + + /* Only wipe the header. The free space partition is empty per + * definition + */ + + wipe_partition(free_part, 1); + + for (i=partition.addr+newsize, j=0; i<(int)(partition.addr+newsize+bufferlen); i++, j++) + nvram_write_byte(i, overlap_buffer[j]); + + free_nvram_buffer(overlap_buffer); + } else { + /* Only wipe the header. */ + wipe_partition(free_part, 1); + } + + /* Clear the new partition space */ + erase_nvram(partition.addr+partition.len, newsize-partition.len); + + nvram_write_word(partition.addr - 16 + 2, newsize); + + create_free_partition(); + + return 1; +} + +static void init_cpulog_partition(partition_t cpulog) +{ + unsigned int offset=cpulog.addr; + + /* see board-xxx/include/nvramlog.h for information */ + nvram_write_word(offset+0, 0x40); // offset + nvram_write_word(offset+2, 0x00); // flags + nvram_write_dword(offset+4, 0x01); // pointer + +} + +void reset_nvram(void) +{ + partition_t cpulog0, cpulog1; + char header[12]; + + DEBUG("Erasing NVRAM\n"); + erase_nvram(0, NVRAM_LENGTH); + + DEBUG("Creating CPU log partitions\n"); + *(uint32_t *)&(header[0]) = be32_to_cpu(LLFW_LOG_BE0_NAME_PREFIX); + *(uint64_t *)&(header[4]) = be64_to_cpu(LLFW_LOG_BE0_NAME); + cpulog0=create_nvram_partition(LLFW_LOG_BE0_SIGNATURE, header, + (LLFW_LOG_BE0_LENGTH*16)-PARTITION_HEADER_SIZE); + + *(uint32_t *)&(header[0]) = be32_to_cpu(LLFW_LOG_BE1_NAME_PREFIX); + *(uint64_t *)&(header[4]) = be64_to_cpu(LLFW_LOG_BE1_NAME); + cpulog1=create_nvram_partition(LLFW_LOG_BE1_SIGNATURE, header, + (LLFW_LOG_BE1_LENGTH*16)-PARTITION_HEADER_SIZE); + + DEBUG("Initializing CPU log partitions\n"); + init_cpulog_partition(cpulog0); + init_cpulog_partition(cpulog1); + + nvramlog_printf("Creating common NVRAM partition\r\n"); + create_nvram_partition(0x70, "common", 0x01000-PARTITION_HEADER_SIZE); + + create_free_partition(); +} + +void nvram_debug(void) +{ + printf("\nNVRAM_BASE: %lx\n", (unsigned long)SB_NVRAM_adr); + printf("NVRAM_LEN: %x\n", NVRAM_LENGTH); +} + diff --git a/lib/libnvram/nvram.h b/lib/libnvram/nvram.h new file mode 100644 index 0000000..d15b85e --- /dev/null +++ b/lib/libnvram/nvram.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef __NVRAM_H +#define __NVRAM_H 1 + +/* data structures */ + +typedef struct { + unsigned long addr; + long len; +} partition_t; + +/* macros */ + +#define DEBUG(x...) +// #define DEBUG(x...) printf(x); + +#ifndef ALIGN +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) +#endif + +#define NULL ((void *)0) + +#define PARTITION_HEADER_SIZE 16 + +/* FIXME this should be done complete and in a more prominent place */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#ifdef __i386__ +#define __BYTE_ORDER __LITTLE_ENDIAN +#else +#define __BYTE_ORDER __BIG_ENDIAN +#endif +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_be64(x) (x) +#define be64_to_cpu(x) (x) +#define cpu_to_be32(x) (x) +#define be32_to_cpu(x) (x) +#else +#include <byteswap.h> +#define cpu_to_be64(x) bswap_64(x) +#define be64_to_cpu(x) bswap_64(x) +#define cpu_to_be32(x) bswap_32(x) +#define be32_to_cpu(x) bswap_32(x) +#endif + +/* exported functions */ + +#define nvram_access_proto(type,name) \ + type nvram_read_##name(unsigned int offset); \ + void nvram_write_##name(unsigned int offset, type data); + +nvram_access_proto(uint8_t, byte) +nvram_access_proto(uint16_t, word) +nvram_access_proto(uint32_t, dword) +nvram_access_proto(uint64_t, qword) + +/* nvram.c */ + +char *get_nvram_buffer(int len); +void free_nvram_buffer(char *buffer); +int nvramlog_printf(const char* fmt, ...); +partition_t get_partition(unsigned int type, char *name); +void erase_nvram(int offset, int len); +int wipe_partition(partition_t partition, int header_only); +partition_t new_nvram_partition(int type, char *name, int len); +int increase_nvram_partition_size(partition_t partition, int newsize); +int clear_nvram_partition(partition_t part); +int delete_nvram_partition(partition_t part); +void reset_nvram(void); +void wipe_nvram(void); +void nvram_debug(void); + +/* envvar.c */ +char *get_env(partition_t part, char *envvar); +int add_env(partition_t part, char *envvar, char *value); +int del_env(partition_t part, char *envvar); +int set_env(partition_t part, char *envvar, char *value); + +#endif |