Change assembly from AT&T to Intel syntax.
[pintos-anon] / src / threads / loader.S
1 /* This file is derived from source code used in MIT's 6.828
2    course.  The original copyright notice is reproduced in full
3    below. */
4
5 /*
6  * Copyright (C) 1997 Massachusetts Institute of Technology 
7  *
8  * This software is being provided by the copyright holders under the
9  * following license. By obtaining, using and/or copying this software,
10  * you agree that you have read, understood, and will comply with the
11  * following terms and conditions:
12  *
13  * Permission to use, copy, modify, distribute, and sell this software
14  * and its documentation for any purpose and without fee or royalty is
15  * hereby granted, provided that the full text of this NOTICE appears on
16  * ALL copies of the software and documentation or portions thereof,
17  * including modifications, that you make.
18  *
19  * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
20  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
21  * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR
22  * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
23  * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY
24  * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT
25  * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR
26  * DOCUMENTATION.
27  *
28  * The name and trademarks of copyright holders may NOT be used in
29  * advertising or publicity pertaining to the software without specific,
30  * written prior permission. Title to copyright in this software and any
31  * associated documentation will at all times remain with copyright
32  * holders. See the file AUTHORS which should have accompanied this software
33  * for a list of all copyright holders.
34  *
35  * This file may be derived from previously copyrighted software. This
36  * copyright applies only to those changes made by the copyright
37  * holders listed in the AUTHORS file. The rest of this file is covered by
38  * the copyright notices, if any, listed below.
39  */
40
41 #include "threads/loader.h"
42         
43         .intel_syntax noprefix
44         
45 #### Kernel loader.
46
47 #### This code should be stored in the first sector of the hard disk.
48 #### When the BIOS runs, it loads this code at physical address
49 #### 0x7c00-0x7e00 (512 bytes).  Then it jumps to the beginning of it,
50 #### in real mode.  This code switches into protected mode (32-bit
51 #### mode) so that all of memory can accessed, loads the kernel into
52 #### memory, and jumps to the first byte of the kernel, where start.S
53 #### is linked.
54         
55 /* Flags in control register 0. */
56 #define CR0_PE 0x00000001      /* Protection Enable. */
57 #define CR0_EM 0x00000004      /* (Floating-point) Emulation. */
58 #define CR0_PG 0x80000000      /* Paging. */
59 #define CR0_WP 0x00010000      /* Write-Protect enable in kernel mode. */
60
61 # Code runs in real mode, which is a 16-bit segment.
62
63 .globl start
64 start:
65         .code16
66
67 # Disable interrupts.
68 # String instructions go upward.
69
70         cli
71         cld
72
73 # Set up data segments and stack.
74
75         sub ax, ax
76         mov es, ax
77         mov ds, ax
78
79 # Stack grows downward starting from us.
80 # We don't ever use the stack so this is strictly speaking
81 # unnecessary.
82
83         mov ss, ax
84         mov sp, 0x7c00
85         
86 #### Enable A20.  Address line 20 is tied to low when the machine
87 #### boots, which prevents addressing memory about 1 MB.  This code
88 #### fixes it.
89         
90 # Poll status register while busy.
91
92 1:      in al, 0x64
93         test al, 0x2
94         jnz 1b
95
96 # Send command for writing output port.
97
98         mov al, 0xd1
99         outb 0x64, al
100
101 # Poll status register while busy.
102
103 1:      in al, 0x64
104         test al, 0x2
105         jnz 1b
106
107 # Enable A20 line.
108
109         mov al, 0xdf
110         out 0x60, al
111
112 #### Get memory size, via interrupt 15h function 88h.  Returns CF
113 #### clear if successful, with AX = (kB of physical memory) - 1024.
114 #### This only works for memory sizes <= 65 MB, which should be fine
115 #### for our purposes.  We cap memory at 64 MB because that's all we
116 #### prepare page tables for, below.
117         
118         mov ah, 0x88
119         int 0x15
120         jc panic
121         add eax, 1024           # Total kB memory
122         cmp eax, 0x10000        # Cap at 64 MB
123         jbe 1f
124         mov eax, 0x10000
125 1:      shr eax, 2              # Total 4 kB pages
126         mov ram_pages, eax 
127         
128 #### Create temporary page directory and page table and set page
129 #### directory base register.
130
131 # Create page directory at 64 kB and fill with zeroes.
132         mov ax, 0x1000
133         mov es, ax
134         sub eax, eax
135         sub edi, edi
136         mov ecx, 0x400
137         rep stosd
138
139 # Add PDEs to point to PTEs for the first 64 MB of RAM.
140 # Also add identical PDEs starting at LOADER_PHYS_BASE.
141 # See [IA32-v3] section 3.7.6 for a description of the bits in eax.
142
143         mov eax, 0x11007
144         mov ecx, 0x11
145         sub edi, edi
146 1:      mov es:[di], eax
147         mov es:LOADER_PHYS_BASE / 1024 / 1024[di], eax 
148         add di, 4
149         add eax, 0x1000
150         loop 1b
151
152 # Set up one-to-map linear to physical map for the first 64 MB of RAM.
153 # See [IA32-v3] section 3.7.6 for a description of the bits in eax.
154
155         mov ax, 0x1100
156         mov es, ax
157         mov eax, 0x7
158         mov ecx, 0x4000
159         sub edi, edi
160 1:      mov es:[di], eax 
161         add di, 4 
162         add eax, 0x1000
163         loop 1b
164
165 # Set page directory base register.
166
167         mov eax, 0x10000
168         mov cr3, eax
169         
170 #### Switch to protected mode.
171
172 # First we turn off interrupts because we don't set up an IDT.
173
174         cli
175
176 # Then we point the GDTR to our GDT.  Protected mode requires a GDT.
177 # We need a data32 prefix to ensure that all 32 bits of the GDT
178 # descriptor are loaded (default is to load only 24 bits).
179
180         data32 lgdt gdtdesc
181
182 # Then we turn on the following bits in CR0:
183 #    PE (Protect Enable): this turns on protected mode.
184 #    PG (Paging): turns on paging.
185 #    WP (Write Protect): if unset, ring 0 code ignores
186 #       write-protect bits in page tables (!).
187 #    EM (Emulation): forces floating-point instructions to trap.
188 #       We don't support floating point. 
189         
190         mov eax, cr0
191         or eax, CR0_PE + CR0_PG + CR0_WP + CR0_EM
192         mov cr0, eax
193         
194 # We're now in protected mode in a 16-bit segment.  The CPU still has
195 # the real-mode code segment cached in cs's segment descriptor.  We
196 # need to reload cs, and the easiest way is to use a far jump.
197 # Because we're not in a 32-bit segment the data32 prefix is needed to
198 # jump to a 32-bit offset.
199
200         data32 ljmp SEL_KCSEG, 1f + LOADER_PHYS_BASE
201
202 # We're now in protected mode in a 32-bit segment.
203
204         .code32
205
206 # Reload all the other segment registers and the stack pointer to
207 # point into our new GDT.
208
209 1:      mov ax, SEL_KDSEG
210         mov ds, ax              
211         mov es, ax              
212         mov fs, ax              
213         mov gs, ax              
214         mov ss, ax
215         mov esp, LOADER_PHYS_BASE + 0x30000
216
217 #### Load kernel starting at physical address LOADER_KERN_BASE by
218 #### frobbing the IDE controller directly.
219
220         mov ebx, 1
221         mov edi, LOADER_KERN_BASE + LOADER_PHYS_BASE
222 read_sector:
223
224 # Poll status register while controller busy.
225
226         mov edx, 0x1f7
227 1:      in al, dx
228         test al, 0x80
229         jnz 1b
230
231 # Read a single sector.
232
233         mov edx, 0x1f2
234         mov al, 1 
235         out dx, al
236
237 # Sector number to write in low 28 bits.
238 # LBA mode, device 0 in top 4 bits.
239
240         mov eax, ebx
241         and eax, 0x0fffffff
242         or eax, 0xe0000000
243
244 # Dump eax to ports 0x1f3...0x1f6.
245
246         mov ecx, 4
247 1:      inc dx
248         out dx, al
249         shr eax, 8
250         loop 1b
251
252 # READ command to command register.
253
254         inc dx
255         mov al, 0x20
256         out dx, al
257
258 # Poll status register while controller busy.
259
260 1:      in al, dx
261         test al, 0x80
262         jnz 1b
263
264 # Poll status register until data ready.
265
266 1:      in al, dx
267         test al, 0x08
268         jz 1b
269
270 # Transfer sector.
271
272         mov ecx, 256
273         mov edx, 0x1f0
274         rep insw
275
276 # Next sector.
277
278         inc ebx
279         cmp ebx, KERNEL_LOAD_PAGES*8 + 1
280         jnz read_sector
281
282 #### Jump to kernel entry point.
283
284         mov eax, LOADER_PHYS_BASE + LOADER_KERN_BASE
285         call eax
286         jmp panic
287
288 #### GDT
289
290 gdt:
291         .quad 0x0000000000000000        # null seg
292         .quad 0x00cf9a000000ffff        # code seg
293         .quad 0x00cf92000000ffff        # data seg
294         
295 gdtdesc:
296         .word   0x17                    # sizeof (gdt) - 1
297         .long   gdt + LOADER_PHYS_BASE  # address gdt
298
299 #### Fatal error.
300 #### Print panicmsg (with help from the BIOS) and spin.
301
302 panic:  .code16                 # We only panic in real mode.
303         mov si, offset panicmsg
304         mov ah, 0xe
305         sub bh, bh
306 1:      lodsb
307         test al, al
308 2:      jz 2b                   # Spin.
309         int 0x10
310         jmp 1b
311
312 panicmsg:
313         .ascii "Loader panic!\r\n"
314         .byte 0
315
316 #### Memory size in 4 kB pages.
317         .org LOADER_RAM_PAGES - LOADER_BASE
318 ram_pages:
319         .long 0
320
321 #### Command-line arguments inserted by another utility.
322 #### The loader doesn't use these, but we note their
323 #### location here for easy reference.
324         .org LOADER_CMD_LINE - LOADER_BASE
325 cmd_line:
326         .fill 0x80, 1, 0
327
328 #### Boot-sector signature for BIOS inspection.
329         .org LOADER_BIOS_SIG - LOADER_BASE
330         .word 0xaa55