Subversion Repositories Kolibri OS

Rev

Rev 4237 | Rev 5039 | 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: 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
 
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
 
920
        mov     [coff], eax
921
 
2384 hidnplayr 922
        movzx   ecx, [eax+COFF_HEADER.nSections]
2288 clevermous 923
        xor     ebx, ebx
924
 
925
        lea     edx, [eax+20]
926
@@:
2384 hidnplayr 927
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
2288 clevermous 928
        add     ebx, 15
929
        and     ebx, not 15
2384 hidnplayr 930
        add     edx, sizeof.COFF_SECTION
2288 clevermous 931
        dec     ecx
932
        jnz     @B
933
        mov     [img_size], ebx
934
 
935
        stdcall kernel_alloc, ebx
936
        test    eax, eax
937
        jz      .fail
938
        mov     [img_base], eax
939
 
940
        mov     edi, eax
941
        xor     eax, eax
942
        mov     ecx, [img_size]
943
        add     ecx, 4095
944
        and     ecx, not 4095
945
        shr     ecx, 2
946
        cld
947
        rep stosd
948
 
949
        mov     edx, [coff]
2384 hidnplayr 950
        movzx   ebx, [edx+COFF_HEADER.nSections]
2288 clevermous 951
        mov     edi, [img_base]
952
        lea     eax, [edx+20]
953
@@:
2384 hidnplayr 954
        mov     [eax+COFF_SECTION.VirtualAddress], edi
955
        mov     esi, [eax+COFF_SECTION.PtrRawData]
2288 clevermous 956
        test    esi, esi
957
        jnz     .copy
2384 hidnplayr 958
        add     edi, [eax+COFF_SECTION.SizeOfRawData]
2288 clevermous 959
        jmp     .next
960
.copy:
961
        add     esi, edx
2384 hidnplayr 962
        mov     ecx, [eax+COFF_SECTION.SizeOfRawData]
2288 clevermous 963
        cld
964
        rep movsb
965
.next:
966
        add     edi, 15
967
        and     edi, not 15
2384 hidnplayr 968
        add     eax, sizeof.COFF_SECTION
2288 clevermous 969
        dec     ebx
970
        jnz     @B
971
 
2384 hidnplayr 972
        mov     ebx, [edx+COFF_HEADER.pSymTable]
2288 clevermous 973
        add     ebx, edx
974
        mov     [sym], ebx
2384 hidnplayr 975
        mov     ecx, [edx+COFF_HEADER.nSymbols]
2288 clevermous 976
        add     ecx, ecx
977
        lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
978
        add     ecx, [sym]
979
        mov     [strings], ecx
980
 
981
        lea     eax, [edx+20]
982
 
2384 hidnplayr 983
        stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
3761 clevermous 984
                [strings], __exports
2288 clevermous 985
        test    eax, eax
986
        jz      .link_fail
987
 
988
        mov     ebx, [coff]
989
        stdcall fix_coff_relocs, ebx, [sym], 0
990
 
2384 hidnplayr 991
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
2288 clevermous 992
        test    eax, eax
993
        jz      .link_fail
994
 
995
        mov     eax, [eax]
996
        shr     eax, 16
997
        cmp     eax, DRV_COMPAT
998
        jb      .ver_fail
999
 
1000
        cmp     eax, DRV_CURRENT
1001
        ja      .ver_fail
1002
 
1003
        mov     ebx, [coff]
2384 hidnplayr 1004
        stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
2288 clevermous 1005
        mov     [start], eax
1006
 
1007
        stdcall kernel_free, [coff]
1008
 
1009
        mov     ebx, [start]
1010
        stdcall ebx, DRV_ENTRY
1011
        test    eax, eax
1012
        jnz     .ok
1013
 
1014
        stdcall kernel_free, [img_base]
3171 hidnplayr 1015
 
2288 clevermous 1016
        xor     eax, eax
1017
        ret
1018
.ok:
1019
        mov     ebx, [img_base]
1020
        mov     [eax+SRV.base], ebx
1021
        mov     ecx, [start]
1022
        mov     [eax+SRV.entry], ecx
1023
        ret
1024
 
