4 ##############################################################################
7 # This code should be stored in the first sector of the hard disk. When the
8 # BIOS runs, it loads this code at physical address 0x7c00-0x7e00 (512 bytes).
9 # Then it jumps to the beginning of it, in real mode.
10 # This code switches into protected mode (32-bit mode) so that all of
11 # memory can accessed, loads the kernel into memory, and jumps to the
12 # first byte of the kernel, where start.S is linked.
13 ##############################################################################
15 .globl start # Entry point
16 start: .code16 # This runs in real mode
17 cli # Disable interrupts
20 movw %ax,%es # Address
23 movw $start,%sp # stack (grows down)
26 #### Address line 20 is tied to low when the machine boots,
27 #### obviously this a bit of a drag, such as when trying to
28 #### address memory above 1MB. This code undoes this.
30 1: inb $0x64,%al # Get status
31 testb $0x2,%al # Busy?
33 movb $0xd1,%al # Command: Write
34 outb %al,$0x64 # output port
35 2: inb $0x64,%al # Get status
36 testb $0x2,%al # Busy?
38 movb $0xdf,%al # Enable
41 #### Get memory size, via interrupt 15h function 88h.
42 #### Returns CF clear if successful, with AX = (kB of physical memory) - 1024.
43 #### This only works for memory sizes <= 65 MB, which should be fine for our purposes.
47 jc panic # Carry flag set on error
48 2: addl $1024,%eax # Total kB
49 shrl $2,%eax # Total 4 kB pages
52 #### switch from real to protected mode
53 #### The segments in GDT allow all of physical memory to be accessed.
54 #### Furthermore, the segments have base addresses of 0, so that the
55 #### segment translation is a NOP, ie. virtual addresses are identical to
56 #### their physical addresses. With this setup, it appears to this code
57 #### that it is running directly on physical memory.
59 cli # Mandatory since we dont set up an IDT
60 lgdt gdtdesc # load GDT -- mandatory in protected mode
61 movl %cr0, %eax # turn on protected mode
64 ### CPU magic: jump to relocation, flush prefetch queue, and
65 ### reload %cs Has the effect of just jmp to the next
66 ### instruction, but simultaneous loads CS with
68 ljmp $SEL_KCSEG, $protcseg
70 #### We are in protected mode in a 32-bit segment (hence the .code32)
73 movw $SEL_KDSEG, %ax # set up data segment registers
80 #### Load kernel starting at physical address LOADER_KERN_BASE by
81 #### frobbing the IDE controller directly.
84 movl $LOADER_KERN_BASE, %edi
87 ### Poll status register while controller busy.
93 ### Read a single sector.
98 ### Sector number to write in low 28 bits.
99 ### LBA mode, device 0 in top 4 bits.
101 andl $0x0fffffff, %eax
102 orl $0xe0000000, %eax
104 ### Dump %eax to ports 0x1f3...0x1f6.
111 ### READ command to command register.
116 ### Poll status register while controller busy.
121 ### Poll status register until data ready.
133 cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx
136 ##### Create temporary page directory and page table, set page
137 ##### directory pointer, and turn on paging.
138 ##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages.
140 # Create page directory at 64 kB.
144 # Fill page directory with zeroes.
149 # Set PDEs for 0 and LOADER_PHYS_BASE to point to the
151 movl $0x11000 | PG_U | PG_W | PG_P, %eax
153 movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20)
155 # Initialize page table.
156 movl $PG_U | PG_W | PG_P, %eax
169 ##### Turn on EM bit in CR0, forcing most floating-point instructions
170 ##### to trap. We don't support floating-point or MMX.
176 ##### Jump to kernel entry point.
178 movl $LOADER_PHYS_BASE + LOADER_BASE, %esp
179 movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax
185 .quad 0x0000000000000000 # null seg
186 .quad 0x00cf9a000000ffff # code seg
187 .quad 0x00cf92000000ffff # data seg
190 .word 0x17 # sizeof (gdt) - 1
191 .long gdt # address gdt
193 ##### To panic, we print panicmsg (with help from the BIOS) and spin.
194 panic: .code16 # We only panic in real mode.
205 .ascii "Loader panic!\r\n"
208 ##### Memory size in 4 kB pages.
209 .org LOADER_RAM_PAGES - LOADER_BASE
213 ##### Command-line arguments inserted by another utility.
214 ##### The loader doesn't use these, but we note their
215 ##### location here for easy reference.
216 .org LOADER_CMD_LINE - LOADER_BASE
220 ##### Boot-sector signature for BIOS inspection.
221 .org LOADER_BIOS_SIG - LOADER_BASE