Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                      ;;
3
;; RAMDISK functions                                                    ;;
4
;; (C) 2004 Ville Turjanmaa, License: GPL                               ;;
5
;; Addings by M.Lisovin                                                 ;;
83 diamond 6
;; LFN support by diamond                                               ;;
1 ha 7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8
 
5 halyavin 9
; calculate fat chain
1 ha 10
 
5 halyavin 11
calculatefatchain:
12
 
13
   pushad
14
 
15
   mov  esi,0x100000+512
16
   mov  edi,0x280000
17
 
18
 fcnew:
19
   mov  eax,dword [esi]
20
   mov  ebx,dword [esi+4]
21
   mov  ecx,dword [esi+8]
22
   mov  edx,ecx
23
   shr  edx,4   ;8 ok
24
   shr  dx,4    ;7 ok
25
   xor  ch,ch
26
   shld ecx,ebx,20 ;6 ok
27
   shr  cx,4     ;5 ok
28
   shld ebx,eax,12
29
   and  ebx,0x0fffffff  ;4 ok
30
   shr  bx,4    ;3 ok
31
   shl  eax,4
32
   and  eax,0x0fffffff  ;2 ok
33
   shr  ax,4  ;1 ok
78 diamond 34
   mov  dword [edi],eax
35
   mov  dword [edi+4],ebx
36
   mov  dword [edi+8],ecx
37
   mov  dword [edi+12],edx
38
   add  edi,16
5 halyavin 39
   add  esi,12
40
 
41
   cmp  edi,0x280000+2856*2   ;2849 clusters
42
   jnz  fcnew
43
 
44
   popad
45
   ret
46
 
47
 
48
restorefatchain:   ; restore fat chain
49
 
50
   pushad
51
 
52
   mov  esi,0x280000
53
   mov  edi,0x100000+512
54
 
55
  fcnew2:
56
   mov  eax,dword [esi]
57
   mov  ebx,dword [esi+4]
58
   shl  ax,4
59
   shl  eax,4
60
   shl  bx,4
61
   shr  ebx,4
62
   shrd eax,ebx,8
63
   shr  ebx,8
78 diamond 64
   mov  dword [edi],eax
65
   mov  word [edi+4],bx
66
   add  edi,6
5 halyavin 67
   add  esi,8
68
 
69
   cmp  edi,0x100000+512+4278     ;4274 bytes - all used FAT
70
   jb   fcnew2
71
 
72
   mov  esi,0x100000+512           ; duplicate fat chain
73
   mov  edi,0x100000+512+0x1200
74
   mov  ecx,1069        ;4274/4
75
   cld
76
   rep  movsd
77
 
78
   popad
79
   ret
80
 
81
 
1 ha 82
ramdisk_free_space:
83
;---------------------------------------------
84
;
85
; returns free space in edi
86
; rewr.by Mihasik
87
;---------------------------------------------
88
 
89
        push   eax ebx ecx
90
 
91
        mov  edi,0x280000 ;start of FAT
92
        xor  ax,ax    ;Free cluster=0x0000 in FAT
93
        xor  ebx,ebx  ;counter
5 halyavin 94
        mov  ecx,2849 ;2849 clusters
1 ha 95
        cld
96
    rdfs1:
97
        repne scasw
98
        jnz  rdfs2    ;if last cluster not 0
99
        inc  ebx
78 diamond 100
        test    ecx, ecx
101
        jnz     rdfs1
1 ha 102
    rdfs2:
103
        shl  ebx,9    ;free clusters*512
104
        mov  edi,ebx
105
 
106
        pop    ecx ebx eax
107
        ret
108
 
109
 
110
expand_filename:
111
;---------------------------------------------
112
;
113
; exapand filename with '.' to 11 character
114
; eax - pointer to filename
115
;---------------------------------------------
116
 
117
        push esi edi ebx
118
 
119
        mov  edi,esp                  ; check for '.' in the name
120
        add  edi,12+8
121
 
122
        mov  esi,eax
123
 
124
        mov  eax,edi
125
        mov  [eax+0],dword '    '
126
        mov  [eax+4],dword '    '
127
        mov  [eax+8],dword '    '
128
 
129
      flr1:
130
 
131
        cmp  [esi],byte '.'
132
        jne  flr2
133
        mov  edi,eax
134
        add  edi,7
135
        jmp  flr3
136
 
137
      flr2:
138
 
139
        mov  bl,[esi]
140
        mov  [edi],bl
141
 
142
      flr3:
143
 
144
        inc  esi
145
        inc  edi
146
 
147
        mov  ebx,eax
148
        add  ebx,11
149
 
150
        cmp  edi,ebx
151
        jbe  flr1
152
 
153
        pop  ebx edi esi
154
        ret
155
 
156
fileread:
157
;----------------------------------------------------------------
158
;
159
;  fileread - sys floppy
160
;
161
;  eax  points to filename 11 chars
162
;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
163
;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
164
;  edx  mem location to return data
165
;  esi  length of filename 12*X 0=root
166
;
167
;  ret ebx = size or 0xffffffff file not found
168
;      eax = 0 ok read or other = errormsg
169
;
170
;--------------------------------------------------------------
171
        test   ebx,ebx ;if ebx=0 - set to 1
172
        jnz    frfl5
173
        inc    ebx
174
      frfl5:
175
        test   ecx,ecx ;if ecx=0 - set to 1
176
        jnz    frfl6
177
        inc    ecx
178
      frfl6:
179
        test   esi,esi          ; return ramdisk root
180
        jnz    fr_noroot        ;if not root
181
        cmp    ebx,14           ;14 clusters=root dir
182
        ja     oorr
183
        cmp    ecx,14
184
        ja     oorr
185
        jmp    fr_do
186
      oorr:
187
        mov    eax,5            ;out of root range (fnf)
188
        xor    ebx,ebx
189
        dec    ebx              ;0xffffffff
190
        ret
191
 
192
      fr_do:                    ;reading rootdir
193
        mov    edi,edx
194
        dec    ebx
195
        push   edx
196
        mov    edx,ecx
197
        add    edx,ebx
5 halyavin 198
        cmp    edx,15     ;ebx+ecx=14+1
1 ha 199
        pushf
200
        jbe    fr_do1
201
        sub    edx,14
202
        sub    ecx,edx
203
      fr_do1:
204
        shl    ebx,9
205
        mov    esi,0x100000+512*19
206
        add    esi,ebx
207
        shl    ecx,7
208
        cld
209
        rep    movsd
210
        popf
211
        pop    edx
5 halyavin 212
        jae    fr_do2
1 ha 213
        xor    eax,eax ; ok read
214
        xor    ebx,ebx
215
        ret
216
      fr_do2:        ;if last cluster
217
        mov    eax,6  ;end of file
218
        xor    ebx,ebx
219
        ret
220
 
221
     fr_noroot:
222
 
223
        sub    esp,32
224
        call   expand_filename
225
 
226
        dec    ebx
227
 
228
        push   eax
229
 
230
        push   eax ebx ecx edx esi edi
231
        call   rd_findfile
232
        je     fifound
233
        add    esp,32+28   ;if file not found
234
        ret
235
 
236
     fifound:
237
 
238
        mov    ebx,[edi-11+28]          ;file size
239
        mov    [esp+20],ebx
240
        mov    [esp+24],ebx
241
        add    edi,0xf
242
        movzx  eax,word [edi]
243
        mov    edi,eax                  ;edi=cluster
244
 
245
      frnew:
246
 
247
        add    eax,31                   ;bootsector+2*fat+filenames
248
        shl    eax,9                    ;*512
249
        add    eax,0x100000             ;image base
250
        mov    ebx,[esp+8]
251
        mov    ecx,512                  ;[esp+4]
252
 
253
        cmp    [esp+16],dword 0         ; wanted cluster ?
254
        jne    frfl7
255
        call   memmove
256
        add    [esp+8],dword 512
257
        dec    dword [esp+12]           ; last wanted cluster ?
258
        je     frnoread
259
        jmp    frfl8
260
      frfl7:
261
        dec    dword [esp+16]
262
      frfl8:
71 diamond 263
        movzx  eax,word [edi*2+0x280000]	; find next cluster from FAT
1 ha 264
        mov    edi,eax
265
        cmp    edi,4095                 ;eof  - cluster
266
        jz     frnoread2
267
 
268
        cmp    [esp+24],dword 512       ;eof  - size
269
        jb     frnoread
270
        sub    [esp+24],dword 512
271
 
272
        jmp    frnew
273
 
274
      frnoread2:
275
 
276
        cmp    [esp+16],dword 0         ; eof without read ?
277
        je     frnoread
278
 
279
        pop    edi esi edx ecx
280
        add    esp,4
281
        pop    ebx     ; ebx <- eax : size of file
282
        add    esp,36
283
        mov    eax,6   ; end of file
284
        ret
285
 
286
      frnoread:
287
 
288
        pop    edi esi edx ecx
289
        add    esp,4
290
        pop    ebx     ; ebx <- eax : size of file
291
        add    esp,36
292
        xor    eax,eax  ;read ok
293
        ret
294
 
295
filedelete:
296
;--------------------------------------------
297
;
298
; filedelete - sys floppy
299
; in:
300
; eax -  pointer to filename 11 chars
301
;
302
; out:
303
; eax - 0 = successful, 5 = file not found
304
;
305
;--------------------------------------------
306
 
307
        sub    esp,32
308
        call   expand_filename
309
 
310
        push   eax ebx ecx edx esi edi
311
 
312
        call   rd_findfile
313
        je     fifoundd
314
        pop    edi esi edx ecx ebx eax ;file not found
315
        add    esp,32
316
        mov    eax,5
317
        ret
318
 
319
     fifoundd:
320
 
321
        mov    [edi-11],byte 0xE5       ;mark filename deleted
322
        add    edi,0xf
323
        movzx  eax,word [edi]
324
        mov    edi,eax                  ;edi = cluster
325
 
326
      frnewd:
327
 
328
        shl    edi,1                    ;find next cluster from FAT
329
        add    edi,0x280000