1025
.ver_fail:
1026
        mov     esi, msg_CR
1027
        call    sys_msg_board_str
1028
        mov     esi, [driver_name]
1029
        call    sys_msg_board_str
1030
        mov     esi, msg_CR
1031
        call    sys_msg_board_str
1032
        mov     esi, msg_version
1033
        call    sys_msg_board_str
1034
        mov     esi, msg_www
1035
        call    sys_msg_board_str
1036
        jmp     .cleanup
1037
 
1038
.link_fail:
1039
        mov     esi, msg_module
1040
        call    sys_msg_board_str
1041
        mov     esi, [driver_name]
1042
        call    sys_msg_board_str
1043
        mov     esi, msg_CR
1044
        call    sys_msg_board_str
1045
.cleanup:
1046
        stdcall kernel_free, [img_base]
1047
.fail:
1048
        stdcall kernel_free, [coff]
1049
.exit:
1050
        xor     eax, eax
1051
        ret
1052
endp
1053
 
1054
; in: edx -> COFF_SECTION struct
1055
; out: eax = alignment as mask for bits to drop
1056
coff_get_align:
1057
; Rules:
1058
; - if alignment is not given, use default = 4K;
1059
; - if alignment is given and is no more than 4K, use it;
1060
; - if alignment is more than 4K, revert to 4K.
1061
        push    ecx
2384 hidnplayr 1062
        mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
2288 clevermous 1063
        mov     eax, 1
1064
        shr     cl, 4
1065
        dec     cl
1066
        js      .default
1067
        cmp     cl, 12
1068
        jbe     @f
1069
.default:
1070
        mov     cl, 12
1071
@@:
1072
        shl     eax, cl
1073
        pop     ecx
1074
        dec     eax
1075
        ret
1076
 
1077
align 4
1078
proc load_library stdcall, file_name:dword
1079
           locals
1080
             fullname  rb 260
1081
             fileinfo  rb 40
1082
             coff      dd ?
1083
             img_base  dd ?
1084
           endl
1085
 
1086
; resolve file name
1087
        mov     ebx, [file_name]
1088
        lea     edi, [fullname+1]
1089
        mov     byte [edi-1], '/'
1090
        stdcall get_full_file_name, edi, 259
1091
        test    al, al
1092
        jz      .fail
1093
 
1094
; scan for required DLL in list of already loaded for this process,
1095
; ignore timestamp
3827 clevermous 1096
        cli
1097
 
2288 clevermous 1098
        mov     esi, [CURRENT_TASK]
1099
        shl     esi, 8
1100
        lea     edi, [fullname]
1101
        mov     ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
1102
        test    ebx, ebx
1103
        jz      .not_in_process
1104
        mov     esi, [ebx+HDLL.fd]
1105
.scan_in_process:
1106
        cmp     esi, ebx
1107
        jz      .not_in_process
1108
        mov     eax, [esi+HDLL.parent]
1109
        add     eax, DLLDESCR.name
1110
        stdcall strncmp, eax, edi, -1
1111
        test    eax, eax
1112
        jnz     .next_in_process
1113
; simple variant: load DLL which is already loaded in this process
1114
; just increment reference counters and return address of exports table
1115
        inc     [esi+HDLL.refcount]
1116
        mov     ecx, [esi+HDLL.parent]
1117
        inc     [ecx+DLLDESCR.refcount]
1118
        mov     eax, [ecx+DLLDESCR.exports]
1119
        sub     eax, [ecx+DLLDESCR.defaultbase]
1120
        add     eax, [esi+HDLL.base]
3827 clevermous 1121
        sti
2288 clevermous 1122
        ret
1123
.next_in_process:
1124
        mov     esi, [esi+HDLL.fd]
1125
        jmp     .scan_in_process
1126
.not_in_process:
1127
 
1128
; scan in full list, compare timestamp
3827 clevermous 1129
        sti
2288 clevermous 1130
        lea     eax, [fileinfo]
1131
        stdcall get_fileinfo, edi, eax
1132
        test    eax, eax
1133
        jnz     .fail
3827 clevermous 1134
        cli
2288 clevermous 1135
        mov     esi, [dll_list.fd]
