forked from yuan-xy/Linux-0.11
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootsect.s
272 lines (247 loc) · 6.19 KB
/
bootsect.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
.code16
# rewrite with AT&T syntax by falcon <[email protected]> at 081012
#
# SYS_SIZE is the number of clicks (16 bytes) to be loaded.
# 0x3000 is 0x30000 bytes = 196kB, more than enough for current
# versions of linux
#
.equ SYSSIZE, 0x3000
#
# bootsect.s (C) 1991 Linus Torvalds
#
# bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
# iself out of the way to address 0x90000, and jumps there.
#
# It then loads 'setup' directly after itself (0x90200), and the system
# at 0x10000, using BIOS interrupts.
#
# NOTE! currently system is at most 8*65536 bytes long. This should be no
# problem, even in the future. I want to keep it simple. This 512 kB
# kernel size should be enough, especially as this doesn't contain the
# buffer cache as in minix
#
# The loader has been made as simple as possible, and continuos
# read errors will result in a unbreakable loop. Reboot by hand. It
# loads pretty fast by getting whole sectors at a time whenever possible.
.global _start, begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
.equ SETUPLEN, 4 # nr of setup-sectors
.equ BOOTSEG, 0x07c0 # original address of boot-sector
.equ INITSEG, 0x9000 # we move boot here - out of the way
.equ SETUPSEG, 0x9020 # setup starts here
.equ SYSSEG, 0x1000 # system loaded at 0x10000 (65536).
.equ ENDSEG, SYSSEG + SYSSIZE # where to stop loading
# ROOT_DEV: 0x000 - same type of floppy as boot.
# 0x301 - first partition on first drive etc
#
##和源码不同,源码中是0x306 第2块硬盘的第一个分区
#
.equ ROOT_DEV, 0x301
ljmp $BOOTSEG, $_start
_start:
mov $BOOTSEG, %ax #将ds段寄存器设置为0x7C0
mov %ax, %ds
mov $INITSEG, %ax #将es段寄存器设置为0x900
mov %ax, %es
mov $256, %cx #设置移动计数值256字
sub %si, %si #源地址 ds:si = 0x07C0:0x0000
sub %di, %di #目标地址 es:si = 0x9000:0x0000
rep #重复执行并递减cx的值
movsw #从内存[si]处移动cx个字到[di]处
ljmp $INITSEG, $go #段间跳转,这里INITSEG指出跳转到的段地址,解释了cs的值为0x9000
go: mov %cs, %ax #将ds,es,ss都设置成移动后代码所在的段处(0x9000)
mov %ax, %ds
mov %ax, %es
# put stack at 0x9ff00.
mov %ax, %ss
mov $0xFF00, %sp # arbitrary value >>512
# load the setup-sectors directly after the bootblock.
# Note that 'es' is already set up.
#
##ah=0x02 读磁盘扇区到内存 al=需要独出的扇区数量
##ch=磁道(柱面)号的低八位 cl=开始扇区(位0-5),磁道号高2位(位6-7)
##dh=磁头号 dl=驱动器号(硬盘则7要置位)
##es:bx ->指向数据缓冲区;如果出错则CF标志置位,ah中是出错码
#
load_setup:
mov $0x0000, %dx # drive 0, head 0
mov $0x0002, %cx # sector 2, track 0
mov $0x0200, %bx # address = 512, in INITSEG
.equ AX, 0x0200+SETUPLEN
mov $AX, %ax # service 2, nr of sectors
int $0x13 # read it
jnc ok_load_setup # ok - continue
mov $0x0000, %dx
mov $0x0000, %ax # reset the diskette
int $0x13
jmp load_setup
ok_load_setup:
# Get disk drive parameters, specifically nr of sectors/track
mov $0x00, %dl
mov $0x0800, %ax # AH=8 is get drive parameters
int $0x13
mov $0x00, %ch
#seg cs
mov %cx, %cs:sectors+0 # %cs means sectors is in %cs
mov $INITSEG, %ax
mov %ax, %es
# Print some inane message
mov $0x03, %ah # read cursor pos
xor %bh, %bh
int $0x10
mov $30, %cx
mov $0x0007, %bx # page 0, attribute 7 (normal)
#lea msg1, %bp
mov $msg1, %bp
mov $0x1301, %ax # write string, move cursor
int $0x10
# ok, we've written the message, now
# we want to load the system (at 0x10000)
mov $SYSSEG, %ax
mov %ax, %es # segment of 0x010000
call read_it
call kill_motor
# After that we check which root-device to use. If the device is
# defined (#= 0), nothing is done and the given device is used.
# Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
# on the number of sectors that the BIOS reports currently.
#seg cs
mov %cs:root_dev+0, %ax
cmp $0, %ax
jne root_defined
#seg cs
mov %cs:sectors+0, %bx
mov $0x0208, %ax # /dev/ps0 - 1.2Mb
cmp $15, %bx
je root_defined
mov $0x021c, %ax # /dev/PS0 - 1.44Mb
cmp $18, %bx
je root_defined
undef_root:
jmp undef_root
root_defined:
#seg cs
mov %ax, %cs:root_dev+0
# after that (everyting loaded), we jump to
# the setup-routine loaded directly after
# the bootblock:
ljmp $SETUPSEG, $0
# This routine loads the system at address 0x10000, making sure
# no 64kB boundaries are crossed. We try to load it as fast as
# possible, loading whole tracks whenever we can.
#
# in: es - starting address segment (normally 0x1000)
#
sread: .word 1+ SETUPLEN # sectors read of current track
head: .word 0 # current head
track: .word 0 # current track
read_it:
mov %es, %ax
test $0x0fff, %ax
die: jne die # es must be at 64kB boundary
xor %bx, %bx # bx is starting address within segment
rp_read:
mov %es, %ax
cmp $ENDSEG, %ax # have we loaded all yet?
jb ok1_read
ret
ok1_read:
#seg cs
mov %cs:sectors+0, %ax
sub sread, %ax
mov %ax, %cx
shl $9, %cx
add %bx, %cx
jnc ok2_read
je ok2_read
xor %ax, %ax
sub %bx, %ax
shr $9, %ax
ok2_read:
call read_track
mov %ax, %cx
add sread, %ax
#seg cs
cmp %cs:sectors+0, %ax
jne ok3_read
mov $1, %ax
sub head, %ax
jne ok4_read
incw track
ok4_read:
mov %ax, head
xor %ax, %ax
ok3_read:
mov %ax, sread
shl $9, %cx
add %cx, %bx
jnc rp_read
mov %es, %ax
add $0x1000, %ax
mov %ax, %es
xor %bx, %bx
jmp rp_read
read_track:
push %ax
push %bx
push %cx
push %dx
mov track, %dx
mov sread, %cx
inc %cx
mov %dl, %ch
mov head, %dx
mov %dl, %dh
mov $0, %dl
and $0x0100, %dx
mov $2, %ah
int $0x13
jc bad_rt
pop %dx
pop %cx
pop %bx
pop %ax
ret
bad_rt: mov $0, %ax
mov $0, %dx
int $0x13
pop %dx
pop %cx
pop %bx
pop %ax
jmp read_track
#/*
# * This procedure turns off the floppy drive motor, so
# * that we enter the kernel in a known state, and
# * don't have to worry about it later.
# */
kill_motor:
push %dx
mov $0x3f2, %dx
mov $0, %al
outsb
pop %dx
ret
sectors:
.word 0
msg1:
.byte 13,10
.ascii "IceCityOS is booting ..."
.byte 13,10,13,10
.org 508
root_dev:
.word ROOT_DEV
boot_flag:
.word 0xAA55
.text
endtext:
.data
enddata:
.bss
endbss: