Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4429 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 4418 $
9
 
10
 
11
DRV_COMPAT   equ  5  ;minimal required drivers version
12
DRV_CURRENT  equ  6  ;current drivers model version
13
 
14
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
15
PID_KERNEL  equ 1    ;os_idle thread
16
 
17
 
18
 
19
align 4
20
proc get_notify stdcall, p_ev:dword
21
 
22
.wait:
23
        mov     ebx, [current_slot]
24
        test    dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
25
        jz      @f
26
        and     dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
27
        mov     edi, [p_ev]
28
        mov     dword [edi], EV_INTR
29
        mov     eax, [ebx+APPDATA.event]
30
        mov     dword [edi+4], eax
31
        ret
32
@@:
33
        call    change_task
34
        jmp     .wait
35
endp
36
 
37
align 4
38
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
39
        push    ebx
40
        xor     eax, eax
41
        xor     ebx, ebx
42
        mov     ah, byte [bus]
43
        mov     al, 6
44
        mov     bh, byte [devfn]
45
        mov     bl, byte [reg]
46
        call    pci_read_reg
47
        pop     ebx
48
        ret
49
endp
50
 
51
align 4
52
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
53
        push    ebx
54
        xor     eax, eax
55
        xor     ebx, ebx
56
        mov     ah, byte [bus]
57
        mov     al, 5
58
        mov     bh, byte [devfn]
59
        mov     bl, byte [reg]
60
        call    pci_read_reg
61
        pop     ebx
62
        ret
63
endp
64
 
65
align 4
66
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
67
        push    ebx
68
        xor     eax, eax
69
        xor     ebx, ebx
70
        mov     ah, byte [bus]
71
        mov     al, 4
72
        mov     bh, byte [devfn]
73
        mov     bl, byte [reg]
74
        call    pci_read_reg
75
        pop     ebx
76
        ret
77
endp
78
 
79
align 4
80
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
81
        push    ebx
82
        xor     eax, eax
83
        xor     ebx, ebx
84
        mov     ah, byte [bus]
85
        mov     al, 8
86
        mov     bh, byte [devfn]
87
        mov     bl, byte [reg]
88
        mov     ecx, [val]
89
        call    pci_write_reg
90
        pop     ebx
91
        ret
92
endp
93
 
94
align 4
95
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
96
        push    ebx
97
        xor     eax, eax
98
        xor     ebx, ebx
99
        mov     ah, byte [bus]
100
        mov     al, 9
101
        mov     bh, byte [devfn]
102
        mov     bl, byte [reg]
103
        mov     ecx, [val]
104
        call    pci_write_reg
105
        pop     ebx
106
        ret
107
endp
108
 
109
align 4
110
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
111
        push    ebx
112
        xor     eax, eax
113
        xor     ebx, ebx
114
        mov     ah, byte [bus]
115
        mov     al, 10
116
        mov     bh, byte [devfn]
117
        mov     bl, byte [reg]
118
        mov     ecx, [val]
119
        call    pci_write_reg
120
        pop     ebx
121
        ret
122
endp
123
 
124
handle     equ  IOCTL.handle
125
io_code    equ  IOCTL.io_code
126
input      equ  IOCTL.input
127
inp_size   equ  IOCTL.inp_size
128
output     equ  IOCTL.output
129
out_size   equ  IOCTL.out_size
130
 
131
 
132
align 4
133
proc srv_handler stdcall, ioctl:dword
134
        mov     esi, [ioctl]
135
        test    esi, esi
136
        jz      .err
137
 
138
        mov     edi, [esi+handle]
139
        cmp     [edi+SRV.magic], ' SRV'
140
        jne     .fail
141
 
142
        cmp     [edi+SRV.size], sizeof.SRV
143
        jne     .fail
144
 
145
;        stdcall [edi+SRV.srv_proc], esi
146
        mov     eax, [edi+SRV.srv_proc]
147
        test    eax, eax
148
        jz      .fail
149
        stdcall eax, esi
150
        ret
151
.fail:
152
        xor     eax, eax
153
        not     eax
154
        mov     [esi+output], eax
155
        mov     [esi+out_size], 4
156
        ret
157
.err:
158
        xor     eax, eax
159
        not     eax
160
        ret
161
endp
162
 
163
; param
164
;  ecx= io_control
165
;
166
; retval
167
;  eax= error code
168
 
169
align 4
170
srv_handlerEx:
171
        cmp     ecx, OS_BASE
172
        jae     .fail
173
 
174
        mov     eax, [ecx+handle]
175
        cmp     [eax+SRV.magic], ' SRV'
176
        jne     .fail
177
 
178
        cmp     [eax+SRV.size], sizeof.SRV
179
        jne     .fail
180
 
181
;        stdcall [eax+SRV.srv_proc], ecx
182
        mov     eax, [eax+SRV.srv_proc]
183
        test    eax, eax
184
        jz      .fail
185
        stdcall eax, ecx
186
        ret
187
.fail:
188
        or      eax, -1
189
        ret
190
 
191
restore  handle
192
restore  io_code
193
restore  input
194
restore  inp_size
195
restore  output
196
restore  out_size
197
 
198
align 4
199
proc get_service stdcall, sz_name:dword
200
        mov     eax, [sz_name]
201
        test    eax, eax
202
        jnz     @F
203
        ret
204
@@:
205
        mov     edx, [srv.fd]
206
@@:
207
        cmp     edx, srv.fd-SRV.fd
208
        je      .not_load
209
 
210
        stdcall strncmp, edx, [sz_name], 16
211
        test    eax, eax
5116 serge 212
        mov     eax, edx
213
        je      .nothing
4429 Serge 214
 
