Subversion Repositories Kolibri OS

Rev

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