Subversion Repositories Kolibri OS

Rev

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