Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / bsp / boot / x86 / tools / bootsect / bootsect.S @ 03e9c04a

History | View | Annotate | Download (9.54 KB)

1 03e9c04a Brad Neuman
/*-
2
 * Copyright (c) 2005, Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
/**
31
 * bootsect.S - Boot sector for FAT
32
 *
33
 * The boot sector is 512 byte code to load the OS image. It is loaded
34
 * to address 0:7c00 by POST BIOS.
35
 * The boot sector searches the target file within the root directory of
36
 * FAT file system, and loads it to predefined memory address. Then, it
37
 * jumps to the first byte of the loaded image.
38
 *
39
 * All disk access are done by using BIOS Int13h interface. The BIOS
40
 * parameter block (BPB) has the disk/FAT information, and it exists
41
 * in the first portion of the FAT boot sector. It must be filled by the
42
 * FAT format utility, or the prex kernel install utility (mkboot.com).
43
 * This program assumes that correct BPB is stored in the boot sector.
44
 *
45
 * Limitation:
46
 *  - Support only FAT12/16. FAT32 is not supported.
47
 *
48
 * Memory usage:
49
 *  > 5000 - 6FFF ... Disk work area
50
 *  > 7000 - 7BFF ... Stack
51
 *  > 7C00 - 7DFF ... This boot sector
52
 *  >10000 -      ... FAT cache
53
 *  >20000 -      ... Data cache
54
 *  >30000 -      ... Image load address
55
 */
56
.code16
57
.text
58
.align 1
59
60
# Memory locations
61
#define BOOT_STACK		0x7c00
62
63
#define LOAD_ADDR		0x30000
64
#define ENTRY_SEG		0x3000
65
#define ENTRY_OFF		0x0000
66
67
#define WORK_AREA		0x5000
68
#define FAT_SEG			0x1000
69
#define DATA_SEG		0x2000
70
71
#define LOAD_MAX		0xA0000
72
73
# FAT Directory entry
74
#define F_NAME			0
75
#define F_ATTR			11
76
#define F_RESERVED		12
77
#define F_TIME			22
78
#define F_DATA			24
79
#define F_CLUSTER		26
80
#define F_SIZE			28
81
82
#define DIR_SIZE		32
83
#define DIRENT_PER_SECTOR	16
84
85
# BIOS parameter block (BPB) location (%bp points to 0x7c00)
86
#define OEM_ID			0x03(%bp)
87
#define BYTE_PER_SECTOR		0x0b(%bp)
88
#define SECT_PER_CLUSTER	0x0d(%bp)
89
#define RESERVED_SECTORS	0x0e(%bp)
90
#define NUM_OF_FATS		0x10(%bp)
91
#define ROOT_ENTRIES		0x11(%bp)
92
#define TOTAL_SECTORS		0x13(%bp)
93
#define MEDIA_DESCRIPTOR	0x15(%bp)
94
#define SECTORS_PER_FAT		0x16(%bp)
95
#define SECTORS_PER_TRACK	0x18(%bp)
96
#define HEADS			0x1a(%bp)
97
#define HIDDEN_SECTORS		0x1c(%bp)
98
#define BIG_TOTAL_SECTORS	0x20(%bp)
99
#define PHYSICAL_DRIVE		0x24(%bp)
100
#define EXT_BOOT_SIGNATURE	0x26(%bp)
101
#define SERIAL_NO		0x27(%bp)
102
#define VOLUME_ID		0x2b(%bp)
103
#define FILE_SYS_ID		0x36(%bp)
104
105
#define FILE_SYS_ID_NUM		0x3a(%bp)
106
107
# Local data area (Note: These data will overlap the existing code)
108
#define FAT_START		0x40(%bp)
109
#define DATA_START		0x44(%bp)
110
111
.global _boot
112
113
#
114
# Boot the system
115
#
116
_boot:
117
	jmp	start				# Skip BPB
118
	nop					# Nop is for DOS compatibility
119
120
#
121
# BPB
122
#
123
	.ascii	"PREX1.00"
124
.fill 0x33, 1, 0				# Drive parameter must be
125
						# filled by intaller
126
127
#
128
# Setup stack and segment registers
129
#
130
start:
131
	cli
132
	cld					# Clear direction flag
133
	xorl	%eax, %eax			# Set EAX to zero
134
	movw	%ax, %ds
135
	movw	%ax, %es
136
	movw	%ax, %ss
137
	movw	$(BOOT_STACK), %sp
138
	movw	%sp, %bp			# EBP = Bios Parameter Block
139
	sti
140
141
#
142
# Display boot message
143
#
144
	movw	$load_msg, %si
145
	movw	$21, %cx
146
	call	puts
147
148
#
149
# Store disk information
150
#
151
	movl	HIDDEN_SECTORS, %ebx		# Get hidden sector
