Subversion Repositories Kolibri OS

Rev

Rev 3761 | Rev 3827 | 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: 3786 $
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
        cli
1034
 
1035
; resolve file name
1036
        mov     ebx, [file_name]
1037
        lea     edi, [fullname+1]
1038
        mov     byte [edi-1], '/'
1039
        stdcall get_full_file_name, edi, 259
1040
        test    al, al
1041
        jz      .fail
1042
 
1043
; scan for required DLL in list of already loaded for this process,
1044
; ignore timestamp
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]
1068
        ret
1069
.next_in_process:
1070
        mov     esi, [esi+HDLL.fd]
1071
        jmp     .scan_in_process
1072
.not_in_process:
1073
 
1074
; scan in full list, compare timestamp
1075
        lea     eax, [fileinfo]
1076
        stdcall get_fileinfo, edi, eax
1077
        test    eax, eax
1078
        jnz     .fail
1079
        mov     esi, [dll_list.fd]
1080
.scan_for_dlls:
1081
        cmp     esi, dll_list
1082
        jz      .load_new
1083
        lea     eax, [esi+DLLDESCR.name]
1084
        stdcall strncmp, eax, edi, -1
1085
        test    eax, eax
1086
        jnz     .continue_scan
1087
.test_prev_dll:
1088
        mov     eax, dword [fileinfo+24]; last modified time
1089
        mov     edx, dword [fileinfo+28]; last modified date
1090
        cmp     dword [esi+DLLDESCR.timestamp], eax
1091
        jnz     .continue_scan
1092
        cmp     dword [esi+DLLDESCR.timestamp+4], edx
1093
        jz      .dll_already_loaded
1094
.continue_scan:
1095
        mov     esi, [esi+DLLDESCR.fd]
1096
        jmp     .scan_for_dlls
1097
 
1098
; new DLL
1099
.load_new:
1100
; load file
1101
        stdcall load_file, edi
1102
        test    eax, eax
1103
        jz      .fail
1104
        mov     [coff], eax
1105
        mov     dword [fileinfo+32], ebx
1106
 
1107
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
1108
        mov     esi, edi
1109
        mov     ecx, -1
1110
        xor     eax, eax
1111
        repnz scasb
1112
        not     ecx
2384 hidnplayr 1113
        lea     eax, [ecx+sizeof.DLLDESCR]
2288 clevermous 1114
        push    ecx
1115
        call    malloc
1116
        pop     ecx
1117
        test    eax, eax
1118
        jz      .fail_and_free_coff
1119
; save timestamp
1120
        lea     edi, [eax+DLLDESCR.name]
1121
        rep movsb
1122
        mov     esi, eax
1123
        mov     eax, dword [fileinfo+24]
1124
        mov     dword [esi+DLLDESCR.timestamp], eax
1125
        mov     eax, dword [fileinfo+28]
1126
        mov     dword [esi+DLLDESCR.timestamp+4], eax
1127
; initialize DLLDESCR struct
1128
        and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
1129
        mov     [esi+DLLDESCR.fd], dll_list
1130
        mov     eax, [dll_list.bk]
1131
        mov     [dll_list.bk], esi
1132
        mov     [esi+DLLDESCR.bk], eax
1133
        mov     [eax+DLLDESCR.fd], esi
1134
 
1135
; calculate size of loaded DLL
1136
        mov     edx, [coff]
2384 hidnplayr 1137
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1138
        xor     ebx, ebx
1139
 
1140
        add     edx, 20
1141
@@:
1142
        call    coff_get_align
1143
        add     ebx, eax
1144
        not     eax
1145
        and     ebx, eax
2384 hidnplayr 1146
        add     ebx, [edx+COFF_SECTION.SizeOfRawData]
1147
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1148
        dec     ecx
1149
        jnz     @B
1150
; it must be nonzero and not too big
1151
        mov     [esi+DLLDESCR.size], ebx
1152
        test    ebx, ebx
1153
        jz      .fail_and_free_dll
1154
        cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
1155
        ja      .fail_and_free_dll
1156
; allocate memory for kernel-side image
1157
        stdcall kernel_alloc, ebx
1158
        test    eax, eax
1159
        jz      .fail_and_free_dll
1160
        mov     [esi+DLLDESCR.data], eax
1161
; calculate preferred base address
1162
        add     ebx, 0x1FFF