215
        mov     edx, [edx+SRV.fd]
216
        jmp     @B
217
.not_load:
218
        mov     eax, [sz_name]
219
        push    edi
220
        sub     esp, 36
221
        mov     edi, esp
222
        mov     dword [edi], '/sys'
223
        mov     dword [edi+4], '/dri'
224
        mov     dword [edi+8], 'vers'
225
        mov     byte [edi+12], '/'
226
@@:
227
        mov     dl, [eax]
228
        mov     [edi+13], dl
229
        inc     eax
230
        inc     edi
231
        test    dl, dl
232
        jnz     @b
233
        mov     dword [edi+12], '.sys'
234
        mov     byte [edi+16], 0
235
        mov     edi, esp
236
        stdcall load_pe_driver, edi, 0
237
        add     esp, 36
238
        pop     edi
239
.nothing:
240
        ret
241
endp
242
 
243
reg_service:
244
        xor     eax, eax
245
        mov     ecx, [esp+8]
246
        jecxz   .nothing
247
        push    sizeof.SRV
248
        push    ecx
249
        pushd   [esp+12]
250
        call    reg_service_ex
251
.nothing:
252
        ret     8
253
 
254
reg_usb_driver:
255
        push    sizeof.USBSRV
256
        pushd   [esp+12]
257
        pushd   [esp+12]
258
        call    reg_service_ex
259
        test    eax, eax
260
        jz      .nothing
261
        mov     ecx, [esp+12]
262
        mov     [eax+USBSRV.usb_func], ecx
263
.nothing:
264
        ret     12
265
 
266
proc reg_service_ex stdcall, name:dword, handler:dword, srvsize:dword
267
 
268
        push    ebx
269
 
270
        xor     eax, eax
271
 
272
        cmp     [name], eax
273
        je      .fail
274
 
275
;        cmp     [handler], eax
276
;        je      .fail
277
 
278
        mov     eax, [srvsize]
279
        call    malloc
280
        test    eax, eax
281
        jz      .fail
282
 
283
        push    esi
284
        push    edi
285
        mov     edi, eax
286
        mov     esi, [name]
287
        movsd
288
        movsd
289
        movsd
290
        movsd
291
        pop     edi
292
        pop     esi
293
 
294
        mov     [eax+SRV.magic], ' SRV'
295
        mov     [eax+SRV.size], sizeof.SRV
296
 
297
        mov     ebx, srv.fd-SRV.fd
298
        mov     edx, [ebx+SRV.fd]
299
        mov     [eax+SRV.fd], edx
300
        mov     [eax+SRV.bk], ebx
301
        mov     [ebx+SRV.fd], eax
302
        mov     [edx+SRV.bk], eax
303
 
304
        mov     ecx, [handler]
305
        mov     [eax+SRV.srv_proc], ecx
306
        pop     ebx
307
        ret
308
.fail:
309
        xor     eax, eax
310
        pop     ebx
311
        ret
312
endp
313
 
314
align 4
315
proc get_proc stdcall, exp:dword, sz_name:dword
316
 
317
        mov     edx, [exp]
318
.next:
319
        mov     eax, [edx]
320
        test    eax, eax
321
        jz      .end
322
 
323
        push    edx
324
        stdcall strncmp, eax, [sz_name], 16
325
        pop     edx
326
        test    eax, eax
327
        jz      .ok
328
 
329
        add     edx, 8
330
        jmp     .next
331
.ok:
332
        mov     eax, [edx+4]
333
.end:
334
        ret
335
endp
336
 
337
align 4
338
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
339
 
340
@@:
341
        stdcall strncmp, [pSym], [sz_sym], 8
342
        test    eax, eax
343
        jz      .ok
344
        add     [pSym], 18
345
        dec     [count]
346
        jnz     @b
347
        xor     eax, eax
348
        ret
349
.ok:
350
        mov     eax, [pSym]
351
        mov     eax, [eax+8]
352
        ret
353
endp
354
 
355
align 4
356
proc get_curr_task
357
        mov     eax, [CURRENT_TASK]
358
        shl     eax, 8
359
        ret
360
endp
361
 
362
align 4
363
proc get_fileinfo stdcall, file_name:dword, info:dword
364
           locals
365
             cmd     dd ?
366
             offset  dd ?
367
                     dd ?
368
             count   dd ?
369
             buff    dd ?
370
                     db ?
371
             name    dd ?
372
           endl
373
 
374
        xor     eax, eax
375
        mov     ebx, [file_name]
376
        mov     ecx, [info]
377
 
378
        mov     [cmd], 5
379
        mov     [offset], eax
380
        mov     [offset+4], eax
381
        mov     [count], eax
382
        mov     [buff], ecx
383
        mov     byte [buff+4], al
384
        mov     [name], ebx
385
 
386
        mov     eax, 70
387
        lea     ebx, [cmd]
388
        int     0x40
389
        ret
390
endp
391
 
392
align 4
393
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
394
                                     bytes:dword
395
           locals
396
             cmd     dd ?
397
             offset  dd ?
398
                     dd ?
399
             count   dd ?
400
             buff    dd ?
401
                     db ?
402
             name    dd ?
403
           endl
404
 
405
        xor     eax, eax
406
        mov     ebx, [file_name]
407
        mov     ecx, [off]
408
        mov     edx, [bytes]
409
        mov     esi, [buffer]
410
 
411
        mov     [cmd], eax
412
        mov     [offset], ecx
413
        mov     [offset+4], eax
414
        mov     [count], edx
415
        mov     [buff], esi
416
        mov     byte [buff+4], al
417
        mov     [name], ebx
418
 
419
        pushad
420
        lea     ebx, [cmd]
421
        call    file_system_lfn_protected
