Commit db0f6d35 authored by Hirokazu Takata's avatar Hirokazu Takata Committed by Linus Torvalds

[PATCH] m32r: update for m32r-g00ff

This patchset was originally from NIIBE Yutaka.

These patch update the m32r kernel for a new bootloader "m32r-g00ff".  The
"m32r-g00ff" has been written and developed by NIIBE Yutaka, and released
under the GPL from http://www.gniibe.org/.

So far, it supports two types of booting operations,
CF boot and Network boot (HTTP boot).

 * CF boot - boot from CompactFlash or Microdrive(TM)
   We can boot a kernel from CF device.
   To make use of m32r-g00ff, we just put a first stage IPL(initial program
   loader) into a flash memory, and a secondary bootloader into CF media device.
   Currently, LILO-21.4.4 can be used to write m32r-g00ff into the boot sector
   of CF device on a cross development environment.

 * HTTP boot - boot via network with HTTP protocol
   By using m32r-g00ff, we can download and boot a kernel image from 
   a web-server.  The m32r-g00ff downloads a kernel image from a given URL,
   resolving the webserver's IP address by DNS.
   As a preparation, we just place a secondary bootloader binary and
   a kernel image on the webserver.

- Position-independent zImage support;
  this aims at removing constraints of zImage(vmlinuz)'s location.