1136
.scan_for_dlls:
1137
        cmp     esi, dll_list
1138
        jz      .load_new
1139
        lea     eax, [esi+DLLDESCR.name]
1140
        stdcall strncmp, eax, edi, -1
1141
        test    eax, eax
1142
        jnz     .continue_scan
1143
.test_prev_dll:
1144
        mov     eax, dword [fileinfo+24]; last modified time
1145
        mov     edx, dword [fileinfo+28]; last modified date
1146
        cmp     dword [esi+DLLDESCR.timestamp], eax
1147
        jnz     .continue_scan
1148
        cmp     dword [esi+DLLDESCR.timestamp+4], edx
1149
        jz      .dll_already_loaded
1150
.continue_scan:
1151
        mov     esi, [esi+DLLDESCR.fd]
1152
        jmp     .scan_for_dlls
1153
 
1154
; new DLL
1155
.load_new:
3827 clevermous 1156
        sti
2288 clevermous 1157
; load file
1158
        stdcall load_file, edi
1159
        test    eax, eax
1160
        jz      .fail
1161
        mov     [coff], eax
1162
        mov     dword [fileinfo+32], ebx
1163
 
1164
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
1165
        mov     esi, edi
1166
        mov     ecx, -1
1167
        xor     eax, eax
1168
        repnz scasb
1169
        not     ecx
2384 hidnplayr 1170
        lea     eax, [ecx+sizeof.DLLDESCR]
2288 clevermous 1171
        push    ecx
1172
        call    malloc
1173
        pop     ecx
1174
        test    eax, eax
1175
        jz      .fail_and_free_coff
1176
; save timestamp
1177
        lea     edi, [eax+DLLDESCR.name]
1178
        rep movsb
1179
        mov     esi, eax
1180
        mov     eax, dword [fileinfo+24]
1181
        mov     dword [esi+DLLDESCR.timestamp], eax
1182
        mov     eax, dword [fileinfo+28]
1183
        mov     dword [esi+DLLDESCR.timestamp+4], eax
1184
 
1185
; calculate size of loaded DLL
1186
        mov     edx, [coff]
2384 hidnplayr 1187
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1188
        xor     ebx, ebx
1189
 
1190
        add     edx, 20
1191
@@:
1192
        call    coff_get_align
1193
        add     ebx, eax
1194
        not     eax
1195
        and     ebx, eax
2384 hidnplayr 1196
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
1197
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1198
        dec     ecx
1199
        jnz     @B
1200
; it must be nonzero and not too big
1201
        mov     [esi+DLLDESCR.size], ebx
1202
        test    ebx, ebx
1203
        jz      .fail_and_free_dll
1204
        cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
1205
        ja      .fail_and_free_dll
1206
; allocate memory for kernel-side image
1207
        stdcall kernel_alloc, ebx
1208
        test    eax, eax
1209
        jz      .fail_and_free_dll
1210
        mov     [esi+DLLDESCR.data], eax
1211
; calculate preferred base address
1212
        add     ebx, 0x1FFF
1213
        and     ebx, not 0xFFF
1214
        mov     ecx, [dll_cur_addr]
1215
        lea     edx, [ecx+ebx]
1216
        cmp     edx, MAX_DEFAULT_DLL_ADDR
1217
        jb      @f
1218
        mov     ecx, MIN_DEFAULT_DLL_ADDR
1219
        lea     edx, [ecx+ebx]
1220
@@:
1221
        mov     [esi+DLLDESCR.defaultbase], ecx
1222
        mov     [dll_cur_addr], edx
1223
 
1224
; copy sections and set correct values for VirtualAddress'es in headers
1225
        push    esi
1226
        mov     edx, [coff]
2384 hidnplayr 1227
        movzx   ebx, [edx+COFF_HEADER.nSections]
2288 clevermous 1228
        mov     edi, eax
1229
        add     edx, 20
1230
        cld
1231
@@:
1232
        call    coff_get_align
1233
        add     ecx, eax
1234
        add     edi, eax
1235
        not     eax
1236
        and     ecx, eax
1237
        and     edi, eax
2384 hidnplayr 1238
        mov     [edx+COFF_SECTION.VirtualAddress], ecx