422
        popad
423
        ret
424
endp
425
 
426
; description
427
;  allocate kernel memory and loads the specified file
428
;
429
; param
430
;  file_name= path to file
431
;
432
; retval
433
;  eax= file image in kernel memory
434
;  ebx= size of file
435
;
436
; warging
437
;  You mast call kernel_free() to delete each file
438
;  loaded by the load_file() function
439
 
440
align 4
441
proc load_file stdcall, file_name:dword
442
           locals
443
             attr       dd ?
444
             flags      dd ?
445
             cr_time    dd ?
446
             cr_date    dd ?
447
             acc_time   dd ?
448
             acc_date   dd ?
449
             mod_time   dd ?
450
             mod_date   dd ?
451
             file_size  dd ?
452
 
453
             file       dd ?
454
             file2      dd ?
455
           endl
456
 
457
        push    esi
458
        push    edi
459
 
460
        lea     eax, [attr]
461
        stdcall get_fileinfo, [file_name], eax
462
        test    eax, eax
463
        jnz     .fail
464
 
465
        mov     eax, [file_size]
466
        cmp     eax, 1024*1024*16
467
        ja      .fail
468
 
469
        stdcall kernel_alloc, [file_size]
470
        mov     [file], eax
471
        test    eax, eax
472
        jz      .fail
473
 
474
        stdcall read_file, [file_name], eax, dword 0, [file_size]
475
        cmp     ebx, [file_size]
476
        jne     .cleanup
477
 
478
        mov     eax, [file]
479
        cmp     dword [eax], 0x4B43504B
480
        jne     .exit
481
        mov     ebx, [eax+4]
482
        mov     [file_size], ebx
483
        stdcall kernel_alloc, ebx
484
 
485
        test    eax, eax
486
        jz      .cleanup
487
 
488
        mov     [file2], eax
489
 
490
        pushad
491
        mov     ecx, unpack_mutex
492
        call    mutex_lock
493
        popad
494
 
495
        stdcall unpack, [file], eax
496
 
497
        pushad
498
        mov     ecx, unpack_mutex
499
        call    mutex_unlock
500
        popad
501
 
502
        stdcall kernel_free, [file]
503
        mov     eax, [file2]
504
        mov     ebx, [file_size]
505
.exit:
506
        push    eax
507
        lea     edi, [eax+ebx]    ;cleanup remain space
508
        mov     ecx, 4096         ;from file end
509
        and     ebx, 4095
510
        jz      @f
511
        sub     ecx, ebx
512
        xor     eax, eax
513
        cld
514
        rep stosb
515
@@:
516
        mov     ebx, [file_size]
517
        pop     eax
518
        pop     edi
519
        pop     esi
520
        ret
521
.cleanup:
522
        stdcall kernel_free, [file]
523
.fail:
524
        xor     eax, eax
525
        xor     ebx, ebx
526
        pop     edi
527
        pop     esi
528
        ret
529
endp
530
 
531
; description
532
;  allocate user memory and loads the specified file
533
;
534
; param
535
;  file_name= path to file
536
;
537
; retval
538
;  eax= file image in user memory
539
;  ebx= size of file
540
;
541
; warging
542
;  You mast call kernel_free() to delete each file
543
;  loaded by the load_file() function
544
 
545
align 4
546
proc load_file_umode stdcall, file_name:dword
547
           locals
548
             attr       dd ?
549
             flags      dd ?
550
             cr_time    dd ?
551
             cr_date    dd ?
552
             acc_time   dd ?
553
             acc_date   dd ?
554
             mod_time   dd ?
555
             mod_date   dd ?
556
             file_size  dd ?
557
 
558
             km_file    dd ?
559
             um_file    dd ?
560
           endl
561
 
562
        push    esi
563
        push    edi
564
        push    ebx
565
 
566
        lea     eax, [attr]
567
        stdcall get_fileinfo, [file_name], eax   ;find file and get info
568
        test    eax, eax
569
        jnz     .err_1
570
 
571
        mov     eax, [file_size]
572
        cmp     eax, 1024*1024*16                ;to be enough for anybody (c)
573
        ja      .err_1
574
                                                 ;it is very likely that the file is packed
575
        stdcall kernel_alloc, [file_size]        ;with kpack, so allocate memory from kernel heap
576
        mov     [km_file], eax
577
        test    eax, eax
578
        jz      .err_1
579
 
580
        stdcall read_file, [file_name], eax, dword 0, [file_size]
581
        cmp     ebx, [file_size]
582
 
583
        jne     .err_2
584
 
585
        mov     eax, [km_file]
586
        cmp     dword [eax], 0x4B43504B          ; check kpack signature
587
        jne     .raw_file
588
 
589
        mov     ebx, [eax+4]                     ;get real size of file
590
        mov     [file_size], ebx
591
        stdcall user_alloc, ebx                  ;and allocate space from user heap
592
        mov     [um_file], eax
593
        test    eax, eax
594
        jz      .err_2
595
 
596
        mov     edx, [file_size]                 ;preallocate page memory
597
        shr     eax, 10
598
        lea     edi, [page_tabs+eax]
599
        add     edx, 4095
600
        shr     edx, 12
601
@@:
602
        call    alloc_page
603
        test    eax, eax
604
        jz      .err_3
605
 
606
        or      eax, PG_UW
607
        stosd
608
        dec     edx
609
        jnz     @B
610
 
611
        pushad
612
        mov     ecx, unpack_mutex
613
        call    mutex_lock
614
 
615
        stdcall unpack, [km_file], [um_file]
616
 
617
        mov     ecx, unpack_mutex
618
        call    mutex_unlock
619
        popad
620
 
