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 /* Flags in control register 0 */
16 #define CR0_PE 0x00000001 /* Protection Enable. */
17 #define CR0_EM 0x00000004 /* (Floating-point) Emulation. */
18 #define CR0_PG 0x80000000 /* Paging. */
20 .globl start # Entry point
21 start: .code16 # This runs in real mode
22 cli # Disable interrupts
25 movw %ax,%es # Address
28 movw $start,%sp # stack (grows down)
31 #### Address line 20 is tied to low when the machine boots,
32 #### obviously this a bit of a drag, such as when trying to
33 #### address memory above 1MB. This code undoes this.
35 1: inb $0x64,%al # Get status
36 testb $0x2,%al # Busy?
38 movb $0xd1,%al # Command: Write
39 outb %al,$0x64 # output port
40 2: inb $0x64,%al # Get status
41 testb $0x2,%al # Busy?
43 movb $0xdf,%al # Enable
46 #### Get memory size, via interrupt 15h function 88h.
47 #### Returns CF clear if successful, with AX = (kB of physical memory) - 1024.
48 #### This only works for memory sizes <= 65 MB, which should be fine for our purposes.
52 jc panic # Carry flag set on error
53 2: addl $1024,%eax # Total kB
54 shrl $2,%eax # Total 4 kB pages
57 #### switch from real to protected mode
58 #### The segments in GDT allow all of physical memory to be accessed.
59 #### Furthermore, the segments have base addresses of 0, so that the
60 #### segment translation is a NOP, ie. virtual addresses are identical to
61 #### their physical addresses. With this setup, it appears to this code
62 #### that it is running directly on physical memory.
64 cli # Mandatory since we dont set up an IDT
65 lgdt gdtdesc # load GDT -- mandatory in protected mode
66 movl %cr0, %eax # turn on protected mode
69 ### CPU magic: jump to relocation, flush prefetch queue, and
70 ### reload %cs Has the effect of just jmp to the next
71 ### instruction, but simultaneous loads CS with
73 ljmp $SEL_KCSEG, $protcseg
75 #### We are in protected mode in a 32-bit segment (hence the .code32)
78 movw $SEL_KDSEG, %ax # set up data segment registers
85 #### Load kernel starting at physical address LOADER_KERN_BASE by
86 #### frobbing the IDE controller directly.
89 movl $LOADER_KERN_BASE, %edi
92 ### Poll status register while controller busy.
98 ### Read a single sector.
103 ### Sector number to write in low 28 bits.
104 ### LBA mode, device 0 in top 4 bits.
106 andl $0x0fffffff, %eax
107 orl $0xe0000000, %eax
109 ### Dump %eax to ports 0x1f3...0x1f6.
116 ### READ command to command register.
121 ### Poll status register while controller busy.
126 ### Poll status register until data ready.
138 cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx
141 ##### Create temporary page directory and page table, set page
142 ##### directory pointer, and turn on paging.
143 ##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages.
145 # Create page directory at 64 kB.
149 # Fill page directory with zeroes.
154 # Set PDEs for 0 and LOADER_PHYS_BASE to point to the
156 movl $0x11000 | PG_U | PG_W | PG_P, %eax
158 movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20)
160 # Initialize page table.
161 movl $PG_U | PG_W | PG_P, %eax
174 ##### Turn on EM bit in CR0, forcing most floating-point instructions
175 ##### to trap. We don't support floating-point or MMX.
181 ##### Jump to kernel entry point.
183 movl $LOADER_PHYS_BASE + LOADER_BASE, %esp
184 movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax
190 .quad 0x0000000000000000 # null seg
191 .quad 0x00cf9a000000ffff # code seg
192 .quad 0x00cf92000000ffff # data seg
195 .word 0x17 # sizeof (gdt) - 1
196 .long gdt # address gdt
198 ##### To panic, we print panicmsg (with help from the BIOS) and spin.
199 panic: .code16 # We only panic in real mode.
210 .ascii "Loader panic!\r\n"
213 ##### Memory size in 4 kB pages.
214 .org LOADER_RAM_PAGES - LOADER_BASE
218 ##### Command-line arguments inserted by another utility.
219 ##### The loader doesn't use these, but we note their
220 ##### location here for easy reference.
221 .org LOADER_CMD_LINE - LOADER_BASE
225 ##### Boot-sector signature for BIOS inspection.
226 .org LOADER_BIOS_SIG - LOADER_BASE