Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2455 mario79 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 5039 $
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
 
2384 hidnplayr 142
        cmp     [edi+SRV.size], sizeof.SRV
2288 clevermous 143
        jne     .fail
144
 
3520 clevermous 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
2288 clevermous 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
 
2384 hidnplayr 178
        cmp     [eax+SRV.size], sizeof.SRV
2288 clevermous 179
        jne     .fail
180
 
3520 clevermous 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
2288 clevermous 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
@@:
2384 hidnplayr 207
        cmp     edx, srv.fd-SRV.fd
2288 clevermous 208
        je      .not_load
209
 
210
        stdcall strncmp, edx, [sz_name], 16
211
        test    eax, eax
212
        je      .ok
213
 
214
        mov     edx, [edx+SRV.fd]
215
        jmp     @B
216
.not_load:
4418 clevermous 217
        mov     eax, [sz_name]
218
; Try to load .dll driver first. If not, fallback to .obj.
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
        test    eax, eax
240
        jnz     .nothing
2288 clevermous 241
        pop     ebp
242
        jmp     load_driver
243
.ok:
244
        mov     eax, edx
4418 clevermous 245
.nothing:
2288 clevermous 246
        ret
247
endp
248
 
3520 clevermous 249
reg_service:
250
        xor     eax, eax
251
        mov     ecx, [esp+8]
252
        jecxz   .nothing
253
        push    sizeof.SRV
254
        push    ecx
255
        pushd   [esp+12]
256
        call    reg_service_ex
257
.nothing:
258
        ret     8
2288 clevermous 259
 
3520 clevermous 260
reg_usb_driver:
261
        push    sizeof.USBSRV
262
        pushd   [esp+12]
263
        pushd   [esp+12]
264
        call    reg_service_ex
265
        test    eax, eax
266
        jz      .nothing
267
        mov     ecx, [esp+12]
268
        mov     [eax+USBSRV.usb_func], ecx
269
.nothing:
270
        ret     12
271
 
272
proc reg_service_ex stdcall, name:dword, handler:dword, srvsize:dword
273
 
2288 clevermous 274
        push    ebx
275
 
276
        xor     eax, eax
277
 
278
        cmp     [name], eax
279
        je      .fail
280
 
3520 clevermous 281
;        cmp     [handler], eax
282
;        je      .fail
2288 clevermous 283
 
3520 clevermous 284
        mov     eax, [srvsize]
2288 clevermous 285
        call    malloc
286
        test    eax, eax
287
        jz      .fail
288
 
289
        push    esi
290
        push    edi
291
        mov     edi, eax
292
        mov     esi, [name]
293
        movsd
294
        movsd
295
        movsd
296
        movsd
297
        pop     edi
298
        pop     esi
299
 
300
        mov     [eax+SRV.magic], ' SRV'
2384 hidnplayr 301
        mov     [eax+SRV.size], sizeof.SRV
2288 clevermous 302
 
2384 hidnplayr 303
        mov     ebx, srv.fd-SRV.fd
2288 clevermous 304
        mov     edx, [ebx+SRV.fd]
305
        mov     [eax+SRV.fd], edx
306
        mov     [eax+SRV.bk], ebx
307
        mov     [ebx+SRV.fd], eax
308
        mov     [edx+SRV.bk], eax
309
 
310
        mov     ecx, [handler]
311
        mov     [eax+SRV.srv_proc], ecx
312
        pop     ebx
313
        ret
314
.fail:
315
        xor     eax, eax
316
        pop     ebx
317
        ret
318
endp
319
 
320
align 4
321
proc get_proc stdcall, exp:dword, sz_name:dword
322
 
323
        mov     edx, [exp]
324
.next:
325
        mov     eax, [edx]
326
        test    eax, eax
327
        jz      .end
328
 
329
        push    edx
330
        stdcall strncmp, eax, [sz_name], 16
331
        pop     edx
332
        test    eax, eax
333
        jz      .ok
334
 
335
        add     edx, 8
336
        jmp     .next
337
.ok:
338
        mov     eax, [edx+4]
339
.end:
340
        ret
341
endp
342
 
343
align 4
344
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
345
 
346
@@:
347
        stdcall strncmp, [pSym], [sz_sym], 8
348
        test    eax, eax
349
        jz      .ok
350
        add     [pSym], 18
351
        dec     [count]
352
        jnz     @b
353
        xor     eax, eax
354
        ret
355
.ok:
356
        mov     eax, [pSym]
357
        mov     eax, [eax+8]
358
        ret
359
endp
360
 
361
align 4
362
proc get_curr_task
363
        mov     eax, [CURRENT_TASK]
364
        shl     eax, 8
365
        ret
366
endp
367
 
368
align 4
369
proc get_fileinfo stdcall, file_name:dword, info:dword
370
           locals
371
             cmd     dd ?
372
             offset  dd ?
373
                     dd ?
374
             count   dd ?
375
             buff    dd ?
376
                     db ?
377
             name    dd ?
378
           endl
379
 
380
        xor     eax, eax
381
        mov     ebx, [file_name]
382
        mov     ecx, [info]
383
 
384
        mov     [cmd], 5
385
        mov     [offset], eax
386
        mov     [offset+4], eax
387
        mov     [count], eax
388
        mov     [buff], ecx
389
        mov     byte [buff+4], al
390
        mov     [name], ebx
391
 
392
        mov     eax, 70
393
        lea     ebx, [cmd]
394
        int     0x40
395
        ret
396
endp
397
 
398
align 4
399
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
400
                                     bytes:dword
401
           locals
402
             cmd     dd ?
403
             offset  dd ?
404
                     dd ?
405
             count   dd ?
406
             buff    dd ?
407
                     db ?
408
             name    dd ?
409
           endl
410
 
411
        xor     eax, eax
412
        mov     ebx, [file_name]
413
        mov     ecx, [off]
414
        mov     edx, [bytes]
415
        mov     esi, [buffer]
416
 
417
        mov     [cmd], eax
418
        mov     [offset], ecx
419
        mov     [offset+4], eax
420
        mov     [count], edx
421
        mov     [buff], esi
422
        mov     byte [buff+4], al
423
        mov     [name], ebx
424
 
425
        pushad
426
        lea     ebx, [cmd]
3296 clevermous 427
        call    file_system_lfn_protected
2288 clevermous 428
        popad
429
        ret
430
endp
431
 