621
        stdcall kernel_free, [km_file]           ;we don't need packed file anymore
622
.exit:
623
 
624
        mov     edi, [um_file]
625
        mov     esi, [um_file]
626
        mov     eax, [file_size]
627
        mov     edx, eax
628
 
629
        add     edi, eax                         ;cleanup remain space
630
        mov     ecx, 4096                        ;from file end
631
        and     eax, 4095
632
        jz      @f
633
        sub     ecx, eax
634
        xor     eax, eax
635
        cld
636
        rep stosb
637
@@:
638
        mov     eax, [um_file]
639
 
640
        pop     ebx
641
        pop     edi
642
        pop     esi
643
        ret
644
 
645
.raw_file:                                       ; sometimes we load unpacked file
646
        stdcall user_alloc, ebx                  ; allocate space from user heap
647
        mov     [um_file], eax
648
 
649
        test    eax, eax
650
        jz      .err_2
651
 
652
        shr     eax, 10                          ; and remap pages.
653
 
654
        mov     ecx, [file_size]
655
        add     ecx, 4095
656
        shr     ecx, 12
657
 
658
        mov     esi, [km_file]
659
        shr     esi, 10
660
        add     esi, page_tabs
661
 
662
        lea     edi, [page_tabs+eax]
663
 
664
        cld
665
@@:
666
        lodsd
667
        and     eax, 0xFFFFF000
668
        or      eax, PG_UW
669
        stosd
670
        loop    @B
671
 
672
        stdcall free_kernel_space, [km_file]     ; release allocated kernel space
673
        jmp     .exit                            ; physical pages still in use
674
.err_3:
675
        stdcall user_free, [um_file]
676
.err_2:
677
        stdcall kernel_free, [km_file]
678
.err_1:
679
        xor     eax, eax
680
        xor     edx, edx
681
 
682
        pop     ebx
683
        pop     edi
684
        pop     esi
685
        ret
686
endp
687
 
688
 
689
uglobal
690
align 4
691
unpack_mutex MUTEX
692
endg
693
 
694
align 4
695
proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
696
        mov     ebx, [imports]
697
        test    ebx, ebx
698
        jz      .end
699
        xor     esi, esi
700
.look_up:
701
 
702
        mov     eax, [ebx+32]
703
        mov     eax, [OS_BASE+eax+esi*4]
704
        add     eax, OS_BASE
705
        stdcall strncmp, eax, [proc_name], 256
706
        test    eax, eax
707
        jz      .ok
708
 
709
        inc     esi
710
        cmp     esi, [ebx+24]
711
        jb      .look_up
712
.end:
713
        xor     eax, eax
714
        ret
715
.ok:
716
        mov     eax, [ebx+28]
717
        mov     eax, [OS_BASE+eax+esi*4]
718
        add     eax, OS_BASE
719
        ret
720
endp
721
 
722
align 4
723
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
724
                      sym_count:dword, strings:dword, imports:dword
725
           locals
726
             retval dd ?
727
           endl
728
 
729
        mov     edi, [symbols]
730
        mov     [retval], 1
731
.fix:
732
        movzx   ebx, [edi+COFF_SYM.SectionNumber]
733
        test    ebx, ebx
734
        jnz     .internal
735
        mov     eax, dword [edi+COFF_SYM.Name]
736
        test    eax, eax
737
        jnz     @F
738
 
739
        mov     edi, [edi+4]
740
        add     edi, [strings]
741
@@:
742
        push    edi
743
        stdcall get_proc_ex, edi, [imports]
744
        pop     edi
745
 
746
        xor     ebx, ebx
747
        test    eax, eax
748
        jnz     @F
749
 
750
        mov     esi, msg_unresolved
751
        call    sys_msg_board_str
752
        mov     esi, edi
753
        call    sys_msg_board_str
754
        mov     esi, msg_CR
755
        call    sys_msg_board_str
756
 
757
        mov     [retval], 0
758
@@:
759
        mov     edi, [symbols]
760
        mov     [edi+COFF_SYM.Value], eax
761
        jmp     .next
762
.internal:
763
        cmp     bx, -1
764
        je      .next
765
        cmp     bx, -2
766
        je      .next
767
 
768
        dec     ebx
769
        shl     ebx, 3
770
        lea     ebx, [ebx+ebx*4]
771
        add     ebx, [sec]
772
 
773
        mov     eax, [ebx+COFF_SECTION.VirtualAddress]
774
        add     [edi+COFF_SYM.Value], eax
775
.next:
776
        add     edi, sizeof.COFF_SYM
777
        mov     [symbols], edi
778
        dec     [sym_count]
779
        jnz     .fix
780
        mov     eax, [retval]
781
        ret
782
endp
783
 
784
align 4
785
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
786
        delta:dword
787
           locals
788
             n_sec     dd ?
789
           endl
790
 
791
        mov     eax, [coff]
792
        movzx   ebx, [eax+COFF_HEADER.nSections]
793
        mov     [n_sec], ebx
794
        lea     esi, [eax+20]
795
.fix_sec:
796
        mov     edi, [esi+COFF_SECTION.PtrReloc]
797
        add     edi, [coff]
798
 
799
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
800
        test    ecx, ecx
801
        jz      .next
802
.reloc_loop:
803
        mov     ebx, [edi+COFF_RELOC.SymIndex]
804
        add     ebx, ebx
805
        lea     ebx, [ebx+ebx*8]
806
        add     ebx, [sym]
807
 
808
        mov     edx, [ebx+COFF_SYM.Value]
809
 
810
        cmp     [edi+COFF_RELOC.Type], 6
811
        je      .dir_32
812
 
813
        cmp     [edi+COFF_RELOC.Type], 20