152
	movw	RESERVED_SECTORS, %ax		# Add reserved sector
153
	addl	%eax, %ebx			# High 16 bit of EAX is 0
154
	movl	%ebx, FAT_START			# FAT start = hidden + reserved
155
156
	movzbw	NUM_OF_FATS, %ax		# Normally 2
157
	mulw	SECTORS_PER_FAT			# AX = Num of sector of FATs
158
	addl	%ebx, %eax			# EAX = Start of root directory
159
160
	movw	ROOT_ENTRIES, %bx
161
	shrw	$4, %bx				# / 16 = DIRENT_PER_SECTOR
162
	movw	%bx, %cx			# CX = Num of sectors for root directory
163
164
	addl	%eax, %ebx			# DATA start = FAT start + root
165
	movl	%ebx, DATA_START		# Start sector of data area
166
167
#
168
# Find the OS image in the root directory
169
#
170
						# EAX = Start sector of root
171
next_sector:
172
	pushw	%cx
173
	movl	$(WORK_AREA), %ebx
174
	pushw	%bx
175
	call	read_sector			# Read 1 sector in root
176
	popw	%di				# DI = dir_entry
177
	movw	$(DIRENT_PER_SECTOR), %cx	# CX = directory count
178
next_entry:
179
	cmpb	$0, (%di)			# End of dir entry ?
180
	je	error				# Not found
181
	testb	$0x18, F_ATTR(%di)		# Subdir or Volume ?
182
	jnz	not_file			# Skip it
183
	pusha
184
	movw	$11, %cx			# File name + ext = 11 byte
185
	movw	$image_name, %si
186
	repe					# Compare file name
187
	cmpsb
188
	popa
189
	je	found_file
190
not_file:
191
	addw	$(DIR_SIZE), %di		# Check next directory entry
192
	loop	next_entry
193
	popw	%cx
194
	loop	next_sector
195
						# Fall through
196
#
197
# Error case
198
#
199
error:
200
	movw	$err_msg, %si
201
	movw	$5, %cx
202
	call	puts
203
hang:
204
	hlt
205
	jmp	hang				# Stop here
206
207
#
208
# Load image
209
#
210
found_file:
211
	movzwl	F_CLUSTER(%di), %eax		# EAX = 1st cluster of loader
212
	movl	$(LOAD_ADDR), %ebx		# EBX = 32bit load address
213
load_next:
214
	call	read_cluster			# Read cluster of loader
215
	call	next_cluster			# Get next cluster# in EAX
216
	jb	load_next			# EOF ?
217
218
#
219
# Turn fdd motor off
220
#
221
	movw	$0x3f2, %dx
222
	xorb	%al, %al
223
	outb	%al, %dx
224
225
#
226
# Jump to loaded image
227
#
228
	ljmp	$0x3000, $0x0
229
230
#
231
# Puts - Print string
232
#
233
# Entry:
234
#   SI - Pointer to message string
235
#   CX - Number of character
236
#
237
puts:
238
	lodsb
239
	movb	$0x0e, %ah
240
	movw	$0x0007, %bx
241
	int	$0x10
242
	loop	puts
243
	ret
244
245
#
246
# next_cluster - Return next cluster
247
#
248
# Entry:
249
#   EAX - Current cluter#
250
#
251
# Exit:
252
#   AF - End of cluster
253
#   EAX - Next cluter#
254
#
255
# Modified:
256
#   Flags,CX,EDX,SI,DI
257
#
258
next_cluster:
259
	pushl	%ebx
260
	movw	%ax, %di			# Save cluster# in DI
261
262
	movw	$0xfff8, %si			# Set default EOF to FAT16
263
264
	movl	%eax, %ecx
265
	shll	$1, %eax			# * 2
266
267
	cmpb	$0x36, FILE_SYS_ID_NUM		# ID is 'FAT16' ?
268
	je	fat_16
269
	addl	%ecx, %eax			# * 3
270
	shrl	$1, %eax			# / 2
271
	movw	$0xff8, %si			# EOF for FAT12
272
fat_16:
273
						# EAX - Offset of FAT entry
274
	xorw	%dx, %dx
275
	divw	BYTE_PER_SECTOR
276
	addl	FAT_START, %eax			# EAX = Sector# for FAT
277
						# DX = Offset in sector
278
	movl	$(WORK_AREA), %ebx
279
	pushw	%bx
280
	call	read_sector			# Read 2 sector for border
281
	call	read_sector			# data
282
	popw	%bx
283
	addw	%dx, %bx
284
	movw	(%bx), %ax
285
	cmpw	$0xfff8, %si			# FAT16 ?
286
	je	chk_end
287
288
	shrw	$1, %di
289
	jc	odd_pos
