Subversion Repositories Kolibri OS

Rev

Rev 1065 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1065 Lrz 1
; Copyright (c) 2008-2009, diamond
2
; All rights reserved.
3
;
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
6
;       * Redistributions of source code must retain the above copyright
7
;       notice, this list of conditions and the following disclaimer.
8
;       * Redistributions in binary form must reproduce the above copyright
9
;       notice, this list of conditions and the following disclaimer in the
10
;       documentation and/or other materials provided with the distribution.
11
;       * Neither the name of the  nor the
12
;       names of its contributors may be used to endorse or promote products
13
;       derived from this software without specific prior written permission.
14
;
15
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka  ''AS IS'' AND ANY
16
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
; DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
19
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
;*****************************************************************************
26
 
27
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond
28
; It is used when main bootloader is Windows loader.
29
 
30
; this code is loaded:
31
; NT/2k/XP: by ntldr to 0D00:0000
32
; 9x: by io.sys from config.sys to xxxx:0100
33
; Vista: by bootmgr to 0000:7C00
34
	format binary
35
	use16
36
 
37
; in any case, we relocate this code to 0000:0600
38
	org 0x600
39
; entry point for 9x and Vista booting
40
	call	@f
41
	db	'NTFS'
42
@@:
43
	pop	si
44
	sub	si, 3
45
	cmp	si, 100h
46
	jnz	boot_vista
47
	mov	si, load_question + 100h - 600h
48
	call	out_string
49
;	mov	si, answer + 100h - 0600h		; already is
50
xxy:	mov	ah, 0
51
	int	16h
52
	or	al, 20h
53
	mov	[si], al
54
	cmp	al, 'y'
55
	jz	xxz
56
	cmp	al, 'n'
57
	jnz	xxy
58
; continue load Windows
59
;	call	out_string
60
;	ret
61
out_string:
62
	push	bx
63
@@:
64
	lodsb
65
	test	al, al
66
	jz	@f
67
	mov	ah, 0Eh
68
	mov	bx, 7
69
	int	10h
70
	jmp	@b
71
@@:
72
	pop	bx
73
	ret
74
xxz:
75
; boot KordOS
76
	call	out_string
77
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers,
78
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached
79
	xor	di, di
80
	mov	ds, di
81
	mov	word [di+4], new01handler + 100h - 600h
82
	mov	[di+6], cs
83
	pushf
84
	pop	ax
85
	or	ah, 1
86
	push	ax
87
	popf
88
; we cannot issue INT 19h directly, because INT command clears TF
89
;	int	19h	; don't issue it directly, because INT command clears TF
90
; so instead we use direct call
91
;	pushf		; there will be no IRET
92
	call	far [di + 19h*4]
93
xxt:
94
	xor	di, di
95
	mov	ds, di
96
	cmp	word [di + 8*4+2], 0F000h
97
	jz	@f
98
	les	bx, [di + 8*4]
99
	mov	eax, [es:bx+1]
100
	mov	[di + 8*4], eax
101
@@:
102
	mov	si, 100h
103
boot_vista:
104
; relocate cs:si -> 0000:0600
105
	push	cs
106
	pop	ds
107
	xor	ax, ax
108
	mov	es, ax
109
	mov	di, 0x600
110
	mov	cx, 2000h/2
111
	rep	movsw
112
	jmp	0:real_entry
113
 
114
load_question	db	'Load KordOS? [y/n]: ',0
115
answer	db	?
116
	db	13,10,0
117
 
118
new01handler:
119
; [sp]=ip, [sp+2]=cs, [sp+4]=flags
120
	push	bp
121
	mov	bp, sp
122
	push	ds
123
	lds	bp, [bp+2]
124
	cmp	word [ds:bp], 19cdh
125
	jz	xxt
126
	pop	ds
127
	pop	bp
128
	iret
129
 
130
; read from hard disk
131
; in: eax = absolute sector
132
;     cx = number of sectors
133
;     es:bx -> buffer
134
; out: CF=1 if error
135
read:
136
	pushad
137
	add	eax, [bp + partition_start - dat]
138
	cmp	[bp + use_lba - dat], 0
139
	jz	.chs
140
; LBA read
141
	push	ds
142
.lbado:
143
	push	ax
144
	push	cx
145
	cmp	cx, 0x7F
146
	jbe	@f
147
	mov	cx, 0x7F
