OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 18, 2024 7:15 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: Calling BIOS Int 0x10 in protected mode with a different way
PostPosted: Sat Jan 14, 2017 11:06 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
Hi.

I know, calling bios interrupts directly in protected mode isn't possible. But I wanted to try it a bit... different way.
I got the address of int 10h handler from IVT, then looked what is there.

Result (First 500 bytes)

Code:
FA  FC  66  50  66  51  66  52  66  53  66  55  66  56  66  57  6  1E  8C  D0  8E  D8  66  89  E3  66  F  B7  E4  66  89  E0  50  E8  2  F2  66  89  DC  1F  7  66  5F  66  5E  66  5D  66  5B  66  5A  66  59  66  58  CF  20  20  4E  55  4C  4C  A  0  20  20  20  61  3D  25  30  38  78  20  20  62  3D  25  30  38  78  20  20  63  3D  25  30  38  78  20  20  64  3D  25  30  38  78  20  64  73  3D  25  30  34  78  20  65  73  3D  25  30  34  78  20  73  73  3D  25  30  34  78  A  0  20  20  73  69  3D  25  30  38  78  20  64  69  3D  25  30  38  78  20  62  70  3D  25  30  38  78  20  73  70  3D  25  30  38  78  20  63  73  3D  25  30  34  78  20  69  70  3D  25  30  34  78  20  20  66  3D  25  30  34  78  A  0  73  74  75  62  20  25  73  3A  25  64  3A  A  0  57  41  52  4E  49  4E  47  20  2D  20  69  6E  74  65  72  6E  61  6C  20  65  72  72  6F  72  20  64  65  74  65  63  74  65  64  20  61  74  20  25  73  3A  25  64  21  A  0  73  65  74  20  56  47  41  20  6D  6F  64  65  20  25  78  A  0  53  74  61  72  74  20  53  65  61  56  47  41  42  49  4F  53  20  28  76  65  72  73  69  6F  6E  20  25  73  29  A  0  65  6E  74  65  72  20  25  73  3A  A  0  4E  6F  20  56  42  45  20  44  49  53  50  49  20  69  6E  74  65  72  66  61  63  65  20  64  65  74  65  63  74  65  64  2C  20  66  61  6C  6C  69  6E  67  20  62  61  63  6B  20  74  6F  20  73  74  64  76  67  61  A  0  56  42  45  20  44  49  53  50  49  3A  20  62  64  66  20  25  30  32  78  3A  25  30  32  78  2E  25  78  2C  20  62  61  72  20  25  64  A  0  56  42  45  20  44  49  53  50  49  3A  20  6C  66  62  5F  61  64  64  72  3D  25  78  2C  20  73  69  7A  65  20  25  64  20  4D  42  A  0  52  65  6D  6F  76  69  6E  67  20  6D  6F  64  65  20  25  78  A  0  53  65  61  42  49  4F  53  20  56  42  45  28  43  29  20  32  30  31  31  0  53  65  61  42  49  4F  53  20  44  65  76  65  6C  6F  70  65  72  73  0  53  65  61  42  49  4F  53  20  56  42  45  20  41  64


In ASCII:

