diff options
Diffstat (limited to 'arch/x86/boot/compressed')
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/boot/compressed/cmdline.c | 21 | ||||
-rw-r--r-- | arch/x86/boot/compressed/early_serial_console.c | 5 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_32.S | 13 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 13 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 56 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.h | 39 | ||||
-rw-r--r-- | arch/x86/boot/compressed/mkpiggy.c | 2 | ||||
-rw-r--r-- | arch/x86/boot/compressed/string.c | 2 | ||||
-rw-r--r-- | arch/x86/boot/compressed/vmlinux.lds.S | 10 |
10 files changed, 137 insertions, 28 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index fbb47daf245..0c229551eea 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -4,7 +4,7 @@ # create a compressed vmlinux image from the original vmlinux # -targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o +targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC @@ -23,7 +23,7 @@ LDFLAGS_vmlinux := -T hostprogs-y := mkpiggy -$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE +$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE $(call if_changed,ld) @: diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c new file mode 100644 index 00000000000..cb62f786990 --- /dev/null +++ b/arch/x86/boot/compressed/cmdline.c @@ -0,0 +1,21 @@ +#include "misc.h" + +static unsigned long fs; +static inline void set_fs(unsigned long seg) +{ + fs = seg << 4; /* shift it back */ +} +typedef unsigned long addr_t; +static inline char rdfs8(addr_t addr) +{ + return *((char *)(fs + addr)); +} +#include "../cmdline.c" +int cmdline_find_option(const char *option, char *buffer, int bufsize) +{ + return __cmdline_find_option(real_mode->hdr.cmd_line_ptr, option, buffer, bufsize); +} +int cmdline_find_option_bool(const char *option) +{ + return __cmdline_find_option_bool(real_mode->hdr.cmd_line_ptr, option); +} diff --git a/arch/x86/boot/compressed/early_serial_console.c b/arch/x86/boot/compressed/early_serial_console.c new file mode 100644 index 00000000000..261e81fb958 --- /dev/null +++ b/arch/x86/boot/compressed/early_serial_console.c @@ -0,0 +1,5 @@ +#include "misc.h" + +int early_serial_base; + +#include "../early_serial_console.c" diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index f543b70ffae..67a655a39ce 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -124,6 +124,19 @@ relocated: rep stosl /* + * Adjust our own GOT + */ + leal _got(%ebx), %edx + leal _egot(%ebx), %ecx +1: + cmpl %ecx, %edx + jae 2f + addl %ebx, (%edx) + addl $4, %edx + jmp 1b +2: + +/* * Do the decompression, and jump to the new kernel.. */ leal z_extract_offset_negative(%ebx), %ebp diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index faff0dc9c06..52f85a196fa 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -280,6 +280,19 @@ relocated: rep stosq /* + * Adjust our own GOT + */ + leaq _got(%rip), %rdx + leaq _egot(%rip), %rcx +1: + cmpq %rcx, %rdx + jae 2f + addq %rbx, (%rdx) + addq $8, %rdx + jmp 1b +2: + +/* * Do the decompression, and jump to the new kernel.. */ pushq %rsi /* Save the real mode argument */ diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 51e240779a4..8f7bef8e9ff 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -9,23 +9,7 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ -/* - * we have to be careful, because no indirections are allowed here, and - * paravirt_ops is a kind of one. As it will only run in baremetal anyway, - * we just keep it from happening - */ -#undef CONFIG_PARAVIRT -#ifdef CONFIG_X86_32 -#define _ASM_X86_DESC_H 1 -#endif - -#include <linux/linkage.h> -#include <linux/screen_info.h> -#include <linux/elf.h> -#include <linux/io.h> -#include <asm/page.h> -#include <asm/boot.h> -#include <asm/bootparam.h> +#include "misc.h" /* WARNING!! * This code is compiled with -fPIC and it is relocated dynamically @@ -123,15 +107,13 @@ static void error(char *m); /* * This is set up by the setup-routine at boot-time */ -static struct boot_params *real_mode; /* Pointer to real-mode data */ +struct boot_params *real_mode; /* Pointer to real-mode data */ static int quiet; +static int debug; void *memset(void *s, int c, size_t n); void *memcpy(void *dest, const void *src, size_t n); -static void __putstr(int, const char *); -#define putstr(__x) __putstr(0, __x) - #ifdef CONFIG_X86_64 #define memptr long #else @@ -170,7 +152,21 @@ static void scroll(void) vidmem[i] = ' '; } -static void __putstr(int error, const char *s) +#define XMTRDY 0x20 + +#define TXR 0 /* Transmit register (WRITE) */ +#define LSR 5 /* Line Status */ +static void serial_putchar(int ch) +{ + unsigned timeout = 0xffff; + + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) + cpu_relax(); + + outb(ch, early_serial_base + TXR); +} + +void __putstr(int error, const char *s) { int x, y, pos; char c; @@ -179,6 +175,14 @@ static void __putstr(int error, const char *s) if (!error) return; #endif + if (early_serial_base) { + const char *str = s; + while (*str) { + if (*str == '\n') + serial_putchar('\r'); + serial_putchar(*str++); + } + } if (real_mode->screen_info.orig_video_mode == 0 && lines == 0 && cols == 0) @@ -305,8 +309,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, { real_mode = rmode; - if (real_mode->hdr.loadflags & QUIET_FLAG) + if (cmdline_find_option_bool("quiet")) quiet = 1; + if (cmdline_find_option_bool("debug")) + debug = 1; if (real_mode->screen_info.orig_video_mode == 7) { vidmem = (char *) 0xb0000; @@ -319,6 +325,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, lines = real_mode->screen_info.orig_video_lines; cols = real_mode->screen_info.orig_video_cols; + console_init(); + if (debug) + putstr("early console in decompress_kernel\n"); + free_mem_ptr = heap; /* Heap */ free_mem_end_ptr = heap + BOOT_HEAP_SIZE; diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h new file mode 100644 index 00000000000..3f19c81a620 --- /dev/null +++ b/arch/x86/boot/compressed/misc.h @@ -0,0 +1,39 @@ +#ifndef BOOT_COMPRESSED_MISC_H +#define BOOT_COMPRESSED_MISC_H + +/* + * we have to be careful, because no indirections are allowed here, and + * paravirt_ops is a kind of one. As it will only run in baremetal anyway, + * we just keep it from happening + */ +#undef CONFIG_PARAVIRT +#ifdef CONFIG_X86_32 +#define _ASM_X86_DESC_H 1 +#endif + +#include <linux/linkage.h> +#include <linux/screen_info.h> +#include <linux/elf.h> +#include <linux/io.h> +#include <asm/page.h> +#include <asm/boot.h> +#include <asm/bootparam.h> + +#define BOOT_BOOT_H +#include "../ctype.h" + +/* misc.c */ +extern struct boot_params *real_mode; /* Pointer to real-mode data */ +void __putstr(int error, const char *s); +#define putstr(__x) __putstr(0, __x) +#define puts(__x) __putstr(0, __x) + +/* cmdline.c */ +int cmdline_find_option(const char *option, char *buffer, int bufsize); +int cmdline_find_option_bool(const char *option); + +/* early_serial_console.c */ +extern int early_serial_base; +void console_init(void); + +#endif diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c index bcbd36c4143..5c228129d17 100644 --- a/arch/x86/boot/compressed/mkpiggy.c +++ b/arch/x86/boot/compressed/mkpiggy.c @@ -77,7 +77,7 @@ int main(int argc, char *argv[]) offs += 32*1024 + 18; /* Add 32K + 18 bytes slack */ offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ - printf(".section \".rodata.compressed\",\"a\",@progbits\n"); + printf(".section \".rodata..compressed\",\"a\",@progbits\n"); printf(".globl z_input_len\n"); printf("z_input_len = %lu\n", ilen); printf(".globl z_output_len\n"); diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c new file mode 100644 index 00000000000..19b3e693cd7 --- /dev/null +++ b/arch/x86/boot/compressed/string.c @@ -0,0 +1,2 @@ +#include "misc.h" +#include "../string.c" diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S index a6f1a59a5b0..34d047c9828 100644 --- a/arch/x86/boot/compressed/vmlinux.lds.S +++ b/arch/x86/boot/compressed/vmlinux.lds.S @@ -26,8 +26,8 @@ SECTIONS HEAD_TEXT _ehead = . ; } - .rodata.compressed : { - *(.rodata.compressed) + .rodata..compressed : { + *(.rodata..compressed) } .text : { _text = .; /* Text */ @@ -41,6 +41,12 @@ SECTIONS *(.rodata.*) _erodata = . ; } + .got : { + _got = .; + KEEP(*(.got.plt)) + KEEP(*(.got)) + _egot = .; + } .data : { _data = . ; *(.data) |