1163
        and     ebx, not 0xFFF
1164
        mov     ecx, [dll_cur_addr]
1165
        lea     edx, [ecx+ebx]
1166
        cmp     edx, MAX_DEFAULT_DLL_ADDR
1167
        jb      @f
1168
        mov     ecx, MIN_DEFAULT_DLL_ADDR
1169
        lea     edx, [ecx+ebx]
1170
@@:
1171
        mov     [esi+DLLDESCR.defaultbase], ecx
1172
        mov     [dll_cur_addr], edx
1173
 
1174
; copy sections and set correct values for VirtualAddress'es in headers
1175
        push    esi
1176
        mov     edx, [coff]
2384 hidnplayr 1177
        movzx   ebx, [edx+COFF_HEADER.nSections]
2288 clevermous 1178
        mov     edi, eax
1179
        add     edx, 20
1180
        cld
1181
@@:
1182
        call    coff_get_align
1183
        add     ecx, eax
1184
        add     edi, eax
1185
        not     eax
1186
        and     ecx, eax
1187
        and     edi, eax
2384 hidnplayr 1188
        mov     [edx+COFF_SECTION.VirtualAddress], ecx
1189
        add     ecx, [edx+COFF_SECTION.SizeOfRawData]
1190
        mov     esi, [edx+COFF_SECTION.PtrRawData]
2288 clevermous 1191
        push    ecx
2384 hidnplayr 1192
        mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
2288 clevermous 1193
        test    esi, esi
1194
        jnz     .copy
1195
        xor     eax, eax
1196
        rep stosb
1197
        jmp     .next
1198
.copy:
1199
        add     esi, [coff]
1200
        rep movsb
1201
.next:
1202
        pop     ecx
2384 hidnplayr 1203
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1204
        dec     ebx
1205
        jnz     @B
1206
        pop     esi
1207
 
1208
; save some additional data from COFF file
1209
; later we will use COFF header, headers for sections and symbol table
1210
; and also relocations table for all sections
1211
        mov     edx, [coff]
2384 hidnplayr 1212
        mov     ebx, [edx+COFF_HEADER.pSymTable]
2288 clevermous 1213
        mov     edi, dword [fileinfo+32]
1214
        sub     edi, ebx
1215
        jc      .fail_and_free_data
1216
        mov     [esi+DLLDESCR.symbols_lim], edi
1217
        add     ebx, edx
2384 hidnplayr 1218
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1219
        lea     ecx, [ecx*5]
1220
        lea     edi, [edi+ecx*8+20]
1221
        add     edx, 20
1222
@@:
2384 hidnplayr 1223
        movzx   eax, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1224
        lea     eax, [eax*5]
1225
        lea     edi, [edi+eax*2]
2384 hidnplayr 1226
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1227
        sub     ecx, 5
1228
        jnz     @b
1229
        stdcall kernel_alloc, edi
1230
        test    eax, eax
1231
        jz      .fail_and_free_data
1232
        mov     edx, [coff]
2384 hidnplayr 1233
        movzx   ecx, [edx+COFF_HEADER.nSections]
2288 clevermous 1234
        lea     ecx, [ecx*5]
1235
        lea     ecx, [ecx*2+5]
1236
        mov     [esi+DLLDESCR.coff_hdr], eax
1237
        push    esi
1238
        mov     esi, edx
1239
        mov     edi, eax
1240
        rep movsd
1241
        pop     esi
1242
        mov     [esi+DLLDESCR.symbols_ptr], edi
1243
        push    esi
2384 hidnplayr 1244
        mov     ecx, [edx+COFF_HEADER.nSymbols]
2288 clevermous 1245
        mov     [esi+DLLDESCR.symbols_num], ecx
1246
        mov     ecx, [esi+DLLDESCR.symbols_lim]
1247
        mov     esi, ebx
1248
        rep movsb
1249
        pop     esi
1250
        mov     ebx, [esi+DLLDESCR.coff_hdr]
1251
        push    esi
2384 hidnplayr 1252
        movzx   eax, [edx+COFF_HEADER.nSections]
2288 clevermous 1253
        lea     edx, [ebx+20]
1254
@@:
2384 hidnplayr 1255
        movzx   ecx, [edx+COFF_SECTION.NumReloc]
2288 clevermous 1256
        lea     ecx, [ecx*5]