148
@@:
149
; create disk address packet on the stack
150
; dq starting LBA
151
	push	0
152
	push	0
153
	push	eax
154
; dd buffer
155
	push	es
156
	push	bx
157
; dw number of blocks to transfer (no more than 0x7F)
158
	push	cx
159
; dw packet size in bytes
160
	push	10h
161
; issue BIOS call
162
	push	ss
163
	pop	ds
164
	mov	si, sp
165
	mov	dl, [bp + boot_drive - dat]
166
	mov	ah, 42h
167
	int	13h
168
	jc	.disk_error_lba
169
	add	sp, 10h		; restore stack
170
; increase current sector & buffer; decrease number of sectors
171
	movzx	esi, cx
172
	mov	ax, es
173
	shl	cx, 5
174
	add	ax, cx
175
	mov	es, ax
176
	pop	cx
177
	pop	ax
178
	add	eax, esi
179
	sub	cx, si
180
	jnz	.lbado
181
	pop	ds
182
	popad
183
	ret
184
.disk_error_lba:
185
	add	sp, 14h
186
	pop	ds
187
	popad
188
	stc
189
	ret
190
 
191
.chs:
192
	pusha
193
	pop	edi		; loword(edi) = di, hiword(edi) = si
194
	push	bx
195
 
196
; eax / (SectorsPerTrack) -> eax, remainder bx
197
	movzx	esi, [bp + sectors - dat]
198
	xor	edx, edx
199
	div	esi
200
	mov	bx, dx		; bx = sector-1
201
 
202
; eax -> dx:ax
203
	push	eax
204
	pop	ax
205
	pop	dx
206
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx
207
	div	[bp + heads - dat]
208
 
209
; number of sectors: read no more than to end of track
210
	sub	si, bx
211
	cmp	cx, si
212
	jbe	@f
213
	mov	cx, si
214
@@:
215
 
216
	inc	bx
217
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector
218
; convert to int13 format
219
	movzx	edi, cx
220
	mov	dh, dl
221
	mov	dl, [bp + boot_drive - dat]
222
	shl	ah, 6
223
	mov	ch, al
224
	mov	al, cl
225
	mov	cl, bl
226
	or	cl, ah
227
	pop	bx
228
	mov	si, 3
229
	mov	ah, 2
230
@@:
231
	push	ax
232
	int	13h
233
	jnc	@f
234
	xor	ax, ax
235
	int	13h	; reset drive
236
	pop	ax
237
	dec	si
238
	jnz	@b
239
	add	sp, 12
240
	popad
241
	stc
242
	ret
243
@@:
244
	pop	ax
245
	mov	ax, es
246
	mov	cx, di
247
	shl	cx, 5
248
	add	ax, cx
249
	mov	es, ax
250
	push	edi
251
	popa
252
	add	eax, edi
253
	sub	cx, di
254
	jnz	.chs
255
	popad
256
	ret
257
 
258
disk_error2	db	'Fatal: cannot read partitions info: '
259
disk_error_msg	db	'disk read error',0
260
disk_params_msg	db	'Fatal: cannot get drive parameters',0
261
start_msg	db	2,' KordOS bootloader',13,10,0
262
part_msg	db	'looking at partition '
263
part_char	db	'0'	; will be incremented before writing message
264
		db	' ... ',0
265
errfs_msg	db	'unknown filesystem',13,10,0
266
fatxx_msg	db	'FATxx'
267
newline		db	13,10,0
268
ntfs_msg	db	'NTFS',13,10,0
269
error_msg	db	'Error'
270
colon		db	': ',0
271
root_string	db	'\',0
272
nomem_msg	db	'No memory',0
273
filesys_string	db	'(filesystem)',0
274
directory_string db	'is a directory',0
275
notdir_string	db	'not a directory',0
276
 
277
; entry point for NT/2k/XP booting
278
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256
279
	repeat	600h + 256h - $
280
		db	1	; any data can be here; 1 in ASCII is a nice face :)
281
	end repeat
282
; cs=es=0D00, ds=07C0, ss=0
283
; esi=edi=ebp=0, esp=7C00
284
	xor	si, si
285
	jmp	boot_vista
286
 
287
real_entry:
288
; ax = 0
289
	mov	ds, ax
290
	mov	es, ax
291
; our stack is 4 Kb: memory range 2000-3000
292
	mov	ss, ax
293
	mov	sp, 3000h
