Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1065 Lrz 1
; Copyright (c) 2009, 
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
; в этой секции идет разбор параметров указатель на секцию храниться в point_default
28
;типы ошибок при обработке макроса
29
;Макрос RamdiskFS
30
;/определение флагов в записи корневой директории
31
ATTR_READ_ONLY  equ	0x01
32
ATTR_HIDDEN 	equ	0x02
33
ATTR_SYSTEM 	equ	0x04
34
ATTR_VOLUME_ID 	equ	0x08
35
ATTR_DIRECTORY	equ	0x10
36
ATTR_ARCHIVE  	equ	0x20
37
 
38
 
39
 
40
show_error_1	equ 	0x1	;кончились данные - не запланированный конец секции
41
show_error_2	equ	0x2	;нет завершающего символа в размере рам диска.
42
show_error_3	equ	0x4	; рам диск будет иметь размер =64 кб.
43
show_error_4	equ	0x8	;
44
 
45
macro use_parse_def_sect
46
{
47
	mov	di,point_default
48
	push	ini_data_
49
	pop	es
50
	mov	si,point_to_point_def
51
	sub	si,2
52
	mov	cx,[si]		;загрузим указатель наследующию секцию
53
 
54
	xor	ax,ax	;обнулим аx для очистки флагов
55
 
56
	sub	cx,di		;вот теперь имеем истиный размер
57
	mov	save_cx_d,cx	;сохраним значение cx своей переменной
58
;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений
59
 
60
	mov	status_flag,ax
61
;;;;
62
;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга
63
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64
;соглашение не разрушаем bp, es, cs, sp
65
;use_Loader_Image	;загрузить образ выше 1 мб
66
use_RamdiskFS
67
;проверяется самый последний.
68
use_LoaderModule    ;особенность - передает управление на загруженный модуль.
69
}
70
 
71
macro use_LoaderModule
72
;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое
73
;управление будет передаваться только после обработки всей секции
74
{
75
local .found_end_str
76
 
77
	mov	di,point_default   ;restore value
78
	mov	cx,save_cx_d
79
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
80
.start_p_LM:
81
	call	get_firs_sym	;get first symbol on new line
82
	test	cx,cx
83
	jz      ._afterLoaderModule	;нету? ну ладно - следующее значение тогда )
84
        cmp	al,'L'
85
        jnz	.start_p_LM
86
;проверка на значение LoaderModule
87
;        parse_LoaderModule
88
        mov     bx,cx
89
        mov     ax,di
90
 
91
        mov     si,parse_LoaderModule
92
        mov     cx,parse_LoaderModule_e - parse_LoaderModule
93
        repe    cmpsb
94
	jnz	.rest_value_loop_LM	   ;is not compare
95
 
96
        sub     bx,parse_LoaderModule_e - parse_LoaderModule ;correct cx
97
        add     bx,cx
98
        mov     cx,bx
99
 
100
	test	status_flag,flag_found_LM 		;оценка флагов
101
	jz	.correct_is_not_set_LM
102
 
103
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
104
;	call	printplain
105
;	jmp	.get_next_str
106
 
107
.correct_is_not_set_LM:
108
	mov	ax,0x3d20	   ;cut al=' ' ah='='
109
	repe    scasb
110
	jcxz	.rest_value_loop_LM          ;not found param timeout
111
 
112
        cmp	ah,byte [es:di-1]    ;find '='
113
	jnz	.rest_value_loop_LM
114
 
115
	repe    scasb              ;cut ' '
116
	inc	cx
117
	dec	di
118
;di указывает на начало блока информации, в cx длинна до конца секции.
119
;после загрузки заноситься значение занятой памяти.
120
;для того что бы загрузить модуль, воспользуемся callback сервисом
121
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
122
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
123
;мы ее модифицируем до такого состояния       dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
124
;сохранили певые 2 word
125
	push	dword [es:di-6]
126
	lea	si,[di-6]
127
 
128
	push	word  [es:di-2]
129
	xor	ax,ax
130
	mov	word [es:di-6],ax	;вносим нужные значения
131
;info_real_mode_size размер и указатель на область в которую можно загрузиться
132
	mov	ax,info_real_mode_size	;0x3000   ;следующий сегмент за данными
133
 
134
 
135
	mov	word [es:di-4],ax
136
	mov	word [es:di-2],16	;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
137
;;;;;; поиск конца строчки
138
@@:	mov	al,byte [es:di]
139
	cmp	al,' '
140
	jz	.found_end_str
141
	cmp	al,0xa
142
	jz	.found_end_str
143
	cmp	al,0xd
144
	jz	.found_end_str
145
	inc	di
146
	dec	cx
147
	jnz	@b
148
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
149
.found_end_str:
150
 
151
	push	word [es:di]
152
	xor	ax,ax
153
	mov	word [es:di],ax
154
;        xor     ax,ax   ; function 1 - read file
155
        mov     di,si	;file_data
156
	inc	ax
157
	push	si
158
	push	es
159
 
160
	push	es
161
	pop	ds
162
	push	cs
163
	pop	es
164
 
165
        call    far  dword [es:loader_callback]
166
 
167
        push    cs
168
        pop     ds
169
 
170
	pop	es
171
	pop	si
172
 
173
        test    bx,bx
174
        jnz     .error_LM
175
 
176
 
177
        jmp	far	dword [es:si]
178
 
179
 
180
 
181
 
182
.error_LM:
183
        call	error.LoaderModule
184
.rest_value_loop_LM:
185
        mov	di,ax
186
	mov	cx,bx
187
	jmp	.start_p_LM
188
 
189
._afterLoaderModule:
190
}
191
 
192
macro use_RamdiskFS
193
; формирование рам диска, + обработка всего связанного.
194
{
195
if DEBUG
196
local ._not_memory_in_sys
197
	mov	si,ramdiskFS_st
198
	call	printplain
199
end if
200
; обнулим регистр состояния ошибок
201
	xor	ax,ax
202
	mov	show_errors_sect,ax
203
use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax
204
;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск.
205
use_RamdiskSize ;значение возвращается в bx
206
	cmp	free_ad_memory,bx	; размерность в кб.
207
	jbe	._not_memory_in_sys
208
	movzx	eax,bx
209
	shl	eax,10	;*1024 = get size in byte
210
	mov	save_ramdisksize,eax 	; сорханим размер в byte
211
 
212
get_type_FS     ;получим тип файловой системы + создадим ее
213
 
214
 
215
._not_memory_in_sys:
216
 
217
if DEBUG
218
;pause
219
	xor	ax,ax
220
	int	0x16
221
end if
222
}
223
macro use_RamdiskSize
224
{
225
local .start_p_RS
226
local .correct_is_not_set_RS
227
local .CS
228
local .correct_val_RS
229
local .correct_size_RS
230
local .rest_value_loop_RS
231
local .end_get_RS_ERROR_1
232
local .end_get_RS_ERROR_2
233
local ._end_parse_RS
234
;обрабатывается размер формируемого рам диска
235
;загрузим начало секции, т.к. будем просматривать с начала и всю секцию
236
	mov	di,point_default   ;restore value
237
	mov	cx,save_cx_d
238
.start_p_RS:
239
	call	get_firs_sym	;get first symbol on new line
240
	test	cx,cx
241
	jz      ._end_parse_RS	;нету? ну ладно - следующее значение тогда )
242
        cmp	al,'R'
243
        jnz	.start_p_RS
244
;проверка на значения RamdiskSize
245
;        parse_RamdiskSize
246
        mov     bx,cx
247
        mov     ax,di
248
 
249
        mov     si,parse_RamdiskSize
250
        mov     cx,parse_RamdiskSize_e - parse_RamdiskSize
251
        repe    cmpsb
252
	jnz	.rest_value_loop_RS    ;is not compare
253
 
254
        sub     bx,parse_RamdiskSize_e - parse_RamdiskSize ;correct cx
255
        add     bx,cx
256
        mov     cx,bx
257
 
258
	test	status_flag,flag_found_RS 		;оценка флагов
259
	jz	.correct_is_not_set_RS