432
; description
433
;  allocate kernel memory and loads the specified file
434
;
435
; param
3786 Serge 436
;  file_name= path to file
2288 clevermous 437
;
438
; retval
439
;  eax= file image in kernel memory
440
;  ebx= size of file
441
;
442
; warging
443
;  You mast call kernel_free() to delete each file
444
;  loaded by the load_file() function
445
 
446
align 4
447
proc load_file stdcall, file_name:dword
448
           locals
449
             attr       dd ?
450
             flags      dd ?
451
             cr_time    dd ?
452
             cr_date    dd ?
453
             acc_time   dd ?
454
             acc_date   dd ?
455
             mod_time   dd ?
456
             mod_date   dd ?
457
             file_size  dd ?
458
 
459
             file       dd ?
460
             file2      dd ?
461
           endl
462
 
463
        push    esi
464
        push    edi
465
 
466
        lea     eax, [attr]
467
        stdcall get_fileinfo, [file_name], eax
468
        test    eax, eax
469
        jnz     .fail
470
 
471
        mov     eax, [file_size]
472
        cmp     eax, 1024*1024*16
473
        ja      .fail
474
 
475
        stdcall kernel_alloc, [file_size]
476
        mov     [file], eax
477
        test    eax, eax
478
        jz      .fail
479
 
480
        stdcall read_file, [file_name], eax, dword 0, [file_size]
481
        cmp     ebx, [file_size]
482
        jne     .cleanup
483
 
484
        mov     eax, [file]
485
        cmp     dword [eax], 0x4B43504B
486
        jne     .exit
487
        mov     ebx, [eax+4]
488
        mov     [file_size], ebx
489
        stdcall kernel_alloc, ebx
490
 
491
        test    eax, eax
492
        jz      .cleanup
493
 
494
        mov     [file2], eax
2486 mario79 495
 
2500 mario79 496
        pushad
2489 mario79 497
        mov     ecx, unpack_mutex
498
        call    mutex_lock
2500 mario79 499
        popad
2486 mario79 500
 
2288 clevermous 501
        stdcall unpack, [file], eax
2486 mario79 502
 
2500 mario79 503
        pushad
504
        mov     ecx, unpack_mutex
2489 mario79 505
        call    mutex_unlock
2500 mario79 506
        popad
2486 mario79 507
 
2288 clevermous 508
        stdcall kernel_free, [file]
509
        mov     eax, [file2]
510
        mov     ebx, [file_size]
511
.exit:
512
        push    eax
513
        lea     edi, [eax+ebx]    ;cleanup remain space
514
        mov     ecx, 4096         ;from file end
515
        and     ebx, 4095
516
        jz      @f
517
        sub     ecx, ebx
518
        xor     eax, eax
519
        cld
520
        rep stosb
521
@@:
522
        mov     ebx, [file_size]
523
        pop     eax
524
        pop     edi
525
        pop     esi
526
        ret
527
.cleanup:
528
        stdcall kernel_free, [file]
529
.fail:
530
        xor     eax, eax
531
        xor     ebx, ebx
532
        pop     edi
533
        pop     esi
534
        ret
535
endp
536
 
3786 Serge 537
; description
538
;  allocate user memory and loads the specified file
539
;
540
; param
541
;  file_name= path to file
542
;
543
; retval
544
;  eax= file image in user memory
545
;  ebx= size of file
546
;
547
; warging
548
;  You mast call kernel_free() to delete each file
549
;  loaded by the load_file() function
550
 
551
align 4
552
proc load_file_umode stdcall, file_name:dword
553
           locals
554
             attr       dd ?
555
             flags      dd ?
556
             cr_time    dd ?
557
             cr_date    dd ?
558
             acc_time   dd ?
559
             acc_date   dd ?
560
             mod_time   dd ?
561
             mod_date   dd ?
562
             file_size  dd ?
563
 
564
             km_file    dd ?
565
             um_file    dd ?
566
           endl
567
 
568
        push    esi
569
        push    edi
570
        push    ebx
571
 
572
        lea     eax, [attr]
573
        stdcall get_fileinfo, [file_name], eax   ;find file and get info
574
        test    eax, eax
575
        jnz     .err_1
576
 
577
        mov     eax, [file_size]
578
        cmp     eax, 1024*1024*16                ;to be enough for anybody (c)
579
        ja      .err_1
580
                                                 ;it is very likely that the file is packed
581
        stdcall kernel_alloc, [file_size]        ;with kpack, so allocate memory from kernel heap
582
        mov     [km_file], eax
583
        test    eax, eax
584
        jz      .err_1
585
 
586
        stdcall read_file, [file_name], eax, dword 0, [file_size]
587
        cmp     ebx, [file_size]
588
 
589
        jne     .err_2
590
 
591
        mov     eax, [km_file]
592
        cmp     dword [eax], 0x4B43504B          ; check kpack signature
593
        jne     .raw_file
594
 
595
        mov     ebx, [eax+4]                     ;get real size of file
596
        mov     [file_size], ebx
4237 Serge 597
        stdcall user_alloc, ebx                  ;and allocate space from user heap
3786 Serge 598
        mov     [um_file], eax
599
        test    eax, eax
600
        jz      .err_2
601
 
4237 Serge 602
        mov     edx, [file_size]                 ;preallocate page memory
603
        shr     eax, 10
604
        lea     edi, [page_tabs+eax]
605
        add     edx, 4095
606
        shr     edx, 12
607
@@:
608
        call    alloc_page
609
        test    eax, eax
610
        jz      .err_3
611
 
612
        or      eax, PG_UW
613
        stosd
614
        dec     edx
615
        jnz     @B
616
 
3786 Serge 617
        pushad
618
        mov     ecx, unpack_mutex
619
        call    mutex_lock
620
 
621
        stdcall unpack, [km_file], [um_file]
622
 
623
        mov     ecx, unpack_mutex
624
        call    mutex_unlock
625
        popad
626
 
627
        stdcall kernel_free, [km_file]           ;we don't need packed file anymore
628
.exit:
4237 Serge 629
 
630
        mov     edi, [um_file]
631
        mov     esi, [um_file]
632
        mov     eax, [file_size]
633
        mov     edx, eax
634
 
635
        add     edi, eax                         ;cleanup remain space
636
        mov     ecx, 4096                        ;from file end
637
        and     eax, 4095
638
        jz      @f
639
        sub     ecx, eax
640
        xor     eax, eax