290
	andb	$0x0f, %ah
291
	jmp	chk_end
292
odd_pos:
293
	shrw	$4, %ax
294
chk_end:
295
	cmpw	%si, %ax
296
	popl	%ebx
297
	ret
298
299
#
300
# read_cluster - Read one cluster
301
#
302
# Entry:
303
#   EBX - 32-bit pointer to buffer
304
#   EAX - Cluster number
305
#
306
# Exit:
307
#   EBX - Point to next buffer
308
#
309
# Modified:
310
#   flags,ECX,ECX,EDX
311
#
312
read_cluster:
313
	pushl	%eax
314
	decw	%ax				# Translate clust# to sec#
315
	decw	%ax
316
	xorl	%ecx, %ecx
317
	movb	SECT_PER_CLUSTER, %cl
318
	mull	%ecx
319
	addl	DATA_START, %eax		# EAX = Read sec#
320
						# CX = Read sector size
321
read_loop:
322
	call	read_sector
323
	cmpl	$(LOAD_MAX), %ebx
324
	jae	error
325
	loop	read_loop
326
	popl	%eax
327
	ret
328
329
#
330
# read_sector - Read one sector
331
#
332
# Entry:
333
#   EBX - 32-bit pointer to buffer
334
#   EAX - Logical sector# to read
335
#
336
# Exit:
337
#   EBX - Pointer to next buffer
338
#   EAX - Next sector
339
#
340
# Modified:
341
#   Flags
342
#
343
read_sector:
344
	pushal
345
	pushw	%ds
346
	pushw	%es
347
348
	movl	%eax, %esi			# ESI = buffer
349
350
	movzwl	SECTORS_PER_TRACK, %ecx		# Get sec/track
351
	xorl	%edx, %edx
352
	divl	%ecx				# EAX = track#
353
						# DX = sec#
354
	movw	$(DATA_SEG), %cx		# Check in cache
355
	leaw	last_data, %di
356
	cmpl	DATA_START, %esi
357
	jae	data_reqest
358
	movw	$(FAT_SEG), %cx
359
	leaw	last_fat, %di
360
data_reqest:
361
						# CX = Cached segment
362
	pushal					# [DI] = Cached track
363
	movw	%cx, %es
364
	xorw	%bx, %bx			# ES:BX = Cache address
365
	cmpl	(%di), %eax			# Last track ?
366
	je	hit_cache
367
	movl	%eax, (%di)			# Save current track#
368
	call	read_track
369
hit_cache:
370
	popal
371
372
	pushw	%es
373
	popw	%ds
374
375
	shlw	$9, %dx				# sec# * 512
376
	movw	%dx, %si			# DS:SI = Offset in cache
377
378
	movw	%bx, %di			# [EBX] -> ES:[DI]
379
	andw	$0xf, %di
380
	shrl	$4, %ebx
381
	movw	%bx, %es
382
383
	mov	$512, %cx			# Copy 1 sector
384
	rep
385
	movsb
386
387
	popw	%es
388
	popw	%ds
389
	popal
390
391
	addl	$512, %ebx			# Next buffer
392
	incl	%eax				# Next sector
393
	ret
394
395
#
396
# read_track - Read one track
397
#
398
# Entry:
399
#   ES:[BX] - Pointer to buffer
400
#   EAX	    - Track number to read
401
#
402
# Exit:
403
#   None
404
#
405
# Modified:
406
#   Flags,EAX,ECX,EDX
407
#
408
read_track:
409
	movzwl	HEADS, %ecx			# Get num of head
410
	xorl	%edx, %edx
411
	divl	%ecx				# AX = cyl#
412
						# DL = head#
413
414
	movb	%al, %ch			# CH = cyl# (low 8 bits)
415
	andb	$3, %ah
416
	shlb	$6, %ah
417
	orb	$1, %ah
418
	movb	%ah, %cl			# CL[7:6] = cyl# (high 2 bits)
419
						# CL[5:0] = sec# = 1
420
	movb	%dl, %dh			# DH = Head#
421
	movw	SECTORS_PER_TRACK, %ax		# AL = Num of sectors to read
422
	movb	$2, %ah				# AH = 02h (Read Disk Sectors)
423
	movb	PHYSICAL_DRIVE, %dl		# DL = Drive#
424
	int	$0x13				# Invoke Disk BIOS
425
	jc	error
426
	ret
427
428
#
429
# Local Data
430
#
431
last_fat:	.long	0xffffffff
432
last_data:	.long	0xffffffff
433
434
load_msg:	.ascii	"Loading "
435
image_name:	.ascii	"PREXOS     "
436
crlf:		.byte	0x0a, 0x0d
437
err_msg:	.ascii	"Error"
438
439
.org	510
440
		.word	0xaa55