Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

From: Yinghai Lu
Date: Mon Aug 02 2010 - 18:32:15 EST


On 08/02/2010 02:27 PM, H. Peter Anvin wrote:
> On 08/02/2010 02:08 PM, H. Peter Anvin wrote:
>> On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
>>> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>>>
>>>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>>>
>>>
>>> I just looked at it, it's the fact that we don't relocate the GOT that
>>> is causing problems. It's relatively easy to fix: here is a patch, but
>>> in grand Linus tradition it is completely untested.
>>>
>>
>> Untested indeed... here is one which doesn't clobber live registers.
>>
>
> And of course I got the test backwards... in AT&T syntax, number
> compares you!

updated version

Subject: [PATCH -v4 2/2] x86: more early console output from compressed/misc.c

will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

-v2: define BOOT_BOOT_H to avoid include boot.h
-v3: early_serial_base need to be static in misc.c ?
-v4: create seperate string.c printf.c cmdline.c early_serial_console.c
after hpa's patch that allow global variables in compressed/misc stage

Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>

---
arch/x86/boot/compressed/Makefile | 4 -
arch/x86/boot/compressed/cmdline.c | 21 +++++++
arch/x86/boot/compressed/early_serial_console.c | 4 +
arch/x86/boot/compressed/misc.c | 66 +++++++++++++++---------
arch/x86/boot/compressed/misc.h | 38 +++++++++++++
arch/x86/boot/compressed/printf.c | 4 +
arch/x86/boot/compressed/string.c | 4 +
arch/x86/boot/main.c | 6 --
8 files changed, 118 insertions(+), 29 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/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 ch
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 *
{
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,9 +325,23 @@ asmlinkage void decompress_kernel(void *
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;

+ if (debug) {
+ putstr("decompress_kernel:\n");
+ printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
+ (unsigned long)input_data,
+ (unsigned long)input_data + input_len - 1,
+ (unsigned long)output,
+ (unsigned long)heap,
+ (unsigned long)heap + BOOT_HEAP_SIZE - 1);
+ }
+
if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
error("Destination address inappropriately aligned");
#ifdef CONFIG_X86_64
Index: linux-2.6/arch/x86/boot/main.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/main.c
+++ linux-2.6/arch/x86/boot/main.c
@@ -132,6 +132,8 @@ void main(void)

/* Initialize the early-boot console */
console_init();
+ if (cmdline_find_option_bool("debug"))
+ puts("early console in setup code\n");

/* End of heap check */
init_heap();
@@ -171,10 +173,6 @@ void main(void)
/* Set the video mode */
set_video();

- /* Parse command line for 'quiet' and pass it to decompressor. */
- if (cmdline_find_option_bool("quiet"))
- boot_params.hdr.loadflags |= QUIET_FLAG;
-
/* Do the last things and invoke protected mode */
go_to_protected_mode();
}
Index: linux-2.6/arch/x86/boot/compressed/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/Makefile
+++ linux-2.6/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 printf.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)/printf.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:

Index: linux-2.6/arch/x86/boot/compressed/cmdline.c
===================================================================
--- /dev/null
+++ linux-2.6/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);
+}
Index: linux-2.6/arch/x86/boot/compressed/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/early_serial_console.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+int early_serial_base;
+#include "../early_serial_console.c"
Index: linux-2.6/arch/x86/boot/compressed/misc.h
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/misc.h
@@ -0,0 +1,38 @@
+#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
+
+/* 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
Index: linux-2.6/arch/x86/boot/compressed/printf.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/printf.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../printf.c"
Index: linux-2.6/arch/x86/boot/compressed/string.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/string.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../string.c"
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/