[CRT] Massively improve performance of rand_s
[reactos.git] / boot / freeldr / freeldr / arch / i386 / multiboot.S
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <asm.inc>
21 #include <arch/pc/x86common.h>
22 #include <multiboot.h>
23
24 /* Multiboot support
25 *
26 * Allows freeldr to be loaded as a "multiboot kernel" by
27 * other boot loaders like GRUB.
28 * This code is not referenced from anywhere. GRUB searches for
29 * the header signature and uses the header to load it.
30 */
31
32 #define MB_INFO_SIZE 60 /* sizeof(multiboot_info_t) */
33 #define MB_INFO_FLAGS_OFFSET 0
34 #define MB_INFO_BOOT_DEVICE_OFFSET 12
35 #define MB_INFO_COMMAND_LINE_OFFSET 16
36 #define MB_INFO_MMAP_LEN_OFFSET 44
37 #define MB_INFO_MMAP_ADDR_OFFSET 48
38 #define MB_MMAP_SIZE 480 /* 20 * sizeof(memory_map_t) - up to 20 entries */
39 #define CMDLINE_SIZE 256
40
41 /*
42 * We want to execute at FREELDR_BASE (to be compatible with
43 * bootsector loading), but GRUB only allows loading of
44 * multiboot kernels above 1MB. So we let GRUB load us
45 * there and then relocate ourself to FREELDR_BASE.
46 */
47 #define INITIAL_BASE HEX(200000)
48
49
50 #ifdef _USE_ML
51 EXTERN __bss_start__:DWORD
52 EXTERN __bss_end__:DWORD
53 #endif
54
55
56 #ifdef _USE_ML
57 .MBDATA SEGMENT PUBLIC 'DATA'
58 //ASSUME nothing
59 #endif
60
61 /* Align to 32 bits boundary */
62 .align 4
63
64 /* Multiboot header */
65 MultibootHeader:
66 /* magic */
67 .long MULTIBOOT_HEADER_MAGIC
68 /* flags */
69 .long MULTIBOOT_HEADER_FLAGS
70 /* checksum */
71 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
72 /* header_addr */
73 .long MultibootHeader + INITIAL_BASE - FREELDR_BASE
74 /* load_addr */
75 .long INITIAL_BASE
76 /* load_end_addr */
77 .long 0
78 /* bss_end_addr */
79 .long 0
80 /* entry_addr */
81 .long MultibootEntry + INITIAL_BASE - FREELDR_BASE
82
83 #ifdef _USE_ML
84 .MBDATA ENDS
85 #endif
86
87
88 .code32
89 ASSUME ES:NOTHING, FS:NOTHING, GS:NOTHING
90
91 MultibootEntry:
92 cld
93
94 /* Check for valid multiboot signature */
95 cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
96 jne mbfail
97
98 /* Save multiboot info structure */
99 mov esi, ebx
100 mov edi, offset MultibootInfo + INITIAL_BASE - FREELDR_BASE
101 mov ecx, (MB_INFO_SIZE / 4)
102 rep movsd
103 mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], 0
104 mov dword ptr ds:[_MultibootInfoPtr + INITIAL_BASE - FREELDR_BASE], offset MultibootInfo
105
106 /* See if the memory map was passed in */
107 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_MEMORY_MAP
108 jz mbchk_command_line
109 /* Check memory map length */
110 mov ecx, dword ptr ds:[ebx + MB_INFO_MMAP_LEN_OFFSET]
111 test ecx, ecx
112 jz mbchk_command_line
113 cmp ecx, MB_MMAP_SIZE
114 jg mbchk_command_line
115 /* Check memory map address */
116 mov esi, dword ptr ds:[ebx + MB_INFO_MMAP_ADDR_OFFSET]
117 test esi, esi
118 jz mbchk_command_line
119 /* Save memory map structure */
120 mov edi, offset MultibootMemoryMap + INITIAL_BASE - FREELDR_BASE
121 shr ecx, 2
122 rep movsd
123 /* Relocate memory map address */
124 mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], offset MultibootMemoryMap
125
126 mbchk_command_line:
127 /* Save command line */
128 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
129 jz mb2
130 mov esi, dword ptr ds:[ebx + MB_INFO_COMMAND_LINE_OFFSET]
131 mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
132 mov ecx, CMDLINE_SIZE - 1
133 mb1:
134 lodsb
135 stosb
136 test al, al
137 jz mb2
138 dec ecx
139 jnz mb1
140
141 mb2:
142 /* See if the boot device was passed in */
143 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_BOOT_DEVICE
144
145 /* If no boot device known, assume first partition of first harddisk */
146 mov dx, HEX(0180)
147 jz mb3
148
149 /* Load boot drive into DL, boot partition into DH */
150 mov edx, dword ptr ds:[ebx + MB_INFO_BOOT_DEVICE_OFFSET]
151 bswap edx
152 inc dh
153
154 mb3:
155 /* Relocate itself to lower address */
156 mov esi, INITIAL_BASE
157 mov edi, FREELDR_BASE
158 mov ecx, offset __bss_start__ - FREELDR_BASE
159 shr ecx, 2
160 rep movsd
161
162 /* Load segment registers for real-address mode */
163 #ifdef _USE_ML
164 lgdt fword ptr ds:[gdtptr]
165 #else
166 lgdt ds:[gdtptr]
167 #endif
168 mov ax, HEX(10)
169 mov ds, ax
170 mov es, ax
171 mov fs, ax
172 mov gs, ax
173 mov ss, ax
174
175 /* Jump to relocated code */
176 ljmp HEX(08), mb4
177
178 mbfail:
179 int 3
180 mbstop:
181 jmp short mbstop /* We should never get here */
182
183 .code16
184 mb4:
185 /* Disable protected mode */
186 mov eax, cr0
187 and eax, CR0_PE_CLR
188 mov cr0, eax
189
190 /* Jump to real entry point */
191 ljmp16 0, FREELDR_BASE
192 .endcode16
193
194
195 /* Force 8-byte alignment */
196 .align 8
197 gdt:
198 .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
199 .word HEX(FFFF), HEX(0000), HEX(9B00), HEX(008F) /* 08: 16-bit flat CS (!) */
200 .word HEX(FFFF), HEX(0000), HEX(9300), HEX(0000) /* 10: 16-bit real mode DS */
201
202 /* GDT table pointer */
203 gdtptr:
204 .word HEX(17) /* Limit */
205 .long gdt /* Base Address */
206
207 PUBLIC _MultibootInfoPtr
208 _MultibootInfoPtr:
209 .long 0
210
211 MultibootInfo:
212 .space MB_INFO_SIZE
213
214 MultibootMemoryMap:
215 .space MB_MMAP_SIZE
216
217 PUBLIC cmdline
218 cmdline:
219 .space CMDLINE_SIZE
220
221 END