Commit 01623627a292fbd9dc62e05489153d7f1add7061

Authored by Ley Foon Tan
1 parent e8bf5bc776

nios2: Add support for compressed kernel

Signed-off-by: Ley Foon Tan <lftan@altera.com>

Showing 8 changed files with 549 additions and 0 deletions Side-by-side Diff

... ... @@ -134,6 +134,14 @@
134 134 will override "Default kernel command string".
135 135 Say N if you are unsure.
136 136  
  137 +config NIOS2_BOOT_LINK_OFFSET
  138 + hex "Link address offset for booting"
  139 + default "0x00500000"
  140 + help
  141 + This option allows you to set the link address offset of the zImage.
  142 + This can be useful if you are on a board which has a small amount of
  143 + memory.
  144 +
137 145 endmenu
138 146  
139 147 menu "Advanced setup"
arch/nios2/boot/Makefile
... ... @@ -24,6 +24,13 @@
24 24 $(call if_changed,uimage)
25 25 @$(kecho) 'Kernel: $@ is ready'
26 26  
  27 +$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
  28 + $(call if_changed,objcopy)
  29 + @$(kecho) 'Kernel: $@ is ready'
  30 +
  31 +$(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE
  32 + $(Q)$(MAKE) $(build)=$(obj)/compressed $@
  33 +
27 34 # Rule to build device tree blobs
28 35 DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE))
29 36  
arch/nios2/boot/compressed/Makefile
  1 +#
  2 +# create a compressed vmlinux image from the original vmlinux
  3 +#
  4 +
  5 +targets := vmlinux head.o misc.o piggy.o vmlinux.lds
  6 +asflags-y :=
  7 +
  8 +OBJECTS = $(obj)/head.o $(obj)/misc.o
  9 +
  10 +LDFLAGS_vmlinux := -T
  11 +
  12 +$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
  13 + $(call if_changed,ld)
  14 + @:
  15 +
  16 +LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T
  17 +
  18 +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/../vmlinux.gz FORCE
  19 + $(call if_changed,ld)