1239
        add     ecx, [edx+COFF_SECTION.SizeOfRawData]
1240
        mov     esi, [edx+COFF_SECTION.PtrRawData]
2288 clevermous 1241
        push    ecx
2384 hidnplayr 1242
        mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
2288 clevermous 1243
        test    esi, esi
1244
        jnz     .copy
1245
        xor     eax, eax
1246
        rep stosb
1247
        jmp     .next
1248
.copy:
1249
        add     esi, [coff]
1250
        rep movsb
1251
.next:
1252
        pop     ecx
2384 hidnplayr 1253
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1254
        dec     ebx
1255
        jnz     @B
1256
        pop     esi
1257
 
1258
; save some additional data from COFF file
1259
; later we will use COFF header, headers for sections and symbol table
1260
; and also relocations table for all sections
1261
        mov     edx, [coff]
2384 hidnplayr 1262
        mov     ebx, [edx+COFF_HEADER.pSymTable]
2288 clevermous 1263
        mov     edi, dword [fileinfo+32]
1264
        sub     edi, ebx
1265
        jc      .fail_and_free_data
1266
        mov     [esi+DLLDESCR.symbols_lim], edi
1267
        add     ebx, edx
2384 hidnplayr 1268
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1269
        lea     ecx, [ecx*5]
1270
        lea     edi, [edi+ecx*8+20]
1271
        add     edx, 20
1272
@@:
2384 hidnplayr 1273
        movzx   eax, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1274
        lea     eax, [eax*5]
1275
        lea     edi, [edi+eax*2]
2384 hidnplayr 1276
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1277
        sub     ecx, 5
1278
        jnz     @b
1279
        stdcall kernel_alloc, edi
1280
        test    eax, eax
1281
        jz      .fail_and_free_data
1282
        mov     edx, [coff]
2384 hidnplayr 1283
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1284
        lea     ecx, [ecx*5]
1285
        lea     ecx, [ecx*2+5]
1286
        mov     [esi+DLLDESCR.coff_hdr], eax
1287
        push    esi
1288
        mov     esi, edx
1289
        mov     edi, eax
1290
        rep movsd
1291
        pop     esi
1292
        mov     [esi+DLLDESCR.symbols_ptr], edi
1293
        push    esi
2384 hidnplayr 1294
        mov     ecx, [edx+COFF_HEADER.nSymbols]
2288 clevermous 1295
        mov     [esi+DLLDESCR.symbols_num], ecx
1296
        mov     ecx, [esi+DLLDESCR.symbols_lim]
1297
        mov     esi, ebx
1298
        rep movsb
1299
        pop     esi
1300
        mov     ebx, [esi+DLLDESCR.coff_hdr]
1301
        push    esi
2384 hidnplayr 1302
        movzx   eax, [edx+COFF_HEADER.nSections]
2288 clevermous 1303
        lea     edx, [ebx+20]
1304
@@:
2384 hidnplayr 1305
        movzx   ecx, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1306
        lea     ecx, [ecx*5]
2384 hidnplayr 1307
        mov     esi, [edx+COFF_SECTION.PtrReloc]
1308
        mov     [edx+COFF_SECTION.PtrReloc], edi
1309
        sub     [edx+COFF_SECTION.PtrReloc], ebx
2288 clevermous 1310
        add     esi, [coff]
1311
        shr     ecx, 1
1312
        rep movsd
1313
        adc     ecx, ecx
1314
        rep movsw
2384 hidnplayr 1315
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1316
        dec     eax
1317
        jnz     @b
1318
        pop     esi
1319
 
1320
; fixup symbols
1321
        mov     edx, ebx
2384 hidnplayr 1322
        mov     eax, [ebx+COFF_HEADER.nSymbols]
2288 clevermous 1323
        add     edx, 20
1324
        mov     ecx, [esi+DLLDESCR.symbols_num]
1325
        lea     ecx, [ecx*9]
1326
        add     ecx, ecx
1327
        add     ecx, [esi+DLLDESCR.symbols_ptr]
1328
 
1329
        stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
1330
                ecx, 0