641
        cld
642
        rep stosb
643
@@:
3786 Serge 644
        mov     eax, [um_file]
645
 
646
        pop     ebx
647
        pop     edi
648
        pop     esi
649
        ret
650
 
651
.raw_file:                                       ; sometimes we load unpacked file
652
        stdcall user_alloc, ebx                  ; allocate space from user heap
653
        mov     [um_file], eax
654
 
655
        test    eax, eax
656
        jz      .err_2
657
 
658
        shr     eax, 10                          ; and remap pages.
659
 
660
        mov     ecx, [file_size]
661
        add     ecx, 4095
662
        shr     ecx, 12
663
 
664
        mov     esi, [km_file]
665
        shr     esi, 10
666
        add     esi, page_tabs
667
 
668
        lea     edi, [page_tabs+eax]
669
 
670
        cld
671
@@:
672
        lodsd
673
        and     eax, 0xFFFFF000
4237 Serge 674
        or      eax, PG_UW
3786 Serge 675
        stosd
676
        loop    @B
677
 
678
        stdcall free_kernel_space, [km_file]     ; release allocated kernel space
679
        jmp     .exit                            ; physical pages still in use
4237 Serge 680
.err_3:
681
        stdcall user_free, [um_file]
3786 Serge 682
.err_2:
683
        stdcall kernel_free, [km_file]
684
.err_1:
685
        xor     eax, eax
686
        xor     edx, edx
687
 
688
        pop     ebx
689
        pop     edi
690
        pop     esi
691
        ret
692
endp
693
 
694
 
2489 mario79 695
uglobal
2288 clevermous 696
align 4
2489 mario79 697
unpack_mutex MUTEX
2486 mario79 698
endg
699
 
700
align 4
3761 clevermous 701
proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
702
        mov     ebx, [imports]
703
        test    ebx, ebx
704
        jz      .end
705
        xor     esi, esi
2288 clevermous 706
.look_up:
707
 
3761 clevermous 708
        mov     eax, [ebx+32]
709
        mov     eax, [OS_BASE+eax+esi*4]
710
        add     eax, OS_BASE
2288 clevermous 711
        stdcall strncmp, eax, [proc_name], 256
712
        test    eax, eax
713
        jz      .ok
714
 
3761 clevermous 715
        inc     esi
716
        cmp     esi, [ebx+24]
717
        jb      .look_up
2288 clevermous 718
.end:
719
        xor     eax, eax
720
        ret
3761 clevermous 721
.ok:
722
        mov     eax, [ebx+28]
723
        mov     eax, [OS_BASE+eax+esi*4]
724
        add     eax, OS_BASE
725
        ret
2288 clevermous 726
endp
727
 
728
align 4
729
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
730
                      sym_count:dword, strings:dword, imports:dword
731
           locals
732
             retval dd ?
733
           endl
734
 
735
        mov     edi, [symbols]
736
        mov     [retval], 1
737
.fix:
2384 hidnplayr 738
        movzx   ebx, [edi+COFF_SYM.SectionNumber]
2288 clevermous 739
        test    ebx, ebx
740
        jnz     .internal
2384 hidnplayr 741
        mov     eax, dword [edi+COFF_SYM.Name]
2288 clevermous 742
        test    eax, eax
743
        jnz     @F
744
 
745
        mov     edi, [edi+4]
746
        add     edi, [strings]
747
@@:
748
        push    edi
749
        stdcall get_proc_ex, edi, [imports]
750
        pop     edi
751
 
752
        xor     ebx, ebx
753
        test    eax, eax
754
        jnz     @F
755
 
756
        mov     esi, msg_unresolved
757
        call    sys_msg_board_str
758
        mov     esi, edi
759
        call    sys_msg_board_str
760
        mov     esi, msg_CR
761
        call    sys_msg_board_str
762
 
763
        mov     [retval], 0
764
@@:
765
        mov     edi, [symbols]
2384 hidnplayr 766
        mov     [edi+COFF_SYM.Value], eax
2288 clevermous 767
        jmp     .next
768
.internal:
769
        cmp     bx, -1
770
        je      .next
771
        cmp     bx, -2
772
        je      .next
773
 
774
        dec     ebx
775
        shl     ebx, 3
776
        lea     ebx, [ebx+ebx*4]
777
        add     ebx, [sec]
778
 
2384 hidnplayr 779
        mov     eax, [ebx+COFF_SECTION.VirtualAddress]
780
        add     [edi+COFF_SYM.Value], eax
2288 clevermous 781
.next:
2384 hidnplayr 782
        add     edi, sizeof.COFF_SYM
2288 clevermous 783
        mov     [symbols], edi
784
        dec     [sym_count]
785
        jnz     .fix
786
        mov     eax, [retval]
787
        ret
788
endp
789
 
790
align 4
791
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
792
        delta:dword
793
           locals
794
             n_sec     dd ?
795
           endl
796
 
797
        mov     eax, [coff]
2384 hidnplayr 798
        movzx   ebx, [eax+COFF_HEADER.nSections]
2288 clevermous 799
        mov     [n_sec], ebx
800
        lea     esi, [eax+20]
801
.fix_sec:
2384 hidnplayr 802
        mov     edi, [esi+COFF_SECTION.PtrReloc]
2288 clevermous 803
        add     edi, [coff]
804
 
2384 hidnplayr 805
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
2288 clevermous 806
        test    ecx, ecx
807
        jz      .next
808
.reloc_loop:
2384 hidnplayr 809
        mov     ebx, [edi+COFF_RELOC.SymIndex]
2288 clevermous 810
        add     ebx, ebx
811
        lea     ebx, [ebx+ebx*8]
812
        add     ebx, [sym]
813
 
2384 hidnplayr 814
        mov     edx, [ebx+COFF_SYM.Value]
2288 clevermous 815
 
2384 hidnplayr 816
        cmp     [edi+COFF_RELOC.Type], 6
2288 clevermous 817
        je      .dir_32
818
 
2384 hidnplayr 819
        cmp     [edi+COFF_RELOC.Type], 20
2288 clevermous 820
        jne     .next_reloc
821
.rel_32:
2384 hidnplayr 822
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
823
        add     eax, [esi+COFF_SECTION.VirtualAddress]
2288 clevermous 824
        sub     edx, eax
825
        sub     edx, 4
826
        jmp     .fix