330
        movzx  eax,word [edi]
331
        mov    [edi],word 0x0           ;clear fat chain cluster
332
        mov    edi,eax
333
        cmp    edi,dword 0xff8          ;last cluster ?
334
        jb     frnewd
335
 
336
        pop    edi esi edx ecx ebx eax
337
        add    esp,32
338
        xor    eax,eax       ; file found
339
        ret
340
 
341
 
342
 
343
filesave:
344
;----------------------------------------------------------
345
;
346
; filesave - sys floppy
347
;
348
; eax points to filename 11 chars
349
;
350
;        eax      ; pointer to file name
351
;        ebx      ; buffer
352
;        ecx      ; count to write in bytes
353
;        edx      ; 0 create new , 1 append
354
;
355
;-----------------------------------------------------------
356
 
357
        sub  esp,32
358
        call expand_filename
359
        test edx,edx
360
        jnz  fsdel
361
        pusha
362
        call filedelete
363
        popa
364
 
365
      fsdel:
366
 
367
        call   ramdisk_free_space
368
        cmp    ecx,edi
369
        jbe    rd_do_save
370
        add    esp,32
371
        mov    eax,8    ;disk full
372
        ret
373
 
374
      rd_do_save:
375
 
376
        push   eax ebx ecx edx esi edi
377
 
378
        mov    edi,0x100000+512*18+512  ;Point at directory
379
        mov    edx,224 +1
380
        ; find an empty spot for filename in the root dir
381
     l20ds:
382
        dec    edx
383
        jz     frnoreadds
384
     l21ds:
385
        cmp    [edi],byte 0xE5
386
        jz     fifoundds
387
        cmp    [edi],byte 0x0
388
        jz     fifoundds
389
        add    edi,32                   ; Advance to next entry
390
        jmp    l20ds
391
     fifoundds:
392
 
393
        push   edi                      ; move the filename to root dir
394
        mov    esi,[esp+4+20]
395
        mov    ecx,11
396
        cld
397
        rep    movsb
398
        pop    edi
399
        mov    edx,edi
400
        add    edx,11+0xf               ; edx <- cluster save position
401
        mov    ebx,[esp+12]             ; save file size
402
        mov    [edi+28],ebx
403
        mov    [edi+11],byte 0x20       ; attribute
404
; Ivan Poddubny 11/12/2003:
405
call get_date_for_file   ; from FAT32.INC
406
mov [edi+24],ax          ; date
407
call get_time_for_file   ; from FAT32.INC
408
mov [edi+22],ax          ; time
409
; End
410
        mov    edi,0x280000            ;pointer to first cluster
411
        mov    ecx,2849
412
        cld
413
      frnewds:
414
        xor    ax,ax
415
        repne  scasw
416
        mov    ebx,2848
417
        sub    ebx,ecx
418
        mov    [edx],bx                 ; save next cluster pos. to prev cl.
419
        mov    edx,edi                  ; next save pos abs mem add
420
        dec    edx
421
        dec    edx
422
        call   fdc_filesave
423
        pusha                           ; move save to floppy cluster
424
        add    ebx,31
425
        shl    ebx,9
426
        add    ebx,0x100000
427
        mov    eax,[esp+32+16]
428
        mov    ecx,512
429
        call   memmove
430
        popa
431
 
432
        mov    eax,[esp+12]
433
        cmp    eax,512
48 halyavin 434
        jbe    flnsa
1 ha 435
        sub    eax,512
436
        mov    [esp+12],eax
78 diamond 437
        add     dword [esp+16], 512
1 ha 438
        jmp    frnewds
439
 
440
     flnsa:
78 diamond 441
        mov    [edi-2],word 4095          ; mark end of file - last cluster
1 ha 442
 
443
      frnoreadds:
444
 
445
        pop    edi esi edx ecx ebx eax
446
        add    esp,32
447
 
19 mario79 448
;        pusha
449
;        cli
450
;        call   fdc_commitfile
451
;        sti
452
;        popa
1 ha 453
 
454
        xor    eax,eax ;ok write
455
        ret
456
 
457
   rd_findfile:
458
   ;by Mihasik
459
   ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
460
 
461
        mov    edi,0x100000+512*18+512  ;Point at directory
462
        cld
463
    rd_newsearch:
464
        mov    esi,eax
465
        mov    ecx,11
466
        rep    cmpsb
467
        je     rd_ff
468
        add    cl,21
469
        add    edi,ecx
470
        cmp    edi,0x100000+512*33
471
        jb     rd_newsearch
472
        mov    eax,5      ;if file not found - eax=5
473
        xor    ebx,ebx
474
        dec    ebx    ;ebx=0xffffffff and zf=0
475
     rd_ff:
476
        ret
477
 
71 diamond 478
; \begin{diamond}
479
 
480
uni2ansi_str:
481
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
482
; in: esi->source, edi->buffer (may be esi=edi)
483
; destroys: eax,esi,edi
83 diamond 484
        lodsw
485
        test    ax, ax
486
        jz      .done
487
        cmp     ax, 0x80
488
        jb      .ascii
489
        cmp     ax, 0x401
490
        jz      .yo1
491
        cmp     ax, 0x451
492
        jz      .yo2
493
        cmp     ax, 0x410
494
        jb      .unk
495
        cmp     ax, 0x440
496
        jb      .rus1
497
        cmp     ax, 0x450
498
        jb      .rus2
71 diamond 499
.unk:
83 diamond 500
        mov     al, '_'
501
        jmp     .doit
71 diamond 502
.yo1:
83 diamond 503
        mov     al, 'ð'
504
        jmp     .doit
71 diamond 505
.yo2:
83 diamond 506
        mov     al, 'ñ'
507
        jmp     .doit
71 diamond 508
.rus1:
509
; 0x410-0x43F -> 0x80-0xAF
83 diamond 510
        add     al, 0x70
511
        jmp     .doit
71 diamond 512
.rus2:
75 diamond 513
; 0x440-0x44F -> 0xE0-0xEF
83 diamond 514
        add     al, 0xA0
71 diamond 515
.ascii:
516
.doit:
83 diamond 517
        stosb
518
        jmp     uni2ansi_str
71 diamond 519
.done:
83 diamond 520
        mov     byte [edi], 0
521
        ret
71 diamond 522
 
75 diamond 523
ansi2uni_char:
524
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
525
        mov     ah, 0
526
; 0x00-0x7F - trivial map
527
        cmp     al, 0x80
528
        jb      .ret
529
; 0x80-0xAF -> 0x410-0x43F
530
        cmp     al, 0xB0
531
        jae     @f
532
        add     ax, 0x410-0x80
533
.ret:
534
        ret
535
@@:
536
; 0xE0-0xEF -> 0x440-0x44F
537
        cmp     al, 0xE0
538
        jb      .unk
539
        cmp     al, 0xF0
540
        jae     @f
541
        add     ax, 0x440-0xE0
542
        ret
543
; 0xF0 -> 0x401
544
; 0xF1 -> 0x451
545
@@:
546
        cmp     al, 'ð'
547
        jz      .yo1
548
        cmp     al, 'ñ'
549
        jz      .yo2
550
.unk:
551
        mov     al, '_'         ; ah=0
552
        ret
553
.yo1:
554
        mov     ax, 0x401
555
        ret
556
.yo2:
557
        mov     ax, 0x451
558
        ret
559
 
71 diamond 560
char_toupper:
561
; convert character to uppercase, using cp866 encoding
562
; in: al=symbol
563
; out: al=converted symbol
83 diamond 564
        cmp     al, 'a'
565
        jb      .ret
566
        cmp     al, 'z'
567
        jbe     .az
568
        cmp     al, ' '
569
        jb      .ret
570
        cmp     al, 'à'
571
        jb      .rus1
572
        cmp     al, 'ï'
573
        ja      .ret
71 diamond 574
; 0xE0-0xEF -> 0x90-0x9F
83 diamond 575
        sub     al, 'à'-''
71 diamond 576
.ret:
83 diamond 577
        ret
71 diamond 578
.rus1:
579
; 0xA0-0xAF -> 0x80-0x8F
580
.az:
83 diamond 581
        and     al, not 0x20
582
        ret
71 diamond 583
 
584
fat_get_name:
585
; in: edi->FAT entry
586
; out: CF=1 - no valid entry
587
; else CF=0 and ebp->ASCIIZ-name
588
; (maximum length of filename is 255 (wide) symbols without trailing 0,
589
;  but implementation requires buffer 261 words)
590
; destroys eax
83 diamond 591
        cmp     byte [edi], 0
592
        jz      .no
593
        cmp     byte [edi], 0xE5
594
        jnz     @f
71 diamond 595
.no:
83 diamond 596
        stc
597
        ret
71 diamond 598
@@:
83 diamond 599
        cmp     byte [edi+11], 0xF
600
        jz      .longname
601
        push    ecx
602
        mov     ecx, 8
603
        push    edi ebp ecx
78 diamond 604
        test    byte [ebp-4], 1
75 diamond 605
        jnz     .unicode_short
71 diamond 606
@@:
83 diamond 607
        mov     al, [edi]
608
        inc     edi
609
        mov     [ebp], al
610
        inc     ebp
611
        loop    @b
612
        pop     ecx
71 diamond 613
@@:
83 diamond 614
        cmp     byte [ebp-1], ' '
615
        jnz     @f
616
        dec     ebp
617
        loop    @b
71 diamond 618
@@:
83 diamond 619
        mov     byte [ebp], '.'
620
        inc     ebp
621
        mov     ecx, 3
622
        push    ecx
71 diamond 623
@@:
83 diamond 624
        mov     al, [edi]
625
        inc     edi
626
        mov     [ebp], al
627
        inc     ebp
628
        loop    @b
629
        pop     ecx
71 diamond 630
@@:
83 diamond 631
        cmp     byte [ebp-1], ' '
632
        jnz     @f
633
        dec     ebp
634
        loop    @b
635
        dec     ebp
71 diamond 636
@@:
83 diamond 637
        and     byte [ebp], 0	; CF=0