814
        jne     .next_reloc
815
.rel_32:
816
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
817
        add     eax, [esi+COFF_SECTION.VirtualAddress]
818
        sub     edx, eax
819
        sub     edx, 4
820
        jmp     .fix
821
.dir_32:
822
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
823
        add     eax, [esi+COFF_SECTION.VirtualAddress]
824
.fix:
825
        add     eax, [delta]
826
        add     [eax], edx
827
.next_reloc:
828
        add     edi, 10
829
        dec     ecx
830
        jnz     .reloc_loop
831
.next:
832
        add     esi, sizeof.COFF_SECTION
833
        dec     [n_sec]
834
        jnz     .fix_sec
835
.exit:
836
        ret
837
endp
838
 
839
align 4
840
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
841
        delta:dword
842
           locals
843
             n_sec     dd ?
844
           endl
845
 
846
        mov     eax, [coff]
847
        movzx   ebx, [eax+COFF_HEADER.nSections]
848
        mov     [n_sec], ebx
849
        lea     esi, [eax+20]
850
        mov     edx, [delta]
851
.fix_sec:
852
        mov     edi, [esi+COFF_SECTION.PtrReloc]
853
        add     edi, [coff]
854
 
855
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
856
        test    ecx, ecx
857
        jz      .next
858
.reloc_loop:
859
        cmp     [edi+COFF_RELOC.Type], 6
860
        jne     .next_reloc
861
.dir_32:
862
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
863
        add     eax, [esi+COFF_SECTION.VirtualAddress]
864
        add     [eax+edx], edx
865
.next_reloc:
866
        add     edi, 10
867
        dec     ecx
868
        jnz     .reloc_loop
869
.next:
870
        add     esi, sizeof.COFF_SECTION
871
        dec     [n_sec]
872
        jnz     .fix_sec
873
.exit:
874
        ret
875
endp
876
 
877
; in: edx -> COFF_SECTION struct
878
; out: eax = alignment as mask for bits to drop
879
coff_get_align:
880
; Rules:
881
; - if alignment is not given, use default = 4K;
882
; - if alignment is given and is no more than 4K, use it;
883
; - if alignment is more than 4K, revert to 4K.
884
        push    ecx
885
        mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
886
        mov     eax, 1
887
        shr     cl, 4
888
        dec     cl
889
        js      .default
890
        cmp     cl, 12
891
        jbe     @f
892
.default:
893
        mov     cl, 12
894
@@:
895
        shl     eax, cl
896
        pop     ecx
897
        dec     eax
898
        ret
899
 
900
align 4
901
proc load_library stdcall, file_name:dword
902
           locals
903
             fullname  rb 260
904
             fileinfo  rb 40
905
             coff      dd ?
906
             img_base  dd ?
907
           endl
908
 
909
; resolve file name
910
        mov     ebx, [file_name]
911
        lea     edi, [fullname+1]
912
        mov     byte [edi-1], '/'
913
        stdcall get_full_file_name, edi, 259
914
        test    al, al
915
        jz      .fail
916
 
917
; scan for required DLL in list of already loaded for this process,
918
; ignore timestamp
919
        cli
920
 
4433 Serge 921
        mov     esi, [current_process]
4429 Serge 922
        lea     edi, [fullname]
4433 Serge 923
        mov     ebx, [esi+PROC.dlls_list_ptr]
4429 Serge 924
        test    ebx, ebx
925
        jz      .not_in_process
926
        mov     esi, [ebx+HDLL.fd]
927
.scan_in_process:
928
        cmp     esi, ebx
929
        jz      .not_in_process
930
        mov     eax, [esi+HDLL.parent]
931
        add     eax, DLLDESCR.name
932
        stdcall strncmp, eax, edi, -1
933
        test    eax, eax
934
        jnz     .next_in_process
935
; simple variant: load DLL which is already loaded in this process
936
; just increment reference counters and return address of exports table
937
        inc     [esi+HDLL.refcount]
938
        mov     ecx, [esi+HDLL.parent]
939
        inc     [ecx+DLLDESCR.refcount]
940
        mov     eax, [ecx+DLLDESCR.exports]
941
        sub     eax, [ecx+DLLDESCR.defaultbase]
942
        add     eax, [esi+HDLL.base]
943
        sti
944
        ret
945
.next_in_process:
946
        mov     esi, [esi+HDLL.fd]
947
        jmp     .scan_in_process
948
.not_in_process:
949
 
950
; scan in full list, compare timestamp
951
        sti
952
        lea     eax, [fileinfo]
953
        stdcall get_fileinfo, edi, eax
954
        test    eax, eax
955
        jnz     .fail
956
        cli
957
        mov     esi, [dll_list.fd]
958
.scan_for_dlls:
959
        cmp     esi, dll_list
960
        jz      .load_new
961
        lea     eax, [esi+DLLDESCR.name]
962
        stdcall strncmp, eax, edi, -1
963
        test    eax, eax
964
        jnz     .continue_scan
965
.test_prev_dll:
966
        mov     eax, dword [fileinfo+24]; last modified time
967
        mov     edx, dword [fileinfo+28]; last modified date
968
        cmp     dword [esi+DLLDESCR.timestamp], eax
969
        jnz     .continue_scan
970
        cmp     dword [esi+DLLDESCR.timestamp+4], edx
971
        jz      .dll_already_loaded
972
.continue_scan:
973
        mov     esi, [esi+DLLDESCR.fd]
974
        jmp     .scan_for_dlls
975
 
976
; new DLL
977
.load_new:
978
        sti
979
; load file
980
        stdcall load_file, edi
981
        test    eax, eax
982
        jz      .fail
983
        mov     [coff], eax
984
        mov     dword [fileinfo+32], ebx
985
 
986
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
987
        mov     esi, edi
988
        mov     ecx, -1
989
        xor     eax, eax
990
        repnz scasb
991
        not     ecx
992
        lea     eax, [ecx+sizeof.DLLDESCR]
993
        push    ecx
994
        call    malloc
995
        pop     ecx
996
        test    eax, eax
997
        jz      .fail_and_free_coff
998
; save timestamp
999
        lea     edi, [eax+DLLDESCR.name]
1000
        rep movsb
1001
        mov     esi, eax
1002
        mov     eax, dword [fileinfo+24]
1003
        mov     dword [esi+DLLDESCR.timestamp], eax
1004
        mov     eax, dword [fileinfo+28]
1005
        mov     dword [esi+DLLDESCR.timestamp+4], eax
1006
 
1007
; calculate size of loaded DLL
1008
        mov     edx, [coff]
1009
        movzx   ecx, [edx+COFF_HEADER.nSections]
1010
        xor     ebx, ebx
1011
 
1012
        add     edx, 20
1013
@@:
1014
        call    coff_get_align
1015
        add     ebx, eax
1016
        not     eax
1017
        and     ebx, eax
1018
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
1019
        add     edx, sizeof.COFF_SECTION
1020
        dec     ecx
1021
        jnz     @B
1022
; it must be nonzero and not too big
1023
        mov     [esi+DLLDESCR.size], ebx
1024
        test    ebx, ebx
1025
        jz      .fail_and_free_dll
1026
        cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
1027
        ja      .fail_and_free_dll
1028
; allocate memory for kernel-side image
1029
        stdcall kernel_alloc, ebx
1030
        test    eax, eax
1031
        jz      .fail_and_free_dll
1032
        mov     [esi+DLLDESCR.data], eax
1033
; calculate preferred base address
1034
        add     ebx, 0x1FFF
1035
        and     ebx, not 0xFFF
1036
        mov     ecx, [dll_cur_addr]
1037
        lea     edx, [ecx+ebx]
1038
        cmp     edx, MAX_DEFAULT_DLL_ADDR
1039
        jb      @f
1040
        mov     ecx, MIN_DEFAULT_DLL_ADDR
1041
        lea     edx, [ecx+ebx]
1042
@@:
1043
        mov     [esi+DLLDESCR.defaultbase], ecx
1044
        mov     [dll_cur_addr], edx
1045
 
1046
; copy sections and set correct values for VirtualAddress'es in headers
1047
        push    esi
1048
        mov     edx, [coff]
1049
        movzx   ebx, [edx+COFF_HEADER.nSections]
1050
        mov     edi, eax
1051
        add     edx, 20
1052
        cld
1053
@@:
1054
        call    coff_get_align
1055
        add     ecx, eax
1056
        add     edi, eax
1057
        not     eax
1058
        and     ecx, eax
1059
        and     edi, eax
1060
        mov     [edx+COFF_SECTION.VirtualAddress], ecx
1061
        add     ecx, [edx+COFF_SECTION.SizeOfRawData]
1062
        mov     esi, [edx+COFF_SECTION.PtrRawData]
1063
        push    ecx
1064
        mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
1065
        test    esi, esi
1066
        jnz     .copy
1067
        xor     eax, eax
1068
        rep stosb
1069
        jmp     .next
1070
.copy:
1071
        add     esi, [coff]
1072
        rep movsb
1073
.next:
1074
        pop     ecx
1075
        add     edx, sizeof.COFF_SECTION
1076
        dec     ebx
1077
        jnz     @B
1078
        pop     esi
1079
 
1080
; save some additional data from COFF file
1081
; later we will use COFF header, headers for sections and symbol table
1082
; and also relocations table for all sections
1083
        mov     edx, [coff]
1084
        mov     ebx, [edx+COFF_HEADER.pSymTable]
1085
        mov     edi, dword [fileinfo+32]
1086
        sub     edi, ebx
1087
        jc      .fail_and_free_data
1088
        mov     [esi+DLLDESCR.symbols_lim], edi
1089
        add     ebx, edx
1090
        movzx   ecx, [edx+COFF_HEADER.nSections]
1091
        lea     ecx, [ecx*5]
1092
        lea     edi, [edi+ecx*8+20]
1093
        add     edx, 20
1094
@@:
1095
        movzx   eax, [edx+COFF_SECTION.NumReloc]
1096
        lea     eax, [eax*5]
1097
        lea     edi, [edi+eax*2]
1098
        add     edx, sizeof.COFF_SECTION
1099
        sub     ecx, 5
1100
        jnz     @b
1101
        stdcall kernel_alloc, edi
1102
        test    eax, eax
1103
        jz      .fail_and_free_data
1104
        mov     edx, [coff]
1105
        movzx   ecx, [edx+COFF_HEADER.nSections]
1106
        lea     ecx, [ecx*5]
1107
        lea     ecx, [ecx*2+5]
1108
        mov     [esi+DLLDESCR.coff_hdr], eax
1109
        push    esi
1110
        mov     esi, edx
1111
        mov     edi, eax
1112
        rep movsd
1113
        pop     esi
1114
        mov     [esi+DLLDESCR.symbols_ptr], edi
1115
        push    esi
1116
        mov     ecx, [edx+COFF_HEADER.nSymbols]
1117
        mov     [esi+DLLDESCR.symbols_num], ecx
1118
        mov     ecx, [esi+DLLDESCR.symbols_lim]
1119
        mov     esi, ebx
1120
        rep movsb
1121
        pop     esi
1122
        mov     ebx, [esi+DLLDESCR.coff_hdr]
1123
        push    esi