2384 hidnplayr 1257
        mov     esi, [edx+COFF_SECTION.PtrReloc]
1258
        mov     [edx+COFF_SECTION.PtrReloc], edi
1259
        sub     [edx+COFF_SECTION.PtrReloc], ebx
2288 clevermous 1260
        add     esi, [coff]
1261
        shr     ecx, 1
1262
        rep movsd
1263
        adc     ecx, ecx
1264
        rep movsw
2384 hidnplayr 1265
        add     edx, sizeof.COFF_SECTION
2288 clevermous 1266
        dec     eax
1267
        jnz     @b
1268
        pop     esi
1269
 
1270
; fixup symbols
1271
        mov     edx, ebx
2384 hidnplayr 1272
        mov     eax, [ebx+COFF_HEADER.nSymbols]
2288 clevermous 1273
        add     edx, 20
1274
        mov     ecx, [esi+DLLDESCR.symbols_num]
1275
        lea     ecx, [ecx*9]
1276
        add     ecx, ecx
1277
        add     ecx, [esi+DLLDESCR.symbols_ptr]
1278
 
1279
        stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
1280
                ecx, 0
1281
;          test eax, eax
1282
;          jnz @F
1283
;
1284
;@@:
1285
 
2384 hidnplayr 1286
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
2288 clevermous 1287
        test    eax, eax
1288
        jnz     @F
1289
 
2384 hidnplayr 1290
        stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
2288 clevermous 1291
@@:
1292
        mov     [esi+DLLDESCR.exports], eax
1293
 
1294
; fix relocs in the hidden copy in kernel memory to default address
1295
; it is first fix; usually this will be enough, but second fix
1296
; can be necessary if real load address will not equal assumption
1297
        mov     eax, [esi+DLLDESCR.data]
1298
        sub     eax, [esi+DLLDESCR.defaultbase]
1299
        stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
1300
 
1301
        stdcall kernel_free, [coff]
1302
 
1303
.dll_already_loaded:
1304
        inc     [esi+DLLDESCR.refcount]
1305
        push    esi
1306
        call    init_heap
1307
        pop     esi
1308
 
1309
        mov     edi, [esi+DLLDESCR.size]
1310
        stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
1311
        test    eax, eax
1312
        jnz     @f
1313
        stdcall user_alloc, edi
1314
        test    eax, eax
1315
        jz      .fail_and_dereference
1316
@@:
1317
        mov     [img_base], eax
2384 hidnplayr 1318
        mov     eax, sizeof.HDLL
2288 clevermous 1319
        call    malloc
1320
        test    eax, eax
1321
        jz      .fail_and_free_user
1322
        mov     ebx, [CURRENT_TASK]
1323
        shl     ebx, 5
1324
        mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
1325
        mov     [eax+HDLL.pid], edx
1326
        push    eax
1327
        call    init_dlls_in_thread
1328
        pop     ebx
1329
        test    eax, eax
1330
        jz      .fail_and_free_user
1331
        mov     edx, [eax+HDLL.fd]
1332
        mov     [ebx+HDLL.fd], edx
1333
        mov     [ebx+HDLL.bk], eax
1334
        mov     [eax+HDLL.fd], ebx
1335
        mov     [edx+HDLL.bk], ebx
1336
        mov     eax, ebx
1337
        mov     ebx, [img_base]
1338
        mov     [eax+HDLL.base], ebx
1339
        mov     [eax+HDLL.size], edi
1340
        mov     [eax+HDLL.refcount], 1
1341
        mov     [eax+HDLL.parent], esi
1342
        mov     edx, ebx
1343
        shr     edx, 12
1344
        or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
1345
; copy entries of page table from kernel-side image to usermode
1346
; use copy-on-write for user-mode image, so map as readonly
1347
        xor     edi, edi
1348
        mov     ecx, [esi+DLLDESCR.data]
1349
        shr     ecx, 12
1350
.map_pages_loop:
1351
        mov     eax, [page_tabs+ecx*4]
1352
        and     eax, not 0xFFF
1353
        or      al, PG_USER
1354
        xchg    eax, [page_tabs+edx*4]
1355
        test    al, 1
1356
        jz      @f
1357
        call    free_page
1358
@@:
1359
        invlpg  [ebx+edi]
1360
        inc     ecx
1361
        inc     edx
1362
        add     edi, 0x1000
1363
        cmp     edi, [esi+DLLDESCR.size]
1364
        jb      .map_pages_loop
1365
 
1366
; if real user-mode base is not equal to preferred base, relocate image
1367
        sub     ebx, [esi+DLLDESCR.defaultbase]
1368
        jz      @f
1369
        stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
1370
@@:
1371
 
1372
        mov     eax, [esi+DLLDESCR.exports]
1373
        sub     eax, [esi+DLLDESCR.defaultbase]
1374
        add     eax, [img_base]
1375
        ret
1376
.fail_and_free_data:
1377
        stdcall kernel_free, [esi+DLLDESCR.data]
1378
.fail_and_free_dll:
1379
        mov     eax, esi
1380
        call    free
1381
.fail_and_free_coff:
1382
        stdcall kernel_free, [coff]
1383
.fail:
1384
        xor     eax, eax
1385
        ret
1386
.fail_and_free_user:
1387
        stdcall user_free, [img_base]
1388
.fail_and_dereference:
1389
        mov     eax, 1  ; delete 1 reference
1390
        call    dereference_dll
1391
        xor     eax, eax
1392
        ret
1393
endp
1394
 
1395
; initialize [APPDATA.dlls_list_ptr] for given thread
1396
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
1397
; kept in sync for all threads of one process.
1398
; out: eax = APPDATA.dlls_list_ptr if all is OK,
1399
; NULL if memory allocation failed
1400
init_dlls_in_thread:
1401
        mov     ebx, [current_slot]
1402
        mov     eax, [ebx+APPDATA.dlls_list_ptr]
1403
        test    eax, eax
1404
        jnz     .ret
1405
        push    [ebx+APPDATA.dir_table]
1406
        mov     eax, 8
1407
        call    malloc
1408
        pop     edx
1409
        test    eax, eax
1410
        jz      .ret
1411
        mov     [eax], eax
1412
        mov     [eax+4], eax
1413
        mov     ecx, [TASK_COUNT]
1414
        mov     ebx, SLOT_BASE+256
1415
.set:
1416
        cmp     [ebx+APPDATA.dir_table], edx
1417
        jnz     @f
1418
        mov     [ebx+APPDATA.dlls_list_ptr], eax
1419
@@:
1420
        add     ebx, 256
1421
        dec     ecx
1422
        jnz     .set
1423
.ret:
1424
        ret
1425
 
1426
; in: eax = number of references to delete, esi -> DLLDESCR struc
1427
dereference_dll:
1428
        sub     [esi+DLLDESCR.refcount], eax
1429
        jnz     .ret
1430
        mov     eax, [esi+DLLDESCR.fd]
1431
        mov     edx, [esi+DLLDESCR.bk]
1432
        mov     [eax+DLLDESCR.bk], edx
1433
        mov     [edx+DLLDESCR.fd], eax
1434
        stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
1435
        stdcall kernel_free, [esi+DLLDESCR.data]
1436
        mov     eax, esi
1437
        call    free
1438
.ret:
1439
        ret
1440
 
1441
destroy_hdll:
1442
        push    ebx ecx esi edi
1443
        push    eax
1444
        mov     ebx, [eax+HDLL.base]
1445
        mov     esi, [eax+HDLL.parent]
1446
        mov     edx, [esi+DLLDESCR.size]
1447
; The following actions require the context of application where HDLL is mapped.
1448
; However, destroy_hdll can be called in the context of OS thread when
1449
; cleaning up objects created by the application which is destroyed.
1450
; So remember current cr3 and set it to page table of target.
1451
        mov     eax, [ecx+APPDATA.dir_table]
1452
; Because we cheat with cr3, disable interrupts: task switch would restore
1453
; page table from APPDATA of current thread.
1454
; Also set [current_slot] because it is used by user_free.
1455
        pushf
1456
        cli
1457
        push    [current_slot]
1458
        mov     [current_slot], ecx
1459
        mov     ecx, cr3
1460
        push    ecx
1461
        mov     cr3, eax
1462
        push    ebx     ; argument for user_free
1463
        mov     eax, ebx
1464
        shr     ebx, 12
1465
        push    ebx
1466
        mov     esi, [esi+DLLDESCR.data]
1467
        shr     esi, 12
1468
.unmap_loop:
1469
        push    eax
1470
        mov     eax, 2
1471
        xchg    eax, [page_tabs+ebx*4]