260
 
261
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
262
;	call	printplain
263
;	jmp	.get_next_str
264
 
265
.correct_is_not_set_RS:
266
	mov	ax,0x3d20	   ;cut al=' ' ah='='
267
	repe    scasb
268
	jcxz	.end_get_RS_ERROR_1          ;not found param
269
 
270
        cmp	ah,byte [es:di-1]    ;find '='
271
	jnz	.start_p_RS			; перейдем на начало и попробуем найти еще секцию
272
 
273
	repe    scasb              ;cut ' '
274
	inc	cx
275
	dec	di
276
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
277
;Тут нужно преобразовывать строчку в цифровое значение.
278
;;;;;;;;;;;;;;;;;;;;;;;;;;
279
	xor	bx,bx
280
	mov	cx,5
281
@@:	mov	al,byte [es:di]
282
	cmp	al,'0'
283
	jb	.CS
284
	cmp	al,'9'
285
	jbe	.correct_val_RS
286
.CS:
287
	cmp	al,'K'
288
	jz	.correct_size_RS
289
	jmp	.end_get_RS_ERROR_2
290
.correct_val_RS:
291
	imul	bx,10
292
	xor 	al,0x30
293
	add	bl,al
294
	inc	di
295
	loop	@b
296
 
297
.correct_size_RS:
298
;возможен 1 вариант, когда размер задан в K киллобайтах
299
;внутренный формат данных это кол-во запрощеной памяти в кб.
300
	test	bx,bx
301
	jnz	@f	;если значение отлично от 0
302
;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны
303
;установить 64 кб размер рам диска.
304
	or	show_errors_sect,show_error_3
305
	mov	bx,64
306
@@:
307
	jmp 	._end_parse_RS
308
 
309
 
310
.rest_value_loop_RS:
311
        mov	di,ax
312
	mov	cx,bx
313
	jmp	.start_p_RS
314
 
315
 
316
 
317
.end_get_RS_ERROR_1:
318
;сообщение об ошибке - данный участок кода не был корректно обработан :(
319
	or	show_errors_sect,show_error_1
320
	jmp	._end_parse_RS
321
.end_get_RS_ERROR_2:
322
	or	show_errors_sect,show_error_2
323
 
324
._end_parse_RS:
325
if DEBUG
326
        pusha
327
        movzx   eax,bx
328
        mov     cx,0x0a
329
        mov     di,RamdiskSize_msg
330
        mov     dword[ds:di],'    '
331
	mov	word [ds:di+4],'  '
332
        call    decode
333
;Show size
334
        mov     si,RamdiskSize_msg
335
        call    printplain
336
 
337
        popa
338
end if
339
 
340
}
341
 
342
macro use_free_memory
343
{
344
local _support_function_use_free_memory
345
;макрос для получения общего числа доступной памяти для формирования рам диска за пределами 1 мб.
346
;используется 0х88 функция 0х15 прерывания
347
; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0
348
	mov	ah,0x88	 ;ah,0x88
349
	int	0x15
350
	jnc	._support_function_use_free_memory
351
	xor	ax,ax
352
;возвращает в ax число в кб
353
._support_function_use_free_memory:
354
	mov	free_ad_memory,ax  ; если не поддерживается биосом, то в ax=0
355
if DEBUG
356
        pusha
357
        movzx   eax,ax
358
        mov     cx,0x0a
359
        mov     di,free_memory_msg
360
        mov     dword[ds:di],'    '
361
	mov	word [ds:di+4],'  '
362
        call    decode
363
;Show size
364
        mov     si,free_memory_msg
365
        call    printplain
366
 
367
        popa
368
end if
369
 
370
 
371
 
372
 
373
}
374
macro show_ERRORS
375
{
376
 
377
}
378
 
379
macro get_type_FS ;получить и создать образ для заданной RFS.
380
{
381
	mov	di,point_default   ;restore value
382
	mov	cx,save_cx_d
383
.start_g_tpe_RFS:
384
	call	get_firs_sym	;get first symbol on new line
385
	test	cx,cx
386
	jz      ._end_parse_FRS	;._end_get_type_RFS	;нету? ну ладно - следующее значение тогда )
387
        cmp	al,'R'
388
        jnz	.start_g_tpe_RFS
389
;проверка на значения RamdiskSize
390
;        parse_RamdiskSize
391
        mov     bx,cx
392
        mov     ax,di
393
 
394
        mov     si,parse_RamdiskFS
395
        mov     cx,parse_RamdiskFS_e - parse_RamdiskFS
396
        repe    cmpsb
397
	jnz	.start_g_tpe_RFS_rest_v	   ;is not compare
398
 
399
        sub     bx,parse_RamdiskFS_e - parse_RamdiskFS ;correct cx
400
        add     bx,cx
401
        mov     cx,bx
402
 
403
	test	status_flag,flag_found_GTRFMS 		;оценка флагов
404
	jz	.correct_is_not_set_FRS
405
 
406
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
407
;	call	printplain
408
;	jmp	.get_next_str
409
 
410
.correct_is_not_set_FRS:
411
	mov	ax,0x3d20	   ;cut al=' ' ah='='
412
	repe    scasb
413
	test	cx,cx
414
	jz	.end_get_FRS_ERROR_1          ;not found param
415
 
416
        cmp	ah,byte [es:di-1]    ;find '='
417
	jnz	.start_g_tpe_RFS			; перейдем на начало и попробуем найти еще секцию
418
 
419
	repe    scasb              ;cut ' '
420
	inc	cx
421
	dec	di
422
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
423
;Тут нужно преобразовывать строчку в цифровое значение.
424
;;;;;;;;;;;;;;;;;;;;;;;;;;
425
        mov     bx,cx
426
        mov     ax,di
427
 
428
        mov     si,parse_RFS_FAT
429
        mov     cx,parse_RFS_FAT_e - parse_RFS_FAT
430
        repe    cmpsb
431
	jnz	.krfs_cmp	   ;is not compare
432
 
433
make_FAT_RamFS	;сделать
434
 
435
if DEBUG
436
        pusha
437
        mov     si,make_fat12_RFS_msg
438
        call    printplain
439
        popa
440
end if
441
	jmp	._end_parse_FRS
442
 
443
.krfs_cmp:
444
	mov	cx,bx
445
	mov	di,ax
446
 
447
        mov     si,parse_RFS_KRFS
448
        mov     cx,parse_RFS_KRFS_e - parse_RFS_KRFS
449
        repe    cmpsb
450
;	jnz	@f	   ;is not compare
451
 
452
	jmp ._end_parse_FRS
453
 
454
 
455
.start_g_tpe_RFS_rest_v:
456
	mov	cx,bx
457
	mov	di,ax
458
	jmp	.start_g_tpe_RFS
459
 
460
 
461
 
462
.end_get_FRS_ERROR_1:
463
;сообщение об ошибке - данный участок кода не был корректно обработан :(
464
	or	show_errors_sect,show_error_1
465
	jmp	._end_parse_FRS
466
.end_get_FRS_ERROR_2:
467
	or	show_errors_sect,show_error_2
468
 
469
._end_parse_FRS:
470
if DEBUG
471
        pusha
472
        mov     si,get_type_FS_msg
473
        call    printplain
474
        popa
475
end if
476
 
477
 
478
 
479
}
480
macro make_FAT_RamFS
481
{
482
local .RS1
483
local .fat12
484
local .fat16
485
; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб..
486
;для случая с FAT12
487
;	mov	di,fat12_buffer	;ds должен быть = cs
488
;es:di - указывают на начало блока для формирования рам фс.
489
use_RamdiskSector	;возращаемое значение в ax размер сектора в байтах
490
	cmp	ax,4096 ;по спецификации значение должно быть в пределах от 1 до 4096
491
	ja	.RS1
492
	test	ax,ax
493
	jnz	@f	;ошибка если сюда прыгнули все таки ...
494
 
495
.RS1:   mov	word [fat12_buffer.BPB_BytsPerSec],512
496
;;;;;;;;;;скажем что по дефолту будем юзать значение...
497
@@:	mov	word [fat12_buffer.BPB_BytsPerSec],ax ;тут все ок
498
 
499
;BPB_SecPerClus кол-во секторов в кластере
500
use_RamdiskCluster	;возращаемое значение в al
501
	cmp	al,128
502
	ja	@f
503
;	test	al,0x1	;проверка на кратность )
504
;	jnz	@f
505
 