827
.dir_32:
2384 hidnplayr 828
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
829
        add     eax, [esi+COFF_SECTION.VirtualAddress]
2288 clevermous 830
.fix:
831
        add     eax, [delta]
832
        add     [eax], edx
833
.next_reloc:
834
        add     edi, 10
835
        dec     ecx
836
        jnz     .reloc_loop
837
.next:
2384 hidnplayr 838
        add     esi, sizeof.COFF_SECTION
2288 clevermous 839
        dec     [n_sec]
840
        jnz     .fix_sec
841
.exit:
842
        ret
843
endp
844
 
845
align 4
846
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
847
        delta:dword
848
           locals
849
             n_sec     dd ?
850
           endl
851
 
852
        mov     eax, [coff]
2384 hidnplayr 853
        movzx   ebx, [eax+COFF_HEADER.nSections]
2288 clevermous 854
        mov     [n_sec], ebx
855
        lea     esi, [eax+20]
856
        mov     edx, [delta]
857
.fix_sec:
2384 hidnplayr 858
        mov     edi, [esi+COFF_SECTION.PtrReloc]
2288 clevermous 859
        add     edi, [coff]
860
 
2384 hidnplayr 861
        movzx   ecx, [esi+COFF_SECTION.NumReloc]
2288 clevermous 862
        test    ecx, ecx
863
        jz      .next
864
.reloc_loop:
2384 hidnplayr 865
        cmp     [edi+COFF_RELOC.Type], 6
2288 clevermous 866
        jne     .next_reloc
867
.dir_32:
2384 hidnplayr 868
        mov     eax, [edi+COFF_RELOC.VirtualAddress]
869
        add     eax, [esi+COFF_SECTION.VirtualAddress]
2288 clevermous 870
        add     [eax+edx], edx
871
.next_reloc:
872
        add     edi, 10
873
        dec     ecx
874
        jnz     .reloc_loop
875
.next:
2384 hidnplayr 876
        add     esi, sizeof.COFF_SECTION
2288 clevermous 877
        dec     [n_sec]
878
        jnz     .fix_sec
879
.exit:
880
        ret
881
endp
882
 
883
align 4
884
proc load_driver stdcall, driver_name:dword
885
           locals
886
             coff      dd ?
887
             sym       dd ?
888
             strings   dd ?
889
             img_size  dd ?
890
             img_base  dd ?
891
             start     dd ?
892
 
893
             file_name rb 13+16+4+1      ; '/sys/drivers/.obj'
894
           endl
895
 
896
        lea     edx, [file_name]
897
        mov     dword [edx], '/sys'
898
        mov     dword [edx+4], '/dri'
899
        mov     dword [edx+8], 'vers'
900
        mov     byte [edx+12], '/'
901
        mov     esi, [driver_name]
902
.redo:
903
        lea     edx, [file_name]
904
        lea     edi, [edx+13]
905
        mov     ecx, 16
906
@@:
907
        lodsb
908
        test    al, al
909
        jz      @f
910
        stosb
911
        loop    @b
912
@@:
913
        mov     dword [edi], '.obj'
914
        mov     byte [edi+4], 0
915
        stdcall load_file, edx
916
 
917
        test    eax, eax
918
        jz      .exit
919
 
5039 clevermous 920
        lea     edx, [file_name]
921
        DEBUGF 1,'K : driver %s is COFF, deprecated\n',edx
2288 clevermous 922
        mov     [coff], eax
923
 
2384 hidnplayr 924
        movzx   ecx, [eax+COFF_HEADER.nSections]
2288 clevermous 925
        xor     ebx, ebx
926
 
927
        lea     edx, [eax+20]
928
@@:
2384 hidnplayr 929
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
2288 clevermous 930
        add     ebx, 15
931
        and     ebx, not 15
2384 hidnplayr 932
        add     edx, sizeof.COFF_SECTION
2288 clevermous 933
        dec     ecx
934
        jnz     @B
935
        mov     [img_size], ebx
936
 
937
        stdcall kernel_alloc, ebx
938
        test    eax, eax
939
        jz      .fail
940
        mov     [img_base], eax
941
 
942
        mov     edi, eax
943
        xor     eax, eax
944
        mov     ecx, [img_size]
945
        add     ecx, 4095
946
        and     ecx, not 4095
947
        shr     ecx, 2
948
        cld
949
        rep stosd
950
 
951
        mov     edx, [coff]
2384 hidnplayr 952
        movzx   ebx, [edx+COFF_HEADER.nSections]
2288 clevermous 953
        mov     edi, [img_base]
954
        lea     eax, [edx+20]
955
@@:
2384 hidnplayr 956
        mov     [eax+COFF_SECTION.VirtualAddress], edi
957
        mov     esi, [eax+COFF_SECTION.PtrRawData]
2288 clevermous 958
        test    esi, esi
959
        jnz     .copy
2384 hidnplayr 960
        add     edi, [eax+COFF_SECTION.SizeOfRawData]
2288 clevermous 961
        jmp     .next
962
.copy:
963
        add     esi, edx
2384 hidnplayr 964
        mov     ecx, [eax+COFF_SECTION.SizeOfRawData]
2288 clevermous 965
        cld
966
        rep movsb
967
.next:
968
        add     edi, 15
969
        and     edi, not 15
2384 hidnplayr 970
        add     eax, sizeof.COFF_SECTION
2288 clevermous 971
        dec     ebx
972
        jnz     @B
973
 
2384 hidnplayr 974
        mov     ebx, [edx+COFF_HEADER.pSymTable]
2288 clevermous 975
        add     ebx, edx
976
        mov     [sym], ebx
2384 hidnplayr 977
        mov     ecx, [edx+COFF_HEADER.nSymbols]
2288 clevermous 978
        add     ecx, ecx
979
        lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
980
        add     ecx, [sym]
981
        mov     [strings], ecx
982
 
983
        lea     eax, [edx+20]
984
 
2384 hidnplayr 985
        stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
3761 clevermous 986
                [strings], __exports
2288 clevermous 987
        test    eax, eax
988
        jz      .link_fail
989
 
990
        mov     ebx, [coff]
991
        stdcall fix_coff_relocs, ebx, [sym], 0
992
 
2384 hidnplayr 993
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
2288 clevermous 994
        test    eax, eax
995
        jz      .link_fail
996
 
997
        mov     eax, [eax]
998
        shr     eax, 16
999
        cmp     eax, DRV_COMPAT
1000
        jb      .ver_fail