1472
        mov     ecx, [page_tabs+esi*4]
1473
        and     eax, not 0xFFF
1474
        and     ecx, not 0xFFF
1475
        cmp     eax, ecx
1476
        jz      @f
1477
        call    free_page
1478
@@:
1479
        pop     eax
1480
        invlpg  [eax]
1481
        add     eax, 0x1000
1482
        inc     ebx
1483
        inc     esi
1484
        sub     edx, 0x1000
1485
        ja      .unmap_loop
1486
        pop     ebx
1487
        and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
1488
        call    user_free
1489
; Restore context.
1490
        pop     eax
1491
        mov     cr3, eax
1492
        pop     [current_slot]
1493
        popf
1494
; Ok, cheating is done.
1495
        pop     eax
1496
        push    eax
1497
        mov     esi, [eax+HDLL.parent]
1498
        mov     eax, [eax+HDLL.refcount]
1499
        call    dereference_dll
1500
        pop     eax
1501
        mov     edx, [eax+HDLL.bk]
1502
        mov     ebx, [eax+HDLL.fd]
1503
        mov     [ebx+HDLL.bk], edx
1504
        mov     [edx+HDLL.fd], ebx
1505
        call    free
1506
        pop     edi esi ecx ebx
1507
        ret
1508
 
1509
; ecx -> APPDATA for slot, esi = dlls_list_ptr
1510
destroy_all_hdlls:
1511
        test    esi, esi
1512
        jz      .ret
1513
.loop:
1514
        mov     eax, [esi+HDLL.fd]
1515
        cmp     eax, esi
1516
        jz      free
1517
        call    destroy_hdll
1518
        jmp     .loop
1519
.ret:
1520
        ret
1521
 
1522
align 4
1523
stop_all_services:
1524
        push    ebp
1525
        mov     edx, [srv.fd]
1526
.next:
2384 hidnplayr 1527
        cmp     edx, srv.fd-SRV.fd
2288 clevermous 1528
        je      .done
1529
        cmp     [edx+SRV.magic], ' SRV'
1530
        jne     .next
2384 hidnplayr 1531
        cmp     [edx+SRV.size], sizeof.SRV
2288 clevermous 1532
        jne     .next
1533
 
1534
        mov     ebx, [edx+SRV.entry]
1535
        mov     edx, [edx+SRV.fd]
1536
        test    ebx, ebx
1537
        jz      .next
1538
 
1539
        push    edx
1540
        mov     ebp, esp
1541
        push    0
1542
        push    -1
1543
        call    ebx
1544
        mov     esp, ebp
1545
        pop     edx
1546
        jmp     .next
1547
.done:
1548
        pop     ebp
1549
        ret
1550
 
1551
; param
1552
;  eax= size
1553
;  ebx= pid
1554
 
1555
align 4
1556
create_kernel_object:
1557
 
1558
        push    ebx
1559
        call    malloc
1560
        pop     ebx
1561
        test    eax, eax
1562
        jz      .fail
1563
 
1564
        mov     ecx, [current_slot]
1565
        add     ecx, APP_OBJ_OFFSET
1566
 
1567
        pushfd
1568
        cli
1569
        mov     edx, [ecx+APPOBJ.fd]
1570
        mov     [eax+APPOBJ.fd], edx
1571
        mov     [eax+APPOBJ.bk], ecx
1572
        mov     [eax+APPOBJ.pid], ebx
1573
 
1574
        mov     [ecx+APPOBJ.fd], eax
1575
        mov     [edx+APPOBJ.bk], eax
1576
        popfd
1577
.fail:
1578
        ret
1579
 
1580
; param
1581
;  eax= object
1582
 
1583
align 4
1584
destroy_kernel_object:
1585
 
1586
        pushfd
1587
        cli
1588
        mov     ebx, [eax+APPOBJ.fd]
1589
        mov     ecx, [eax+APPOBJ.bk]
1590
        mov     [ebx+APPOBJ.bk], ecx
1591
        mov     [ecx+APPOBJ.fd], ebx
1592
        popfd
1593
 
1594
        xor     edx, edx       ;clear common header
1595
        mov     [eax], edx
1596
        mov     [eax+4], edx
1597
        mov     [eax+8], edx
1598
        mov     [eax+12], edx
1599
        mov     [eax+16], edx
1600
 
1601
        call    free           ;release object memory
1602
        ret