7461 illumos should support multiboot2 protocol
[unleashed.git] / usr / src / uts / i86pc / dboot / dboot_grub.s
blob7409c1299891874d579c26c05be149c5c5e49768
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #if defined(__lint)
29 int silence_lint_warnings = 0;
31 #else /* __lint */
33 #include <sys/multiboot.h>
34 #include <sys/multiboot2.h>
35 #include <sys/asm_linkage.h>
36 #include <sys/segments.h>
37 #include <sys/controlregs.h>
39 #include "dboot_xboot.h"
41 .text
42 .globl _start
43 _start:
44 jmp code_start
47 * The multiboot header has to be at the start of the file
49 * The 32 bit kernel is ELF32, so the MB header is mostly ignored.
51 * The 64 bit kernel is ELF64, so we get grub to load the entire
52 * ELF file into memory and trick it into jumping into this code.
53 * The trick is done by a binary utility run after unix is linked,
54 * that rewrites the mb_header.
56 .align 4
57 .globl mb_header
58 mb_header:
59 .long MB_HEADER_MAGIC /* magic number */
60 #if defined(_BOOT_TARGET_i386)
61 .long MB_HEADER_FLAGS_32 /* flags */
62 .long MB_HEADER_CHECKSUM_32 /* checksum */
63 #elif defined (_BOOT_TARGET_amd64)
64 .long MB_HEADER_FLAGS_64 /* flags */
65 .long MB_HEADER_CHECKSUM_64 /* checksum */
66 #else
67 #error No architecture defined
68 #endif
69 .long 0x11111111 /* header_addr: patched by mbh_patch */
70 .long 0x100000 /* load_addr: patched by mbh_patch */
71 .long 0 /* load_end_addr - 0 means entire file */
72 .long 0 /* bss_end_addr */
73 .long 0x2222222 /* entry_addr: patched by mbh_patch */
74 .long 0 /* video mode.. */
75 .long 0 /* width 0 == don't care */
76 .long 0 /* height 0 == don't care */
77 .long 0 /* depth 0 == don't care */
79 #if defined(_BOOT_TARGET_i386)
81 * The MB2 header must be 8 byte aligned relative to the beginning of
82 * the in-memory ELF object. The 32-bit kernel ELF file has sections
83 * which are 4-byte aligned, and as .align family directives only do
84 * control the alignment inside the section, we need to construct the
85 * image manually, by inserting the padding where needed. The alignment
86 * setup here depends on the first PT_LOAD section of the ELF file, if
87 * this section offset will change, this code must be reviewed.
88 * Similarily, if we add extra tag types into the information request
89 * or add tags into the tag list.
91 .long 0 /* padding */
92 #else
93 .balign MULTIBOOT_HEADER_ALIGN
94 #endif
95 mb2_header:
96 .long MULTIBOOT2_HEADER_MAGIC
97 .long MULTIBOOT_ARCHITECTURE_I386
98 .long mb2_header_end - mb2_header
99 .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (mb2_header_end - mb2_header))
102 * Multiboot 2 tags follow. Note, the first tag immediately follows
103 * the header. Subsequent tags must be aligned by MULTIBOOT_TAG_ALIGN.
105 * MB information request tag.
107 information_request_tag_start:
108 .word MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
109 .word 0
110 .long information_request_tag_end - information_request_tag_start
111 .long MULTIBOOT_TAG_TYPE_CMDLINE
112 .long MULTIBOOT_TAG_TYPE_MODULE
113 .long MULTIBOOT_TAG_TYPE_BOOTDEV
114 .long MULTIBOOT_TAG_TYPE_MMAP
115 .long MULTIBOOT_TAG_TYPE_BASIC_MEMINFO
116 information_request_tag_end:
117 .long 0 /* padding */
119 #if defined (_BOOT_TARGET_amd64)
121 * The following values are patched by mbh_patch for the 64-bit kernel,
122 * so we only provide this tag for the 64-bit kernel.
124 .balign MULTIBOOT_TAG_ALIGN
125 address_tag_start:
126 .word MULTIBOOT_HEADER_TAG_ADDRESS
127 .word 0
128 .long address_tag_end - address_tag_start
129 .long mb2_header
130 .globl mb2_load_addr
131 mb2_load_addr:
132 .long 0 /* load addr */
133 .long 0 /* load_end_addr */
134 .long 0 /* bss_end_addr */
135 address_tag_end:
137 * entry address tag
139 .balign MULTIBOOT_TAG_ALIGN
140 entry_address_tag_start:
141 .word MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
142 .word 0
143 .long entry_address_tag_end - entry_address_tag_start
144 .long 0 /* entry addr */
145 entry_address_tag_end:
147 .balign MULTIBOOT_TAG_ALIGN /* Alignment for the next tag */
148 #endif
150 * MB console flags tag
152 console_tag_start:
153 .word MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS
154 .word 0
155 .long console_tag_end - console_tag_start
156 .long MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
157 console_tag_end:
158 .long 0 /* padding */
161 * Tell the bootloader to load the modules page aligned to
162 * the specified alignment.
164 .word MULTIBOOT_HEADER_TAG_MODULE_ALIGN
165 .word 0
166 .long 8
169 * Termination tag.
171 .word MULTIBOOT_HEADER_TAG_END
172 .word 0
173 .long 8
174 mb2_header_end:
177 * At entry we are in protected mode, 32 bit execution, paging and
178 * interrupts are disabled.
180 * EAX == MB_BOOTLOADER_MAGIC
181 * EBX points to multiboot information
182 * segment registers all have segments with base 0, limit == 0xffffffff
184 code_start:
185 movl %eax, mb_magic
186 movl %ebx, mb_addr
188 movl $stack_space, %esp /* load my stack pointer */
189 addl $STACK_SIZE, %esp
191 pushl $0x0 /* push a dead-end frame */
192 pushl $0x0
193 movl %esp, %ebp
195 pushl $0x0 /* clear all processor flags */
196 popf
199 * setup a global descriptor table with known contents
201 lgdt gdt_info
202 movw $B32DATA_SEL, %ax
203 movw %ax, %ds
204 movw %ax, %es
205 movw %ax, %fs
206 movw %ax, %gs
207 movw %ax, %ss
208 ljmp $B32CODE_SEL, $newgdt
209 newgdt:
213 * go off and determine memory config, build page tables, etc.
215 call startup_kernel
219 * On amd64 we'll want the stack pointer to be 16 byte aligned.
221 andl $0xfffffff0, %esp
224 * Enable PGE, PAE and large pages
226 movl %cr4, %eax
227 testl $1, pge_support
228 jz 1f
229 orl $CR4_PGE, %eax
231 testl $1, pae_support
232 jz 1f
233 orl $CR4_PAE, %eax
235 testl $1, largepage_support
236 jz 1f
237 orl $CR4_PSE, %eax
239 movl %eax, %cr4
242 * enable NX protection if processor supports it
244 testl $1, NX_support
245 jz 1f
246 movl $MSR_AMD_EFER, %ecx
247 rdmsr
248 orl $AMD_EFER_NXE, %eax
249 wrmsr
254 * load the pagetable base address into cr3
256 movl top_page_table, %eax
257 movl %eax, %cr3
259 #if defined(_BOOT_TARGET_amd64)
261 * enable long mode
263 movl $MSR_AMD_EFER, %ecx
264 rdmsr
265 orl $AMD_EFER_LME, %eax
266 wrmsr
267 #endif
270 * enable paging, write protection, alignment masking, but disable
271 * the cache disable and write through only bits.
273 movl %cr0, %eax
274 orl $_CONST(CR0_PG | CR0_WP | CR0_AM), %eax
275 andl $_BITNOT(CR0_NW | CR0_CD), %eax
276 movl %eax, %cr0
277 jmp paging_on
278 paging_on:
281 * The xboot_info ptr gets passed to the kernel as its argument
283 movl bi, %edi
284 movl entry_addr_low, %esi
286 #if defined(_BOOT_TARGET_i386)
288 pushl %edi
289 call *%esi
291 #elif defined(_BOOT_TARGET_amd64)
294 * We're still in compatibility mode with 32 bit execution.
295 * Switch to 64 bit mode now by switching to a 64 bit code segment.
296 * then set up and do a lret to get into 64 bit execution.
298 pushl $B64CODE_SEL
299 pushl $longmode
300 lret
301 longmode:
302 .code64
303 movq $0xffffffff00000000,%rdx
304 orq %rdx, %rsi /* set upper bits of entry addr */
305 notq %rdx
306 andq %rdx, %rdi /* clean %rdi for passing arg */
307 call *%rsi
309 #else
310 #error "undefined target"
311 #endif
313 .code32
316 * if reset fails halt the system
318 ENTRY_NP(dboot_halt)
320 SET_SIZE(dboot_halt)
323 * flush the TLB
325 ENTRY_NP(reload_cr3)
326 movl %cr3, %eax
327 movl %eax, %cr3
329 SET_SIZE(reload_cr3)
332 * Detect if we can do cpuid, see if we can change bit 21 of eflags.
333 * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s.
334 * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels.
336 ENTRY_NP(have_cpuid)
337 pushf
338 pushf
339 xorl %eax, %eax
340 popl %ecx
341 movl %ecx, %edx
342 xorl $0x200000, %ecx
343 pushl %ecx
344 popf
345 pushf
346 popl %ecx
347 cmpl %ecx, %edx
348 setne %al
349 popf
351 SET_SIZE(have_cpuid)
354 * We want the GDT to be on its own page for better performance
355 * running under hypervisors.
357 .skip 4096
358 #include "../boot/boot_gdt.s"
359 .skip 4096
360 .long 0
362 #endif /* __lint */