1331
;          test eax, eax
1332
;          jnz @F
1333
;
1334
;@@:
1335
 
2384 hidnplayr 1336
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
2288 clevermous 1337
        test    eax, eax
1338
        jnz     @F
1339
 
2384 hidnplayr 1340
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
2288 clevermous 1341
@@:
1342
        mov     [esi+DLLDESCR.exports], eax
1343
 
1344
; fix relocs in the hidden copy in kernel memory to default address
1345
; it is first fix; usually this will be enough, but second fix
1346
; can be necessary if real load address will not equal assumption
1347
        mov     eax, [esi+DLLDESCR.data]
1348
        sub     eax, [esi+DLLDESCR.defaultbase]
1349
        stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
1350
 
1351
        stdcall kernel_free, [coff]
1352
 
3827 clevermous 1353
        cli
1354
; initialize DLLDESCR struct
1355
        and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
1356
        mov     [esi+DLLDESCR.fd], dll_list
1357
        mov     eax, [dll_list.bk]
1358
        mov     [dll_list.bk], esi
1359
        mov     [esi+DLLDESCR.bk], eax
1360
        mov     [eax+DLLDESCR.fd], esi
2288 clevermous 1361
.dll_already_loaded:
1362
        inc     [esi+DLLDESCR.refcount]
1363
        push    esi
1364
        call    init_heap
1365
        pop     esi
1366
 
1367
        mov     edi, [esi+DLLDESCR.size]
1368
        stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
1369
        test    eax, eax
1370
        jnz     @f
1371
        stdcall user_alloc, edi
1372
        test    eax, eax
1373
        jz      .fail_and_dereference
1374
@@:
1375
        mov     [img_base], eax
2384 hidnplayr 1376
        mov     eax, sizeof.HDLL
2288 clevermous 1377
        call    malloc
1378
        test    eax, eax
1379
        jz      .fail_and_free_user
1380
        mov     ebx, [CURRENT_TASK]
1381
        shl     ebx, 5
1382
        mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
1383
        mov     [eax+HDLL.pid], edx
1384
        push    eax
1385
        call    init_dlls_in_thread
1386
        pop     ebx
1387
        test    eax, eax
1388
        jz      .fail_and_free_user
1389
        mov     edx, [eax+HDLL.fd]
1390
        mov     [ebx+HDLL.fd], edx
1391
        mov     [ebx+HDLL.bk], eax
1392
        mov     [eax+HDLL.fd], ebx
1393
        mov     [edx+HDLL.bk], ebx
1394
        mov     eax, ebx
1395
        mov     ebx, [img_base]
1396
        mov     [eax+HDLL.base], ebx
1397
        mov     [eax+HDLL.size], edi
1398
        mov     [eax+HDLL.refcount], 1
1399
        mov     [eax+HDLL.parent], esi
1400
        mov     edx, ebx
1401
        shr     edx, 12
1402
        or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
1403
; copy entries of page table from kernel-side image to usermode
1404
; use copy-on-write for user-mode image, so map as readonly
1405
        xor     edi, edi
1406
        mov     ecx, [esi+DLLDESCR.data]
1407
        shr     ecx, 12
1408
.map_pages_loop:
1409
        mov     eax, [page_tabs+ecx*4]
1410
        and     eax, not 0xFFF
1411
        or      al, PG_USER
1412
        xchg    eax, [page_tabs+edx*4]
1413
        test    al, 1
1414
        jz      @f
1415
        call    free_page
1416
@@:
1417
        invlpg  [ebx+edi]
1418
        inc     ecx
1419
        inc     edx
1420
        add     edi, 0x1000
1421
        cmp     edi, [esi+DLLDESCR.size]
1422
        jb      .map_pages_loop
1423
 
1424
; if real user-mode base is not equal to preferred base, relocate image
1425
        sub     ebx, [esi+DLLDESCR.defaultbase]
1426
        jz      @f
1427
        stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
1428
@@:
1429
 
1430
        mov     eax, [esi+DLLDESCR.exports]
1431
        sub     eax, [esi+DLLDESCR.defaultbase]
1432
        add     eax, [img_base]
3827 clevermous 1433
        sti
2288 clevermous 1434
        ret