506
	mov	byte [fat12_buffer.BPB_SecPerClus],al
507
 
508
	;incorrect value will be set dafault
509
 
510
;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно
511
; мы должны ругнуться на это
512
;@@:	;mov	byte [fat12_buffer.BPB_SecPerClus],1
513
 
514
;;;;; определеим какая у нас будет использоваться FAT
515
;по условию, fat12<4085<=fat16<65525<=fat32
516
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов
517
        movzx	eax,word [fat12_buffer.BPB_BytsPerSec]
518
	movzx	ebx,byte [fat12_buffer.BPB_SecPerClus]
519
 
520
	imul 	ebx,eax	;тут размерность сектора
521
	mov	eax,save_ramdisksize  ;размер запрошенного рам диска в байтах
522
	cdq
523
	idiv	ebx
524
;;;;;;;; сейчас частное в eax, а остаток в edx
525
;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать.
526
	cmp	eax,4085
527
	jb	.fat12
528
	cmp	eax,65525
529
	jb	.fat16
530
;;;;;;;;;;;;;;;;;;;;;;;; тут fat32
531
	mov	set_ramfs,32	;установим тип файловой системы
532
	mov	word [fat12_buffer.BPB_RsvdSecCnt],32
533
	xor	eax,eax
534
	mov	word [fat12_buffer.BPB_RootEntCnt],ax
535
        mov	word [fat12_buffer.BPB_TotSec16],ax
536
        mov	dword [fat12_buffer.BPB_TotSec32],eax
537
 
538
 
539
.fat16:	;fat16
540
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
541
	jmp	$
542
	mov	set_ramfs,16	;установим тип файловой системы
543
	movzx	ebx,byte [fat12_buffer.BPB_SecPerClus]
544
	imul	eax,ebx
545
 
546
        cmp	eax,0x10000
547
	jae	@f
548
	mov	word [fat12_buffer.BPB_TotSec16],ax
549
	mov	dword [fat12_buffer.BPB_TotSec32],0
550
@@:
551
;количество секторов занимаемое одной копией фат
552
;       mov	word [fat12_buffer.BPB_FATSz16],0x9	;Для FAT12/FAT16 это количество секторов одной FAT. ??
553
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
554
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
555
;быть 0. Пока константа, нужно будет позже доделать.
556
	mov	eax,root_dir_entry_count
557
	mov	word [fat12_buffer.BPB_RootEntCnt],ax	; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
558
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
559
;;;;;;;
560
;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение
561
;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32.
562
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec;
563
 
564
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
565
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
566
;If(FATType == FAT32)
567
;    TmpVal2 = TmpVal2 / 2;
568
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2;
569
;If(FATType == FAT32) {
570
;    BPB_FATSz16 = 0;
571
;    BPB_FATSz32 = FATSz;
572
;} else {
573
;    BPB_FATSz16 = LOWORD(FATSz);
574
;    /* there is no BPB_FATSz32 in a FAT16 BPB */
575
;}
576
;=====================================
577
;RootDirSectors
578
	movzx	ebx, word [fat12_buffer.BPB_BytsPerSec]
579
	imul	eax,32
580
	add	eax,ebx
581
	dec	eax
582
 
583
	cdq
584
	idiv	ebx
585
;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14
586
;BPB_ResvdSecCnt + RootDirSectors
587
	movzx	ebx, word [fat12_buffer.BPB_RsvdSecCnt]
588
	add	ebx,eax
589
 
590
;DskSize у нас это значение уже получено и доступно
591
	movzx	eax,word [fat12_buffer.BPB_TotSec16]	;должен быть в секторах
592
	sub	eax,ebx
593
 
594
 
595
;TmpVal1=eax
596
	shl	edi,8	;=edi*256
597
	movzx	ecx,byte [fat12_buffer.BPB_NumFATs]
598
	add	edi,ecx
599
;TmpVal2=edi
600
        add	eax,edi
601
	dec 	eax
602
	cdq
603
	idiv	edi
604
;FATSz = сейчас частное в eax, а остаток в edx
605
        mov	word [fat12_buffer.BPB_FATSz16],ax
606
 
607
 
608
 
609
 
610
 
611
 
612
 
613
 
614
.fat12: ;fat12
615
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
616
	mov	set_ramfs,12	;установим тип файловой системы
617
	movzx	ebx,byte [fat12_buffer.BPB_SecPerClus]
618
	imul	eax,ebx
619
 
620
        cmp	eax,0x10000
621
	jae	@f
622
	mov	word [fat12_buffer.BPB_TotSec16],ax
623
	mov	dword [fat12_buffer.BPB_TotSec32],0
624
@@:
625
;количество секторов занимаемое одной копией фат
626
;       mov	word [fat12_buffer.BPB_FATSz16],0x9	;Для FAT12/FAT16 это количество секторов одной FAT. ??
627
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
628
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
629
;быть 0. Пока константа, нужно будет позже доделать.
630
	mov	eax,root_dir_entry_count
631
	mov	word [fat12_buffer.BPB_RootEntCnt],ax	; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
632
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
633
;;;;;;;
634
;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах)
635
;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет
636
;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12
637
        movzx	eax, word [fat12_buffer.BPB_TotSec16]
638
	imul	eax,12
639
	shr	eax,3	;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера
640
	movzx	ebx,word  [fat12_buffer.BPB_BytsPerSec]	;размер сектора
641
	cdq
642
	idiv	ebx	;разделим на размер кластера
643
;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам
644
;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт
645
;но т.к. все равно делить нижний код нам не нужен
646
;	and	eax,0xfff200
647
;	add	eax,0x200	;добавим 512 байт	 для 1.44 дискеты идеально подходит ))
648
 
649
	inc	ax
650
;по идее должно на каждую фат таблицу
651
;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600
652
;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512
653
;FATSz = сейчас частное в eax
654
        mov	word [fat12_buffer.BPB_FATSz16],ax
655
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
656
get_firstDataSector ;получить смещение до данных
657
;создадим певую запись в фат по определенному адресу.
658
first_create_fat_table
659
;закиним BPB файловой системы за 1 мб.
660
use_BPB_RAM
661
;
662
;копирование файла.
663
use_RamdiskFile
664
 
665
;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
666
;	movzx	ebx, [fat12_buffer.BPB_NumFATs]
667
;	movzx	eax,ax
668
;	imul	eax,ebx
669
;eax=(BPB_NumFATs * BPB_FATSz16)
670
;	inc	eax
671
; BPB_ResvdSecCnt значение только 1 для fat12/16
672
;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1  = 1+ (1*1) =2 или 3
673
 
674
if DEBUG
675
        pusha
676
;	mov	ax,point_default
677
;        mov     ax,cx
678
        mov     cx,0x0a
679
        mov     di,show_db1
680
;        mov     dword[ds:di],'    '
681
;	mov	word [ds:di+4],'  '
682
        call    decode
683
;Show size
684
        mov     si,show_db1
685
        call    printplain
686
;
687
;	xor	ax,ax
688
; 	int	0x16
689
        popa
690
end if
691
 
692
 
693
 
694
 
695
 
696
 
697
 
698
}
699
 
700
macro use_RamdiskSector
701
{
702
;для некоторых FS будет игнорироваться
703
	mov	di,point_default   ;restore value
704
	mov	cx,save_cx_d
705
 
706
.start_RamdiskSector:
707
	call	get_firs_sym	;get first symbol on new line
708
	test	cx,cx
709
	jz      .end_RamdiskSector	;нету? ну ладно - следующее значение тогда )
710
 
711
        cmp	al,'R'
712
        jnz	.start_RamdiskSector
713
;проверка на значения RamdiskSize
714
;        parse_RamdiskSize
715
 