1001
 
1002
        cmp     eax, DRV_CURRENT
1003
        ja      .ver_fail
1004
 
1005
        mov     ebx, [coff]
2384 hidnplayr 1006
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
2288 clevermous 1007
        mov     [start], eax
1008
 
1009
        stdcall kernel_free, [coff]
1010
 
1011
        mov     ebx, [start]
1012
        stdcall ebx, DRV_ENTRY
1013
        test    eax, eax
1014
        jnz     .ok
1015
 
1016
        stdcall kernel_free, [img_base]
3171 hidnplayr 1017
 
2288 clevermous 1018
        xor     eax, eax
1019
        ret
1020
.ok:
1021
        mov     ebx, [img_base]
1022
        mov     [eax+SRV.base], ebx
1023
        mov     ecx, [start]
1024
        mov     [eax+SRV.entry], ecx
1025
        ret
1026
 
1027
.ver_fail:
1028
        mov     esi, msg_CR
1029
        call    sys_msg_board_str
1030
        mov     esi, [driver_name]
1031
        call    sys_msg_board_str
1032
        mov     esi, msg_CR
1033
        call    sys_msg_board_str
1034
        mov     esi, msg_version
1035
        call    sys_msg_board_str
1036
        mov     esi, msg_www
1037
        call    sys_msg_board_str
1038
        jmp     .cleanup
1039
 
1040
.link_fail:
1041
        mov     esi, msg_module
1042
        call    sys_msg_board_str
1043
        mov     esi, [driver_name]
1044
        call    sys_msg_board_str
1045
        mov     esi, msg_CR
1046
        call    sys_msg_board_str
1047
.cleanup:
1048
        stdcall kernel_free, [img_base]
1049
.fail:
1050
        stdcall kernel_free, [coff]
1051
.exit:
1052
        xor     eax, eax
1053
        ret
1054
endp
1055
 
1056
; in: edx -> COFF_SECTION struct
1057
; out: eax = alignment as mask for bits to drop
1058
coff_get_align:
1059
; Rules:
1060
; - if alignment is not given, use default = 4K;
1061
; - if alignment is given and is no more than 4K, use it;
1062
; - if alignment is more than 4K, revert to 4K.
1063
        push    ecx
2384 hidnplayr 1064
        mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
2288 clevermous 1065
        mov     eax, 1
1066
        shr     cl, 4
1067
        dec     cl
1068
        js      .default
1069
        cmp     cl, 12
1070
        jbe     @f
1071
.default:
1072
        mov     cl, 12
1073
@@:
1074
        shl     eax, cl
1075
        pop     ecx
1076
        dec     eax
1077
        ret
1078
 
1079
align 4
1080
proc load_library stdcall, file_name:dword
1081
           locals
1082
             fullname  rb 260
1083
             fileinfo  rb 40
1084
             coff      dd ?
1085
             img_base  dd ?
1086
           endl
1087
 
1088
; resolve file name
1089
        mov     ebx, [file_name]
1090
        lea     edi, [fullname+1]
1091
        mov     byte [edi-1], '/'
1092
        stdcall get_full_file_name, edi, 259
1093
        test    al, al
1094
        jz      .fail
1095
 
1096
; scan for required DLL in list of already loaded for this process,
1097
; ignore timestamp
3827 clevermous 1098
        cli
1099
 
2288 clevermous 1100
        mov     esi, [CURRENT_TASK]
1101
        shl     esi, 8
1102
        lea     edi, [fullname]
1103
        mov     ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
1104
        test    ebx, ebx
1105
        jz      .not_in_process
1106
        mov     esi, [ebx+HDLL.fd]
1107
.scan_in_process:
1108
        cmp     esi, ebx
1109
        jz      .not_in_process
1110
        mov     eax, [esi+HDLL.parent]
1111
        add     eax, DLLDESCR.name
1112
        stdcall strncmp, eax, edi, -1
1113
        test    eax, eax
1114
        jnz     .next_in_process
1115
; simple variant: load DLL which is already loaded in this process
1116
; just increment reference counters and return address of exports table
1117
        inc     [esi+HDLL.refcount]
1118
        mov     ecx, [esi+HDLL.parent]
1119
        inc     [ecx+DLLDESCR.refcount]
1120
        mov     eax, [ecx+DLLDESCR.exports]
1121
        sub     eax, [ecx+DLLDESCR.defaultbase]
1122
        add     eax, [esi+HDLL.base]
3827 clevermous 1123
        sti
2288 clevermous 1124
        ret
1125
.next_in_process:
1126
        mov     esi, [esi+HDLL.fd]
1127
        jmp     .scan_in_process
1128
.not_in_process:
1129
 
1130
; scan in full list, compare timestamp
3827 clevermous 1131
        sti
2288 clevermous 1132
        lea     eax, [fileinfo]
1133
        stdcall get_fileinfo, edi, eax
1134
        test    eax, eax
1135
        jnz     .fail
3827 clevermous 1136
        cli
2288 clevermous 1137
        mov     esi, [dll_list.fd]
1138
.scan_for_dlls:
1139
        cmp     esi, dll_list
1140
        jz      .load_new
1141
        lea     eax, [esi+DLLDESCR.name]
1142
        stdcall strncmp, eax, edi, -1
1143
        test    eax, eax
1144
        jnz     .continue_scan
1145
.test_prev_dll:
1146
        mov     eax, dword [fileinfo+24]; last modified time
1147
        mov     edx, dword [fileinfo+28]; last modified date
1148
        cmp     dword [esi+DLLDESCR.timestamp], eax
1149
        jnz     .continue_scan
1150
        cmp     dword [esi+DLLDESCR.timestamp+4], edx
1151
        jz      .dll_already_loaded
1152
.continue_scan:
1153
        mov     esi, [esi+DLLDESCR.fd]
1154
        jmp     .scan_for_dlls
1155
 
1156
; new DLL
1157
.load_new:
3827 clevermous 1158
        sti
2288 clevermous 1159
; load file
1160
        stdcall load_file, edi
1161
        test    eax, eax
1162
        jz      .fail
1163
        mov     [coff], eax
1164
        mov     dword [fileinfo+32], ebx
1165
 
1166
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
1167
        mov     esi, edi
1168
        mov     ecx, -1
1169
        xor     eax, eax
1170
        repnz scasb
1171
        not     ecx
2384 hidnplayr 1172
        lea     eax, [ecx+sizeof.DLLDESCR]
