Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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