716
        mov     bx,cx
717
        mov     ax,di
718
 
719
        mov     si,parse_RamdiskSector
720
        mov     cx,parse_RamdiskSector_e - parse_RamdiskSector
721
        repe    cmpsb
722
	jnz	.RamdiskSector_rest_val	   ;is not compare
723
 
724
        sub     bx,parse_RamdiskSector_e - parse_RamdiskSector ;correct cx
725
        add     bx,cx
726
        mov     cx,bx
727
 
728
	test	status_flag,flag_found_RamdiskSector 		;оценка флагов
729
	jz	.correct_is_not_set_RamdiskSector
730
 
731
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
732
;	call	printplain
733
;	jmp	.get_next_str
734
 
735
.correct_is_not_set_RamdiskSector:
736
	mov	ax,0x3d20	   ;cut al=' ' ah='='
737
	repe    scasb
738
	jcxz	.end_get_RamS_ERROR_1          ;not found param
739
 
740
        cmp	ah,byte [es:di-1]    ;find '='
741
	jnz	.start_RamdiskSector			; перейдем на начало и попробуем найти еще секцию
742
 
743
	repe    scasb              ;cut ' '
744
	inc	cx
745
	dec	di
746
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
747
	xor	bx,bx
748
	mov	cx,4
749
@@:	movzx	ax,byte [es:di]
750
	cmp	al,'0'
751
	jb	.end_RamdiskSector
752
	cmp	al,'9'
753
	ja	.end_RamdiskSector
754
;;;;;;;;;;;;;;;;;;;
755
 
756
	imul	bx,10
757
	xor 	al,0x30
758
	add	bx,ax
759
 
760
	inc	di
761
 
762
	loop	@b
763
	jmp	.end_RamdiskSector
764
 
765
 
766
.RamdiskSector_rest_val:
767
	mov	cx,bx
768
	mov	di,ax
769
	jmp	.start_RamdiskSector
770
.end_get_RamS_ERROR_1:
771
 
772
.end_RamdiskSector:
773
	mov	ax,bx
774
 
775
if DEBUG
776
        pusha
777
        movzx	eax,bx;save_cx_d;point_default
778
        mov     cx,0x0a
779
        mov     di,RamdiskSector_msg
780
        mov     dword[ds:di],'    '
781
	mov	dword [ds:di+4],'    '
782
        call    decode
783
;Show size
784
        mov     si,RamdiskSector_msg
785
        call    printplain
786
 
787
        popa
788
end if
789
 
790
;	pop	di
791
;	pop	es
792
}
793
 
794
macro use_RamdiskCluster
795
{
796
;для некоторых FS будет игнорироваться
797
;	push	es
798
;	push	di
799
	mov	di,point_default   ;restore value
800
	mov	cx,save_cx_d
801
;	push	ini_data_
802
;	pop	es
803
.start_RamdiskCluster:
804
	call	get_firs_sym	;get first symbol on new line
805
	test	cx,cx
806
	jz      .end_RamdiskCluster	;нету? ну ладно - следующее значение тогда )
807
        cmp	al,'R'
808
        jnz	.start_RamdiskCluster
809
;проверка на значения RamdiskSize
810
;        parse_RamdiskSize
811
 
812
        mov     bx,cx
813
        mov     ax,di
814
 
815
        mov     si,parse_RamdiskCluster
816
        mov     cx,parse_RamdiskCluster_e - parse_RamdiskCluster
817
        repe    cmpsb
818
	jnz	.RamdiskCluster_rest_val	   ;is not compare
819
 
820
        sub     bx,parse_RamdiskCluster_e - parse_RamdiskCluster ;correct cx
821
        add     bx,cx
822
        mov     cx,bx
823
 
824
	test	status_flag,flag_found_RamdiskCluster 		;оценка флагов
825
	jz	.correct_is_not_set_RamdiskCluster
826
 
827
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
828
;	call	printplain
829
;	jmp	.get_next_str
830
 
831
.correct_is_not_set_RamdiskCluster:
832
	mov	ax,0x3d20	   ;cut al=' ' ah='='
833
	repe    scasb
834
	jcxz	.end_get_RamSC_ERROR_1          ;not found param
835
 
836
        cmp	ah,byte [es:di-1]    ;find '='
837
	jnz	.start_RamdiskCluster			; перейдем на начало и попробуем найти еще секцию
838
 
839
	repe    scasb              ;cut ' '
840
	inc	cx
841
	dec	di
842
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
843
@@:	movzx	ax,byte [es:di]
844
	cmp	al,'0'
845
	jb	.end_RamdiskCluster
846
	cmp	al,'9'
847
	ja	.end_RamdiskCluster
848
;;;;;;;;;;;;;;;;;;;
849
	xor 	al,0x30
850
 
851
	jmp	.end_RamdiskCluster
852
 
853
 
854
.RamdiskCluster_rest_val:
855
	mov	cx,bx
856
	mov	di,ax
857
	jmp	.start_RamdiskCluster
858
.end_get_RamSC_ERROR_1:
859
 
860
.end_RamdiskCluster:
861
if DEBUG
862
        pusha
863
        mov     cx,0x0a
864
        mov     di,RamdiskCluster_msg
865
;        mov     word[ds:di],'  '
866
        call    decode
867
;Show size
868
        mov     si,RamdiskCluster_msg
869
        call    printplain
870
 
871
        popa
872
end if
873
 
874
}
875
 
876
macro use_Loader_Image
877
;предназначен для загрузки образов выше 1 Мб.
878
;первоначальная версия загружает образ дискеты 1.44 мб
879
{
880
local .start_p_LI
881
local .exit
882
local .error_LI
883
local .rest_value_loop
884
local .found_end_str
885
	mov	di,point_default   ;restore value
886
	mov	cx,save_cx_d
887
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
888
.start_p_LI:
889
	call	get_firs_sym	;get first symbol on new line
890
	test	cx,cx
891
	jz      .exit	;нету? ну ладно - следующее значение тогда )
892
        cmp	al,'L'
893
        jnz	.start_p_LI
894
;проверка на значение LoaderModule
895
;        parse_LoaderModule
896
        mov     bx,cx
897
        mov     ax,di
898
 
899
        mov     si,parse_LoaderImage
900
        mov     cx,parse_LoaderImage_e - parse_LoaderImage
901
        repe    cmpsb
902
	jnz	.rest_value_loop	   ;is not compare
903
 
904
        sub     bx,parse_LoaderImage_e - parse_LoaderImage ;correct cx
905
        add     bx,cx
906
        mov     cx,bx
907
 
908
;	test	status_flag,flag_found_LM 		;оценка флагов
909
;	jz	.correct_is_not_set_LI
910
 
911
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
912
;	call	printplain
913
;	jmp	.get_next_str
914
 
915
;.correct_is_not_set_LI:
916
	mov	ax,0x3d20	   ;cut al=' ' ah='='
917
	repe    scasb
918
	jcxz	.rest_value_loop_LI          ;not found param timeout
919
 
920
        cmp	ah,byte [es:di-1]    ;find '='
921
	jnz	.rest_value_loop_LI
922
 
923
	repe    scasb              ;cut ' '
924
	inc	cx
925
	dec	di
926
;di указывает на начало блока информации, в cx длинна до конца секции.
927
;после загрузки заноситься значение занятой памяти.
928
;для того что бы загрузить модуль, воспользуемся callback сервисом
929
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
930
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
931
;мы ее модифицируем до такого состояния       dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
932
;сохранили певые 2 word
933
	push	dword [es:di-6]
934
	lea	si,[di-6]
935
 
936
	push	word  [es:di-2]
937
	xor	ax,ax
938
	mov	word [es:di-6],ax	;вносим нужные значения
939
;info_real_mode_size размер и указатель на область в которую можно загрузиться
940
	mov	ax,info_real_mode_size	;0x3000   ;следующий сегмент за данными
941
 
942
 
943
	mov	word [es:di-4],ax
944
	mov	word [es:di-2],16	;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
945
;;;;;; поиск конца строчки
946
@@:	mov	al,byte [es:di]
947
	cmp	al,' '
