Считывание дампа микрокода из ПЗУ Д3-28

Настоящий материал в оригинальном (авторском виде) впервые опубликован здесь.
С разрешения автора приводим эти же сведения на нашем сайте, немного изменив стиль с форумного на повествовательный.

Общие сведения
Короче, сдампил я прошивку микрокода Д3-28. Прошивка эта от «микросхемного» модуля ПЗУ от Д3-28. (Примечание сайта d3-28.ru — бывали еще в Д3-28 ПЗУ на ферритовых сердечниках. Обычно в самых ранних моделях с 16 и 32 кбайтами ОЗУ. Располагалось такое ПЗУ не в кассете, как другие платы, а на дне корпуса под клавиатурой. В моделях более поздних 32 кбайта ОЗУ и во всех 128 кбайтных модификациях использовались только ПЗУ на микросхемах и оно находилось в кассете).
Модуль этот называется ПЕЛ3.065.001 «Устройство постоянное запоминающее».
Модуль диодно-трансформаторного ПЗУ, но его я пока не дампил — ну, как-нить потом сдамплю. (Примечание сайта d3-28.ru — что такое «диодно-трансформаторное ПЗУ» мы не знаем. Возможно это то, что нам известно как «ПЗУ на ферритовых сердечниках»).
Кому надо — дамп ПЗУ Д3-28 здесь. Это zip-архив, а в нём текстовый файл с ноликами и единичками.
Файлы с контрольными суммами md5 и sha1.

Как пользоваться дампом прошивки. Пояснения к формату файла и прочее.
1. Модуль ПЗУ имеет объём памяти:
— (М) микросхемный = 48 кбайт ровно
— (ДТ) диодно-трансформаторный = 22528 байт
2. Организация памяти:
— М — 8 кслов, каждое шириной 48 бит
— ДТ — 4 кслов, каждое шириной 44 бит
3. Шина адреса представлена двумя наборами линий — «ПX..» и «ПY..». Ну, такая несовременная нотация, очевидно, происходит из того, что линии ПX.. приходят на X-дешифратор адреса, а ПY — соответственно на Y-дешифратор, которые выбирают в XY-матрице требуемый проводок (в диодно-трансформаторном ПЗУ). В микросхемном модуле ПЗУ все эти линии приходят на адресные входы микросхем масочного ПЗУ, но нотацию менять не стали. Короче, можно рассматривать этот набор линий просто как монолитную шину адреса вот с такими хитрыми обозначениями отдельных линий:
— М — шина адреса имеет ширину 13 бит и представлена линиями ПY64, ПY32, ПY16 … ПY1, ПX32, ПX16 … ПX1
— ДТ — шина адреса имеет ширину 12 бит и представлена линиями ПY32, ПY16 … ПY1, ПX32, ПX16 … ПX1
3++. Для очень внимательных инженеров сообщу, что на самом деле в ДТ ПЗУ Y-дешифратор принимает только линии ПY16 … ПY1 — таким образом получается, что «проводков» и «диодиков» в матрице всего (2^5)*(2^6)=2048, а не 4096, как должно было бы быть для получения заявленных «4 кслов». Фишка в том, что каждый проводок проходит через 88 считывающих трансформаторов, а не через 44 (по ширине слова = 44 бит). Ну а суть линия ПY32 — она просто выбирает, какой набор из 88 трансформаторов — «первые 44» или «вторые 44» — выбрать для формирования отклика модуля. Получается, что «вторые 44 трансформатора» в те времена были дешевле, чем ещё «вторые 2048 диодиков»… Ну, на самом деле, думаю, лимитирующим фактором было место на плате, т.к. трансформаторы такого места занимают существенно меньше, чем поляна диодиков.
4. Отмечу, что я условно принял линии «ПY» как старшие разряды адреса, а линии «ПX» — как младшие. Это в общем не так суть важно, но просто строки в файле с дампом прошивки упорядочены именно исходя из такой схемы «упаковки» адресных линий.
4++. Для внимательных инженеров сообщу, что такая схема упаковки «почти» соответствует той схеме, которая принята в модуле микросхемного ПЗУ. Здесь «почти» означает, что преимущественно ПX приходят на младшие линии шины адреса A0..A12 микросхем ПЗУ, а ПY — преимущественно на старшие. Но, на самом деле, там почему-то вот именно линия ПY32 приходит на линию A0 — это как непонятное для меня исключение… Наверное с целью нас с вами — потомков — запутать :)
К чему я это уточнение сделал — ну, к тому, что если кто-то вдруг зачем-то захочет соотнести «мою» прошивку с прошивкой конкретной микросхемы из состава модуля ПЗУ, то надо иметь в виду, что там вот есть такие нюансы в принципиальной схеме. A0 = ПY32, A1 = ПX1, A2 = ПX2, ну и т.д.
5. Шина данных представлена набором линий «E..»
— М — шина данных имеет ширину 48 бит и представлена линиями E1..E48 (обратите внимание, что нумерация с «1», а не с «0»)
— ДТ — шина данных имеет ширину 44 бит и представлена линиями E1..E44
6. !! очень важное обстоятельство !! На самом деле все линии адреса и данных в модуле ПЗУ (как М, так и ДТ) — инверсные. То есть на разъёмы выведены сигналы «~ПX..», «~ПY..», «~Е..».
Как я не люблю вот эти инверсные сигналы! Это всегда так запутывает дело и заставляет писАть много-много лишних буковок, чтобы два-три раза разными словами объяснить читателю одну и ту же вещь — лишь бы тебя 300% поняли правильно.
Так вот, в моём файле данные представлены для ПРЯМЫХ (т.е. НЕинвертированных) линий —- т.е. для линий «ПX..», «ПY..», «Е..».
Если в моём файле указано, что скажем линия ПX1 принимает вот здесь значение 0 — то это означает, что на контакт разъёма платы «~ПX1» нужно подать +5 В (т.е. инвертированное значение). То же — с «ПY» и с «Е».
6++. А вот сигналы управления «СТРОБ» и пр. у этих модулей … вроде бы … не инвертированные — но это к файлу прошивки отношения уже не имеет
Вот. Ну, теперь, особенно если посмотреть схему модуля, полагаю, должно быть понятно, как работать с файлом, который я тут выложил.