294
	mov	bp, dat
295
	sti	; just for case
296
; say hi to user
297
	mov	si, start_msg
298
	call	out_string
299
; we are booting from hard disk identified by [boot_drive]
300
	mov	dl, [bp + boot_drive - dat]
301
; is LBA supported?
302
	mov	[bp + use_lba - dat], 0
303
	mov	ah, 41h
304
	mov	bx, 55AAh
305
	int	13h
306
	jc	.no_lba
307
	cmp	bx, 0AA55h
308
	jnz	.no_lba
309
	test	cl, 1
310
	jz	.no_lba
311
	inc	[bp + use_lba - dat]
312
	jmp	disk_params_ok
313
.no_lba:
314
; get drive geometry
315
	mov	ah, 8
316
	mov	dl, [bp + boot_drive - dat]
317
	int	13h
318
	jnc	@f
319
	mov	si, disk_params_msg
320
	call	out_string
321
	jmp	$
322
@@:
323
	movzx	ax, dh
324
	inc	ax
325
	mov	[bp + heads - dat], ax
326
	and	cx, 3Fh
327
	mov	[bp + sectors - dat], cx
328
disk_params_ok:
329
; determine size of cache for folders
330
	int	12h	; ax = size of available base memory in Kb
331
	sub	ax, 94000h / 1024
332
	jc	nomem
333
	shr	ax, 3
334
	mov	[bp + cachelimit - dat], ax	; size of cache - 1
335
; scan all partitions
336
new_partition_ex:
337
	xor	eax, eax	; read first sector of current disk area
338
	mov	[bp + extended_part_cur - dat], eax	; no extended partition yet
339
	mov	[bp + cur_partition_ofs - dat], 31BEh	; start from first partition
340
	push	es
341
	mov	cx, 1
342
	mov	bx, 3000h
343
	call	read
344
	pop	es
345
	jnc	new_partition
346
	mov	si, disk_error2
347
	call	out_string
348
	jmp	$
349
new_partition:
350
	mov	bx, [bp + cur_partition_ofs - dat]
351
	mov	al, [bx+4]	; partition type
352
	test	al, al
353
	jz	next_partition
354
	cmp	al, 5
355
	jz	@f
356
	cmp	al, 0xF
357
	jnz	not_extended
358
@@:
359
; extended partition
360
	mov	eax, [bx+8]	; partition start
361
	add	eax, [bp + extended_part_start - dat]
362
	mov	[bp + extended_part_cur - dat], eax
363
next_partition:
364
	add	[bp + cur_partition_ofs - dat], 10h
365
	cmp	[bp + cur_partition_ofs - dat], 31FEh
366
	jb	new_partition
367
	mov	eax, [bp + extended_part_cur - dat]
368
	test	eax, eax
369
	jz	partitions_done
370
	cmp	[bp + extended_part_start - dat], 0
371
	jnz	@f
372
	mov	[bp + extended_part_start - dat], eax
373
@@:
374
	mov	[bp + extended_parent - dat], eax
375
	mov	[bp + partition_start - dat], eax
376
	jmp	new_partition_ex
377
partitions_done:
378
	mov	si, total_kaput
379
	call	out_string
380
	jmp	$
381
not_extended:
382
	mov	eax, [bx+8]
383
	add	eax, [bp + extended_parent - dat]
384
	mov	[bp + partition_start - dat], eax
385
; try to load from current partition
386
; inform user
387
	mov	si, part_msg
388
	inc	[si + part_char - part_msg]
389
	call	out_string
390
; read bootsector
391
	xor	eax, eax
392
	mov	[bp + cur_obj - dat], filesys_string
393
	push	es
394
	mov	cx, 1
395
	mov	bx, 3200h
396
	call	read
397
	pop	es
398
	mov	si, disk_error_msg
399
	jc	find_error_si
400
	movzx	si, byte [bx+13]
401
	mov	word [bp + sect_per_clust - dat], si
402
	test	si, si
403
	jz	unknown_fs
404
	lea	ax, [si-1]
405
	test	si, ax
406
	jnz	unknown_fs
407
; determine file system
408
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h)
409
	cmp	word [bx+11], 0x200
410
	jnz	unknown_fs
411
; is it NTFS?
412
	cmp	dword [bx+3], 'NTFS'
413
	jnz	not_ntfs
414
	cmp	byte [bx+16], bl
415
	jz	ntfs
