浏览代码

Merge branch 'x86/setup' into x86/devel

Ingo Molnar 17 年之前
父节点
当前提交
3c1ca43faf

+ 0 - 0
Documentation/i386/IO-APIC.txt → Documentation/x86/i386/IO-APIC.txt


+ 46 - 33
Documentation/i386/boot.txt → Documentation/x86/i386/boot.txt

@@ -1,17 +1,14 @@
-		     THE LINUX/I386 BOOT PROTOCOL
-		     ----------------------------
+		     THE LINUX/x86 BOOT PROTOCOL
+		     ---------------------------
 
 
-		    H. Peter Anvin <hpa@zytor.com>
-			Last update 2007-05-23
-
-On the i386 platform, the Linux kernel uses a rather complicated boot
+On the x86 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
 convention.  This has evolved partially due to historical aspects, as
 well as the desire in the early days to have the kernel itself be a
 well as the desire in the early days to have the kernel itself be a
 bootable image, the complicated PC memory model and due to changed
 bootable image, the complicated PC memory model and due to changed
 expectations in the PC industry caused by the effective demise of
 expectations in the PC industry caused by the effective demise of
 real-mode DOS as a mainstream operating system.
 real-mode DOS as a mainstream operating system.
 
 
-Currently, the following versions of the Linux/i386 boot protocol exist.
+Currently, the following versions of the Linux/x86 boot protocol exist.
 
 
 Old kernels:	zImage/Image support only.  Some very early kernels
 Old kernels:	zImage/Image support only.  Some very early kernels
 		may not even support a command line.
 		may not even support a command line.
@@ -372,10 +369,17 @@ Protocol:	2.00+
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 
 
+  Bit 5 (write): QUIET_FLAG
+	- If 0, print early messages.
+	- If 1, suppress early messages.
+		This requests to the kernel (decompressor and early
+		kernel) to not write early messages that require
+		accessing the display hardware directly.
+
   Bit 6 (write): KEEP_SEGMENTS
   Bit 6 (write): KEEP_SEGMENTS
 	Protocol: 2.07+
 	Protocol: 2.07+
-	- if 0, reload the segment registers in the 32bit entry point.
-	- if 1, do not reload the segment registers in the 32bit entry point.
+	- If 0, reload the segment registers in the 32bit entry point.
+	- If 1, do not reload the segment registers in the 32bit entry point.
 		Assume that %cs %ds %ss %es are all set to flat segments with
 		Assume that %cs %ds %ss %es are all set to flat segments with
 		a base of 0 (or the equivalent for their environment).
 		a base of 0 (or the equivalent for their environment).
 
 
@@ -504,7 +508,7 @@ Protocol:	2.06+
   maximum size was 255.
   maximum size was 255.
 
 
 Field name:	hardware_subarch
 Field name:	hardware_subarch
-Type:		write
+Type:		write (optional, defaults to x86/PC)
 Offset/size:	0x23c/4
 Offset/size:	0x23c/4
 Protocol:	2.07+
 Protocol:	2.07+
 
 
@@ -520,11 +524,13 @@ Protocol:	2.07+
   0x00000002	Xen
   0x00000002	Xen
 
 
 Field name:	hardware_subarch_data
 Field name:	hardware_subarch_data
-Type:		write
+Type:		write (subarch-dependent)
 Offset/size:	0x240/8
 Offset/size:	0x240/8
 Protocol:	2.07+
 Protocol:	2.07+
 
 
   A pointer to data that is specific to hardware subarch
   A pointer to data that is specific to hardware subarch
+  This field is currently unused for the default x86/PC environment,
+  do not modify.
 
 
 Field name:	payload_offset
 Field name:	payload_offset
 Type:		read
 Type:		read
@@ -545,6 +551,34 @@ Protocol:	2.08+
 
 
   The length of the payload.
   The length of the payload.
 
 
+Field name:	setup_data
+Type:		write (special)
+Offset/size:	0x250/8
+Protocol:	2.09+
+
+  The 64-bit physical pointer to NULL terminated single linked list of
+  struct setup_data. This is used to define a more extensible boot
+  parameters passing mechanism. The definition of struct setup_data is
+  as follow:
+
+  struct setup_data {
+	  u64 next;
+	  u32 type;
+	  u32 len;
+	  u8  data[0];
+  };
+
+  Where, the next is a 64-bit physical pointer to the next node of
+  linked list, the next field of the last node is 0; the type is used
+  to identify the contents of data; the len is the length of data
+  field; the data holds the real payload.
+
+  This list may be modified at a number of points during the bootup
+  process.  Therefore, when modifying this list one should always make
+  sure to consider the case where the linked list already contains
+  entries.
+
+
 **** THE IMAGE CHECKSUM
 **** THE IMAGE CHECKSUM
 
 
 From boot protocol version 2.08 onwards the CRC-32 is calculated over
 From boot protocol version 2.08 onwards the CRC-32 is calculated over
@@ -553,6 +587,7 @@ initial remainder of 0xffffffff.  The checksum is appended to the
 file; therefore the CRC of the file up to the limit specified in the
 file; therefore the CRC of the file up to the limit specified in the
 syssize field of the header is always 0.
 syssize field of the header is always 0.
 
 
+
 **** THE KERNEL COMMAND LINE
 **** THE KERNEL COMMAND LINE
 
 
 The kernel command line has become an important way for the boot
 The kernel command line has become an important way for the boot
@@ -584,28 +619,6 @@ command line is entered using the following protocol:
 	covered by setup_move_size, so you may need to adjust this
 	covered by setup_move_size, so you may need to adjust this
 	field.
 	field.
 
 
-Field name:	setup_data
-Type:		write (obligatory)
-Offset/size:	0x250/8
-Protocol:	2.09+
-
-  The 64-bit physical pointer to NULL terminated single linked list of
-  struct setup_data. This is used to define a more extensible boot
-  parameters passing mechanism. The definition of struct setup_data is
-  as follow:
-
-  struct setup_data {
-	  u64 next;
-	  u32 type;
-	  u32 len;
-	  u8  data[0];
-  };
-
-  Where, the next is a 64-bit physical pointer to the next node of
-  linked list, the next field of the last node is 0; the type is used
-  to identify the contents of data; the len is the length of data
-  field; the data holds the real payload.
-
 
 
 **** MEMORY LAYOUT OF THE REAL-MODE CODE
 **** MEMORY LAYOUT OF THE REAL-MODE CODE
 
 

+ 0 - 0
Documentation/i386/usb-legacy-support.txt → Documentation/x86/i386/usb-legacy-support.txt


+ 0 - 0
Documentation/i386/zero-page.txt → Documentation/x86/i386/zero-page.txt


+ 0 - 0
Documentation/x86_64/00-INDEX → Documentation/x86/x86_64/00-INDEX


+ 0 - 0
Documentation/x86_64/boot-options.txt → Documentation/x86/x86_64/boot-options.txt


+ 0 - 0
Documentation/x86_64/cpu-hotplug-spec → Documentation/x86/x86_64/cpu-hotplug-spec


+ 0 - 0
Documentation/x86_64/fake-numa-for-cpusets → Documentation/x86/x86_64/fake-numa-for-cpusets


+ 0 - 0
Documentation/x86_64/kernel-stacks → Documentation/x86/x86_64/kernel-stacks


+ 0 - 0
Documentation/x86_64/machinecheck → Documentation/x86/x86_64/machinecheck


+ 0 - 0
Documentation/x86_64/mm.txt → Documentation/x86/x86_64/mm.txt


+ 0 - 0
Documentation/x86_64/uefi.txt → Documentation/x86/x86_64/uefi.txt


+ 8 - 0
arch/x86/Kconfig.debug

@@ -20,6 +20,14 @@ config NONPROMISC_DEVMEM
 
 
 	  If in doubt, say Y.
 	  If in doubt, say Y.
 
 
+config X86_VERBOSE_BOOTUP
+	bool "Enable verbose x86 bootup info messages"
+	default y
+	help
+	  Enables the informational output from the decompression stage
+	  (e.g. bzImage) of the boot. If you disable this you will still
+	  see errors. Disable this if you want silent bootup.
+
 config EARLY_PRINTK
 config EARLY_PRINTK
 	bool "Early printk" if EMBEDDED
 	bool "Early printk" if EMBEDDED
 	default y
 	default y

+ 4 - 1
arch/x86/boot/a20.c

@@ -1,7 +1,7 @@
 /* -*- linux-c -*- ------------------------------------------------------- *
 /* -*- linux-c -*- ------------------------------------------------------- *
  *
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright (C) 1991, 1992 Linus Torvalds
- *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
  *
  *
  *   This file is part of the Linux kernel, and is made available under
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
  *   the terms of the GNU General Public License version 2.
@@ -95,6 +95,9 @@ static void enable_a20_kbc(void)
 
 
 	outb(0xdf, 0x60);	/* A20 on */
 	outb(0xdf, 0x60);	/* A20 on */
 	empty_8042();
 	empty_8042();
+
+	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
+	empty_8042();
 }
 }
 
 
 static void enable_a20_fast(void)
 static void enable_a20_fast(void)

+ 32 - 23
arch/x86/boot/compressed/misc.c

@@ -30,6 +30,7 @@
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/page.h>
 #include <asm/boot.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
@@ -187,13 +188,8 @@ static void gzip_release(void **);
 /*
 /*
  * This is set up by the setup-routine at boot-time
  * This is set up by the setup-routine at boot-time
  */
  */
-static unsigned char *real_mode; /* Pointer to real-mode data */
-
-#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
-#ifndef STANDARD_MEMORY_BIOS_CALL
-#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
-#endif
-#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+static struct boot_params *real_mode;		/* Pointer to real-mode data */
+static int quiet;
 
 
 extern unsigned char input_data[];
 extern unsigned char input_data[];
 extern int input_len;
 extern int input_len;
@@ -206,7 +202,8 @@ static void free(void *where);
 static void *memset(void *s, int c, unsigned n);
 static void *memset(void *s, int c, unsigned n);
 static void *memcpy(void *dest, const void *src, unsigned n);
 static void *memcpy(void *dest, const void *src, unsigned n);
 
 
-static void putstr(const char *);
+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
@@ -270,18 +267,24 @@ static void scroll(void)
 		vidmem[i] = ' ';
 		vidmem[i] = ' ';
 }
 }
 
 
-static void putstr(const char *s)
+static void __putstr(int error, const char *s)
 {
 {
 	int x, y, pos;
 	int x, y, pos;
 	char c;
 	char c;
 
 
+#ifndef CONFIG_X86_VERBOSE_BOOTUP
+	if (!error)
+		return;
+#endif
+
 #ifdef CONFIG_X86_32
 #ifdef CONFIG_X86_32
-	if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
+	if (real_mode->screen_info.orig_video_mode == 0 &&
+	    lines == 0 && cols == 0)
 		return;
 		return;
 #endif
 #endif
 
 
-	x = RM_SCREEN_INFO.orig_x;
-	y = RM_SCREEN_INFO.orig_y;
+	x = real_mode->screen_info.orig_x;
+	y = real_mode->screen_info.orig_y;
 
 
 	while ((c = *s++) != '\0') {
 	while ((c = *s++) != '\0') {
 		if (c == '\n') {
 		if (c == '\n') {
@@ -302,8 +305,8 @@ static void putstr(const char *s)
 		}
 		}
 	}
 	}
 
 
-	RM_SCREEN_INFO.orig_x = x;
-	RM_SCREEN_INFO.orig_y = y;
+	real_mode->screen_info.orig_x = x;
+	real_mode->screen_info.orig_y = y;
 
 
 	pos = (x + cols * y) * 2;	/* Update cursor position */
 	pos = (x + cols * y) * 2;	/* Update cursor position */
 	outb(14, vidport);
 	outb(14, vidport);
@@ -366,9 +369,9 @@ static void flush_window(void)
 
 
 static void error(char *x)
 static void error(char *x)
 {
 {
-	putstr("\n\n");
-	putstr(x);
-	putstr("\n\n -- System halted");
+	__putstr(1, "\n\n");
+	__putstr(1, x);
+	__putstr(1, "\n\n -- System halted");
 
 
 	while (1)
 	while (1)
 		asm("hlt");
 		asm("hlt");
@@ -395,7 +398,8 @@ static void parse_elf(void *output)
 		return;
 		return;
 	}
 	}
 
 
-	putstr("Parsing ELF... ");
+	if (!quiet)
+		putstr("Parsing ELF... ");
 
 
 	phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
 	phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
 	if (!phdrs)
 	if (!phdrs)
@@ -430,7 +434,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 {
 {
 	real_mode = rmode;
 	real_mode = rmode;
 
 
-	if (RM_SCREEN_INFO.orig_video_mode == 7) {
+	if (real_mode->hdr.loadflags & QUIET_FLAG)
+		quiet = 1;
+
+	if (real_mode->screen_info.orig_video_mode == 7) {
 		vidmem = (char *) 0xb0000;
 		vidmem = (char *) 0xb0000;
 		vidport = 0x3b4;
 		vidport = 0x3b4;
 	} else {
 	} else {
@@ -438,8 +445,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 		vidport = 0x3d4;
 		vidport = 0x3d4;
 	}
 	}
 
 
-	lines = RM_SCREEN_INFO.orig_video_lines;
-	cols = RM_SCREEN_INFO.orig_video_cols;
+	lines = real_mode->screen_info.orig_video_lines;
+	cols = real_mode->screen_info.orig_video_cols;
 
 
 	window = output;		/* Output buffer (Normally at 1M) */
 	window = output;		/* Output buffer (Normally at 1M) */
 	free_mem_ptr     = heap;	/* Heap */
 	free_mem_ptr     = heap;	/* Heap */
@@ -465,9 +472,11 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 #endif
 #endif
 
 
 	makecrc();
 	makecrc();
-	putstr("\nDecompressing Linux... ");
+	if (!quiet)
+		putstr("\nDecompressing Linux... ");
 	gunzip();
 	gunzip();
 	parse_elf(output);
 	parse_elf(output);
-	putstr("done.\nBooting the kernel.\n");
+	if (!quiet)
+		putstr("done.\nBooting the kernel.\n");
 	return;
 	return;
 }
 }

+ 110 - 88
arch/x86/boot/compressed/relocs.c

@@ -10,16 +10,20 @@
 #define USE_BSD
 #define USE_BSD
 #include <endian.h>
 #include <endian.h>
 
 
-#define MAX_SHDRS 100
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 static Elf32_Ehdr ehdr;
 static Elf32_Ehdr ehdr;
-static Elf32_Shdr shdr[MAX_SHDRS];
-static Elf32_Sym  *symtab[MAX_SHDRS];
-static Elf32_Rel  *reltab[MAX_SHDRS];
-static char *strtab[MAX_SHDRS];
 static unsigned long reloc_count, reloc_idx;
 static unsigned long reloc_count, reloc_idx;
 static unsigned long *relocs;
 static unsigned long *relocs;
 
 
+struct section {
+	Elf32_Shdr     shdr;
+	struct section *link;
+	Elf32_Sym      *symtab;
+	Elf32_Rel      *reltab;
+	char           *strtab;
+};
+static struct section *secs;
+
 /*
 /*
  * Following symbols have been audited. There values are constant and do
  * Following symbols have been audited. There values are constant and do
  * not change if bzImage is loaded at a different physical address than
  * not change if bzImage is loaded at a different physical address than
@@ -35,7 +39,7 @@ static int is_safe_abs_reloc(const char* sym_name)
 {
 {
 	int i;
 	int i;
 
 
-	for(i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
+	for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
 		if (!strcmp(sym_name, safe_abs_relocs[i]))
 		if (!strcmp(sym_name, safe_abs_relocs[i]))
 			/* Match found */
 			/* Match found */
 			return 1;
 			return 1;
@@ -137,10 +141,10 @@ static const char *sec_name(unsigned shndx)
 {
 {
 	const char *sec_strtab;
 	const char *sec_strtab;
 	const char *name;
 	const char *name;
-	sec_strtab = strtab[ehdr.e_shstrndx];
+	sec_strtab = secs[ehdr.e_shstrndx].strtab;
 	name = "<noname>";
 	name = "<noname>";
 	if (shndx < ehdr.e_shnum) {
 	if (shndx < ehdr.e_shnum) {
-		name = sec_strtab + shdr[shndx].sh_name;
+		name = sec_strtab + secs[shndx].shdr.sh_name;
 	}
 	}
 	else if (shndx == SHN_ABS) {
 	else if (shndx == SHN_ABS) {
 		name = "ABSOLUTE";
 		name = "ABSOLUTE";
@@ -159,7 +163,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
 		name = sym_strtab + sym->st_name;
 		name = sym_strtab + sym->st_name;
 	}
 	}
 	else {
 	else {
-		name = sec_name(shdr[sym->st_shndx].sh_name);
+		name = sec_name(secs[sym->st_shndx].shdr.sh_name);
 	}
 	}
 	return name;
 	return name;
 }
 }
@@ -244,29 +248,34 @@ static void read_ehdr(FILE *fp)
 static void read_shdrs(FILE *fp)
 static void read_shdrs(FILE *fp)
 {
 {
 	int i;
 	int i;
-	if (ehdr.e_shnum > MAX_SHDRS) {
-		die("%d section headers supported: %d\n",
-			ehdr.e_shnum, MAX_SHDRS);
+	Elf32_Shdr shdr;
+
+	secs = calloc(ehdr.e_shnum, sizeof(struct section));
+	if (!secs) {
+		die("Unable to allocate %d section headers\n",
+		    ehdr.e_shnum);
 	}
 	}
 	if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
 	if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
 		die("Seek to %d failed: %s\n",
 		die("Seek to %d failed: %s\n",
 			ehdr.e_shoff, strerror(errno));
 			ehdr.e_shoff, strerror(errno));
 	}
 	}
-	if (fread(&shdr, sizeof(shdr[0]), ehdr.e_shnum, fp) != ehdr.e_shnum) {
-		die("Cannot read ELF section headers: %s\n",
-			strerror(errno));
-	}
-	for(i = 0; i < ehdr.e_shnum; i++) {
-		shdr[i].sh_name      = elf32_to_cpu(shdr[i].sh_name);
-		shdr[i].sh_type      = elf32_to_cpu(shdr[i].sh_type);
-		shdr[i].sh_flags     = elf32_to_cpu(shdr[i].sh_flags);
-		shdr[i].sh_addr      = elf32_to_cpu(shdr[i].sh_addr);
-		shdr[i].sh_offset    = elf32_to_cpu(shdr[i].sh_offset);
-		shdr[i].sh_size      = elf32_to_cpu(shdr[i].sh_size);
-		shdr[i].sh_link      = elf32_to_cpu(shdr[i].sh_link);
-		shdr[i].sh_info      = elf32_to_cpu(shdr[i].sh_info);
-		shdr[i].sh_addralign = elf32_to_cpu(shdr[i].sh_addralign);
-		shdr[i].sh_entsize   = elf32_to_cpu(shdr[i].sh_entsize);
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		if (fread(&shdr, sizeof shdr, 1, fp) != 1)
+			die("Cannot read ELF section headers %d/%d: %s\n",
+			    i, ehdr.e_shnum, strerror(errno));
+		sec->shdr.sh_name      = elf32_to_cpu(shdr.sh_name);
+		sec->shdr.sh_type      = elf32_to_cpu(shdr.sh_type);
+		sec->shdr.sh_flags     = elf32_to_cpu(shdr.sh_flags);
+		sec->shdr.sh_addr      = elf32_to_cpu(shdr.sh_addr);
+		sec->shdr.sh_offset    = elf32_to_cpu(shdr.sh_offset);
+		sec->shdr.sh_size      = elf32_to_cpu(shdr.sh_size);
+		sec->shdr.sh_link      = elf32_to_cpu(shdr.sh_link);
+		sec->shdr.sh_info      = elf32_to_cpu(shdr.sh_info);
+		sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
+		sec->shdr.sh_entsize   = elf32_to_cpu(shdr.sh_entsize);
+		if (sec->shdr.sh_link < ehdr.e_shnum)
+			sec->link = &secs[sec->shdr.sh_link];
 	}
 	}
 
 
 }
 }
@@ -274,20 +283,22 @@ static void read_shdrs(FILE *fp)
 static void read_strtabs(FILE *fp)
 static void read_strtabs(FILE *fp)
 {
 {
 	int i;
 	int i;
-	for(i = 0; i < ehdr.e_shnum; i++) {
-		if (shdr[i].sh_type != SHT_STRTAB) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		if (sec->shdr.sh_type != SHT_STRTAB) {
 			continue;
 			continue;
 		}
 		}
-		strtab[i] = malloc(shdr[i].sh_size);
-		if (!strtab[i]) {
+		sec->strtab = malloc(sec->shdr.sh_size);
+		if (!sec->strtab) {
 			die("malloc of %d bytes for strtab failed\n",
 			die("malloc of %d bytes for strtab failed\n",
-				shdr[i].sh_size);
+				sec->shdr.sh_size);
 		}
 		}
-		if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 			die("Seek to %d failed: %s\n",
 			die("Seek to %d failed: %s\n",
-				shdr[i].sh_offset, strerror(errno));
+				sec->shdr.sh_offset, strerror(errno));
 		}
 		}
-		if (fread(strtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+		if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
+		    != sec->shdr.sh_size) {
 			die("Cannot read symbol table: %s\n",
 			die("Cannot read symbol table: %s\n",
 				strerror(errno));
 				strerror(errno));
 		}
 		}