948
	jz	.found_end_str
949
	cmp	al,0xa
950
	jz	.found_end_str
951
	cmp	al,0xd
952
	jz	.found_end_str
953
	inc	di
954
	dec	cx
955
	jnz	@b
956
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
957
.found_end_str:
958
; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб.
959
	push	word [es:di]
960
	xor	ax,ax
961
	mov	word [es:di],ax
962
;        xor     ax,ax   ; function 1 - read file
963
        mov     di,si	;file_data
964
	inc	ax
965
	push	si
966
	push	es
967
        call    far  dword [loader_callback]
968
        push    cs
969
        pop     ds
970
 
971
	pop	es
972
	pop	si
973
 
974
        test    bx,bx
975
        jnz     .error_LM
976
 
977
 
978
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб.
979
        mov     si,table_15_87
980
        push    es
981
        push    ds
982
        pop     es
983
        mov     cx, 256*18
984
        mov     ah, 0x87
985
        int     0x15
986
        pop     es
987
        pop     dx cx
988
        test    ah, ah
989
 
990
 
991
 
992
        jmp	far	dword [es:si]
993
 
994
 
995
 
996
 
997
.rest_value_loop:
998
        mov	di,ax
999
	mov	cx,bx
1000
	jmp	.start_p_LI
1001
 
1002
.exit:
1003
 
1004
 
1005
 
1006
}
1007
 
1008
 
1009
 
1010
macro name_in_root_fat
1011
;макрос, который записывает информацию о загруженном файле в корневую фат таблицу
1012
{
1013
 
1014
}
1015
 
1016
 
1017
 
1018
macro use_RamdiskFile
1019
{
1020
;загрузка файлов с использование callback сервиса первичного загрузчика
1021
;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает
1022
;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб
1023
local	.start_loop
1024
local   ._end
1025
local   .rest_value_loop
1026
local   .error
1027
	mov	di,point_default   ;restore value
1028
	mov	cx,save_cx_d
1029
	mov	data_offset,0	;clean offset
1030
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
1031
.start_loop:
1032
	call	get_firs_sym	;get first symbol on new line
1033
	test	cx,cx
1034
	jz      ._end	;нету? ну ладно - следующее значение тогда )
1035
        cmp	al,'R'
1036
        jnz	.start_loop
1037
;проверка на значение RamdiskFile
1038
        mov     bx,cx
1039
        mov     ax,di
1040
 
1041
        mov     si,parse_RamdiskFile
1042
        mov     cx,parse_RamdiskFile_e - parse_RamdiskFile
1043
        repe    cmpsb
1044
	jnz	.rest_value_loop	   ;is not compare
1045
 
1046
        sub     bx,parse_RamdiskFile_e - parse_RamdiskFile ;correct cx
1047
        add     bx,cx
1048
        mov     cx,bx
1049
;	test	status_flag,flag_found_LM 		;оценка флагов
1050
;	jz	.correct_is_not_set_LM
1051
 
1052
;	mov	si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
1053
;	call	printplain
1054
;	jmp	.get_next_str
1055
 
1056
;.correct_is_not_set_LM:
1057
	mov	ax,0x3d20	   ;cut al=' ' ah='='
1058
	repe    scasb
1059
	test	ecx,ecx
1060
	jz	.rest_value_loop   ;not found param timeout
1061
 
1062
        cmp	ah,byte [es:di-1]  ;find '='
1063
	jnz	.rest_value_loop
1064
 
1065
	repe    scasb              ;cut ' '
1066
	inc	cx
1067
	dec	di
1068
 
1069
	mov	save_di_RAMDISK,di
1070
	mov	save_cx_RAMDISK,cx
1071
;di указывает на начало блока информации, в cx длинна до конца секции.
1072
;после загрузки заноситься значение занятой памяти.
1073
;для того что бы загрузить модуль, воспользуемся callback сервисом
1074
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
1075
;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu
1076
;мы ее модифицируем до такого состояния       dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем
1077
;сохранили певые 2 word
1078
 
1079
;//проверка наличия такого же имени в рут дир
1080
 
1081
@@:	mov	al,byte [es:di]
1082
	cmp	al,','  	; т.е. ищем разделитель
1083
	jz	.found_end_str
1084
	inc	di
1085
	dec	cx
1086
	jnz	@b
1087
;;;not found допустим,что это конец файла и он не имеет привычного завершения строки
1088
.found_end_str:
1089
;        mov	al,byte [es:di]
1090
;	cmp	al,' '  	; убираем пробелы, если они есть
1091
;	jnz	@f
1092
;	inc	di
1093
;	dec	cx
1094
;	jnz	.found_end_str
1095
 
1096
;@@:
1097
        mov	point_to_dest_file_name,di
1098
	inc	di
1099
;проверка индивидуальности имени файла
1100
check_name_file
1101
;/restore di - point and cx -size section
1102
	mov	di,save_di_RAMDISK
1103
	mov	cx,save_cx_RAMDISK
1104
 
1105
	test	al,al
1106
	jnz	.start_loop	;если в al значение не =0, то такое имя уже существует в системе.
1107
 
1108
 
1109
 
1110
	push	dword [es:di-6]
1111
	lea	si,[di-6]
1112
 
1113
	push	word  [es:di-2]
1114
	push	di
1115
	xor	ax,ax
1116
	mov	word [es:di-6],ax	;вносим нужные значения
1117
;info_real_mode_size размер и указатель на область в которую можно загрузиться
1118
	mov	ax,info_real_mode_size	;0x3000   ;следующий сегмент за данными
1119
 
1120
 
1121
	mov	word [es:di-4],ax
1122
	mov	word [es:di-2],16	;кол-во блоков по 4 кб =64 кб т.е. больше не читаем
1123
 
1124
        mov	di,point_to_dest_file_name
1125
 
1126
	push	word [es:di]
1127
	push	cx
1128
	xor	ax,ax
1129
	mov	word [es:di],ax
1130
;        xor     ax,ax   ; function 1 - read file
1131
	push	di
1132
        mov     di,si	;file_data
1133
	inc	ax
1134
	push	si
1135
	push	es
1136
	push	bp
1137
 
1138
	push	es
1139
	pop	ds
1140
	push	cs
1141
	pop	es
1142
 
1143
        call    far  dword [es:loader_callback]
1144
 
1145
 
1146
        push    cs
1147
        pop     ds
1148
 
1149
	pop	bp
1150
	pop	es
1151
	pop	si
1152
 
1153
        cmp    bx,2
1154
        ja     .error
1155
; сейчас у нас в dx:ax размер файла, который мы загрузили.
1156
; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске
1157
	mov	status_flag_loader_f,bx
1158
 
1159
	shl	edx,16
1160
	mov	dx,ax
1161
;	shr	edx,10 	;размер файла в кб.
1162
;;в edx размер в байтах.
1163
	mov	save_file_size,edx
1164
	mov	eax,edx
1165
;восстановим полностью файл сценария
1166
	pop	di
1167
	pop	cx	;длинна остатка с 2-ой частью имени т.е. с именем назначением.
1168
	pop	word [es:di]
1169
	pop	di
1170
	pop     word  [es:di-2]
1171
	pop	dword [es:di-6]
1172
 
1173
 
1174
if DEBUG
1175
        pusha
1176
        mov     cx,0x0a
1177
        mov     di,RamdiskFile_msg
1178
        mov     dword[ds:di],'    '
1179
        call    decode
1180
;Show size
1181
        mov     si,RamdiskFile_msg
1182
        call    printplain
1183
 
1184
        popa
1185
end if
1186
 
1187
 
1188
 
1189
 
1190
 
1191
 
1192
 
1193
 
1194
 
1195
 
1196
; загрузим чему у нас равен кластер
1197
;	mov	ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта
1198
;	movzx	bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере
1199
;	imul	ax,bx
1200
;сейчас в eax размер кластера (512) байт
1201
;в edx длина файла в байтах до 64 кб
1202
;закиним файл за 1 мб
1203
;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл
1204
 