1124
        movzx   eax, [edx+COFF_HEADER.nSections]
1125
        lea     edx, [ebx+20]
1126
@@:
1127
        movzx   ecx, [edx+COFF_SECTION.NumReloc]
1128
        lea     ecx, [ecx*5]
1129
        mov     esi, [edx+COFF_SECTION.PtrReloc]
1130
        mov     [edx+COFF_SECTION.PtrReloc], edi
1131
        sub     [edx+COFF_SECTION.PtrReloc], ebx
1132
        add     esi, [coff]
1133
        shr     ecx, 1
1134
        rep movsd
1135
        adc     ecx, ecx
1136
        rep movsw
1137
        add     edx, sizeof.COFF_SECTION
1138
        dec     eax
1139
        jnz     @b
1140
        pop     esi
1141
 
1142
; fixup symbols
1143
        mov     edx, ebx
1144
        mov     eax, [ebx+COFF_HEADER.nSymbols]
1145
        add     edx, 20
1146
        mov     ecx, [esi+DLLDESCR.symbols_num]
1147
        lea     ecx, [ecx*9]
1148
        add     ecx, ecx
1149
        add     ecx, [esi+DLLDESCR.symbols_ptr]
1150
 
1151
        stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
1152
                ecx, 0
1153
;          test eax, eax
1154
;          jnz @F
1155
;
1156
;@@:
1157
 
1158
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
1159
        test    eax, eax
1160
        jnz     @F
1161
 
1162
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
1163
@@:
1164
        mov     [esi+DLLDESCR.exports], eax
1165
 
1166
; fix relocs in the hidden copy in kernel memory to default address
1167
; it is first fix; usually this will be enough, but second fix
1168
; can be necessary if real load address will not equal assumption
1169
        mov     eax, [esi+DLLDESCR.data]
1170
        sub     eax, [esi+DLLDESCR.defaultbase]
1171
        stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
1172
 
1173
        stdcall kernel_free, [coff]
1174
 
1175
        cli
1176
; initialize DLLDESCR struct
1177
        and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
1178
        mov     [esi+DLLDESCR.fd], dll_list
1179
        mov     eax, [dll_list.bk]
1180
        mov     [dll_list.bk], esi
1181
        mov     [esi+DLLDESCR.bk], eax
1182
        mov     [eax+DLLDESCR.fd], esi
1183
.dll_already_loaded:
1184
        inc     [esi+DLLDESCR.refcount]
1185
        push    esi
1186
        call    init_heap
1187
        pop     esi
1188
 
1189
        mov     edi, [esi+DLLDESCR.size]
1190
        stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
1191
        test    eax, eax
1192
        jnz     @f
1193
        stdcall user_alloc, edi
1194
        test    eax, eax
1195
        jz      .fail_and_dereference
1196
@@:
1197
        mov     [img_base], eax
1198
        mov     eax, sizeof.HDLL
1199
        call    malloc
1200
        test    eax, eax
1201
        jz      .fail_and_free_user
1202
        mov     ebx, [CURRENT_TASK]
1203
        shl     ebx, 5
1204
        mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
1205
        mov     [eax+HDLL.pid], edx
1206
        push    eax
1207
        call    init_dlls_in_thread
1208
        pop     ebx
1209
        test    eax, eax
1210
        jz      .fail_and_free_user
1211
        mov     edx, [eax+HDLL.fd]
1212
        mov     [ebx+HDLL.fd], edx
1213
        mov     [ebx+HDLL.bk], eax
1214
        mov     [eax+HDLL.fd], ebx
1215
        mov     [edx+HDLL.bk], ebx
1216
        mov     eax, ebx
1217
        mov     ebx, [img_base]
1218
        mov     [eax+HDLL.base], ebx
1219
        mov     [eax+HDLL.size], edi
1220
        mov     [eax+HDLL.refcount], 1
1221
        mov     [eax+HDLL.parent], esi
1222
        mov     edx, ebx
1223
        shr     edx, 12
1224
        or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
1225
; copy entries of page table from kernel-side image to usermode
1226
; use copy-on-write for user-mode image, so map as readonly
1227
        xor     edi, edi
1228
        mov     ecx, [esi+DLLDESCR.data]
1229
        shr     ecx, 12
1230
.map_pages_loop:
1231
        mov     eax, [page_tabs+ecx*4]
1232
        and     eax, not 0xFFF
1233
        or      al, PG_USER
1234
        xchg    eax, [page_tabs+edx*4]
1235
        test    al, 1
1236
        jz      @f
1237
        call    free_page
1238
@@:
1239
        invlpg  [ebx+edi]
1240
        inc     ecx
1241
        inc     edx
1242
        add     edi, 0x1000
1243
        cmp     edi, [esi+DLLDESCR.size]
1244
        jb      .map_pages_loop
1245
 
1246
; if real user-mode base is not equal to preferred base, relocate image
1247
        sub     ebx, [esi+DLLDESCR.defaultbase]
1248
        jz      @f
1249
        stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
1250
@@:
1251
 
1252
        mov     eax, [esi+DLLDESCR.exports]
1253
        sub     eax, [esi+DLLDESCR.defaultbase]
1254
        add     eax, [img_base]
1255
        sti
1256
        ret
1257
.fail_and_free_data:
1258
        stdcall kernel_free, [esi+DLLDESCR.data]
1259
.fail_and_free_dll:
1260
        mov     eax, esi
1261
        call    free
1262
.fail_and_free_coff:
1263
        stdcall kernel_free, [coff]
1264
.fail:
1265
        xor     eax, eax
1266
        ret
1267
.fail_and_free_user:
1268
        stdcall user_free, [img_base]
