использование Ke386CallBios

Тема в разделе "WASM.WIN32", создана пользователем LightElf, 4 июн 2005.

  1. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    Всем привет!



    Не поделитесь примером использования Ke386CallBios в NT4 и XP?



    Чего-то не то делаю видимо, система в перезагрузку уходит.
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Не знаю, поможет ли чем
    Код (Text):
    1. NTSTATUS
    2. Ke386CallBios (
    3.     IN ULONG BiosCommand,
    4.     IN OUT PCONTEXT BiosArguments
    5.     )
    6.  
    7. /*++
    8.  
    9. Routine Description:
    10.  
    11.     This function invokes specified ROM BIOS code by executing
    12.     "INT BiosCommand."  Before executing the BIOS code, this function
    13.     will setup VDM context, change stack pointer ...etc.  If for some reason
    14.     the operation fails, a status code will be returned.  Otherwise, this
    15.     function always returns success reguardless of the result of the BIOS
    16.     call.
    17.  
    18.     N.B. This implementation relies on the fact that the direct
    19.          I/O access operations between apps are serialized by win user.
    20.  
    21. Arguments:
    22.  
    23.     BiosCommand - specifies which ROM BIOS function to invoke.
    24.  
    25.     BiosArguments - specifies a pointer to the context which will be used
    26.                   to invoke ROM BIOS.
    27.  
    28. Return Value:
    29.  
    30.     NTSTATUS code to specify the failure.
    31.  
    32. --*/




    http://66.102.9.104/search?q=cache:No9f56ZMgkoJ:cvs.cosoft.org.cn/cgi- bin/viewcvs.cgi/fileshare/FreeWin/drivers/video/miniport/vbe/vbemp.c%3 Frev%3DHEAD+Ke386CallBios&hl=en
     
  3. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    БИГ САНКС!!!!!!!!!!!!! а то я до исходников так и не дотянулся, понять не могу, куда засунул :dntknw:
     
  4. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13




    Ну прототип я знаю (его из videoprt.sys видно). Больше конечно хотелось бы увидеть кусок реального сорца. За линк на ReactOS спасибо. Остался невыясненным вопрос - насколько поведение Ke386CallBios в ReactOS и в NT похожи, если учесть что даже прототипы разные ;)
     
  5. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Про различия между прототипами для ROS и NT сложно сказать, авторы же никогда не видели оригинальные сорцы :))). Но почему-то кажется, что KV86M_REGISTERS чем-то сильно похожа на CONTEXT.
     
  6. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13




    Такое ощущение, что у Ke386CallBios разные прототипы в NT4 и XP. Причем у XP точно CONTEXT, а вот у стрктура NT4 больше похожа на KV86M_REGISTERS...
     
  7. sarinn

    sarinn New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2005
    Сообщения:
    3
    Адрес:
    Незе Мля
    Для получения информацию о VBE-режимах VideoPortInt10 не подходит т.к. не задействует регистр ES, a функции:

    а) Eax=0x4F00/Int10 - VBE_GET_CONTROLLER_INFORMATION
    б) Eax=0x4F01/Int10 - VBE_GET_MODE_INFORMATION

    именно в ES:EDI передают необходимый блок информации.

    годится только Ke386CallBios(), её декларация:

    Код (Text):
    1. #define SIZE_OF_80387_REGISTERS 80
    2. typedef struct _FLOATING_SAVE_AREA {
    3. ULONG ControlWord;
    4. ULONG StatusWord;
    5. ULONG TagWord;
    6. ULONG ErrorOffset;
    7. ULONG ErrorSelector;
    8. ULONG DataOffset;
    9. ULONG DataSelector;
    10. UCHAR RegisterArea[SIZE_OF_80387_REGISTERS];
    11. ULONG Cr0NpxState;
    12. } FLOATING_SAVE_AREA;
    13.  
    14. typedef struct _CONTEXT {
    15. ULONG ContextFlags;
    16. ULONG Dr0;
    17. ULONG Dr1;
    18. ULONG Dr2;
    19. ULONG Dr3;
    20. ULONG Dr6;
    21. ULONG Dr7;
    22. FLOATING_SAVE_AREA FloatSave;
    23. ULONG SegGs;
    24. ULONG SegFs;
    25. ULONG SegEs;
    26. ULONG SegDs;
    27. ULONG Edi;
    28. ULONG Esi;
    29. ULONG Ebx;
    30. ULONG Edx;
    31. ULONG Ecx;
    32. ULONG Eax;
    33. ULONG Ebp;
    34. ULONG Eip;
    35. ULONG SegCs; // MUST BE SANITIZED
    36. ULONG EFlags; // MUST BE SANITIZED
    37. ULONG Esp;
    38. ULONG SegSs;
    39. } CONTEXT;
    40.  
    41. typedef CONTEXT *PCONTEXT;
    42.  
    43. NTSTATUS
    44. Ke386CallBios (
    45. IN ULONG BiosCommand,
    46. IN OUT PCONTEXT BiosArguments
    47. );
    Вот пример использования Этой Ф-ции:

    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));

    BiosRegisters.Eax = 0x4F00;
    BiosRegisters.Es = (ULONG)MemoryAddress >> 4;
    BiosRegisters.Edi =(ULONG)MemoryAddress & 0xF;
    Status = Ke386CallBios(0x10, &BiosRegisters);
     
  8. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    2 sarinn:



    1) Перед тем как вызывать Ke386CallBios, нужно мапнуть в контекст текущего процесса сам биос, видеопамять, досовские вектора прерываний, кусок памяти, в который ядро положит trampoline code и так далее.

    2) Требуется, чтобы первый мегабайт этого процесса был свободен

    3) Вызывать надо всегда из одного и того же процесса



    В общем ИМХО проще использовать VideoPortInt10, где весь этот геморрой уже за тебя сделан
     
  9. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    LightElf

    а можно поинтереосваться откуда такие сведения по поводу вышеизложенного ??
     
  10. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    Это не из ROS:
    Код (Text):
    1. NTSTATUS
    2. Ke386CallBios (
    3.     IN ULONG BiosCommand,
    4.     IN OUT PCONTEXT BiosArguments
    5.     )
    6.  
    7. /*++
    8.  
    9. Routine Description:
    10.  
    11.     This function invokes specified ROM BIOS code by executing
    12.     "INT BiosCommand."  Before executing the BIOS code, this function
    13.     will setup VDM context, change stack pointer ...etc.  If for some reason
    14.     the operation fails, a status code will be returned.  Otherwise, this
    15.     function always returns success reguardless of the result of the BIOS
    16.     call.
    17.  
    18.     N.B. This implementation relies on the fact that the direct
    19.          I/O access operations between apps are serialized by win user.
    20.  
    21. Arguments:
    22.  
    23.     BiosCommand - specifies which ROM BIOS function to invoke.
    24.  
    25.     BiosArguments - specifies a pointer to the context which will be used
    26.                   to invoke ROM BIOS.
    27.  
    28. Return Value:
    29.  
    30.     NTSTATUS code to specify the failure.
    31.  
    32. --*/
    33.  
    34. {
    35.  
    36.     NTSTATUS Status = STATUS_SUCCESS;
    37.     PVDM_TIB VdmTib;
    38.     PUCHAR BaseAddress = (PUCHAR)V86_CODE_ADDRESS;
    39.     PTEB UserInt10Teb = (PTEB)INT_10_TEB;
    40.     PKTSS Tss;
    41.     PKPROCESS Process;
    42.     PKTHREAD Thread;
    43.     USHORT OldIopmOffset, OldIoMapBase;
    44.     PVDM_PROCESS_OBJECTS VdmObjects;
    45.     ULONG   ContextLength;
    46.  
    47. //  KIRQL OldIrql;
    48. //#if DBG
    49. //    PULONG IdtAddress;
    50. //    ULONG RegionSize;
    51. //    ULONG OldProtect;
    52. //#endif
    53.  
    54.     //
    55.     // Map in ROM BIOS area to perform the int 10 code
    56.     //
    57.  
    58.     if (!BiosInitialized) {
    59.         RtlZeroMemory(UserInt10Teb, sizeof(TEB));
    60.     }
    61.  
    62. //#if DBG
    63. //    IdtAddress = 0;
    64. //    RegionSize = 0x1000;
    65. //    ZwProtectVirtualMemory ( NtCurrentProcess(),
    66. //                             &IdtAddress,
    67. //                             &RegionSize,
    68. //                             PAGE_READWRITE,
    69. //                             &OldProtect
    70. //                             );
    71. //#endif
    72.  
    73.     try {
    74.  
    75.         //
    76.         // Write "Int BiosCommand; bop" to reserved user space (0x1000).
    77.         // Later control will transfer to the user space to execute
    78.         // these two instructions.
    79.         //
    80.  
    81.         *BaseAddress++ = INT_OPCODE;
    82.         *BaseAddress++ = (UCHAR)BiosCommand;
    83.         *(PULONG)BaseAddress = V86_BOP_OPCODE;
    84.  
    85.         //
    86.         // Set up Vdm(v86) context to execute the int BiosCommand
    87.         // instruction by copying user supplied context to VdmContext
    88.         // and updating the control registers to predefined values.
    89.         //
    90.  
    91.         //
    92.         // We want to use a constant number for the int10.
    93.         //
    94.         //
    95.         // Create a fake TEB so we can switch the thread to it while we
    96.         // do an int10
    97.         //
    98.  
    99.         UserInt10Teb->Vdm = (PVOID)VDM_TIB_ADDRESS;
    100.         VdmTib = (PVDM_TIB)VDM_TIB_ADDRESS;
    101.         RtlZeroMemory(VdmTib, sizeof(VDM_TIB));
    102.         VdmTib->Size = sizeof(VDM_TIB);
    103.         *pNtVDMState = 0;
    104.  
    105.         //
    106.         // extended registers are never going to matter to
    107.         //  an Int10 call, so only copy the old part of the
    108.         //  context record.
    109.         //
    110.         ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
    111.         RtlMoveMemory(&(VdmTib->VdmContext), BiosArguments,  ContextLength);
    112.         VdmTib->VdmContext.SegCs = (ULONG)BaseAddress >> 4;
    113.         VdmTib->VdmContext.SegSs = (ULONG)BaseAddress >> 4;
    114.         VdmTib->VdmContext.Eip = 0;
    115.         VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG);
    116.         VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
    117.         VdmTib->VdmContext.ContextFlags = CONTEXT_FULL;
    118.  
    119.     } except (EXCEPTION_EXECUTE_HANDLER) {
    120.  
    121.         Status = GetExceptionCode();
    122.     }
    123.  
    124.     //
    125.     // The vdm kernel code finds the Tib by looking at a pointer cached in
    126.     // kernel memory, which was probed at Vdm creation time.  Since the
    127.     // creation semantics for this vdm are peculiar, we do something similar
    128.     // here.
    129.     //
    130.  
    131.     try {
    132.  
    133.         //
    134.         // We never get here on a process that is a real vdm.  If we do,
    135.         // bad things will happen  (pool leak, failure to execute dos and windows apps)
    136.         //
    137.         ASSERT(PsGetCurrentProcess()->VdmObjects == NULL);
    138.         VdmObjects = ExAllocatePoolWithTag(
    139.             NonPagedPool,
    140.             sizeof(VDM_PROCESS_OBJECTS),
    141.             '  eK'
    142.             );
    143.  
    144.  
    145.         //
    146.         // Since we are doing this on behalf of CSR not a user process, we aren't
    147.         // charging quota.
    148.         //
    149.         if (VdmObjects == NULL) {
    150.             Status = STATUS_NO_MEMORY;
    151.         } else {
    152.  
    153.             //
    154.             // We are only initializing the VdmTib pointer, because that's the only
    155.             // part of the VdmObjects we use for ROM calls.  We aren't set up
    156.             // to simulate interrupts, or any of the other stuff that would be done
    157.             // in a conventional vdm
    158.             //
    159.             RtlZeroMemory( VdmObjects, sizeof(VDM_PROCESS_OBJECTS));
    160.  
    161.             VdmObjects->VdmTib = VdmTib;
    162.  
    163.             PsGetCurrentProcess()->VdmObjects = VdmObjects;
    164.         }
    165.     }  except (EXCEPTION_EXECUTE_HANDLER) {
    166.  
    167.         Status = GetExceptionCode();
    168.     }
    169.  
    170.     if (Status == STATUS_SUCCESS) {
    171.  
    172.         //
    173.         // Since we are going to v86 mode and accessing some I/O ports, we
    174.         // need to make sure the IopmOffset is set correctly across context
    175.         // swap and the I/O bit map has all the bits cleared.
    176.         // N.B.  This implementation assumes that there is only one full
    177.         //       screen DOS app and the io access between full screen DOS
    178.         //       app and the server code is serialized by win user.  That
    179.         //       means even we change the IOPM, the full screen dos app won't
    180.         //       be able to run on this IOPM.
    181.         //     * In another words, IF THERE IS
    182.         //     * MORE THAN ONE FULL SCREEN DOS APPS, THIS CODE IS BROKEN.*
    183.         //
    184.         // NOTE This code works on the assumption that winuser serializes
    185.         //      direct I/O access operations.
    186.         //
    187.  
    188.         //
    189.         // Call the bios from the processor which booted the machine.
    190.         //
    191.  
    192.         Thread = KeGetCurrentThread();
    193.         KeSetSystemAffinityThread(1);
    194.         Tss = KeGetPcr()->TSS;
    195.  
    196.         //
    197.         // Save away the original IOPM bit map and clear all the IOPM bits
    198.         // to allow v86 int 10 code to access ALL the io ports.
    199.         //
    200.  
    201.         //
    202.         // Make sure there are at least 2 IOPM maps.
    203.         //
    204.  
    205.         ASSERT(KeGetPcr()->GDT[KGDT_TSS / 8].LimitLow >= (0x2000 + IOPM_OFFSET - 1));
    206.         RtlMoveMemory (Ki386IopmSaveArea,
    207.                        (PVOID)&Tss->IoMaps[0].IoMap,
    208.                        PAGE_SIZE * 2
    209.                        );
    210.         RtlZeroMemory ((PVOID)&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);
    211.  
    212.         Process = Thread->ApcState.Process;
    213.         OldIopmOffset = Process->IopmOffset;
    214.         OldIoMapBase = Tss->IoMapBase;
    215.         Process->IopmOffset = (USHORT)(IOPM_OFFSET);      // Set Process IoPmOffset before
    216.         Tss->IoMapBase = (USHORT)(IOPM_OFFSET);           //     updating Tss IoMapBase
    217.  
    218.         //
    219.         // Call ASM routine to switch stack to exit to v86 mode to
    220.         // run Int BiosCommand.
    221.         //
    222.  
    223.         Ki386SetupAndExitToV86Code(UserInt10Teb);
    224.  
    225.         //
    226.         // After we return from v86 mode, the control comes here.
    227.         //
    228.         // Restore old IOPM
    229.         //
    230.  
    231.         RtlMoveMemory ((PVOID)&Tss->IoMaps[0].IoMap,
    232.                        Ki386IopmSaveArea,
    233.                        PAGE_SIZE * 2
    234.                        );
    235.  
    236.         Process->IopmOffset = OldIopmOffset;
    237.         Tss->IoMapBase = OldIoMapBase;
    238.  
    239.         //
    240.         // Restore old affinity for current thread.
    241.         //
    242.  
    243.         KeRevertToUserAffinityThread();
    244.  
    245.         //
    246.         // Copy 16 bit vdm context back to caller.
    247.         //
    248.         // Extended register state is not going to matter,
    249.         // so copy only the old part of the context record.
    250.         //
    251.         ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
    252.         RtlMoveMemory(BiosArguments, &(VdmTib->VdmContext), ContextLength);
    253.         BiosArguments->ContextFlags = CONTEXT_FULL;
    254.  
    255.         //
    256.         // Free the pool used for the VdmTib pointer
    257.         //
    258.         ExFreePool(PsGetCurrentProcess()->VdmObjects);
    259.         PsGetCurrentProcess()->VdmObjects = NULL;
    260.  
    261.     }
    262.  
    263. //#if DBG
    264. //    IdtAddress = 0;
    265. //    RegionSize = 0x1000;
    266. //    ZwProtectVirtualMemory ( NtCurrentProcess(),
    267. //                             &IdtAddress,
    268. //                             &RegionSize,
    269. //                             PAGE_NOACCESS,
    270. //                             &OldProtect
    271. //                             );
    272. //#endif
    273.  
    274.     return(Status);
    275. }
     
  11. sarinn

    sarinn New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2005
    Сообщения:
    3
    Адрес:
    Незе Мля
    А в WindowsXP/2003 есть НОВЫЙ ПОЛНОЦЕННЫЙ Int10CallBios() API для работы с прерыванием INT10.

    Именно он используется в VGA.SYS от XP/2003.

    Пример:
    Код (Text):
    1.    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
    2.    BiosRegisters.Eax = 0x4F15;
    3.    BiosRegisters.Ebx = 0;
    4.    BiosRegisters.Edi = 0;
    5.    BiosRegisters.SegEs = 0;
    6.    VBEDeviceExtension->Int10Interface.Int10CallBios(
    7.       VBEDeviceExtension->Int10Interface.Context,
    8.       &BiosRegisters);
    Подробная информация здесь: "Display and print devices: Windows XP DDK" (Built on Friday, February 18, 2005) - http://www.navozhdeniye.narod.ru/g.zip
    И здесь: http://www.osronline.com/ddkx/graphics/vpfncs_3odj.htm
    И еще (M$): http://msdn2.microsoft.com/en-us/library/aa479122.aspx