1205
;записать инфорамацию о файле в корневую директорию
1206
register_file_in_fat
1207
;перенести за 1 мб содержимое файла
1208
move_file_up
1209
 
1210
;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки
1211
	cmp	status_flag_loader_f,0x1
1212
	jnz	@f
1213
;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре
1214
 
1215
 
1216
 
1217
 
1218
 
1219
 
1220
 
1221
 
1222
 
1223
@@:
1224
;тут организован цикл по загрузке файлов в корневую директорию
1225
	mov	di,save_di_RAMDISK
1226
	mov	cx,save_cx_RAMDISK
1227
if DEBUG
1228
        pusha
1229
	xor	ax,ax
1230
	int	0x16
1231
        popa
1232
end if
1233
 
1234
 
1235
        jmp	.start_loop
1236
 
1237
 
1238
.error:
1239
        ;call	error.LoaderModule
1240
;fixme!
1241
.rest_value_loop:
1242
        mov	di,ax
1243
	mov	cx,bx
1244
	jmp	.start_loop
1245
 
1246
._end:
1247
;перенесем за 1-ый мб фат и рут дир
1248
move_up_fat_and_root_d
1249
 
1250
 
1251
 
1252
 
1253
 
1254
 
1255
;загрузка блока
1256
;	mov	ah,0x87
1257
;	mov	cx,	;size in byte
1258
 
1259
 
1260
;es:si point to descripts
1261
 
1262
 
1263
}
1264
 
1265
macro use_BPB_RAM
1266
;данный макрос закидывает BPB структуру, пока только фат12 за 1 мб
1267
{
1268
	mov	ax,fat12_buffer
1269
        mov     si,table_15_87
1270
	add	word [si+8*2+2],ax
1271
        push    es
1272
        push    ds
1273
        pop     es
1274
        mov     cx,31	;фат12 укладывается в 62 байта 62/2=31
1275
        mov     ah, 0x87
1276
        int     0x15
1277
        pop     es
1278
;add 512 byte for destination adress
1279
;	add     dword [si+8*3+2], 512
1280
;        test    ah, ah
1281
;        jz
1282
if DEBUG
1283
        pusha
1284
	mov	ax,word [si+8*2+2]
1285
        mov     cx,0x0a
1286
        mov     di,BPB_msg
1287
        call    decode
1288
;Show size
1289
        mov     si,BPB_msg
1290
        call    printplain
1291
        popa
1292
end if
1293
}
1294
macro first_create_fat_table
1295
;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение
1296
;для смещения в корневой таблице.
1297
{
1298
	mov	al,byte [fat12_buffer.BPB_Media]
1299
 
1300
 
1301
        push	ds
1302
 
1303
 
1304
	mov	di,info_real_mode_size
1305
	add	di,0x1000
1306
        push	di   ;	push	word info_real_mode_size+0x1000   ;cледующий сегмент за загруженным участком
1307
 
1308
	xor	di,di
1309
	mov	point_to_free_root,di	;значение смещения =0 в корневой фат таблице описания
1310
 
1311
 
1312
	pop	ds
1313
 
1314
	mov	byte [di],al
1315
	or	ax,-1
1316
	inc	di
1317
	mov	word [di],ax
1318
 
1319
 
1320
 
1321
	pop	ds
1322
	mov	point_next_fat_str,3
1323
 
1324
if DEBUG
1325
        pusha
1326
	mov	ax,point_next_fat_str
1327
        mov     cx,0x0a
1328
        mov     di,fat_create_msg
1329
        call    decode
1330
;Show size
1331
        mov     si,fat_create_msg
1332
        call    printplain
1333
        popa
1334
end if
1335
 
1336
}
1337
macro register_file_in_fat
1338
;макрос регистрации файла в файловой структуре Fat
1339
;пока поддерживается только фат12, пока ))
1340
;вычисление смежных кластеров и занесение инфы в fat/
1341
{
1342
local	.step2
1343
local	.step3
1344
local	.end
1345
local   .eof_file
1346
 
1347
;di point on root dir на фри секцию.
1348
	push	es
1349
 
1350
	mov	ax,info_real_mode_size
1351
	add	ax,0x1000
1352
	mov	es,ax  ;	push	word info_real_mode_size+0x1000   ;сегмент следующий за загруженным блоком в 64 кб
1353
 
1354
; определяем тип фат пока не определяем, пока только фат 12
1355
; 12 бит, для вычесления соседних каластеров.
1356
	mov	di,firstDataSect     ;в секторах
1357
	sub	di,size_root_dir
1358
;теперь в ax размер в секторах начала рут дир
1359
	shl	di,9 ;imul 512
1360
	add	di,point_to_free_root   ;смещение в уже записанных 32-х структурах.
1361
;необходимо внести значение в рут дир т.е. 32 байта
1362
;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле.
1363
	mov	si,shot_name_fat
1364
	mov	cx,11
1365
;запишем в структуру имя
1366
@@:	lodsb
1367
	stosb
1368
	loop	@b
1369
 
1370
;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0
1371
	xor	ax,ax
1372
	mov	ah,ATTR_VOLUME_ID
1373
        mov	word [es:di],ax
1374
	add	di,2
1375
;DIR_CrtTimeTenth
1376
	mov	byte [es:di],100
1377
	inc	di
1378
;DIR_CrtTime
1379
	mov	word [es:di],0x032b    ;дата
1380
	add	di,2
1381
;DIR_CrtDate
1382
	mov	word [es:di],0x0       ;время ><
1383
	add	di,2
1384
;DIR_LstAccDate
1385
	mov	word [es:di],0x032b    ;дата моего
1386
	add	di,2
1387
;DIR_FstClusHI
1388
	mov	word [es:di],0x0       ;время для фат12 /16 всегда 0
1389
	add	di,2
1390
;DIR_WrtTime
1391
	mov	word [es:di],0x0       ;время ><
1392
	add	di,2
1393
;DIR_WrtDate
1394
	mov	word [es:di],0x032b
1395
	add	di,2
1396
 
1397
	mov	ax,point_next_fat_str
1398
	mov	word [es:di],ax
1399
	add	di,2
1400
 
1401
	push	di
1402
;DIR_FstClusLO			Младшее слово номера первого кластера.
1403
;	mov	ax,point_next_fat_str	;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
1404
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
1405
	mov	bx,ax
1406
	shr	bx,1
1407
	add	ax,bx
1408
;в ах сейчас FATOffset
1409
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);
1410
        mov	bx, word [fat12_buffer.BPB_BytsPerSec]
1411
	cwd
1412
	idiv	bx
1413
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель.
1414
	mov	si,ax
1415
;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла.
1416
;узнаем размер кластера.
1417
	movzx	eax,word [fat12_buffer.BPB_BytsPerSec]
1418
	movzx	ebx,byte [fat12_buffer.BPB_SecPerClus]
1419
	imul	eax,ebx
1420
;ax - размер кластера.
1421
;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью
1422
;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла.
1423
	mov	ebx,save_file_size	;размер файла в байтах
1424
 
1425
@@:	sub	ebx,eax
1426
	cmp	ebx,eax
1427
	jbe	.eof_file
1428
 
1429
	inc     point_next_fat_str
1430
	mov	cx,point_next_fat_str	;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
1431
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
1432
	mov	dx,ax
1433
	shr	dx,1
1434
	add	cx,dx
1435
 
1436
 
1437
 
1438
	test	si,0x1
1439
	jz	.step2
1440
	shl	cx,4
1441
	mov	word[es:si],cx
1442
	inc	si
1443
	add	cx,ax
1444
	jmp	@b
1445
 
1446
.step2:	and	cx,0x0FFF
1447
	mov	word[es:si],cx
1448
	inc	si
1449
	add	cx,ax
1450
	jmp	@b
1451
 
1452
.eof_file:
1453
        mov	cx,0x0fff
1454
	test	si,0x1
1455
	jz	.step3
1456
	shl	cx,4
1457
	mov	word[es:si],cx
1458
	jmp	.end
1459
 
1460
.step3:	and	cx,0x0FFF
1461
	mov	word[es:si],cx
1462
 