638
        pop     ebp edi ecx
639
        ret
75 diamond 640
.unicode_short:
641
@@:
642
        mov     al, [edi]
643
        inc     edi
644
        call    ansi2uni_char
645
        mov     [ebp], ax
646
        inc     ebp
647
        inc     ebp
648
        loop    @b
649
        pop     ecx
650
@@:
83 diamond 651
        cmp     word [ebp-2], ' '
652
        jnz     @f
653
        dec     ebp
654
        dec     ebp
655
        loop    @b
75 diamond 656
@@:
83 diamond 657
        mov     word [ebp], '.'
658
        inc     ebp
659
        inc     ebp
660
        mov     ecx, 3
661
        push    ecx
75 diamond 662
@@:
83 diamond 663
        mov     al, [edi]
664
        inc     edi
665
        call    ansi2uni_char
666
        mov     [ebp], ax
75 diamond 667
        inc     ebp
668
        inc     ebp
669
        loop    @b
670
        pop     ecx
671
@@:
83 diamond 672
        cmp     word [ebp-2], ' '
673
        jnz     @f
674
        dec     ebp
675
        dec     ebp
676
        loop    @b
677
        dec     ebp
678
        dec     ebp
75 diamond 679
@@:
83 diamond 680
        and     word [ebp], 0	; CF=0
681
        pop     ebp edi ecx
682
        ret
71 diamond 683
.longname:
684
; LFN
83 diamond 685
        mov     al, byte [edi]
686
        and     eax, 0x3F
687
        dec     eax
688
        cmp     al, 20
689
        jae     .no     ; ignore invalid entries
690
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
691
        imul    eax, 13*2
692
        add     ebp, eax
693
        test    byte [edi], 0x40
694
        jz      @f
695
        mov     word [ebp+13*2], 0
71 diamond 696
@@:
83 diamond 697
        push    eax
71 diamond 698
; now copy name from edi to ebp ...
83 diamond 699
        mov     eax, [edi+1]
700
        mov     [ebp], eax      ; symbols 1,2
701
        mov     eax, [edi+5]
702
        mov     [ebp+4], eax	; 3,4
703
        mov     eax, [edi+9]
704
        mov     [ebp+8], ax	; 5
705
        mov     eax, [edi+14]
706
        mov     [ebp+10], eax	; 6,7
707
        mov     eax, [edi+18]
708
        mov     [ebp+14], eax	; 8,9
709
        mov     eax, [edi+22]
710
        mov     [ebp+18], eax	; 10,11
711
        mov     eax, [edi+28]
712
        mov     [ebp+22], eax	; 12,13
71 diamond 713
; ... done
83 diamond 714
        pop     eax
715
        sub     ebp, eax
716
        test    eax, eax
717
        jz      @f
71 diamond 718
; if this is not first entry, more processing required
83 diamond 719
        stc
720
        ret
71 diamond 721
@@:
722
; if this is first entry:
78 diamond 723
        test    byte [ebp-4], 1
75 diamond 724
        jnz     .ret
71 diamond 725
; buffer at ebp contains UNICODE name, convert it to ANSI
83 diamond 726
        push    esi edi
727
        mov     esi, ebp
728
        mov     edi, ebp
729
        call    uni2ansi_str
730
        pop     edi esi
75 diamond 731
.ret:
83 diamond 732
        clc
733
        ret
71 diamond 734
 
735
fat_compare_name:
736
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
737
; in: esi->name, ebp->name
738
; out: if names match: ZF=1 and esi->next component of name
739
;      else: ZF=0, esi is not changed
740
; destroys eax
83 diamond 741
        push    ebp esi
71 diamond 742
.loop:
83 diamond 743
        mov     al, [ebp]
744
        inc     ebp
745
        call    char_toupper
746
        push    eax
747
        lodsb
748
        call    char_toupper
749
        cmp     al, [esp]
750
        jnz     .done
751
        pop     eax
752
        test    al, al
753
        jnz     .loop
754
        dec     esi
755
        pop     eax
756
        pop     ebp
757
        xor     eax, eax	; set ZF flag
758
        ret
71 diamond 759
.done:
83 diamond 760
        cmp     al, '/'
761
        jnz     @f
762
        cmp     byte [esp], 0
763
        jnz     @f
764
        mov     [esp+4], esi
71 diamond 765
@@:
83 diamond 766
        pop     eax
767
        pop     esi ebp
768
        ret
71 diamond 769
 
75 diamond 770
fat_time_to_bdfe:
771
; in: eax=FAT time
772
; out: eax=BDFE time
83 diamond 773
        push    ecx edx
774
        mov     ecx, eax
775
        mov     edx, eax
776
        shr     eax, 11
777
        shl     eax, 16	; hours
778
        and     edx, 0x1F
779
        add     edx, edx
780
        mov     al, dl	; seconds
781
        shr     ecx, 5
782
        and     ecx, 0x3F
783
        mov     ah, cl	; minutes
784
        pop     edx ecx
785
        ret
75 diamond 786
 
787
fat_date_to_bdfe:
83 diamond 788
        push    ecx edx
789
        mov     ecx, eax
790
        mov     edx, eax
791
        shr     eax, 9
792
        add     ax, 1980
793
        shl     eax, 16	; year
794
        and     edx, 0x1F
795
        mov     al, dl	; day
796
        shr     ecx, 5
797
        and     ecx, 0xF
798
        mov     ah, cl	; month
799
        pop     edx ecx
800
        ret
75 diamond 801
 
86 diamond 802
bdfe_to_fat_time:
803
        push    edx
804
        mov     edx, eax
805
        shr     eax, 16
806
        and     dh, 0x3F
807
        shl     eax, 6
808
        or      al, dh
809
        shr     dl, 1
810
        and     dl, 0x1F
811
        shl     eax, 5
812
        or      al, dl
813
        pop     edx
814
        ret
815
 
816
bdfe_to_fat_date:
817
        push    edx
818
        mov     edx, eax
819
        shr     eax, 16
820
        sub     ax, 1980
821
        and     dh, 0xF
822
        shl     eax, 4
823
        or      al, dh
824
        and     dl, 0x1F
825
        shl     eax, 5
826
        or      al, dl
827
        pop     edx
828
        ret
829
 
75 diamond 830
fat_entry_to_bdfe:
831
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
832
; destroys eax
86 diamond 833
        mov     eax, [ebp-4]
834
        mov     [esi+4], eax	; ASCII/UNICODE name
835
fat_entry_to_bdfe2:
75 diamond 836
        movzx   eax, byte [edi+11]
837
        mov     [esi], eax	; attributes
838
        movzx   eax, word [edi+14]
839
        call    fat_time_to_bdfe
840
        mov     [esi+8], eax	; creation time
841
        movzx   eax, word [edi+16]
842
        call    fat_date_to_bdfe
843
        mov     [esi+12], eax	; creation date
844
        and     dword [esi+16], 0	; last access time is not supported on FAT
845
        movzx   eax, word [edi+18]
846
        call    fat_date_to_bdfe
847
        mov     [esi+20], eax	; last access date
848
        movzx   eax, word [edi+22]
849
        call    fat_time_to_bdfe
850
        mov     [esi+24], eax	; last write time
851
        movzx   eax, word [edi+24]
852
        call    fat_date_to_bdfe
853
        mov     [esi+28], eax	; last write date
854
        mov     eax, [edi+28]
855
        mov     [esi+32], eax	; file size (low dword)
856
        xor     eax, eax
857
        mov     [esi+36], eax	; file size (high dword)
86 diamond 858
        test    ebp, ebp
859
        jz      .ret
75 diamond 860
        push    ecx edi
861
        lea     edi, [esi+40]
862
        mov     esi, ebp
78 diamond 863
        test    byte [esi-4], 1
864
        jz      .ansi
865
        mov     ecx, 260/2
75 diamond 866
        rep     movsd
78 diamond 867
        mov     [edi-2], ax
868
@@:
75 diamond 869
        mov     esi, edi
870
        pop     edi ecx
86 diamond 871
.ret:
75 diamond 872
        ret
78 diamond 873
.ansi:
874
        mov     ecx, 264/4
875
        rep     movsd
876
        mov     [edi-1], al
877
        jmp     @b
75 diamond 878
 
86 diamond 879
bdfe_to_fat_entry:
880
; convert BDFE at edx to FAT entry at edi
881
; destroys eax
882
; attributes byte
883
        test    byte [edi+11], 8        ; volume label?
884
        jnz     @f
885
        mov     al, [edx]
886
        and     al, 0x27
887
        and     byte [edi+11], 0x10
888
        or      byte [edi+11], al
889
@@:
890
        mov     eax, [edx+8]
891
        call    bdfe_to_fat_time
892
        mov     [edi+14], ax            ; creation time
893
        mov     eax, [edx+12]
894
        call    bdfe_to_fat_date
895
        mov     [edi+16], ax            ; creation date
896
        mov     eax, [edx+20]
897
        call    bdfe_to_fat_date
898
        mov     [edi+18], ax            ; last access date
899
        mov     eax, [edx+24]
900
        call    bdfe_to_fat_time
901
        mov     [edi+22], ax            ; last write time
902
        mov     eax, [edx+28]
903
        call    bdfe_to_fat_date
904
        mov     [edi+24], ax            ; last write date
905
        ret
906
 
907
ramdisk_root_first:
908
        mov     edi, 0x100000+512*19
909
        clc
910
        ret
911
ramdisk_root_next:
912
        add     edi, 0x20
913
        cmp     edi, 0x100000+512*33
914
        cmc
915
        ret
916
 
91 diamond 917
ramdisk_root_extend_dir:
918
        stc
919
        ret
920
 
171 diamond 921
uglobal
922
; this is for delete support
923
rd_prev_sector          dd      ?
924
rd_prev_prev_sector     dd      ?
925
endg
926
 
91 diamond 927
ramdisk_notroot_next:
928
        add     edi, 0x20
929
        test    edi, 0x1FF
930
        jz      ramdisk_notroot_next_sector
931
        ret     ; CF=0
