diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig index be01f3d..7e17f9d 100644 --- a/arch/arm/cpu/Kconfig +++ b/arch/arm/cpu/Kconfig @@ -69,3 +69,11 @@ Note that your board must be properly built and your board port must properly enable any big-endian related features of your chipset/board/processor. + +config ARCH_HAS_L2X0 + bool + +config CACHE_L2X0 + bool "Enable L2x0 PrimeCell" + depends on ARCH_HAS_L2X0 + diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 7f03436..ae1f762 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -16,3 +16,5 @@ obj-$(CONFIG_CPU_32v5) += cache-armv5.o obj-$(CONFIG_CPU_32v6) += cache-armv6.o obj-$(CONFIG_CPU_32v7) += cache-armv7.o +obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o + diff --git a/arch/arm/cpu/cache-armv4.S b/arch/arm/cpu/cache-armv4.S index a0ab256..a79cc27 100644 --- a/arch/arm/cpu/cache-armv4.S +++ b/arch/arm/cpu/cache-armv4.S @@ -86,7 +86,7 @@ * * (same as v4wb) */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #CACHE_DLINESIZE - 1 bic r0, r0, #CACHE_DLINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -109,7 +109,7 @@ * * (same as v4wb) */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHE_DLINESIZE @@ -126,7 +126,7 @@ * - start - virtual start address * - end - virtual end address */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry add r0, r0, #CACHE_DLINESIZE diff --git a/arch/arm/cpu/cache-armv5.S b/arch/arm/cpu/cache-armv5.S index 3618c44..f52bcb7 100644 --- a/arch/arm/cpu/cache-armv5.S +++ b/arch/arm/cpu/cache-armv5.S @@ -62,7 +62,7 @@ * * (same as v4wb) */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #CACHE_DLINESIZE - 1 bic r0, r0, #CACHE_DLINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -85,7 +85,7 @@ * * (same as v4wb) */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHE_DLINESIZE @@ -102,7 +102,7 @@ * - start - virtual start address * - end - virtual end address */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry add r0, r0, #CACHE_DLINESIZE diff --git a/arch/arm/cpu/cache-armv6.S b/arch/arm/cpu/cache-armv6.S index ceabd52..e3498bb 100644 --- a/arch/arm/cpu/cache-armv6.S +++ b/arch/arm/cpu/cache-armv6.S @@ -61,7 +61,7 @@ * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #D_CACHE_LINE_SIZE - 1 bic r0, r0, #D_CACHE_LINE_SIZE - 1 #ifdef HARVARD_CACHE @@ -94,7 +94,7 @@ * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: #ifdef HARVARD_CACHE @@ -114,7 +114,7 @@ * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: #ifdef HARVARD_CACHE diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S index b370acd..9afa20d 100644 --- a/arch/arm/cpu/cache-armv7.S +++ b/arch/arm/cpu/cache-armv7.S @@ -128,7 +128,7 @@ * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) dcache_line_size r2, r3 sub r3, r2, #1 tst r0, r3 @@ -145,14 +145,14 @@ blo 1b dsb mov pc, lr -ENDPROC(dma_inv_range) +ENDPROC(__dma_inv_range) /* * v7_dma_clean_range(start,end) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 @@ -163,14 +163,14 @@ blo 1b dsb mov pc, lr -ENDPROC(dma_clean_range) +ENDPROC(__dma_clean_range) /* * v7_dma_flush_range(start,end) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 @@ -181,5 +181,5 @@ blo 1b dsb mov pc, lr -ENDPROC(dma_flush_range) +ENDPROC(__dma_flush_range) diff --git a/arch/arm/cpu/cache-l2x0.c b/arch/arm/cpu/cache-l2x0.c new file mode 100644 index 0000000..61569d2 --- /dev/null +++ b/arch/arm/cpu/cache-l2x0.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#define CACHE_LINE_SIZE 32 + +static void __iomem *l2x0_base; + +#define L2X0_CACHE_ID 0x000 +#define L2X0_CACHE_TYPE 0x004 +#define L2X0_CTRL 0x100 +#define L2X0_AUX_CTRL 0x104 +#define L2X0_TAG_LATENCY_CTRL 0x108 +#define L2X0_DATA_LATENCY_CTRL 0x10C +#define L2X0_EVENT_CNT_CTRL 0x200 +#define L2X0_EVENT_CNT1_CFG 0x204 +#define L2X0_EVENT_CNT0_CFG 0x208 +#define L2X0_EVENT_CNT1_VAL 0x20C +#define L2X0_EVENT_CNT0_VAL 0x210 +#define L2X0_INTR_MASK 0x214 +#define L2X0_MASKED_INTR_STAT 0x218 +#define L2X0_RAW_INTR_STAT 0x21C +#define L2X0_INTR_CLEAR 0x220 +#define L2X0_CACHE_SYNC 0x730 +#define L2X0_INV_LINE_PA 0x770 +#define L2X0_INV_WAY 0x77C +#define L2X0_CLEAN_LINE_PA 0x7B0 +#define L2X0_CLEAN_LINE_IDX 0x7B8 +#define L2X0_CLEAN_WAY 0x7BC +#define L2X0_CLEAN_INV_LINE_PA 0x7F0 +#define L2X0_CLEAN_INV_LINE_IDX 0x7F8 +#define L2X0_CLEAN_INV_WAY 0x7FC +#define L2X0_LOCKDOWN_WAY_D 0x900 +#define L2X0_LOCKDOWN_WAY_I 0x904 +#define L2X0_TEST_OPERATION 0xF00 +#define L2X0_LINE_DATA 0xF10 +#define L2X0_LINE_TAG 0xF30 +#define L2X0_DEBUG_CTRL 0xF40 + +static inline void cache_wait(void __iomem *reg, unsigned long mask) +{ + /* wait for the operation to complete */ + while (readl(reg) & mask) + ; +} + +static inline void cache_sync(void) +{ + void __iomem *base = l2x0_base; + writel(0, base + L2X0_CACHE_SYNC); + cache_wait(base + L2X0_CACHE_SYNC, 1); +} + +static inline void l2x0_clean_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + writel(addr, base + L2X0_CLEAN_LINE_PA); +} + +static inline void l2x0_inv_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + cache_wait(base + L2X0_INV_LINE_PA, 1); + writel(addr, base + L2X0_INV_LINE_PA); +} + +static inline void l2x0_flush_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + + /* Clean by PA followed by Invalidate by PA */ + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + writel(addr, base + L2X0_CLEAN_LINE_PA); + cache_wait(base + L2X0_INV_LINE_PA, 1); + writel(addr, base + L2X0_INV_LINE_PA); +} + +static inline void l2x0_inv_all(void) +{ + /* invalidate all ways */ + writel(0xff, l2x0_base + L2X0_INV_WAY); + cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); + cache_sync(); +} + +static void l2x0_inv_range(unsigned long start, unsigned long end) +{ + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + l2x0_flush_line(start); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + l2x0_flush_line(end); + } + + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_inv_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(l2x0_base + L2X0_INV_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_clean_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE - 1); + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_clean_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + cache_sync(); +} + +void l2x0_flush_range(unsigned long start, unsigned long end) +{ + start &= ~(CACHE_LINE_SIZE - 1); + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_flush_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(l2x0_base + L2X0_CLEAN_INV_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_disable(void) +{ + writel(0xff, l2x0_base + L2X0_CLEAN_INV_WAY); + while (readl(l2x0_base + L2X0_CLEAN_INV_WAY)); + writel(0, l2x0_base + L2X0_CTRL); +} + +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) +{ + __u32 aux; + + l2x0_base = base; + + /* + * Check if l2x0 controller is already enabled. + * If you are booting from non-secure mode + * accessing the below registers will fault. + */ + if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { + + /* l2x0 controller is disabled */ + + aux = readl(l2x0_base + L2X0_AUX_CTRL); + aux &= aux_mask; + aux |= aux_val; + writel(aux, l2x0_base + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + /* enable L2X0 */ + writel(1, l2x0_base + L2X0_CTRL); + } + + outer_cache.inv_range = l2x0_inv_range; + outer_cache.clean_range = l2x0_clean_range; + outer_cache.flush_range = l2x0_flush_range; + outer_cache.disable = l2x0_disable; +} + diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c index 1b8fc97..a5e2fe2 100644 --- a/arch/arm/cpu/cpu.c +++ b/arch/arm/cpu/cpu.c @@ -132,18 +132,16 @@ } /** - * Prepare a "clean" CPU for Linux to run + * Disable MMU and D-cache, flush caches * @return 0 (always) * - * This function is called by the generic barebox part just before we call - * Linux. It prepares the processor for Linux. + * This function is called by shutdown_barebox to get a clean + * memory/cache state. */ -int cleanup_before_linux (void) +void arch_shutdown(void) { int i; - shutdown_barebox(); - #ifdef CONFIG_MMU mmu_disable(); #endif @@ -151,8 +149,8 @@ /* flush I/D-cache */ i = 0; asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); - return 0; } + /** * @page arm_boot_preparation Linux Preparation on ARM * diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 4c4e196..66ee987 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -60,12 +60,17 @@ ); } +struct outer_cache_fns outer_cache; + /* * Clean and invalide caches, disable MMU */ void mmu_disable(void) { + if (outer_cache.disable) + outer_cache.disable(); + asm volatile ( "bl __mmu_cache_flush;" "bl __mmu_cache_off;" @@ -98,7 +103,7 @@ if (mem) return mem + dma_coherent_offset; - return NULL; + return NULL; } unsigned long virt_to_phys(void *virt) @@ -116,3 +121,24 @@ free(mem - dma_coherent_offset); } +void dma_clean_range(unsigned long start, unsigned long end) +{ + if (outer_cache.clean_range) + outer_cache.clean_range(start, end); + __dma_clean_range(start, end); +} + +void dma_flush_range(unsigned long start, unsigned long end) +{ + if (outer_cache.flush_range) + outer_cache.flush_range(start, end); + __dma_flush_range(start, end); +} + +void dma_inv_range(unsigned long start, unsigned long end) +{ + if (outer_cache.inv_range) + outer_cache.inv_range(start, end); + __dma_inv_range(start, end); +} + diff --git a/arch/arm/include/asm/common.h b/arch/arm/include/asm/common.h index da84fa5..9afcff7 100644 --- a/arch/arm/include/asm/common.h +++ b/arch/arm/include/asm/common.h @@ -1 +1 @@ -/* nothing */ +#define ARCH_SHUTDOWN diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index 0dd3fa8..fdd23b5 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -19,9 +19,9 @@ void *dma_alloc_coherent(size_t size); void dma_free_coherent(void *mem); -void dma_clean_range(const void *, const void *); -void dma_flush_range(const void *, const void *); -void dma_inv_range(const void *, const void *); +void dma_clean_range(unsigned long, unsigned long); +void dma_flush_range(unsigned long, unsigned long); +void dma_inv_range(unsigned long, unsigned long); unsigned long virt_to_phys(void *virt); void *phys_to_virt(unsigned long phys); @@ -46,19 +46,34 @@ return (unsigned long)mem; } -static inline void dma_clean_range(const void *s, const void *e) +static inline void dma_clean_range(unsigned long s, unsigned long e) { } -static inline void dma_flush_range(const void *s, const void *e) +static inline void dma_flush_range(unsigned long s, unsigned long e) { } -static inline void dma_inv_range(const void *s, const void *e) +static inline void dma_inv_range(unsigned long s, unsigned long e) { } #endif +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); + +struct outer_cache_fns { + void (*inv_range)(unsigned long, unsigned long); + void (*clean_range)(unsigned long, unsigned long); + void (*flush_range)(unsigned long, unsigned long); + void (*disable)(void); +}; + +extern struct outer_cache_fns outer_cache; + +void __dma_clean_range(unsigned long, unsigned long); +void __dma_flush_range(unsigned long, unsigned long); +void __dma_inv_range(unsigned long, unsigned long); + #endif /* __ASM_MMU_H */ diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h new file mode 100644 index 0000000..34f7838 --- /dev/null +++ b/arch/arm/include/asm/unaligned.h @@ -0,0 +1,19 @@ +#ifndef _ASM_ARM_UNALIGNED_H +#define _ASM_ARM_UNALIGNED_H + +#include +#include +#include + +/* + * Select endianness + */ +#ifndef __ARMEB__ +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le +#else +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be +#endif + +#endif /* _ASM_ARM_UNALIGNED_H */ diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index 2415c29..019c030 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -192,7 +192,7 @@ /* we assume that the kernel is in place */ printf("\nStarting kernel ...\n\n"); - cleanup_before_linux(); + shutdown_barebox(); theKernel (0, armlinux_architecture, armlinux_bootparams); return -1; @@ -283,7 +283,7 @@ #endif setup_end_tag(); - cleanup_before_linux(); + shutdown_barebox(); theKernel(0, armlinux_architecture, armlinux_bootparams); return 0; @@ -325,7 +325,7 @@ setup_commandline_tag(commandline); setup_end_tag(); - cleanup_before_linux(); + shutdown_barebox(); theKernel(0, armlinux_architecture, armlinux_bootparams); return 1; diff --git a/arch/arm/mach-at91/clocksource.c b/arch/arm/mach-at91/clocksource.c index 564b560..84df1a1 100644 --- a/arch/arm/mach-at91/clocksource.c +++ b/arch/arm/mach-at91/clocksource.c @@ -73,10 +73,13 @@ /* * Reset the cpu through the reset controller */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); + + /* Not reached */ + while (1); } EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c index 2a7d90e..3aa8e14 100644 --- a/arch/arm/mach-ep93xx/clocksource.c +++ b/arch/arm/mach-ep93xx/clocksource.c @@ -72,7 +72,7 @@ /* * Reset the cpu */ -void reset_cpu(ulong ignored) +void __noreturn reset_cpu(unsigned long ignored) { struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; uint32_t value; diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index eeb392a..10561f0 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -228,7 +228,8 @@ bool "phyCORE-i.MX35" select HAS_CFI select HAVE_MMU - select MACH_HAS_LOWLEVEL_INIT + select MACH_HAS_LOWLEVEL_INIT + select ARCH_HAS_L2X0 help Say Y here if you are using Phytec's phyCORE-i.MX35 (pcm043) equipped with a Freescale i.MX35 Processor diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 09d4318..4b400a0 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -95,7 +95,7 @@ /* * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { /* Disable watchdog and set Time-Out field to 0 */ WCR = 0x0000; diff --git a/arch/arm/mach-imx/include/mach/imx21-regs.h b/arch/arm/mach-imx/include/mach/imx21-regs.h index 08520e9..3d21749 100644 --- a/arch/arm/mach-imx/include/mach/imx21-regs.h +++ b/arch/arm/mach-imx/include/mach/imx21-regs.h @@ -107,11 +107,42 @@ #define MPCTL1_BRMO (1 << 6) #define MPCTL1_LF (1 << 15) -#define PCCR0_NFC_EN (1 << 19) -#define PCCR1_GPT1_EN (1 << 25) +#define PCCR0_PERCLK3_EN (1 << 18) +#define PCCR0_NFC_EN (1 << 19) +#define PCCR0_HCLK_LCDC_EN (1 << 26) + +#define PCCR1_GPT1_EN (1 << 25) #define CCSR_32K_SR (1 << 15) +#define PA5_PF_LSCLK (GPIO_PORTA | GPIO_PF | GPIO_OUT | 5) +#define PA6_PF_LD0 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 6) +#define PA7_PF_LD1 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 7) +#define PA8_PF_LD2 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 8) +#define PA9_PF_LD3 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 9) +#define PA10_PF_LD4 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 10) +#define PA11_PF_LD5 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 11) +#define PA12_PF_LD6 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 12) +#define PA13_PF_LD7 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 13) +#define PA14_PF_LD8 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 14) +#define PA15_PF_LD9 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15) +#define PA16_PF_LD10 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16) +#define PA17_PF_LD11 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 17) +#define PA18_PF_LD12 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 18) +#define PA19_PF_LD13 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 19) +#define PA20_PF_LD14 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 20) +#define PA21_PF_LD15 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 21) +#define PA22_PF_LD16 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 22) +#define PA23_PF_LD17 (GPIO_PORTA | GPIO_PF | GPIO_OUT | 23) +#define PA24_PF_REV (GPIO_PORTA | GPIO_PF | GPIO_OUT | 24) +#define PA25_PF_CLS (GPIO_PORTA | GPIO_PF | GPIO_OUT | 25) +#define PA26_PF_PS (GPIO_PORTA | GPIO_PF | GPIO_OUT | 26) +#define PA27_PF_SPL_SPR (GPIO_PORTA | GPIO_PF | GPIO_OUT | 27) +#define PA28_PF_HSYNC (GPIO_PORTA | GPIO_PF | GPIO_OUT | 28) +#define PA29_PF_VSYNC (GPIO_PORTA | GPIO_PF | GPIO_OUT | 29) +#define PA30_PF_CONTRAST (GPIO_PORTA | GPIO_PF | GPIO_OUT | 30) +#define PA31_PF_OE_ACD (GPIO_PORTA | GPIO_PF | GPIO_OUT | 31) + #define PE12_PF_UART1_TXD (GPIO_PORTE | GPIO_OUT | GPIO_PF | 12) #define PE13_PF_UART1_RXD (GPIO_PORTE | GPIO_IN | GPIO_PF | 13) #define PE14_PF_UART1_CTS (GPIO_PORTE | GPIO_OUT | GPIO_PF | 14) diff --git a/arch/arm/mach-imx/include/mach/iomux-mx25.h b/arch/arm/mach-imx/include/mach/iomux-mx25.h index 020b7f2..379bfcb 100644 --- a/arch/arm/mach-imx/include/mach/iomux-mx25.h +++ b/arch/arm/mach-imx/include/mach/iomux-mx25.h @@ -400,12 +400,12 @@ #define MX25_PAD_GPIO_D__SS2 IOMUX_PAD(0x3fc, 0x200, 7, 0x4c4, 1, NO_PAD_CTRL) #define MX25_PAD_GPIO_E__GPIO4 IOMUX_PAD(0x400, 0x204, 0, 0, 0, NO_PAD_CTRL) #define MX25_PAD_GPIO_E__SCL IOMUX_PAD(0x400, 0x204, 1, 0x524, 2, NO_PAD_CTRL) -#define MX25_PAD_GPIO_E__LCDC_LD16 IOMUX_PAD(0x400, 0x204, 2, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_E__LCDC_LD16 IOMUX_PAD(0x400, 0x204, 2, 0, 0, (PKE | PUE | PUS_100K_UP)) #define MX25_PAD_GPIO_E__AUD7_TXD IOMUX_PAD(0x400, 0x204, 4, 0, 0, NO_PAD_CTRL) #define MX25_PAD_GPIO_E__RXD_MUX IOMUX_PAD(0x400, 0x204, 6, 0x570, 2, NO_PAD_CTRL) #define MX25_PAD_GPIO_E__CTI_TRIG_IN0_6 IOMUX_PAD(0x400, 0x204, 7, 0, 0, NO_PAD_CTRL) #define MX25_PAD_GPIO_F__GPIO5 IOMUX_PAD(0x404, 0x208, 0, 0, 0, NO_PAD_CTRL) -#define MX25_PAD_GPIO_F__LCDC_LD17 IOMUX_PAD(0x404, 0x208, 2, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_F__LCDC_LD17 IOMUX_PAD(0x404, 0x208, 2, 0, 0, (PKE | PUE | PUS_100K_UP)) #define MX25_PAD_GPIO_F__EPITO IOMUX_PAD(0x404, 0x208, 3, 0, 0, NO_PAD_CTRL) #define MX25_PAD_GPIO_F__AUD7_TXC IOMUX_PAD(0x404, 0x208, 4, 0, 0, NO_PAD_CTRL) #define MX25_PAD_GPIO_F__TXD_MUX IOMUX_PAD(0x404, 0x208, 6, 0, 0, NO_PAD_CTRL) diff --git a/arch/arm/mach-imx/speed-imx21.c b/arch/arm/mach-imx/speed-imx21.c index c68a367..9ae8026 100644 --- a/arch/arm/mach-imx/speed-imx21.c +++ b/arch/arm/mach-imx/speed-imx21.c @@ -135,6 +135,11 @@ return imx_decode_perclk((PCDR1 & 0x3f) + 1); } +ulong imx_get_lcdclk(void) +{ + return imx_get_perclk3(); +} + void imx_dump_clocks(void) { uint32_t cid = CID; diff --git a/arch/arm/mach-imx/speed-imx25.c b/arch/arm/mach-imx/speed-imx25.c index b33674f..a615017 100644 --- a/arch/arm/mach-imx/speed-imx25.c +++ b/arch/arm/mach-imx/speed-imx25.c @@ -72,6 +72,11 @@ return imx_get_ipgclk(); } +unsigned long imx_get_lcdclk(void) +{ + return imx_get_perclk(7); +} + int imx_dump_clocks(void) { printf("mpll: %10d Hz\n", imx_get_mpllclk()); @@ -81,6 +86,7 @@ printf("uart: %10d Hz\n", imx_get_perclk(15)); printf("gpt: %10d Hz\n", imx_get_ipgclk()); printf("nand: %10d Hz\n", imx_get_perclk(8)); + printf("lcd: %10d Hz\n", imx_get_perclk(7)); return 0; } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index 69cf196..de1e1b0 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -137,9 +137,12 @@ return COMMAND_ERROR_USAGE; } -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { SYSTEM_REG(SYSTEM_RES_CR) = 0x01000008; + + /* Not reached */ + while (1); } diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c index 05c5c19..9893145 100644 --- a/arch/arm/mach-omap/omap3_generic.c +++ b/arch/arm/mach-omap/omap3_generic.c @@ -56,7 +56,7 @@ * * @return void */ -void reset_cpu(ulong addr) +void __noreturn reset_cpu(ulong addr) { /* FIXME: Enable WDT and cause reset */ hang(); diff --git a/arch/arm/mach-s3c24xx/generic.c b/arch/arm/mach-s3c24xx/generic.c index 2de03ca..372904f 100644 --- a/arch/arm/mach-s3c24xx/generic.c +++ b/arch/arm/mach-s3c24xx/generic.c @@ -221,7 +221,7 @@ } core_initcall(clocksource_init); -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { /* Disable watchdog */ writew(0x0000, WTCON); diff --git a/arch/blackfin/include/asm/common.h b/arch/blackfin/include/asm/common.h index 2ab1954..fa58e37 100644 --- a/arch/blackfin/include/asm/common.h +++ b/arch/blackfin/include/asm/common.h @@ -2,4 +2,4 @@ /* We have to disable instruction cache before * executing an external program */ -#define ARCH_HAS_EXECUTE +#define ARCH_SHUTDOWN diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 019995b..581947b 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -44,13 +44,7 @@ core_initcall(blackfin_mem_malloc_init); -int arch_execute(void * address, int argc, char *argv[]) +void arch_shutdown(void) { - int ret; - icache_disable(); - ret = ((ulong (*)(int, char *[]))address) (argc, &argv[0]); - icache_enable(); - - return ret; } diff --git a/arch/blackfin/lib/cpu.c b/arch/blackfin/lib/cpu.c index e81fa9a..f96d22d 100644 --- a/arch/blackfin/lib/cpu.c +++ b/arch/blackfin/lib/cpu.c @@ -32,7 +32,7 @@ #include #include -void reset_cpu(ulong ignored) +void __noreturn reset_cpu(ulong ignored) { icache_disable(); @@ -43,6 +43,9 @@ : : "r" (L1_ISRAM) ); + + /* Not reached */ + while (1); } void icache_disable(void) diff --git a/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c index c7b77ab..3b1a25b 100644 --- a/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c +++ b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c @@ -27,7 +27,7 @@ /** * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { while ( ignored ) { ; }; diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index 59b1538..7ee1954 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -71,7 +71,7 @@ /* ------------------------------------------------------------------------- */ -void reset_cpu (ulong unused) +void __noreturn reset_cpu (unsigned long unused) { ulong msr; /* Interrupts and MMU off */ diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index d63a2f4..acfa35e 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -137,7 +137,7 @@ return now; } -int reset_cpu(int unused) +void __attribute__((noreturn)) reset_cpu(int unused) { cookmode(); exit(0); diff --git a/arch/x86/mach-i386/reset.c b/arch/x86/mach-i386/reset.c index a4eb364..cdd970e 100644 --- a/arch/x86/mach-i386/reset.c +++ b/arch/x86/mach-i386/reset.c @@ -25,7 +25,7 @@ #include -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { /** How to reset the machine? */ while(1) diff --git a/board/imx21ads/imx21ads.c b/board/imx21ads/imx21ads.c index bc638e3..9eba19a 100644 --- a/board/imx21ads/imx21ads.c +++ b/board/imx21ads/imx21ads.c @@ -34,6 +34,10 @@ #include #include #include +#include + +#define MX21ADS_IO_REG 0xCC800000 +#define MX21ADS_IO_LCDON (1 << 9) static struct device_d cfi_dev = { .name = "cfi_flash", @@ -70,6 +74,45 @@ // IRQ is connected to UART3_RTS }; +/* Sharp LQ035Q7DB02 QVGA display */ +static struct imx_fb_videomode imx_fb_modedata = { + .mode = { + .name = "Sharp-LQ035Q7", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 188679, + .left_margin = 6, + .right_margin = 16, + .upper_margin = 8, + .lower_margin = 10, + .hsync_len = 2, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, + }, + .pcr = 0xfb108bc7, + .bpp = 16, +}; + +static struct imx_fb_platform_data imx_fb_data = { + .mode = &imx_fb_modedata, + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + .pwmr = 0x00a903ff, + .lscr1 = 0x00120300, + .dmacr = 0x00020008, +}; + +static struct device_d imxfb_dev = { + .name = "imxfb", + .map_base = 0x10021000, + .size = 0x1000, + .platform_data = &imx_fb_data, +}; + static int imx21ads_timing_init(void) { u32 temp; @@ -111,6 +154,33 @@ { int i; unsigned int mode[] = { + PA5_PF_LSCLK, + PA6_PF_LD0, + PA7_PF_LD1, + PA8_PF_LD2, + PA9_PF_LD3, + PA10_PF_LD4, + PA11_PF_LD5, + PA12_PF_LD6, + PA13_PF_LD7, + PA14_PF_LD8, + PA15_PF_LD9, + PA16_PF_LD10, + PA17_PF_LD11, + PA18_PF_LD12, + PA19_PF_LD13, + PA20_PF_LD14, + PA21_PF_LD15, + PA22_PF_LD16, + PA23_PF_LD17, + PA24_PF_REV, + PA25_PF_CLS, + PA26_PF_PS, + PA27_PF_SPL_SPR, + PA28_PF_HSYNC, + PA29_PF_VSYNC, + PA30_PF_CONTRAST, + PA31_PF_OE_ACD, PE12_PF_UART1_TXD, PE13_PF_UART1_RXD, PE14_PF_UART1_CTS, @@ -125,6 +195,7 @@ register_device(&sdram_dev); register_device(&nand_dev); register_device(&cs8900_dev); + register_device(&imxfb_dev); armlinux_add_dram(&sdram_dev); armlinux_set_bootparams((void *)0xc0000100); @@ -135,6 +206,18 @@ device_initcall(mx21ads_devices_init); +static int mx21ads_enable_display(void) +{ + u16 tmp; + + tmp = readw(MX21ADS_IO_REG); + tmp |= MX21ADS_IO_LCDON; + writew(tmp, MX21ADS_IO_REG); + return 0; +} + +late_initcall(mx21ads_enable_display); + static struct device_d mx21ads_serial_device = { .name = "imx_serial", .map_base = IMX_UART1_BASE, diff --git a/board/pcm043/pcm043.c b/board/pcm043/pcm043.c index 7b0bad1..2ce7e3a 100644 --- a/board/pcm043/pcm043.c +++ b/board/pcm043/pcm043.c @@ -145,7 +145,7 @@ }; #ifdef CONFIG_MMU -static void pcm043_mmu_init(void) +static int pcm043_mmu_init(void) { mmu_init(); @@ -159,20 +159,21 @@ #else arm_create_section(0x0, TEXT_BASE, 1, PMD_SECT_DEF_UNCACHED); #endif + mmu_enable(); + +#ifdef CONFIG_CACHE_L2X0 + l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); +#endif + return 0; } -#else -static void pcm043_mmu_init(void) -{ -} +postcore_initcall(pcm043_mmu_init); #endif static int imx35_devices_init(void) { uint32_t reg; - pcm043_mmu_init(); - /* CS0: Nor Flash */ writel(0x0000cf03, CSCR_U(0)); writel(0x10000d03, CSCR_L(0)); diff --git a/commands/Kconfig b/commands/Kconfig index bb264fc..0c09f91 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -118,6 +118,12 @@ default y prompt "echo" +config CMD_ECHO_E + bool + depends on CMD_ECHO + select PROCESS_ESCAPE_SEQUENCE + prompt "support -e option to echo" + endmenu menu "memory " @@ -300,4 +306,12 @@ include gpio_set_value, gpio_get_value, gpio_direction_input and gpio_direction_output commands to control gpios. +config CMD_UNLZO + bool + select LZO_DECOMPRESS + prompt "unlzo" + help + Say yes here to get the unlzo command. lzo is a fast compression + algorithm by Markus Franz Xaver Johannes Oberhumer. + endmenu diff --git a/commands/Makefile b/commands/Makefile index b32fa05..74b0994 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_USB_GADGET_DFU) += dfu.o obj-$(CONFIG_CMD_GPIO) += gpio.o +obj-$(CONFIG_CMD_UNLZO) += unlzo.o diff --git a/commands/echo.c b/commands/echo.c index d5640a0..dfa14d6 100644 --- a/commands/echo.c +++ b/commands/echo.c @@ -25,6 +25,7 @@ #include #include #include +#include static int do_echo(struct command *cmdtp, int argc, char *argv[]) { @@ -32,7 +33,10 @@ int fd = stdout, opt, newline = 1; char *file = NULL; int oflags = O_WRONLY | O_CREAT; - +#ifdef CONFIG_CMD_ECHO_E + char str[CONFIG_CBSIZE]; + int process_escape = 0; +#endif /* We can't use getopt() here because we want to * echo all things we don't understand. */ @@ -62,6 +66,11 @@ goto no_optarg_out; optind++; break; +#ifdef CONFIG_CMD_ECHO_E + case 'e': + process_escape = 1; + break; +#endif default: goto exit_parse; } @@ -80,7 +89,13 @@ for (i = optind; i < argc; i++) { if (i > optind) fputc(fd, ' '); - fputs(fd, argv[i]); +#ifdef CONFIG_CMD_ECHO_E + if (process_escape) { + process_escape_sequence(argv[i], str, CONFIG_CBSIZE); + fputs(fd, str); + } else +#endif + fputs(fd, argv[i]); } if (newline) diff --git a/commands/go.c b/commands/go.c index 588d6fc..0262940 100644 --- a/commands/go.c +++ b/commands/go.c @@ -35,6 +35,7 @@ void *addr; int rcode = 1; int fd = -1; + int (*func)(int argc, char *argv[]); if (argc < 2) return COMMAND_ERROR_USAGE; @@ -54,17 +55,21 @@ } else addr = (void *)simple_strtoul(argv[1], NULL, 16); - printf ("## Starting application at 0x%08lX ...\n", addr); + printf("## Starting application at 0x%08lX ...\n", addr); console_flush(); -#ifdef ARCH_HAS_EXECUTE - rcode = arch_execute(addr, argc, &argv[1]); -#else - rcode = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); -#endif + func = addr; - printf ("## Application terminated, rcode = 0x%lX\n", rcode); + shutdown_barebox(); + func(argc - 1, &argv[1]); + + /* + * The application returned. Since we have shutdown barebox and + * we know nothing about the state of the cpu/memory we can't + * do anything here. + */ + while (1); out: if (fd > 0) close(fd); diff --git a/commands/unlzo.c b/commands/unlzo.c new file mode 100644 index 0000000..0b6dd4b --- /dev/null +++ b/commands/unlzo.c @@ -0,0 +1,69 @@ +/* + * unlzo.c - uncompress a lzo compressed file + * + * Copyright (c) 2010 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +static int do_unlzo(struct command *cmdtp, int argc, char *argv[]) +{ + int from, to, ret, retlen; + + if (argc != 3) + return COMMAND_ERROR_USAGE; + + from = open(argv[1], O_RDONLY); + if (from < 0) { + perror("open"); + return 1; + } + + to = open(argv[2], O_WRONLY | O_CREAT); + if (to < 0) { + perror("open"); + ret = 1; + goto exit_close; + } + + ret = unlzo(from, to, &retlen); + if (ret) + printf("failed to decompress\n"); + + close(to); +exit_close: + close(from); + return ret; +} + +static const __maybe_unused char cmd_unlzo_help[] = +"Usage: unlzo \n" +"Uncompress a lzo compressed file\n"; + +BAREBOX_CMD_START(unlzo) + .cmd = do_unlzo, + .usage = "lzop ", + BAREBOX_CMD_HELP(cmd_unlzo_help) +BAREBOX_CMD_END + diff --git a/common/Kconfig b/common/Kconfig index 4c4a627..f514759 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -226,6 +226,15 @@ prompt "hush PS2" default "> " +config HUSH_FANCY_PROMPT + bool + depends on SHELL_HUSH + select PROCESS_ESCAPE_SEQUENCE + prompt "allow fancy hush prompts" + help + Allow to set PS1 from the command line. PS1 can have several escaped commands + like \h for CONFIG_BOARDINFO or \w for the current working directory. + config CMDLINE_EDITING bool prompt "Enable command line editing" diff --git a/common/hush.c b/common/hush.c index cf6704b..19e35f5 100644 --- a/common/hush.c +++ b/common/hush.c @@ -389,15 +389,19 @@ return *i->p; } - static char *getprompt(void) { - static char *prompt; + static char prompt[PATH_MAX + 32]; - if (!prompt) - prompt = xmalloc(PATH_MAX + strlen(CONFIG_PROMPT) + 1); +#ifdef CONFIG_HUSH_FANCY_PROMPT + const char *ps1 = getenv("PS1"); + if (ps1) + process_escape_sequence(ps1, prompt, PATH_MAX + 32); + else +#endif sprintf(prompt, "%s%s ", CONFIG_PROMPT, getcwd()); + return prompt; } @@ -699,7 +703,7 @@ debug("run_pipe_real returned %d\n",rcode); if (rcode < -1) { last_return_code = -rcode - 2; - return -2; /* exit */ + return rcode; /* exit */ } last_return_code=rcode; if ( rmode == RES_IF || rmode == RES_ELIF ) @@ -779,8 +783,9 @@ int cnt=0, pathc; const char *s; char *dest; + for (cnt=1, s=src; s && *s; s++) { - if (*s == '\\') s++; + if (*s == '\\' && strchr("*[?", *(s + 1))) s++; cnt++; } dest = xmalloc(cnt); @@ -794,7 +799,7 @@ pglob->gl_pathv[pathc-1] = dest; pglob->gl_pathv[pathc] = NULL; for (s=src; s && *s; s++, dest++) { - if (*s == '\\') s++; + if (*s == '\\' && strchr("*[?", *(s + 1))) s++; *dest = *s; } *dest='\0'; @@ -1371,17 +1376,9 @@ free_pipe_list(ctx->list_head, 0); continue; } - if (code == -2) { /* exit */ + if (code < -1) { /* exit */ b_free(&temp); - - /* XXX hackish way to not allow exit from main loop */ - if (inp->peek == file_peek) { - printf("exit not allowed from main input shell.\n"); - code = 0; - continue; - } - code = last_return_code; - break; + return -code - 2; } } else { if (ctx->old_flag != 0) { diff --git a/common/startup.c b/common/startup.c index 6dca270..2ed16fe 100644 --- a/common/startup.c +++ b/common/startup.c @@ -161,7 +161,7 @@ /* NOTREACHED - no way out of command loop except booting */ } -void hang (void) +void __noreturn hang (void) { puts ("### ERROR ### Please RESET the board ###\n"); for (;;); @@ -174,5 +174,8 @@ void shutdown_barebox(void) { devices_shutdown(); +#ifdef ARCH_SHUTDOWN + arch_shutdown(); +#endif } diff --git a/drivers/nand/nand_imx.c b/drivers/nand/nand_imx.c index 5c910d8..cacf91c 100644 --- a/drivers/nand/nand_imx.c +++ b/drivers/nand/nand_imx.c @@ -200,12 +200,17 @@ } }; -static void __nand_boot_init memcpy32(void *trg, const void *src, int size) +static void memcpy32(void *trg, const void *src, int size) { int i; unsigned int *t = trg; unsigned const int *s = src; +#ifdef CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS + if (!((unsigned long)trg & 0x3) && !((unsigned long)src & 0x3)) + memcpy(trg, src, size); + else +#endif for (i = 0; i < (size >> 2); i++) *t++ = *s++; } @@ -290,7 +295,7 @@ * @param spare_only set true if only the spare area is transferred */ static void __nand_boot_init send_page(struct imx_nand_host *host, - unsigned int ops) + unsigned int ops, int wait) { int bufs, i; @@ -306,7 +311,8 @@ writew(ops, host->regs + NFC_CONFIG2); /* Wait for operation to complete */ - wait_op_done(host); + if (wait) + wait_op_done(host); } } @@ -499,7 +505,7 @@ int n = mtd->oobsize + mtd->writesize - col; n = min(n, len); - memcpy32(host->data_buf + col, buf, n); + memcpy(host->data_buf + col, buf, n); host->buf_start += n; } @@ -523,7 +529,7 @@ n = min(n, len); - memcpy32(buf, host->data_buf + col, len); + memcpy(buf, host->data_buf + col, len); host->buf_start += len; } @@ -666,11 +672,17 @@ { struct nand_chip *nand_chip = mtd->priv; struct imx_nand_host *host = nand_chip->priv; + static int cached = -1; MTD_DEBUG(MTD_DEBUG_LEVEL3, "imx_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", command, column, page_addr); + if (cached != -1) + wait_op_done(host); + if (command != NAND_CMD_READ0) + cached = -1; + /* * Reset command state information */ @@ -697,17 +709,44 @@ command = NAND_CMD_READ0; - send_cmd(host, command); - mxc_do_addr_cycle(mtd, column, page_addr); + if (cached == page_addr) { + memcpy32(host->data_buf, host->main_area0, mtd->writesize); + copy_spare(mtd, 1); - if (host->pagesize_2k) - /* send read confirm command */ - send_cmd(host, NAND_CMD_READSTART); + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr + 1); - send_page(host, NFC_OUTPUT); + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); - memcpy32(host->data_buf, host->main_area0, mtd->writesize); - copy_spare(mtd, 1); + send_page(host, NFC_OUTPUT, 0); + + cached = page_addr + 1; + } else { + host->buf_start = column; + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr); + + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); + + send_page(host, NFC_OUTPUT, 1); + memcpy32(host->data_buf, host->main_area0, mtd->writesize); + copy_spare(mtd, 1); + + send_cmd(host, command); + mxc_do_addr_cycle(mtd, column, page_addr + 1); + + if (host->pagesize_2k) + /* send read confirm command */ + send_cmd(host, NAND_CMD_READSTART); + + send_page(host, NFC_OUTPUT, 0); + cached = page_addr + 1; + } + break; case NAND_CMD_SEQIN: @@ -744,7 +783,7 @@ case NAND_CMD_PAGEPROG: memcpy32(host->main_area0, host->data_buf, mtd->writesize); copy_spare(mtd, 0); - send_page(host, NFC_INPUT); + send_page(host, NFC_INPUT, 1); send_cmd(host, command); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -845,7 +884,7 @@ #endif /* Allocate memory for MTD device structure and private data */ host = kzalloc(sizeof(struct imx_nand_host) + NAND_MAX_PAGESIZE + - NAND_MAX_OOBSIZE, GFP_KERNEL); + NAND_MAX_OOBSIZE * 2, GFP_KERNEL); if (!host) return -ENOMEM; @@ -1025,6 +1064,16 @@ } } +static void __nand_boot_init __memcpy32(void *trg, const void *src, int size) +{ + int i; + unsigned int *t = trg; + unsigned const int *s = src; + + for (i = 0; i < (size >> 2); i++) + *t++ = *s++; +} + void __nand_boot_init imx_nand_load_image(void *dest, int size) { struct imx_nand_host host; @@ -1122,7 +1171,7 @@ page * pagesize); if (host.pagesize_2k) send_cmd(&host, NAND_CMD_READSTART); - send_page(&host, NFC_OUTPUT); + send_page(&host, NFC_OUTPUT, 1); page++; if (host.pagesize_2k) { @@ -1135,7 +1184,7 @@ continue; } - memcpy32(dest, host.base, pagesize); + __memcpy32(dest, host.base, pagesize); dest += pagesize; size -= pagesize; diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 49140e7..8440333 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -425,7 +425,8 @@ writew(data_length, &fec->tbd_base[fec->tbd_index].data_length); writel((uint32_t)(eth_data), &fec->tbd_base[fec->tbd_index].data_pointer); - dma_flush_range(eth_data, eth_data + data_length); + dma_flush_range((unsigned long)eth_data, + (unsigned long)(eth_data + data_length)); /* * update BD's status now * This block: diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c index e535f18..673007a 100644 --- a/drivers/net/netx_eth.c +++ b/drivers/net/netx_eth.c @@ -19,8 +19,6 @@ #define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<ep = ep; - dma_flush_range(req->req.buf, req->req.buf + req->req.length); + dma_flush_range((unsigned long)req->req.buf, + (unsigned long)(req->req.buf + req->req.length)); req->req.status = -EINPROGRESS; req->req.actual = 0; diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c index cb5a073..d7efaad 100644 --- a/drivers/usb/usb_ehci_core.c +++ b/drivers/usb/usb_ehci_core.c @@ -129,9 +129,9 @@ static void flush_invalidate(void *addr, int size, int flush) { if (flush) - dma_flush_range(addr, addr + size); + dma_flush_range((unsigned long)addr, (unsigned long)(addr + size)); else - dma_inv_range(addr, addr + size); + dma_inv_range((unsigned long)addr, (unsigned long)(addr + size)); } static void cache_qtd(struct qTD *qtd, int flush) diff --git a/drivers/video/imx.c b/drivers/video/imx.c index 9a30ca4..87c08d3 100644 --- a/drivers/video/imx.c +++ b/drivers/video/imx.c @@ -251,6 +251,9 @@ struct imxfb_info *fbi = info->priv; writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); +#ifdef CONFIG_ARCH_IMX21 + PCCR0 |= PCCR0_PERCLK3_EN | PCCR0_HCLK_LCDC_EN; +#endif #ifdef CONFIG_ARCH_IMX27 PCCR0 |= PCCR0_LCDC_EN; PCCR1 |= PCCR1_HCLK_LCDC; @@ -263,6 +266,9 @@ struct imxfb_info *fbi = info->priv; writel(0, fbi->regs + LCDC_RMCR); +#ifdef CONFIG_ARCH_IMX21 + PCCR0 &= ~(PCCR0_PERCLK3_EN | PCCR0_HCLK_LCDC_EN); +#endif #ifdef CONFIG_ARCH_IMX27 PCCR0 &= ~PCCR0_LCDC_EN; PCCR1 &= ~PCCR1_HCLK_LCDC; @@ -505,6 +511,9 @@ if (!pdata) return -ENODEV; +#ifdef CONFIG_ARCH_IMX21 + PCCR0 &= ~(PCCR0_PERCLK3_EN | PCCR0_HCLK_LCDC_EN); +#endif #ifdef CONFIG_ARCH_IMX27 PCCR0 &= ~PCCR0_LCDC_EN; PCCR1 &= ~PCCR1_HCLK_LCDC; diff --git a/include/common.h b/include/common.h index 76e9be9..319535b 100644 --- a/include/common.h +++ b/include/common.h @@ -65,8 +65,8 @@ */ void reginfo(void); -void hang (void) __attribute__ ((noreturn)); -void panic(const char *fmt, ...); +void __noreturn hang (void); +void __noreturn panic(const char *fmt, ...); /* */ long int initdram (int); @@ -80,7 +80,7 @@ long get_ram_size (volatile long *, long); /* $(CPU)/cpu.c */ -void reset_cpu (ulong addr); +void __noreturn reset_cpu(unsigned long addr); /* $(CPU)/interrupts.c */ //void timer_interrupt (struct pt_regs *); @@ -134,7 +134,7 @@ void start_barebox(void); void shutdown_barebox(void); -int arch_execute(void *, int argc, char *argv[]); +void arch_shutdown(void); int run_shell(void); diff --git a/include/libbb.h b/include/libbb.h index 735ed21..4151230 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -28,4 +28,6 @@ int copy_file(const char *src, const char *dst); +int process_escape_sequence(const char *source, char *dest, int destlen); + #endif /* __LIBBB_H */ diff --git a/include/lzo.h b/include/lzo.h new file mode 100644 index 0000000..5694985 --- /dev/null +++ b/include/lzo.h @@ -0,0 +1,46 @@ +#ifndef __LZO_H__ +#define __LZO_H__ +/* + * LZO Public Kernel Interface + * A mini subset of the LZO real-time data compression library + * + * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for kernel use by: + * Nitin Gupta + * Richard Purdie + */ + +#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *)) +#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS + +#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3) + +/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */ +int lzo1x_1_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + +/* safe decompression with overrun testing */ +int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len); + +/* + * Return values (< 0 = Error) + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) +#define LZO_E_NOT_COMPRESSIBLE (-3) +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) + +int unlzo(int in_fd, int out_fd, int *dest_len); + +#endif diff --git a/include/stdio.h b/include/stdio.h index c23dfc6..cd1a913 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -31,6 +31,7 @@ int printf(const char *fmt, ...); int vprintf(const char *fmt, va_list args); int sprintf(char * buf, const char *fmt, ...); +int snprintf(char *buf, size_t size, const char *fmt, ...); int vsprintf(char *buf, const char *fmt, va_list args); char *asprintf(const char *fmt, ...); char *vasprintf(const char *fmt, va_list ap); diff --git a/include/unaligned/access_ok.h b/include/unaligned/access_ok.h new file mode 100644 index 0000000..99c1b4d --- /dev/null +++ b/include/unaligned/access_ok.h @@ -0,0 +1,67 @@ +#ifndef _LINUX_UNALIGNED_ACCESS_OK_H +#define _LINUX_UNALIGNED_ACCESS_OK_H + +#include +#include + +static inline u16 get_unaligned_le16(const void *p) +{ + return le16_to_cpup((__le16 *)p); +} + +static inline u32 get_unaligned_le32(const void *p) +{ + return le32_to_cpup((__le32 *)p); +} + +static inline u64 get_unaligned_le64(const void *p) +{ + return le64_to_cpup((__le64 *)p); +} + +static inline u16 get_unaligned_be16(const void *p) +{ + return be16_to_cpup((__be16 *)p); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return be32_to_cpup((__be32 *)p); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return be64_to_cpup((__be64 *)p); +} + +static inline void put_unaligned_le16(u16 val, void *p) +{ + *((__le16 *)p) = cpu_to_le16(val); +} + +static inline void put_unaligned_le32(u32 val, void *p) +{ + *((__le32 *)p) = cpu_to_le32(val); +} + +static inline void put_unaligned_le64(u64 val, void *p) +{ + *((__le64 *)p) = cpu_to_le64(val); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + *((__be16 *)p) = cpu_to_be16(val); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + *((__be32 *)p) = cpu_to_be32(val); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + *((__be64 *)p) = cpu_to_be64(val); +} + +#endif /* _LINUX_UNALIGNED_ACCESS_OK_H */ diff --git a/include/unaligned/be_byteshift.h b/include/unaligned/be_byteshift.h new file mode 100644 index 0000000..9356b24 --- /dev/null +++ b/include/unaligned/be_byteshift.h @@ -0,0 +1,70 @@ +#ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H +#define _LINUX_UNALIGNED_BE_BYTESHIFT_H + +#include + +static inline u16 __get_unaligned_be16(const u8 *p) +{ + return p[0] << 8 | p[1]; +} + +static inline u32 __get_unaligned_be32(const u8 *p) +{ + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +static inline u64 __get_unaligned_be64(const u8 *p) +{ + return (u64)__get_unaligned_be32(p) << 32 | + __get_unaligned_be32(p + 4); +} + +static inline void __put_unaligned_be16(u16 val, u8 *p) +{ + *p++ = val >> 8; + *p++ = val; +} + +static inline void __put_unaligned_be32(u32 val, u8 *p) +{ + __put_unaligned_be16(val >> 16, p); + __put_unaligned_be16(val, p + 2); +} + +static inline void __put_unaligned_be64(u64 val, u8 *p) +{ + __put_unaligned_be32(val >> 32, p); + __put_unaligned_be32(val, p + 4); +} + +static inline u16 get_unaligned_be16(const void *p) +{ + return __get_unaligned_be16((const u8 *)p); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return __get_unaligned_be32((const u8 *)p); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return __get_unaligned_be64((const u8 *)p); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + __put_unaligned_be16(val, p); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + __put_unaligned_be32(val, p); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + __put_unaligned_be64(val, p); +} + +#endif /* _LINUX_UNALIGNED_BE_BYTESHIFT_H */ diff --git a/include/unaligned/be_memmove.h b/include/unaligned/be_memmove.h new file mode 100644 index 0000000..c2a76c5 --- /dev/null +++ b/include/unaligned/be_memmove.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_UNALIGNED_BE_MEMMOVE_H +#define _LINUX_UNALIGNED_BE_MEMMOVE_H + +#include + +static inline u16 get_unaligned_be16(const void *p) +{ + return __get_unaligned_memmove16((const u8 *)p); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return __get_unaligned_memmove32((const u8 *)p); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return __get_unaligned_memmove64((const u8 *)p); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + __put_unaligned_memmove16(val, p); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + __put_unaligned_memmove32(val, p); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + __put_unaligned_memmove64(val, p); +} + +#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */ diff --git a/include/unaligned/be_struct.h b/include/unaligned/be_struct.h new file mode 100644 index 0000000..1324158 --- /dev/null +++ b/include/unaligned/be_struct.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_UNALIGNED_BE_STRUCT_H +#define _LINUX_UNALIGNED_BE_STRUCT_H + +#include + +static inline u16 get_unaligned_be16(const void *p) +{ + return __get_unaligned_cpu16((const u8 *)p); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return __get_unaligned_cpu32((const u8 *)p); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return __get_unaligned_cpu64((const u8 *)p); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + __put_unaligned_cpu16(val, p); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + __put_unaligned_cpu32(val, p); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + __put_unaligned_cpu64(val, p); +} + +#endif /* _LINUX_UNALIGNED_BE_STRUCT_H */ diff --git a/include/unaligned/generic.h b/include/unaligned/generic.h new file mode 100644 index 0000000..02d97ff --- /dev/null +++ b/include/unaligned/generic.h @@ -0,0 +1,68 @@ +#ifndef _LINUX_UNALIGNED_GENERIC_H +#define _LINUX_UNALIGNED_GENERIC_H + +/* + * Cause a link-time error if we try an unaligned access other than + * 1,2,4 or 8 bytes long + */ +extern void __bad_unaligned_access_size(void); + +#define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({ \ + __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ + __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \ + __bad_unaligned_access_size())))); \ + })) + +#define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({ \ + __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \ + __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \ + __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \ + __bad_unaligned_access_size())))); \ + })) + +#define __put_unaligned_le(val, ptr) ({ \ + void *__gu_p = (ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: \ + *(u8 *)__gu_p = (__force u8)(val); \ + break; \ + case 2: \ + put_unaligned_le16((__force u16)(val), __gu_p); \ + break; \ + case 4: \ + put_unaligned_le32((__force u32)(val), __gu_p); \ + break; \ + case 8: \ + put_unaligned_le64((__force u64)(val), __gu_p); \ + break; \ + default: \ + __bad_unaligned_access_size(); \ + break; \ + } \ + (void)0; }) + +#define __put_unaligned_be(val, ptr) ({ \ + void *__gu_p = (ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: \ + *(u8 *)__gu_p = (__force u8)(val); \ + break; \ + case 2: \ + put_unaligned_be16((__force u16)(val), __gu_p); \ + break; \ + case 4: \ + put_unaligned_be32((__force u32)(val), __gu_p); \ + break; \ + case 8: \ + put_unaligned_be64((__force u64)(val), __gu_p); \ + break; \ + default: \ + __bad_unaligned_access_size(); \ + break; \ + } \ + (void)0; }) + +#endif /* _LINUX_UNALIGNED_GENERIC_H */ diff --git a/include/unaligned/le_byteshift.h b/include/unaligned/le_byteshift.h new file mode 100644 index 0000000..be376fb --- /dev/null +++ b/include/unaligned/le_byteshift.h @@ -0,0 +1,70 @@ +#ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H +#define _LINUX_UNALIGNED_LE_BYTESHIFT_H + +#include + +static inline u16 __get_unaligned_le16(const u8 *p) +{ + return p[0] | p[1] << 8; +} + +static inline u32 __get_unaligned_le32(const u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; +} + +static inline u64 __get_unaligned_le64(const u8 *p) +{ + return (u64)__get_unaligned_le32(p + 4) << 32 | + __get_unaligned_le32(p); +} + +static inline void __put_unaligned_le16(u16 val, u8 *p) +{ + *p++ = val; + *p++ = val >> 8; +} + +static inline void __put_unaligned_le32(u32 val, u8 *p) +{ + __put_unaligned_le16(val >> 16, p + 2); + __put_unaligned_le16(val, p); +} + +static inline void __put_unaligned_le64(u64 val, u8 *p) +{ + __put_unaligned_le32(val >> 32, p + 4); + __put_unaligned_le32(val, p); +} + +static inline u16 get_unaligned_le16(const void *p) +{ + return __get_unaligned_le16((const u8 *)p); +} + +static inline u32 get_unaligned_le32(const void *p) +{ + return __get_unaligned_le32((const u8 *)p); +} + +static inline u64 get_unaligned_le64(const void *p) +{ + return __get_unaligned_le64((const u8 *)p); +} + +static inline void put_unaligned_le16(u16 val, void *p) +{ + __put_unaligned_le16(val, p); +} + +static inline void put_unaligned_le32(u32 val, void *p) +{ + __put_unaligned_le32(val, p); +} + +static inline void put_unaligned_le64(u64 val, void *p) +{ + __put_unaligned_le64(val, p); +} + +#endif /* _LINUX_UNALIGNED_LE_BYTESHIFT_H */ diff --git a/include/unaligned/le_memmove.h b/include/unaligned/le_memmove.h new file mode 100644 index 0000000..269849b --- /dev/null +++ b/include/unaligned/le_memmove.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_UNALIGNED_LE_MEMMOVE_H +#define _LINUX_UNALIGNED_LE_MEMMOVE_H + +#include + +static inline u16 get_unaligned_le16(const void *p) +{ + return __get_unaligned_memmove16((const u8 *)p); +} + +static inline u32 get_unaligned_le32(const void *p) +{ + return __get_unaligned_memmove32((const u8 *)p); +} + +static inline u64 get_unaligned_le64(const void *p) +{ + return __get_unaligned_memmove64((const u8 *)p); +} + +static inline void put_unaligned_le16(u16 val, void *p) +{ + __put_unaligned_memmove16(val, p); +} + +static inline void put_unaligned_le32(u32 val, void *p) +{ + __put_unaligned_memmove32(val, p); +} + +static inline void put_unaligned_le64(u64 val, void *p) +{ + __put_unaligned_memmove64(val, p); +} + +#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */ diff --git a/include/unaligned/le_struct.h b/include/unaligned/le_struct.h new file mode 100644 index 0000000..088c457 --- /dev/null +++ b/include/unaligned/le_struct.h @@ -0,0 +1,36 @@ +#ifndef _LINUX_UNALIGNED_LE_STRUCT_H +#define _LINUX_UNALIGNED_LE_STRUCT_H + +#include + +static inline u16 get_unaligned_le16(const void *p) +{ + return __get_unaligned_cpu16((const u8 *)p); +} + +static inline u32 get_unaligned_le32(const void *p) +{ + return __get_unaligned_cpu32((const u8 *)p); +} + +static inline u64 get_unaligned_le64(const void *p) +{ + return __get_unaligned_cpu64((const u8 *)p); +} + +static inline void put_unaligned_le16(u16 val, void *p) +{ + __put_unaligned_cpu16(val, p); +} + +static inline void put_unaligned_le32(u32 val, void *p) +{ + __put_unaligned_cpu32(val, p); +} + +static inline void put_unaligned_le64(u64 val, void *p) +{ + __put_unaligned_cpu64(val, p); +} + +#endif /* _LINUX_UNALIGNED_LE_STRUCT_H */ diff --git a/include/unaligned/memmove.h b/include/unaligned/memmove.h new file mode 100644 index 0000000..eeb5a77 --- /dev/null +++ b/include/unaligned/memmove.h @@ -0,0 +1,45 @@ +#ifndef _LINUX_UNALIGNED_MEMMOVE_H +#define _LINUX_UNALIGNED_MEMMOVE_H + +#include +#include + +/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ + +static inline u16 __get_unaligned_memmove16(const void *p) +{ + u16 tmp; + memmove(&tmp, p, 2); + return tmp; +} + +static inline u32 __get_unaligned_memmove32(const void *p) +{ + u32 tmp; + memmove(&tmp, p, 4); + return tmp; +} + +static inline u64 __get_unaligned_memmove64(const void *p) +{ + u64 tmp; + memmove(&tmp, p, 8); + return tmp; +} + +static inline void __put_unaligned_memmove16(u16 val, void *p) +{ + memmove(p, &val, 2); +} + +static inline void __put_unaligned_memmove32(u32 val, void *p) +{ + memmove(p, &val, 4); +} + +static inline void __put_unaligned_memmove64(u64 val, void *p) +{ + memmove(p, &val, 8); +} + +#endif /* _LINUX_UNALIGNED_MEMMOVE_H */ diff --git a/include/unaligned/packed_struct.h b/include/unaligned/packed_struct.h new file mode 100644 index 0000000..2498bb9 --- /dev/null +++ b/include/unaligned/packed_struct.h @@ -0,0 +1,46 @@ +#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H +#define _LINUX_UNALIGNED_PACKED_STRUCT_H + +#include + +struct __una_u16 { u16 x __attribute__((packed)); }; +struct __una_u32 { u32 x __attribute__((packed)); }; +struct __una_u64 { u64 x __attribute__((packed)); }; + +static inline u16 __get_unaligned_cpu16(const void *p) +{ + const struct __una_u16 *ptr = (const struct __una_u16 *)p; + return ptr->x; +} + +static inline u32 __get_unaligned_cpu32(const void *p) +{ + const struct __una_u32 *ptr = (const struct __una_u32 *)p; + return ptr->x; +} + +static inline u64 __get_unaligned_cpu64(const void *p) +{ + const struct __una_u64 *ptr = (const struct __una_u64 *)p; + return ptr->x; +} + +static inline void __put_unaligned_cpu16(u16 val, void *p) +{ + struct __una_u16 *ptr = (struct __una_u16 *)p; + ptr->x = val; +} + +static inline void __put_unaligned_cpu32(u32 val, void *p) +{ + struct __una_u32 *ptr = (struct __una_u32 *)p; + ptr->x = val; +} + +static inline void __put_unaligned_cpu64(u64 val, void *p) +{ + struct __una_u64 *ptr = (struct __una_u64 *)p; + ptr->x = val; +} + +#endif /* _LINUX_UNALIGNED_PACKED_STRUCT_H */ diff --git a/lib/Kconfig b/lib/Kconfig index c272078..28c92cd 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -13,3 +13,8 @@ config GENERIC_FIND_NEXT_BIT def_bool n +config PROCESS_ESCAPE_SEQUENCE + def_bool n + +source lib/lzo/Kconfig + diff --git a/lib/Makefile b/lib/Makefile index b532690..b072fb6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,3 +28,6 @@ obj-y += glob.o obj-y += notifier.o obj-y += copy_file.o +obj-y += lzo/ +obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o +obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c new file mode 100644 index 0000000..8f9cdcf --- /dev/null +++ b/lib/decompress_unlzo.c @@ -0,0 +1,199 @@ +/* + * LZO decompressor for barebox. Code borrowed from the lzo + * implementation by Markus Franz Xaver Johannes Oberhumer. + * + * Linux kernel adaptation: + * Copyright (C) 2009 + * Albin Tonnerre, Free Electrons + * + * Original code: + * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer + * All Rights Reserved. + * + * lzop and the LZO library are free software; you can redistribute them + * and/or modify them under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. + * If not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Markus F.X.J. Oberhumer + * + * http://www.oberhumer.com/opensource/lzop/ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static const unsigned char lzop_magic[] = { + 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a }; + +#define LZO_BLOCK_SIZE (256*1024l) +#define HEADER_HAS_FILTER 0x00000800L + +static inline int parse_header(int in_fd) +{ + u8 l; + u16 version; + int ret; + unsigned char buf[256]; /* maximum filename length + 1 */ + + /* read magic (9), library version (2), 'need to be extracted' + * version (2) and method (1) + */ + ret = read(in_fd, buf, 9); + if (ret < 0) + return ret; + + /* check magic */ + for (l = 0; l < 9; l++) { + if (buf[l] != lzop_magic[l]) + return -EINVAL; + } + + ret = read(in_fd, buf, 4); /* version, lib_version */ + if (ret < 0) + return ret; + version = get_unaligned_be16(buf); + + if (version >= 0x0940) { + ret = read(in_fd, buf, 2); /* version to extract */ + if (ret < 0) + return ret; + } + + ret = read(in_fd, buf, 1); /* method */ + if (ret < 0) + return ret; + + if (version >= 0x0940) + read(in_fd, buf, 1); /* level */ + + ret = read(in_fd, buf, 4); /* flags */ + if (ret < 0) + return ret; + + if (get_unaligned_be32(buf) & HEADER_HAS_FILTER) { + ret = read(in_fd, buf, 4); /* skip filter info */ + if (ret < 0) + return ret; + } + + /* skip mode and mtime_low */ + ret = read(in_fd, buf, 8); + if (ret < 0) + return ret; + + if (version >= 0x0940) { + ret = read(in_fd, buf, 4); /* skip mtime_high */ + if (ret < 0) + return ret; + } + + ret = read(in_fd, &l, 1); + if (ret < 0) + return ret; + /* don't care about the file name, and skip checksum */ + ret = read(in_fd, buf, l + 4); + if (ret < 0) + return ret; + + return 0; +} + +int unlzo(int in_fd, int out_fd, int *dest_len) +{ + u8 r = 0; + u32 src_len, dst_len; + size_t tmp; + u8 *in_buf, *out_buf; + int obytes_processed = 0; + unsigned char buf[8]; + int ret; + + if (parse_header(in_fd)) + return -EINVAL; + + out_buf = xmalloc(LZO_BLOCK_SIZE); + in_buf = xmalloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); + + for (;;) { + /* read uncompressed block size */ + ret = read(in_fd, buf, 4); + if (ret < 0) + goto exit_free; + dst_len = get_unaligned_be32(buf); + + /* exit if last block */ + if (dst_len == 0) + break; + + if (dst_len > LZO_BLOCK_SIZE) { + printf("dest len longer than block size"); + goto exit_free; + } + + /* read compressed block size, and skip block checksum info */ + ret = read(in_fd, buf, 8); + if (ret < 0) + goto exit_free; + + src_len = get_unaligned_be32(buf); + + if (src_len <= 0 || src_len > dst_len) { + printf("file corrupted"); + goto exit_free; + } + ret = read(in_fd, in_buf, src_len); + if (ret < 0) + goto exit_free; + + /* decompress */ + tmp = dst_len; + if (src_len < dst_len) { + r = lzo1x_decompress_safe((u8 *) in_buf, src_len, + out_buf, &tmp); + if (r != LZO_E_OK || dst_len != tmp) { + printf("Compressed data violation"); + goto exit_free; + } + ret = write(out_fd, out_buf, dst_len); + if (ret < 0) + goto exit_free; + } else { + if (src_len != dst_len) { + printf("Compressed data violation"); + goto exit_free; + } + ret = write(out_fd, in_buf, dst_len); + if (ret < 0) + goto exit_free; + } + + obytes_processed += dst_len; + } + +exit_free: + free(in_buf); + free(out_buf); + + *dest_len = obytes_processed; + return 0; +} + diff --git a/lib/lzo/Kconfig b/lib/lzo/Kconfig new file mode 100644 index 0000000..4016785 --- /dev/null +++ b/lib/lzo/Kconfig @@ -0,0 +1,6 @@ +config LZO_DECOMPRESS + bool + +config LZO_COMPRESS + bool + diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile new file mode 100644 index 0000000..e1a97ae --- /dev/null +++ b/lib/lzo/Makefile @@ -0,0 +1,4 @@ + +obj-$(CONFIG_LZO_COMPRESS) += lzo1x_compress.o +obj-$(CONFIG_LZO_DECOMPRESS) += lzo1x_decompress.o + diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c new file mode 100644 index 0000000..a604099 --- /dev/null +++ b/lib/lzo/lzo1x_compress.c @@ -0,0 +1,226 @@ +/* + * LZO1X Compressor from MiniLZO + * + * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for kernel use by: + * Nitin Gupta + * Richard Purdie + */ + +#include +#include +#include +#include +#include "lzodefs.h" + +static noinline size_t +_lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len, void *wrkmem) +{ + const unsigned char * const in_end = in + in_len; + const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5; + const unsigned char ** const dict = wrkmem; + const unsigned char *ip = in, *ii = ip; + const unsigned char *end, *m, *m_pos; + size_t m_off, m_len, dindex; + unsigned char *op = out; + + ip += 4; + + for (;;) { + dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK; + m_pos = dict[dindex]; + + if (m_pos < in) + goto literal; + + if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) + goto literal; + + m_off = ip - m_pos; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + + dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f); + m_pos = dict[dindex]; + + if (m_pos < in) + goto literal; + + if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) + goto literal; + + m_off = ip - m_pos; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + + goto literal; + +try_match: + if (get_unaligned((const unsigned short *)m_pos) + == get_unaligned((const unsigned short *)ip)) { + if (likely(m_pos[2] == ip[2])) + goto match; + } + +literal: + dict[dindex] = ip; + ++ip; + if (unlikely(ip >= ip_end)) + break; + continue; + +match: + dict[dindex] = ip; + if (ip != ii) { + size_t t = ip - ii; + + if (t <= 3) { + op[-2] |= t; + } else if (t <= 18) { + *op++ = (t - 3); + } else { + size_t tt = t - 18; + + *op++ = 0; + while (tt > 255) { + tt -= 255; + *op++ = 0; + } + *op++ = tt; + } + do { + *op++ = *ii++; + } while (--t > 0); + } + + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ + || m_pos[5] != *ip++ || m_pos[6] != *ip++ + || m_pos[7] != *ip++ || m_pos[8] != *ip++) { + --ip; + m_len = ip - ii; + + if (m_off <= M2_MAX_OFFSET) { + m_off -= 1; + *op++ = (((m_len - 1) << 5) + | ((m_off & 7) << 2)); + *op++ = (m_off >> 3); + } else if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; + *op++ = (M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } else { + m_off -= 0x4000; + + *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11) + | (m_len - 2)); + goto m3_m4_offset; + } + } else { + end = in_end; + m = m_pos + M2_MAX_LEN + 1; + + while (ip < end && *m == *ip) { + m++; + ip++; + } + m_len = ip - ii; + + if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; + if (m_len <= 33) { + *op++ = (M3_MARKER | (m_len - 2)); + } else { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } else { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) { + *op++ = (M4_MARKER + | ((m_off & 0x4000) >> 11) + | (m_len - 2)); + } else { + m_len -= M4_MAX_LEN; + *op++ = (M4_MARKER + | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) { + m_len -= 255; + *op++ = 0; + } + + *op++ = (m_len); + } + } +m3_m4_offset: + *op++ = ((m_off & 63) << 2); + *op++ = (m_off >> 6); + } + + ii = ip; + if (unlikely(ip >= ip_end)) + break; + } + + *out_len = op - out; + return in_end - ii; +} + +int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out, + size_t *out_len, void *wrkmem) +{ + const unsigned char *ii; + unsigned char *op = out; + size_t t; + + if (unlikely(in_len <= M2_MAX_LEN + 5)) { + t = in_len; + } else { + t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem); + op += *out_len; + } + + if (t > 0) { + ii = in + in_len - t; + + if (op == out && t <= 238) { + *op++ = (17 + t); + } else if (t <= 3) { + op[-2] |= t; + } else if (t <= 18) { + *op++ = (t - 3); + } else { + size_t tt = t - 18; + + *op++ = 0; + while (tt > 255) { + tt -= 255; + *op++ = 0; + } + + *op++ = tt; + } + do { + *op++ = *ii++; + } while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} +EXPORT_SYMBOL_GPL(lzo1x_1_compress); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZO1X-1 Compressor"); + diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c new file mode 100644 index 0000000..af94382 --- /dev/null +++ b/lib/lzo/lzo1x_decompress.c @@ -0,0 +1,247 @@ +/* + * LZO1X Decompressor from MiniLZO + * + * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for kernel use by: + * Nitin Gupta + * Richard Purdie + */ + +#include +#include +#include +#include "lzodefs.h" + +#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x)) +#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x)) +#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op) + +#define COPY4(dst, src) \ + put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst)) + +int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len) +{ + const unsigned char * const ip_end = in + in_len; + unsigned char * const op_end = out + *out_len; + const unsigned char *ip = in, *m_pos; + unsigned char *op = out; + size_t t; + + *out_len = 0; + + if (*ip > 17) { + t = *ip++ - 17; + if (t < 4) + goto match_next; + if (HAVE_OP(t, op_end, op)) + goto output_overrun; + if (HAVE_IP(t + 1, ip_end, ip)) + goto input_overrun; + do { + *op++ = *ip++; + } while (--t > 0); + goto first_literal_run; + } + + while ((ip < ip_end)) { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) { + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + while (*ip == 0) { + t += 255; + ip++; + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + } + t += 15 + *ip++; + } + if (HAVE_OP(t + 3, op_end, op)) + goto output_overrun; + if (HAVE_IP(t + 4, ip_end, ip)) + goto input_overrun; + + COPY4(op, ip); + op += 4; + ip += 4; + if (--t > 0) { + if (t >= 4) { + do { + COPY4(op, ip); + op += 4; + ip += 4; + t -= 4; + } while (t >= 4); + if (t > 0) { + do { + *op++ = *ip++; + } while (--t > 0); + } + } else { + do { + *op++ = *ip++; + } while (--t > 0); + } + } + +first_literal_run: + t = *ip++; + if (t >= 16) + goto match; + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + + if (HAVE_LB(m_pos, out, op)) + goto lookbehind_overrun; + + if (HAVE_OP(3, op_end, op)) + goto output_overrun; + *op++ = *m_pos++; + *op++ = *m_pos++; + *op++ = *m_pos; + + goto match_done; + + do { +match: + if (t >= 64) { + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; + if (HAVE_LB(m_pos, out, op)) + goto lookbehind_overrun; + if (HAVE_OP(t + 3 - 1, op_end, op)) + goto output_overrun; + goto copy_match; + } else if (t >= 32) { + t &= 31; + if (t == 0) { + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + while (*ip == 0) { + t += 255; + ip++; + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + } + t += 31 + *ip++; + } + m_pos = op - 1; + m_pos -= get_unaligned_le16(ip) >> 2; + ip += 2; + } else if (t >= 16) { + m_pos = op; + m_pos -= (t & 8) << 11; + + t &= 7; + if (t == 0) { + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + while (*ip == 0) { + t += 255; + ip++; + if (HAVE_IP(1, ip_end, ip)) + goto input_overrun; + } + t += 7 + *ip++; + } + m_pos -= get_unaligned_le16(ip) >> 2; + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; + } else { + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + + if (HAVE_LB(m_pos, out, op)) + goto lookbehind_overrun; + if (HAVE_OP(2, op_end, op)) + goto output_overrun; + + *op++ = *m_pos++; + *op++ = *m_pos; + goto match_done; + } + + if (HAVE_LB(m_pos, out, op)) + goto lookbehind_overrun; + if (HAVE_OP(t + 3 - 1, op_end, op)) + goto output_overrun; + + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { + COPY4(op, m_pos); + op += 4; + m_pos += 4; + t -= 4 - (3 - 1); + do { + COPY4(op, m_pos); + op += 4; + m_pos += 4; + t -= 4; + } while (t >= 4); + if (t > 0) + do { + *op++ = *m_pos++; + } while (--t > 0); + } else { +copy_match: + *op++ = *m_pos++; + *op++ = *m_pos++; + do { + *op++ = *m_pos++; + } while (--t > 0); + } +match_done: + t = ip[-2] & 3; + if (t == 0) + break; +match_next: + if (HAVE_OP(t, op_end, op)) + goto output_overrun; + if (HAVE_IP(t + 1, ip_end, ip)) + goto input_overrun; + + *op++ = *ip++; + if (t > 1) { + *op++ = *ip++; + if (t > 2) + *op++ = *ip++; + } + + t = *ip++; + } while (ip < ip_end); + } + + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; + +eof_found: + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; + +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; + +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +} + +EXPORT_SYMBOL(lzo1x_decompress_safe); + diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h new file mode 100644 index 0000000..b6d482c --- /dev/null +++ b/lib/lzo/lzodefs.h @@ -0,0 +1,43 @@ +/* + * lzodefs.h -- architecture, OS and compiler specific defines + * + * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer + * + * The full LZO package can be found at: + * http://www.oberhumer.com/opensource/lzo/ + * + * Changed for kernel use by: + * Nitin Gupta + * Richard Purdie + */ + +#define LZO_VERSION 0x2020 +#define LZO_VERSION_STRING "2.02" +#define LZO_VERSION_DATE "Oct 17 2005" + +#define M1_MAX_OFFSET 0x0400 +#define M2_MAX_OFFSET 0x0800 +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#define M2_MAX_LEN 8 +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#define D_BITS 14 +#define D_MASK ((1u << D_BITS) - 1) +#define D_HIGH ((D_MASK >> 1) + 1) + +#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \ + << (s1)) ^ (p)[0]) +#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0]) diff --git a/lib/lzo/modules.builtin b/lib/lzo/modules.builtin new file mode 100644 index 0000000..d860562 --- /dev/null +++ b/lib/lzo/modules.builtin @@ -0,0 +1,2 @@ +kernel/lib/lzo/lzo_compress.ko +kernel/lib/lzo/lzo_decompress.ko diff --git a/lib/process_escape_sequence.c b/lib/process_escape_sequence.c new file mode 100644 index 0000000..546edaa --- /dev/null +++ b/lib/process_escape_sequence.c @@ -0,0 +1,78 @@ +/* + * process_esacpe_sequence.c + * + * Copyright (c) 2010 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +int process_escape_sequence(const char *source, char *dest, int destlen) +{ + int i = 0; + + while (*source) { + if (*source == '\\') { + switch (*(source + 1)) { + case 0: + return 0; + case '\\': + dest[i++] = '\\'; + break; + case 'a': + dest[i++] = '\a'; + break; + case 'b': + dest[i++] = '\b'; + break; + case 'n': + dest[i++] = '\n'; + break; + case 'r': + dest[i++] = '\r'; + break; + case 't': + dest[i++] = '\t'; + break; + case 'f': + dest[i++] = '\f'; + break; + case 'e': + dest[i++] = 0x1b; + break; + case 'h': + i += snprintf(dest + i, destlen - i, "%s", CONFIG_BOARDINFO); + break; + case 'w': + i += snprintf(dest + i, destlen - i, "%s", getcwd()); + break; + default: + dest[i++] = '\\'; + dest[i++] = *(source + 1); + } + source++; + } else + dest[i++] = *source; + source++; + if (!(destlen - i)) + break; + } + dest[i] = 0; + return 0; +} + diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 6008305..91ad613 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -547,6 +547,18 @@ } EXPORT_SYMBOL(sprintf); +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; +} +EXPORT_SYMBOL(sprintf); + /* Simplified asprintf. */ char *vasprintf(const char *fmt, va_list ap) { @@ -581,7 +593,7 @@ } EXPORT_SYMBOL(asprintf); -void panic(const char *fmt, ...) +void __noreturn panic(const char *fmt, ...) { va_list args; va_start(args, fmt);