Rename printk() to printf().
[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 #include "threads/mmu.h"
43         
44 ##############################################################################
45 # Kernel loader.
46 #
47 # This code should be stored in the first sector of the hard disk.  When the  
48 # BIOS runs, it loads this code at physical address 0x7c00-0x7e00 (512 bytes).
49 # Then it jumps to the beginning of it, in real mode.  
50 # This code switches into protected mode (32-bit mode) so that all of
51 # memory can accessed, loads the kernel into memory, and jumps to the
52 # first byte of the kernel, where start.S is linked.
53 ##############################################################################
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 .globl start                            # Entry point   
62 start:  .code16                         # This runs in real mode
63         cli                             # Disable interrupts
64         cld                             # String ops inc
65         xorw %ax,%ax                    # Zero
66         movw %ax,%es                    # Address
67         movw %ax,%ds                    #  data
68         movw %ax,%ss                    # Set up
69         movw $start,%sp                 #  stack (grows down)
70         
71 #### Enable A20:
72 ####   Address line 20 is tied to low when the machine boots, 
73 ####   obviously this a bit of a drag, such as when trying to
74 ####   address memory above 1MB.  This code undoes this.
75         
76 1:      inb $0x64,%al           # Get status
77         testb $0x2,%al          # Busy?
78         jnz 1b                  # Yes
79         movb $0xd1,%al          # Command: Write
80         outb %al,$0x64          #  output port
81 2:      inb $0x64,%al           # Get status
82         testb $0x2,%al          # Busy?
83         jnz 2b                  # Yes
84         movb $0xdf,%al          # Enable
85         outb %al,$0x60          #  A20
86
87 #### Get memory size, via interrupt 15h function 88h.
88 #### Returns CF clear if successful, with AX = (kB of physical memory) - 1024.
89 #### This only works for memory sizes <= 65 MB, which should be fine for our purposes.
90         
91         movb $0x88,%ah
92         int $0x15
93         jc panic                # Carry flag set on error
94 2:      addl $1024,%eax         # Total kB
95         shrl $2,%eax            # Total 4 kB pages
96         movl %eax, ram_pages
97         
98 #### switch from real to protected mode 
99 ####     The segments in GDT allow all of physical memory to be accessed.
100 ####     Furthermore, the segments have base addresses of 0, so that the
101 ####     segment translation is a NOP, ie. virtual addresses are identical to
102 ####     their physical addresses.  With this setup, it appears to this code
103 ####     that it is running directly on physical memory.
104         
105         cli                     # Mandatory since we dont set up an IDT
106         lgdt gdtdesc            # load GDT -- mandatory in protected mode
107         movl %cr0, %eax         # turn on protected mode
108         orl $CR0_PE, %eax       # 
109         movl %eax, %cr0         # 
110         ### CPU magic: jump to relocation, flush prefetch queue, and
111         ### reload %cs Has the effect of just jmp to the next
112         ### instruction, but simultaneous loads CS with
113         ### $PROT_MODE_CSEG.
114         ljmp $SEL_KCSEG, $protcseg
115         
116 #### We are in protected mode in a 32-bit segment (hence the .code32)
117 protcseg:
118         .code32
119         movw $SEL_KDSEG, %ax    # set up data segment registers
120         movw %ax, %ds           
121         movw %ax, %es           
122         movw %ax, %fs           
123         movw %ax, %gs           
124         movw %ax, %ss
125
126 #### Load kernel starting at physical address LOADER_KERN_BASE by
127 #### frobbing the IDE controller directly.
128
129         movl $1, %ebx
130         movl $LOADER_KERN_BASE, %edi
131 read_sector:
132
133         ### Poll status register while controller busy.
134         movl $0x1f7, %edx
135 1:      inb %dx, %al
136         testb $0x80, %al
137         jnz 1b
138
139         ### Read a single sector.
140         movl $0x1f2, %edx
141         movb $1, %al
142         outb %al, %dx
143
144         ### Sector number to write in low 28 bits.
145         ### LBA mode, device 0 in top 4 bits.
146         movl %ebx, %eax
147         andl $0x0fffffff, %eax
148         orl $0xe0000000, %eax
149
150         ### Dump %eax to ports 0x1f3...0x1f6.
151         movl $4, %ecx
152 2:      incw %dx
153         outb %al, %dx
154         shrl $8, %eax
155         loop 2b
156
157         ### READ command to command register.
158         incw %dx
159         movb $0x20, %al
160         outb %al, %dx
161
162         ### Poll status register while controller busy.
163 1:      inb %dx, %al
164         testb $0x80, %al
165         jnz 1b
166
167         ### Poll status register until data ready.
168 1:      inb %dx, %al
169         testb $0x08, %al
170         jz 1b
171
172         ### Transfer sector.
173         movl $512 / 4, %ecx
174         movl $0x1f0, %edx
175         rep insl
176
177         ### Next sector.
178         incl %ebx
179         cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx
180         jnz read_sector
181
182 ##### Create temporary page directory and page table, set page
183 ##### directory pointer, and turn on paging.
184 ##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages.
185
186         # Create page directory at 64 kB.
187         movl $0x10000, %edi             
188         movl %edi, %cr3
189
190         # Fill page directory with zeroes.
191         subl %eax, %eax
192         movl $0x400, %ecx
193         rep stosl
194
195         # Set PDEs for 0 and LOADER_PHYS_BASE to point to the
196         # page table.
197         movl $0x11000 | PG_U | PG_W | PG_P, %eax
198         movl %eax, 0x10000
199         movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20)
200
201         # Initialize page table.
202         movl $PG_U | PG_W | PG_P, %eax
203         movl $0x400, %ecx
204 1:      stosl
205         addl $0x1000, %eax
206         loop 1b
207
208         # Turn on paging and kernel write-protect.
209         movl %cr0, %eax
210         orl $CR0_PG | CR0_WP, %eax
211         movl %eax, %cr0
212         jmp 1f
213 1:
214
215 ##### Turn on EM bit in CR0, forcing most floating-point instructions
216 ##### to trap.  We don't support floating-point or MMX.
217
218         movl %cr0, %eax
219         orl $CR0_EM, %eax
220         movl %eax, %cr0
221         
222 ##### Jump to kernel entry point.
223
224         movl $LOADER_PHYS_BASE + 0x20000, %esp
225         movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax
226         call *%eax
227         jmp panic
228
229 ##### GDT
230
231 gdt:
232         .quad 0x0000000000000000        # null seg
233         .quad 0x00cf9a000000ffff        # code seg
234         .quad 0x00cf92000000ffff        # data seg
235         
236 gdtdesc:
237         .word   0x17                    # sizeof (gdt) - 1
238         .long   gdt                     # address gdt
239
240 ##### To panic, we print panicmsg (with help from the BIOS) and spin.
241 panic:  .code16                 # We only panic in real mode.
242         movw $panicmsg, %si
243         movb $0xe, %ah
244         xorb %bh, %bh
245 1:      lodsb
246         test %al, %al
247 2:      jz 2b                   # Spin.
248         int $0x10
249         jmp 1b
250
251 panicmsg:
252         .ascii "Loader panic!\r\n"
253         .byte 0
254
255 ##### Memory size in 4 kB pages.
256         .org LOADER_RAM_PAGES - LOADER_BASE
257 ram_pages:
258         .long 0
259
260 ##### Command-line arguments inserted by another utility.
261 ##### The loader doesn't use these, but we note their
262 ##### location here for easy reference.
263         .org LOADER_CMD_LINE - LOADER_BASE
264 cmd_line:
265         .fill 0x80, 1, 0
266
267 ##### Boot-sector signature for BIOS inspection.
268         .org LOADER_BIOS_SIG - LOADER_BASE
269         .word 0xaa55