416
not_ntfs:
417
; is it FAT? FAT12/FAT16/FAT32?
418
; get count of sectors to dword in cx:si
419
	mov	si, [bx+19]
420
	xor	cx, cx
421
	test	si, si
422
	jnz	@f
423
	mov	si, [bx+32]
424
	mov	cx, [bx+34]
425
@@:
426
	xor	eax, eax
427
; subtract size of system area
428
	sub	si, [bx+14]	; BPB_ResvdSecCnt
429
	sbb	cx, ax
430
	mov	ax, [bx+17]	; BPB_RootEntCnt
431
	add	ax, 0xF
432
	rcr	ax, 1
433
	shr	ax, 3
434
	sub	si, ax
435
	sbb	cx, 0
436
	push	cx
437
	push	si
438
	mov	ax, word [bx+22]
439
	test	ax, ax
440
	jnz	@f
441
	mov	eax, [bx+36]
442
@@:
443
	movzx	ecx, byte [bx+16]
444
	imul	ecx, eax
445
	pop	eax
446
	sub	eax, ecx
447
; now eax = count of sectors in the data region
448
	xor	edx, edx
449
	div	[bp + sect_per_clust - dat]
450
; now eax = count of clusters in the data region
451
	mov	si, fatxx_msg
452
	cmp	eax, 0xFFF5
453
	jae	test_fat32
454
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38
455
	cmp	byte [bx+38], 0x29
456
	jnz	not_fat
457
	cmp	ax, 0xFF5
458
	jae	fat16
459
fat12:
460
	mov	[bp + get_next_cluster_ptr - dat], fat12_get_next_cluster
461
	mov	di, cx		; BPB_NumFATs
462
	mov	ax, '12'
463
	push	ax		; save for secondary loader
464
	mov	word [si+3], ax
465
	call	out_string
466
	movzx	ecx, word [bx+22]	; BPB_FATSz16
467
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes)
468
.fatloop:
469
; if first copy is not readable, try to switch to other copies
470
	push	0x6000
471
	pop	es
472
	xor	bx, bx
473
	movzx	eax, word [0x320E]	; BPB_RsvdSecCnt
474
	push	cx
475
	cmp	cx, 12
476
	jb	@f
477
	mov	cx, 12
478
@@:
479
	call	read
480
	pop	cx
481
	jnc	fat1x_common
482
	add	eax, ecx	; switch to next copy of FAT
483
	dec	di
484
	jnz	.fatloop
485
	mov	si, disk_error_msg
486
	jmp	find_error_si
487
fat16:
488
	mov	[bp + get_next_cluster_ptr - dat], fat16_get_next_cluster
489
	mov	ax, '16'
490
	push	ax		; save for secondary loader
491
	mov	word [si+3], ax
492
	call	out_string
493
; FAT16: init FAT cache - no sectors loaded
494
	mov	di, 0x3400
495
	xor	ax, ax
496
	mov	cx, 0x100/2
497
	rep	stosw
498
fat1x_common:
499
	mov	bx, 0x3200
500
	movzx	eax, word [bx+22]	; BPB_FATSz16
501
	xor	esi, esi	; no root cluster
502
	jmp	fat_common
503
test_fat32:
504
; FAT32 bootsector has it at the offset +66
505
	cmp	byte [bx+66], 0x29
506
	jnz	not_fat
507
	mov	[bp + get_next_cluster_ptr - dat], fat32_get_next_cluster
508
	mov	ax, '32'
509
	push	ax		; save for secondary loader
510
	mov	word [si+3], ax
511
	call	out_string
512
; FAT32 - init cache for FAT table: no sectors loaded
513
	lea	si, [bp + cache1head - dat]
514
	mov	[si], si		; no sectors in cache:
515
	mov	[si+2], si		; 'prev' & 'next' links point to self
516
	mov	[bp + cache1end - dat], 3400h	; first free item = 3400h
517
	mov	[bp + cache1limit - dat], 3C00h
518
	mov	eax, [bx+36]	; BPB_FATSz32
519
	mov	esi, [bx+44]	; BPB_RootClus
520
	jmp	fat_common
521
not_fat:
522
unknown_fs:
523
	mov	si, errfs_msg
524
	call	out_string
525
	jmp	next_partition
526
fat_common:
527
	push	ss
528
	pop	es
529
	movzx	edx, byte [bx+16]	; BPB_NumFATs
530
	mul	edx