Quote:
úüfPfQfRfSfUfVfWŒÐŽØf‰ãf·äf‰àPèòf‰Üf_f^f]f[fZfYfXÏ NULL a=%08x b=%08x c=%08x d=%08x ds=%04x es=%04x ss=%04x si=%08x di=%08x bp=%08x sp=%08x cs=%04x ip=%04x f=%04xstub %s:%d:WARNING - internal error detected at %s:%d!set VGA mode %xStart SeaVGABIOS (version %s)enter %s:No VBE DISPI interface detected, falling back to stdvgaVBE DISPI: bdf %02x:%02x.%x, bar %dVBE DISPI: lfb_addr=%x, size %d MBRemoving mode %xSeaBIOS VBE(C) 2011SeaBIOS DevelopersSeaBIOS VBE Ad


Disassembled version until iret:

Code:
.data:00000000 fa                          cli   
.data:00000001 fc                          cld   
.data:00000002 66 50                       push   %eax
.data:00000004 66 51                       push   %ecx
.data:00000006 66 52                       push   %edx
.data:00000008 66 53                       push   %ebx
.data:0000000a 66 55                       push   %ebp
.data:0000000c 66 56                       push   %esi
.data:0000000e 66 57                       push   %edi
.data:00000010 61                          popa   
.data:00000011 e8 cd 08                    call   0x000008e1
.data:00000014 ed                          in     (%dx),%ax
.data:00000015 86 68 9e                    xchg   %ch,-0x62(%bx,%si)
.data:00000018 36 6f                       outsw  %ss:(%si),(%dx)
.data:0000001a b7 e4                       mov    $0xe4,%bh
.data:0000001c 66 89 e0                    mov    %esp,%eax
.data:0000001f 50                          push   %ax
.data:00000020 e8 2f 26                    call   0x00002652
.data:00000023 68 9d c1                    push   $0xc19d
.data:00000026 f7 66 5f                    mulw   0x5f(%bp)
.data:00000029 66 5e                       pop    %esi
.data:0000002b 66 5d                       pop    %ebp
.data:0000002d 66 5b                       pop    %ebx
.data:0000002f 66 5a                       pop    %edx
.data:00000031 66 59                       pop    %ecx
.data:00000033 66 58                       pop    %eax
.data:00000035 cf                          iret


This is how did I get the data:

Code:
    uint32_t* ptr = (uint32_t*) (0x10 * 4);
    uint32_t handler_loc = *ptr;

    uint16_t segment, offset = 0;

    segment = (handler_loc >> 16) & 0xFFFF;
    offset = handler_loc & 0xFFFF;

    uint32_t address = (segment * 16) + offset;

    for (uint8_t* x = (uint8_t*) address; x < address + 500; x++)
    {
        printf(" %X ", *x);
    }


I think there are some problems in disassembly, but nevermind :P
How can I make that code to work in protected mode? With removal of override prefixes (66) and a bit modification can it work?

Is it possible at least?

Thx. :roll:

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:32 am 
Offline
Member
Member
User avatar

Joined: Thu Mar 10, 2016 7:35 am
Posts: 167
Location: Lancaster, England, Disunited Kingdom
Well you'll need to explore the two calls (which need expansion to 32 bits of course) before an answer can be given and they will need doctoring too, {as will the functions that they call}

where {} is an extended Backus-Naur syntax construct for "repeat zero or more times".
Looks unappetisingly tedious to me :-(


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:35 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
MichaelFarthing wrote:
Well you'll need to explore the two calls (which need expansion to 32 bits of course) before an answer can be given and they will need doctoring too, {as will the functions that they call}

where {} is an extended Backus-Naur syntax construct for "repeat zero or more times".
Looks unappetisingly tedious to me :-(


The memory area of calls are just empty or full of junk data, no instructions.
That made me think it is a problem of online disassembler, not interrupt.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:40 am 
Offline
Member
Member
User avatar

Joined: Tue Jan 10, 2017 3:19 pm
Posts: 84
You'll need to switch to V8086 or Real mode to get int 0x10. Otherwise, you're gonna get a bunch of garbage.

_________________
(not so frequently updated) Code is at:

https://github.com/NunoLava1998/DixiumOS-1


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:42 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
DixiumOS wrote:
You'll need to switch to V8086 or Real mode to get int 0x10. Otherwise, you're gonna get a bunch of garbage.

I don't want to call bios interrupt actually. I just want to get the code of int 0x10 handler and rewrite it in i386 assembly, not i8086. Then if I make the conversion run-time, then OS'll be able to handle int 0x10 itself.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:47 am 
Offline
Member
Member
User avatar

Joined: Thu Mar 10, 2016 7:35 am
Posts: 167
Location: Lancaster, England, Disunited Kingdom
The disassembler looks OK to me and the call mnemonics in particular correctly decode the machine coding:

i.e. .data:00000011 e8 cd 08 call 0x000008e1

is correct

e8 is the opcode for a relative call (16 bit)
0x08cd is the displacement to the call address from the next instruction (at 00000014)
0x0014+0x08cd = 0x08e1 as in the decoding you have.

Perhaps more likely that you have not correctly got the memory at the call locations?

But seriously, it's going to be a long job. This interrupt does a lot of work in lots of sub functions and is likely 16 bit all the way


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 11:58 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
MichaelFarthing wrote:
The disassembler looks OK to me and the call mnemonics in particular correctly decode the machine coding:

i.e. .data:00000011 e8 cd 08 call 0x000008e1

is correct

e8 is the opcode for a relative call (16 bit)
0x08cd is the displacement to the call address from the next instruction (at 00000014)
0x0014+0x08cd = 0x08e1 as in the decoding you have.

Perhaps more likely that you have not correctly got the memory at the call locations?

But seriously, it's going to be a long job. This interrupt does a lot of work in lots of sub functions and is likely 16 bit all the way


Tried set base address in disassembler with address of int10 handler (0xC5682) instead of 0x0, then got memory locations.
Didn't help, I still get garbage code.

This is the garbage code I got:

Code:
                           .data:00000000 cc                               int3   
                           .data:00000001 cc                               int3   
                           .data:00000002 78 00                            js     0x00000004
                           .data:00000004 00 0e 66 66                      add    BYTE PTR ds:0x6666,cl
                           .data:00000008 c6 c7 86                         mov    bh,0x86
                           .data:0000000b c6 c6 6e                         mov    dh,0x6e
                           .data:0000000e 60                               pusha 
                           .data:0000000f 00 00                            add    BYTE PTR [bx+si],al
                           .data:00000011 f0 60                            lock pusha
                           .data:00000013 60                               pusha 
                           .data:00000014 60                               pusha 
                           .data:00000015 60                               pusha 
                           .data:00000016 60                               pusha 
                           .data:00000017 62 66 fe                         bound  sp,DWORD PTR [bp-0x2]
                           .data:0000001a 00 00                            add    BYTE PTR [bx+si],al
                           .data:0000001c 0c 6e                            or     al,0x6e
                           .data:0000001e ef                               out    dx,ax
                           .data:0000001f ef                               out    dx,ax
                           .data:00000020 ed                               in     ax,dx
                           .data:00000021 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000022 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000023 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000024 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000025 60                               pusha 
                           .data:00000026 00 00                            add    BYTE PTR [bx+si],al
                           .data:00000028 c6                               (bad) 
                           .data:00000029 e6 f6                            out    0xf6,al
                           .data:0000002b fe                               (bad) 
                           .data:0000002c de ce                            fmulp  st(6),st
                           .data:0000002e c6 c6 c6                         mov    dh,0xc6
                           .data:00000031 00 00                            add    BYTE PTR [bx+si],al
                           .data:00000033 03 86 cc 6c                      add    ax,WORD PTR [bp+0x6ccc]
                           .data:00000037 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000038 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000039 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000003a 66 c3                            ret   
                           .data:0000003c 80 00 00                         add    BYTE PTR [bx+si],0x0
                           .data:0000003f fc                               cld   
                           .data:00000040 66 66 66 7c 60                   data32 data32 data32 jl 0x000000a5
                           .data:00000045 60                               pusha 
                           .data:00000046 60                               pusha 
                           .data:00000047 f0 00 00                         lock add BYTE PTR [bx+si],al
                           .data:0000004a 07                               pop    es
                           .data:0000004b cc                               int3   
                           .data:0000004c 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000004d 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000004e 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000004f 6d                               ins    WORD PTR es:[di],dx
                           .data:00000050 6d                               ins    WORD PTR es:[di],dx
                           .data:00000051 e7 cc                            out    0xcc,ax
                           .data:00000053 e0 00                            loopne 0x00000055
                           .data:00000055 0f c6 66 66 67                   shufps xmm4,XMMWORD PTR [bp+0x66],0x67
                           .data:0000005a c6 c6 66                         mov    dh,0x66
                           .data:0000005d 6e                               outs   dx,BYTE PTR ds:[si]
                           .data:0000005e 60                               pusha 
                           .data:0000005f 00 00                            add    BYTE PTR [bx+si],al
                           .data:00000061 7c c6                            jl     0x00000029
                           .data:00000063 c6                               (bad) 
                           .data:00000064 60                               pusha 
                           .data:00000065 38 cc                            cmp    ah,cl
                           .data:00000067 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000068 67 c0 00 00                      rol    BYTE PTR [eax],0x0
                           .data:0000006c 7e 7e                            jle    0x000000ec
                           .data:0000006e 5a                               pop    dx
                           .data:0000006f 18 18                            sbb    BYTE PTR [bx+si],bl
                           .data:00000071 18 18                            sbb    BYTE PTR [bx+si],bl
                           .data:00000073 18 3c                            sbb    BYTE PTR [si],bh
                           .data:00000075 00 00                            add    BYTE PTR [bx+si],al
                           .data:00000077 0c 6c                            or     al,0x6c
                           .data:00000079 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007a 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007b 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007c 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007d 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007e 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000007f 67 c0 00 00                      rol    BYTE PTR [eax],0x0
                           .data:00000083 c6 c6 c6                         mov    dh,0xc6
                           .data:00000086 c6 c6 c6                         mov    dh,0xc6
                           .data:00000089 6c                               ins    BYTE PTR es:[di],dx
                           .data:0000008a 38 10                            cmp    BYTE PTR [bx+si],dl
                           .data:0000008c 00 00                            add    BYTE PTR [bx+si],al
                           .data:0000008e 0c 6c                            or     al,0x6c
                           .data:00000090 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000091 6c                               ins    BYTE PTR es:[di],dx
                           .data:00000092 6d                               ins    WORD PTR es:[di],dx
                           .data:00000093 6d                               ins    WORD PTR es:[di],dx
                           .data:00000094 6f                               outs   dx,WORD PTR ds:[si]
                           .data:00000095 e7 c6                            out    0xc6,ax
                           .data:00000097 c0 00 00                         rol    BYTE PTR [bx+si],0x0
                           .data:0000009a c6 c6 6c                         mov    dh,0x6c
                           .data:0000009d 38 38                            cmp    BYTE PTR [bx+si],bh
                           .data:0000009f 38 6c c6                         cmp    BYTE PTR [si-0x3a],ch
                           .data:000000a2 c6 00 00                         mov    BYTE PTR [bx+si],0x0
                           .data:000000a5 06                               push   es
                           .data:000000a6 66 66 66 63 c1                   data32 data32 data32 arpl cx,ax
                           .data:000000ab 81 81 83 c0 00 00                add    WORD PTR [bx+di-0x3f7d],0x0
                           .data:000000b1 fe c6                            inc    dh
                           .data:000000b3 8c 18                            mov    WORD PTR [bx+si],ds
                           .data:000000b5 30 60 c2                         xor    BYTE PTR [bx+si-0x3e],ah
                           .data:000000b8 c6                               (bad) 
                           .data:000000b9 fe 00                            inc    BYTE PTR [bx+si]
                           .data:000000bb 00 03                            add    BYTE PTR [bp+di],al
                           .data:000000bd c3                               ret   
                           .data:000000be 03 03                            add    ax,WORD PTR [bp+di]
                           .data:000000c0 03 03                            add    ax,WORD PTR [bp+di]
                           .data:000000c2 03 03                            add    ax,WORD PTR [bp+di]
                           .data:000000c4 03 c0                            add    ax,ax
                           .data:000000c6 00 00                            add    BYTE PTR [bx+si],al
                           .data:000000c8 80 c0 e0                         add    al,0xe0
                           .data:000000cb 70 38                            jo     0x00000105
                           .data:000000cd 1c e6                            sbb    al,0xe6
                           .data:000000cf 20 00                            and    BYTE PTR [bx+si],al
                           .data:000000d1 00 3c                            add    BYTE PTR [si],bh
                           .data:000000d3 cc                               int3   
                           .data:000000d4 cc                               int3   
                           .data:000000d5 cc                               int3   

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 12:24 pm 
Offline
Member
Member
User avatar

Joined: Thu Mar 10, 2016 7:35 am
Posts: 167
Location: Lancaster, England, Disunited Kingdom
Agola wrote:

Tried set base address in disassembler with address of int10 handler (0xC5682) instead of 0x0, then got memory locations.
Didn't help, I still get garbage code.


Where did this value 0xC5682 come from?

Edit:
[More particularly, as it is a 32 bit address have you calculated it yourself from a segment:offset address. If so, did you do it correctly?]


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 12:41 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
MichaelFarthing wrote:
Agola wrote:

Tried set base address in disassembler with address of int10 handler (0xC5682) instead of 0x0, then got memory locations.
Didn't help, I still get garbage code.


Where did this value 0xC5682 come from?

Edit:
[More particularly, as it is a 32 bit address have you calculated it yourself from a segment:offset address. If so, did you do it correctly?]


Its correct, also after iret there is some ASCII text about VBE BIOS

Code:
    uint32_t* ptr = (uint32_t*) (0x10 * 4);
    uint32_t handler_loc = *ptr;

    uint16_t segment, offset = 0;

    segment = (handler_loc >> 16) & 0xFFFF;
    offset = handler_loc & 0xFFFF;

    uint32_t address = (segment * 16) + offset;


Then uint32_t address is 0xC5682

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 3:53 pm 
Offline
Member
Member
User avatar

Joined: Tue Jan 10, 2017 3:19 pm
Posts: 84
You'll need to return to Virtual 8086 mode, get 0x10 using Assembly correctly, store it somewhere, go from v8086 to protected mode and run that. If you can, anyway.

If you don't go to v8086, you're just gonna read a random segment of the memory.

_________________
(not so frequently updated) Code is at:

https://github.com/NunoLava1998/DixiumOS-1


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sat Jan 14, 2017 9:50 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

Agola wrote:
How can I make that code to work in protected mode? With removal of override prefixes (66) and a bit modification can it work?


In protected mode (and long mode) the default code size is determined by a flag in the code segment's descriptor; and if you used a 16-bit code segment (in protected mode or long mode) you wouldn't need to change override prefixes, etc.

The biggest problem is segment register loads. For a simple example, if the BIOS loads zero into ES (to access something in the BDA/BIOS Data Area) then that's fine in real mode, but in protected mode it loads the "NULL descriptor" from the GDT which would mean that every load from memory that uses ES would cause a general protection fault (and won't access the BDA).

There is no simple way to fix the problem with segment register loads. The "simple" approach (a general protection fault handler that dynamically generates a suitable descriptor) can't work correctly for various cases (e.g. loading zero into a segment register, loading a value that isn't a multiple of 4 into a segment register, etc), and is complicated by the fact that BIOS code can move a value from a segment register into a normal register and do some calculations.

Note that video cards are very different, and the code for "int 0x10" for one video card will be very different to the code for "int 0x10" for a very different video card. You can not take the code from the video card on your computer and expect it to work on other computers. Also, you can't take the video ROM code, translate it, then publish your translation; as this violates the video ROM's copyright. Both of these problems mean that you have to do it at run-time and not compile-time.

Agola wrote:
Is it possible at least?


You can't solve the problems without ending up with dynamic recompilation (e.g. a JIT), or switching to a different approach (an interpreter, virtual8086 mode, etc).

The other thing that might be worth pointing out is that BIOS is deprecated and none of this will work on modern (and future) UEFI systems. This means that any time you spend trying to get "int 0x10" to work (using any method) is going to be wasted time. The "most sane" alternative is to set the best video mode possible during boot (using the firmware, whatever the firmware is - e.g. using "int 0x10" in real mode if the firmware is BIOS, and using "GOP" or "UGA" in long mode if the firmware is 64-bit UEFI ) and then use resolution independent code for graphics after that (so that you have no valid reason to want to change from the best video mode to a worse video mode).


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Calling BIOS Int 0x10 in protected mode with a different
PostPosted: Sun Jan 15, 2017 12:58 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
I wanted to use Virtual 8086 instead of this way firstly. But I couldn't make it work even after 4 days work, then I gave up.

It immediately general protection faults after I set the VM bit of eflags, then iret. http://wiki.osdev.org/Virtual_Monitor says it'll GPF when I use a privileged instruction, not immediately.
I just have a TSS for V8086 mode with segments configured for user mode. Virtual 8086 monitor isn't fully working yet, I'll finish that after fixing that GPF ;(

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 114 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group