Merge branch 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86, setup: move isdigit.h to ctype.h, header files on top. x86, setup: enable early console output from the decompressor x86, setup: reorganize the early console setup x86, setup: Allow global variables and functions in the decompressor x86, setup: Only set early_serial_base after port is initialized x86, setup: Make the setup code also accept console=uart8250 x86, setup: Early-boot serial I/O support
This commit is contained in:
@@ -26,10 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
|
|||||||
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
|
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
|
||||||
subdir- := compressed
|
subdir- := compressed
|
||||||
|
|
||||||
setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
|
setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
|
||||||
setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
|
setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o
|
||||||
setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
|
setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
|
||||||
setup-y += version.o
|
setup-y += video-mode.o version.o
|
||||||
setup-$(CONFIG_X86_APM_BOOT) += apm.o
|
setup-$(CONFIG_X86_APM_BOOT) += apm.o
|
||||||
|
|
||||||
# The link order of the video-*.o modules can matter. In particular,
|
# The link order of the video-*.o modules can matter. In particular,
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#include <asm/processor-flags.h>
|
#include <asm/processor-flags.h>
|
||||||
|
#include "ctype.h"
|
||||||
|
|
||||||
/* Useful macros */
|
/* Useful macros */
|
||||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||||
@@ -37,6 +38,8 @@
|
|||||||
extern struct setup_header hdr;
|
extern struct setup_header hdr;
|
||||||
extern struct boot_params boot_params;
|
extern struct boot_params boot_params;
|
||||||
|
|
||||||
|
#define cpu_relax() asm volatile("rep; nop")
|
||||||
|
|
||||||
/* Basic port I/O */
|
/* Basic port I/O */
|
||||||
static inline void outb(u8 v, u16 port)
|
static inline void outb(u8 v, u16 port)
|
||||||
{
|
{
|
||||||
@@ -198,11 +201,6 @@ static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int isdigit(int ch)
|
|
||||||
{
|
|
||||||
return (ch >= '0') && (ch <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Heap -- available for dynamic lists. */
|
/* Heap -- available for dynamic lists. */
|
||||||
extern char _end[];
|
extern char _end[];
|
||||||
extern char *HEAP;
|
extern char *HEAP;
|
||||||
@@ -287,8 +285,18 @@ struct biosregs {
|
|||||||
void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
|
void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
|
||||||
|
|
||||||
/* cmdline.c */
|
/* cmdline.c */
|
||||||
int cmdline_find_option(const char *option, char *buffer, int bufsize);
|
int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize);
|
||||||
int cmdline_find_option_bool(const char *option);
|
int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option);
|
||||||
|
static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
|
||||||
|
{
|
||||||
|
return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cmdline_find_option_bool(const char *option)
|
||||||
|
{
|
||||||
|
return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* cpu.c, cpucheck.c */
|
/* cpu.c, cpucheck.c */
|
||||||
struct cpu_features {
|
struct cpu_features {
|
||||||
@@ -300,6 +308,10 @@ extern struct cpu_features cpu;
|
|||||||
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
|
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
|
||||||
int validate_cpu(void);
|
int validate_cpu(void);
|
||||||
|
|
||||||
|
/* early_serial_console.c */
|
||||||
|
extern int early_serial_base;
|
||||||
|
void console_init(void);
|
||||||
|
|
||||||
/* edd.c */
|
/* edd.c */
|
||||||
void query_edd(void);
|
void query_edd(void);
|
||||||
|
|
||||||
@@ -329,8 +341,10 @@ void initregs(struct biosregs *regs);
|
|||||||
|
|
||||||
/* string.c */
|
/* string.c */
|
||||||
int strcmp(const char *str1, const char *str2);
|
int strcmp(const char *str1, const char *str2);
|
||||||
|
int strncmp(const char *cs, const char *ct, size_t count);
|
||||||
size_t strnlen(const char *s, size_t maxlen);
|
size_t strnlen(const char *s, size_t maxlen);
|
||||||
unsigned int atou(const char *s);
|
unsigned int atou(const char *s);
|
||||||
|
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);
|
||||||
|
|
||||||
/* tty.c */
|
/* tty.c */
|
||||||
void puts(const char *);
|
void puts(const char *);
|
||||||
|
@@ -27,9 +27,8 @@ static inline int myisspace(u8 c)
|
|||||||
* Returns the length of the argument (regardless of if it was
|
* Returns the length of the argument (regardless of if it was
|
||||||
* truncated to fit in the buffer), or -1 on not found.
|
* truncated to fit in the buffer), or -1 on not found.
|
||||||
*/
|
*/
|
||||||
int cmdline_find_option(const char *option, char *buffer, int bufsize)
|
int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
|
||||||
{
|
{
|
||||||
u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
|
|
||||||
addr_t cptr;
|
addr_t cptr;
|
||||||
char c;
|
char c;
|
||||||
int len = -1;
|
int len = -1;
|
||||||
@@ -100,9 +99,8 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
|
|||||||
* Returns the position of that option (starts counting with 1)
|
* Returns the position of that option (starts counting with 1)
|
||||||
* or 0 on not found
|
* or 0 on not found
|
||||||
*/
|
*/
|
||||||
int cmdline_find_option_bool(const char *option)
|
int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
|
||||||
{
|
{
|
||||||
u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
|
|
||||||
addr_t cptr;
|
addr_t cptr;
|
||||||
char c;
|
char c;
|
||||||
int pos = 0, wstart = 0;
|
int pos = 0, wstart = 0;
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
# create a compressed vmlinux image from the original vmlinux
|
# 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 := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
|
||||||
KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
|
KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
|
||||||
@@ -23,7 +23,7 @@ LDFLAGS_vmlinux := -T
|
|||||||
|
|
||||||
hostprogs-y := mkpiggy
|
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)
|
$(call if_changed,ld)
|
||||||
@:
|
@:
|
||||||
|
|
||||||
|
21
arch/x86/boot/compressed/cmdline.c
Normal file
21
arch/x86/boot/compressed/cmdline.c
Normal file
@@ -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);
|
||||||
|
}
|
5
arch/x86/boot/compressed/early_serial_console.c
Normal file
5
arch/x86/boot/compressed/early_serial_console.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
int early_serial_base;
|
||||||
|
|
||||||
|
#include "../early_serial_console.c"
|
@@ -123,6 +123,19 @@ relocated:
|
|||||||
shrl $2, %ecx
|
shrl $2, %ecx
|
||||||
rep stosl
|
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..
|
* Do the decompression, and jump to the new kernel..
|
||||||
*/
|
*/
|
||||||
|
@@ -279,6 +279,19 @@ relocated:
|
|||||||
shrq $3, %rcx
|
shrq $3, %rcx
|
||||||
rep stosq
|
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..
|
* Do the decompression, and jump to the new kernel..
|
||||||
*/
|
*/
|
||||||
|
@@ -9,23 +9,7 @@
|
|||||||
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
|
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#include "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>
|
|
||||||
|
|
||||||
/* WARNING!!
|
/* WARNING!!
|
||||||
* This code is compiled with -fPIC and it is relocated dynamically
|
* 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
|
* 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 quiet;
|
||||||
|
static int debug;
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n);
|
void *memset(void *s, int c, size_t n);
|
||||||
void *memcpy(void *dest, const void *src, 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
|
#ifdef CONFIG_X86_64
|
||||||
#define memptr long
|
#define memptr long
|
||||||
#else
|
#else
|
||||||
@@ -170,7 +152,21 @@ static void scroll(void)
|
|||||||
vidmem[i] = ' ';
|
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;
|
int x, y, pos;
|
||||||
char c;
|
char c;
|
||||||
@@ -179,6 +175,14 @@ static void __putstr(int error, const char *s)
|
|||||||
if (!error)
|
if (!error)
|
||||||
return;
|
return;
|
||||||
#endif
|
#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 &&
|
if (real_mode->screen_info.orig_video_mode == 0 &&
|
||||||
lines == 0 && cols == 0)
|
lines == 0 && cols == 0)
|
||||||
@@ -305,8 +309,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
|
|||||||
{
|
{
|
||||||
real_mode = rmode;
|
real_mode = rmode;
|
||||||
|
|
||||||
if (real_mode->hdr.loadflags & QUIET_FLAG)
|
if (cmdline_find_option_bool("quiet"))
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
|
if (cmdline_find_option_bool("debug"))
|
||||||
|
debug = 1;
|
||||||
|
|
||||||
if (real_mode->screen_info.orig_video_mode == 7) {
|
if (real_mode->screen_info.orig_video_mode == 7) {
|
||||||
vidmem = (char *) 0xb0000;
|
vidmem = (char *) 0xb0000;
|
||||||
@@ -319,6 +325,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
|
|||||||
lines = real_mode->screen_info.orig_video_lines;
|
lines = real_mode->screen_info.orig_video_lines;
|
||||||
cols = real_mode->screen_info.orig_video_cols;
|
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_ptr = heap; /* Heap */
|
||||||
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
|
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
|
||||||
|
|
||||||
|
39
arch/x86/boot/compressed/misc.h
Normal file
39
arch/x86/boot/compressed/misc.h
Normal file
@@ -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
|
2
arch/x86/boot/compressed/string.c
Normal file
2
arch/x86/boot/compressed/string.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include "misc.h"
|
||||||
|
#include "../string.c"
|
@@ -41,6 +41,12 @@ SECTIONS
|
|||||||
*(.rodata.*)
|
*(.rodata.*)
|
||||||
_erodata = . ;
|
_erodata = . ;
|
||||||
}
|
}
|
||||||
|
.got : {
|
||||||
|
_got = .;
|
||||||
|
KEEP(*(.got.plt))
|
||||||
|
KEEP(*(.got))
|
||||||
|
_egot = .;
|
||||||
|
}
|
||||||
.data : {
|
.data : {
|
||||||
_data = . ;
|
_data = . ;
|
||||||
*(.data)
|
*(.data)
|
||||||
|
21
arch/x86/boot/ctype.h
Normal file
21
arch/x86/boot/ctype.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef BOOT_ISDIGIT_H
|
||||||
|
|
||||||
|
#define BOOT_ISDIGIT_H
|
||||||
|
|
||||||
|
static inline int isdigit(int ch)
|
||||||
|
{
|
||||||
|
return (ch >= '0') && (ch <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isxdigit(int ch)
|
||||||
|
{
|
||||||
|
if (isdigit(ch))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((ch >= 'a') && (ch <= 'f'))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (ch >= 'A') && (ch <= 'F');
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
139
arch/x86/boot/early_serial_console.c
Normal file
139
arch/x86/boot/early_serial_console.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#include "boot.h"
|
||||||
|
|
||||||
|
#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
|
||||||
|
|
||||||
|
#define XMTRDY 0x20
|
||||||
|
|
||||||
|
#define DLAB 0x80
|
||||||
|
|
||||||
|
#define TXR 0 /* Transmit register (WRITE) */
|
||||||
|
#define RXR 0 /* Receive register (READ) */
|
||||||
|
#define IER 1 /* Interrupt Enable */
|
||||||
|
#define IIR 2 /* Interrupt ID */
|
||||||
|
#define FCR 2 /* FIFO control */
|
||||||
|
#define LCR 3 /* Line control */
|
||||||
|
#define MCR 4 /* Modem control */
|
||||||
|
#define LSR 5 /* Line Status */
|
||||||
|
#define MSR 6 /* Modem Status */
|
||||||
|
#define DLL 0 /* Divisor Latch Low */
|
||||||
|
#define DLH 1 /* Divisor latch High */
|
||||||
|
|
||||||
|
#define DEFAULT_BAUD 9600
|
||||||
|
|
||||||
|
static void early_serial_init(int port, int baud)
|
||||||
|
{
|
||||||
|
unsigned char c;
|
||||||
|
unsigned divisor;
|
||||||
|
|
||||||
|
outb(0x3, port + LCR); /* 8n1 */
|
||||||
|
outb(0, port + IER); /* no interrupt */
|
||||||
|
outb(0, port + FCR); /* no fifo */
|
||||||
|
outb(0x3, port + MCR); /* DTR + RTS */
|
||||||
|
|
||||||
|
divisor = 115200 / baud;
|
||||||
|
c = inb(port + LCR);
|
||||||
|
outb(c | DLAB, port + LCR);
|
||||||
|
outb(divisor & 0xff, port + DLL);
|
||||||
|
outb((divisor >> 8) & 0xff, port + DLH);
|
||||||
|
outb(c & ~DLAB, port + LCR);
|
||||||
|
|
||||||
|
early_serial_base = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_earlyprintk(void)
|
||||||
|
{
|
||||||
|
int baud = DEFAULT_BAUD;
|
||||||
|
char arg[32];
|
||||||
|
int pos = 0;
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
|
if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
if (!strncmp(arg, "serial", 6)) {
|
||||||
|
port = DEFAULT_SERIAL_PORT;
|
||||||
|
pos += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[pos] == ',')
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
if (!strncmp(arg, "ttyS", 4)) {
|
||||||
|
static const int bases[] = { 0x3f8, 0x2f8 };
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (!strncmp(arg + pos, "ttyS", 4))
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
if (arg[pos++] == '1')
|
||||||
|
idx = 1;
|
||||||
|
|
||||||
|
port = bases[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[pos] == ',')
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
baud = simple_strtoull(arg + pos, &e, 0);
|
||||||
|
if (baud == 0 || arg + pos == e)
|
||||||
|
baud = DEFAULT_BAUD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port)
|
||||||
|
early_serial_init(port, baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BASE_BAUD (1843200/16)
|
||||||
|
static unsigned int probe_baud(int port)
|
||||||
|
{
|
||||||
|
unsigned char lcr, dll, dlh;
|
||||||
|
unsigned int quot;
|
||||||
|
|
||||||
|
lcr = inb(port + LCR);
|
||||||
|
outb(lcr | DLAB, port + LCR);
|
||||||
|
dll = inb(port + DLL);
|
||||||
|
dlh = inb(port + DLH);
|
||||||
|
outb(lcr, port + LCR);
|
||||||
|
quot = (dlh << 8) | dll;
|
||||||
|
|
||||||
|
return BASE_BAUD / quot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_console_uart8250(void)
|
||||||
|
{
|
||||||
|
char optstr[64], *options;
|
||||||
|
int baud = DEFAULT_BAUD;
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* console=uart8250,io,0x3f8,115200n8
|
||||||
|
* need to make sure it is last one console !
|
||||||
|
*/
|
||||||
|
if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
options = optstr;
|
||||||
|
|
||||||
|
if (!strncmp(options, "uart8250,io,", 12))
|
||||||
|
port = simple_strtoull(options + 12, &options, 0);
|
||||||
|
else if (!strncmp(options, "uart,io,", 8))
|
||||||
|
port = simple_strtoull(options + 8, &options, 0);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (options && (options[0] == ','))
|
||||||
|
baud = simple_strtoull(options + 1, &options, 0);
|
||||||
|
else
|
||||||
|
baud = probe_baud(port);
|
||||||
|
|
||||||
|
if (port)
|
||||||
|
early_serial_init(port, baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void console_init(void)
|
||||||
|
{
|
||||||
|
parse_earlyprintk();
|
||||||
|
|
||||||
|
if (!early_serial_base)
|
||||||
|
parse_console_uart8250();
|
||||||
|
}
|
@@ -130,6 +130,11 @@ void main(void)
|
|||||||
/* First, copy the boot header into the "zeropage" */
|
/* First, copy the boot header into the "zeropage" */
|
||||||
copy_boot_params();
|
copy_boot_params();
|
||||||
|
|
||||||
|
/* Initialize the early-boot console */
|
||||||
|
console_init();
|
||||||
|
if (cmdline_find_option_bool("debug"))
|
||||||
|
puts("early console in setup code\n");
|
||||||
|
|
||||||
/* End of heap check */
|
/* End of heap check */
|
||||||
init_heap();
|
init_heap();
|
||||||
|
|
||||||
@@ -168,10 +173,6 @@ void main(void)
|
|||||||
/* Set the video mode */
|
/* Set the video mode */
|
||||||
set_video();
|
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 */
|
/* Do the last things and invoke protected mode */
|
||||||
go_to_protected_mode();
|
go_to_protected_mode();
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
|
|||||||
#define SMALL 32 /* Must be 32 == 0x20 */
|
#define SMALL 32 /* Must be 32 == 0x20 */
|
||||||
#define SPECIAL 64 /* 0x */
|
#define SPECIAL 64 /* 0x */
|
||||||
|
|
||||||
#define do_div(n,base) ({ \
|
#define __do_div(n, base) ({ \
|
||||||
int __res; \
|
int __res; \
|
||||||
__res = ((unsigned long) n) % (unsigned) base; \
|
__res = ((unsigned long) n) % (unsigned) base; \
|
||||||
n = ((unsigned long) n) / (unsigned) base; \
|
n = ((unsigned long) n) / (unsigned) base; \
|
||||||
@@ -83,7 +83,7 @@ static char *number(char *str, long num, int base, int size, int precision,
|
|||||||
tmp[i++] = '0';
|
tmp[i++] = '0';
|
||||||
else
|
else
|
||||||
while (num != 0)
|
while (num != 0)
|
||||||
tmp[i++] = (digits[do_div(num, base)] | locase);
|
tmp[i++] = (digits[__do_div(num, base)] | locase);
|
||||||
if (i > precision)
|
if (i > precision)
|
||||||
precision = i;
|
precision = i;
|
||||||
size -= precision;
|
size -= precision;
|
||||||
|
@@ -30,6 +30,22 @@ int strcmp(const char *str1, const char *str2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strncmp(const char *cs, const char *ct, size_t count)
|
||||||
|
{
|
||||||
|
unsigned char c1, c2;
|
||||||
|
|
||||||
|
while (count) {
|
||||||
|
c1 = *cs++;
|
||||||
|
c2 = *ct++;
|
||||||
|
if (c1 != c2)
|
||||||
|
return c1 < c2 ? -1 : 1;
|
||||||
|
if (!c1)
|
||||||
|
break;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t strnlen(const char *s, size_t maxlen)
|
size_t strnlen(const char *s, size_t maxlen)
|
||||||
{
|
{
|
||||||
const char *es = s;
|
const char *es = s;
|
||||||
@@ -48,3 +64,50 @@ unsigned int atou(const char *s)
|
|||||||
i = i * 10 + (*s++ - '0');
|
i = i * 10 + (*s++ - '0');
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Works only for digits and letters, but small and fast */
|
||||||
|
#define TOLOWER(x) ((x) | 0x20)
|
||||||
|
|
||||||
|
static unsigned int simple_guess_base(const char *cp)
|
||||||
|
{
|
||||||
|
if (cp[0] == '0') {
|
||||||
|
if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
|
||||||
|
return 16;
|
||||||
|
else
|
||||||
|
return 8;
|
||||||
|
} else {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* simple_strtoull - convert a string to an unsigned long long
|
||||||
|
* @cp: The start of the string
|
||||||
|
* @endp: A pointer to the end of the parsed string will be placed here
|
||||||
|
* @base: The number base to use
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
|
||||||
|
{
|
||||||
|
unsigned long long result = 0;
|
||||||
|
|
||||||
|
if (!base)
|
||||||
|
base = simple_guess_base(cp);
|
||||||
|
|
||||||
|
if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
|
||||||
|
cp += 2;
|
||||||
|
|
||||||
|
while (isxdigit(*cp)) {
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
|
||||||
|
if (value >= base)
|
||||||
|
break;
|
||||||
|
result = result * base + value;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)cp;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -10,24 +10,37 @@
|
|||||||
* ----------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Very simple screen I/O
|
* Very simple screen and serial I/O
|
||||||
* XXX: Probably should add very simple serial I/O?
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
|
|
||||||
|
int early_serial_base;
|
||||||
|
|
||||||
|
#define XMTRDY 0x20
|
||||||
|
|
||||||
|
#define TXR 0 /* Transmit register (WRITE) */
|
||||||
|
#define LSR 5 /* Line Status */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are in .inittext so they can be used to signal
|
* These functions are in .inittext so they can be used to signal
|
||||||
* error during initialization.
|
* error during initialization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void __attribute__((section(".inittext"))) putchar(int ch)
|
static void __attribute__((section(".inittext"))) serial_putchar(int ch)
|
||||||
|
{
|
||||||
|
unsigned timeout = 0xffff;
|
||||||
|
|
||||||
|
while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
outb(ch, early_serial_base + TXR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((section(".inittext"))) bios_putchar(int ch)
|
||||||
{
|
{
|
||||||
struct biosregs ireg;
|
struct biosregs ireg;
|
||||||
|
|
||||||
if (ch == '\n')
|
|
||||||
putchar('\r'); /* \n -> \r\n */
|
|
||||||
|
|
||||||
initregs(&ireg);
|
initregs(&ireg);
|
||||||
ireg.bx = 0x0007;
|
ireg.bx = 0x0007;
|
||||||
ireg.cx = 0x0001;
|
ireg.cx = 0x0001;
|
||||||
@@ -36,6 +49,17 @@ void __attribute__((section(".inittext"))) putchar(int ch)
|
|||||||
intcall(0x10, &ireg, NULL);
|
intcall(0x10, &ireg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __attribute__((section(".inittext"))) putchar(int ch)
|
||||||
|
{
|
||||||
|
if (ch == '\n')
|
||||||
|
putchar('\r'); /* \n -> \r\n */
|
||||||
|
|
||||||
|
bios_putchar(ch);
|
||||||
|
|
||||||
|
if (early_serial_base != 0)
|
||||||
|
serial_putchar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
void __attribute__((section(".inittext"))) puts(const char *str)
|
void __attribute__((section(".inittext"))) puts(const char *str)
|
||||||
{
|
{
|
||||||
while (*str)
|
while (*str)
|
||||||
@@ -112,3 +136,4 @@ int getchar_timeout(void)
|
|||||||
|
|
||||||
return 0; /* Timeout! */
|
return 0; /* Timeout! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user