Signed-off-by: default avatarNIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: default avatarHirokazu Takata <takata@linux-m32r.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 27bd98a6
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
# #
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \ targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \
m32r-sio.o piggy.o vmlinux.lds piggy.o vmlinux.lds
EXTRA_AFLAGS := -traditional EXTRA_AFLAGS := -traditional
OBJECTS = $(obj)/head.o $(obj)/misc.o $(obj)/m32r_sio.o OBJECTS = $(obj)/head.o $(obj)/misc.o
# #
# IMAGE_OFFSET is the load offset of the compression loader # IMAGE_OFFSET is the load offset of the compression loader
...@@ -28,6 +28,8 @@ $(obj)/vmlinux.bin: vmlinux FORCE ...@@ -28,6 +28,8 @@ $(obj)/vmlinux.bin: vmlinux FORCE
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip) $(call if_changed,gzip)
CFLAGS_misc.o += -fpic
LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T
OBJCOPYFLAGS += -R .empty_zero_page OBJCOPYFLAGS += -R .empty_zero_page
......
...@@ -13,20 +13,62 @@ ...@@ -13,20 +13,62 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/assembler.h> #include <asm/assembler.h>
/*
* This code can be loaded anywhere, as long as output will not
* overlap it.
*
* NOTE: This head.S should *NOT* be compiled with -fpic.
*
*/
.global startup .global startup
.global __bss_start, _ebss, end, zimage_data, zimage_len
__ALIGN __ALIGN
startup: startup:
ldi r0, #0x0000 /* SPI, disable EI */ ldi r0, #0x0000 /* SPI, disable EI */
mvtc r0, psw mvtc r0, psw
ldi r12, #-8
bl 1f
.fillinsn
1:
seth r1, #high(CONFIG_MEMORY_START + 0x00400000) /* Start address */
add r12, r14 /* Real address */
sub r12, r1 /* difference */
.global got_len
seth r3, #high(_GLOBAL_OFFSET_TABLE_+8)
or3 r3, r3, #low(_GLOBAL_OFFSET_TABLE_+12)
add r3, r14
/* Update the contents of global offset table */
ldi r1, #low(got_len)
srli r1, #2
beqz r1, 2f
.fillinsn
1:
ld r2, @r3
add r2, r12
st r2, @r3
addi r3, #4
addi r1, #-1
bnez r1, 1b
.fillinsn
2:
/* XXX: resolve plt */
/* /*
* Clear BSS first so that there are no surprises... * Clear BSS first so that there are no surprises...
*/ */
#ifdef CONFIG_ISA_DUAL_ISSUE #ifdef CONFIG_ISA_DUAL_ISSUE
seth r2, #high(__bss_start)
or3 r2, r2, #low(__bss_start)
add r2, r12
seth r3, #high(_ebss)
or3 r3, r3, #low(_ebss)
add r3, r12
sub r3, r2
LDIMM (r2, __bss_start)
LDIMM (r3, _end)
sub r3, r2 ; BSS size in bytes
; R4 = BSS size in longwords (rounded down) ; R4 = BSS size in longwords (rounded down)
mv r4, r3 || ldi r1, #0 mv r4, r3 || ldi r1, #0
srli r4, #4 || addi r2, #-4 srli r4, #4 || addi r2, #-4
...@@ -52,10 +94,13 @@ startup: ...@@ -52,10 +94,13 @@ startup:
.Lendloop2: .Lendloop2:
#else /* not CONFIG_ISA_DUAL_ISSUE */ #else /* not CONFIG_ISA_DUAL_ISSUE */
seth r2, #high(__bss_start)
LDIMM (r2, __bss_start) or3 r2, r2, #low(__bss_start)
LDIMM (r3, _end) add r2, r12
sub r3, r2 ; BSS size in bytes seth r3, #high(_ebss)
or3 r3, r3, #low(_ebss)
add r3, r12
sub r3, r2
mv r4, r3 mv r4, r3
srli r4, #2 ; R4 = BSS size in longwords (rounded down) srli r4, #2 ; R4 = BSS size in longwords (rounded down)
ldi r1, #0 ; clear R1 for longwords store ldi r1, #0 ; clear R1 for longwords store
...@@ -66,27 +111,29 @@ startup: ...@@ -66,27 +111,29 @@ startup:
addi r4, #-1 ; decrement count addi r4, #-1 ; decrement count
bnez r4, .Lloop1 ; go do some more bnez r4, .Lloop1 ; go do some more
.Lendloop1: .Lendloop1:
and3 r4, r3, #3 ; get no. of remaining BSS bytes to clear
addi r2, #4 ; account for pre-inc store
beqz r4, .Lendloop2 ; any more to go?
.Lloop2:
stb r1, @r2 ; yep, zero out another byte
addi r2, #1 ; bump address
addi r4, #-1 ; decrement count
bnez r4, .Lloop2 ; go do some more
.Lendloop2:
#endif /* not CONFIG_ISA_DUAL_ISSUE */ #endif /* not CONFIG_ISA_DUAL_ISSUE */
seth r0, #shigh(stack_start) seth r1, #high(end)
ld sp, @(r0, low(stack_start)) /* set stack point */ or3 r1, r1, #low(end)
add r1, r12
mv sp, r1
/* /*
* decompress the kernel * decompress the kernel
*/ */
mv r0, sp
srli r0, 31 /* MMU is ON or OFF */
seth r1, #high(zimage_data)
or3 r1, r1, #low(zimage_data)
add r1, r12
seth r2, #high(zimage_len)
or3 r2, r2, #low(zimage_len)
mv r3, sp
bl decompress_kernel bl decompress_kernel
#if defined(CONFIG_CHIP_M32700) #if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_VDEC2)
/* Cache flush */ /* Cache flush */
ldi r0, -1 ldi r0, -1
ldi r1, 0xd0 ; invalidate i-cache, copy back d-cache ldi r1, 0xd0 ; invalidate i-cache, copy back d-cache
...@@ -94,8 +141,13 @@ startup: ...@@ -94,8 +141,13 @@ startup:
#else #else
#error "put your cache flush function, please" #error "put your cache flush function, please"
#endif #endif
seth r0, #high(CONFIG_MEMORY_START)
mv r0, sp
srli r0, 31 /* MMU is ON or OFF */
slli r0, 31
or3 r0, r0, #0x2000 or3 r0, r0, #0x2000
seth r1, #high(CONFIG_MEMORY_START)
or r0, r1
jmp r0 jmp r0
.balign 512 .balign 512
......
...@@ -6,12 +6,10 @@ ...@@ -6,12 +6,10 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <asm/m32r.h>
#include <asm/io.h>
void putc(char c); static void putc(char c);
int puts(const char *s) static int puts(const char *s)
{ {
char c; char c;
while ((c = *s++)) putc(c); while ((c = *s++)) putc(c);
...@@ -19,6 +17,9 @@ int puts(const char *s) ...@@ -19,6 +17,9 @@ int puts(const char *s)
} }
#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) #if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT)
#include <asm/m32r.h>
#include <asm/io.h>
#define USE_FPGA_MAP 0 #define USE_FPGA_MAP 0
#if USE_FPGA_MAP #if USE_FPGA_MAP
...@@ -35,7 +36,7 @@ int puts(const char *s) ...@@ -35,7 +36,7 @@ int puts(const char *s)
#define BOOT_SIO0TXB PLD_ESIO0TXB #define BOOT_SIO0TXB PLD_ESIO0TXB
#endif #endif
void putc(char c) static void putc(char c)
{ {
while ((*BOOT_SIO0STS & 0x3) != 0x3) ; while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
...@@ -46,8 +47,17 @@ void putc(char c) ...@@ -46,8 +47,17 @@ void putc(char c)
*BOOT_SIO0TXB = c; *BOOT_SIO0TXB = c;
} }
#else #else
void putc(char c) #define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
static void putc(char c)
{ {
/* do nothing */
while ((*SIO0STS & 0x1) == 0) ;
if (c == '\n') {
*SIO0TXB = '\r';
while ((*SIO0STS & 0x1) == 0) ;
}
*SIO0TXB = c;
} }
#endif #endif
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
* *
* Adapted for SH by Stuart Menefy, Aug 1999 * Adapted for SH by Stuart Menefy, Aug 1999
* *
* Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
*
* 2003-02-12: Support M32R by Takeo Takahashi * 2003-02-12: Support M32R by Takeo Takahashi
* This is based on arch/sh/boot/compressed/misc.c. * This is based on arch/sh/boot/compressed/misc.c.
*/ */
...@@ -38,9 +36,9 @@ typedef unsigned long ulg; ...@@ -38,9 +36,9 @@ typedef unsigned long ulg;
static uch *inbuf; /* input buffer */ static uch *inbuf; /* input buffer */
static uch window[WSIZE]; /* Sliding window buffer */ static uch window[WSIZE]; /* Sliding window buffer */
static unsigned insize; /* valid bytes in inbuf */ static unsigned insize = 0; /* valid bytes in inbuf */
static unsigned inptr; /* index of next byte to be processed in inbuf */ static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
static unsigned outcnt; /* bytes in output buffer */ static unsigned outcnt = 0; /* bytes in output buffer */
/* gzip flag byte */ /* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
...@@ -76,24 +74,18 @@ static void error(char *m); ...@@ -76,24 +74,18 @@ static void error(char *m);
static void gzip_mark(void **); static void gzip_mark(void **);
static void gzip_release(void **); static void gzip_release(void **);
extern char input_data[]; static unsigned char *input_data;
extern int input_len; static int input_len;
static long bytes_out; static long bytes_out = 0;
static uch *output_data; static uch *output_data;
static unsigned long output_ptr; static unsigned long output_ptr = 0;
#include "m32r_sio.c"
static void *malloc(int size); static void *malloc(int size);
static void free(void *where); static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
extern int puts(const char *);
extern int _text; /* Defined in vmlinux.lds.S */
extern int _end;
static unsigned long free_mem_ptr; static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr; static unsigned long free_mem_end_ptr;
...@@ -105,8 +97,8 @@ static void *malloc(int size) ...@@ -105,8 +97,8 @@ static void *malloc(int size)
{ {
void *p; void *p;
if (size <0) error("Malloc error\n"); if (size <0) error("Malloc error");
if (free_mem_ptr == 0) error("Memory error\n"); if (free_mem_ptr == 0) error("Memory error");
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
...@@ -114,7 +106,7 @@ static void *malloc(int size) ...@@ -114,7 +106,7 @@ static void *malloc(int size)
free_mem_ptr += size; free_mem_ptr += size;
if (free_mem_ptr >= free_mem_end_ptr) if (free_mem_ptr >= free_mem_end_ptr)
error("\nOut of memory\n"); error("Out of memory");
return p; return p;
} }
...@@ -159,7 +151,7 @@ void* memcpy(void* __dest, __const void* __src, ...@@ -159,7 +151,7 @@ void* memcpy(void* __dest, __const void* __src,
static int fill_inbuf(void) static int fill_inbuf(void)
{ {
if (insize != 0) { if (insize != 0) {
error("ran out of input data\n"); error("ran out of input data");
} }
inbuf = input_data; inbuf = input_data;
...@@ -199,25 +191,20 @@ static void error(char *x) ...@@ -199,25 +191,20 @@ static void error(char *x)
while(1); /* Halt */ while(1); /* Halt */
} }
#define STACK_SIZE (4096)
long user_stack [STACK_SIZE];
long* stack_start = &user_stack[STACK_SIZE];
/* return decompressed size */ /* return decompressed size */
long decompress_kernel(void) void
decompress_kernel(int mmu_on, unsigned char *zimage_data,
unsigned int zimage_len, unsigned long heap)
{ {
insize = 0; output_data = (unsigned char *)CONFIG_MEMORY_START + 0x2000
inptr = 0; + (mmu_on ? 0x80000000 : 0);
bytes_out = 0; free_mem_ptr = heap;
outcnt = 0;
output_data = 0;
output_ptr = CONFIG_MEMORY_START + 0x2000;
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
input_data = zimage_data;
input_len = zimage_len;
makecrc(); makecrc();
puts("Uncompressing Linux... "); puts("Uncompressing Linux... ");
gunzip(); gunzip();
puts("Ok, booting the kernel.\n"); puts("Ok, booting the kernel.\n");
return bytes_out;
} }
...@@ -8,16 +8,24 @@ SECTIONS ...@@ -8,16 +8,24 @@ SECTIONS
_text = .; _text = .;
.text : { *(.text) } = 0 .text : { *(.text) } = 0
.rodata : { *(.rodata) } .rodata : { *(.rodata) *(.rodata.*) }
_etext = .; _etext = .;
. = ALIGN(32) + (. & (32 - 1)); . = ALIGN(32 / 8);
.data : { *(.data) } .data : { *(.data) }
. = ALIGN(32 / 8);
_got = .;
.got : { *(.got) _egot = .; *(.got.*) }
_edata = .; _edata = .;
. = ALIGN(32 / 8); . = ALIGN(32 / 8);
__bss_start = .; __bss_start = .;
.bss : { *(.bss) } .bss : { *(.bss) *(.sbss) }
. = ALIGN(32 / 8); . = ALIGN(32 / 8);
_end = . ; _ebss = .;
. = ALIGN(4096);
. += 4096;
end = . ;
got_len = (_egot - _got);
} }
SECTIONS SECTIONS
{ {
.data : { .data : {
input_len = .; zimage_data = .;
LONG(input_data_end - input_data) input_data = .;
*(.data) *(.data)
input_data_end = .; zimage_data_end = .;
} }
zimage_len = zimage_data_end - zimage_data;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment