Skip to content

Commit

Permalink
nios2: Add support for compressed kernel
Browse files Browse the repository at this point in the history
Signed-off-by: Ley Foon Tan <[email protected]>
  • Loading branch information
Ley Foon Tan committed Feb 10, 2015
1 parent e8bf5bc commit 0162362
Show file tree
Hide file tree
Showing 8 changed files with 549 additions and 0 deletions.
8 changes: 8 additions & 0 deletions arch/nios2/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ config NIOS2_PASS_CMDLINE
will override "Default kernel command string".
Say N if you are unsure.

config NIOS2_BOOT_LINK_OFFSET
hex "Link address offset for booting"
default "0x00500000"
help
This option allows you to set the link address offset of the zImage.
This can be useful if you are on a board which has a small amount of
memory.

endmenu

menu "Advanced setup"
Expand Down
7 changes: 7 additions & 0 deletions arch/nios2/boot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ $(obj)/vmImage: $(obj)/vmlinux.gz
$(call if_changed,uimage)
@$(kecho) 'Kernel: $@ is ready'

$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@$(kecho) 'Kernel: $@ is ready'

$(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@

# Rule to build device tree blobs
DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE))

Expand Down
19 changes: 19 additions & 0 deletions arch/nios2/boot/compressed/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# create a compressed vmlinux image from the original vmlinux
#

targets := vmlinux head.o misc.o piggy.o vmlinux.lds
asflags-y :=

OBJECTS = $(obj)/head.o $(obj)/misc.o

LDFLAGS_vmlinux := -T

$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:

LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T

$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/../vmlinux.gz FORCE
$(call if_changed,ld)
125 changes: 125 additions & 0 deletions arch/nios2/boot/compressed/console.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (C) 2008-2010 Thomas Chou <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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. If not, see <http://www.gnu.org/licenses/>.
*
*/

#include <linux/io.h>

#if (defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE))\
|| (defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE))
static void *my_ioremap(unsigned long physaddr)
{
return (void *)(physaddr | CONFIG_NIOS2_IO_REGION_BASE);
}
#endif

#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE)

#define ALTERA_JTAGUART_SIZE 8
#define ALTERA_JTAGUART_DATA_REG 0
#define ALTERA_JTAGUART_CONTROL_REG 4
#define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400)
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000)
static void *uartbase;

#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void jtag_putc(int ch)
{
if (readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK)
writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
}
#else
static void jtag_putc(int ch)
{
while ((readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0)
;
writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
}
#endif

static int putchar(int ch)
{
jtag_putc(ch);
return ch;
}

static void console_init(void)
{
uartbase = my_ioremap((unsigned long) JTAG_UART_BASE);
writel(ALTERA_JTAGUART_CONTROL_AC_MSK,
uartbase + ALTERA_JTAGUART_CONTROL_REG);
}

#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE)

#define ALTERA_UART_SIZE 32
#define ALTERA_UART_TXDATA_REG 4
#define ALTERA_UART_STATUS_REG 8
#define ALTERA_UART_DIVISOR_REG 16
#define ALTERA_UART_STATUS_TRDY_MSK (0x40)
static unsigned uartbase;

static void uart_putc(int ch)
{
int i;

for (i = 0; (i < 0x10000); i++) {
if (readw(uartbase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK)
break;
}
writeb(ch, uartbase + ALTERA_UART_TXDATA_REG);
}

static int putchar(int ch)
{
uart_putc(ch);
if (ch == '\n')
uart_putc('\r');
return ch;
}

static void console_init(void)
{
unsigned int baud, baudclk;

uartbase = (unsigned long) my_ioremap((unsigned long) UART0_BASE);
baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
baudclk = UART0_FREQ / baud;
writew(baudclk, uartbase + ALTERA_UART_DIVISOR_REG);
}

#else

static int putchar(int ch)
{
return ch;
}

static void console_init(void)
{
}

#endif

static int puts(const char *s)
{
while (*s)
putchar(*s++);
return 0;
}
117 changes: 117 additions & 0 deletions arch/nios2/boot/compressed/head.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright (C) 2009 Thomas Chou <[email protected]>
*
* Based on arch/nios2/kernel/head.S
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/

/*
* This code can be loaded anywhere, eg FLASH ROM as reset vector,
* as long as output does not overlap it.
*/

#include <linux/linkage.h>
#include <asm/cache.h>

.text
.set noat
ENTRY(_start)
wrctl status, r0 /* disable interrupt */
/* invalidate all instruction cache */
movia r1, NIOS2_ICACHE_SIZE
movui r2, NIOS2_ICACHE_LINE_SIZE
1: initi r1
sub r1, r1, r2
bgt r1, r0, 1b
/* invalidate all data cache */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: initd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b

nextpc r1 /* Find out where we are */
chkadr:
movia r2, chkadr
beq r1, r2, finish_move /* We are running in correct address,
done */
/* move code, r1: src, r2: dest, r3: last dest */
addi r1, r1, (_start - chkadr) /* Source */
movia r2, _start /* Destination */
movia r3, __bss_start /* End of copy */
1: ldw r8, 0(r1) /* load a word from [r1] */
stw r8, 0(r2) /* stort a word to dest [r2] */
addi r1, r1, 4 /* inc the src addr */
addi r2, r2, 4 /* inc the dest addr */
blt r2, r3, 1b
/* flush the data cache after moving */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: flushd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b
movia r1, finish_move
jmp r1 /* jmp to linked address */

finish_move:
/* zero out the .bss segment (uninitialized common data) */
movia r2, __bss_start /* presume nothing is between */
movia r1, _end /* the .bss and _end. */
1: stb r0, 0(r2)
addi r2, r2, 1
bne r1, r2, 1b
/*
* set up the stack pointer, some where higher than _end.
* The stack space must be greater than 32K for decompress.
*/
movia sp, 0x10000
add sp, sp, r1
/* save args passed from u-boot, maybe */
addi sp, sp, -16
stw r4, 0(sp)
stw r5, 4(sp)
stw r6, 8(sp)
stw r7, 12(sp)
/* decompress the kernel */
call decompress_kernel
/* pass saved args to kernel */
ldw r4, 0(sp)
ldw r5, 4(sp)
ldw r6, 8(sp)
ldw r7, 12(sp)

/* flush all data cache after decompressing */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: flushd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b
/* flush all instruction cache */
movia r1, NIOS2_ICACHE_SIZE
movui r2, NIOS2_ICACHE_LINE_SIZE
1: flushi r1
sub r1, r1, r2
bgt r1, r0, 1b
flushp
/* jump to start real kernel */
movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
jmp r1

.balign 512
fake_headers_as_bzImage:
.short 0
.ascii "HdrS"
.short 0x0202
.short 0
.short 0
.byte 0x00, 0x10
.short 0
.byte 0
.byte 1
.byte 0x00, 0x80
.long 0
.long 0
Loading

0 comments on commit 0162362

Please sign in to comment.