arch/nios2/boot/compressed/console.c
  1 +/*
  2 + * Copyright (C) 2008-2010 Thomas Chou <thomas@wytron.com.tw>
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 2 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + *
  17 + */
  18 +
  19 +#include <linux/io.h>
  20 +
  21 +#if (defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE))\
  22 + || (defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE))
  23 +static void *my_ioremap(unsigned long physaddr)
  24 +{
  25 + return (void *)(physaddr | CONFIG_NIOS2_IO_REGION_BASE);
  26 +}
  27 +#endif
  28 +
  29 +#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE)
  30 +
  31 +#define ALTERA_JTAGUART_SIZE 8
  32 +#define ALTERA_JTAGUART_DATA_REG 0
  33 +#define ALTERA_JTAGUART_CONTROL_REG 4
  34 +#define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400)
  35 +#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000)
  36 +static void *uartbase;
  37 +
  38 +#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
  39 +static void jtag_putc(int ch)
  40 +{
  41 + if (readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
  42 + ALTERA_JTAGUART_CONTROL_WSPACE_MSK)
  43 + writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
  44 +}
  45 +#else
  46 +static void jtag_putc(int ch)
  47 +{
  48 + while ((readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
  49 + ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0)
  50 + ;
  51 + writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
  52 +}
  53 +#endif
  54 +
  55 +static int putchar(int ch)
  56 +{
  57 + jtag_putc(ch);
  58 + return ch;
  59 +}
  60 +
  61 +static void console_init(void)
  62 +{
  63 + uartbase = my_ioremap((unsigned long) JTAG_UART_BASE);
  64 + writel(ALTERA_JTAGUART_CONTROL_AC_MSK,
  65 + uartbase + ALTERA_JTAGUART_CONTROL_REG);
  66 +}
  67 +
  68 +#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE)
  69 +
  70 +#define ALTERA_UART_SIZE 32
  71 +#define ALTERA_UART_TXDATA_REG 4
  72 +#define ALTERA_UART_STATUS_REG 8
  73 +#define ALTERA_UART_DIVISOR_REG 16
  74 +#define ALTERA_UART_STATUS_TRDY_MSK (0x40)
  75 +static unsigned uartbase;
  76 +
  77 +static void uart_putc(int ch)
  78 +{
  79 + int i;
  80 +
  81 + for (i = 0; (i < 0x10000); i++) {
  82 + if (readw(uartbase + ALTERA_UART_STATUS_REG) &
  83 + ALTERA_UART_STATUS_TRDY_MSK)
  84 + break;
  85 + }
  86 + writeb(ch, uartbase + ALTERA_UART_TXDATA_REG);
  87 +}
  88 +
  89 +static int putchar(int ch)
  90 +{
  91 + uart_putc(ch);
  92 + if (ch == '\n')
  93 + uart_putc('\r');
  94 + return ch;
  95 +}
  96 +
  97 +static void console_init(void)
  98 +{
  99 + unsigned int baud, baudclk;
  100 +
  101 + uartbase = (unsigned long) my_ioremap((unsigned long) UART0_BASE);
  102 + baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
  103 + baudclk = UART0_FREQ / baud;
  104 + writew(baudclk, uartbase + ALTERA_UART_DIVISOR_REG);
  105 +}
  106 +
  107 +#else
  108 +
  109 +static int putchar(int ch)
  110 +{
  111 + return ch;
  112 +}
  113 +
  114 +static void console_init(void)
  115 +{
  116 +}
  117 +
  118 +#endif
  119 +
  120 +static int puts(const char *s)
  121 +{
  122 + while (*s)
  123 + putchar(*s++);
  124 + return 0;
  125 +}
arch/nios2/boot/compressed/head.S
  1 +/*
  2 + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
  3 + *
  4 + * Based on arch/nios2/kernel/head.S
  5 + *
  6 + * This file is subject to the terms and conditions of the GNU General Public
  7 + * License. See the file "COPYING" in the main directory of this archive
  8 + * for more details.
  9 + *
  10 + */
  11 +
  12 +/*
  13 + * This code can be loaded anywhere, eg FLASH ROM as reset vector,
  14 + * as long as output does not overlap it.
  15 + */
  16 +
  17 +#include <linux/linkage.h>
  18 +#include <asm/cache.h>
  19 +
  20 + .text
  21 + .set noat
  22 +ENTRY(_start)
  23 + wrctl status, r0 /* disable interrupt */
  24 + /* invalidate all instruction cache */
  25 + movia r1, NIOS2_ICACHE_SIZE
  26 + movui r2, NIOS2_ICACHE_LINE_SIZE
  27 +1: initi r1
  28 + sub r1, r1, r2
  29 + bgt r1, r0, 1b
  30 + /* invalidate all data cache */
  31 + movia r1, NIOS2_DCACHE_SIZE
  32 + movui r2, NIOS2_DCACHE_LINE_SIZE
  33 +1: initd 0(r1)
  34 + sub r1, r1, r2
  35 + bgt r1, r0, 1b
  36 +
  37 + nextpc r1 /* Find out where we are */
  38 +chkadr:
  39 + movia r2, chkadr
  40 + beq r1, r2, finish_move /* We are running in correct address,
  41 + done */
  42 + /* move code, r1: src, r2: dest, r3: last dest */
  43 + addi r1, r1, (_start - chkadr) /* Source */
  44 + movia r2, _start /* Destination */
  45 + movia r3, __bss_start /* End of copy */
  46 +1: ldw r8, 0(r1) /* load a word from [r1] */
  47 + stw r8, 0(r2) /* stort a word to dest [r2] */
  48 + addi r1, r1, 4 /* inc the src addr */
  49 + addi r2, r2, 4 /* inc the dest addr */
  50 + blt r2, r3, 1b
  51 + /* flush the data cache after moving */
  52 + movia r1, NIOS2_DCACHE_SIZE
  53 + movui r2, NIOS2_DCACHE_LINE_SIZE
  54 +1: flushd 0(r1)
  55 + sub r1, r1, r2
  56 + bgt r1, r0, 1b
  57 + movia r1, finish_move
  58 + jmp r1 /* jmp to linked address */
  59 +
  60 +finish_move:
  61 + /* zero out the .bss segment (uninitialized common data) */
  62 + movia r2, __bss_start /* presume nothing is between */
  63 + movia r1, _end /* the .bss and _end. */
  64 +1: stb r0, 0(r2)
  65 + addi r2, r2, 1
  66 + bne r1, r2, 1b
  67 + /*
  68 + * set up the stack pointer, some where higher than _end.
  69 + * The stack space must be greater than 32K for decompress.
  70 + */
  71 + movia sp, 0x10000
  72 + add sp, sp, r1
  73 + /* save args passed from u-boot, maybe */
  74 + addi sp, sp, -16
  75 + stw r4, 0(sp)
  76 + stw r5, 4(sp)
  77 + stw r6, 8(sp)
  78 + stw r7, 12(sp)
  79 + /* decompress the kernel */
  80 + call decompress_kernel
  81 + /* pass saved args to kernel */
  82 + ldw r4, 0(sp)
  83 + ldw r5, 4(sp)
  84 + ldw r6, 8(sp)
  85 + ldw r7, 12(sp)
  86 +
  87 + /* flush all data cache after decompressing */
  88 + movia r1, NIOS2_DCACHE_SIZE
  89 + movui r2, NIOS2_DCACHE_LINE_SIZE
  90 +1: flushd 0(r1)
  91 + sub r1, r1, r2
  92 + bgt r1, r0, 1b
  93 + /* flush all instruction cache */
  94 + movia r1, NIOS2_ICACHE_SIZE
  95 + movui r2, NIOS2_ICACHE_LINE_SIZE
  96 +1: flushi r1
  97 + sub r1, r1, r2
  98 + bgt r1, r0, 1b
  99 + flushp
  100 + /* jump to start real kernel */
  101 + movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
  102 + jmp r1
  103 +
  104 + .balign 512
  105 +fake_headers_as_bzImage:
  106 + .short 0
  107 + .ascii "HdrS"
  108 + .short 0x0202
  109 + .short 0
  110 + .short 0
  111 + .byte 0x00, 0x10
  112 + .short 0
  113 + .byte 0
  114 + .byte 1
  115 + .byte 0x00, 0x80
  116 + .long 0
  117 + .long 0
arch/nios2/boot/compressed/misc.c
  1 +/*
  2 + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
  3 + *
  4 + * This is a collection of several routines from gzip-1.0.3
  5 + * adapted for Linux.
  6 + *
  7 + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  8 + *
  9 + * Adapted for SH by Stuart Menefy, Aug 1999
  10 + *
  11 + * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
  12 + *
  13 + * Based on arch/sh/boot/compressed/misc.c
  14 + *
  15 + * This program is free software; you can redistribute it and/or modify
  16 + * it under the terms of the GNU General Public License as published by
  17 + * the Free Software Foundation; either version 2 of the License, or
  18 + * (at your option) any later version.
  19 + *
  20 + * This program is distributed in the hope that it will be useful,
  21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23 + * GNU General Public License for more details.
  24 + *
  25 + * You should have received a copy of the GNU General Public License
  26 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  27 + *
  28 + */
  29 +
  30 +#include <linux/string.h>
  31 +
  32 +/*
  33 + * gzip declarations
  34 + */
  35 +#define OF(args) args
  36 +#define STATIC static
  37 +
  38 +#undef memset
  39 +#undef memcpy
  40 +#define memzero(s, n) memset((s), 0, (n))
  41 +
  42 +typedef unsigned char uch;
  43 +typedef unsigned short ush;
  44 +typedef unsigned long ulg;
  45 +#define WSIZE 0x8000 /* Window size must be at least 32k, */
  46 + /* and a power of two */
  47 +
  48 +static uch *inbuf; /* input buffer */
  49 +static uch window[WSIZE]; /* Sliding window buffer */
  50 +
  51 +static unsigned insize; /* valid bytes in inbuf */
  52 +static unsigned inptr; /* index of next byte to be processed in inbuf */
  53 +static unsigned outcnt; /* bytes in output buffer */
  54 +
  55 +/* gzip flag byte */
  56 +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
  57 +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip
  58 + file */
  59 +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
  60 +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
  61 +#define COMMENT 0x10 /* bit 4 set: file comment present */
  62 +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
  63 +#define RESERVED 0xC0 /* bit 6,7: reserved */
  64 +
  65 +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  66 +
  67 +#ifdef DEBUG
  68 +# define Assert(cond, msg) {if (!(cond)) error(msg); }
  69 +# define Trace(x) fprintf x
  70 +# define Tracev(x) {if (verbose) fprintf x ; }
  71 +# define Tracevv(x) {if (verbose > 1) fprintf x ; }
  72 +# define Tracec(c, x) {if (verbose && (c)) fprintf x ; }
  73 +# define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; }
  74 +#else
  75 +# define Assert(cond, msg)
  76 +# define Trace(x)
  77 +# define Tracev(x)
  78 +# define Tracevv(x)
  79 +# define Tracec(c, x)
  80 +# define Tracecv(c, x)
  81 +#endif
  82 +static int fill_inbuf(void);
  83 +static void flush_window(void);
  84 +static void error(char *m);
  85 +
  86 +extern char input_data[];
  87 +extern int input_len;
  88 +
  89 +static long bytes_out;
  90 +static uch *output_data;
  91 +static unsigned long output_ptr;
  92 +
  93 +#include "console.c"
  94 +
  95 +static void error(char *m);
  96 +
  97 +int puts(const char *);
  98 +
  99 +extern int _end;
  100 +static unsigned long free_mem_ptr;
  101 +static unsigned long free_mem_end_ptr;
  102 +
  103 +#define HEAP_SIZE 0x10000
  104 +
  105 +#include "../../../../lib/inflate.c"
  106 +
  107 +void *memset(void *s, int c, size_t n)
  108 +{
  109 + int i;
  110 + char *ss = (char *)s;
  111 +
  112 + for (i = 0; i < n; i++)
  113 + ss[i] = c;
  114 + return s;
  115 +}
  116 +
  117 +void *memcpy(void *__dest, __const void *__src, size_t __n)
  118 +{
  119 + int i;
  120 + char *d = (char *)__dest, *s = (char *)__src;
  121 +
  122 + for (i = 0; i < __n; i++)
  123 + d[i] = s[i];
  124 + return __dest;
  125 +}
  126 +
  127 +/*
  128 + * Fill the input buffer. This is called only when the buffer is empty
  129 + * and at least one byte is really needed.
  130 + */
  131 +static int fill_inbuf(void)
  132 +{
  133 + if (insize != 0)
  134 + error("ran out of input data");
  135 +
  136 + inbuf = input_data;
  137 + insize = input_len;
  138 + inptr = 1;
  139 + return inbuf[0];
  140 +}
  141 +
  142 +/*
  143 + * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  144 + * (Used for the decompressed data only.)
  145 + */
  146 +static void flush_window(void)
  147 +{
  148 + ulg c = crc; /* temporary variable */
  149 + unsigned n;
  150 + uch *in, *out, ch;
  151 +
  152 + in = window;
  153 + out = &output_data[output_ptr];
  154 + for (n = 0; n < outcnt; n++) {
  155 + ch = *out++ = *in++;
  156 + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  157 + }
  158 + crc = c;
  159 + bytes_out += (ulg)outcnt;
  160 + output_ptr += (ulg)outcnt;
  161 + outcnt = 0;
  162 +}
  163 +
  164 +static void error(char *x)
  165 +{
  166 + puts("\nERROR\n");
  167 + puts(x);
  168 + puts("\n\n -- System halted");
  169 +
  170 + while (1) /* Halt */
  171 + ;
  172 +}
  173 +
  174 +void decompress_kernel(void)
  175 +{
  176 + output_data = (void *) (CONFIG_NIOS2_MEM_BASE |
  177 + CONFIG_NIOS2_KERNEL_REGION_BASE);
  178 + output_ptr = 0;
  179 + free_mem_ptr = (unsigned long)&_end;
  180 + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
  181 +
  182 + console_init();
  183 + makecrc();
  184 + puts("Uncompressing Linux... ");
  185 + gunzip();
  186 + puts("Ok, booting the kernel.\n");
  187 +}
arch/nios2/boot/compressed/vmlinux.lds.S
  1 +/*
  2 + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 2 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + *
  17 + */
  18 +
  19 +#include <asm-generic/vmlinux.lds.h>
  20 +
  21 +OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
  22 +
  23 +OUTPUT_ARCH(nios)
  24 +ENTRY(_start) /* Defined in head.S */
  25 +
  26 +SECTIONS
  27 +{
  28 + . = (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_BOOT_LINK_OFFSET) | \
  29 + CONFIG_NIOS2_KERNEL_REGION_BASE;
  30 +
  31 + _text = .;
  32 + .text : { *(.text) } = 0
  33 + .rodata : { *(.rodata) *(.rodata.*) }
  34 + _etext = .;
  35 +
  36 + . = ALIGN(32 / 8);
  37 + .data : { *(.data) }
  38 + . = ALIGN(32 / 8);
  39 + _got = .;
  40 + .got : {
  41 + *(.got.plt)
  42 + *(.igot.plt)
  43 + *(.got)
  44 + *(.igot)
  45 + }
  46 + _egot = .;
  47 + _edata = .;
  48 +
  49 + . = ALIGN(32 / 8);
  50 + __bss_start = .;
  51 + .bss : { *(.bss) *(.sbss) }
  52 + . = ALIGN(32 / 8);
  53 + _ebss = .;
  54 + end = . ;
  55 + _end = . ;
  56 +
  57 + got_len = (_egot - _got);
  58 +}
arch/nios2/boot/compressed/vmlinux.scr
  1 +/*
  2 + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 2 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + *
  17 + */
  18 +
  19 +SECTIONS
  20 +{
  21 + .data : {
  22 + input_len = .;
  23 + LONG(input_data_end - input_data) input_data = .;
  24 + *(.data)
  25 + . = ALIGN(4);
  26 + input_data_end = .;
  27 + }
  28 +}