Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b6815c6 authored by H. Peter Anvin's avatar H. Peter Anvin
Browse files

x86 setup: handle boot loaders which set up the stack incorrectly



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: default avatarH. Peter Anvin <hpa@zytor.com>
parent c9927c2b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+44 −18
Original line number Diff line number Diff line
@@ -173,7 +173,8 @@ ramdisk_size: .long 0 # its size in bytes
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.
@@ -230,28 +231,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