Программирование драйверов

Тема в разделе "WASM.BEGINNERS", создана пользователем s3dworld, 26 янв 2011.

  1. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго вечера!

    Вот я практически добрался до такого момента, когда уже пора прощаться с R-Mode. И вот раз я покидаю R-Mode, то мне нужно будет написать два драйвера: драйвер для дисковода гибких дисков и драйвер клавиатуры.

    Проблема не понимания у меня заключается в том, что адрес, где будет лежать в памяти (в страничной памяти) драйвер, точно не известен. То есть драйвера будут загружать куда-то по адресу, ближе к ядру операционной системы. Но чёткого адреса нет. Тогда вот я и думаю, как же тогда проектировать такие драйвера в коде. Вот например буду я писать так драйвер:

    Код (Text):
    1. use64
    2. org 0x0000000000000000
    3. ; Код драйвера
    И таким образом у меня будет начинаться каждый драйвер. Но ведь этот драйвер потом может попасть на любую страничку, но точно не на страничку с индексом 0. В связи с этим будут рассчитаны не правильно смещения. Я вижу два вариант решения проблемы.

    ПЕРВЫЙ ВАРИАНТ
    Писать драйвера так, чтобы у них было своё адресное пространство процесса. То есть свои таблицы страниц, загрузка в CR3.

    ВТОРОЙ ВАРИАНТ
    Вводить какую-нибудь переменную:

    Код (Text):
    1. use64
    2. org 0x0000000000000000
    3. jmp startDriver
    4.  
    5. driverAddress dq 0x0000000000000000
    6.  
    7. startDriver:
    8.     ; Код драйвера
    При загрузке драйвера в память подставлять значение в поле driverAddress. А в самом коде драйвера делать обращения от базы driverAddress.

    В общем это то, что было в голове. Как делаете Вы?
     
  2. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    s3dworld
    Драйвер грузится самой ОС, у него есть своя точка входа.
    ОС сама ищет точку входа, и передает ей управление.
     
  3. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    s3dworld
    ну в винде же драйвера таблицу релокаций имеют, это и позволяет им загружаться по произвольным адресам.
    поэтому и в вашем случае надо сделать некий загрузчик, настраивающий смещение по таблице релоков.

    хотя можно и самонастраивающиеся драйвера сделать, поместив в точку входа базонезависимый код, выполняющий настройку.
     
  4. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    Если нужно именно 64-битный драйвер то можно и без релокаций обойтись. Код можно легко сделать базонезависимым.

    При получение аддресса для фасм.
    вместо
    Код (Text):
    1. mov rax,driverAddress
    используй всегда lea
    Код (Text):
    1. lea rax,[driverAddress]    ;опкод с rip-аддрессацией
    В 32-битных релоки более нужные т. к. базонезависимыми их труднее делать.
     
  5. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    s_d_f
    Спасибо, большое! Я про оператор lea до этого времени вообще не знал.

    То есть получается что lea загружает смещение от начала кода до того места, куда указывает метка. Я вот начал делать вчера по такому принципу:

    Код (Text):
    1. use64
    2. org 0x0000000000000000
    3.  
    4. addressGetPower     dq GetPower
    5. addressSetEngineOn  dq SetEngineOn
    6. addressSetEngineOff dq SetEngineOff
    7.  
    8. ; *************************************************************************************
    9. ;           Ф У Н К Ц И И    Д Р А Й В Е Р А    Г И Б К О Г О    Д И С К А
    10. ; *************************************************************************************
    11.  
    12. ; -------------------------------------------------------------------------------------
    13. ; Формат:     bool GetPower(void);
    14. ; Описание:     Проверка подачи питания дисководу
    15. ; Результат:   false - нет питания, true - питание есть
    16. ; -------------------------------------------------------------------------------------
    17. GetPower:
    18.     xor AL,AL
    19.     mov DX,0x03F1
    20.     in AL,DX
    21.     test AL,00000001b
    22.     je _getPower_Off
    23.    
    24.     mov RAX,1
    25.     jmp _getPower_Exit
    26.  
    27. _getPower_Off:
    28.     xor RAX,RAX
    29.  
    30. _getPower_Exit:
    31. ret
    32.  
    33. ; -------------------------------------------------------------------------------------
    34. ; Формат:     bool SetEngineOn(unsigned char _drive);
    35. ; Описание:     Включение мотора дисковода
    36. ; Параметры:   _drive - номер дисковода (1 либо 2)
    37. ; Результат:   false - ошибка, true - всё нормально
    38. ; -------------------------------------------------------------------------------------
    39. SetEngineOn:
    40.     ; [RBP+16] - _drive
    41.    
    42.     push RBP
    43.     mov RBP,RSP
    44.    
    45.     mov RAX,[RBP+16]
    46.     test RAX,RAX
    47.     jz _setEngineOn_Error
    48.     cmp RAX,2
    49.     jg _setEngineOn_Error
    50.    
    51.     mov DX,0x03F2
    52.     mov AL,0
    53.     out DX,AL
    54.     cmp [RBP+16],word 1
    55.     je _setEngineOn_Drive1
    56.     jmp _setEngineOn_Drive2
    57.    
    58. _setEngineOn_Drive1:
    59.     mov AL,0x1C
    60.     jmp _setEngineOn_DriveC
    61.  
    62. _setEngineOn_Drive2:
    63.     mov AL,0x2D
    64.    
    65. _setEngineOn_DriveC:
    66.     out DX,AL
    67.     mov CX,8000
    68.    
    69. _setEngineOn_Delay:
    70.     loop _setEngineOn_Delay
    71.     jmp _setEngineOn_Complete
    72.  
    73. _setEngineOn_Error:
    74.     xor RAX,RAX
    75.     jmp _setEngineOn_Exit
    76.  
    77. _setEngineOn_Complete:
    78.     mov RAX,1
    79.  
    80. _setEngineOn_Exit:
    81.     mov RSP,RBP
    82.     pop RBP
    83. ret 8
    84.  
    85. ; -------------------------------------------------------------------------------------
    86. ; Формат:     bool SetEngineOff(unsigned char _drive);
    87. ; Описание:     Выключение мотора дисковода
    88. ; Параметры:   _drive - номер дисковода (1 либо 2)
    89. ; Результат:   false - ошибка, true - всё нормально
    90. ; -------------------------------------------------------------------------------------
    91. SetEngineOff:
    92.     ; [RBP+16] - _drive
    93.    
    94.     push RBP
    95.     mov RBP,RSP
    96.    
    97.     mov RAX,[RBP+16]
    98.     test RAX,RAX
    99.     jz _setEngineOff_Error
    100.     cmp RAX,2
    101.     jg _setEngineOff_Error
    102.    
    103.     mov DX,0x03F2
    104.     cmp [RBP+16],word 1
    105.     je _setEngineOff_Drive1
    106.     jmp _setEngineOff_Drive2
    107.    
    108. _setEngineOff_Drive1:
    109.     mov AL,0x0C
    110.     jmp _setEngineOff_DriveC
    111.  
    112. _setEngineOff_Drive2:
    113.     mov AL,0x0D
    114.    
    115. _setEngineOff_DriveC:
    116.     out DX,AL
    117.     jmp _setEngineOff_Complete
    118.  
    119. _setEngineOff_Error:
    120.     xor RAX,RAX
    121.     jmp _setEngineOff_Exit
    122.  
    123. _setEngineOff_Complete:
    124.     mov RAX,1
    125.  
    126. _setEngineOff_Exit:
    127.     mov RSP,RBP
    128.     pop RBP
    129. ret 8
    Раз смещение 0, то и проблем меньше. В самом верху находятся адреса функции, которые указывают смещение именно от самого начала. Таким образом, когда ядро загрузит драйвер по определённому адресу, оно этот адрес внесёт в таблицу. И когда нужно будет вызвать какую-то функцию из драйвера, ядро возьмём адрес расположения драйвера и сложит его с адресом начала функции. На полученный адрес и будет передано управление.

    А за lea ещё раз огромное спасибо! Это ведь благодаря ей я смогу в драйвере хранить локальные переменные (именно не локальные переменные функции, а статические/глобальные переменные драйвера), к которым будут обращаться функции.
     
  6. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Вот тут я описал свои сложности: http://dubrovkin.h18.ru/TPD.htm

    Надеюсь кто-нибудь поможет их решить.