1463
.end:  	inc     point_next_fat_str
1464
 
1465
	pop	di
1466
;DIR_FileSize 32-битный DWORD содержит размер файла в байтах.
1467
	mov	eax,save_file_size
1468
	mov	dword [es:di],eax
1469
 
1470
if DEBUG
1471
        pushad
1472
 
1473
	mov	di,firstDataSect     ;в секторах
1474
	sub	di,size_root_dir
1475
;теперь в ax размер в секторах начала рут дир
1476
	shl	di,9 ;imul 512
1477
	add	di,point_to_free_root   ;смещение в уже записанных 32-х структурах.
1478
 
1479
	mov	si,dest_name_fat
1480
	mov	cx,11
1481
;запишем в структуру имя
1482
@@:	mov	al,byte [es:di]
1483
	inc	di
1484
	mov	byte [ds:si],al
1485
	inc	si
1486
	loop	@b
1487
 
1488
	xor	ax,ax
1489
	mov	byte [si],al
1490
	mov	si,dest_name_fat
1491
        call    printplain
1492
	popad
1493
 
1494
END IF
1495
 
1496
 
1497
 
1498
 
1499
 
1500
	add	point_to_free_root,32	;увелицим смещение до следующего значения.
1501
	pop	es
1502
 
1503
}
1504
 
1505
 
1506
 
1507
 
1508
 
1509
macro get_firstDataSector
1510
;макрос для вычисления певого сектора данных т.е. данных файлов в фате
1511
;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;
1512
{
1513
	mov	ax,word [fat12_buffer.BPB_FATSz16]
1514
	movzx	bx,byte [fat12_buffer.BPB_NumFATs]
1515
	imul	ax,bx   ;9x1=9
1516
;ax=BPB_NumFATs * FATSz
1517
	mov	bx,word [fat12_buffer.BPB_RootEntCnt]	; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
1518
	shr	bx,4	;imul bx,32 and then div 512 -> in bx size in sectors
1519
	add	ax,bx   ;9+14=23
1520
	mov	size_root_dir,bx
1521
	movzx	bx,byte [fat12_buffer.BPB_RsvdSecCnt]	;add 1 for fat 16/12
1522
	add	ax,bx
1523
;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор
1524
        mov	firstDataSect,ax	;сохраним для вычисления
1525
;	получимзначение кластеров, это объем в который мы можем записать данные
1526
        mov	bx,word [fat12_buffer.BPB_TotSec16]
1527
	sub	bx,ax
1528
	mov	ax,bx
1529
	movzx	bx,byte [fat12_buffer.BPB_SecPerClus]
1530
	cwd
1531
	idiv	bx
1532
	mov	DataClasters,ax
1533
 
1534
if DEBUG
1535
        pusha
1536
	mov	ax,firstDataSect	;первый сектор данных
1537
        mov     cx,0x0a
1538
        mov     di,firstDataSect_msg
1539
        call    decode
1540
;Show size
1541
        mov     si,firstDataSect_msg
1542
        call    printplain
1543
;;;;;;;;;;;;;;;;;;;;;;;;;;
1544
	mov	ax,size_root_dir	;размер рут дир в сетокторах
1545
        mov     cx,0x0a
1546
        mov     di,size_root_dir_msg
1547
        call    decode
1548
;Show size
1549
        mov     si,size_root_dir_msg
1550
        call    printplain
1551
;;;;;;;;;;;;;;;;;;;;;;;;;;
1552
	mov	ax,DataClasters	;кластеры
1553
        mov     cx,0x0a
1554
        mov     di,DataClasters_msg
1555
        call    decode
1556
;Show size
1557
        mov     si,DataClasters_msg
1558
        call    printplain
1559
        popa
1560
 
1561
end if
1562
 
1563
}
1564
 
1565
macro use_RamdiskPATHS
1566
;парсинг пути источника файлов.
1567
{
1568
 
1569
}
1570
 