1435
.fail_and_free_data:
1436
        stdcall kernel_free, [esi+DLLDESCR.data]
1437
.fail_and_free_dll:
1438
        mov     eax, esi
1439
        call    free
1440
.fail_and_free_coff:
1441
        stdcall kernel_free, [coff]
1442
.fail:
1443
        xor     eax, eax
1444
        ret
1445
.fail_and_free_user:
1446
        stdcall user_free, [img_base]
1447
.fail_and_dereference:
1448
        mov     eax, 1  ; delete 1 reference
1449
        call    dereference_dll
3827 clevermous 1450
        sti
2288 clevermous 1451
        xor     eax, eax
1452
        ret
1453
endp
1454
 
1455
; initialize [APPDATA.dlls_list_ptr] for given thread
1456
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
1457
; kept in sync for all threads of one process.
1458
; out: eax = APPDATA.dlls_list_ptr if all is OK,
1459
; NULL if memory allocation failed
1460
init_dlls_in_thread:
1461
        mov     ebx, [current_slot]
1462
        mov     eax, [ebx+APPDATA.dlls_list_ptr]
1463
        test    eax, eax
1464
        jnz     .ret
1465
        push    [ebx+APPDATA.dir_table]
1466
        mov     eax, 8
1467
        call    malloc
1468
        pop     edx
1469
        test    eax, eax
1470
        jz      .ret
1471
        mov     [eax], eax
1472
        mov     [eax+4], eax
1473
        mov     ecx, [TASK_COUNT]
1474
        mov     ebx, SLOT_BASE+256
1475
.set:
1476
        cmp     [ebx+APPDATA.dir_table], edx
1477
        jnz     @f
1478
        mov     [ebx+APPDATA.dlls_list_ptr], eax
1479
@@:
1480
        add     ebx, 256
1481
        dec     ecx
1482
        jnz     .set
1483
.ret:
1484
        ret
1485
 
1486
; in: eax = number of references to delete, esi -> DLLDESCR struc
1487
dereference_dll:
1488
        sub     [esi+DLLDESCR.refcount], eax
1489
        jnz     .ret
1490
        mov     eax, [esi+DLLDESCR.fd]
1491
        mov     edx, [esi+DLLDESCR.bk]
1492
        mov     [eax+DLLDESCR.bk], edx
1493
        mov     [edx+DLLDESCR.fd], eax
1494
        stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
1495
        stdcall kernel_free, [esi+DLLDESCR.data]
1496
        mov     eax, esi
1497
        call    free
1498
.ret:
1499
        ret
1500
 
1501
destroy_hdll:
1502
        push    ebx ecx esi edi
1503
        push    eax
1504
        mov     ebx, [eax+HDLL.base]
1505
        mov     esi, [eax+HDLL.parent]
1506
        mov     edx, [esi+DLLDESCR.size]
1507
; The following actions require the context of application where HDLL is mapped.
1508
; However, destroy_hdll can be called in the context of OS thread when
1509
; cleaning up objects created by the application which is destroyed.
1510
; So remember current cr3 and set it to page table of target.
1511
        mov     eax, [ecx+APPDATA.dir_table]
1512
; Because we cheat with cr3, disable interrupts: task switch would restore
1513
; page table from APPDATA of current thread.
1514
; Also set [current_slot] because it is used by user_free.
1515
        pushf
1516
        cli
1517
        push    [current_slot]
1518
        mov     [current_slot], ecx
1519
        mov     ecx, cr3
1520
        push    ecx
1521
        mov     cr3, eax
1522
        push    ebx     ; argument for user_free
1523
        mov     eax, ebx
1524
        shr     ebx, 12
1525
        push    ebx
1526
        mov     esi, [esi+DLLDESCR.data]
1527
        shr     esi, 12
1528
.unmap_loop:
1529
        push    eax
1530
        mov     eax, 2
1531
        xchg    eax, [page_tabs+ebx*4]
1532
        mov     ecx, [page_tabs+esi*4]
1533
        and     eax, not 0xFFF
1534
        and     ecx, not 0xFFF
1535
        cmp     eax, ecx
1536
        jz      @f
