|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
||||||
Как работать с жестким диском на уровне эквивалетном уровню IRQL DISPATCH или выше?01.09.2023, 19:25. Показов 5070. Ответов 41
Всем привет!
Я пишу свой гипервизор и у меня всё-таки возникла необходимость после выхода из гостевой VM писать что-либо на жесткий диск. строка 55 Кликните здесь для просмотра всего текста
https://github.com/Nitr0-G/SVM... in.cpp#L55 Когда я выхожу из гостевой VM и попадаю к себе, то я перехожу к SVMExitHandler(выше показан пример. Раскидываются коды аналогично того как это делает debug main loop по ExitCode, но только я нахожусь на уровне гипервизора, т.е. по сути на Ring -1 и управляю эксепшионами своего ЦП) Пример с картинкой: По сути я нахожусь на том месте, который я выделил красным квадратом. Моя задача писать из определенного ExitCode, к примеру DB Exception(single step трассировка) на жесткий диск (строка 70) (https://github.com/Nitr0-G/SVM... in.cpp#L70) Использование ZwWriteFile и т.п. API приводит к BSOD из-за того, что они хоть и вызываются формально на IRQL 0, но по сути я нахожусь на максимальном IRQL. В аналогии с Intel это называется VMX root mode(https://docs.hyperdbg.org/tips... -root-mode) у меня соответственно SVM root mode. Так вот встаёт главный вопрос, как драйвер для тех же sata жестких дисков выполняют на них запись? А ещё один вопрос: как происходит запись на RamDisk? Где я могу посмотреть возможные реализации того, что мне нужно и почитать теорию? Т.е. по сути мне нужно написать свою максимально низкоуровневую ZwWriteFile. P.S. Делаю это как свой проект. Сначала я пытаюсь вирутализировать свою систему, потом на этих наработках попытаюсь сделать свой гипервизор типа VirtualBox и т.п. с расширенными возможностями и меньшим детектом того, что Винда работает на гипервизоре типа VmWare со стороны системы и различных вирусов. P.P.S. Надеюсь на любую помощь: Начиная с названий различных книг, которые мне помогут в решении проблемы выше и, заканчивая предложением того, что я могу пореверсить для того, чтобы понять как оно работает.
0
|
||||||
| 01.09.2023, 19:25 | |
|
Ответы с готовыми решениями:
41
Материнская плата работает с одним жестким диском и отказывается работать с другим Компьютер самостоятельно начинает работать с жестким диском после 20-30 минут простоя Проблемы с компом или жестким диском |
|
Эксперт Hardware
|
|||||||
| 03.09.2023, 22:32 | |||||||
|
просто ваш Bus:device:Function 00:31:00 указан в 10-тичном, а в hex это будет 00:1F:00руткит по ссылки выше бесполезно парсить - он заточен под чипсеты Интела с константами - вот фрагмент из него:
1
|
|||||||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
||||
| 03.09.2023, 22:56 [ТС] | ||||
|
0
|
||||
|
Эксперт Hardware
|
||||||
| 03.09.2023, 23:21 | ||||||
|
Вот общий план действий, чтобы подобраться к регистрам ATA/SATA..
Известно, что контролёры всех вторичных девайсов висят на шине PCI. Для хранения свойств этих девайсов (в том числе и регистров) используется "PCI Config Space", или просто конфигурационное пространство. Для PciCfg биос выделяет блок вирт.памяти в самом верхнем диапазоне 32-битного адреса, т.е. 4Gb - xx. Но с приходом PCI-Express архитектура чипсетов изменилась, и теперь обычная шина PCI подключается через мост Bridge и стала дочерней по отношению к PCIe. То-есть схема стала такая:Соответственно, чтобы подобраться к какому-либо устройству, нам нужно знать адрес Root-комплекса, или RCBA. Сам Root это тоже девайс, и как все имеет свои регистры, которые ходят под ником RCRB или "Root Complex Registers Block". Таким образом, в любом случае нужно получить базу рута RCBA, через которую уже можно читать регистры любого девайса из конфиг.пространста Pci. Возьмём к примеру PciCfg контролёра SATA. По смещению от 10h до 24h в любом PciCfg лежат 6 регистров BAR девайса, или "Base Addr Reg". Значения в этих полях указываются как смещения относительно RCBA, в результате получаем дерево, с корнем "RootComplex". Если-бы в BAR лежали не смещения RVA от базы, а конкретные вирт.адреса VA, то проблем-бы не было - просто читаешь их, и попадаешь сразу в область порта регистров. Вот например BAR'ы моего контролёра диска из "PCIScope" pciAddr = 00:1F:02. Вы можете у себя в утилите "RW" выбрать из выпадающего списка "SATA Controller" и сравнить их со-своими значениями, учитывая размеры полей (удобно выставить их в 8-бит, а не 32):Кликните здесь для просмотра всего текста
1
|
||||||
|
Эксперт Hardware
|
||||||
| 03.09.2023, 23:44 | ||||||
|
По сути, можно без проблем прочитать cfg любого девайса в системе, и собрать таким образом все сведения о них. Опознать девайс можно по его кодам: "Class, Sub-Class, Prog-Interface". Например для контролёров SATA они будут равны
01018Fh, для моста PCI-to-LPC 060100h и т.д. Только какой от этого прок, если у нас нет значения RCBA? Драйвера читают значения Cfg или функцией HalGetBusDataByOffset(), или-же обратившись напрямую к диспетчеру PnP с мажорным кодом IRP_MJ_PNP, и минорными IRP_MN_QUERY_INTERFACE + IRP_MN_READ_CONFIG.
1
|
||||||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
||
| 04.09.2023, 00:19 [ТС] | ||
|
Спасибо за столь подробное объяснение!
0
|
||
|
Эксперт Hardware
|
||
| 04.09.2023, 00:37 | ||
|
Можно найти кореша у кого линух (ну или поставить его на виртуалку самому), и запросить эту команду. Мне резона нет, т.к. сижу на чипсете Intel, а вот вам - как вариант. Хотя это разовое решение, только для тестов на лок.машине. Интересным является поле в PciCfg по смещению(4) "Command Register". Это маска, в которой зарыта базовая инфа о девайсе. Например, если не установлен бит(1), то обмен через MMIO (Memory Mapped I/O) не возможен. Расшифровывается этот регистр так:
1
|
||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|||
| 04.09.2023, 00:41 [ТС] | |||
|
1
|
|||
|
Эксперт Hardware
|
|||||||||||||||||
| 04.09.2023, 01:29 | |||||||||||||||||
|
Можно посмотреть на это дело с иного ракурса.. например позвать на помощь драйвер, которому подсунуть пакет "IRP_MJ_WRITE". Только нужно разобраться, какому именно драйверу, ведь в стеке их много. Для этого воспользуемся отладчиком, чтобы получить иерархию драйверов диска в стеке. Известно, что если продвигаться от юзера к физ.диску, то драйвера расположены в порядке:
disk.sys --> atapi.sys --> psiide.sys. Между каждым из этих драйверов вклинивается ещё и acpi.sys для контроля питания и прочей лабуды - он представляет собой фильтр-драйвер FiDO, и нам не нужен. Значит запрашиваем объекты трёх/этих драйверов, после чего сразу просматриваем стек их устройств. Стек конкретного драйвера представляется отладчиком так, что первым в списке будет идти драйвер верхнего уровня (ближе к юзеру), и далее всё ближе к железу - смотрим:
partmgr.sys --> disk.sys --> atapi.sys. смотрим оставшиеся 2..
pci.sys, а это уже драйвер шины, за которой пристально следит диспетчер PNP, на предмет подключенных к ней новых устройств. Теперь посмотрим, какой из перечисленных драйверов способен обслуживать коды "IRP_MJ_WRITE", т.к. посылать их остальным драйверам бесполезно - они тупо проигнорируют запрос. Здесь из логов я удалил всё лишнее и как оказалось, запрос на запись поддерживает только disk.sys, а значит функцией IoAttachToDeviceStack() нужно вклиниваться именно в его стек:
lspci -s 00:14.0 -x = дамп моста LPC, и ключ -v в хвосте для его лога.
1
|
|||||||||||||||||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|||||||
| 04.09.2023, 06:10 [ТС] | |||||||
|
Т.е. вы предлагаете аттачнуться к стеку драйверов disk.sys. Далее сформировать DrvWrite функцию внутри своего драйвера, которая условно будет
0
|
|||||||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
||
| 06.09.2023, 12:50 [ТС] | ||
|
В общем, сделал я себе дривер(отдельный), который вроде бы и работает и я могу напрямую читать/писать через него в сектора, но в самом гипервизоре эта реализация тоже не работает xD Делаю как говорил R71MT, но только я не подключаюсь к стеку драйверов.
Сам дривер скину позже, так как сейчас ещё реализации тестирую. В теории можно ввести свою систему оповещения и как-то писать во втором потоке, но только нужно свой KeWaitForSingleObject будет сделать... Добавлено через 1 минуту IoBuildSynchronousFsdRequest IoCallDriver
0
|
||
|
Эксперт Hardware
|
|
| 06.09.2023, 14:13 | |
|
Nitro-G, блин оказывается напутал я всё..
База рута RCBA нужна только для доступа к регистрам самого чиспета (и устройств на шине LPC), а база портов SATA прописывается уже в его личном конфигурационном пространстве. То-есть для прямых операций с секторами диска из ядра, достаточно лишь найти блоки cfg контроллёров ATA/SATA в общем кфг.пространстве системы. Поскольку "Device Configuration Space" это часть спецификации шины PCI, работа с ним не зависит от типа чипсета, будь то Intel, или AMD. Нюансы я оформил в стиле FAQ для себя, но если нужно, могу выложить и сюда.
1
|
|
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
||||||||
| 06.09.2023, 21:30 [ТС] | ||||||||
|
Добавлено через 2 минуты Т.е. геометрию диска и т.п. моменты я ещё получить могу, так как я могу это сделать до входа в гипервизор, а вот далее я формирую такой код для чтения к примеру:
Добавлено через 47 минут Добавлено через 10 минут Просто согласно тому документу, который вы мне скидывали, а именно: SATA_Controller.pdf(TMS320C674x/OMAP-L1x Processor Serial ATA (SATA) Controller), то они там на 19-ой странице настраивают FIS, atapi commands and etc. Но мне это не нужно, мне нужно это как-то из венды получить...
0
|
||||||||
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|
| 07.09.2023, 07:52 [ТС] | |
|
Да я всё-таки прав. В SvmExitcodeHandler есть ровно такой же SVM root mode как и в Intel Vmx root mode
https://github.com/tandasat/Si... m.cpp#L756 Так что надо всё-таки как-то напрямую работать с портами SATA. Использование любых(не any IRQL API) ведет к BSOD'у Добавлено через 3 минуты Также надо как-то обходиться без IoBuildSynchronousFsdRequest IoCallDriver Так как они тоже ведут к BSOD'у, а соответственно делать толковую пересылку IRP пакета на запись или чтение как я это делаю в коде выше я также не могу. Добавлено через 1 минуту В память я складывать данные также не могу, так как хоть у меня и 80ГБ озу, но на описание всех структур в ASM коде и по сути построения файла трассировки у меня памяти не хватит... Добавлено через 3 минуты Хмм я нашел такое https://learn.microsoft.com/en... tion-space Также там пару статеек я нашел о написание драйверов под девайсы, как их почитаю и пойму, что толковые скину сюда. Возможно, даже переведу. Также скину сегодня вечером свою отдельную реализацию read/write sectors, но там отправляются IRP пакеты в Disk.sys для этого, а => что мне тоже это не подойдет ну и соответственно не подошло, так как уже проверил. Добавлено через 15 минут У меня в read/write sectors драйвере также есть поддержка CPP в кернеле. Так что на гитхаб, скорее всего, выложу, так как кода много
1
|
|
|
Эксперт Hardware
|
|
| 07.09.2023, 09:19 | |
|
Nitro-G, в скрепке лежит набор утилит.
Запустите из него CPUZ и на вкладке "О программе" сохраните отчёт "Как TXT-файл" (не html). В этом логе будут дампы конфиг.пространства PCI всех устройств вашего чипсета. Скиньте сюда этот лог, чтобы я сравнил структуру cfg-пространства AMD, со-своим Intel. Они должны совпадать, но всё-же..
1
|
|
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|
| 07.09.2023, 12:53 [ТС] | |
|
0
|
|
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|
| 08.09.2023, 01:40 [ТС] | |
|
1
|
|
|
7 / 7 / 0
Регистрация: 05.08.2023
Сообщений: 49
|
|||||||||||||||||
| 10.09.2023, 14:10 [ТС] | |||||||||||||||||
|
R71MT, Вы сможете пожалуйста ответить или у вас времени не хватает?
Я тут сделал реализацию записи, но столкнулся с проблемами, которые описывал выше, а именно:
Я не могу использовать семафоры на методе TraceRip, так как тогда я занимаю эксклюзивно одно ядро и система падает, так как думает, что что-то не так. Что делать в таких случаях? По хорошему это
Добавлено через 1 час 33 минуты
1)Есть пропуски в записи 2)Из-за первого пункта можно уже выкинуть в мусорку этот вариант Но код выше в данный момент самый быстрый, который можно получить из кода ещё выше. Так что думать надо как ускорить запись, так как трассировка таким образом происходит не за 30сек, а за 6 минут, а это вообще не подходит... Какие есть идеи? ZwWriteFile отрабатывает на RamDisk, так что быстрее диска просто существовать в данный момент не может. Кстати, а к чему относится примечание (https://learn.microsoft.com/ru... _pool_type) "только для внутреннего использования.". Что они подразумевают "внутренним использованием" в контексте драйвера? Я думал просто сделать запись в кэш, было бы быстрее... Добавлено через 3 минуты И насколько ограничены ресурсы NonPagedPool памяти? У меня, когда вектор начинает потреблять больше 100мибов вылет в синьку происходит...
0
|
|||||||||||||||||
|
Эксперт Hardware
|
|||||||||
| 10.09.2023, 18:35 | |||||||||
1
|
|||||||||
|
Эксперт Hardware
|
|||||||||||||||||||||
| 10.09.2023, 22:50 | |||||||||||||||||||||
|
Не уверен, что данный пост поможет чем-нибудь вам, но поскольку обещал, то выкладываю.
Я уже говорил, что создавал доку для себя, и оформил её в виде FAQ. .:: Общие сведения по работе с портами устройств из ядра ::. Известно, что обращения к портам происходит инструкциями ассемблера IN/OUT, от куда собственно и взялся термин I/O. Эти инструкции входят в состав привилегированных и доступны только из режима процессора “Real-Mode”, или нулевого кольца ОС. Библиотека ядра HAL.DLL раньше имела с десяток функций для этих нужд, но на х64 их вроде урезали. При дизассемблировании выясняется, что эти функции просто обёртка к инструкциям IN/OUT. Как и подобает функциям _cdecl, аргументы в виде адреса и номера порта передаются им через стек, а если ввод-вывод буферизованный, то ещё и значение счётчика + адрес источника/приёмника. Судя по всему, вызов этих функций даже не попадает в системную очередь DPC, а потому доступен с любого IRQL выше 1. Система просто не знает, что мы обращаемся к портам, а значит и не в состоянии их отследить.
.:: Как в системной памяти ОЗУ найти адрес конфиг.пространства устройств? ::. Всякое устройство имеет свои требования к системе – производитель зашивает их в ПЗУ своих девайсов. После процедуры POST, биос создаёт карту обнаруженных устройств и собирает их запросы в своём конфиг.пространстве. Каждой тушке выделяется блок памяти размером строго FFh=256 байт, куда биос тут-же прописывает и назначенные устройству ресурсы, типа номеров прерываний и т.п. Но у современных девайсов требований к системе гораздо больше, а потому после загрузки, ОС копирует весь cfg-space из области биос к себе в вирт.память. Кому не достаточно базовых 256-байт (привет девайсы PCI-Express), система выделят дополнительно по их запросам (иногда 4 и более Кбайт). При этом базовый блок у всех остаётся на месте, и выступает теперь в качестве заголовка. Процессорам х86 доступны 65535 физ.портов ввода-вывода с номерами 0000-FFFFh, два из которых адресуют именно “Конфиг.пространство устройств” на шине PCI (далее cfg). Номер порта должен всегда указываться в 16-битном регистре DX.1. Порт 0CF8h = CONFIG_ADDRESS. Вкл/отключает доступ ПО к cfg и определяет, в какую именно его часть нужно обратиться с запросом на RW. Значение должно содержать 32-битный адрес Long в формате BDFR: Bus:Device:Function:Register. Пример записи: mov eax,BDFR --> mov edx,0cf8h --> out dx,eax.2. Порт 0CFCh = CONFIG_DATA. Это 32-битное окно чтения/записи в пространство сfg. Адрес определяет содержимое порта CONFIG_ADDRESS. Пример чтения: mov edx,0cfсh --> in eax,dx. В спецификации на PCI представлена топология шины, где определяется макс.значения BDFR: • всего шин(В)=256 (8-бит). К первичной шине(0) чз мосты "PCI-to-PCI Bridge" подключаются вторичные. • устройств(D) на одной шине=32 (5-бит). Это контроллёры на материнской плате. • функций(F)=8 (3-бита). Подключённое к контроллёру устройство, например тот-же "Mass-Storage" ATA/SATA/SCSI. • регистров(R)=64 (6-бит). Хранит смещение в 4-байтных словах, для выбора поля в cfg устройства. 64х4=256-байтный базовый блок. При оформлении CONFIG_ADDRESS из 4-х этих составляющих, нужно обязательно установить в нём старший бит(31), который разрешает доступ к конфиг.пространству системы. Если он останется сброшенным, процессор тупо проигнорирует запрос. Это касается и двух младших бит[1:0]. Во-первых они определяют тип запроса и должны быть сброшены в нуль, а во-вторых выравнивают значение регистра(R) на 4-байтную границу. В силу того, что размеры некоторых полей меньше 8-бит, полный адрес нужно формировать путём сдвигов влево, ну или применять логическое сложение OR по маске. .:: Зоопарк PCI конфиг.пространств в системе ::. Выше упоминалось, что мостам и устройствам PCI-Express система выделяет более 256-байт пространства. В спецификации на шину PCI приводится всего три типа пространств – оно указывается в 1-байтном поле “HeaderType” каждого из cfg. Типичными значениями для этого поля являются 00, 01, 80 и 81h: Однако под номер регистра “Register Number” в CONFIG_ADDRESS отводится всего 6-бит, что ограничивает число адресуемых 32-битных регистров значением: 26=64. Поэтому позже это поле расширили до 10-бит, выделив для них из резерва ещё 4-бита. В результате имеем уже 210=1024 адресуемых регистра в общем пространстве cfg, что в сумме даёт: 1024х4=4096 байт. Первый механизм доступа обозвали PCI-CAM или “Configuration Access Mechanism”, а второй – расширенный ECAM (Enhanced). На рис.ниже представлен формат конфиг.пространства хост-контроллёра SATA. По сути, основную инфу можно вытащить и обычным САМ-механизмом, но за пределами первых 256-байт в двойном слове(90h) имеется и поле “PCS”, значение в котором хранит состояние портов SATA на мат.плате куда подключаем шлейфы. Биты[3:0] в нём отображают настройки биос вкл/выкл портов, а биты[7:4] – на каком именно из них висит клиент. Значимые поля в общем пространстве я выделил здесь цветом. Слева – это стандартный блок размером 256-байт, а справа – фрагмент расширенного: .:: Как в цикле поиска найти пространство контроллёров ATA/SATA? ::. Каждое устройство имеет свой класс, код которого лежит по смещению 0Bh=11d в его cfg. Поскольку в CONFIG_ADDRESS значение “Register Number” (далее R) позволяет читать из cfg только с шагом в 4-байта, то задаём ему значение R=2, в результате чего получим байты 8-11. Для устройств хранения данных предписан класс(1), а подкласс и интерфейс уточняют, какое именно это устройство:
что он имеет classCode = 01:06:01 (ревизия не интересна), т.е. SATA с хост-контроллёром AHCI (Advanced Host Controller Interface):.:: Что такое порт, и режимы обмена PIO / MMIO / DMA ::. • PIO или "Programmable IO" – это программный ввод-вывод под управлением ЦП. Если устройство поддерживает PIO, его порты будут находиться в пространстве в/в процессора (запросы не выставляются на адресную шину озу). Реально, девайсы имеют только регистры, которые по функциональному назначению собираются в блоки по 5-10 штук. Тогда "порт" – это просто номер блока с присвоенным ему именем, например порт-адреса, или порт-данных. Получив доступ к порту(N) мы тут-же упираемся в первый его базовый регистр, относительно которого адресуются все остальные регистры порта, например Base+4. В доках на PCI уже редко можно встретить термин "порт", а его место занял BAR “Base Address Register”, что более подходит по смыслу. Скорость обмена в режиме PIO не превышает 14 МБ/сек. • Альтернативой PIO является MMIO, или "Memory Mapped IO" (в/в с отображением в память). Здесь тоже всё под контролем ЦП, только порты устройств и все их регистры проецируются уже в память ОЗУ. Для этих целей, система резервирует порядка 1Гб своей памяти в верхних адресах так, что на 32-битных ОС становится доступно лишь 3Гб, из 4-х возможных. Именно поэтому регистры BAR всегда размером 32-бит. На 64-битных ОС часть памяти MMIO может быть перемещена за пределы первых 4Гб. Чтобы обратиться к порту на таком “расстоянии”, приходится складывать два последовательных BAR'а, что в сумме даёт один 64-битный. Свойства любого регистра BAR хранятся в нём-же, а точнее в младшей его тетраде, где указывается в том числе и разрядность 32 или 64-бит. • Режимы PIO и MMIO имеют главный недостаток – они функционируют под управлением ЦП, а значит вплоть до окончания текущей транзакации, процессор не может заниматься чем-то другим. Решает эту проблему режим обмена "Direct Memory Access" или DMA (прямой доступ к памяти). Его инициатором всегда выступает только сам девайс, который должен быть способен захватывать шину-памяти в своё распоряжение. Устройства данного класса назвали "Bus Master". Обмен начинается с того, что инициатор записывает в регистры своего порта DMA адрес получателя + размер и указатель на данные, после чего оповещает о готовности ЦП. Если шина свободна, хозяин даёт добро и больше не вмешивается в процесс, продолжая дальше заниматься своей текучкой. Указатель на порт DMA хранится в BAR(5) конфиг.пространства устройства, а его расширение UDMA-6 способно "разогнаться" макс.до 133 МБ/сек. .:: Как найти базовый порт ATA/SATA устройств ::. Обнаружив по классам 01:01:xx и 01:06:xx пространство ATA/SATA, теперь читаем значения его регистров BAR. Всего имеется шесть таких регистров: по 2 для портов первого и второго каналов SATA, база порта встроенного DMA и база порта AHCI. Смещение первого BAR =10h от начала, а последнего 24h. Поскольку 10h=16, то перед операцией чтения нужно в CONFIG_ADDRESS положить R=16/4=4. Каждый BAR размером 32-бита, а потому для чтения следующих ставим R=5,6,7, и последние R=8,9 (хотя в данном случае DMA и AHCI нам не нужны)..:: Дополнительная информация в регистрах BAR ::. Помимо непосредственно адреса, в BAR хранится ещё несколько важных деталей. В частности, самый младший бит[0] является флагом расположения порта: 0=MMIO, 1=PIO. • Если это MMIO, то в следующих битах[2:1] будет лежать разрядность данного регистра BAR: 00=32-бит, 10=64-бит. • Если-же порт физический и находится в компетенции самого ЦП, то бит[0] будет =1, а следующий бит[1] в резерве. Таким образом, чтобы получить реальное значение BAR, нужно сбросить в них эти информационные биты в нуль. Для MMIO получается 4 мл.бита (что выровнит адрес порта в памяти на границу 16-байт), а для PIO это 2-бита, в результате чего номер физ.порта будет всегда кратен 4. Обмен через порты PIO обычно юзали диски ATA/IDE, но в целях совместимости со-старым ПО, его эмулируют и большинство совремнных SATA. В таких случаях, в одном BAR указывается адрес порта в MMIO, а во-втором – номер порта PIO. Вычислить девайс с подобным раздвоением личности позволяет поле "Command Register" по смешению(4) в cfg SATA – три младших бита в нём являются флагами PIO, MMIO и BusMaster соответственно. Это видно и на скрине “PCIScope” ниже: у BAR(0,1,5) младший бит сброшен = режим обмена MMIO, а у BAR(2,3,4) он взведён = режим PIO. Так, сбросив инфо-биты в BAR мы нашли порт (физический, или указатель на него в MMIO). Но как теперь вычислить его размер, аля кол-во регистров в порту? Когда ОС выделяет ресурсы, она запрашивает их у самих девайсов, в т.ч. и кол-во требуемой им памяти в MMIO. Для этого, текущее значение BAR сохраняется, и на его место прописывается макс.адрес FFFFFFFFh. Тут логика девайса понимает, что от неё требуют вернуть размер порта в байтах, и возвращает его в тот-же BAR путём лог.сложения XOR. Это приводит к тому, что размер оказывается инверсным, т.к. в BAR уже лежало мак.значение -1. Например, если устройству требуется для порта область памяти размером в 4КБ=0FFFh, то в BAR вернётся FFFFF000h. Теперь чтобы привести его в человеческий вид, нужно применить к BAR инверсию NOT=00000FFFh, и к результату прибавить(1) =1000h, или 4096 байт. Такая вот арифметика...:: Стандартные регистры ATA/SATA ::. Порты древних устройств АТА отображались всегда в пространство ввода-вывода ЦП, а потому имели фиксированные номера. Обмен осуществлялся только посредством PIO. Поскольку IDE подразумевает девайс со-встроенным контроллёром, то хост контроллёр на мат.плате просто обслуживает шлейф и через порт окрывает доступ к физическим регистрам IDE. Его называли ещё HBA “Host Bus Adapter” или просто двуканальный хаб, на каждом канале которого можно было повесить 2 устройства Master/Slave. В регистрах BAR(0:3) конфиг.пространства параллельного ATA всегда лежат нули, а в BAR(4) указывается лишь порт встроенного в IDE контроллёра DMA. Вот номера аппаратно заданных портов АТА. Когда SATA эмулирует их, он меняет номер на свой/виртуальный, хотя и отображает его на пространство в/в ЦП. Например на скрине выше видно, что в BAR(2) прописан номер порта I/O 2080h, который является точной копией мастера АТА 01F0h:
Возьмём к примеру порт ATA 01F0h. Под номер сектора диска в нём выделяются всего 28-бит, что ограничивает всего секторов 228 = 268.435.456. Если размер одного сектора 512-байт, то получаем полный объём диска 137Gb. Чтобы преодолеть этот барьер, позже некоторые регистры в порту расширили до 16-бит. В частности, под номер сектора выделяется теперь 48-бит, а это всего: 281.474.976.710.656 штук, или диск объёмом 144 ПетаБайт. Работа с диском через порты должна всегда начинаться с идентификации клиента, для чего существует ATA-команда IDENTIFY_DEVICE. Она возвращает 512-байтный блок данных из ПЗУ девайсов ATA/SATA, где можно найти строки с названием производителя, а так-же поддержку 48-битного адреса. Все поля этого блока описываются в спецификации ACS “ATA Command Set”, а здесь я приведу лишь поля для данного случая (всего 256 2-байтных слов):
то 4-байта по смещению 78h хранят общее кол-во адресуемых секторов, а слова C8h = резерв; 2. Если набор функций 48-битного адреса поддерживается, и кол-во секторов меньше 0FFF_FFFFh=268.435.455, то 4-байта по смещению 78h и C8h должны содержать общее кол-во адресуемых секторов; 3. Если набор функций 48-битного адреса поддерживается, и кол-во секторов больше 0FFF_FFFFh,то слова 78h должны содержать 0FFF_FFFFh, а слова C8h = общее кол-во секторов.В разделе(7) спеки ACS указан набор функций вместе с утверждением, использует-ли команда 28 или 48-битную(Ex) адресацию. Если команда использует 28-битное форматирование, то в регистрах ATA: • поле Feature, Error, Count, CHS-LBA, Command, Status имеют длину 8 бит; • поле LBA имеет длину 28 бит. Если команда использует 48-битное форматирование, то: • поле Error, CHS-LBA, Command, Status имеют длину 8 бит; • поле Feature и Count имеют длину 16 бит; • поле LBA имеет длину 48 бит. В таблице ниже видно, что при 48-битной адресации, в порту 01F0h 16-битными становятся только регистры: 01F1,2,3,4,5h – это увеличивает размер порта с 8 до 12-байт. Помимо основного кода команды в регистре 1F7h, некоторые команды могут иметь и параметр, который указывается в регистре “Feature” 1F1h (например команда SMART). Эти два регистра доступны как для записи, так и для чтения. Если при чтении статуса из 1F7h будет взведён бит(0), значит предыдущая команда завершилась с ошибкой, а её характер указывается в регистре 1F1h “Error”. Бит(6) в регистре 1F6h позволяет задавать геометрию адреса: трёхмерная CHS(0), или логический номер сектора LBA(1). Бит(4) там-же раньше выбирал устройство на канале Master/Slave и для девайсов SATA должен быть сброшен в нуль. При 28-битной адресации, за одну операцию можно было записывать/считывать макс.255 секторов (см.счётчик в 1F2), теперь-же это 65.535 штук, или 32 MB. Кстати нуль в регистре счётчика 1F2h означает макс.65536 секторов, т.е. отсчёт начинается с 1 (см.описание команд R/W Sector в доке ACS):
1
|
|||||||||||||||||||||
|
Эксперт Hardware
|
||||||||||||||||
| 10.09.2023, 22:53 | ||||||||||||||||
|
.:: Примеры работы с портами “Config-Space & ATA” ::.
Код ниже проделывает всё вышеизложенное. Если убрать в нём диалог с юзером, можно уложить его и в 500 байт, т.к. сейчас его размер всего 1 КБ. Более того, можно сделать из него чисто модуль типа объектного файла. Кроме указателей на буферы он вообще не привязан к памяти, а потому может сыграть даже роль шелл-кода. Опишу в двух словах его алго: 1. Чтобы у юзера был выбор, запрашиваем у него режим сканирования конфиг.пространства PCI: если вводит нуль, то ищем АТА девайсы по класс-коду 0101h, если-же единицу, то SATA 0106h.2. Номера CFG-портов 3F8h и 3FCh заданы жёстко, поэтому проблем не возникает. Просто начинаем с BDFR=0, в результате чего из CFG получим VID/DID. Если данный адрес BDF биос не выделил ни одному девайсу, то арбитр шины PCI вернём нам значение FFFFFFFFh. В этом случае производим инкремент функции в адресе, и проверяем её на переполнение(8). Если упёрлись в потолок, сбрасываем функцию опять в нуль, и увеличиваем на 1 устройство(D) на шине. Всего их может быть 32, после чего увеличиваем соответственно шину(D), а остальные сбрасываем в дефолтный нуль.3. Если-же на запрос мы получим значение отличное от FFFFFFFFh, значит по текущему адресу в CFG кто-то есть. Здесь нужно запомнить адрес BDF, и изменить значение R=2, чтобы считать регистр/поле с класс-кодом устройства. Если класс не совпал с 0106h для SATA, то продолжаем скан выставив F+1, а если в яблочко, то ставим R=4 и в цикле читаем сразу все 4 регистра BAR, на каждой итерации прибавляя к R единицу. В системе может быть несколько устройств SATA, поэтому нужно просканировать все 256-шин.4. По окончании, берём по одному сохранённые BAR и проверяем в них мл.бит(0). Если он взедён, значит это наш клиент, с которым можно работать по протоколу PIO. Сбросив у BAR 2-младших бита, получим номер порта ввода-вывода ATA/SATA. 5. Чтобы найти нужный хард из пула имеющихся, нужно будет запросить у него ID размером в сектор, где будет строка с моделью и прочий его паспорт. Для этого, записываем в регистр(7) порта код операции IDENTIFY_DEVICE=ECh, после чего читаем из регистра(0) все 512-байт. Клиент в юзер-моде должен будет предварительно передать драйверу имя девайса, чтобы мы его опознали. 6. Запись в секторы через порты ничем не отличается от чтения идентификатора, и на доступном уровне описывается в спецификации “ATA Command Set”. В своей демке я сбрасывают дамп 512-байтного сектора в файл, чтобы пропарсить его позже. На своей системе х64 я не могу тестировать драйвера, а потому код для реального режима DOS. Вроде это всё.. Find ATA/SATA controller port
Здесь я так и непонял, почему в первом блоке BAR(2,3) имеют другие номера, а не как возвращает утилита “PCIScope”. А вот 512-байтный дамп паспорта диска, который возвратил мне запрос IDENTIFY_DEVICE. В спеке ACS имеются описание всех полей, среди которых отчётливо видны серийник, номер ревизии 3.06, а так-же модель моей старушки ST380011A. Кстати этот код отработал меньше чем за 1-сек, а ведь он просканировал все 256 шин, считал сектор и сбросил его в файл. Такие вот дела.. IDENTIFY_DEVICE dump
В дампах из CPUZ (которые вы высылали мне) наблюдаем всё тоже-самое, только поражает общее кол-во шин в системе – аж 51 штука. На чипсетах Intel я макс. насчитывал всего 10 шин, а тут.. Как видно из дампа, один из контроллёров SATA повесился на шине 45, причём все его порты отображаются в пространство ввода-вывода ЦП, и соответственно с ними можно работать через PIO:
1
|
||||||||||||||||
| 10.09.2023, 22:53 | |
|
Траблы с жестким диском или кривые руки Битва титанов или Недоразумения с жёстким диском Что-то с жестким диском или комп на помойку?
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики
1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
|
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928
Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
|
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего
Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
|
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы
Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
|
|
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока
Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
|
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
|
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат»
Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
|
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
|