воскресенье, 23 января 2022 г.

Превращаем блок питания EMC SPS в обычный бесперебойник

Волею судеб попал мне в руки блок гарантированного питания от EMC Clariion, CX3 или CX4 (за давностью документов уже не осталось). Само СХД было давно списано, а блок пылился на шкафу уже много лет. На самом блоке написано "Southboro, MA01772 Standby power supply". Парт намбер, если кому интересно - 100-809-017.
Естественно, возникло желание использовать его дома как обычный бесперебойник - все же 1200 ватт заявлено на наклейке. Сам он без шумящих вентиляторов, нет никаких пищящих динамиков, плоский, так что можно запихать куда-нибудь под шкаф в спальне и он не будет мешать спать. А металлический корпус спасет от пожара.

Сам блок выглядит так:

Прикупил к нему по новогодней акции 5 батареек (родные уже давно сдохли от переразряда), зарядил - но, как говорится, беда подкралась откуда не ждали. После отключения 220в - блок выключается ровно через 2 минуты.
Природная бережливость не дала его выбросить или выставить на Авито, чтобы отбить хотя бы стоимость батарей, поэтому я решил посмотреть что же там внутри. Вдруг удастся его убедить так быстро не выключаться.

Снял крышку - и понял, что тут мне повезло. Внутри стоит микросхема PIC16F877A, причем не впаянная, а во вполне удобной колодке:
Кроме того, она еще и оказалась без защиты от дампа прошивки.

Сдампил прошивку через программатор K150. Под Windows 11 он данную микросхему понял только в режиме ICSP - пришлось подключить ее на весу проводками:
Чтобы провода держались лучше - вставил микросхему в колодку, которая была в наличии. 

Прошивка нормально считалась, внутри видны строки и команды бутлоадера:


IDA также нормально восприняла файл

Собственно, можно приступать к анализу.

Так как блок питания отключается через 120 секунд - логично предположить, что эта цифра где-то присутствует в коде. Это может быть цифра 120 (0x78), 120000 (0x1D4C0) и еще какие-нибудь варианты. Так как процессор "маленький", в первую очередь интересует поиск однобайтной константы. 

В данном процессоре, наиболее часто употребляемый способ загрузить куда-то константу - это команда MOVLW. Ее код для значения 0x78 - "3078". 

Делаю поиск, нашлось всего 4 места. Для иллюстрации приведу первое:
Видно, что по адресу byte_DATA_2E кладется интересующая нас цифра.
Но нас интересует не просто место установки значения переменной, а еще и то, как с данной переменной потом работают. Если это таймер - то переменная должна уменьшаться на 1.

Смотрим, как используется byte_DATA_2E:
И видим команду DECF. Похоже на то, что нам надо.

Для проверки - делаю простой тест.
Правлю константу 0x78 в прошивке на 0x3C. Тем самым время выключения должно со 120 секунд уменьшиться до 60.
(выделенную на скриншоте цифру 78 надо поменять на 3C) 

Заливаю прошивку, проверяю - работает! Блок питания вырубился теперь не через 120 секунд, а ровно через минуту после отключения питания.

Вот так с первой попытки угадать нужное место - это ли не удача? Оказывается нет, не так всё просто. Меняю константу на 0xFF, тем самым устройство должно отключаться через 255 секунд. Заливаю прошивку - и блок питания отключается через 120 секунд, как будто я ничего  не менял.

Значит, надо идти другим путем.
Смотрю на код, который уменьшает ячейку на 1. Ячейку я переименовал в SomeCounter.
Видим, что тут сравнивается значение ячейки с нулем, потом она уменьшается на 1 и снова сравнивается с нулем. Такая же операция производится с ячейкой byte_DATA_2D (кстати, в коде есть место, где в нее тоже записывается 0x78). Во всех случаях при нуле идет переход на loc_CODE_3E3. 

А что будет, если код после loc_CODE_3E3 не будет выполняться?

Для этого сразу после CLRWDT (сброс watchdog, на всякий случай лучше его оставить) ставим RETURN. Как видно из кода по адресу 03E2, код команды RETURN - 0008.
Прошивку правим непосредственно в Microbrn, шьем, выдергиваем провод питания - и блок питания работает минуту, две, три... То есть, грязный хак удался.

Я достиг чего хотел - блок питания теперь не выключается через 2 минуты. Правильнее сказать, он не выключается теперь никогда, точнее, пока батареи полностью не разрядятся. Выключить его теперь просто невозможно - если выдернуть питание или выключить выключатель, он переходит на батареи и будет сидеть на них "вечно". Зарядка батарей происходит нормально, мой ПК проработал на батареях 40 минут, после чего я устал ждать и включил питание назад. 

Как я думаю, лучше батареи не разряжать в ноль, так как после этого, скорее всего, блок питания просто откажется с ними работать. Да и сроку их жизни это не пойдет на пользу. 

Что еще я "отрубил топором" кроме отключения - неизвестно. Поэтому данную модификацию не советую использовать вообще никому! А если будете использовать, то точно не на сервере жизнеобеспечения, а на чем-нибудь некритичном, вроде лампочки в туалете.

Еще крайне не советую после подобной модификации прошивки лезть в блок питания для извлечения PIC контроллера не отключив батареи. Можно получить очень неприятный удар током.


Доп информация.
На блоке питания есть коммуникационный разьем. Напряжение там 5 вольт. Распиновку я нашел где-то в интернете, дополнил своими комментариями:

1

Ground

Земля

2

ENABLED_OUT

5В при работе от батарей, либо при зарядке батарей

3

AC_FAIL_OUT

5В при отсутствии на входе 220В

4

ANY_FAULT_OUT

Всегда 5В, жаль не проверил на оригинальной прошивке

5

SPS transmit to SP

 

6

SPS receive from SP

 

Хоть в прошивке и видны какие-то команды, и я нашел в ней место инициализации UART (скорость 9600) - мне не удалось добиться общения с устройством по СОМ порту. Но статус, думаю, можно брать по AC_FAIL_OUT, а сдохшие батареи по ANY_FAULT_OUT. Для лампочки в туалете этого достаточно.

Комментариев нет: