--- /dev/null
+From 6b6815c6d5d1dc209701d1661a7a0e09a295db2f Mon Sep 17 00:00:00 2001
+From: H. Peter Anvin <hpa@zytor.com>
+Date: Thu, 25 Oct 2007 16:11:33 -0700
+Subject: x86 setup: handle boot loaders which set up the stack incorrectly
+Message-ID: <472BBA17.6080207@zytor.com>
+
+From: H. Peter Anvin <hpa@zytor.com>
+
+patch 6b6815c6d5d1dc209701d1661a7a0e09a295db2f in mainline.
+
+Apparently some specific versions of LILO enter the kernel with a
+stack pointer that doesn't match the rest of the segments. Make our
+best attempt at untangling the resulting mess.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/i386/boot/boot.h | 4 +--
+ arch/i386/boot/header.S | 62 ++++++++++++++++++++++++++++++++++--------------
+ 2 files changed, 46 insertions(+), 20 deletions(-)
+
+--- a/arch/i386/boot/boot.h
++++ b/arch/i386/boot/boot.h
+@@ -17,6 +17,8 @@
+ #ifndef BOOT_BOOT_H
+ #define BOOT_BOOT_H
+
++#define STACK_SIZE 512 /* Minimum number of bytes for stack */
++
+ #ifndef __ASSEMBLY__
+
+ #include <stdarg.h>
+@@ -198,8 +200,6 @@ static inline int isdigit(int ch)
+ }
+
+ /* Heap -- available for dynamic lists. */
+-#define STACK_SIZE 512 /* Minimum number of bytes for stack */
+-
+ extern char _end[];
+ extern char *HEAP;
+ extern char *heap_end;
+--- a/arch/i386/boot/header.S
++++ b/arch/i386/boot/header.S
+@@ -173,7 +173,8 @@ ramdisk_size: .long 0 # its size in byt
+ bootsect_kludge:
+ .long 0 # obsolete
+
+-heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later)
++heap_end_ptr: .word _end+STACK_SIZE-512
++ # (Header version 0x0201 or later)
+ # space from here (exclusive) down to
+ # end of setup code can be used by setup
+ # for local heap purposes.
+@@ -225,28 +226,53 @@ start_of_setup:
+ int $0x13
+ #endif
+
+-# We will have entered with %cs = %ds+0x20, normalize %cs so
+-# it is on par with the other segments.
+- pushw %ds
+- pushw $setup2
+- lretw
+-
+-setup2:
+ # Force %es = %ds
+ movw %ds, %ax
+ movw %ax, %es
+ cld
+
+-# Stack paranoia: align the stack and make sure it is good
+-# for both 16- and 32-bit references. In particular, if we
+-# were meant to have been using the full 16-bit segment, the
+-# caller might have set %sp to zero, which breaks %esp-based
+-# references.
+- andw $~3, %sp # dword align (might as well...)
+- jnz 1f
+- movw $0xfffc, %sp # Make sure we're not zero
+-1: movzwl %sp, %esp # Clear upper half of %esp
+- sti
++# Apparently some ancient versions of LILO invoked the kernel
++# with %ss != %ds, which happened to work by accident for the
++# old code. If the CAN_USE_HEAP flag is set in loadflags, or
++# %ss != %ds, then adjust the stack pointer.
++
++ # Smallest possible stack we can tolerate
++ movw $(_end+STACK_SIZE), %cx
++
++ movw heap_end_ptr, %dx
++ addw $512, %dx
++ jnc 1f
++ xorw %dx, %dx # Wraparound - whole segment available
++1: testb $CAN_USE_HEAP, loadflags
++ jnz 2f
++
++ # No CAN_USE_HEAP
++ movw %ss, %dx
++ cmpw %ax, %dx # %ds == %ss?
++ movw %sp, %dx
++ # If so, assume %sp is reasonably set, otherwise use
++ # the smallest possible stack.
++ jne 4f # -> Smallest possible stack...
++
++ # Make sure the stack is at least minimum size. Take a value
++ # of zero to mean "full segment."
++2:
++ andw $~3, %dx # dword align (might as well...)
++ jnz 3f
++ movw $0xfffc, %dx # Make sure we're not zero
++3: cmpw %cx, %dx
++ jnb 5f
++4: movw %cx, %dx # Minimum value we can possibly use
++5: movw %ax, %ss
++ movzwl %dx, %esp # Clear upper half of %esp
++ sti # Now we should have a working stack
++
++# We will have entered with %cs = %ds+0x20, normalize %cs so
++# it is on par with the other segments.
++ pushw %ds
++ pushw $6f
++ lretw
++6:
+
+ # Check signature at end of setup
+ cmpl $0x5a5aaa55, setup_sig
--- /dev/null
+From e6e1ace9904b72478f0c5a5aa7bd174cb6f62561 Mon Sep 17 00:00:00 2001
+From: H. Peter Anvin <hpa@zytor.com>
+Date: Thu, 25 Oct 2007 16:09:38 -0700
+Subject: x86 setup: sizeof() is unsigned, unbreak comparisons
+Message-ID: <472BBA17.6080207@zytor.com>
+
+From: H. Peter Anvin <hpa@zytor.com>
+
+patch e6e1ace9904b72478f0c5a5aa7bd174cb6f62561 in mainline.
+
+
+We use signed values for limit checking since the values can go
+negative under certain circumstances. However, sizeof() is unsigned
+and forces the comparison to be unsigned, so move the comparison into
+the heap_free() macros so we can ensure it is a signed comparison.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/i386/boot/boot.h | 4 ++--
+ arch/i386/boot/video-bios.c | 2 +-
+ arch/i386/boot/video-vesa.c | 2 +-
+ arch/i386/boot/video.c | 2 +-
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/i386/boot/boot.h
++++ b/arch/i386/boot/boot.h
+@@ -216,9 +216,9 @@ static inline char *__get_heap(size_t s,
+ #define GET_HEAP(type, n) \
+ ((type *)__get_heap(sizeof(type),__alignof__(type),(n)))
+
+-static inline int heap_free(void)
++static inline bool heap_free(size_t n)
+ {
+- return heap_end-HEAP;
++ return (int)(heap_end-HEAP) >= (int)n;
+ }
+
+ /* copy.S */
+--- a/arch/i386/boot/video-bios.c
++++ b/arch/i386/boot/video-bios.c
+@@ -79,7 +79,7 @@ static int bios_probe(void)
+ video_bios.modes = GET_HEAP(struct mode_info, 0);
+
+ for (mode = 0x14; mode <= 0x7f; mode++) {
+- if (heap_free() < sizeof(struct mode_info))
++ if (!heap_free(sizeof(struct mode_info)))
+ break;
+
+ if (mode_defined(VIDEO_FIRST_BIOS+mode))
+--- a/arch/i386/boot/video-vesa.c
++++ b/arch/i386/boot/video-vesa.c
+@@ -57,7 +57,7 @@ static int vesa_probe(void)
+ while ((mode = rdfs16(mode_ptr)) != 0xffff) {
+ mode_ptr += 2;
+
+- if (heap_free() < sizeof(struct mode_info))
++ if (!heap_free(sizeof(struct mode_info)))
+ break; /* Heap full, can't save mode info */
+
+ if (mode & ~0x1ff)
+--- a/arch/i386/boot/video.c
++++ b/arch/i386/boot/video.c
+@@ -371,7 +371,7 @@ static void save_screen(void)
+ saved.curx = boot_params.screen_info.orig_x;
+ saved.cury = boot_params.screen_info.orig_y;
+
+- if (heap_free() < saved.x*saved.y*sizeof(u16)+512)
++ if (!heap_free(saved.x*saved.y*sizeof(u16)+512))
+ return; /* Not enough heap to save the screen */
+
+ saved.data = GET_HEAP(u16, saved.x*saved.y);