xref: /illumos-gate/usr/src/boot/efi/loader/arch/i386/multiboot_tramp.S (revision dd72704bd9e794056c558153663c739e2012d721)
1/*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source.  A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12/*
13 * Copyright 2016 Toomas Soome <tsoome@me.com>
14 */
15
16#include <x86/specialreg.h>
17
18	.file	"multiboot_tramp.s"
19
20/*
21 * dboot expects a 32-bit multiboot environment and to execute in 32-bit mode.
22 *
23 * EAX: MB magic
24 * EBX: 32-bit physical address of MBI
25 * CS: 32-bit read/execute code segment with offset 0 and limit 0xFFFFFFFF
26 * DS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
27 * ES: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
28 * FS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
29 * GS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
30 * SS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF
31 * A20 enabled
32 * CR0: PG cleared, PE set
33 * EFLAGS: VM cleared, IF cleared
34 * interrupts disabled
35 */
36
37		.set	SEL_SCODE,0x8
38		.set	SEL_SDATA,0x10
39
40		.text
41		.p2align 4
42		.globl	multiboot_tramp
43		.type	multiboot_tramp, STT_FUNC
44
45/*
46 * Note as we are running in 32-bit mode, all pointers are 32-bit.
47 * void multiboot_tramp(uint32_t magic, struct relocator *relocator,
48 *    vm_offset_t entry)
49 */
50multiboot_tramp:
51		cli
52		pushl	%ebp		/* keep familiar stack frame */
53		movl	%esp, %ebp	/* current SP */
54		movl	0xc(%ebp),%eax	/* relocator */
55		movl	(%eax), %eax	/* new SP */
56		movl	%eax, %esp
57
58		/* now copy arguments to new stack */
59		movl	0x10(%ebp),%eax	/* entry */
60		pushl	%eax
61		movl	0xc(%ebp),%eax	/* relocator */
62		pushl	%eax
63		movl	0x8(%ebp),%eax	/* magic */
64		pushl	%eax
65		xorl	%eax,%eax
66		pushl	%eax		/* fake IP, just to keep stack frame */
67		pushl	%ebp
68		movl	%esp, %ebp
69		subl	$0x30, %esp	/* local mbi, gdt and gdt desc */
70
71		movl	0xc(%ebp), %eax	/* relocator */
72		pushl	%eax
73		movl	0x4(%eax), %eax	/* relocator->copy */
74		call	*%eax
75		addl	$0x4, %esp
76		movl	%eax, -0x4(%ebp)	/* save MBI */
77
78		/* set up GDT descriptor */
79		lea	-0x1c(%ebp), %eax	/* address of GDT */
80		movw	$0x17, -0x22(%ebp)	/* limit */
81		movl	%eax, -0x20(%ebp)	/* base */
82
83/*
84 * set up following GDT:
85 *		.word	0x0, 0x0		NULL entry
86 *		.byte	0x0, 0x0, 0x0, 0x0
87 *		.word	0xffff, 0x0		code segment
88 *		.byte	0x0, 0x9a, 0xcf, 0x0
89 *		.word	0xffff, 0x0		data segment
90 *		.byte	0x0, 0x92, 0xcf, 0x0
91 *
92 * This will create access for 4GB flat memory with
93 * base = 0x00000000, segment limit = 0xffffffff
94 * page granulariy 4k
95 * 32-bit protected mode
96 * ring 0
97 * code segment is executable RW
98 * data segment is not-executable RW
99 */
100		movw	$0x0, -0x1c(%ebp)
101		movw	$0x0, -0x1a(%ebp)
102		movb	$0x0, -0x18(%ebp)
103		movb	$0x0, -0x17(%ebp)
104		movb	$0x0, -0x16(%ebp)
105		movb	$0x0, -0x15(%ebp)
106
107		movw	$0xffff, -0x14(%ebp)
108		movw	$0x0, -0x12(%ebp)
109		movb	$0x0, -0x10(%ebp)
110		movb	$0x9a, -0xf(%ebp)
111		movb	$0xcf, -0xe(%ebp)
112		movb	$0x0, -0xd(%ebp)
113
114		movw	$0xffff, -0xc(%ebp)
115		movw	$0x0, -0xa(%ebp)
116		movb	$0x0, -0x8(%ebp)
117		movb	$0x92, -0x7(%ebp)
118		movb	$0xcf, -0x6(%ebp)
119		movb	$0x0, -0x5(%ebp)
120
121		lea	-0x22(%ebp), %eax	/* address of GDT */
122		lgdt	(%eax)
123
124		movl	0x8(%ebp), %edx		/* magic */
125		movl	-0x4(%ebp), %ebx	/* MBI */
126		movl	0x10(%ebp), %esi	/* entry */
127
128		movl	$SEL_SDATA, %eax
129		movw	%ax, %ss
130		movw	%ax, %ds
131		movw	%ax, %es
132		movw	%ax, %fs
133		movw	%ax, %gs
134
135		/*
136		 * We most likely don't need to push SEL_SDATA and esp
137		 * because we do not expect to perform a privilege transition.
138		 * However, it doesn't hurt us to push them as dboot will set
139		 * up its own stack.
140		 */
141		movl	%esp, %eax
142		pushl	$SEL_SDATA
143		pushl	%eax
144		pushf
145		pushl	$SEL_SCODE
146		pushl	%esi
147		movl	%edx, %eax
148		iretl
149
150multiboot_tramp_end:
151