1571
macro use_RamdiskPATHD
1572
;парсинг пути назначения файлов.
1573
{
1574
 
1575
}
1576
macro check_name_file
1577
;макрос проверки имени на повтор, имя должно быть уникальным.
1578
;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini
1579
;di - указатель на имя файла т.е. es:di указывает на имя файла назначения
1580
;выходные данные eax =-1 имя совпало, eax=0 имя не совпало.
1581
{
1582
local	.no_equal
1583
local	.exit
1584
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
1585
;преобразуем в аналог фат записи сточку с именем назначения
1586
	convertion_file_name
1587
	test	ax,ax
1588
	jnz	.exit
1589
 
1590
	mov	si,shot_name_fat
1591
 
1592
;вычислим указатель на корневую директорию
1593
	mov	di,firstDataSect
1594
	sub	di,size_root_dir
1595
;теперь в ax размер в секторах начала рут дир
1596
 
1597
 
1598
	shl	di,9 ;imul 512
1599
 
1600
 
1601
 
1602
 
1603
;di= Это смещение от начала буфера до рут директории.
1604
;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать.
1605
        mov	dx,root_dir_entry_count
1606
;        mov     si,point_to_dest_file_name
1607
 
1608
	mov	ax,info_real_mode_size
1609
	add	ax,0x1000
1610
 
1611
 
1612
	mov	gs,ax
1613
	mov	cx,11	;size of name in struct FAT
1614
 
1615
@@:
1616
	mov	al,byte [ds:si+bx]
1617
	mov	ah,byte [gs:di+bx] 	;gs:di - point to name in fat struct
1618
	inc	bx
1619
 
1620
	cmp	ah,al
1621
	jnz	.no_equal
1622
 
1623
;	dec	cx
1624
;	jnz	@b
1625
	loop	@b
1626
;.succesfuly:
1627
;печально, такое имя уже имеется :(
1628
	or	ax,-1
1629
	jmp	.exit
1630
 
1631
 
1632
.no_equal:
1633
	mov	cx,11;save_cx_check_name
1634
	xor	bx,bx
1635
	add	di,32		;fat struct =32 byte
1636
	dec	dx
1637
	jnz	@b
1638
 
1639
;.exit_check_name:
1640
	and	ax,0
1641
 
1642
.exit:
1643
 
1644
if DEBUG
1645
        pusha
1646
;	movzx	eax,ax;point_next_fat_str
1647
        mov     cx,0x0a
1648
        mov     di,check_name_fat_msg
1649
        mov	dword [di],'    '
1650
        mov	word  [di+4],'  '
1651
        call    decode
1652
;Show size
1653
        mov     si,check_name_fat_msg
1654
        call    printplain
1655
        popa
1656
end if
1657
 
1658
}
1659
 
1660
 
1661
macro convertion_file_name
1662
;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать
1663
;преобразование имени типа hello.asm в 'HELLO   ASM', в соответствии с правилами fat.
1664
{
1665
local	.next_step
1666
local   .error
1667
local   .st1
1668
local   .st2
1669
local	.st2_l
1670
local	.st3
1671
local	.st4_s
1672
local	.st4
1673
local	.st5
1674
 
1675
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
1676
;	mov     di,point_to_dest_file_name   входной параметр
1677
	mov	si,shot_name_fat
1678
	or      first_input,-1	;при первом входе устанавливаем флаг
1679
	mov	cx,11	;длинна имени в стуктуре фат таблицы
1680
 
1681
@@:
1682
	mov	al,byte [es:di]
1683
	cmp	al,0xa
1684
	jz	.st4_s
1685
	cmp	al,0xd
1686
	jz	.st4_s
1687
	cmp	al,0x20
1688
	jz	.st4_s
1689
 
1690
	cmp	al,0x20
1691
	jb	.error
1692
	cmp	al,0x22
1693
	jz	.error
1694
	cmp	al,0x2a
1695
	jz	.error
1696
	cmp	al,0x2b
1697
	jz	.error
1698
	cmp	al,0x2c
1699
	jz	.error
1700
	cmp	al,0x2F
1701
	jz	.error
1702
 
1703
	cmp	al,0x3a
1704
	jz	.error
1705
	cmp	al,0x3b
1706
	jz	.error
1707
	cmp	al,0x3c
1708
	jz	.error
1709
	cmp	al,0x3d
1710
	jz	.error
1711
	cmp	al,0x3E
1712
	jz	.error
1713
	cmp	al,0x3F
1714
	jz	.error
1715
 
1716
	cmp	al,0x5b
1717
	jz	.error
1718
	cmp	al,0x5c
1719
	jz	.error
1720
	cmp	al,0x5d
1721
	jz	.error
1722
 
1723
	cmp	al,0x7c
1724
	jz	.error
1725
 
1726
 
1727
	cmp     first_input,-1
1728
	jnz     .next_step
1729
	and	first_input,0	;сборосим флаг.
1730
	cmp	al,'.'
1731
	jz	.error	;обработка точки, файл не может начинаться с точки
1732
 
1733
.next_step:
1734
	cmp	al,0x2e
1735
	jnz	.st2		;обработка точки, в середине файла
1736
;тут у нас установлен разделитель
1737
;все остальнео место займут пробелы
1738
	mov	al,' '
1739
 
1740
;!fixme обработаны не все исключения :(
1741
	cmp	cl,3	;формат файла такой GIDGIDIIASM т.е. gidgidii.asm
1742
	jbe	.st2
1743
 
1744
 
1745
.st3:
1746
	mov	byte [si],al
1747
	inc	si
1748
	dec	cx
1749
	cmp	cx,3
1750
	ja	.st3
1751
;	inc	cx
1752
	inc	di
1753
	jmp	@b
1754
 
1755
.st2:
1756
	cmp	al,0x60
1757
	jbe     .st2_l
1758
 
1759
      	xor	al,0x20	;сделаем заглавные буквы
1760
.st2_l:	mov	byte [si],al
1761
	inc	di
1762
	inc	si
1763
;        dec	cx
1764
;	jnz	@b
1765
	loop	@b
1766
.st5:	xor	ax,ax
1767
	jmp	@f
1768
 
1769
;;;;;;;;файл закончился, и нужно внести в конец пробелы
1770
.st4_s:	mov	al,' '
1771
.st4:	mov	byte [si],al
1772
	inc	si
1773
	loop	.st4
1774
	jmp	.st5
1775
 
1776
.error:	or	ax,-1
1777
@@:
1778
 
1779
if DEBUG
1780
        pusha
1781
;	mov	ax,point_next_fat_str
1782
        mov     cx,0x0a
1783
        mov     di,convertion_file_name_msg
1784
        call    decode
1785
;Show size
1786
        mov     si,convertion_file_name_msg
1787
        call    printplain
1788
 
1789
	mov	si,shot_name_fat
1790
	mov	byte [si+12],0
1791
	call    printplain
1792
        popa
1793
 
1794
end if
1795
}
1796
 
1797
macro move_file_up
1798
;макрос который перемещает за 1 мб с правилами фат данные файла.
1799
{
1800
local	.st1
1801
local	.correct_on_byte
1802
;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены,
1803
;а нам нужно вычислить место, и перенести туда содержимое файла
1804
;полученое значение указывает в байтах на начало данных
1805
 
1806
	mov	ax,info_real_mode_size  ; сегмент где расположены данные
1807
        mov     si,table_15_87
1808
	mov	word [si+8*2+2],ax
1809
;смещение до данных уже за 1-м мб
1810
	movzx	eax,firstDataSect
1811
	movzx	edx,data_offset
1812
	add	eax,edx
1813
 
1814
       	movzx	ebx,word [fat12_buffer.BPB_BytsPerSec]
1815
	movzx	edx,byte [fat12_buffer.BPB_SecPerClus]
1816
	imul	bx,dx   ;получим размер кластера
1817
 
1818
 
1819
 
1820
	push	ebx	;save bx
1821
 
1822
	imul	eax,ebx
1823
;	shl	eax,9	;умножим на 512
1824
 
1825
if DEBUG
1826
	pusha
1827
;	mov	eax,ebx;point_next_fat_str
1828
        mov     cx,0x0a
1829
        mov     di,show_db1
1830
        call    decode
1831
;Show size
1832
        mov     si,show_db1
1833
        call    printplain
1834
	popa
1835
 
1836
end if
1837
 
1838
;      	mov	bx,word [fat12_buffer.BPB_BytsPerSec]
1839
;	movzx	dx,byte [fat12_buffer.BPB_SecPerClus]
1840
;	imul	bx,dx
1841
;	cwd
1842
;	idiv	bx
1843
 
1844
        mov	dl,0x10
1845
 
1846
@@:	cmp	eax,0x00010000
1847
	jb	@f
1848
 
1849
	sub	eax,0x00010000
1850
	inc	dl
1851
	jmp	@b
1852
 
1853
 
1854
@@:	mov	byte [si+8*3+3],dl      ;куда писать
1855
	mov	word [si+8*3+2],ax
1856
 
1857
        mov     ecx,save_file_size	;размер файла в байтах.
1858
        cmp	ecx,0x0000ffff		;размер блока т.е. 64 кб
1859
        jbe	.correct_on_byte        ;корректировка на байт значения
1860
 
1861
 
1862
 
1863
        mov	ecx,0x00010000		;65536
1864
        sub	save_file_size,ecx	;отнимим
1865
;	jmp	.st1			;получим 0х8000
1866
 
1867
 
1868
 
1869
 
1870
;корректировка значения должна быть выполенена на размер кластера
1871
.correct_on_byte:
1872
;/узнаем размер кластера
1873
	pop	eax	;restore size of claster
1874
	push	ecx
1875
@@:	inc	data_offset
1876
 
1877
	cmp	eax,ecx
1878
	jae	@f
1879
	sub	ecx,eax
1880
	jmp	@b
1881
@@:	pop	ecx
1882
 
1883
 
1884
 
1885
 
1886
	test	ecx,0x1
1887
	jz	.st1
1888
	inc	ecx
1889
.st1:   shr	ecx,1     ; преобразовать значение для 0x87 function
1890
 
1891
;перенесем блок за 1 мб
1892
        push    es
1893
        push    ds
1894
        pop     es
1895
 
1896
        mov     ah, 0x87
1897
        int     0x15
1898
        pop     es
1899
 
1900
if DEBUG
1901
	pusha
1902
;	mov	ax,point_next_fat_str
1903
        mov     cx,0x0a
1904
        mov     di,return_code_af_move
1905
        call    decode
1906
;Show size
1907
        mov     si,return_code_af_move
1908
        call    printplain
1909
	popa
1910
 
1911
end if
1912
 
1913
}
1914
 
1915
 
1916
macro move_up_fat_and_root_d
1917
;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию
1918
{
1919
local  .st1
1920
 
1921
	mov	ax,info_real_mode_size
1922
	add	ax,0x1000
1923
 
1924
        mov     si,table_15_87
1925
	mov	word [si+8*2+2],ax
1926
;смещение до данных
1927
	mov	ax,512
1928
	mov	word [si+8*3+2],ax
1929
;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных.
1930
 
1931
	movzx	ecx,word [fat12_buffer.BPB_FATSz16]
1932
	movzx	bx,byte [fat12_buffer.BPB_NumFATs]
1933
	imul	cx,bx   ;9x1=9
1934
 
1935
        add	cx,size_root_dir	;размер корневой дирректории
1936
	shl	ecx,9	;imul 512
1937
 
1938
 
1939
;корректировка значения
1940
	test	ecx,0x1
1941
	jz	.st1
1942
	inc	ecx
1943
.st1:   shr	ecx,1
1944
 
1945
        push    es
1946
        push    ds
1947
        pop     es
1948
 
1949
        mov     ah, 0x87
1950
        int     0x15
1951
        pop     es
1952
 
1953
if DEBUG
1954
	pusha
1955
;	mov	ax,point_next_fat_str
1956
        mov     cx,0x0a
1957
        mov     di,return_code_af_fat_m
1958
        call    decode
1959
;Show size
1960
        mov     si,return_code_af_fat_m
1961
        call    printplain
1962
	popa
1963
 
1964
end if
1965
 
1966
}