2288 clevermous 1173
        push    ecx
1174
        call    malloc
1175
        pop     ecx
1176
        test    eax, eax
1177
        jz      .fail_and_free_coff
1178
; save timestamp
1179
        lea     edi, [eax+DLLDESCR.name]
1180
        rep movsb
1181
        mov     esi, eax
1182
        mov     eax, dword [fileinfo+24]
1183
        mov     dword [esi+DLLDESCR.timestamp], eax
1184
        mov     eax, dword [fileinfo+28]
1185
        mov     dword [esi+DLLDESCR.timestamp+4], eax
1186
 
1187
; calculate size of loaded DLL
1188
        mov     edx, [coff]
2384 hidnplayr 1189
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1190
        xor     ebx, ebx
1191
 
1192
        add     edx, 20
1193
@@:
1194
        call    coff_get_align
1195
        add     ebx, eax
1196
        not     eax
1197
        and     ebx, eax
2384 hidnplayr 1198
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
1199
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1200
        dec     ecx
1201
        jnz     @B
1202
; it must be nonzero and not too big
1203
        mov     [esi+DLLDESCR.size], ebx
1204
        test    ebx, ebx
1205
        jz      .fail_and_free_dll
1206
        cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
1207
        ja      .fail_and_free_dll
1208
; allocate memory for kernel-side image
1209
        stdcall kernel_alloc, ebx
1210
        test    eax, eax
1211
        jz      .fail_and_free_dll
1212
        mov     [esi+DLLDESCR.data], eax
1213
; calculate preferred base address
1214
        add     ebx, 0x1FFF
1215
        and     ebx, not 0xFFF
1216
        mov     ecx, [dll_cur_addr]
1217
        lea     edx, [ecx+ebx]
1218
        cmp     edx, MAX_DEFAULT_DLL_ADDR
1219
        jb      @f
1220
        mov     ecx, MIN_DEFAULT_DLL_ADDR
1221
        lea     edx, [ecx+ebx]
1222
@@:
1223
        mov     [esi+DLLDESCR.defaultbase], ecx
1224
        mov     [dll_cur_addr], edx
1225
 
1226
; copy sections and set correct values for VirtualAddress'es in headers
1227
        push    esi
1228
        mov     edx, [coff]
2384 hidnplayr 1229
        movzx   ebx, [edx+COFF_HEADER.nSections]
2288 clevermous 1230
        mov     edi, eax
1231
        add     edx, 20
1232
        cld
1233
@@:
1234
        call    coff_get_align
1235
        add     ecx, eax
1236
        add     edi, eax
1237
        not     eax
1238
        and     ecx, eax
1239
        and     edi, eax
2384 hidnplayr 1240
        mov     [edx+COFF_SECTION.VirtualAddress], ecx
1241
        add     ecx, [edx+COFF_SECTION.SizeOfRawData]
1242
        mov     esi, [edx+COFF_SECTION.PtrRawData]
2288 clevermous 1243
        push    ecx
2384 hidnplayr 1244
        mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
2288 clevermous 1245
        test    esi, esi
1246
        jnz     .copy
1247
        xor     eax, eax
1248
        rep stosb
1249
        jmp     .next
1250
.copy:
1251
        add     esi, [coff]
1252
        rep movsb
1253
.next:
1254
        pop     ecx
2384 hidnplayr 1255
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1256
        dec     ebx
1257
        jnz     @B
1258
        pop     esi
1259
 
1260
; save some additional data from COFF file
1261
; later we will use COFF header, headers for sections and symbol table
1262
; and also relocations table for all sections
1263
        mov     edx, [coff]
2384 hidnplayr 1264
        mov     ebx, [edx+COFF_HEADER.pSymTable]
2288 clevermous 1265
        mov     edi, dword [fileinfo+32]
1266
        sub     edi, ebx
1267
        jc      .fail_and_free_data
1268
        mov     [esi+DLLDESCR.symbols_lim], edi
1269
        add     ebx, edx
2384 hidnplayr 1270
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1271
        lea     ecx, [ecx*5]
1272
        lea     edi, [edi+ecx*8+20]
1273
        add     edx, 20
1274
@@:
2384 hidnplayr 1275
        movzx   eax, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1276
        lea     eax, [eax*5]
1277
        lea     edi, [edi+eax*2]
2384 hidnplayr 1278
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1279
        sub     ecx, 5
1280
        jnz     @b
1281
        stdcall kernel_alloc, edi
1282
        test    eax, eax
1283
        jz      .fail_and_free_data
1284
        mov     edx, [coff]
2384 hidnplayr 1285
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1286
        lea     ecx, [ecx*5]
1287
        lea     ecx, [ecx*2+5]
1288
        mov     [esi+DLLDESCR.coff_hdr], eax
1289
        push    esi
1290
        mov     esi, edx
1291
        mov     edi, eax
1292
        rep movsd
1293
        pop     esi
1294
        mov     [esi+DLLDESCR.symbols_ptr], edi
1295
        push    esi
2384 hidnplayr 1296
        mov     ecx, [edx+COFF_HEADER.nSymbols]
2288 clevermous 1297
        mov     [esi+DLLDESCR.symbols_num], ecx
1298
        mov     ecx, [esi+DLLDESCR.symbols_lim]
1299
        mov     esi, ebx
1300
        rep movsb
1301
        pop     esi
1302
        mov     ebx, [esi+DLLDESCR.coff_hdr]
1303
        push    esi
2384 hidnplayr 1304
        movzx   eax, [edx+COFF_HEADER.nSections]
2288 clevermous 1305
        lea     edx, [ebx+20]
1306
@@:
2384 hidnplayr 1307
        movzx   ecx, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1308
        lea     ecx, [ecx*5]
2384 hidnplayr 1309
        mov     esi, [edx+COFF_SECTION.PtrReloc]
1310
        mov     [edx+COFF_SECTION.PtrReloc], edi
1311
        sub     [edx+COFF_SECTION.PtrReloc], ebx
2288 clevermous 1312
        add     esi, [coff]
1313
        shr     ecx, 1
1314
        rep movsd
1315
        adc     ecx, ecx
1316
        rep movsw
2384 hidnplayr 1317
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1318
        dec     eax
1319
        jnz     @b
1320
        pop     esi
1321
 
1322
; fixup symbols
1323
        mov     edx, ebx