531
	mov	[bp + root_start - dat], eax	; this is for FAT1x
532
; eax = total size of all FAT tables, in sectors
533
	movzx	ecx, word [bx+17]	; BPB_RootEntCnt
534
	add	ecx, 0xF
535
	shr	ecx, 4
536
	add	eax, ecx
537
	mov	cx, word [bx+14]	; BPB_RsvdSecCnt
538
	add	[bp + root_start - dat], ecx	; this is for FAT1x
539
	add	eax, ecx
540
; cluster 2 begins from sector eax
541
	movzx	ebx, byte [bx+13]	; BPB_SecPerClus
542
	sub	eax, ebx
543
	sub	eax, ebx
544
	mov	[bp + data_start - dat], eax
545
; no clusters in folders cache
546
	mov	di, foldcache_clus - 2
547
	xor	ax, ax
548
	mov	cx, 7*8/2 + 1
549
	rep	stosw
550
	mov	[bp + root_clus - dat], esi
551
; load secondary loader
552
	mov	[bp + load_file_ptr - dat], load_file_fat
553
load_secondary:
554
	push	0x1000
555
	pop	es
556
	xor	bx, bx
557
	mov	si, kernel_name
558
	mov	cx, 0x30000 / 0x200
559
	call	[bp + load_file_ptr - dat]
560
; say error if needed
561
	mov	si, error_too_big
562
	dec	bx
563
	js	@f
564
	jz	find_error_si
565
	mov	si, disk_error_msg
566
	jmp	find_error_si
567
@@:
568
; fill loader information and jump to secondary loader
569
	mov	al, 'h'		; boot device: hard drive
570
	mov	ah, [bp + boot_drive - dat]
571
	sub	ah, 80h		; boot device: identifier
572
	pop	bx		; restore file system ID ('12'/'16'/'32'/'nt')
573
	mov	si, callback
574
	jmp	1000h:0000h
575
 
576
nomem:
577
	mov	si, nomem_msg
578
	call	out_string
579
	jmp	$
580
 
581
ntfs:
582
	push	'nt'		; save for secondary loader
583
	mov	si, ntfs_msg
584
	call	out_string
585
	xor	eax, eax
586
	mov	[bp + data_start - dat], eax
587
	mov	ecx, [bx+40h]	; frs_size
588
	cmp	cl, al
589
	jg	.1
590
	neg	cl
591
	inc	ax
592
	shl	eax, cl
593
	jmp	.2
594
.1:
595
	mov	eax, ecx
596
	shl	eax, 9
597
.2:
598
	mov	[bp + frs_size - dat], ax
599
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different
600
; (at least with standard tools)
601
; we allow extra size, but no more than 0x1000 bytes = 4 Kb
602
	mov	si, invalid_volume_msg
603
	cmp	eax, 0x1000
604
	ja	find_error_si
605
; must be multiple of sector size
606
	test	ax, 0x1FF
607
	jnz	find_error_si
608
	shr	ax, 9
609
	xchg	cx, ax
610
; initialize cache - no data loaded
611
	lea	si, [bp + cache1head - dat]
612
	mov	[si], si
613
	mov	[si+2], si
614
	mov	word [si+4], 3400h	; first free item = 3400h
615
	mov	word [si+6], 3400h + 8*8	; 8 items in this cache
616
; read first MFT record - description of MFT itself
617
	mov	[bp + cur_obj - dat], mft_string
618
	mov	eax, [bx+30h]	; mft_cluster
619
	mul	[bp + sect_per_clust - dat]
620
	push	0x8000
621
	pop	es
622
	xor	bx, bx
623
	push	es
624
	call	read
625
	pop	ds
626
	call	restore_usa
627
; scan for unnamed $DATA attribute
628
	mov	[bp + freeattr - dat], 4000h
629
	mov	ax, 80h
630
	call	load_attr
631
	push	ss
632
	pop	ds
633
	mov	si, nodata_string
634
	jc	find_error_si
635
; load secondary loader
636
	mov	[bp + load_file_ptr - dat], load_file_ntfs
637
	jmp	load_secondary
638
 
639
find_error_si:
640
	push	si
641
find_error_sp:
642
	cmp	[bp + in_callback - dat], 0
643
	jnz	error_in_callback
644
	push	ss
645
	pop	ds
646
	push	ss
647
	pop	es
648
	mov	si, error_msg
649
	call	out_string