932
ramdisk_notroot_next_sector:
933
        push    ecx
934
        mov     ecx, [eax]
171 diamond 935
        push    [rd_prev_sector]
936
        pop     [rd_prev_prev_sector]
937
        mov     [rd_prev_sector], ecx
91 diamond 938
        mov     ecx, [ecx*2+0x280000]
939
        and     ecx, 0xFFF
940
        cmp     ecx, 2849
941
        jae     ramdisk_notroot_first.err2
942
        mov     [eax], ecx
943
        pop     ecx
944
ramdisk_notroot_first:
945
        mov     eax, [eax]
946
        cmp     eax, 2
947
        jb      .err
948
        cmp     eax, 2849
949
        jae     .err
950
        shl     eax, 9
951
        lea     edi, [eax+(31 shl 9)+0x100000]
952
        clc
953
        ret
954
.err2:
955
        pop     ecx
956
.err:
957
        stc
958
        ret
959
ramdisk_notroot_next_write:
960
        test    edi, 0x1FF
961
        jz      ramdisk_notroot_next_sector
962
ramdisk_root_next_write:
963
        ret
964
 
965
ramdisk_notroot_extend_dir:
966
        pusha
967
        xor     eax, eax
968
        mov     edi, 0x280000
969
        mov     ecx, 2849
970
        repnz   scasw
971
        jnz     .notfound
972
        mov     word [edi-2], 0xFFF
973
        sub     edi, 0x280000
974
        shr     edi, 1
975
        dec     edi
976
        mov     eax, [esp+28]
977
        mov     ecx, [eax]
978
        mov     [0x280000+ecx*2], di
979
        mov     [eax], edi
980
        shl     edi, 9
981
        add     edi, (31 shl 9)+0x100000
982
        mov     [esp], edi
983
        xor     eax, eax
984
        mov     ecx, 128
985
        rep     stosd
986
        popa
987
        clc
988
        ret
989
.notfound:
990
        popa
991
        stc
992
        ret
993
 
71 diamond 994
rd_find_lfn:
995
; in: esi->name
996
; out: CF=1 - file not found
997
;      else CF=0 and edi->direntry
86 diamond 998
        push    esi edi
91 diamond 999
        push    0
86 diamond 1000
        push    ramdisk_root_first
1001
        push    ramdisk_root_next
91 diamond 1002
.loop:
86 diamond 1003
        call    fat_find_lfn
1004
        jc      .notfound
1005
        cmp     byte [esi], 0
91 diamond 1006
        jz      .found
1007
        test    byte [edi+11], 10h
1008
        jz      .notfound
1009
        movzx   eax, word [edi+26]
1010
        mov     [esp+8], eax
1011
        mov     dword [esp+4], ramdisk_notroot_first
1012
        mov     dword [esp], ramdisk_notroot_next
1013
        jmp     .loop
1014
.notfound:
86 diamond 1015
        add     esp, 12
1016
        pop     edi esi
78 diamond 1017
        stc
1018
        ret
91 diamond 1019
.found:
1020
        mov     eax, [esp+8]
1021
        add     esp, 16         ; CF=0
1022
        pop     esi
1023
        ret
71 diamond 1024
 
1025
;----------------------------------------------------------------
1026
;
1027
;  fs_RamdiskRead - LFN variant for reading sys floppy
1028
;
1029
;  esi  points to filename
1030
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1031
;       may be ebx=0 - start from first byte
1032
;  ecx  number of bytes to read, 0+
1033
;  edx  mem location to return data
1034
;
77 diamond 1035
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 1036
;      eax = 0 ok read or other = errormsg
1037
;
1038
;--------------------------------------------------------------
1039
fs_RamdiskRead:
75 diamond 1040
        cmp     byte [esi], 0
1041
        jnz     @f
1042
        or      ebx, -1
1043
        mov     eax, 10         ; access denied
1044
        ret
71 diamond 1045
@@:
75 diamond 1046
        push    edi
1047
        call    rd_find_lfn
1048
        jnc     .found
1049
        pop     edi
1050
        or      ebx, -1
1051
        mov     eax, 5          ; file not found
1052
        ret
71 diamond 1053
.found:
75 diamond 1054
        test    ebx, ebx
1055
        jz      .l1
1056
        cmp     dword [ebx+4], 0
1057
        jz      @f
77 diamond 1058
        xor     ebx, ebx
71 diamond 1059
.reteof:
75 diamond 1060
        mov     eax, 6          ; EOF
1061
        pop     edi
1062
        ret
71 diamond 1063
@@:
75 diamond 1064
        mov     ebx, [ebx]
71 diamond 1065
.l1:
77 diamond 1066
        push    ecx edx
1067
        push    0
1068
        mov     eax, [edi+28]
1069
        sub     eax, ebx
1070
        jb      .eof
1071
        cmp     eax, ecx
1072
        jae     @f
1073
        mov     ecx, eax
1074
        mov     byte [esp], 6           ; EOF
1075
@@:
75 diamond 1076
        movzx   edi, word [edi+26]	; cluster
71 diamond 1077
.new:
75 diamond 1078
        jecxz   .done
1079
        test    edi, edi
1080
        jz      .eof
1081
        cmp     edi, 0xFF8
1082
        jae     .eof
1083
        lea     eax, [edi+31]           ; bootsector+2*fat+filenames
1084
        shl     eax, 9                  ; *512
1085
        add     eax, 0x100000           ; image base
71 diamond 1086
; now eax points to data of cluster
75 diamond 1087
        sub     ebx, 512
1088
        jae     .skip
1089
        lea     eax, [eax+ebx+512]
1090
        neg     ebx
1091
        push    ecx
1092
        cmp     ecx, ebx
1093
        jbe     @f
1094
        mov     ecx, ebx
71 diamond 1095
@@:
75 diamond 1096
        mov     ebx, edx
1097
        call    memmove
1098
        add     edx, ecx
1099
        sub     [esp], ecx
1100
        pop     ecx
1101
        xor     ebx, ebx
71 diamond 1102
.skip:
75 diamond 1103
        movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
1104
        jmp     .new
71 diamond 1105
.eof:
77 diamond 1106
        mov     ebx, edx
1107
        pop     eax edx ecx
1108
        sub     ebx, edx
75 diamond 1109
        jmp     .reteof
71 diamond 1110
.done:
77 diamond 1111
        mov     ebx, edx
1112
        pop     eax edx ecx edi
1113
        sub     ebx, edx
75 diamond 1114
        ret
71 diamond 1115
 
75 diamond 1116
;----------------------------------------------------------------
1117
;
1118
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
1119
;
1120
;  esi  points to filename; only root is folder on ramdisk
78 diamond 1121
;  ebx  pointer to structure 32-bit number = first wanted block
1122
;                          & flags (bitfields)
1123
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1124
;  ecx  number of blocks to read, 0+
1125
;  edx  mem location to return data
1126
;
1127
;  ret ebx = size or 0xffffffff file not found
1128
;      eax = 0 ok read or other = errormsg
1129
;
1130
;--------------------------------------------------------------
1131
fs_RamdiskReadFolder:
91 diamond 1132
        push    edi
75 diamond 1133
        cmp     byte [esi], 0
91 diamond 1134
        jz      .root
1135
        call    rd_find_lfn
1136
        jnc     .found
1137
        pop     edi
75 diamond 1138
        or      ebx, -1
91 diamond 1139
        mov     eax, ERROR_FILE_NOT_FOUND
75 diamond 1140
        ret
91 diamond 1141
.found:
1142
        test    byte [edi+11], 0x10
1143
        jnz     .found_dir
1144
        pop     edi
1145
        or      ebx, -1
1146
        mov     eax, ERROR_ACCESS_DENIED
1147
        ret
1148
.found_dir:
1149
        movzx   eax, word [edi+26]
1150
        add     eax, 31
1151
        push    0
1152
        jmp     .doit
1153
.root:
1154
        mov     eax, 19
1155
        push    14
1156
.doit:
1157
        push    esi ecx ebp
1158
        sub     esp, 262*2      ; reserve space for LFN
1159
        mov     ebp, esp
1160
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE names
1161
        mov     ebx, [ebx]
75 diamond 1162
; init header
91 diamond 1163
        push    eax ecx
75 diamond 1164
        mov     edi, edx
1165
        mov     ecx, 32/4
1166
        xor     eax, eax
1167
        rep     stosd
1168
        mov     byte [edx], 1   ; version
91 diamond 1169
        pop     ecx eax
75 diamond 1170
        mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
91 diamond 1171
.main_loop:
1172
        mov     edi, eax
1173
        shl     edi, 9
1174
        add     edi, 0x100000
1175
        push    eax
75 diamond 1176
.l1:
1177
        call    fat_get_name
1178
        jc      .l2
1179
        cmp     byte [edi+11], 0xF
91 diamond 1180
        jnz     .do_bdfe
75 diamond 1181
        add     edi, 0x20
91 diamond 1182
        test    edi, 0x1FF
1183
        jnz     .do_bdfe
1184
        pop     eax
1185
        inc     eax
1186
        dec     byte [esp+262*2+16]
1187
        jz      .done
1188
        jns     @f
1189
; read next sector from FAT
1190
        mov     eax, [(eax-31-1)*2+0x280000]
1191
        and     eax, 0xFFF
1192
        cmp     eax, 0xFF8
1193
        jae     .done
1194
        add     eax, 31
1195
        mov     byte [esp+262*2+16], 0
75 diamond 1196
@@:
91 diamond 1197
        mov     edi, eax
1198
        shl     edi, 9
1199
        add     edi, 0x100000
1200
        push    eax
1201
.do_bdfe:
75 diamond 1202
        inc     dword [edx+8]   ; new file found
1203
        dec     ebx
1204
        jns     .l2
1205
        dec     ecx
1206
        js      .l2
1207
        inc     dword [edx+4]  ; new file block copied
1208
        call    fat_entry_to_bdfe
1209
.l2:
1210
        add     edi, 0x20
91 diamond 1211
        test    edi, 0x1FF
1212
        jnz     .l1