2384 hidnplayr 1324
        mov     eax, [ebx+COFF_HEADER.nSymbols]
2288 clevermous 1325
        add     edx, 20
1326
        mov     ecx, [esi+DLLDESCR.symbols_num]
1327
        lea     ecx, [ecx*9]
1328
        add     ecx, ecx
1329
        add     ecx, [esi+DLLDESCR.symbols_ptr]
1330
 
1331
        stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
1332
                ecx, 0
1333
;          test eax, eax
1334
;          jnz @F
1335
;
1336
;@@:
1337
 
2384 hidnplayr 1338
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
2288 clevermous 1339
        test    eax, eax
1340
        jnz     @F
1341
 
2384 hidnplayr 1342
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
2288 clevermous 1343
@@:
1344
        mov     [esi+DLLDESCR.exports], eax
1345
 
1346
; fix relocs in the hidden copy in kernel memory to default address
1347
; it is first fix; usually this will be enough, but second fix
1348
; can be necessary if real load address will not equal assumption
1349
        mov     eax, [esi+DLLDESCR.data]
1350
        sub     eax, [esi+DLLDESCR.defaultbase]
1351
        stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
1352
 
1353
        stdcall kernel_free, [coff]
1354
 
3827 clevermous 1355
        cli
1356
; initialize DLLDESCR struct
1357
        and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
1358
        mov     [esi+DLLDESCR.fd], dll_list
1359
        mov     eax, [dll_list.bk]
1360
        mov     [dll_list.bk], esi
1361
        mov     [esi+DLLDESCR.bk], eax
1362
        mov     [eax+DLLDESCR.fd], esi
2288 clevermous 1363
.dll_already_loaded:
1364
        inc     [esi+DLLDESCR.refcount]
1365
        push    esi
1366
        call    init_heap
1367
        pop     esi
1368
 
1369
        mov     edi, [esi+DLLDESCR.size]
1370
        stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
1371
        test    eax, eax
1372
        jnz     @f
1373
        stdcall user_alloc, edi
1374
        test    eax, eax
1375
        jz      .fail_and_dereference
1376
@@:
1377
        mov     [img_base], eax
2384 hidnplayr 1378
        mov     eax, sizeof.HDLL
2288 clevermous 1379
        call    malloc
1380
        test    eax, eax
1381
        jz      .fail_and_free_user
1382
        mov     ebx, [CURRENT_TASK]
1383
        shl     ebx, 5
1384
        mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
1385
        mov     [eax+HDLL.pid], edx
1386
        push    eax
1387
        call    init_dlls_in_thread
1388
        pop     ebx
1389
        test    eax, eax
1390
        jz      .fail_and_free_user
1391
        mov     edx, [eax+HDLL.fd]
1392
        mov     [ebx+HDLL.fd], edx
1393
        mov     [ebx+HDLL.bk], eax
1394
        mov     [eax+HDLL.fd], ebx
1395
        mov     [edx+HDLL.bk], ebx
1396
        mov     eax, ebx
1397
        mov     ebx, [img_base]
1398
        mov     [eax+HDLL.base], ebx
1399
        mov     [eax+HDLL.size], edi
1400
        mov     [eax+HDLL.refcount], 1
1401
        mov     [eax+HDLL.parent], esi
1402
        mov     edx, ebx
1403
        shr     edx, 12
1404
        or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
1405
; copy entries of page table from kernel-side image to usermode
1406
; use copy-on-write for user-mode image, so map as readonly
1407
        xor     edi, edi
1408
        mov     ecx, [esi+DLLDESCR.data]
1409
        shr     ecx, 12
1410
.map_pages_loop:
1411
        mov     eax, [page_tabs+ecx*4]
1412
        and     eax, not 0xFFF
1413
        or      al, PG_USER
1414
        xchg    eax, [page_tabs+edx*4]
1415
        test    al, 1
1416
        jz      @f
1417
        call    free_page
1418
@@:
1419
        invlpg  [ebx+edi]
1420
        inc     ecx
1421
        inc     edx
1422
        add     edi, 0x1000
1423
        cmp     edi, [esi+DLLDESCR.size]
1424
        jb      .map_pages_loop
1425
 
1426
; if real user-mode base is not equal to preferred base, relocate image
1427
        sub     ebx, [esi+DLLDESCR.defaultbase]
1428
        jz      @f
1429
        stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
1430
@@:
1431
 
1432
        mov     eax, [esi+DLLDESCR.exports]
1433
        sub     eax, [esi+DLLDESCR.defaultbase]
1434
        add     eax, [img_base]
3827 clevermous 1435
        sti
2288 clevermous 1436
        ret
1437
.fail_and_free_data:
1438
        stdcall kernel_free, [esi+DLLDESCR.data]
1439
.fail_and_free_dll:
1440
        mov     eax, esi
1441
        call    free
1442
.fail_and_free_coff:
1443
        stdcall kernel_free, [coff]
1444
.fail:
1445
        xor     eax, eax
1446
        ret
1447
.fail_and_free_user:
1448
        stdcall user_free, [img_base]
1449
.fail_and_dereference:
1450
        mov     eax, 1  ; delete 1 reference
1451
        call    dereference_dll
3827 clevermous 1452
        sti
2288 clevermous 1453
        xor     eax, eax
1454
        ret
1455
endp
1456
 
1457
; initialize [APPDATA.dlls_list_ptr] for given thread
1458
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
1459
; kept in sync for all threads of one process.
1460
; out: eax = APPDATA.dlls_list_ptr if all is OK,
1461
; NULL if memory allocation failed
1462
init_dlls_in_thread:
1463
        mov     ebx, [current_slot]
1464
        mov     eax, [ebx+APPDATA.dlls_list_ptr]
1465
        test    eax, eax
1466
        jnz     .ret
1467
        push    [ebx+APPDATA.dir_table]
1468
        mov     eax, 8
1469
        call    malloc
1470
        pop     edx
1471
        test    eax, eax
1472
        jz      .ret
1473
        mov     [eax], eax
1474
        mov     [eax+4], eax
1475
        mov     ecx, [TASK_COUNT]
1476
        mov     ebx, SLOT_BASE+256
1477
.set:
1478
        cmp     [ebx+APPDATA.dir_table], edx
1479
        jnz     @f
1480
        mov     [ebx+APPDATA.dlls_list_ptr], eax
1481
@@:
1482
        add     ebx, 256
1483
        dec     ecx