650
	mov	si, [bp + cur_obj - dat]
651
@@:
652
	lodsb
653
	test	al, al
654
	jz	@f
655
	cmp	al, '/'
656
	jz	@f
657
	mov	ah, 0Eh
658
	mov	bx, 7
659
	int	10h
660
	jmp	@b
661
@@:
662
	mov	si, colon
663
	call	out_string
664
	pop	si
665
	call	out_string
666
	mov	si, newline
667
	call	out_string
668
	mov	sp, 0x3000
669
	jmp	next_partition
670
error_in_callback:
671
; return status: file not found, except for read errors
672
	mov	bx, 2
673
	cmp	si, disk_error_msg
674
	jnz	@f
675
	inc	bx
676
@@:
677
	mov	ax, 0xFFFF
678
	mov	dx, ax
679
	mov	sp, 3000h - 6
680
	ret
681
 
682
callback:
683
; in: ax = function number; only functions 1 and 2 are defined for now
684
; save caller's stack
685
	mov	dx, ss
686
	mov	cx, sp
687
; set our stack (required because we need ss=0)
688
	xor	si, si
689
	mov	ss, si
690
	mov	sp, 3000h
691
	mov	bp, dat
692
	mov	[bp + in_callback - dat], 1
693
	push	dx
694
	push	cx
695
; set ds:si -> ASCIIZ name
696
	lea	si, [di+6]
697
; set cx = limit in sectors; 4Kb = 8 sectors
698
	movzx	ecx, word [di+4]
699
	shl	cx, 3
700
; set es:bx = pointer to buffer
701
	les	bx, [di]
702
; call our function
703
	stc	; unsupported function
704
	dec	ax
705
	jz	callback_readfile
706
	dec	ax
707
	jnz	callback_ret
708
	call	continue_load_file
709
	jmp	callback_ret_succ
710
callback_readfile:
711
; function 1: read file
712
; in: ds:di -> information structure
713
;	dw:dw	address
714
;	dw	limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
715
;	ASCIIZ	name
716
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
717
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
718
	call	[bp + load_file_ptr - dat]
719
callback_ret_succ:
720
	clc
721
callback_ret:
722
; restore caller's stack
723
	pop	cx
724
	pop	ss
725
	mov	sp, cx
726
; return to caller
727
	retf
728
 
729
read_file_chunk.resident:
730
; auxiliary label for read_file_chunk procedure
731
	mov	di, bx
732
	lodsw
733
read_file_chunk.resident.continue:
734
	mov	dx, ax
735
	add	dx, 0x1FF
736
	shr	dx, 9
737
	cmp	dx, cx
738
	jbe	@f
739
	mov	ax, cx
740
	shl	ax, 9
741
@@:
742
	xchg	ax, cx
743
	rep	movsb
744
	xchg	ax, cx
745
	clc	; no disk error if no disk requests
746
	mov	word [bp + num_sectors - dat], ax
747
	ret
748
 
749
read_file_chunk:
750
; in: ds:si -> file chunk
751
; in: es:bx -> buffer for output
752
; in: ecx = maximum number of sectors to read (high word must be 0)
753
; out: CF=1 <=> disk read error
754
	lodsb
755
	mov	[bp + cur_chunk_resident - dat], al
756
	test	al, al
757
	jz	.resident
758
; normal case: load (non-resident) attribute from disk
759
.read_block:
760
	lodsd
761
	xchg	eax, edx
762
	test	edx, edx
763
	jz	.ret
764
	lodsd
765
; eax = start cluster, edx = number of clusters, cx = limit in sectors
766
	imul	eax, [bp + sect_per_clust - dat]
767
	add	eax, [bp + data_start - dat]
768
	mov	[bp + cur_cluster - dat], eax
769
	imul	edx, [bp + sect_per_clust - dat]
770
	mov	[bp + num_sectors - dat], edx
771
	and	[bp + cur_delta - dat], 0
772
.nonresident.continue:
773
	cmp	edx, ecx
774
	jb	@f
775
	mov	edx, ecx
776
@@:
777
	test	dx, dx
778
	jz	.read_block
779
	add	[bp + cur_delta - dat], edx
780
	sub	[bp + num_sectors - dat], edx
781
	sub	ecx, edx
782
	push	cx
783
	mov	cx, dx
784
	call	read
785
	pop	cx
786
	jc	.ret
787
	test	cx, cx