1269
.fail_and_dereference:
1270
        mov     eax, 1  ; delete 1 reference
1271
        call    dereference_dll
1272
        sti
1273
        xor     eax, eax
1274
        ret
1275
endp
1276
 
1277
; initialize [APPDATA.dlls_list_ptr] for given thread
1278
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
1279
; kept in sync for all threads of one process.
1280
; out: eax = APPDATA.dlls_list_ptr if all is OK,
1281
; NULL if memory allocation failed
1282
init_dlls_in_thread:
4433 Serge 1283
        mov     ebx, [current_process]
1284
        mov     eax, [ebx+PROC.dlls_list_ptr]
4429 Serge 1285
        test    eax, eax
1286
        jnz     .ret
4433 Serge 1287
 
4429 Serge 1288
        mov     eax, 8
4433 Serge 1289
        call    malloc                               ; FIXME
4429 Serge 1290
        test    eax, eax
1291
        jz      .ret
4433 Serge 1292
 
4429 Serge 1293
        mov     [eax], eax
1294
        mov     [eax+4], eax
4433 Serge 1295
 
1296
        mov     ebx, [current_process]
1297
        mov     [ebx+PROC.dlls_list_ptr], eax
4429 Serge 1298
.ret:
1299
        ret
1300
 
1301
; in: eax = number of references to delete, esi -> DLLDESCR struc
1302
dereference_dll:
1303
        sub     [esi+DLLDESCR.refcount], eax
1304
        jnz     .ret
1305
        mov     eax, [esi+DLLDESCR.fd]
1306
        mov     edx, [esi+DLLDESCR.bk]
1307
        mov     [eax+DLLDESCR.bk], edx
1308
        mov     [edx+DLLDESCR.fd], eax
1309
        stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
1310
        stdcall kernel_free, [esi+DLLDESCR.data]
1311
        mov     eax, esi
1312
        call    free
1313
.ret:
1314
        ret
1315
 
1316
destroy_hdll:
1317
        push    ebx ecx esi edi
1318
        mov     ebx, [eax+HDLL.base]
1319
        mov     esi, [eax+HDLL.parent]
1320
        mov     edx, [esi+DLLDESCR.size]
4459 Serge 1321
 
4429 Serge 1322
        push    eax
1323
        mov     esi, [eax+HDLL.parent]
1324
        mov     eax, [eax+HDLL.refcount]
1325
        call    dereference_dll
1326
        pop     eax
1327
        mov     edx, [eax+HDLL.bk]
1328
        mov     ebx, [eax+HDLL.fd]
1329
        mov     [ebx+HDLL.bk], edx
1330
        mov     [edx+HDLL.fd], ebx
1331
        call    free
1332
        pop     edi esi ecx ebx
1333
        ret
1334
 
1335
; ecx -> APPDATA for slot, esi = dlls_list_ptr
1336
destroy_all_hdlls:
1337
        test    esi, esi
1338
        jz      .ret
1339
.loop:
1340
        mov     eax, [esi+HDLL.fd]
1341
        cmp     eax, esi
1342
        jz      free
1343
        call    destroy_hdll
1344
        jmp     .loop
1345
.ret:
1346
        ret
1347
 
1348
align 4
1349
stop_all_services:
1350
        push    ebp
1351
        mov     edx, [srv.fd]
1352
.next:
1353
        cmp     edx, srv.fd-SRV.fd
1354
        je      .done
1355
        cmp     [edx+SRV.magic], ' SRV'
1356
        jne     .next
1357
        cmp     [edx+SRV.size], sizeof.SRV
1358
        jne     .next
1359
 
1360
        mov     ebx, [edx+SRV.entry]
1361
        mov     edx, [edx+SRV.fd]
1362
        test    ebx, ebx
1363
        jz      .next
1364
 
1365
        push    edx
1366
        mov     ebp, esp
1367
        push    0
1368
        push    -1
1369
        call    ebx
1370
        mov     esp, ebp
1371
        pop     edx
1372
        jmp     .next
1373
.done:
1374
        pop     ebp
1375
        ret
1376
 
1377
; param
1378
;  eax= size
1379
;  ebx= pid
1380
 
1381
align 4
1382
create_kernel_object:
1383
 
1384
        push    ebx
1385
        call    malloc
1386
        pop     ebx
1387
        test    eax, eax
1388
        jz      .fail
1389
 
1390
        mov     ecx, [current_slot]
1391
        add     ecx, APP_OBJ_OFFSET
1392
 
1393
        pushfd
1394
        cli
1395
        mov     edx, [ecx+APPOBJ.fd]
1396
        mov     [eax+APPOBJ.fd], edx
1397
        mov     [eax+APPOBJ.bk], ecx
1398
        mov     [eax+APPOBJ.pid], ebx
1399
 
1400
        mov     [ecx+APPOBJ.fd], eax
1401
        mov     [edx+APPOBJ.bk], eax
1402
        popfd
1403
.fail:
1404
        ret
1405
 
1406
; param
1407
;  eax= object
1408
 
1409
align 4
1410
destroy_kernel_object:
1411
 
1412
        pushfd
1413
        cli
1414
        mov     ebx, [eax+APPOBJ.fd]
1415
        mov     ecx, [eax+APPOBJ.bk]
1416
        mov     [ebx+APPOBJ.bk], ecx
1417
        mov     [ecx+APPOBJ.fd], ebx
1418
        popfd
1419
 
1420
        xor     edx, edx       ;clear common header
1421
        mov     [eax], edx
1422
        mov     [eax+4], edx
1423
        mov     [eax+8], edx
1424
        mov     [eax+12], edx
1425
        mov     [eax+16], edx
1426
 
1427
        call    free           ;release object memory
1428
        ret