-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboot.s
177 lines (132 loc) · 3.63 KB
/
boot.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Stałe niezbędne dla MULTIBOOT
.set ALIGN, 0x01
.set MEMINFO, 0x10
.set FLAGS, ALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
// Zapisanie w pamięci wcześniej zdefiniowanych stałych.
// Bootloader szuka wartości MAGIC i odczytuje dwie kolejne
// Musi znajdować się w pierwszych 8kb programu jądra
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
// Tworzy stos o rozmiarze 16kb.
// Wygamane jest aby był wyrówanany do 16 bajtów
// Stos rośnie w dół - rejestr ESP jest dekrementowany
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
// Rozmiar i adres globalnej tablicy deskryptorów GDT
gdtr:
.word 0
.long 0
// Rozmiar i adres tablicy deskryptorów przerwań IDT
idtr:
.word 0
.long 0
// Adres struktury multiboot
multiboot_info:
.long 0
.text
// Zwraca adres struktury multiboot_info
// Wywoływane z poziomu C - unsigned int get_multibot_info(void)
.global get_multibot_info
.type get_multibot_info, @function
get_multibot_info:
movl multiboot_info, %eax
ret
// Ładuje rozmiar i adres globalnej tablicy deskryptorów do rejestru GDTR
// Wywoływane z poziomu C - set_GDT(GDT, sizeof(GDT)-1)
.global set_GDT
.type set_GDT, @function
set_GDT:
mov 4(%esp), %eax
mov %eax, gdtr+2
mov 8(%esp), %ax
mov %ax, gdtr
lgdt gdtr
ret
// Ładuje rozmiar i adres tablicy deskryptorów przerwań do rejestru IDTR
// Wywoływane z poziomu C - set_IDT(IDT, sizeof(IDT)-1)
.global set_IDT
.type set_IDT, @function
set_IDT:
mov 4(%esp), %eax
mov %eax, idtr+2
mov 8(%esp), %ax
mov %ax, idtr
lidt idtr
sti
ret
// Ładuje selektory do rejestrów segmentowych procesora
// Wywoływanie z poziomu C - reload_segments()
.global reload_segments
.type reload_segments, @function
reload_segments:
ljmp $0x8, $reload_CS
.global reload_CS
reload_CS:
MOV $0x10, %ax
MOV %ax, %ds
MOV %ax, %es
MOV %ax, %fs
MOV %ax, %gs
MOV %ax, %ss
RET
// Zwraca stan licznika PIT
// Wywoływane z poziomu C - unsigned short read_pit_count(void)
.global read_PIT_count
.type read_PIT_count, @function
read_PIT_count:
pushf // Zrzucamy na stos rejestr EFLAG, 4 bajty - teraz parametry są głębiej
cli
mov $0, %al
out %al, $0x43 // Polecenie Counter Latch
in $0x40, %al // Odczyt pierwszego bajtu
mov %al, %ah
in $0x40, %al // Odczyt drugiego bajtu
rol $8, %ax
sti
popf
ret
// Ustala stan licznika PIT
// Wywoływane z poziomu C - void set_PIT_count(unsigned short count)
.global set_PIT_count
.type set_PIT_count, @function
set_PIT_count:
pushf
cli
mov 8(%esp), %al
out %al, $0x40 // Set low byte of reload value
rol $8, %ax // al = high byte, ah = low byte
mov 9(%esp), %al
out %al, $0x40 // Set high byte of reload value
rol $8, %ax // al = low byte, ah = high byte (ax = original reload value)
sti
popf
ret
// Tryb pracy procesora jest zmieniany na tryb chroniony
// Ustawiamy bit PE - pierwszy bit w rejestrze CR0
// Wyłącza to adresowanie płaskie i umożliwia mechanizmy takie jak stronicowanie i segmentacja
.type enter_protection_mode, @function
enter_protected_mode:
mov %cr0, %eax
or $0x01, %eax
mov %eax, %cr0
ret
// Wykonywanie rozpoczyna się od tej procedury
.global _start
.type _start, @function
_start:
mov %ebx, multiboot_info
cli
call enter_protected_mode
mov $stack_top, %esp
call kernel_main
1: hlt
jmp 1b
.size _start, . - _start