Очень хочется из защищенного режима полноценной ОС (скажем Linux) прыгнуть в реальный режим с сохранением памяти и последующим JMP FAR на свой участок кода. Проделываю следующие шаги: 1. Из ядра ОС пишу образ своей 16 бит COM-программы в первый МБ физической памяти 2. Пишу в ячейки 467h offset образа, а в 469h segment образа (формат как в реальном режиме, т.е. деленный на 16) (подробно здесь: http://www.wasm.ru/forum/viewtopic.php?id=10135&p=1 ) 3. Запрещаю аппаратные прерывания, запрещаю NMI вот так: Код (Text): cli mov al,8Fh ;запрещаем NMI (80h) и выбираем байт состояния отключения 0Fh для записи в него out 70h,al ;порт КМОП-микросхемы jmp wait_1 ;задержка wait_1: 4. Устанавливаю режим восстановления после сброса процессора Код (Text): mov al,0Ah ;Устанавливаем режим восстановления после сброса out 71h,al ;(пробовал и 05h в регистр al положить) 5. Сброс Код (Text): mov al,0FEh ;команда сброса процессора out 64h,al ;в порт 64h wait_2: jmp wait_2 ;бесконечный цикл И получаю ... ничего не получаю. Зависаю намертво, графическая картинка так и остается на экране. 16-бит программа, образ которой записали в п.1 выполняет следующее: 1) размаскирует NMI, разрешает аппаратные прерывания 2) настраивает стек 3) выводит на экран тестовую фразу и ждет нажатия клавиши, после чего переходит в бесконечный цикл. 16-бит программа записанная в MBR жесткого диска отрабатывает нормально. Подскажите пожалуйста, можно ли вообще осуществить сброс из уже загруженной ОС??? (Или переход в реальный режим на крайний случай ) Из-за чего может в данном случае возникать зависание? Нужно ли сохранять какие-то участки памяти BIOS перед загрузкой Linux? Занимался ли кто-нть этой задачей? Может она не решается? HELP!!! P.S. Память таблицы векторов BIOS Linux не трогает - проверял. P.P.S. Информацию по сбросу процессора брал здесь: http://www.wasm.ru/forum/viewtopic.php?id=10135&p=1
А тебе доступ к портам клавиатуры разрешён (в IO bitmap)? Серьёзные ОСи (Linux вроде тоже к ним относится) должны защищать себя от внезапного ресета. Получишь доступ к порту и должно сбросить. ЗЫ: лучше проверять сначала клаву на готовность получать команды
как отображал часть физического адресного пространство на линейное адресное пространство ядра? через __ioremap()? какие флаги указывал для отображения?
А ты уверен что твоя программа не работает? Вот судя по этому вполне может быть что она работает. Ты перешёл в RM, видео осталось в графическом режиме. Если ты теперь текст выводиш в текстовом режиме - ты его можеш просто не увидеть. Не все BIOS'ы поддерживают TTY в графическом режиме. Ну а потом ты уже жми чего хочеш - программа в цикл входит как ты и хотел. Попробуй вместо вывода на экран "бип" поставь через динамик. Вообще покажи код RM программы.
to 10110111: Все вышеуказанные действия осуществляю прямо из инициализирующей функции модуля ядра. Т.е. гружу модуль командой insmod module.ko, выполняется инициализирующая функция модуля в ядре ОС. Просто ресет проверил - работает. Т.е. выполняю код: Код (Text): mov AL,0Fh ; выбираем байт состояния out 70h,AL mov AL,0 ; просто reset out 71h,AL mov AL,0FEh out 64h,AL wait: jmp wait и машина благополучно уходит в reboot Грешил на Vmware, но на физической тестовой машине абсолютно теже симптомы. to rei3er: доступ к физической памяти делал двумя методами: 1. запись в файл /dev/mem 2. и через virt_addr = ioremap(phys_addr,PAGE_SIZE); (без подчеркиваний в начале и с двумя аргументами) или virt_addr = ioremap_nocache(phys_addr,PAGE_SIZE); Причем склоняюсь ко второй функции. Исходники функций здесь: http://www.gelato.unsw.edu.au/lxr/source/arch/i386/mm/ioremap.c?a=i386#L191 С флагами не разбирался, поскольку думаю/надеюсь, что ОС не будет сбрасывать страницу на диск, если я ее только что использовал и она в нижней памяти. Для теста писал в файл /dev/mem и читал из памяти после ioremap_nocache. что записал, то и прочитал. Следующим постом приведу текст RM программы, может там какая ошибка закралась. А может быть скажем такой вариант, что Linux загружаясь, портит область памяти с обработчиками прерываний BIOS? Память с таблицей векторов не портится это я проверял, а вот сами обработчики? Тогда если на моменте выполнения MBR сохранить отдельные участки на диск или оттяпать кусок от 640К памяти записью в ячейку 0:[413h], а потом восстановить память перед сбросом, то может все и получится? Только вот какие области памяти конкретно надо сохранить? P.S. Спасибо за оперативные отклики
Ну вот как-то так: RM программа на NASM: Код (Text): org 100h segment .text start: mov al,0 out 70h,al ;разрешаем NMI xor ax,ax mov ss,ax mov sp,7c00h ; настраиваем стек sti ;разрешаем аппаратные прерывания cld push cs pop ds mov si,m4 next_char: ;печатаем m4 lodsb cmp al,0 je str_ok push si mov bx,7 mov ah,14 int 10h pop si jmp next_char str_ok: mov ax,0 int 16h ;wait press key wait: jmp wait section .data m4: db "Slava KPSS",0 Компилируем и собираем в 16-бит com файл. nasm -o rm_prog.com -f bin rm_prog.asm
Ну вот, то что я и говорил. Ты выводиш текст функцией BIOS TTY Write - а видеосистема в графическом режиме. BIOS не обязан поддерживать эту функцию для графического режима, это как минимум проверять надо. Во вторых - ожидание нажатия клавиши. А контроллер прерываний (или APIC - смотря что стоит) ты перепрограммировал на стандартные для RM базы? Что-то мне кажется что нет. А в PM базы скорее всего 20h и 28h. Прерывания ты разрешил, и допустим IRQ0 (Timer) постоянно будет вызывать int20h, а в RM должно вызывать int08h. С остальными аппаратными прерываниями то же самое.
Так ща буду разбираться. Спасибо за наводку. По поводу beep хорошая идея спасибо! про контроллер прерываний можно какую-нть ссылочку почитать вот чегой-то я енто упустил. Чего куда писать? Что за циферки 20h и 28h? Разве со сбросом процессора все само собой не должно на RM режим настроиться??? Можно просто ссылкой бросить или послать в направлении куда читать
Ура все заработало!!! ))))))))))) Дело действительно было в графическом режиме, неперепрограммированном при сбросе контроллере прерываний. Правильная последовательность действий в RM после сброса такова: 1. Перепрограммируем контроллер прерываний, как показано здесь : http://www.codenet.ru/progr/asm/inter.php 2. Разрешаем NMI 3. Настраиваем стек 4. Разрешаем аппаратные прерывания 5. Включаем beep 6. Ждем нажатия клавиши 7. Выключаем beep Все прекрасно работает! Спасибо всем кто откликнулся и отдельное Спасибо cppasm!
Alexius_R не забудь, что некоторые (или даже все) биосы имеют 32-разрядные калл-баки и после перехода в реальный режим можно получить оччень неожиданный результат. в частности, при перегреве проца BIOS может попытаться вызвать 32-разрядный калл-бак, что для тебя будет полной неожиданностью. до калл-бака дело даже не дойдет. все умрет еще в самом BIOS'е в BIOS'е на самом деле очень много 32-разрядного кода, причем, сама BIOS в 32-битный режим не переключается. она считает, что уже находится в нем
Хорошо, но тогда вопрос, а если я загрузился в чистый дос 16-бит реальный режим и долго и упорно работаю, код в BIOS также может неожиданно привести к падению при перегреве процессора? Или разработчики BIOS по дефолту считают, что комп недолго будет в реальном режиме работать и практически сразу перейдет в защищенный режим? Вообще реальный режим при включении компа отличается от реального режима при сбросе из защищенного?
фигня какая-то, никто не обещал что всегда будет переход в защищенный режим, есть куча real-mode ОС, и что по-твоему во всех них биос будет глючить ? в общем хотелось бы либо подробное объяснение либо примеры насчет 32 битного кода в студию.
набор инвариантов реального режима не отличается но "косметические" отличия могут быть + состояние физической памяти, кэшей, значения MSR-регистров, регистров общего назначения и пр. могут быть разные под "косметическими" отличиями понимается нечто типа изменных разрядностей сегментов, измененных лимитов сегментов и пр