Интересные моменты.
1. Я понятия не имею, зачем в микросхемном модуле ПЗУ ширина слова микрокода была увеличена до 48 бит, при том, что в диодно-трансформаторном ПЗУ она составляет 44 бита.
2. Если кто-то думает, что в верхних 24 кбайтах микросхемного модуля ПЗУ записаны супер-секретные алгоритмы, которых нет в машинах с диодно-трансформаторным ПЗУ, ну или хотя бы порнушка…
… расслабьтесь! там записана КОПИЯ нижних 24 кбайт — не больше и не меньше.
Но я бы не спешил сказать «увы» по поводу пункта 2.
Наличие второй копии прошивки:
— во-первых, позволяет сравнить её с первой копией — и, если они равны, то утверждать, что обе они сдампились правильно (ну, наверное, так можно утверждать)
— и во-вторых, если вам не повезло, и конкретно в вашем модуле ПЗУ побился один-два битика в «нижнем» банке, то вы можете перевести ваш модуль ПЗУ на работу по «верхнему» банку (в надежде, что в нём нет битых битиков). (Примечание сайта d3-28.ru — мы, зная ГДЕ применялись комплексы на Д3-28, предполагаем, что это был один из способов сделать работу более надежной).
Если кто-то захочет повторить опыт, то пишите на форум — я дам комментарии.
Схему я собрал предельно примитивную:
— шлейфы для подключения к модулю — вот это было, пожалуй, самым трудоёмким моментом,
— микроконтроллер ATmega32, четыре керамических конденсатора и один электролит в цепи питания… кварц тут не понадобился… ну, ещё я добавил светодиод, чтобы по его «условному подмигиванию» как-то видеть, что там контроллер сейчас делает,
— плата для быстрого прототипирования и пучок проводков к ней,
— блок питания… Нюанс! Модуль микросхемного ПЗУ потребляет около 1 ампера постоянного тока при напряжении питания 5 вольт,
— ну и программатор AVR ISP MKII (даже не JTAG).

Внимательные инженеры, наверное, обратили внимание, что в перечне совершенно отсутствуют детали для организации канала передачи прошивки из микроконтроллера куда-либо…
… да, такой канал там и не нужен был — я реализовал сохранение считанной прошивки в Flash память ATmega, а потом просто вычитывал всю его память через программатор (вот для чего программатор! А вы что подумали?).
Контроллер ATmega32 имеет четыре 8-битных порта. Два из них я использовал для линий адреса и управления — ПY, ПX, СТРОБ, tПЗУ, свето-диод.
Другие два — для чтения части линий шины данных «E..». В связи с этим мне пришлось дампить прошивку в три итерации, т.к. 48/16 = 3.
Рискну предположить, для чего таки нужны четыре дополнительных битика E45..E48 в микросхемном ПЗУ.
В общем, если из разрядов E45..E48 составить 4-битное двоичное число (разряд E48 — самый младший), то…
… дополнение этого числа до 16 и число единиц в разрядах E1…E44 должны быть равны по модулю 16.
То есть, эти четыре бита — это просто контрольные биты.
Например, строка:
PY….. PX…. E……………………………………………E
64….1 32…1 48….41 40….33 32….25 24….17 16…..9 8……1
0000000 101010 : 10110000 10011000 00000000 00001011 11111100 11111011
разряды E44..E1: 0000 10011000 00000000 00001011 11111100 11111011
число «единиц» равно 19
по модулю 16 получим 3
в разрядах E48..E45: 1011
составим число <E45.E48> — получим 0b1101 = десятичное 13
дополнение до 16 будет равно 3
Вот. И это выполняется по всему файлу.

Для проверки был написан вот такой небольшой скриптик на python 2.7:

f = open(«rom.txt», «r»)
for l in f:
if ‘:’ not in l:
continue
addr, data = l.strip(‘n’).split(‘ : ‘)
data = data.replace(‘ ‘, »)
e4845, e4401 = data[:4], data[4:]
ones = len([e for e in e4401 if e == ‘1’]) % 16
check = (16 — int(».join(reversed(e4845)), 2)) % 16
if check != ones:
print «ROM failure at address %s» % addr
break
else:
print «ROM is Ok»
f.close()

Модуль «микросхемного» ПЗУ для снятия дампа мне любезно предоставил наш уважаемый коллега sanders с сайта Полигон призраков, за что ему огромное спасибо!

С уважением,
Александр aka xioss