@@ -297,28 +308,31 @@ static void read_strtabs(FILE *fp)
 static void read_symtabs(FILE *fp)
 static void read_symtabs(FILE *fp)
 {
 {
 	int i,j;
 	int i,j;
-	for(i = 0; i < ehdr.e_shnum; i++) {
-		if (shdr[i].sh_type != SHT_SYMTAB) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		if (sec->shdr.sh_type != SHT_SYMTAB) {
 			continue;
 			continue;
 		}
 		}
-		symtab[i] = malloc(shdr[i].sh_size);
-		if (!symtab[i]) {
+		sec->symtab = malloc(sec->shdr.sh_size);
+		if (!sec->symtab) {
 			die("malloc of %d bytes for symtab failed\n",
 			die("malloc of %d bytes for symtab failed\n",
-				shdr[i].sh_size);
+				sec->shdr.sh_size);
 		}
 		}
-		if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 			die("Seek to %d failed: %s\n",
 			die("Seek to %d failed: %s\n",
-				shdr[i].sh_offset, strerror(errno));
+				sec->shdr.sh_offset, strerror(errno));
 		}
 		}
-		if (fread(symtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+		if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
+		    != sec->shdr.sh_size) {
 			die("Cannot read symbol table: %s\n",
 			die("Cannot read symbol table: %s\n",
 				strerror(errno));
 				strerror(errno));
 		}
 		}
-		for(j = 0; j < shdr[i].sh_size/sizeof(symtab[i][0]); j++) {
-			symtab[i][j].st_name  = elf32_to_cpu(symtab[i][j].st_name);
-			symtab[i][j].st_value = elf32_to_cpu(symtab[i][j].st_value);
-			symtab[i][j].st_size  = elf32_to_cpu(symtab[i][j].st_size);
-			symtab[i][j].st_shndx = elf16_to_cpu(symtab[i][j].st_shndx);
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
+			Elf32_Sym *sym = &sec->symtab[j];
+			sym->st_name  = elf32_to_cpu(sym->st_name);
+			sym->st_value = elf32_to_cpu(sym->st_value);
+			sym->st_size  = elf32_to_cpu(sym->st_size);
+			sym->st_shndx = elf16_to_cpu(sym->st_shndx);
 		}
 		}
 	}
 	}
 }
 }
@@ -327,26 +341,29 @@ static void read_symtabs(FILE *fp)
 static void read_relocs(FILE *fp)
 static void read_relocs(FILE *fp)
 {
 {
 	int i,j;
 	int i,j;
-	for(i = 0; i < ehdr.e_shnum; i++) {
-		if (shdr[i].sh_type != SHT_REL) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		if (sec->shdr.sh_type != SHT_REL) {
 			continue;
 			continue;
 		}
 		}
-		reltab[i] = malloc(shdr[i].sh_size);
-		if (!reltab[i]) {
+		sec->reltab = malloc(sec->shdr.sh_size);
+		if (!sec->reltab) {
 			die("malloc of %d bytes for relocs failed\n",
 			die("malloc of %d bytes for relocs failed\n",
-				shdr[i].sh_size);
+				sec->shdr.sh_size);
 		}
 		}
-		if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 			die("Seek to %d failed: %s\n",
 			die("Seek to %d failed: %s\n",
-				shdr[i].sh_offset, strerror(errno));
+				sec->shdr.sh_offset, strerror(errno));
 		}
 		}
-		if (fread(reltab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
+		if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
+		    != sec->shdr.sh_size) {
 			die("Cannot read symbol table: %s\n",
 			die("Cannot read symbol table: %s\n",
 				strerror(errno));
 				strerror(errno));
 		}
 		}
-		for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
-			reltab[i][j].r_offset = elf32_to_cpu(reltab[i][j].r_offset);
-			reltab[i][j].r_info   = elf32_to_cpu(reltab[i][j].r_info);
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
+			Elf32_Rel *rel = &sec->reltab[j];
+			rel->r_offset = elf32_to_cpu(rel->r_offset);
+			rel->r_info   = elf32_to_cpu(rel->r_info);
 		}
 		}
 	}
 	}
 }
 }
@@ -357,19 +374,21 @@ static void print_absolute_symbols(void)
 	int i;
 	int i;
 	printf("Absolute symbols\n");
 	printf("Absolute symbols\n");
 	printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
 	printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
-	for(i = 0; i < ehdr.e_shnum; i++) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
 		char *sym_strtab;
 		char *sym_strtab;
 		Elf32_Sym *sh_symtab;
 		Elf32_Sym *sh_symtab;
 		int j;
 		int j;
