aboutsummaryrefslogtreecommitdiffstats
path: root/arch/nios2
diff options
context:
space:
mode:
authorLey Foon Tan <lftan@altera.com>2015-02-10 10:26:34 -0500
committerLey Foon Tan <lftan@altera.com>2015-02-10 10:26:34 -0500
commit01623627a292fbd9dc62e05489153d7f1add7061 (patch)
treedd29d173f5499e5dc015e4b8fa2d5575c406bc6f /arch/nios2
parente8bf5bc776edef44777b13b2eb4461d653519bae (diff)
nios2: Add support for compressed kernel
Signed-off-by: Ley Foon Tan <lftan@altera.com>
Diffstat (limited to 'arch/nios2')
-rw-r--r--arch/nios2/Kconfig8
-rw-r--r--arch/nios2/boot/Makefile7
-rw-r--r--arch/nios2/boot/compressed/Makefile19
-rw-r--r--arch/nios2/boot/compressed/console.c125
-rw-r--r--arch/nios2/boot/compressed/head.S117
-rw-r--r--arch/nios2/boot/compressed/misc.c187
-rw-r--r--arch/nios2/boot/compressed/vmlinux.lds.S58
-rw-r--r--arch/nios2/boot/compressed/vmlinux.scr28
8 files changed, 549 insertions, 0 deletions
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 2361acf6d2b1..f77991ecfd8e 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -134,6 +134,14 @@ config NIOS2_PASS_CMDLINE
134 will override "Default kernel command string". 134 will override "Default kernel command string".
135 Say N if you are unsure. 135 Say N if you are unsure.
136 136
137config 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
137endmenu 145endmenu
138 146
139menu "Advanced setup" 147menu "Advanced setup"
diff --git a/arch/nios2/boot/Makefile b/arch/nios2/boot/Makefile
index 59392dc0bdcb..c899876320df 100644
--- a/arch/nios2/boot/Makefile
+++ b/arch/nios2/boot/Makefile
@@ -24,6 +24,13 @@ $(obj)/vmImage: $(obj)/vmlinux.gz
24 $(call if_changed,uimage) 24 $(call if_changed,uimage)
25 @$(kecho) 'Kernel: $@ is ready' 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# Rule to build device tree blobs 34# Rule to build device tree blobs
28DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) 35DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE))
29 36
diff --git a/arch/nios2/boot/compressed/Makefile b/arch/nios2/boot/compressed/Makefile
new file mode 100644
index 000000000000..5b0fb346d888
--- /dev/null
+++ b/arch/nios2/boot/compressed/Makefile
@@ -0,0 +1,19 @@
1#
2# create a compressed vmlinux image from the original vmlinux
3#
4
5targets := vmlinux head.o misc.o piggy.o vmlinux.lds
6asflags-y :=
7
8OBJECTS = $(obj)/head.o $(obj)/misc.o
9
10LDFLAGS_vmlinux := -T
11
12$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
13 $(call if_changed,ld)
14 @:
15
16LDFLAGS_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)
diff --git a/arch/nios2/boot/compressed/console.c b/arch/nios2/boot/compressed/console.c
new file mode 100644
index 000000000000..2675e879b85a
--- /dev/null
+++ b/arch/nios2/boot/compressed/console.c
@@ -0,0 +1,125 @@
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))
23static 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)
36static void *uartbase;
37
38#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
39static 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
46static 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
55static int putchar(int ch)
56{
57 jtag_putc(ch);
58 return ch;
59}
60
61static 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)
75static unsigned uartbase;
76
77static 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
89static int putchar(int ch)
90{
91 uart_putc(ch);
92 if (ch == '\n')
93 uart_putc('\r');
94 return ch;
95}
96
97static 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
109static int putchar(int ch)
110{
111 return ch;
112}
113
114static void console_init(void)
115{
116}
117
118#endif
119
120static int puts(const char *s)
121{
122 while (*s)
123 putchar(*s++);
124 return 0;
125}
diff --git a/arch/nios2/boot/compressed/head.S b/arch/nios2/boot/compressed/head.S
new file mode 100644
index 000000000000..15c6c48dd909
--- /dev/null
+++ b/arch/nios2/boot/compressed/head.S
@@ -0,0 +1,117 @@
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
22ENTRY(_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
271: 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
331: initd 0(r1)
34 sub r1, r1, r2
35 bgt r1, r0, 1b
36
37 nextpc r1 /* Find out where we are */
38chkadr:
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 */
461: 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
541: 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
60finish_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. */
641: 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
901: 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
961: 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
105fake_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
diff --git a/arch/nios2/boot/compressed/misc.c b/arch/nios2/boot/compressed/misc.c
new file mode 100644
index 000000000000..84377825ef1a
--- /dev/null
+++ b/arch/nios2/boot/compressed/misc.c
@@ -0,0 +1,187 @@
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
42typedef unsigned char uch;
43typedef unsigned short ush;
44typedef unsigned long ulg;
45#define WSIZE 0x8000 /* Window size must be at least 32k, */
46 /* and a power of two */
47
48static uch *inbuf; /* input buffer */
49static uch window[WSIZE]; /* Sliding window buffer */
50
51static unsigned insize; /* valid bytes in inbuf */
52static unsigned inptr; /* index of next byte to be processed in inbuf */
53static 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
82static int fill_inbuf(void);
83static void flush_window(void);
84static void error(char *m);
85
86extern char input_data[];
87extern int input_len;
88
89static long bytes_out;
90static uch *output_data;
91static unsigned long output_ptr;
92
93#include "console.c"
94
95static void error(char *m);
96
97int puts(const char *);
98
99extern int _end;
100static unsigned long free_mem_ptr;
101static unsigned long free_mem_end_ptr;
102
103#define HEAP_SIZE 0x10000
104
105#include "../../../../lib/inflate.c"
106
107void *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
117void *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 */
131static 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 */
146static 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
164static 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
174void 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}
diff --git a/arch/nios2/boot/compressed/vmlinux.lds.S b/arch/nios2/boot/compressed/vmlinux.lds.S
new file mode 100644
index 000000000000..e867b3756059
--- /dev/null
+++ b/arch/nios2/boot/compressed/vmlinux.lds.S
@@ -0,0 +1,58 @@
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
21OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
22
23OUTPUT_ARCH(nios)
24ENTRY(_start) /* Defined in head.S */
25
26SECTIONS
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}
diff --git a/arch/nios2/boot/compressed/vmlinux.scr b/arch/nios2/boot/compressed/vmlinux.scr
new file mode 100644
index 000000000000..28c42f1d127e
--- /dev/null
+++ b/arch/nios2/boot/compressed/vmlinux.scr
@@ -0,0 +1,28 @@
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
19SECTIONS
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}