788
	jnz	.read_block
789
.ret:
790
	ret
791
 
792
cache_lookup:
793
; in: eax = value to look, si = pointer to cache structure
794
; out: di->cache entry; CF=1 <=> the value was not found
795
	push	ds bx
796
	push	ss
797
	pop	ds
798
	mov	di, [si+2]
799
.look:
800
	cmp	di, si
801
	jz	.not_in_cache
802
	cmp	eax, [di+4]
803
	jz	.in_cache
804
	mov	di, [di+2]
805
	jmp	.look
806
.not_in_cache:
807
; cache miss
808
; cache is full?
809
	mov	di, [si+4]
810
	cmp	di, [si+6]
811
	jnz	.cache_not_full
812
; yes, delete the oldest entry
813
	mov	di, [si]
814
	mov	bx, [di]
815
	mov	[si], bx
816
	push	word [di+2]
817
	pop	word [bx+2]
818
	jmp	.cache_append
819
.cache_not_full:
820
; no, allocate new item
821
	add	word [si+4], 8
822
.cache_append:
823
	mov	[di+4], eax
824
	stc
825
	jmp	@f
826
.in_cache:
827
; delete this sector from the list
828
	push	si
829
	mov	si, [di]
830
	mov	bx, [di+2]
831
	mov	[si+2], bx
832
	mov	[bx], si
833
	pop	si
834
@@:
835
; add new sector to the end of list
836
	mov	bx, di
837
	xchg	bx, [si+2]
838
	push	word [bx]
839
	pop	word [di]
840
	mov	[bx], di
841
	mov	[di+2], bx
842
	pop	bx ds
843
	ret
844
 
845
include 'fat.inc'
846
include 'ntfs.inc'
847
 
848
total_kaput	db	13,10,'Fatal error: cannot load the secondary loader',0
849
error_too_big	db	'file is too big',0
850
nodata_string	db	'$DATA '
851
error_not_found	db	'not found',0
852
noindex_string	db	'$INDEX_ROOT not found',0
853
badname_msg	db	'bad name for FAT',0
854
invalid_volume_msg db	'invalid volume',0
855
mft_string	db	'$MFT',0
856
fragmented_string db	'too fragmented file',0
857
invalid_read_request_string db 'cannot read attribute',0
858
 
1942 clevermous 859
kernel_name	db	'kernel.mnt',0
1065 Lrz 860
 
861
align 4
862
dat:
863
 
864
extended_part_start	dd	0	; start sector for main extended partition
865
extended_part_cur	dd	?	; start sector for current extended child
866
extended_parent		dd	0	; start sector for current extended parent
867
partition_start		dd	0	; start sector for current logical disk
868
cur_partition_ofs	dw	?	; offset in MBR data for current partition
869
sect_per_clust		dd	0
870
; change this variable if you want to boot from other physical drive
871
boot_drive	db	80h
872
in_callback	db	0
873
 
874
; uninitialized data
875
use_lba		db	?
876
cur_chunk_resident db	?
877
align 2
878
heads		dw	?
879
sectors		dw	?
880
cache1head	rw	2
881
cache1end	dw	?
882
cache1limit	dw	?
883
data_start	dd	?
884
cachelimit	dw	?
885
load_file_ptr	dw	?
886
cur_obj		dw	?
887
missing_slash	dw	?
888
root_clus	dd	?
889
root_start	dd	?
890
get_next_cluster_ptr	dw	?
891
frs_size	dw	?
892
freeattr	dw	?
893
index_root	dw	?
894
index_alloc	dw	?
895
cur_index_seg	dw	?
896
cur_index_cache	dw	?
897
filesize	dd	?
898
filesize_sectors dd	?
899
cur_cluster	dd	?
900
cur_delta	dd	?
901
num_sectors	dd	?
902
sectors_read	dd	?
903
cur_chunk_ptr	dw	?
904
 
905
rootcache_size	dw	?	; must be immediately before foldcache_clus
906
if $-dat >= 0x80
907
warning: unoptimal data displacement!
908
end if
909
foldcache_clus	rd	7
910
foldcache_mark	rw	7
911
foldcache_size	rw	7
912
fat_filename	rb	11
913
 
914
if $ > 2000h
915
error: file is too big
916
end if
917
 
918
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long
919
repeat 0x2600 - $
920
	db	2	; any data can be here; 2 is another nice face in ASCII :)
921
end repeat