-		if (shdr[i].sh_type != SHT_SYMTAB) {
+
+		if (sec->shdr.sh_type != SHT_SYMTAB) {
 			continue;
 			continue;
 		}
 		}
-		sh_symtab = symtab[i];
-		sym_strtab = strtab[shdr[i].sh_link];
-		for(j = 0; j < shdr[i].sh_size/sizeof(symtab[0][0]); j++) {
+		sh_symtab = sec->symtab;
+		sym_strtab = sec->link->strtab;
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
 			Elf32_Sym *sym;
 			Elf32_Sym *sym;
 			const char *name;
 			const char *name;
-			sym = &symtab[i][j];
+			sym = &sec->symtab[j];
 			name = sym_name(sym_strtab, sym);
 			name = sym_name(sym_strtab, sym);
 			if (sym->st_shndx != SHN_ABS) {
 			if (sym->st_shndx != SHN_ABS) {
 				continue;
 				continue;
@@ -389,26 +408,27 @@ static void print_absolute_relocs(void)
 {
 {
 	int i, printed = 0;
 	int i, printed = 0;
 
 
-	for(i = 0; i < ehdr.e_shnum; i++) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		struct section *sec_applies, *sec_symtab;
 		char *sym_strtab;
 		char *sym_strtab;
 		Elf32_Sym *sh_symtab;
 		Elf32_Sym *sh_symtab;
-		unsigned sec_applies, sec_symtab;
 		int j;
 		int j;
-		if (shdr[i].sh_type != SHT_REL) {
+		if (sec->shdr.sh_type != SHT_REL) {
 			continue;
 			continue;
 		}
 		}
-		sec_symtab  = shdr[i].sh_link;
-		sec_applies = shdr[i].sh_info;
-		if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
+		sec_symtab  = sec->link;
+		sec_applies = &secs[sec->shdr.sh_info];
+		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 			continue;
 			continue;
 		}
 		}
-		sh_symtab = symtab[sec_symtab];
-		sym_strtab = strtab[shdr[sec_symtab].sh_link];
-		for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
+		sh_symtab  = sec_symtab->symtab;
+		sym_strtab = sec_symtab->link->strtab;
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 			Elf32_Rel *rel;
 			Elf32_Rel *rel;
 			Elf32_Sym *sym;
 			Elf32_Sym *sym;
 			const char *name;
 			const char *name;
-			rel = &reltab[i][j];
+			rel = &sec->reltab[j];
 			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 			name = sym_name(sym_strtab, sym);
 			name = sym_name(sym_strtab, sym);
 			if (sym->st_shndx != SHN_ABS) {
 			if (sym->st_shndx != SHN_ABS) {
@@ -456,26 +476,28 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
 {
 {
 	int i;
 	int i;
 	/* Walk through the relocations */
 	/* Walk through the relocations */
-	for(i = 0; i < ehdr.e_shnum; i++) {
+	for (i = 0; i < ehdr.e_shnum; i++) {
 		char *sym_strtab;
 		char *sym_strtab;
 		Elf32_Sym *sh_symtab;
 		Elf32_Sym *sh_symtab;
-		unsigned sec_applies, sec_symtab;
+		struct section *sec_applies, *sec_symtab;
 		int j;
 		int j;
-		if (shdr[i].sh_type != SHT_REL) {
+		struct section *sec = &secs[i];
+
+		if (sec->shdr.sh_type != SHT_REL) {
 			continue;
 			continue;
 		}
 		}
-		sec_symtab  = shdr[i].sh_link;
-		sec_applies = shdr[i].sh_info;
-		if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
+		sec_symtab  = sec->link;
+		sec_applies = &secs[sec->shdr.sh_info];
+		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 			continue;
 			continue;
 		}
 		}
-		sh_symtab = symtab[sec_symtab];
-		sym_strtab = strtab[shdr[sec_symtab].sh_link];
-		for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
+		sh_symtab = sec_symtab->symtab;
+		sym_strtab = sec->link->strtab;
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 			Elf32_Rel *rel;
 			Elf32_Rel *rel;
 			Elf32_Sym *sym;
 			Elf32_Sym *sym;
 			unsigned r_type;
 			unsigned r_type;
-			rel = &reltab[i][j];
+			rel = &sec->reltab[j];
 			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 			r_type = ELF32_R_TYPE(rel->r_info);
 			r_type = ELF32_R_TYPE(rel->r_info);
 			/* Don't visit relocations to absolute symbols */
 			/* Don't visit relocations to absolute symbols */
@@ -539,7 +561,7 @@ static void emit_relocs(int as_text)
 		 */
 		 */
 		printf(".section \".data.reloc\",\"a\"\n");
 		printf(".section \".data.reloc\",\"a\"\n");
 		printf(".balign 4\n");
 		printf(".balign 4\n");
-		for(i = 0; i < reloc_count; i++) {
+		for (i = 0; i < reloc_count; i++) {
 			printf("\t .long 0x%08lx\n", relocs[i]);
 			printf("\t .long 0x%08lx\n", relocs[i]);
 		}
 		}
 		printf("\n");
 		printf("\n");
@@ -550,7 +572,7 @@ static void emit_relocs(int as_text)
 		/* Print a stop */
 		/* Print a stop */
 		printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
 		printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
 		/* Now print each relocation */
 		/* Now print each relocation */
-		for(i = 0; i < reloc_count; i++) {
+		for (i = 0; i < reloc_count; i++) {
 			buf[0] = (relocs[i] >>  0) & 0xff;
 			buf[0] = (relocs[i] >>  0) & 0xff;
 			buf[1] = (relocs[i] >>  8) & 0xff;
 			buf[1] = (relocs[i] >>  8) & 0xff;
 			buf[2] = (relocs[i] >> 16) & 0xff;
 			buf[2] = (relocs[i] >> 16) & 0xff;
@@ -577,7 +599,7 @@ int main(int argc, char **argv)
 	show_absolute_relocs = 0;
 	show_absolute_relocs = 0;
 	as_text = 0;
 	as_text = 0;
 	fname = NULL;
 	fname = NULL;
-	for(i = 1; i < argc; i++) {
+	for (i = 1; i < argc; i++) {
 		char *arg = argv[i];
 		char *arg = argv[i];
 		if (*arg == '-') {
 		if (*arg == '-') {
 			if (strcmp(argv[1], "--abs-syms") == 0) {
 			if (strcmp(argv[1], "--abs-syms") == 0) {

+ 2 - 0
arch/x86/boot/cpu.c

@@ -28,6 +28,8 @@ static char *cpu_name(int level)
 	if (level == 64) {
 	if (level == 64) {
 		return "x86-64";
 		return "x86-64";
 	} else {
 	} else {
+		if (level == 15)
+			level = 6;
 		sprintf(buf, "i%d86", level);
 		sprintf(buf, "i%d86", level);
 		return buf;
 		return buf;
 	}
 	}

+ 4 - 0
arch/x86/boot/main.c

@@ -165,6 +165,10 @@ 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();
 }
 }

+ 2 - 2
arch/x86/boot/pmjump.S

@@ -33,6 +33,8 @@ protected_mode_jump:
 	movw	%cs, %bx
 	movw	%cs, %bx
 	shll	$4, %ebx
 	shll	$4, %ebx
 	addl	%ebx, 2f
 	addl	%ebx, 2f
+	jmp	1f			# Short jump to serialize on 386/486
+1:
 
 
 	movw	$__BOOT_DS, %cx
 	movw	$__BOOT_DS, %cx
 	movw	$__BOOT_TSS, %di
 	movw	$__BOOT_TSS, %di
@@ -40,8 +42,6 @@ protected_mode_jump:
 	movl	%cr0, %edx
 	movl	%cr0, %edx
 	orb	$X86_CR0_PE, %dl	# Protected mode
 	orb	$X86_CR0_PE, %dl	# Protected mode
 	movl	%edx, %cr0
 	movl	%edx, %cr0
-	jmp	1f			# Short jump to serialize on 386/486
-1:
 
 
 	# Transition to 32-bit mode
 	# Transition to 32-bit mode
 	.byte	0x66, 0xea		# ljmpl opcode
 	.byte	0x66, 0xea		# ljmpl opcode

+ 1 - 0
include/asm-x86/bootparam.h

@@ -40,6 +40,7 @@ struct setup_header {
 	__u8	type_of_loader;
 	__u8	type_of_loader;
 	__u8	loadflags;
 	__u8	loadflags;
 #define LOADED_HIGH	(1<<0)
 #define LOADED_HIGH	(1<<0)
+#define QUIET_FLAG	(1<<5)
 #define KEEP_SEGMENTS	(1<<6)
 #define KEEP_SEGMENTS	(1<<6)
 #define CAN_USE_HEAP	(1<<7)
 #define CAN_USE_HEAP	(1<<7)
 	__u16	setup_move_size;
 	__u16	setup_move_size;