1484
        jnz     .set
1485
.ret:
1486
        ret
1487
 
1488
; in: eax = number of references to delete, esi -> DLLDESCR struc
1489
dereference_dll:
1490
        sub     [esi+DLLDESCR.refcount], eax
1491
        jnz     .ret
1492
        mov     eax, [esi+DLLDESCR.fd]
1493
        mov     edx, [esi+DLLDESCR.bk]
1494
        mov     [eax+DLLDESCR.bk], edx
1495
        mov     [edx+DLLDESCR.fd], eax
1496
        stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
1497
        stdcall kernel_free, [esi+DLLDESCR.data]
1498
        mov     eax, esi
1499
        call    free
1500
.ret:
1501
        ret
1502
 
1503
destroy_hdll:
1504
        push    ebx ecx esi edi
1505
        push    eax
1506
        mov     ebx, [eax+HDLL.base]
1507
        mov     esi, [eax+HDLL.parent]
1508
        mov     edx, [esi+DLLDESCR.size]
1509
; The following actions require the context of application where HDLL is mapped.
1510
; However, destroy_hdll can be called in the context of OS thread when
1511
; cleaning up objects created by the application which is destroyed.
1512
; So remember current cr3 and set it to page table of target.
1513
        mov     eax, [ecx+APPDATA.dir_table]
1514
; Because we cheat with cr3, disable interrupts: task switch would restore
1515
; page table from APPDATA of current thread.
1516
; Also set [current_slot] because it is used by user_free.
1517
        pushf
1518
        cli
1519
        push    [current_slot]
1520
        mov     [current_slot], ecx
1521
        mov     ecx, cr3
1522
        push    ecx
1523
        mov     cr3, eax
1524
        push    ebx     ; argument for user_free
1525
        mov     eax, ebx
1526
        shr     ebx, 12
1527
        push    ebx
1528
        mov     esi, [esi+DLLDESCR.data]
1529
        shr     esi, 12
1530
.unmap_loop:
1531
        push    eax
1532
        mov     eax, 2
1533
        xchg    eax, [page_tabs+ebx*4]
1534
        mov     ecx, [page_tabs+esi*4]
1535
        and     eax, not 0xFFF
1536
        and     ecx, not 0xFFF
1537
        cmp     eax, ecx
1538
        jz      @f
1539
        call    free_page
1540
@@:
1541
        pop     eax
1542
        invlpg  [eax]
1543
        add     eax, 0x1000
1544
        inc     ebx
1545
        inc     esi
1546
        sub     edx, 0x1000
1547
        ja      .unmap_loop
1548
        pop     ebx
1549
        and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
1550
        call    user_free
1551
; Restore context.
1552
        pop     eax
1553
        mov     cr3, eax
1554
        pop     [current_slot]
1555
        popf
1556
; Ok, cheating is done.
1557
        pop     eax
1558
        push    eax
1559
        mov     esi, [eax+HDLL.parent]
1560
        mov     eax, [eax+HDLL.refcount]
1561
        call    dereference_dll
1562
        pop     eax
1563
        mov     edx, [eax+HDLL.bk]
1564
        mov     ebx, [eax+HDLL.fd]
1565
        mov     [ebx+HDLL.bk], edx
1566
        mov     [edx+HDLL.fd], ebx
1567
        call    free
1568
        pop     edi esi ecx ebx
1569
        ret
1570
 
1571
; ecx -> APPDATA for slot, esi = dlls_list_ptr
1572
destroy_all_hdlls:
1573
        test    esi, esi
1574
        jz      .ret
1575
.loop:
1576
        mov     eax, [esi+HDLL.fd]
1577
        cmp     eax, esi
1578
        jz      free
1579
        call    destroy_hdll
1580
        jmp     .loop
1581
.ret:
1582
        ret
1583
 
1584
align 4
1585
stop_all_services:
1586
        push    ebp
1587
        mov     edx, [srv.fd]
1588
.next:
2384 hidnplayr 1589
        cmp     edx, srv.fd-SRV.fd
2288 clevermous 1590
        je      .done
1591
        cmp     [edx+SRV.magic], ' SRV'
1592
        jne     .next
2384 hidnplayr 1593
        cmp     [edx+SRV.size], sizeof.SRV
2288 clevermous 1594
        jne     .next
1595
 
1596
        mov     ebx, [edx+SRV.entry]
1597
        mov     edx, [edx+SRV.fd]
1598
        test    ebx, ebx
1599
        jz      .next
1600
 
1601
        push    edx
1602
        mov     ebp, esp
1603
        push    0
1604
        push    -1
1605
        call    ebx
1606
        mov     esp, ebp
1607
        pop     edx
1608
        jmp     .next
1609
.done:
1610
        pop     ebp
1611
        ret
1612
 
1613
; param
1614
;  eax= size
1615
;  ebx= pid
1616
 
1617
align 4
1618
create_kernel_object:
1619
 
1620
        push    ebx
1621
        call    malloc
1622
        pop     ebx
1623
        test    eax, eax
1624
        jz      .fail
1625
 
1626
        mov     ecx, [current_slot]
1627
        add     ecx, APP_OBJ_OFFSET
1628
 
1629
        pushfd
1630
        cli
1631
        mov     edx, [ecx+APPOBJ.fd]
1632
        mov     [eax+APPOBJ.fd], edx
1633
        mov     [eax+APPOBJ.bk], ecx
1634
        mov     [eax+APPOBJ.pid], ebx
1635
 
1636
        mov     [ecx+APPOBJ.fd], eax
1637
        mov     [edx+APPOBJ.bk], eax
1638
        popfd
1639
.fail:
1640
        ret
1641
 
1642
; param
1643
;  eax= object
1644
 
1645
align 4
1646
destroy_kernel_object:
1647
 
1648
        pushfd
1649
        cli
1650
        mov     ebx, [eax+APPOBJ.fd]
1651
        mov     ecx, [eax+APPOBJ.bk]
1652
        mov     [ebx+APPOBJ.bk], ecx
1653
        mov     [ecx+APPOBJ.fd], ebx
1654
        popfd
1655
 
1656
        xor     edx, edx       ;clear common header
1657
        mov     [eax], edx
1658
        mov     [eax+4], edx
1659
        mov     [eax+8], edx
1660
        mov     [eax+12], edx
1661
        mov     [eax+16], edx
1662
 
1663
        call    free           ;release object memory
1664
        ret