1213
        pop     eax
1214
        inc     eax
1215
        dec     byte [esp+262*2+16]
1216
        jz      .done
1217
        jns     @f
1218
; read next sector from FAT
1219
        mov     eax, [(eax-31-1)*2+0x280000]
1220
        and     eax, 0xFFF
1221
        cmp     eax, 0xFF8
1222
        jae     .done
1223
        add     eax, 31
1224
        mov     byte [esp+262*2+16], 0
1225
@@:
1226
        jmp     .main_loop
1227
.done:
75 diamond 1228
        add     esp, 262*2+4
1229
        pop     ebp
77 diamond 1230
        mov     ebx, [edx+4]
75 diamond 1231
        xor     eax, eax
1232
        dec     ecx
1233
        js      @f
1234
        mov     al, ERROR_END_OF_FILE
1235
@@:
91 diamond 1236
        pop     ecx esi edi edi
75 diamond 1237
        ret
1238
 
83 diamond 1239
iglobal
1240
label fat_legal_chars byte
1241
; 0 = not allowed
1242
; 1 = allowed only in long names
1243
; 3 = allowed
1244
        times 32 db 0
1245
;                 ! " # $ % & ' ( ) * + , - . /
1246
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
1247
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1248
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
1249
;               @ A B C D E F G H I J K L M N O
1250
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1251
;               P Q R S T U V W X Y Z [ \ ] ^ _
1252
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
1253
;               ` a b c d e f g h i j k l m n o
1254
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1255
;               p q r s t u v w x y z { | } ~
1256
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
1257
endg
1258
 
1259
fat_name_is_legal:
1260
; in: esi->(long) name
1261
; out: CF set <=> legal
1262
; destroys eax
1263
        push    esi
1264
        xor     eax, eax
1265
@@:
1266
        lodsb
1267
        test    al, al
1268
        jz      .done
1269
        cmp     al, 80h
1270
        jae     .big
1271
        test    [fat_legal_chars+eax], 1
1272
        jnz     @b
1273
.err:
1274
        pop     esi
1275
        clc
1276
        ret
1277
.big:
1278
; 0x80-0xAF, 0xE0-0xEF
1279
        cmp     al, 0xB0
1280
        jb      @b
1281
        cmp     al, 0xE0
1282
        jb      .err
1283
        cmp     al, 0xF0
1284
        jb      @b
1285
        jmp     .err
1286
.done:
1287
        sub     esi, [esp]
1288
        cmp     esi, 257
1289
        pop     esi
1290
        ret
1291
 
1292
fat_next_short_name:
1293
; in: edi->8+3 name
1294
; out: name corrected
1295
;      CF=1 <=> error
1296
        pushad
1297
        mov     ecx, 8
1298
        mov     al, '~'
1299
        std
1300
        push    edi
1301
        add     edi, 7
1302
        repnz   scasb
1303
        pop     edi
1304
        cld
1305
        jz      .tilde
1306
; tilde is not found, insert "~1" at end
1307
        add     edi, 6
1308
        cmp     word [edi], '  '
1309
        jnz     .insert_tilde
1310
@@:     dec     edi
1311
        cmp     byte [edi], ' '
1312
        jz      @b
1313
        inc     edi
1314
.insert_tilde:
1315
        mov     word [edi], '~1'
1316
        popad
1317
;       clc     ; CF already cleared
1318
        ret
1319
.tilde:
1320
        push    edi
1321
        add     edi, 7
1322
        xor     ecx, ecx
1323
@@:
1324
; after tilde may be only digits and trailing spaces
1325
        cmp     byte [edi], '~'
1326
        jz      .break
1327
        cmp     byte [edi], ' '
1328
        jz      .space
1329
        cmp     byte [edi], '9'
1330
        jnz     .found
1331
        dec     edi
1332
        jmp     @b
1333
.space:
1334
        dec     edi
1335
        inc     ecx
1336
        jmp     @b
1337
.found:
1338
        inc     byte [edi]
1339
.succ:
1340
        pop     edi
1341
        popad
1342
        clc
1343
        ret
1344
.break:
1345
        jecxz   .noplace
1346
        inc     edi
1347
        mov     al, '1'
1348
@@:
1349
        xchg    al, [edi]
1350
        inc     edi
1351
        cmp     al, ' '
1352
        mov     al, '0'
1353
        jnz     @b
1354
        jmp     .succ
1355
.noplace:
1356
        dec     edi
1357
        cmp     edi, [esp]
1358
        jz      .err
1359
        add     dword [esp], 8
1360
        mov     word [edi], '~1'
1361
        inc     edi
1362
        inc     edi
1363
@@:
1364
        mov     byte [edi], '0'
1365
        inc     edi
1366
        cmp     edi, [esp]
1367
        jb      @b
1368
        pop     edi
1369
        popad
1370
        ;clc    ; automatically
1371
        ret
1372
.err:
1373
        pop     edi
1374
        popad
1375
        stc
1376
        ret
1377
 
1378
fat_gen_short_name:
1379
; in: esi->long name
1380
;     edi->buffer (8+3=11 chars)
1381
; out: buffer filled
1382
        pushad
1383
        mov     eax, '    '
1384
        push    edi
1385
        stosd
1386
        stosd
1387
        stosd
1388
        pop     edi
1389
        xor     eax, eax
1390
        push    8
1391
        pop     ebx
1392
        lea     ecx, [edi+8]
1393
.loop:
1394
        lodsb
1395
        test    al, al
1396
        jz      .done
1397
        call    char_toupper
1398
        cmp     al, ' '
1399
        jz      .space
1400
        cmp     al, 80h
1401
        ja      .big
1402
        test    [fat_legal_chars+eax], 2
1403
        jnz     .symbol
1404
.inv_symbol:
1405
        mov     al, '_'
1406
        or      bh, 1
1407
.symbol:
1408
        cmp     al, '.'
1409
        jz      .dot
1410
.normal_symbol:
1411
        dec     bl
1412
        jns     .store
1413
        mov     bl, 0
1414
.space:
1415
        or      bh, 1
1416
        jmp     .loop
1417
.store:
1418
        stosb
1419
        jmp     .loop
1420
.big:
1421
        cmp     al, 0xB0
1422
        jb      .normal_symbol
1423
        cmp     al, 0xE0
1424
        jb      .inv_symbol
1425
        cmp     al, 0xF0
1426
        jb      .normal_symbol
1427
        jmp     .inv_symbol
1428
.dot:
1429
        test    bh, 2
1430
        jz      .firstdot
1431
        pop     ebx
1432
        add     ebx, edi
1433
        sub     ebx, ecx
1434
        push    ebx
1435
        cmp     edi, ecx
1436
        jbe     .skip
1437
@@:
1438
        dec     edi
1439
        mov     al, ' '
1440
        xchg    al, [edi]
1441
        dec     ebx
1442
        mov     [ebx], al
1443
        cmp     edi, ecx
1444
        ja      @b
1445
.skip:
1446
        mov     bh, 3
1447
        jmp     @f
1448
.firstdot:
1449
        cmp     bl, 8
1450
        jz      .space
1451
        push    edi
1452
        or      bh, 2
1453
@@:
1454
        mov     edi, ecx
1455
        mov     bl, 3
1456
        jmp     .loop
1457
.done:
1458
        test    bh, 2
1459
        jz      @f
1460
        pop     edi
1461
@@:
1462
        lea     edi, [ecx-8]
1463
        test    bh, 1
1464
        jz      @f
1465
        call    fat_next_short_name
1466
@@:
1467
        popad
1468
        ret
1469
 
1470
;----------------------------------------------------------------
1471
;
1472
;  fs_RamdiskRewrite - LFN variant for writing sys floppy
1473
;
1474
;  esi  points to filename
1475
;  ebx  ignored (reserved)
1476
;  ecx  number of bytes to write, 0+
1477
;  edx  mem location to data
1478
;
1479
;  ret ebx = number of written bytes
1480
;      eax = 0 ok read or other = errormsg
1481
;
1482
;--------------------------------------------------------------
1483
@@:
1484
        mov     eax, ERROR_ACCESS_DENIED
1485
        xor     ebx, ebx
1486
        ret
1487
 
1488
fs_RamdiskRewrite:
1489
        cmp     byte [esi], 0
1490
        jz      @b
91 diamond 1491
        pushad
1492
        xor     ebp, ebp
83 diamond 1493
        push    esi
1494
@@:
1495
        lodsb
1496
        test    al, al
1497
        jz      @f
1498
        cmp     al, '/'
1499
        jnz     @b
91 diamond 1500
        lea     ebp, [esi-1]
1501
        jmp     @b
1502
@@:
83 diamond 1503
        pop     esi
91 diamond 1504
        test    ebp, ebp
1505
        jnz     .noroot
1506
        push    ramdisk_root_extend_dir
1507
        push    ramdisk_root_next_write
1508
        push    ebp
1509
        push    ramdisk_root_first
1510
        push    ramdisk_root_next
1511
        jmp     .common1
1512
.noroot:
1513
; check existence
1514
        mov     byte [ebp], 0
1515
        call    rd_find_lfn
1516
        mov     byte [ebp], '/'
1517
        lea     esi, [ebp+1]
1518
        jnc     @f
1519
        mov     eax, ERROR_FILE_NOT_FOUND
1520
.ret1:
1521
        mov     [esp+28], eax
1522
        popad
83 diamond 1523
        xor     ebx, ebx
1524
        ret
1525
@@:
91 diamond 1526
        test    byte [edi+11], 0x10     ; must be directory
1527
        mov     eax, ERROR_ACCESS_DENIED
1528
        jz      .ret1
1529
        movzx   ebp, word [edi+26]      ; ebp=cluster
1530
        mov     eax, ERROR_FAT_TABLE
1531
        cmp     ebp, 2
1532
        jb      .ret1
1533
        cmp     ebp, 2849
1534
        jae     .ret1
1535
        push    ramdisk_notroot_extend_dir
1536
        push    ramdisk_notroot_next_write
1537
        push    ebp
1538
        push    ramdisk_notroot_first
1539
        push    ramdisk_notroot_next
1540
.common1:
1541
        call    fat_find_lfn
83 diamond 1542
        jc      .notfound
91 diamond 1543
; found; must not be directory
1544
        test    byte [edi+11], 10h
1545
        jz      @f
1546
        add     esp, 20
1547
        popad
1548
        mov     eax, ERROR_ACCESS_DENIED
1549
        xor     ebx, ebx
1550
        ret
1551
@@:
1552
; delete FAT chain
83 diamond 1553
        push    edi
1554
        xor     eax, eax
1555
        mov     dword [edi+28], eax     ; zero size
1556
        xchg    ax, word [edi+26]       ; start cluster
1557
        test    eax, eax
1558
        jz      .done1
1559
@@:
1560
        cmp     eax, 0xFF8
1561
        jae     .done1
1562
        lea     edi, [0x280000 + eax*2] ; position in FAT
1563
        xor     eax, eax
1564
        xchg    ax, [edi]
1565
        jmp     @b
1566
.done1:
1567
        pop     edi
1568
        call    get_time_for_file
1569
        mov     [edi+22], ax
1570
        call    get_date_for_file
1571
        mov     [edi+24], ax
1572
        mov     [edi+18], ax
1573
        or      byte [edi+11], 20h      ; set 'archive' attribute
1574
        jmp     .doit
1575
.notfound:
1576
; file is not found; generate short name
1577
        call    fat_name_is_legal
1578
        jc      @f
91 diamond 1579
        add     esp, 20
1580
        popad
1581
        mov     eax, ERROR_FILE_NOT_FOUND
1582
        xor     ebx, ebx
1583
        ret
83 diamond 1584
@@:
1585
        sub     esp, 12
1586
        mov     edi, esp
1587
        call    fat_gen_short_name
1588
.test_short_name_loop:
91 diamond 1589
        push    esi edi ecx
1590
        mov     esi, edi
1591
        lea     eax, [esp+12+12+8]
1592
        mov     [eax], ebp
1593
        call    dword [eax-4]
1594
        jc      .found
83 diamond 1595
.test_short_name_entry:
91 diamond 1596
        cmp     byte [edi+11], 0xF
83 diamond 1597
        jz      .test_short_name_cont
1598
        mov     ecx, 11
1599
        push    esi edi
1600
        repz    cmpsb
1601
        pop     edi esi
1602
        jz      .short_name_found
1603
.test_short_name_cont:
91 diamond 1604
        lea     eax, [esp+12+12+8]
1605
        call    dword [eax-8]
1606
        jnc     .test_short_name_entry
83 diamond 1607
        jmp     .found
1608
.short_name_found:
91 diamond 1609
        pop     ecx edi esi
83 diamond 1610
        call    fat_next_short_name
1611
        jnc     .test_short_name_loop
1612
.disk_full:
91 diamond 1613
        add     esp, 12+20
1614
        popad
83 diamond 1615
        mov     eax, ERROR_DISK_FULL
1616
        xor     ebx, ebx
1617
        ret
1618
.found:
91 diamond 1619
        pop     ecx edi esi
83 diamond 1620
; now find space in directory
1621
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1622
        mov     al, '~'
1623
        push    ecx edi
1624
        mov     ecx, 8
1625
        repnz   scasb
1626
        push    1
1627
        pop     eax     ; 1 entry
1628
        jnz     .notilde
1629
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1630
        xor     eax, eax
1631
@@:
1632
        cmp     byte [esi], 0
1633
        jz      @f
1634
        inc     esi
1635
        inc     eax
1636
        jmp     @b
1637
@@:
1638
        sub     esi, eax
1639
        add     eax, 12+13
1640
        mov     ecx, 13
1641
        push    edx
1642
        cdq
1643
        div     ecx
1644
        pop     edx
1645
.notilde:
91 diamond 1646
        push    -1
1647
        push    -1
83 diamond 1648
; find  successive entries in directory
1649
        xor     ecx, ecx
91 diamond 1650
        push    eax
1651
        lea     eax, [esp+12+8+12+8]
1652
        mov     [eax], ebp
1653
        call    dword [eax-4]
1654
        pop     eax
83 diamond 1655
.scan_dir:
1656
        cmp     byte [edi], 0
1657
        jz      .free
1658
        cmp     byte [edi], 0xE5
1659
        jz      .free
1660
        xor     ecx, ecx
1661
.scan_cont:
91 diamond 1662
        push    eax
1663
        lea     eax, [esp+12+8+12+8]
1664
        call    dword [eax-8]
1665
        pop     eax
1666
        jnc     .scan_dir
1667
        push    eax
1668
        lea     eax, [esp+12+8+12+8]
1669
        call    dword [eax+8]           ; extend directory
1670
        pop     eax
1671
        jnc     .scan_dir
1672
        add     esp, 8+8+12+20
1673
        popad
1674
        mov     eax, ERROR_DISK_FULL
1675
        xor     ebx, ebx
1676
        ret
83 diamond 1677
.free:
91 diamond 1678
        test    ecx, ecx
1679
        jnz     @f
1680
        mov     [esp], edi
1681
        mov     ecx, [esp+8+8+12+8]
1682
        mov     [esp+4], ecx
1683
        xor     ecx, ecx
1684
@@:
83 diamond 1685
        inc     ecx
1686
        cmp     ecx, eax
1687
        jb      .scan_cont
1688
; found!
1689
; calculate name checksum
1690
        push    esi ecx
91 diamond 1691
        mov     esi, [esp+8+8]
83 diamond 1692
        mov     ecx, 11
1693
        xor     eax, eax
1694
@@:
1695
        ror     al, 1
1696
        add     al, [esi]
1697
        inc     esi
1698
        loop    @b
1699
        pop     ecx esi
91 diamond 1700
        pop     edi
1701
        pop     dword [esp+8+12+8]
83 diamond 1702
; edi points to last entry in free chunk
1703
        dec     ecx
1704
        jz      .nolfn
1705
        push    esi
91 diamond 1706
        push    eax
1707
        mov     al, 40h
83 diamond 1708
.writelfn:
91 diamond 1709
        or      al, cl
1710
        mov     esi, [esp+4]
1711
        push    ecx
1712
        dec     ecx
1713
        imul    ecx, 13
1714
        add     esi, ecx
83 diamond 1715
        stosb
1716
        mov     cl, 5
1717
        call    .read_symbols
1718
        mov     ax, 0xF
1719
        stosw
91 diamond 1720
        mov     al, [esp+4]
83 diamond 1721
        stosb
1722
        mov     cl, 6
1723
        call    .read_symbols
1724
        xor     eax, eax
1725
        stosw
1726
        mov     cl, 2
1727
        call    .read_symbols
91 diamond 1728
        pop     ecx
1729
        lea     eax, [esp+8+8+12+8]
1730
        call    dword [eax+4]   ; next write
1731
        xor     eax, eax
83 diamond 1732
        loop    .writelfn
91 diamond 1733
        pop     eax
83 diamond 1734
        pop     esi
1735
.nolfn:
1736
        xchg    esi, [esp]
1737
        mov     ecx, 11
1738
        rep     movsb
1739
        mov     word [edi], 20h         ; attributes
1740
        sub     edi, 11
1741
        pop     esi ecx
1742
        add     esp, 12
1743
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1744
        call    get_time_for_file
1745
        mov     [edi+14], ax            ; creation time
1746
        mov     [edi+22], ax            ; last write time
1747
        call    get_date_for_file
1748
        mov     [edi+16], ax            ; creation date
1749
        mov     [edi+24], ax            ; last write date
1750
        mov     [edi+18], ax            ; last access date
1751
        and     word [edi+20], 0        ; high word of cluster
1752
        and     word [edi+26], 0        ; low word of cluster - to be filled
1753
        and     dword [edi+28], 0       ; file size - to be filled
1754
.doit:
91 diamond 1755
        push    edx
83 diamond 1756
        push    ecx
1757
        push    edi
1758
        add     edi, 26         ; edi points to low word of cluster
1759
        push    edi
1760
        jecxz   .done
1761
        mov     ecx, 2849
1762
        mov     edi, 0x280000
1763
.write_loop:
1764
; allocate new cluster
1765
        xor     eax, eax
1766
        repnz   scasw
1767
        jnz     .disk_full2
1768
        dec     edi
1769
        dec     edi
1770
        lea     eax, [edi-0x280000]
1771
        shr     eax, 1                  ; eax = cluster
1772
        mov     word [edi], 0xFFF       ; mark as last cluster
1773
        xchg    edi, [esp]
1774
        stosw
1775
        pop     edi
1776
        push    edi
1777
        inc     ecx
1778
; write data
1779
        shl     eax, 9
1780
        add     eax, 0x100000+31*512
1781
        mov     ebx, edx
1782
        xchg    eax, ebx
1783
        push    ecx
1784
        mov     ecx, 512
1785
        cmp     dword [esp+12], ecx
1786
        jae     @f
1787
        mov     ecx, [esp+12]
1788
@@:
1789
        call    memmove
1790
        add     edx, ecx
1791
        sub     [esp+12], ecx
1792
        pop     ecx
1793
        jnz     .write_loop
1794
.done:
1795
        mov     ebx, edx
91 diamond 1796
        pop     edi edi ecx edx
83 diamond 1797
        sub     ebx, edx
1798
        mov     [edi+28], ebx
91 diamond 1799
        add     esp, 20
131 diamond 1800
        mov     [esp+16], ebx
91 diamond 1801
        popad
83 diamond 1802
        xor     eax, eax
1803
        ret
1804
.disk_full2:
1805
        mov     ebx, edx
91 diamond 1806
        pop     edi edi ecx edx
83 diamond 1807
        sub     ebx, edx
1808
        mov     [edi+28], ebx
91 diamond 1809
        add     esp, 20
131 diamond 1810
        mov     [esp+16], ebx
91 diamond 1811
        popad
83 diamond 1812
        push    ERROR_DISK_FULL
1813
        pop     eax
1814
        ret
1815
 
1816
.read_symbol:
1817
        or      ax, -1
1818
        test    esi, esi
1819
        jz      .retFFFF
1820
        lodsb
1821
        test    al, al
1822
        jnz     ansi2uni_char
1823
        xor     eax, eax
1824
        xor     esi, esi
1825
.retFFFF:
1826
        ret
1827
 
1828
.read_symbols:
1829
        call    .read_symbol
1830
        stosw
1831
        loop    .read_symbols
1832
        ret
1833
 
131 diamond 1834
;----------------------------------------------------------------
1835
;
1836
;  fs_RamdiskWrite - LFN variant for writing to sys floppy
1837
;
1838
;  esi  points to filename
1839
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1840
;       may be ebx=0 - start from first byte
1841
;  ecx  number of bytes to write, 0+
1842
;  edx  mem location to data
1843
;
1844
;  ret ebx = bytes written (maybe 0)
1845
;      eax = 0 ok write or other = errormsg
1846
;
1847
;--------------------------------------------------------------
1848
@@:
1849
        push    ERROR_ACCESS_DENIED
1850
fs_RamdiskWrite.ret0:
1851
        pop     eax
1852
        xor     ebx, ebx
1853
        ret
1854
 
1855
fs_RamdiskWrite:
1856
        cmp     byte [esi], 0
1857
        jz      @b
1858
        pushad
1859
        call    rd_find_lfn
1860
        jnc     .found
1861
        popad
1862
        push    ERROR_FILE_NOT_FOUND
1863
        jmp     .ret0
1864
.found:
1865
; must not be directory
1866
        test    byte [edi+11], 10h
1867
        jz      @f
1868
        popad
1869
        push    ERROR_ACCESS_DENIED
1870
        jmp     .ret0
1871
@@:
1872
; FAT does not support files larger than 4GB
1873
        test    ebx, ebx
1874
        jz      .l1
1875
        cmp     dword [ebx+4], 0
1876
        jz      @f
1877
.eof:
1878
        popad
1879
        push    ERROR_END_OF_FILE
1880
        jmp     .ret0
1881
@@:
1882
        mov     ebx, [ebx]
1883
.l1:
1884
; now edi points to direntry, ebx=start byte to write,
1885
; ecx=number of bytes to write, edx=data pointer
133 diamond 1886
        call    fat_update_datetime
131 diamond 1887
 
1888
; extend file if needed
1889
        add     ecx, ebx
1890
        jc      .eof    ; FAT does not support files larger than 4GB
1891
        push    0       ; return value=0
1892
        cmp     ecx, [edi+28]
1893
        jbe     .length_ok
1894
        cmp     ecx, ebx
1895
        jz      .length_ok
1896
        call    ramdisk_extend_file
1897
        jnc     .length_ok
1898
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
1899
; First case is fatal error, in second case we may write some data
1900
        mov     [esp], eax
1901
        cmp     al, ERROR_DISK_FULL
1902
        jz      .disk_full
1903
        pop     eax
1904
        mov     [esp+28], eax
1905
        popad
1906
        xor     ebx, ebx
1907
        ret
1908
.disk_full:
1909
; correct number of bytes to write
1910
        mov     ecx, [edi+28]
1911
        cmp     ecx, ebx
1912
        ja      .length_ok
1913
.ret:
1914
        pop     eax
1915
        mov     [esp+28], eax   ; eax=return value
1916
        sub     edx, [esp+20]
1917
        mov     [esp+16], edx   ; ebx=number of written bytes
1918
        popad
1919
        ret
1920
.length_ok:
1921
; now ebx=start pos, ecx=end pos, both lie inside file
1922
        sub     ecx, ebx
1923
        jz      .ret
1924
        movzx   edi, word [edi+26]      ; starting cluster
1925
.write_loop:
1926
        sub     ebx, 0x200
1927
        jae     .next_cluster
1928
        push    ecx
1929
        neg     ebx
1930
        cmp     ecx, ebx
1931
        jbe     @f
1932
        mov     ecx, ebx
1933
@@:
1934
        mov     eax, edi
1935
        shl     eax, 9
1936
        add     eax, 0x100000+31*512+0x200
1937
        sub     eax, ebx
1938
        mov     ebx, eax
1939
        mov     eax, edx
1940
        call    memmove
1941
        xor     ebx, ebx
1942
        add     edx, ecx
1943
        sub     [esp], ecx
1944
        pop     ecx
1945
        jz      .ret
1946
.next_cluster:
1947
        movzx   edi, word [edi*2+0x280000]
1948
        jmp     .write_loop
1949
 
1950
ramdisk_extend_file.zero_size:
1951
        xor     eax, eax
1952
        jmp     ramdisk_extend_file.start_extend
1953
 
1954
; extends file on ramdisk to given size, new data area is filled by 0
1955
; in: edi->direntry, ecx=new size
133 diamond 1956
; out: CF=0 => OK, eax=0
131 diamond 1957
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
1958
ramdisk_extend_file:
1959
        push    ecx
1960
; find the last cluster of file
1961
        movzx   eax, word [edi+26]      ; first cluster
1962
        mov     ecx, [edi+28]
1963
        jecxz   .zero_size
1964
@@:
1965
        sub     ecx, 0x200
1966
        jbe     @f
1967
        mov     eax, [eax*2+0x280000]
1968
        and     eax, 0xFFF
1969
        jz      .fat_err
1970
        cmp     eax, 0xFF8
1971
        jb      @b
1972
.fat_err:
1973
        pop     ecx
1974
        push    ERROR_FAT_TABLE
1975
        pop     eax
1976
        stc
1977
        ret
1978
@@:
1979
        push    eax
1980
        mov     eax, [eax*2+0x280000]
1981
        and     eax, 0xFFF
1982
        cmp     eax, 0xFF8
1983
        pop     eax
1984
        jb      .fat_err
1985
; set length to full number of sectors and make sure that last sector is zero-padded
1986
        sub     [edi+28], ecx
1987
        push    eax edi
1988
        mov     edi, eax
1989
        shl     edi, 9
1990
        lea     edi, [edi+0x100000+31*512+0x200+ecx]
1991
        neg     ecx
1992
        xor     eax, eax
1993
        rep     stosb
1994
        pop     edi eax
1995
.start_extend:
1996
        pop     ecx
1997
; now do extend
1998
        push    edx esi
1999
        mov     esi, 0x280000+2*2       ; start scan from cluster 2
2000
        mov     edx, 2847               ; number of clusters to scan
2001
.extend_loop:
2002
        cmp     [edi+28], ecx
2003
        jae     .extend_done
2004
; add new sector
2005
        push    ecx
2006
        mov     ecx, edx
2007
        push    edi
2008
        mov     edi, esi
2009
        jecxz   .disk_full
2010
        push    eax
2011
        xor     eax, eax
2012
        repnz   scasw
2013
        pop     eax
2014
        jnz     .disk_full
2015
        mov     word [edi-2], 0xFFF
2016
        mov     esi, edi
2017
        mov     edx, ecx
2018
        sub     edi, 0x280000
2019
        shr     edi, 1
2020
        dec     edi     ; now edi=new cluster
2021
        test    eax, eax
2022
        jz      .first_cluster
2023
        mov     [0x280000+eax*2], di
2024
        jmp     @f
2025
.first_cluster:
2026
        pop     eax     ; eax->direntry
2027
        push    eax
2028
        mov     [eax+26], di
2029
@@:
2030
        push    edi
2031
        shl     edi, 9
2032
        add     edi, 0x100000+31*512
2033
        xor     eax, eax
2034
        mov     ecx, 512/4
2035
        rep     stosd
2036
        pop     eax     ; eax=new cluster
2037
        pop     edi     ; edi->direntry
2038
        pop     ecx     ; ecx=required size
2039
        add     dword [edi+28], 0x200
2040
        jmp     .extend_loop
2041
.extend_done:
2042
        mov     [edi+28], ecx
2043
        pop     esi edx
133 diamond 2044
        xor     eax, eax        ; CF=0
131 diamond 2045
        ret
2046
.disk_full:
2047
        pop     edi ecx
2048
        pop     esi edx
2049
        stc
2050
        push    ERROR_DISK_FULL
2051
        pop     eax
2052
        ret
2053
 
133 diamond 2054
fat_update_datetime:
2055
        call    get_time_for_file
2056
        mov     [edi+22], ax            ; last write time
2057
        call    get_date_for_file
2058
        mov     [edi+24], ax            ; last write date
2059
        mov     [edi+18], ax            ; last access date
2060
        ret
2061
 
2062
;----------------------------------------------------------------
2063
;
2064
;  fs_RamdiskSetFileEnd - set end of file on ramdisk
2065
;
2066
;  esi  points to filename
2067
;  ebx  points to 64-bit number = new file size
2068
;  ecx  ignored (reserved)
2069
;  edx  ignored (reserved)
2070
;
2071
;  ret eax = 0 ok or other = errormsg
2072
;
2073
;--------------------------------------------------------------
2074
fs_RamdiskSetFileEnd:
2075
        cmp     byte [esi], 0
2076
        jnz     @f
2077
.access_denied:
2078
        push    ERROR_ACCESS_DENIED
2079
        jmp     .ret
2080
@@:
2081
        push    edi
2082
        call    rd_find_lfn
2083
        jnc     @f
2084
        pop     edi
2085
        push    ERROR_FILE_NOT_FOUND
2086
.ret:
2087
        pop     eax
2088
        ret
2089
@@:
2090
; must not be directory
2091
        test    byte [edi+11], 10h
2092
        jz      @f
2093
        pop     edi
2094
        jmp     .access_denied
2095
@@:
2096
; file size must not exceed 4Gb
2097
        cmp     dword [ebx+4], 0
2098
        jz      @f
2099
        pop     edi
2100
        push    ERROR_END_OF_FILE
2101
        jmp     .ret
2102
@@:
2103
; set file modification date/time to current
2104
        call    fat_update_datetime
2105
        mov     eax, [ebx]
2106
        cmp     eax, [edi+28]
2107
        jb      .truncate
2108
        ja      .expand
2109
        pop     edi
2110
        xor     eax, eax
2111
        ret
2112
.expand:
2113
        push    ecx
2114
        mov     ecx, eax
2115
        call    ramdisk_extend_file
2116
        pop     ecx
2117
        pop     edi
2118
        ret
2119
.truncate:
2120
        mov     [edi+28], eax
2121
        push    ecx
2122
        movzx   ecx, word [edi+26]
2123
        test    eax, eax
2124
        jz      .zero_size
2125
; find new last sector
2126
@@:
2127
        sub     eax, 0x200
2128
        jbe     @f
2129
        movzx   ecx, word [0x280000+ecx*2]
2130
        jmp     @b
2131
@@:
2132
; zero data at the end of last sector
2133
        push    ecx
2134
        mov     edi, ecx
2135
        shl     edi, 9
2136
        lea     edi, [edi+0x100000+31*512+eax+0x200]
2137
        mov     ecx, eax
2138
        neg     ecx
2139
        xor     eax, eax
2140
        rep     stosb
2141
        pop     ecx
2142
; terminate FAT chain
2143
        lea     ecx, [0x280000+ecx+ecx]
2144
        push    dword [ecx]
2145
        mov     word [ecx], 0xFFF
2146
        pop     ecx
2147
        and     ecx, 0xFFF
2148
        jmp     .delete
2149
.zero_size:
2150
        and     word [edi+26], 0
2151
.delete:
2152
; delete FAT chain starting with ecx
2153
; mark all clusters as free
2154
        cmp     ecx, 0xFF8
2155
        jae     .deleted
2156
        lea     ecx, [0x280000+ecx+ecx]
2157
        push    dword [ecx]
2158
        and     word [ecx], 0
2159
        pop     ecx
2160
        and     ecx, 0xFFF
2161
        jmp     .delete
2162
.deleted:
2163
        pop     ecx
2164
        pop     edi
2165
        xor     eax, eax
2166
        ret
2167
 
86 diamond 2168
fs_RamdiskGetFileInfo:
2169
        cmp     byte [esi], 0
2170
        jnz     @f
2171
        mov     eax, 2  ; unsupported
2172
        ret
2173
@@:
2174
        push    edi
2175
        call    rd_find_lfn
2176
fs_GetFileInfo_finish:
2177
        jnc     @f
2178
        pop     edi
2179
        mov     eax, ERROR_FILE_NOT_FOUND
2180
        ret
2181
@@:
2182
        push    esi ebp
2183
        xor     ebp, ebp
2184
        mov     esi, edx
2185
        and     dword [esi+4], 0
2186
        call    fat_entry_to_bdfe2
2187
        pop     ebp esi
2188
        pop     edi
2189
        xor     eax, eax
2190
        ret
2191
 
2192
fs_RamdiskSetFileInfo:
2193
        cmp     byte [esi], 0
2194
        jnz     @f
2195
        mov     eax, 2  ; unsupported
2196
        ret
2197
@@:
2198
        push    edi
2199
        call    rd_find_lfn
2200
        jnc     @f
2201
        pop     edi
2202
        mov     eax, ERROR_FILE_NOT_FOUND
2203
        ret
2204
@@:
2205
        call    bdfe_to_fat_entry
2206
        pop     edi
2207
        xor     eax, eax
2208
        ret
2209
 
91 diamond 2210
;----------------------------------------------------------------
2211
;
2212
;  fs_RamdiskExecute - LFN variant for executing on sys floppy
2213
;
2214
;  esi  points to ramdisk filename (e.g. 'launcher')
2215
;  ebp  points to full filename (e.g. '/rd/1/launcher')
2216
;  dword [ebx] = flags
2217
;  dword [ebx+4] = cmdline
2218
;
2219
;  ret ebx,edx destroyed
2220
;      eax > 0 - PID, < 0 - error
2221
;
2222
;--------------------------------------------------------------
2223
fs_RamdiskExecute:
2224
        mov     edx, [ebx]
2225
        mov     ebx, [ebx+4]
2226
        test    ebx, ebx
2227
        jz      @f
2228
        add     ebx, std_application_base_address
2229
@@:
2230
 
2231
;----------------------------------------------------------------
2232
;
2233
; fs_RamdiskExecute.flags - second entry
2234
;
2235
;  esi  points to ramdisk filename (kernel address)
2236
;  ebp  points to full filename
2237
;  edx  flags
2238
;  ebx  cmdline (kernel address)
2239
;
2240
;  ret  eax > 0 - PID, < 0 - error
2241
;
2242
;--------------------------------------------------------------
2243
 
2244
.flags:
2245
        cmp     byte [esi], 0
2246
        jnz     @f
2247
; cannot execute root!
2248
        mov     eax, -ERROR_ACCESS_DENIED
2249
        ret
2250
@@:
2251
        push    edi
2252
        call    rd_find_lfn
2253
        jnc     .found
2254
        pop     edi
2255
        mov     eax, -ERROR_FILE_NOT_FOUND
2256
        ret
2257
.found:
2258
        movzx   eax, word [edi+26]      ; cluster
2259
        push    eax
2260
        push    dword [edi+28]          ; size
2261
        push    .DoRead
2262
        call    fs_execute
2263
        add     esp, 12
2264
        pop     edi
2265
        ret
2266
 
2267
.DoRead:
2268
; read next block
2269
; in: eax->parameters, edi->buffer
2270
; out: eax = error code
2271
        pushad
2272
        cmp     dword [eax], 0  ; file size
2273
        jz      .eof
2274
        mov     edx, [eax+4]    ; cluster
2275
        lea     esi, [edx+31]
2276
        shl     esi, 9
2277
        add     esi, 0x100000
2278
        mov     ecx, 512/4
2279
        rep     movsd
2280
        mov     ecx, [eax]
2281
        sub     ecx, 512
2282
        jae     @f
2283
        add     edi, ecx
2284
        neg     ecx
2285
        push    eax
2286
        xor     eax, eax
2287
        rep     stosb
2288
        pop     eax
2289
@@:
2290
        mov     [eax], ecx
2291
        mov     dx, [edx*2+0x280000]
2292
        mov     [eax+4], dx     ; high word is already zero
2293
        popad
2294
        xor     eax, eax
2295
        ret
2296
.eof:
2297
        popad
2298
        mov     eax, 6
2299
        ret
2300
 
171 diamond 2301
;----------------------------------------------------------------
2302
;
2303
;  fs_RamdiskDelete - delete file or empty folder from ramdisk
2304
;
2305
;  esi  points to filename
2306
;
2307
;  ret  eax = 0 ok or other = errormsg
2308
;
2309
;--------------------------------------------------------------
2310
fs_RamdiskDelete:
2311
        cmp     byte [esi], 0
2312
        jnz     @f
2313
; cannot delete root!
2314
.access_denied:
2315
        push    ERROR_ACCESS_DENIED
2316
.pop_ret:
2317
        pop     eax
2318
        ret
2319
@@:
2320
        and     [rd_prev_sector], 0
2321
        and     [rd_prev_prev_sector], 0
2322
        push    edi
2323
        call    rd_find_lfn
2324
        jnc     .found
2325
        pop     edi
2326
        push    ERROR_FILE_NOT_FOUND
2327
        jmp     .pop_ret
2328
.found:
2329
        cmp     dword [edi], '.   '
2330
        jz      .access_denied2
2331
        cmp     dword [edi], '..  '
2332
        jz      .access_denied2
2333
        test    byte [edi+11], 10h
2334
        jz      .dodel
2335
; we can delete only empty folders!
2336
        movzx   eax, word [edi+26]
2337
        push    ebx
2338
        mov     ebx, eax
2339
        shl     ebx, 9
2340
        add     ebx, RAMDISK + 31*0x200 + 2*0x20
2341
.checkempty:
2342
        cmp     byte [ebx], 0
2343
        jz      .empty
2344
        cmp     byte [ebx], 0xE5
2345
        jnz     .notempty
2346
        add     ebx, 0x20
2347
        test    ebx, 0x1FF
2348
        jnz     .checkempty
2349
        movzx   eax, word [RAMDISK_FAT + eax*2]
2350
        test    eax, eax
2351
        jz      .empty
2352
        mov     ebx, eax
2353
        shl     ebx, 9
2354
        add     ebx, RAMDISK + 31*0x200
2355
        jmp     .checkempty
2356
.notempty:
2357
        pop     ebx
2358
.access_denied2:
2359
        pop     edi
2360
        jmp     .access_denied
2361
.empty:
2362
        pop     ebx
2363
.dodel:
2364
        movzx   eax, word [edi+26]
2365
; delete folder entry
2366
        mov     byte [edi], 0xE5
2367
; delete LFN (if present)
2368
.lfndel:
2369
        test    edi, 0x1FF
2370
        jnz     @f
2371
        cmp     [rd_prev_sector], 0
2372
        jz      @f
2373
        cmp     [rd_prev_sector], -1
2374
        jz      .lfndone
2375
        mov     edi, [rd_prev_sector]
2376
        push    [rd_prev_prev_sector]
2377
        pop     [rd_prev_sector]
2378
        or      [rd_prev_prev_sector], -1
2379
        shl     edi, 9
2380
        add     edi, RAMDISK + 31*0x200 + 0x200
2381
@@:
2382
        sub     edi, 0x20
2383
        cmp     byte [edi], 0xE5
2384
        jz      .lfndone
2385
        cmp     byte [edi+11], 0xF
2386
        jnz     .lfndone
2387
        mov     byte [edi], 0xE5
2388
        jmp     .lfndel
2389
.lfndone:
2390
; delete FAT chain
2391
        test    eax, eax
2392
        jz      .done
2393
        lea     eax, [RAMDISK_FAT + eax*2]
2394
        push    dword [eax]
2395
        and     word [eax], 0
2396
        pop     eax
2397
        and     eax, 0xFFF
2398
        jmp     .lfndone
2399
.done:
2400
        pop     edi
2401
        xor     eax, eax
2402
        ret
2403
 
78 diamond 2404
; \end{diamond}