diff options
author | Ingo Albrecht <prom@berlin.ccc.de> | 2010-07-15 20:30:44 +0200 |
---|---|---|
committer | Ingo Albrecht <prom@berlin.ccc.de> | 2010-08-17 00:29:08 +0200 |
commit | 0829532cb8c653cbf5d1242e50d548bd296bc81f (patch) | |
tree | 1ebf19b3bbc1d82b95897eaae02829142c6bd733 | |
parent | ff7ce383a16d4eeede22039873f060341630294a (diff) |
firmware: switched from libmini to dietlibc
-rw-r--r-- | src/Makefile | 7 | ||||
-rw-r--r-- | src/target/firmware/Makefile | 5 | ||||
-rw-r--r-- | src/target/firmware/Makefile.inc | 8 | ||||
-rw-r--r-- | src/target/firmware/comm/sercomm_cons.c | 30 | ||||
-rw-r--r-- | src/target/firmware/display/ssd1783.c | 2 | ||||
-rw-r--r-- | src/target/firmware/display/st7558.c | 2 | ||||
-rw-r--r-- | src/target/firmware/include/comm/sercomm_cons.h | 3 | ||||
-rw-r--r-- | src/target/firmware/include/display.h | 4 | ||||
-rw-r--r-- | src/target/firmware/include/stdint.h | 29 | ||||
-rw-r--r-- | src/target/firmware/include/stdio.h | 52 | ||||
-rw-r--r-- | src/target/firmware/include/string.h | 12 | ||||
-rw-r--r-- | src/target/firmware/lib/Makefile | 4 | ||||
-rw-r--r-- | src/target/firmware/lib/copy_template.S | 255 | ||||
-rw-r--r-- | src/target/firmware/lib/ctype.c | 34 | ||||
-rw-r--r-- | src/target/firmware/lib/lib1funcs.S | 334 | ||||
-rw-r--r-- | src/target/firmware/lib/memcpy.S | 59 | ||||
-rw-r--r-- | src/target/firmware/lib/memset.S | 80 | ||||
-rw-r--r-- | src/target/firmware/lib/printf.c | 19 | ||||
-rw-r--r-- | src/target/firmware/lib/string.c | 50 | ||||
-rw-r--r-- | src/target/firmware/lib/system.c | 42 | ||||
-rw-r--r-- | src/target/firmware/lib/vsprintf.c | 847 |
21 files changed, 80 insertions, 1798 deletions
diff --git a/src/Makefile b/src/Makefile index 6d16b7d6..75d3a554 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,7 +12,7 @@ OSMOCORE_CONFIGURE_ENV= LIBOSMOCORE_LIBS=$(TOPDIR)/shared/libosmocore/build-host LIBOSMOCORE_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \ LIBOSMOVTY_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include -all: libosmocore-host libosmocore-target layer23 osmocon firmware +all: libosmocore-host libosmocore-target layer23 osmocon dietlibc firmware libosmocore-host: shared/libosmocore/build-host/src/.libs/libosmocore.la @@ -69,6 +69,9 @@ host/layer23/Makefile: host/layer23/configure host/layer23/layer23: host/layer23/Makefile libosmocore-host make -C host/layer23 +.PHONY: dietlibc +dietlibc: + make -C target/dietlibc .PHONY: firmware firmware: libosmocore-target @@ -80,6 +83,7 @@ clean: make -C shared/libosmocore/build-target $@ make -C host/layer23 $@ make -C host/osmocon $@ + make -C target/dietlibc $@ make -C target/firmware $@ distclean: @@ -87,4 +91,5 @@ distclean: rm -rf shared/libosmocore/build-target make -C host/layer23 $@ make -C host/osmocon $@ + make -C target/dietlibc clean # always distclean make -C target/firmware $@ diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile index b5fcf995..30055398 100644 --- a/src/target/firmware/Makefile +++ b/src/target/firmware/Makefile @@ -1,5 +1,4 @@ - # List of all supported boards (meant to be overridden on command line) BOARDS?=compal_e88 compal_e99 gta0x @@ -50,7 +49,7 @@ e99loader_OBJS=board/compal/header.o e99flash_LDS=board/compal_e99/flash.lds # Global include path -INCLUDES=-Iinclude/ -I../../../include -I../../shared/libosmocore/include +INCLUDES=-Iinclude/ -I../../../include -I../dietlibc/include -I../../shared/libosmocore/include # Various objects that are currently linked into all applications FLASH_OBJS=flash/cfi_flash.o @@ -60,7 +59,7 @@ RF_OBJS=rf/trf6151.o # Objects that go in all applications ANY_APP_OBJS+=$(ABB_OBJS) $(RF_OBJS) $(DISPLAY_OBJS) $(FLASH_OBJS) -ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a +ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm.a ../dietlibc/bin-arm/dietlibc.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a # Libraries are defined in subdirectories diff --git a/src/target/firmware/Makefile.inc b/src/target/firmware/Makefile.inc index 11c63ec8..5f1542d0 100644 --- a/src/target/firmware/Makefile.inc +++ b/src/target/firmware/Makefile.inc @@ -22,7 +22,7 @@ CFLAGS += -g$(DEBUGF) #ASFLAGS=--g$(DEBUGF) $(INCLUDES) -D__ASSEMBLY__ ASFLAGS=$(INCLUDES) -D__ASSEMBLY__ -LDFLAGS = -nostartfiles -nostdlib -nodefaultlibs --gc-sections --cref +LDFLAGS = -static -static-libgcc -nostartfiles -nostdlib -nodefaultlibs -Wl,--gc-sections -Wl,--cref #### GIT VERSION #### @@ -82,9 +82,9 @@ $(1)_$(2)_$(3)_OBJS+=board/$(2)/$(1).$(3).manifest.o $$($(3)_OBJS) # define compilation rule, also generates map file board/$(2)/$(1).$(3).elf board/$(2)/$(1).$(3).map: $$($(1)_$(2)_$(3)_OBJS) $$($(1)_$(2)_$(3)_LIBS) $$($(3)_LDS) - $(CROSS_COMPILE)$(LD) $(LDFLAGS) -T $$($(3)_LDS) -Bstatic \ - -Map board/$(2)/$(1).$(3).map -o board/$(2)/$(1).$(3).elf \ - --start-group $$($(1)_$(2)_$(3)_OBJS) $$($(1)_$(2)_$(3)_LIBS) --end-group + $(CROSS_COMPILE)$(CC) $(LDFLAGS) -T $$($(3)_LDS) \ + -Wl,-Map="board/$(2)/$(1).$(3).map" -o board/$(2)/$(1).$(3).elf \ + -Wl,--start-group -lgcc $$($(1)_$(2)_$(3)_OBJS) $$($(1)_$(2)_$(3)_LIBS) -Wl,--end-group # define size rule board/$(2)/$(1).$(3).size: board/$(2)/$(1).$(3).elf diff --git a/src/target/firmware/comm/sercomm_cons.c b/src/target/firmware/comm/sercomm_cons.c index 5d7842fb..dd833e42 100644 --- a/src/target/firmware/comm/sercomm_cons.c +++ b/src/target/firmware/comm/sercomm_cons.c @@ -50,16 +50,15 @@ static void raw_puts(const char *s) #define raw_putd(x) #endif -int sercomm_puts(const char *s) +int sercomm_write(const char *s, const int len) { unsigned long flags; - const int len = strlen(s); unsigned int bytes_left = len; if (!sercomm_initialized()) { raw_putd("sercomm not initialized: "); raw_puts(s); - return len - 1; + return len; } /* This function is called from any context: Supervisor, IRQ, FIQ, ... @@ -112,27 +111,34 @@ int sercomm_puts(const char *s) bytes_left -= write_num; if (flush) { - sercomm_sendmsg(SC_DLCI_CONSOLE, scons.cur_msg); - /* reset scons.cur_msg pointer to ensure we allocate - * a new one next round */ - scons.cur_msg = NULL; + sercomm_flush(); } } local_irq_restore(flags); - return len - 1; + sercomm_flush(); + + return len; +} + +void sercomm_flush() +{ + if(scons.cur_msg) { + sercomm_sendmsg(SC_DLCI_CONSOLE, scons.cur_msg); + /* reset scons.cur_msg pointer to ensure we allocate + * a new one next round */ + scons.cur_msg = NULL; + } } int sercomm_putchar(int c) { - char s[2]; + char xc = c & 0xFF; int rc; - s[0] = c & 0xff; - s[1] = '\0'; + rc = sercomm_write(&xc, 1); - rc = sercomm_puts(s); if (rc < 0) return rc; diff --git a/src/target/firmware/display/ssd1783.c b/src/target/firmware/display/ssd1783.c index 5696b48f..98f7c357 100644 --- a/src/target/firmware/display/ssd1783.c +++ b/src/target/firmware/display/ssd1783.c @@ -252,6 +252,6 @@ const struct display_driver ssd1783_display = { .unset_attr = &ssd1783_set_attr, .clrscr = &ssd1783_clrscr, .goto_xy = &ssd1783_goto_xy, - .putc = &ssd1783_putc, + .putchr = &ssd1783_putc, .puts = &ssd1783_puts, }; diff --git a/src/target/firmware/display/st7558.c b/src/target/firmware/display/st7558.c index baed9eb0..ca22daa0 100644 --- a/src/target/firmware/display/st7558.c +++ b/src/target/firmware/display/st7558.c @@ -119,5 +119,5 @@ const struct display_driver st7558_display = { .clrscr = &st7558_clrscr, .set_attr = &st7558_set_attr, .unset_attr = &st7558_unset_attr, - .putc = &st7558_putc, + .putchr = &st7558_putc, }; diff --git a/src/target/firmware/include/comm/sercomm_cons.h b/src/target/firmware/include/comm/sercomm_cons.h index 11f66545..179bf77d 100644 --- a/src/target/firmware/include/comm/sercomm_cons.h +++ b/src/target/firmware/include/comm/sercomm_cons.h @@ -4,7 +4,8 @@ /* how large buffers do we allocate? */ #define SERCOMM_CONS_ALLOC 256 -int sercomm_puts(const char *s); +int sercomm_write(const char *s, const int len); int sercomm_putchar(int c); +void sercomm_flush(); #endif /* _SERCOMM_CONS_H */ diff --git a/src/target/firmware/include/display.h b/src/target/firmware/include/display.h index 89d02a57..c2b614e7 100644 --- a/src/target/firmware/include/display.h +++ b/src/target/firmware/include/display.h @@ -13,7 +13,7 @@ struct display_driver { void (*clrscr)(void); void (*goto_xy)(int xpos, int ypos); void (*set_color)(int fgcolor, int bgcolor); - int (*putc)(unsigned char c); + int (*putchr)(unsigned char c); int (*puts)(const char *str); }; @@ -37,7 +37,7 @@ static inline void display_clrscr(void) } static inline int display_putchar(unsigned char c) { - return display->putc(c); + return display->putchr(c); } int display_puts(const char *s); diff --git a/src/target/firmware/include/stdint.h b/src/target/firmware/include/stdint.h deleted file mode 100644 index 96907992..00000000 --- a/src/target/firmware/include/stdint.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef OSMO_STDINT_H -#define OSMO_STDINT_H - -/* some older toolchains (like gnuarm-3.x) don't provide a C99 - compliant stdint.h yet, so we define our own here */ - -/* to make matters worse newer gcc with glibc headers have - a incompatible definition of these types. We will use the - gcc'ism of #include_next to include the compiler's libc - header file and then check if it has defined int8_t and - if not we will use our own typedefs */ - -#include_next <stdint.h> - -#ifndef __int8_t_defined -typedef signed char int8_t; -typedef unsigned char uint8_t; - -typedef signed short int16_t; -typedef unsigned short uint16_t; - -typedef signed int int32_t; -typedef unsigned int uint32_t; - -typedef long long int int64_t; -typedef unsigned long long int uint64_t; -#endif - -#endif diff --git a/src/target/firmware/include/stdio.h b/src/target/firmware/include/stdio.h deleted file mode 100644 index 15ed6688..00000000 --- a/src/target/firmware/include/stdio.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _STDIO_H -#define _STDIO_H - -#ifndef NULL -#define NULL 0 -#endif /* NULL */ - -#include <sys/types.h> - -int printf(const char *format, ...); -int sprintf(char *str, const char *format, ...); -int snprintf(char *str, size_t size, const char *format, ...); - -#include <stdarg.h> - -int vprintf(const char *format, va_list ap); -int vsprintf(char *str, const char *format, va_list ap); -int vsnprintf(char *str, size_t size, const char *format, va_list ap); -int puts(const char *s); - -#if 0 -/* start.S based uart console */ -#include <calypso/uart.h> -#define putchar(c) uart_putchar_wait(1, c) -int puts(const char *s); -#endif - -#if 0 -/* regular UART console */ -#include <console.h> -#define putchar(c) cons_putchar(c) -#define _puts(s) cons_puts(s) -#define ARCH_HAS_CONSOLE -#endif - -#if 1 -/* sercomm based console */ -#include <comm/sercomm_cons.h> -#define putchar(c) sercomm_putchar(c) -#define _puts(s) sercomm_puts(s) -#define ARCH_HAS_CONSOLE -#endif - -struct __file { -}; - -typedef struct __file FILE; - -/* non-standard */ -extern void phex(unsigned int c, unsigned int len); - -#endif /* _STDIO_H */ diff --git a/src/target/firmware/include/string.h b/src/target/firmware/include/string.h deleted file mode 100644 index f060659a..00000000 --- a/src/target/firmware/include/string.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H - -#include <sys/types.h> - -size_t strnlen(const char *s, size_t count); -size_t strlen(const char *s); - -void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, const void *src, size_t n); - -#endif diff --git a/src/target/firmware/lib/Makefile b/src/target/firmware/lib/Makefile index 987857c9..b7cb061e 100644 --- a/src/target/firmware/lib/Makefile +++ b/src/target/firmware/lib/Makefile @@ -1,7 +1,7 @@ LIBRARIES+=mini mini_DIR=lib -mini_SRCS=vsprintf.c string.c ctype.c printf.c console.c ctors.c \ - changebit.S clearbit.S div64.S lib1funcs.S memcpy.S memset.S setbit.S testchangebit.S testclearbit.S testsetbit.S +mini_SRCS=system.c console.c ctors.c \ + changebit.S clearbit.S setbit.S testchangebit.S testclearbit.S testsetbit.S diff --git a/src/target/firmware/lib/copy_template.S b/src/target/firmware/lib/copy_template.S deleted file mode 100644 index cab355c0..00000000 --- a/src/target/firmware/lib/copy_template.S +++ /dev/null @@ -1,255 +0,0 @@ -/* - * linux/arch/arm/lib/copy_template.s - * - * Code template for optimized memory copy functions - * - * Author: Nicolas Pitre - * Created: Sep 28, 2005 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This can be used to enable code to cacheline align the source pointer. - * Experiments on tested architectures (StrongARM and XScale) didn't show - * this a worthwhile thing to do. That might be different in the future. - */ -//#define CALGN(code...) code -#define CALGN(code...) - -/* - * Theory of operation - * ------------------- - * - * This file provides the core code for a forward memory copy used in - * the implementation of memcopy(), copy_to_user() and copy_from_user(). - * - * The including file must define the following accessor macros - * according to the need of the given function: - * - * ldr1w ptr reg abort - * - * This loads one word from 'ptr', stores it in 'reg' and increments - * 'ptr' to the next word. The 'abort' argument is used for fixup tables. - * - * ldr4w ptr reg1 reg2 reg3 reg4 abort - * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort - * - * This loads four or eight words starting from 'ptr', stores them - * in provided registers and increments 'ptr' past those words. - * The'abort' argument is used for fixup tables. - * - * ldr1b ptr reg cond abort - * - * Similar to ldr1w, but it loads a byte and increments 'ptr' one byte. - * It also must apply the condition code if provided, otherwise the - * "al" condition is assumed by default. - * - * str1w ptr reg abort - * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort - * str1b ptr reg cond abort - * - * Same as their ldr* counterparts, but data is stored to 'ptr' location - * rather than being loaded. - * - * enter reg1 reg2 - * - * Preserve the provided registers on the stack plus any additional - * data as needed by the implementation including this code. Called - * upon code entry. - * - * exit reg1 reg2 - * - * Restore registers with the values previously saved with the - * 'preserv' macro. Called upon code termination. - */ - - - enter r4, lr - - subs r2, r2, #4 - blt 8f - ands ip, r0, #3 - PLD( pld [r1, #0] ) - bne 9f - ands ip, r1, #3 - bne 10f - -1: subs r2, r2, #(28) - stmfd sp!, {r5 - r8} - blt 5f - - CALGN( ands ip, r1, #31 ) - CALGN( rsb r3, ip, #32 ) - CALGN( sbcnes r4, r3, r2 ) @ C is always set here - CALGN( bcs 2f ) - CALGN( adr r4, 6f ) - CALGN( subs r2, r2, r3 ) @ C gets set - CALGN( add pc, r4, ip ) - - PLD( pld [r1, #0] ) -2: PLD( subs r2, r2, #96 ) - PLD( pld [r1, #28] ) - PLD( blt 4f ) - PLD( pld [r1, #60] ) - PLD( pld [r1, #92] ) - -3: PLD( pld [r1, #124] ) -4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f - subs r2, r2, #32 - str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f - bge 3b - PLD( cmn r2, #96 ) - PLD( bge 4b ) - -5: ands ip, r2, #28 - rsb ip, ip, #32 - addne pc, pc, ip @ C is always clear here - b 7f -6: nop - ldr1w r1, r3, abort=20f - ldr1w r1, r4, abort=20f - ldr1w r1, r5, abort=20f - ldr1w r1, r6, abort=20f - ldr1w r1, r7, abort=20f - ldr1w r1, r8, abort=20f - ldr1w r1, lr, abort=20f - - add pc, pc, ip - nop - nop - str1w r0, r3, abort=20f - str1w r0, r4, abort=20f - str1w r0, r5, abort=20f - str1w r0, r6, abort=20f - str1w r0, r7, abort=20f - str1w r0, r8, abort=20f - str1w r0, lr, abort=20f - - CALGN( bcs 2b ) - -7: ldmfd sp!, {r5 - r8} - -8: movs r2, r2, lsl #31 - ldr1b r1, r3, ne, abort=21f - ldr1b r1, r4, cs, abort=21f - ldr1b r1, ip, cs, abort=21f - str1b r0, r3, ne, abort=21f - str1b r0, r4, cs, abort=21f - str1b r0, ip, cs, abort=21f - - exit r4, pc - -9: rsb ip, ip, #4 - cmp ip, #2 - ldr1b r1, r3, gt, abort=21f - ldr1b r1, r4, ge, abort=21f - ldr1b r1, lr, abort=21f - str1b r0, r3, gt, abort=21f - str1b r0, r4, ge, abort=21f - subs r2, r2, ip - str1b r0, lr, abort=21f - blt 8b - ands ip, r1, #3 - beq 1b - -10: bic r1, r1, #3 - cmp ip, #2 - ldr1w r1, lr, abort=21f - beq 17f - bgt 18f - - - .macro forward_copy_shift pull push - - subs r2, r2, #28 - blt 14f - - CALGN( ands ip, r1, #31 ) - CALGN( rsb ip, ip, #32 ) - CALGN( sbcnes r4, ip, r2 ) @ C is always set here - CALGN( subcc r2, r2, ip ) - CALGN( bcc 15f ) - -11: stmfd sp!, {r5 - r9} - - PLD( pld [r1, #0] ) - PLD( subs r2, r2, #96 ) - PLD( pld [r1, #28] ) - PLD( blt 13f ) - PLD( pld [r1, #60] ) - PLD( pld [r1, #92] ) - -12: PLD( pld [r1, #124] ) -13: ldr4w r1, r4, r5, r6, r7, abort=19f - mov r3, lr, pull #\pull - subs r2, r2, #32 - ldr4w r1, r8, r9, ip, lr, abort=19f - orr r3, r3, r4, push #\push - mov r4, r4, pull #\pull - orr r4, r4, r5, push #\push - mov r5, r5, pull #\pull - orr r5, r5, r6, push #\push - mov r6, r6, pull #\pull - orr r6, r6, r7, push #\push - mov r7, r7, pull #\pull - orr r7, r7, r8, push #\push - mov r8, r8, pull #\pull - orr r8, r8, r9, push #\push - mov r9, r9, pull #\pull - orr r9, r9, ip, push #\push - mov ip, ip, pull #\pull - orr ip, ip, lr, push #\push - str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f - bge 12b - PLD( cmn r2, #96 ) - PLD( bge 13b ) - - ldmfd sp!, {r5 - r9} - -14: ands ip, r2, #28 - beq 16f - -15: mov r3, lr, pull #\pull - ldr1w r1, lr, abort=21f - subs ip, ip, #4 - orr r3, r3, lr, push #\push - str1w r0, r3, abort=21f - bgt 15b - CALGN( cmp r2, #0 ) - CALGN( bge 11b ) - -16: sub r1, r1, #(\push / 8) - b 8b - - .endm - - - forward_copy_shift pull=8 push=24 - -17: forward_copy_shift pull=16 push=16 - -18: forward_copy_shift pull=24 push=8 - - -/* - * Abort preamble and completion macros. - * If a fixup handler is required then those macros must surround it. - * It is assumed that the fixup code will handle the private part of - * the exit macro. - */ - - .macro copy_abort_preamble -19: ldmfd sp!, {r5 - r9} - b 21f -20: ldmfd sp!, {r5 - r8} -21: - .endm - - .macro copy_abort_end - ldmfd sp!, {r4, pc} - .endm - diff --git a/src/target/firmware/lib/ctype.c b/src/target/firmware/lib/ctype.c deleted file mode 100644 index f3732140..00000000 --- a/src/target/firmware/lib/ctype.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * linux/lib/ctype.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -#include <ctype.h> - -unsigned char _ctype[] = { -_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ -_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ -_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ -_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ -_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ -_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ -_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ -_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ -_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ -_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ -_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ -_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ -_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ -_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ -_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ -_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ -_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ -_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ -_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ -_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ -_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ -_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ - diff --git a/src/target/firmware/lib/lib1funcs.S b/src/target/firmware/lib/lib1funcs.S deleted file mode 100644 index b02a85eb..00000000 --- a/src/target/firmware/lib/lib1funcs.S +++ /dev/null @@ -1,334 +0,0 @@ -/* - * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines - * - * Author: Nicolas Pitre <nico@cam.org> - * - contributed to gcc-3.4 on Sep 30, 2003 - * - adapted for the Linux kernel on Oct 2, 2003 - */ - -/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. - -This file is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -In addition to the permissions in the GNU General Public License, the -Free Software Foundation gives you unlimited permission to link the -compiled version of this file into combinations with other programs, -and to distribute those combinations without any restriction coming -from the use of this file. (The General Public License restrictions -do apply in other respects; for example, they cover modification of -the file, and distribution when not linked into a combine -executable.) - -This file is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -#include <asm/linkage.h> -#include <asm/assembler.h> - - -.macro ARM_DIV_BODY dividend, divisor, result, curbit - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \curbit, \divisor - clz \result, \dividend - sub \result, \curbit, \result - mov \curbit, #1 - mov \divisor, \divisor, lsl \result - mov \curbit, \curbit, lsl \result - mov \result, #0 - -#else - - @ Initially shift the divisor left 3 bits if possible, - @ set curbit accordingly. This allows for curbit to be located - @ at the left end of each 4 bit nibbles in the division loop - @ to save one loop in most cases. - tst \divisor, #0xe0000000 - moveq \divisor, \divisor, lsl #3 - moveq \curbit, #8 - movne \curbit, #1 - - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. -1: cmp \divisor, #0x10000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #4 - movlo \curbit, \curbit, lsl #4 - blo 1b - - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. -1: cmp \divisor, #0x80000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #1 - movlo \curbit, \curbit, lsl #1 - blo 1b - - mov \result, #0 - -#endif - - @ Division loop -1: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - orrhs \result, \result, \curbit - cmp \dividend, \divisor, lsr #1 - subhs \dividend, \dividend, \divisor, lsr #1 - orrhs \result, \result, \curbit, lsr #1 - cmp \dividend, \divisor, lsr #2 - subhs \dividend, \dividend, \divisor, lsr #2 - orrhs \result, \result, \curbit, lsr #2 - cmp \dividend, \divisor, lsr #3 - subhs \dividend, \dividend, \divisor, lsr #3 - orrhs \result, \result, \curbit, lsr #3 - cmp \dividend, #0 @ Early termination? - movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? - movne \divisor, \divisor, lsr #4 - bne 1b - -.endm - - -.macro ARM_DIV2_ORDER divisor, order - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \order, \divisor - rsb \order, \order, #31 - -#else - - cmp \divisor, #(1 << 16) - movhs \divisor, \divisor, lsr #16 - movhs \order, #16 - movlo \order, #0 - - cmp \divisor, #(1 << 8) - movhs \divisor, \divisor, lsr #8 - addhs \order, \order, #8 - - cmp \divisor, #(1 << 4) - movhs \divisor, \divisor, lsr #4 - addhs \order, \order, #4 - - cmp \divisor, #(1 << 2) - addhi \order, \order, #3 - addls \order, \order, \divisor, lsr #1 - -#endif - -.endm - - -.macro ARM_MOD_BODY dividend, divisor, order, spare - -#if __LINUX_ARM_ARCH__ >= 5 - - clz \order, \divisor - clz \spare, \dividend - sub \order, \order, \spare - mov \divisor, \divisor, lsl \order - -#else - - mov \order, #0 - - @ Unless the divisor is very big, shift it up in multiples of - @ four bits, since this is the amount of unwinding in the main - @ division loop. Continue shifting until the divisor is - @ larger than the dividend. -1: cmp \divisor, #0x10000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #4 - addlo \order, \order, #4 - blo 1b - - @ For very big divisors, we must shift it a bit at a time, or - @ we will be in danger of overflowing. -1: cmp \divisor, #0x80000000 - cmplo \divisor, \dividend - movlo \divisor, \divisor, lsl #1 - addlo \order, \order, #1 - blo 1b - -#endif - - @ Perform all needed substractions to keep only the reminder. - @ Do comparisons in batch of 4 first. - subs \order, \order, #3 @ yes, 3 is intended here - blt 2f - -1: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - cmp \dividend, \divisor, lsr #1 - subhs \dividend, \dividend, \divisor, lsr #1 - cmp \dividend, \divisor, lsr #2 - subhs \dividend, \dividend, \divisor, lsr #2 - cmp \dividend, \divisor, lsr #3 - subhs \dividend, \dividend, \divisor, lsr #3 - cmp \dividend, #1 - mov \divisor, \divisor, lsr #4 - subges \order, \order, #4 - bge 1b - - tst \order, #3 - teqne \dividend, #0 - beq 5f - - @ Either 1, 2 or 3 comparison/substractions are left. -2: cmn \order, #2 - blt 4f - beq 3f - cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - mov \divisor, \divisor, lsr #1 -3: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor - mov \divisor, \divisor, lsr #1 -4: cmp \dividend, \divisor - subhs \dividend, \dividend, \divisor -5: -.endm - - -ENTRY(__udivsi3) -ENTRY(__aeabi_uidiv) - - subs r2, r1, #1 - moveq pc, lr - bcc Ldiv0 - cmp r0, r1 - bls 11f - tst r1, r2 - beq 12f - - ARM_DIV_BODY r0, r1, r2, r3 - - mov r0, r2 - mov pc, lr - -11: moveq r0, #1 - movne r0, #0 - mov pc, lr - -12: ARM_DIV2_ORDER r1, r2 - - mov r0, r0, lsr r2 - mov pc, lr - - -ENTRY(__umodsi3) - - subs r2, r1, #1 @ compare divisor with 1 - bcc Ldiv0 - cmpne r0, r1 @ compare dividend with divisor - moveq r0, #0 - tsthi r1, r2 @ see if divisor is power of 2 - andeq r0, r0, r2 - movls pc, lr - - ARM_MOD_BODY r0, r1, r2, r3 - - mov pc, lr - - -ENTRY(__divsi3) -ENTRY(__aeabi_idiv) - - cmp r1, #0 - eor ip, r0, r1 @ save the sign of the result. - beq Ldiv0 - rsbmi r1, r1, #0 @ loops below use unsigned. - subs r2, r1, #1 @ division by 1 or -1 ? - beq 10f - movs r3, r0 - rsbmi r3, r0, #0 @ positive dividend value - cmp r3, r1 - bls 11f - tst r1, r2 @ divisor is power of 2 ? - beq 12f - - ARM_DIV_BODY r3, r1, r0, r2 - - cmp ip, #0 - rsbmi r0, r0, #0 - mov pc, lr - -10: teq ip, r0 @ same sign ? - rsbmi r0, r0, #0 - mov pc, lr - -11: movlo r0, #0 - moveq r0, ip, asr #31 - orreq r0, r0, #1 - mov pc, lr - -12: ARM_DIV2_ORDER r1, r2 - - cmp ip, #0 - mov r0, r3, lsr r2 - rsbmi r0, r0, #0 - mov pc, lr - - -ENTRY(__modsi3) - - cmp r1, #0 - beq Ldiv0 - rsbmi r1, r1, #0 @ loops below use unsigned. - movs ip, r0 @ preserve sign of dividend - rsbmi r0, r0, #0 @ if negative make positive - subs r2, r1, #1 @ compare divisor with 1 - cmpne r0, r1 @ compare dividend with divisor - moveq r0, #0 - tsthi r1, r2 @ see if divisor is power of 2 - andeq r0, r0, r2 - bls 10f - - ARM_MOD_BODY r0, r1, r2, r3 - -10: cmp ip, #0 - rsbmi r0, r0, #0 - mov pc, lr - -ENTRY(__aeabi_uidivmod) - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_uidiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -ENTRY(__aeabi_idivmod) - - stmfd sp!, {r0, r1, ip, lr} - bl __aeabi_idiv - ldmfd sp!, {r1, r2, ip, lr} - mul r3, r0, r2 - sub r1, r1, r3 - mov pc, lr - -Ldiv0: - - str lr, [sp, #-8]! - bl __div0 - mov r0, #0 @ About as wrong as it could be. - ldr pc, [sp], #8 - -ENTRY(__div0) - mov pc, lr diff --git a/src/target/firmware/lib/memcpy.S b/src/target/firmware/lib/memcpy.S deleted file mode 100644 index 2bbd5692..00000000 --- a/src/target/firmware/lib/memcpy.S +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/arch/arm/lib/memcpy.S - * - * Author: Nicolas Pitre - * Created: Sep 28, 2005 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <asm/linkage.h> -#include <asm/assembler.h> - - .macro ldr1w ptr reg abort - ldr \reg, [\ptr], #4 - .endm - - .macro ldr4w ptr reg1 reg2 reg3 reg4 abort - ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} - .endm - - .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort - ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} - .endm - - .macro ldr1b ptr reg cond=al abort - ldr\cond\()b \reg, [\ptr], #1 - .endm - - .macro str1w ptr reg abort - str \reg, [\ptr], #4 - .endm - - .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort - stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} - .endm - - .macro str1b ptr reg cond=al abort - str\cond\()b \reg, [\ptr], #1 - .endm - - .macro enter reg1 reg2 - stmdb sp!, {r0, \reg1, \reg2} - .endm - - .macro exit reg1 reg2 - ldmfd sp!, {r0, \reg1, \reg2} - .endm - - .text - -/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ - -ENTRY(memcpy) - -#include "copy_template.S" - diff --git a/src/target/firmware/lib/memset.S b/src/target/firmware/lib/memset.S deleted file mode 100644 index 04e254a8..00000000 --- a/src/target/firmware/lib/memset.S +++ /dev/null @@ -1,80 +0,0 @@ -/* - * linux/arch/arm/lib/memset.S - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include <asm/linkage.h> -#include <asm/assembler.h> - - .text - .align 5 - .word 0 - -1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 - strltb r1, [r0], #1 @ 1 - strleb r1, [r0], #1 @ 1 - strb r1, [r0], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -/* - * The pointer is now aligned and the length is adjusted. Try doing the - * memzero again. - */ - -ENTRY(memset) - ands r3, r0, #3 @ 1 unaligned? - bne 1b @ 1 -/* - * we know that the pointer in r0 is aligned to a word boundary. - */ - orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - mov r3, r1 - cmp r2, #16 - blt 4f -/* - * We need an extra register for this loop - save the return address and - * use the LR - */ - str lr, [sp, #-4]! - mov ip, r1 - mov lr, r1 - -2: subs r2, r2, #64 - stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - bgt 2b - LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go. -/* - * No need to correct the count; we're only testing bits from now on - */ - tst r2, #32 - stmneia r0!, {r1, r3, ip, lr} - stmneia r0!, {r1, r3, ip, lr} - tst r2, #16 - stmneia r0!, {r1, r3, ip, lr} - ldr lr, [sp], #4 - -4: tst r2, #8 - stmneia r0!, {r1, r3} - tst r2, #4 - strne r1, [r0], #4 -/* - * When we get here, we've got less than 4 bytes to zero. We - * may have an unaligned pointer as well. - */ -5: tst r2, #2 - strneb r1, [r0], #1 - strneb r1, [r0], #1 - tst r2, #1 - strneb r1, [r0], #1 - RETINSTR(mov,pc,lr) diff --git a/src/target/firmware/lib/printf.c b/src/target/firmware/lib/printf.c deleted file mode 100644 index a4fc6876..00000000 --- a/src/target/firmware/lib/printf.c +++ /dev/null @@ -1,19 +0,0 @@ - -#include <stdio.h> -#include <stdarg.h> - -static char printf_buffer[1024]; - -int printf(const char *fmt, ...) -{ - va_list args; - int r; - - va_start(args, fmt); - r = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, args); - va_end(args); - - puts(printf_buffer); - - return r; -} diff --git a/src/target/firmware/lib/string.c b/src/target/firmware/lib/string.c deleted file mode 100644 index 97036528..00000000 --- a/src/target/firmware/lib/string.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * linux/lib/string.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * stupid library routines.. The optimized versions should generally be found - * as inline code in <asm-xx/string.h> - * - * These are buggy as well.. - * - * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de> - * - Added strsep() which will replace strtok() soon (because strsep() is - * reentrant and should be faster). Use only strsep() in new code, please. - * - * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>, - * Matthew Hawkins <matt@mh.dropbear.id.au> - * - Kissed strtok() goodbye - */ - -#include <sys/types.h> -#include <string.h> -#include <ctype.h> - - -#ifndef __HAVE_ARCH_STRNLEN -/** - * strnlen - Find the length of a length-limited string - * @s: The string to be sized - * @count: The maximum number of bytes to search - */ -size_t strnlen(const char *s, size_t count) -{ - const char *sc; - - for (sc = s; count-- && *sc != '\0'; ++sc) - /* nothing */; - return sc - s; -} -#endif - -size_t strlen(const char *s) -{ - const char *sc; - - for (sc = s; *sc != '\0'; ++sc) - /* nothing */; - return sc - s; -} diff --git a/src/target/firmware/lib/system.c b/src/target/firmware/lib/system.c new file mode 100644 index 00000000..48ef5f1e --- /dev/null +++ b/src/target/firmware/lib/system.c @@ -0,0 +1,42 @@ + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <errno.h> +#include <unistd.h> + +#include <comm/sercomm_cons.h> + +int errno; + +int ioctl(int fd, long int request, ...) { + return 0; +} + +ssize_t __libc_write(int fd, const void *buf, size_t count) { + char c; + int i; + + switch(fd) { + default: + case 0: + errno = EBADF; + return -1; + case 1: + case 2: + return sercomm_write(buf, count); + } +} + +ssize_t write(int fd, const void *buf, size_t count) { + return __libc_write(fd, buf, count); +} + +off_t lseek(int fd, off_t offset, int whence) { + return offset; +} + +void _exit(int status) { + puts("Program exit\n"); + while(1) { } +} diff --git a/src/target/firmware/lib/vsprintf.c b/src/target/firmware/lib/vsprintf.c deleted file mode 100644 index 80e8c1ad..00000000 --- a/src/target/firmware/lib/vsprintf.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * linux/lib/vsprintf.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ -/* - * Wirzenius wrote this portably, Torvalds fucked it up :-) - */ - -/* - * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> - * - changed to provide snprintf and vsnprintf functions - * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> - * - scnprintf and vscnprintf - */ - -#include <stdio.h> -#include <limits.h> -#include <stdarg.h> -#include <sys/types.h> -#include <string.h> -#include <ctype.h> - -#include <asm/div64.h> - -/** - * strtoul - convert a string to an unsigned long - * @cp: The start of the string - * @endp: A pointer to the end of the parsed string will be placed here - * @base: The number base to use - */ -unsigned long strtoul(const char *cp,char **endp,unsigned int base) -{ - unsigned long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } else if (base == 16) { - if (cp[0] == '0' && toupper(cp[1]) == 'X') - cp += 2; - } - while (isxdigit(*cp) && - (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - - -/** - * strtol - convert a string to a signed long - * @cp: The start of the string - * @endp: A pointer to the end of the parsed string will be placed here - * @base: The number base to use - */ -long strtol(const char *cp,char **endp,unsigned int base) -{ - if(*cp=='-') - return -strtoul(cp+1,endp,base); - return strtoul(cp,endp,base); -} - - -/** - * strtoull - convert a string to an unsigned long long - * @cp: The start of the string - * @endp: A pointer to the end of the parsed string will be placed here - * @base: The number base to use - */ -unsigned long long strtoull(const char *cp,char **endp,unsigned int base) -{ - unsigned long long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } else if (base == 16) { - if (cp[0] == '0' && toupper(cp[1]) == 'X') - cp += 2; - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - - -/** - * strtoll - convert a string to a signed long long - * @cp: The start of the string - * @endp: A pointer to the end of the parsed string will be placed here - * @base: The number base to use - */ -long long strtoll(const char *cp,char **endp,unsigned int base) -{ - if(*cp=='-') - return -strtoull(cp+1,endp,base); - return strtoull(cp,endp,base); -} - -static int skip_atoi(const char **s) -{ - int i=0; - - while (isdigit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) -{ - char c,sign,tmp[66]; - const char *digits; - static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - int i; - - digits = (type & LARGE) ? large_digits : small_digits; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return NULL; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if ((signed long long) num < 0) { - sign = '-'; - num = - (signed long long) num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) { - while(size-->0) { - if (buf <= end) - *buf = ' '; - ++buf; - } - } - if (sign) { - if (buf <= end) - *buf = sign; - ++buf; - } - if (type & SPECIAL) { - if (base==8) { - if (buf <= end) - *buf = '0'; - ++buf; - } else if (base==16) { - if (buf <= end) - *buf = '0'; - ++buf; - if (buf <= end) - *buf = digits[33]; - ++buf; - } - } - if (!(type & LEFT)) { - while (size-- > 0) { - if (buf <= end) - *buf = c; - ++buf; - } - } - while (i < precision--) { - if (buf <= end) - *buf = '0'; - ++buf; - } - while (i-- > 0) { - if (buf <= end) - *buf = tmp[i]; - ++buf; - } - while (size-- > 0) { - if (buf <= end) - *buf = ' '; - ++buf; - } - return buf; -} - -/** - * vsnprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @size: The size of the buffer, including the trailing null space - * @fmt: The format string to use - * @args: Arguments for the format string - * - * The return value is the number of characters which would - * be generated for the given input, excluding the trailing - * '\0', as per ISO C99. If you want to have the exact - * number of characters written into @buf as return value - * (not including the trailing '\0'), use vscnprintf. If the - * return is greater than or equal to @size, the resulting - * string is truncated. - * - * Call this function if you are already dealing with a va_list. - * You probably want snprintf instead. - */ -int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) -{ - int len; - unsigned long long num; - int i, base; - char *str, *end, c; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - /* 'z' support added 23/7/1999 S.H. */ - /* 'z' changed to 'Z' --davidm 1/25/99 */ - /* 't' added for ptrdiff_t */ - - /* Reject out-of-range values early */ - if ((int) size < 0) { - return 0; - } - - str = buf; - end = buf + size - 1; - - if (end < buf - 1) { - end = ((void *) -1); - size = end - buf + 1; - } - - for (; *fmt ; ++fmt) { - if (*fmt != '%') { - if (str <= end) - *str = *fmt; - ++str; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if (isdigit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (isdigit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || - *fmt =='Z' || *fmt == 'z' || *fmt == 't') { - qualifier = *fmt; - ++fmt; - if (qualifier == 'l' && *fmt == 'l') { - qualifier = 'L'; - ++fmt; - } - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) { - while (--field_width > 0) { - if (str <= end) - *str = ' '; - ++str; - } - } - c = (unsigned char) va_arg(args, int); - if (str <= end) - *str = c; - ++str; - while (--field_width > 0) { - if (str <= end) - *str = ' '; - ++str; - } - continue; - - case 's': - s = va_arg(args, char *); - - len = strnlen(s, precision); - - if (!(flags & LEFT)) { - while (len < field_width--) { - if (str <= end) - *str = ' '; - ++str; - } - } - for (i = 0; i < len; ++i) { - if (str <= end) - *str = *s; - ++str; ++s; - } - while (len < field_width--) { - if (str <= end) - *str = ' '; - ++str; - } - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, end, - (unsigned long) va_arg(args, void *), - 16, field_width, precision, flags); - continue; - - - case 'n': - /* FIXME: - * What does C99 say about the overflow case here? */ - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else if (qualifier == 'Z' || qualifier == 'z') { - size_t * ip = va_arg(args, size_t *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - case '%': - if (str <= end) - *str = '%'; - ++str; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - if (str <= end) - *str = '%'; - ++str; - if (*fmt) { - if (str <= end) - *str = *fmt; - ++str; - } else { - --fmt; - } - continue; - } - if (qualifier == 'L') - num = va_arg(args, long long); - else if (qualifier == 'l') { - num = va_arg(args, unsigned long); - if (flags & SIGN) - num = (signed long) num; - } else if (qualifier == 'Z' || qualifier == 'z') { - num = va_arg(args, size_t); - } else if (qualifier == 't') { - num = va_arg(args, long); - } else if (qualifier == 'h') { - num = (unsigned short) va_arg(args, int); - if (flags & SIGN) - num = (signed short) num; - } else { - num = va_arg(args, unsigned int); - if (flags & SIGN) - num = (signed int) num; - } - str = number(str, end, num, base, - field_width, precision, flags); - } - if (str <= end) - *str = '\0'; - else if (size > 0) - /* don't write out a null byte if the buf size is zero */ - *end = '\0'; - /* the trailing null byte doesn't count towards the total - * ++str; - */ - return str-buf; -} - - -/** - * vscnprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @size: The size of the buffer, including the trailing null space - * @fmt: The format string to use - * @args: Arguments for the format string - * - * The return value is the number of characters which have been written into - * the @buf not including the trailing '\0'. If @size is <= 0 the function - * returns 0. - * - * Call this function if you are already dealing with a va_list. - * You probably want scnprintf instead. - */ -int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) -{ - unsigned int i; - - i=vsnprintf(buf,size,fmt,args); - return (i >= size) ? (size - 1) : i; -} - - -/** - * snprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @size: The size of the buffer, including the trailing null space - * @fmt: The format string to use - * @...: Arguments for the format string - * - * The return value is the number of characters which would be - * generated for the given input, excluding the trailing null, - * as per ISO C99. If the return is greater than or equal to - * @size, the resulting string is truncated. - */ -int snprintf(char * buf, size_t size, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsnprintf(buf,size,fmt,args); - va_end(args); - return i; -} - - -/** - * scnprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @size: The size of the buffer, including the trailing null space - * @fmt: The format string to use - * @...: Arguments for the format string - * - * The return value is the number of characters written into @buf not including - * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is - * greater than or equal to @size, the resulting string is truncated. - */ - -int scnprintf(char * buf, size_t size, const char *fmt, ...) -{ - va_list args; - unsigned int i; - - va_start(args, fmt); - i = vsnprintf(buf, size, fmt, args); - va_end(args); - return (i >= size) ? (size - 1) : i; -} - -/** - * vsprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @fmt: The format string to use - * @args: Arguments for the format string - * - * The function returns the number of characters written - * into @buf. Use vsnprintf or vscnprintf in order to avoid - * buffer overflows. - * - * Call this function if you are already dealing with a va_list. - * You probably want sprintf instead. - */ -int vsprintf(char *buf, const char *fmt, va_list args) -{ - return vsnprintf(buf, INT_MAX, fmt, args); -} - - -/** - * sprintf - Format a string and place it in a buffer - * @buf: The buffer to place the result into - * @fmt: The format string to use - * @...: Arguments for the format string - * - * The function returns the number of characters written - * into @buf. Use snprintf or scnprintf in order to avoid - * buffer overflows. - */ -int sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsnprintf(buf, INT_MAX, fmt, args); - va_end(args); - return i; -} - - -/** - * vsscanf - Unformat a buffer into a list of arguments - * @buf: input buffer - * @fmt: format of buffer - * @args: arguments - */ -int vsscanf(const char * buf, const char * fmt, va_list args) -{ - const char *str = buf; - char *next; - char digit; - int num = 0; - int qualifier; - int base; - int field_width; - int is_sign = 0; - - while(*fmt && *str) { - /* skip any white space in format */ - /* white space in format matchs any amount of - * white space, including none, in the input. - */ - if (isspace(*fmt)) { - while (isspace(*fmt)) - ++fmt; - while (isspace(*str)) - ++str; - } - - /* anything that is not a conversion must match exactly */ - if (*fmt != '%' && *fmt) { - if (*fmt++ != *str++) - break; - continue; - } - - if (!*fmt) - break; - ++fmt; - - /* skip this conversion. - * advance both strings to next white space - */ - if (*fmt == '*') { - while (!isspace(*fmt) && *fmt) - fmt++; - while (!isspace(*str) && *str) - str++; - continue; - } - - /* get field width */ - field_width = -1; - if (isdigit(*fmt)) - field_width = skip_atoi(&fmt); - - /* get conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || - *fmt == 'Z' || *fmt == 'z') { - qualifier = *fmt++; - if (qualifier == *fmt) { - if (qualifier == 'h') { - qualifier = 'H'; - fmt++; - } else if (qualifier == 'l') { - qualifier = 'L'; - fmt++; - } - } - } - base = 10; - is_sign = 0; - - if (!*fmt || !*str) - break; - - switch(*fmt++) { - case 'c': - { - char *s = (char *) va_arg(args,char*); - if (field_width == -1) - field_width = 1; - do { - *s++ = *str++; - } while (--field_width > 0 && *str); - num++; - } - continue; - case 's': - { - char *s = (char *) va_arg(args, char *); - if(field_width == -1) - field_width = INT_MAX; - /* first, skip leading white space in buffer */ - while (isspace(*str)) - str++; - - /* now copy until next white space */ - while (*str && !isspace(*str) && field_width--) { - *s++ = *str++; - } - *s = '\0'; - num++; - } - continue; - case 'n': - /* return number of characters read so far */ - { - int *i = (int *)va_arg(args,int*); - *i = str - buf; - } - continue; - case 'o': - base = 8; - break; - case 'x': - case 'X': - base = 16; - break; - case 'i': - base = 0; - case 'd': - is_sign = 1; - case 'u': - break; - case '%': - /* looking for '%' in str */ - if (*str++ != '%') - return num; - continue; - default: - /* invalid format; stop here */ - return num; - } - - /* have some sort of integer conversion. - * first, skip white space in buffer. - */ - while (isspace(*str)) - str++; - - digit = *str; - if (is_sign && digit == '-') - digit = *(str + 1); - - if (!digit - || (base == 16 && !isxdigit(digit)) - || (base == 10 && !isdigit(digit)) - || (base == 8 && (!isdigit(digit) || digit > '7')) - || (base == 0 && !isdigit(digit))) - break; - - switch(qualifier) { - case 'H': /* that's 'hh' in format */ - if (is_sign) { - signed char *s = (signed char *) va_arg(args,signed char *); - *s = (signed char) strtol(str,&next,base); - } else { - unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); - *s = (unsigned char) strtoul(str, &next, base); - } - break; - case 'h': - if (is_sign) { - short *s = (short *) va_arg(args,short *); - *s = (short) strtol(str,&next,base); - } else { - unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); - *s = (unsigned short) strtoul(str, &next, base); - } - break; - case 'l': - if (is_sign) { - long *l = (long *) va_arg(args,long *); - *l = strtol(str,&next,base); - } else { - unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); - *l = strtoul(str,&next,base); - } - break; - case 'L': - if (is_sign) { - long long *l = (long long*) va_arg(args,long long *); - *l = strtoll(str,&next,base); - } else { - unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); - *l = strtoull(str,&next,base); - } - break; - case 'Z': - case 'z': - { - size_t *s = (size_t*) va_arg(args,size_t*); - *s = (size_t) strtoul(str,&next,base); - } - break; - default: - if (is_sign) { - int *i = (int *) va_arg(args, int*); - *i = (int) strtol(str,&next,base); - } else { - unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); - *i = (unsigned int) strtoul(str,&next,base); - } - break; - } - num++; - - if (!next) - break; - str = next; - } - return num; -} - - -/** - * sscanf - Unformat a buffer into a list of arguments - * @buf: input buffer - * @fmt: formatting of buffer - * @...: resulting arguments - */ -int sscanf(const char * buf, const char * fmt, ...) -{ - va_list args; - int i; - - va_start(args,fmt); - i = vsscanf(buf,fmt,args); - va_end(args); - return i; -} - -/* generic puts() implementation independent of who provides putchar() */ -int puts(const char *s) -{ -#ifdef ARCH_HAS_CONSOLE - return _puts(s); -#else - while (1) { - char c = *s++; - if (c == 0) - return; - putchar(c); - } - return 0; -#endif -} |