Выключение компьютера через порты

Тема в разделе "WASM.OS.DEVEL", создана пользователем T_A_M_A_R_A, 24 июл 2007.

  1. T_A_M_A_R_A

    T_A_M_A_R_A New Member

    Публикаций:
    0
    Регистрация:
    6 ноя 2006
    Сообщения:
    4
    Доброго времни суток!

    В книжках и статьях весьма неплохо описан процесс начальной загрузки компьютера. С выгрузкой (?) все не так прозрачно, во всяком случае я не видела ничего похожего на описание кода, выключающего компьютер....

    Подскажите пожалуйста, где можно узнать про то, как завершить работу системы на аппаратном уровне, работая в защищенном режиме процессора? Т.е. желательно без прерываний BIOS. А то я тут загрузчик пишу, а выключаться кнопкой что-т не смешно...

    Благодарю за внимание!
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    T_A_M_A_R_A
    Читаем спецификацию Advanced Power Management (APM).
    Там есть точки для выключения как в реальном так и в защищенном режиме.
    Код (Text):
    1. POWER_OFF:  
    2. mov ax, 0x5301  
    3. xor bx, bx  
    4. int 0x15  
    5. mov ax, 0x5308  
    6. mov bx, 1  
    7. mov cx, bx  
    8. int 0x15  
    9. mov ax, 0x530D  
    10. mov bx, 1  
    11. mov cx, bx  
    12. int 0x15  
    13. mov ax, 0x530F  
    14. mov bx, 1  
    15. mov cx, bx  
    16. int 0x15  
    17. mov ax, 0x530E  
    18. xor bx, bx  
    19. mov cx, 0x102  
    20. int 15h  
    21. mov ax, 0x5307  
    22. mov bx, 1  
    23. mov cx, 3  
    24. int 0x15  
    25. jmp $
     
  3. Denwer

    Denwer New Member

    Публикаций:
    0
    Регистрация:
    20 дек 2006
    Сообщения:
    104
    Ну и женщины пошли, что же будет дальше то?
     
  4. twgt

    twgt New Member

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    1.494
    Не поверю что это дама, пока не потрогаю :)
     
  5. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    T_A_M_A_R_A
    Это будет нелегко... С БИОСом, как показал Pavia все более-менее стандартно, а вот напрямую - тут у каждого чипсета свои заморочки. Один мой коллега что-то ковырял, но только по Intel'овским чипам, и то ругался, что они шибко разные... :dntknw: На i915 у него вроде получалось выключить питание одной записью в порт. Причем эту святую комбинацию он выковырял методом исследования обработчика все того же int 15.
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    через ACPI AFAIK можно. однако это жесть =)
     
  7. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    вообщем-то ничего особо страшного в выключении через ACPI и нет. Главная тонкость в получении значения SLP_TYP, соответствующего Soft Off. По "правильному" его надо получать из AML -- а именно, от объекта _S5, т.е. как бы само собой подразумевается наличие тяжеловесного AML-интерпретатора даже для такой простой задачи. Всю остальную инфу можно почерпнуть из таблиц в чистом виде.

    Но можно задействовать и читерский "правильный" способ, который опирается на тот факт, что _S5 (и вообще _Sx) реализован в виде dword'ового Package'а, который можно тупо найти в DSDT по сигнатуре, без парсинга AML, и взять значение для S5 напрямую.

    Есть еще один, расп..ский, способ -- взять фиксированные значения SLP_TYP вместо возни с AML-кодом. Во всех наблюдаемых чипсетах SLP_TYP для S5 равен либо 111b (7) -- чипсеты Intel, AMD, nvidia, либо 010b (2) -- чипсеты VIA. Что замечательно, это то, что у первых 010b попадает в резервед, а у вторых -- 111b в резерведе. Налицо масонский заговор, hehe. ;) Есть конечно некоторые, у которых S5 SLP_TYP не 2 и не 7, но они составляют позорное меньшинство (устаревшее).

    Вот пример того самого читерского "правильного" способа -- получение S5 SLP_TYP непосредственно из DSDT, но без парсинга AML. Из функций ядра используется только работа с физ.маппингом. Особо его не тестил на разных машинах, но по-хорошему надо потестить, т.к. по идее должен работать не только у меня, а в идеале универсально на всех тачках с ACPI. Перед тестом лучше перезагрузиться, чтобы хоть отчасти уменьшить вероятность потери каких-либо архиважных данных из-за внезапного отрубания питания. ;) Поддержка APM постепенно сходит на нет, так что на ACPI все равно придется переходить, благо afaik он приживется и под EFI.
    Код (Text):
    1. ;------------------------------------------------------------------
    2. ; Turn off PC via ACPI soft off
    3. ;------------------------------------------------------------------
    4.         pushad
    5.         mov word ptr [PM1a_CNT_SLP_S5], -1
    6. ; first, map bios' F segment
    7.         _call   MmMapIoSpace, 0F0000h, 0, 64 K, 0
    8.         push    eax
    9. ; now search RSDP struc
    10.         mov ecx, 64 K - 8
    11.  
    12. @@srch_rsdp:    cmp dword ptr [eax], ' DSR'     ; scan for "RSD PTR "
    13.         jnz @@rsdp_next
    14.         cmp dword ptr [eax+4], ' RTP'
    15.         jz  @@fnd_rsdp
    16. @@rsdp_next:    inc eax
    17.         loop    @@srch_rsdp
    18.         jmp @@done  ; RSDP signature not found
    19.  
    20. @@fnd_rsdp: _call   MmMapIoSpace, dword ptr [eax+10h], 0, 36, 0
    21.         push    eax
    22.         xchg    eax, esi
    23.         ; esi --> RSDT
    24.         lodsd
    25.         cmp eax, 'TDSR'
    26.         jnz @@rsdt_done
    27.         lodsd
    28.  
    29.         sub eax, 36
    30.         add esi, 36 - 8
    31.         shr eax, 2      ; eax = number of RSDT entries
    32.         xchg    eax, edi
    33.  
    34. @@l_rsdt:   lodsd
    35.         _call   MmMapIoSpace, eax, 0, 60h, 0    ; should be enough
    36.         push    eax
    37.         xchg    eax, ebx
    38.         cmp dword ptr [ebx], 'PCAF'
    39.         jnz @@entry_done
    40.         ; ebx --> FADT, get ACPI I/O ranges
    41.         mov eax, [ebx+38h]
    42.         mov [PM1a_EVT_BLK], eax
    43.         mov eax, [ebx+3Ch]
    44.         mov [PM1b_EVT_BLK], eax
    45.         mov eax, [ebx+40h]
    46.         mov [PM1a_CNT_BLK], eax
    47.         mov eax, [ebx+44h]
    48.         mov [PM1b_CNT_BLK], eax
    49.         movzx   eax, byte ptr [ebx+58h]
    50.         mov [PM1_EVT_LEN], eax
    51.         movzx   eax, byte ptr [ebx+59h]
    52.         mov [PM1_CNT_LEN], eax
    53.         mov ebx, [ebx+28h]  ; ebx = DSDT phys addr
    54.         ; get full mapping len
    55.         _call   MmMapIoSpace, ebx, 0, 8, 0
    56.         mov edi, dword ptr [eax+4]      ; edi = DSDT length in bytes
    57.         _call   MmUnmapIoSpace, eax, 8
    58.         ; now map the whole DSDT range
    59.         _call   MmMapIoSpace, ebx, 0, edi, 0
    60.         push    edi
    61.         push    eax
    62.         xchg    eax, edx
    63.         ; edx --> DSDT data, edi = DSDT length, scan for _S5 object
    64.  
    65.         sub edi, 8
    66.  
    67. @@l_srch_s5:    cmp dword ptr [edx], '_5S_'
    68.         jnz @@s5_next
    69.         cmp byte ptr [edx+4], 12h
    70.         jnz @@s5_next
    71.         mov al, [edx+8]
    72.         mov [PM1a_CNT_SLP_S5], al
    73.         mov al, [edx+0Ah]
    74.         mov [PM1b_CNT_SLP_S5], al
    75.         jmp short @@s5_done
    76. @@s5_next:  inc edx
    77.         dec edi
    78.         jnz @@l_srch_s5
    79.  
    80. @@s5_done:  pop eax
    81.         pop edi
    82.         _call   MmUnmapIoSpace, eax, edi    ; unmap DSDT
    83.  
    84.         push    1
    85.         pop edi     ; break
    86.  
    87. @@entry_done:   pop eax
    88.         _call   MmUnmapIoSpace, eax, 60h
    89.         dec edi
    90.         jnz @@l_rsdt
    91.  
    92. @@rsdt_done:    pop eax
    93.         _call   MmUnmapIoSpace, eax, 36
    94.  
    95. @@done:     ; unmap F segment
    96.         pop eax
    97.         _call   MmUnmapIoSpace, eax, 64 K
    98.  
    99.         ; phew! no more f**king mappings
    100.         cmp word ptr [PM1a_CNT_SLP_S5], -1
    101.         jz  @@done_off  ; probably system doesn't support Soft Off
    102.         ; do the actual transition to the S5 state
    103.         mov ebx, [PM1_EVT_LEN]
    104.         shr ebx, 1
    105.         xor eax, eax
    106.  
    107.         mov edx, [PM1a_EVT_BLK]
    108.         test    edx, edx
    109.         jz  @@done_pm1a_evt
    110.         add edx, ebx    ; edx = _EN-register I/O address
    111.         cmp ebx, 2
    112.         jnz @@not_2
    113.         out dx, ax
    114.         jmp short @@done_pm1a_evt
    115. @@not_2:    out dx, eax
    116. @@done_pm1a_evt:
    117.         mov edx, [PM1b_EVT_BLK]
    118.         test    edx, edx
    119.         jz  @@done_pm1b_evt
    120.         add edx, ebx    ; edx = _EN-register I/O address
    121.         cmp ebx, 2
    122.         jnz @@not_2_
    123.         out dx, ax
    124.         jmp short @@done_pm1b_evt
    125. @@not_2_:   out dx, eax
    126. @@done_pm1b_evt:
    127.  
    128.         ; first, write to PM1a_CNT.SLP_TYP, then to PM1b_CNT.SLP_TYP
    129.         movzx   eax, byte ptr [PM1a_CNT_SLP_S5]
    130.         shl eax, 10     ; move it to SLP_TYPx position
    131.         bts eax, 13     ; set SLP_EN
    132.         mov edx, [PM1a_CNT_BLK]
    133.         test    edx, edx
    134.         jz  @@done_pm1a_cnt
    135.         out dx, ax      ; compatible with both 16 and 32 bits
    136. @@done_pm1a_cnt:
    137.         movzx   eax, byte ptr [PM1b_CNT_SLP_S5]
    138.         shl eax, 10     ; move it to SLP_TYPx position
    139.         bts eax, 13     ; set SLP_EN
    140.         mov edx, [PM1b_CNT_BLK]
    141.         test    edx, edx
    142.         jz  @@done_pm1b_cnt
    143.         out dx, ax      ; compatible with both 16 and 32 bits
    144. @@done_pm1b_cnt:
    145. ; There is only one reason to get here -- if all the above crap didn't work
    146.  
    147. @@done_off: popad
    P.S. Это кстати и есть выключение "напрямую", т.е. через порты, с той лишь разницей что информация, в какие порты и что писать, берется от ACPI, а не от идентификации чипсетов и индивидуальной работы с ними.
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    _BC_
    в доступных мне сорцах коды для State5 искались как раз через доступ к объекту _S5. со всеми вытекающими =)
     
  9. T_A_M_A_R_A

    T_A_M_A_R_A New Member

    Публикаций:
    0
    Регистрация:
    6 ноя 2006
    Сообщения:
    4
    Denwer, twgt )))))

    А вообще всем ответившим - спасибо! Особенно вам, _BC_! Над этим я помедитирую)
     
  10. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    n0name
    да, но надо полагать, не без помощи громоздкого AML-интерпретатора? Здесь же практически никакой работы с AML. ;)

    add: кто-нть у себя пробовал запускать?
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    естественно =)
    только на VMWare. работает.
     
  12. Denwer

    Denwer New Member

    Публикаций:
    0
    Регистрация:
    20 дек 2006
    Сообщения:
    104
    Ну круто, таким методом определять пол. Я все же предпочитаю снача узнать пол, а уж потом трогать.
     
  13. apple_rom

    apple_rom Роман

    Публикаций:
    0
    Регистрация:
    1 авг 2006
    Сообщения:
    34
    Адрес:
    Минск
    Вообще, _BC_, как всегда, на высоте. Правда, я лично банально привязываюсь к чипсетам. Благо их нонче совсем не так уж и много. ;) В результате, например, для Intel получится "чуть" короче: :)
    Код (Text):
    1. mov     dx, 404h  
    2. in      ax, dx    
    3. out     0EBh, al  
    4. mov     ah, 111100b
    5. out     dx, ax
     
  14. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    apple_rom
    только еще надо тогда добавить взятие PMBASE из pci conf'а, вместо постоянной базы, она к счастью на всех интелах кроме древнейших PIIX'ов берется одинаково, c B0:lol: 31:F0:40h.
     
  15. apple_rom

    apple_rom Роман

    Публикаций:
    0
    Регистрация:
    1 авг 2006
    Сообщения:
    34
    Адрес:
    Минск
    В том то и дело, что всё к тому же самому счастью, почти всегда она (PMBASE) равна 400. :)

    п.с. Однако, повторюсь, что в случае написания "универсальной" утилиты - правильней "вычислять" всё "ручками". В частности, вычитывая нужное из PCI-регистров для Power Management.
     
  16. bohdant

    bohdant New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2008
    Сообщения:
    22
    Всем привет!

    Помогите разобраться, не могу добраться до таблиц ACPI :/
    Под виндой приведеный _BC_ пример работает великолепно.
    Работаю в защищенном режиме. Читаю в запись "RSD PTR" в биос

    Код (Text):
    1. 000FA160  52 53 44 20 50 54 52 20 6C 41 4D 49 20 20 20 00 RSD PTR lAMI   .
    2. 000FA170  00 00 FF 3F C0 6E 06 00 E9 B4 E1 2E F6 06 C1 E2 ...?.n..........
    3. Size: 20
    4. ACPI detected at: 000FA160
    5. , RsdtAddress: 3FFF0000
    6.  
    7. , Revision: 0, oem: AMI   , Checksum: 108
    По полученному адрессу находится какая то фигня:
    Код (Text):
    1. 3FFF0000  67 00 00 03 67 10 00 03 67 20 00 03 67 30 00 03 g...g...g ..g0..
    2. 3FFF0010  67 40 00 03 67 50 00 03 67 60 00 03 67 70 00 03 g@..gP..g`..gp..
    3. 3FFF0020  67 80 00 03 67 90 00 03 67 A0 00 03 67 B0 00 03 g...g...g...g...
    4. 3FFF0030  67 C0 00 03 67 D0 00 03 67 E0 00 03 67 F0 00 03 g...g...g...g...
    У меня память адрессуется 1:1 до указанного адресса включительно.
    Код (Text):
    1. {P cpuid= 0, pid= 368
    2.  Virtual  Physical Size
    3.  00001000 00001000 1048568KB---------------------- 3FFFE000h> 3FFF0000H>0 ???
    4.  80001000 3FEFC000      4KB
    5.  80002000 3FEFA000      4KB
    6.  80003000 DFFFF000      8KB
    7.  80005000 C0000000      2MB
    8. ....
    9. ....
    10. ....
    11. ....
    Может кто то что нибудь подскажет?
    Таблица RSDT копируется в оперативную память? Тогда может что то ее портит?
    Или нужно делать какие либо манипуляции с RsdtAddress?
    Вобщем жду любого совета, т.к. зашел в конкретный тупик...
     
  17. Treant

    Treant Member

    Публикаций:
    0
    Регистрация:
    24 май 2009
    Сообщения:
    247
    Хм... а я наоборот борюсь с выключением из-за ошибок!
     
  18. bohdant

    bohdant New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2008
    Сообщения:
    22
    Разобрался, операционка затирала табличку.
     
  19. lsvmo

    lsvmo New Member

    Публикаций:
    0
    Регистрация:
    21 апр 2008
    Сообщения:
    12
    В самом главном коде приведённом _BC_, есть, кажется, ошибочка
    Код (Text):
    1. mov    al, [edx+0Ah]
    2. mov    [PM1b_CNT_SLP_S5], al
    Должно быть
    [edx+09h]. По спецификации на каждое поле выделяется по байту
     
  20. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Тема старая... Если речь идет о выборке из пакета \_S5, то нужно знать AML, чтобы понять, что смещение может быть разным. Да, действительно по спецификации данный пакет должен содержать 4 значения размером 1 байт каждое, но во-первых длина пакета может кодироваться 1-4 байтами (для этого пакета достаточно 1 байта, но компилятор может поступить и подругому), а во-вторых каждое значение размером 1 байт может кодироваться 1-2 байтами (если присутствует байт-префикс, то поле имеет размер 2 байта).