1537
        call    free_page
1538
@@:
1539
        pop     eax
1540
        invlpg  [eax]
1541
        add     eax, 0x1000
1542
        inc     ebx
1543
        inc     esi
1544
        sub     edx, 0x1000
1545
        ja      .unmap_loop
1546
        pop     ebx
1547
        and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
1548
        call    user_free
1549
; Restore context.
1550
        pop     eax
1551
        mov     cr3, eax
1552
        pop     [current_slot]
1553
        popf
1554
; Ok, cheating is done.
1555
        pop     eax
1556
        push    eax
1557
        mov     esi, [eax+HDLL.parent]
1558
        mov     eax, [eax+HDLL.refcount]
1559
        call    dereference_dll
1560
        pop     eax
1561
        mov     edx, [eax+HDLL.bk]
1562
        mov     ebx, [eax+HDLL.fd]
1563
        mov     [ebx+HDLL.bk], edx
1564
        mov     [edx+HDLL.fd], ebx
1565
        call    free
1566
        pop     edi esi ecx ebx
1567
        ret
1568
 
1569
; ecx -> APPDATA for slot, esi = dlls_list_ptr
1570
destroy_all_hdlls:
1571
        test    esi, esi
1572
        jz      .ret
1573
.loop:
1574
        mov     eax, [esi+HDLL.fd]
1575
        cmp     eax, esi
1576
        jz      free
1577
        call    destroy_hdll
1578
        jmp     .loop
1579
.ret:
1580
        ret
1581
 
1582
align 4
1583
stop_all_services:
1584
        push    ebp
1585
        mov     edx, [srv.fd]
1586
.next:
2384 hidnplayr 1587
        cmp     edx, srv.fd-SRV.fd
2288 clevermous 1588
        je      .done
1589
        cmp     [edx+SRV.magic], ' SRV'
1590
        jne     .next
2384 hidnplayr 1591
        cmp     [edx+SRV.size], sizeof.SRV
2288 clevermous 1592
        jne     .next
1593
 
1594
        mov     ebx, [edx+SRV.entry]
1595
        mov     edx, [edx+SRV.fd]
1596
        test    ebx, ebx
1597
        jz      .next
1598
 
1599
        push    edx
1600
        mov     ebp, esp
1601
        push    0
1602
        push    -1
1603
        call    ebx
1604
        mov     esp, ebp
1605
        pop     edx
1606
        jmp     .next
1607
.done:
1608
        pop     ebp
1609
        ret
1610
 
1611
; param
1612
;  eax= size
1613
;  ebx= pid
1614
 
1615
align 4
1616
create_kernel_object:
1617
 
1618
        push    ebx
1619
        call    malloc
1620
        pop     ebx
1621
        test    eax, eax
1622
        jz      .fail
1623
 
1624
        mov     ecx, [current_slot]
1625
        add     ecx, APP_OBJ_OFFSET
1626
 
1627
        pushfd
1628
        cli
1629
        mov     edx, [ecx+APPOBJ.fd]
1630
        mov     [eax+APPOBJ.fd], edx
1631
        mov     [eax+APPOBJ.bk], ecx
1632
        mov     [eax+APPOBJ.pid], ebx
1633
 
1634
        mov     [ecx+APPOBJ.fd], eax
1635
        mov     [edx+APPOBJ.bk], eax
1636
        popfd
1637
.fail:
1638
        ret
1639
 
1640
; param
1641
;  eax= object
1642
 
1643
align 4
1644
destroy_kernel_object:
1645
 
1646
        pushfd
1647
        cli
1648
        mov     ebx, [eax+APPOBJ.fd]
1649
        mov     ecx, [eax+APPOBJ.bk]
1650
        mov     [ebx+APPOBJ.bk], ecx
1651
        mov     [ecx+APPOBJ.fd], ebx
1652
        popfd
1653
 
1654
        xor     edx, edx       ;clear common header
1655
        mov     [eax], edx
1656
        mov     [eax+4], edx
1657
        mov     [eax+8], edx
1658
        mov     [eax+12], edx
1659
        mov     [eax+16], edx
1660
 
1661
        call    free           ;release object memory
1662
        ret