-
Notifications
You must be signed in to change notification settings - Fork 215
/
Copy pathstage_2.s
105 lines (86 loc) · 2.41 KB
/
stage_2.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
.section .boot, "awx"
.intel_syntax noprefix
.code16
# This stage sets the target operating mode, loads the kernel from disk,
# creates an e820 memory map, enters protected mode, and jumps to the
# third stage.
second_stage_start_str: .asciz "Booting (second stage)..."
kernel_load_failed_str: .asciz "Failed to load kernel from disk"
kernel_load_failed:
lea si, [kernel_load_failed_str]
call real_mode_println
kernel_load_failed_spin:
jmp kernel_load_failed_spin
stage_2:
lea si, [second_stage_start_str]
call real_mode_println
set_target_operating_mode:
# Some BIOSs assume the processor will only operate in Legacy Mode. We change the Target
# Operating Mode to "Long Mode Target Only", so the firmware expects each CPU to enter Long Mode
# once and then stay in it. This allows the firmware to enable mode-specifc optimizations.
# We save the flags, because CF is set if the callback is not supported (in which case, this is
# a NOP)
pushf
mov ax, 0xec00
mov bl, 0x2
int 0x15
popf
load_kernel_from_disk:
# start of memory buffer
lea eax, _kernel_buffer
mov [dap_buffer_addr], ax
# number of disk blocks to load
mov word ptr [dap_blocks], 1
# number of start block
mov eax, offset _kernel_start_addr
mov ebx, offset _start
sub eax, ebx
shr eax, 9 # divide by 512 (block size)
mov [dap_start_lba], eax
# destination address
mov edi, 0x400000
# block count
lea ecx, _kernel_size
add ecx, 511 # align up
shr ecx, 9
load_next_kernel_block_from_disk:
# load block from disk
lea si, dap
mov ah, 0x42
int 0x13
jc kernel_load_failed
# copy block to 2MiB
push ecx
push esi
mov ecx, 512 / 4
# move with zero extension
# because we are moving a word ptr
# to esi, a 32-bit register.
movzx esi, word ptr [dap_buffer_addr]
# move from esi to edi ecx times.
rep movsd [edi], [esi]
pop esi
pop ecx
# next block
mov eax, [dap_start_lba]
add eax, 1
mov [dap_start_lba], eax
sub ecx, 1
jnz load_next_kernel_block_from_disk
create_memory_map:
lea di, es:[_memory_map]
call do_e820
video_mode_config:
call config_video_mode
enter_protected_mode_again:
cli
lgdt [gdt32info]
mov eax, cr0
or al, 1 # set protected mode bit
mov cr0, eax
push 0x8
lea eax, [stage_3]
push eax
retf
spin32:
jmp spin32