Pull to refresh

Хакаем DDR3 SPD

Reading time 9 min
Views 68K
Original author: Hannu Hartikainen
Я проапгрейдил старый ноутбук двумя модулями памяти 4GB DDR3-1333, но оказалось, что ноутбук совместим максимум с DDR3-1066. Что сделает настоящий мужчина? Конечно же, перепрошьёт EEPROM для ребиннинга DDR3 на более медленную модель!


Рабочее место. Справа Thinkpad для проведения перепрошивки, а слева проблемный MacBook Pro

Будьте очень осторожны. Очевидно, что вы можете повредить или навсегда заблокировать запись на свой DIMM. Возможные более тонкие неполадки, в том числе сбой логической схемы батареи, или материнская плата превратится в кирпич.

Как всё началось


У меня 13-дюймовый MacBook Pro середины 2010 года. Его файловая система была повреждена при обычной перезагрузке, и дисковая утилита (из раздела восстановления) ничего не могла с этим поделать. Ну, я давно этого ждал: пришло время поставить SSD и добавить немного оперативной памяти.

Я купил SSD и мне повезло найти в горе электронного мусора пару сломанных ноутбуков с подходящими модулями оперативной памяти. Вставляем SSD и два модуля по 4 ГБ, запускаем Internet Recovery — и через час у нас должна быть рабочая система. Но нет. Загрузка просто зависает. Из-за чего? Наибольшее подозрение вызывают эти модули RAM, в конце концов, они же из мусора. Поэтому делаем то, что сделал бы любой: создаём USB-флэшку с memtest86 и запускаем её на ночь. Отлично, память в порядке. После многих часов с пробами разных методов установки для разных версий macOS наконец приходит открытие, что всё работает отлично, если просто вставить обратно старую память.1

Истинная причина


Понимая проблему, я быстро узнал, что MacBook Pro 2009−2010 годов на самом деле не работают с памятью быстрее, чем PC3-8500, и что проблему можно обойти, изменив метаданные RAM с помощью программы Windows под названием Thaiphoon Burner.

Истинной причиной сбоя является интегрированный графический процессор GeForce 320M, который использует общую память, то есть обычную RAM. Он может работать максимум с PC3-8500 (aka DDR3-1066, то есть с тактовой частотой DRAM 533 МГц), но контроллер системной памяти не знает об этом и повышает максимальную доступную скорость до 667 МГц (т.е. PC3-10600 aka DDR3-1333). У остальных компонентов нет проблем с этим, как и у GPU в режиме VESA (я думаю).

Я не слышал ни о каком другом оборудовании, которое отказывает в работе оперативной памяти, способной к более высоким скоростям, чем оборудование может использовать. Конечно, при покупке модулей памяти на рынке продавцы предупредили бы об этом нюансе. Это всё равно намного лучше, чем припаянная оперативка, как в ноутбуках Apple с 2012 года.

Настройка прошивки


Разобравшись с причиной, я установил один оригинальный модуль PC3-8500 на 2 ГБ и один новый модуль 4 ГБ, и всё заработало. Но ребиннинг DDR3 казался хорошим проектом, поэтому я решил попробовать.

Конечно, я не собираюсь устанавливать Windows только для прошивки EEPROM и не собираюсь покупать причудливое программное обеспечение, если всё можно сделать вручную. Я думал, что задача явно должна выполняться в Linux, возможно, с некоторыми дополнительными инструментами. Я также не хотел устанавливать Linux на макбук только для этого. Поэтому мой старый надёжный Thinkpad X220 с NixOS стал идеальной площадкой для работ. Потребовалось немного времени для его обновления, потому что я не загружал машину год или около того.

Затем наступил черёд выбрать, какой модуль попробовать первым. У Thinkpad уже было два по 4 ГБ, и я нашел четыре модуля 4 ГБ, поэтому мне было из чего выбрать. Я решил начать с самого странного, производства Micron. Все остальные были Samsung. У одного была наклейка Lenovo.

Чтение SPD


Модули памяти поставляются с микросхемой EEPROM, которая содержит метаданные о модуле Serial Presence Detect (SPD). Сам формат простой, а доступ к EEPROM можно организовать через шину SMBus, которая по сути не отличается от I²C.2

К счастью, для взаимодействия с SMBus и даже чтения EEPROM DDR3 есть драйверы ядра и готовое программное обеспечение.

Во-первых, для просмотра устройств на шине нужны i2c-tools и некоторые модули ядра.

$ nix-shell -p i2c-tools
$ modprobe i2c-dev
$ modprobe i2c-i801
$ i2cdetect -l
i2c-0 unknown i915 gmbus ssc N/A
i2c-1 unknown i915 gmbus vga N/A
i2c-2 unknown i915 gmbus panel N/A
i2c-3 unknown i915 gmbus dpc N/A
i2c-4 unknown i915 gmbus dpb N/A
i2c-5 unknown i915 gmbus dpd N/A
i2c-6 unknown DPDDC-B N/A
i2c-7 unknown DPDDC-C N/A
i2c-8 unknown DPDDC-D N/A
i2c-9 unknown SMBus I801 adapter at efa0 N/A


Здесь представляет интерес адаптер SMBus, в моём случае i2c-9.

Пакет i2c-tools поставляется даже с инструментом decode-dimms для чтения информации о RAM в удобочитаемом формате. Для этого требуется модуль ядра eeprom.

$ modprobe eeprom
$ decode-dimms
$ modprobe -r eeprom


Вот часть выдачи для одного модуля памяти:

Memory Serial Presence Detect Decoder
By Philip Edelbrock, Christian Zuckschwerdt, Burkart Lingner,
Jean Delvare, Trent Piepho and others


Decoding EEPROM: /sys/bus/i2c/drivers/eeprom/9-0050
Guessing DIMM is in                              bank 1

---=== SPD EEPROM Information ===---
EEPROM CRC of bytes 0-116                        OK (0xAEA4)
# of bytes written to SDRAM EEPROM               176
Total number of bytes in EEPROM                  256
Fundamental Memory type                          DDR3 SDRAM
Module Type                                      SO-DIMM

---=== Memory Characteristics ===---
Maximum module speed                             1333 MHz (PC3-10600)
Size                                             4096 MB
Banks x Rows x Columns x Bits                    8 x 15 x 10 x 64
Ranks                                            2
SDRAM Device Width                               8 bits
Bus Width Extension                              0 bits
tCL-tRCD-tRP-tRAS                                9-9-9-24
Supported CAS Latencies (tCL)                    10T, 9T, 8T, 7T, 6T, 5T

---=== Timings at Standard Speeds ===---
tCL-tRCD-tRP-tRAS as DDR3-1333                   9-9-9-24
tCL-tRCD-tRP-tRAS as DDR3-1066                   7-7-7-20
tCL-tRCD-tRP-tRAS as DDR3-800                    6-6-6-15

---=== Timing Parameters ===---
Minimum Cycle Time (tCK)                         1.500 ns
Minimum CAS Latency Time (tAA)                   13.125 ns
Minimum Write Recovery time (tWR)                15.000 ns
Minimum RAS# to CAS# Delay (tRCD)                13.125 ns
Minimum Row Active to Row Active Delay (tRRD)    6.000 ns
Minimum Row Precharge Delay (tRP)                13.125 ns
Minimum Active to Precharge Delay (tRAS)         36.000 ns
Minimum Active to Auto-Refresh Delay (tRC)       49.125 ns
Minimum Recovery Delay (tRFC)                    160.000 ns
Minimum Write to Read CMD Delay (tWTR)           7.500 ns
Minimum Read to Pre-charge CMD Delay (tRTP)      7.500 ns
Minimum Four Activate Window Delay (tFAW)        30.000 ns

---=== Optional Features ===---
Operable voltages                                1.5V
RZQ/6 supported?                                 No
RZQ/7 supported?                                 Yes
DLL-Off Mode supported?                          Yes
Operating temperature range                      0-95 degrees C
Refresh Rate in extended temp range              2X
Auto Self-Refresh?                               Yes
On-Die Thermal Sensor readout?                   No
Partial Array Self-Refresh?                      No
Module Thermal Sensor                            Yes
SDRAM Device Type                                Standard Monolithic

---=== Physical Characteristics ===---
Module Height                                    30 mm
Module Thickness                                 2 mm front, 2 mm back
Module Width                                     67.6 mm
Module Reference Card                            F revision 0
Rank 1 Mapping                                   Standard

---=== Manufacturer Data ===---
Module Manufacturer                              Micron Technology
DRAM Manufacturer                                Micron Technology
Manufacturing Location Code                      0x0F
Manufacturing Date                               2011-W23
Assembly Serial Number                           0xFB5C7F1A
Part Number                                      16JSF51264HZ-1G4D1
Revision Code                                    0x4431

Довольно много данных. Часть показанной информации вычисляется из данных. Например, тайминги на стандартных скоростях (т.е. отсчёты цикла) вычисляются на основе параметров тайминга в наносекундном разрешении. Даже они сохранены как величины, кратные блоку развёртки (time base unit), установленному в другом месте на EEPROM, но это не относится к теме статьи. Данный модуль RAM выдаёт 7-7-7-20 на DDR3-1066, что соответствует стандарту DDR3-1066F JEDEC. Не спрашивайте меня, что такое JEDEC, но он быстрее, чем самый дешёвый DDR3-1066G.

Я потратил много времени на подтверждение моего вывода: при попытке ребиннинга памяти единственное важное число — это минимальное время цикла (tCK). Здесь это 1,5 нс, т.е. 667 МГц.

Давайте посмотрим на исходные данные.

$ i2cdump 9 0x50
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-9, address 0x50, mode byte
Continue? [Y/n]
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 92 10 0b 03 03 19 00 09 03 52 01 08 0c 00 7e 00    ??????.??R???.~.
10: 69 78 69 30 69 11 20 89 00 05 3c 3c 00 f0 82 05    ixi0i? ?.?<<.???
20: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
30: 00 00 00 00 00 00 00 00 00 00 00 00 0f 11 05 00    ............???.
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 80 2c 0f 11 23 fb 5c 7f 1a a4 ae    .....?,??#?\????
80: 31 36 4a 53 46 35 31 32 36 34 48 5a 2d 31 47 34    16JSF51264HZ-1G4
90: 44 31 44 31 80 2c 00 00 00 00 00 00 00 00 00 00    D1D1?,..........
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

Спецификации говорят, что минимальное время указано по адресу 0x0c. Посмотрим, оно в первой строке (00:), в колонке c. Кстати, его значение тоже 0x0c или 12. Это кратно средней временной базе (MTB), которая представляет собой частное от деления значения в 0x0a на значение в 0x0b (в наносекундах). Здесь 1⁄8 нс. Так что 12 MTB соответствует 1,5 нс.

Планирование изменений


Чтобы опуститься до DDR3-1066, нам нужно 533 МГц, что составляет 1,875 нс или 15 MTB, или 0x0f. То есть мы хотим написать 0x0f по адресу 0x0c.

Но подождите, очевидно, есть исправление ошибок. CRC первых 116 байт сохраняется в 0x7e-7f. Я посмотрел туда и увидел a4 ae, затем пошёл искать калькулятор для расчёта. Мне потребовалось удивительно много времени, чтобы найти работоспособный калькулятор CRC. Я попробовал несколько инструментов командной строки, но всё-таки остановился на онлайн-калькуляторе http://crccalc.com/. Затем узнал, что здесь используется вариант CRC-16/XMODEM, а контрольная сумма на самом деле 0xAEA4. Порядок байтов и всё такое. Следовало заметить её в выдаче decode-dimms.

Поэтому нужно записать новое минимальное время цикла (0x0f) по адресу 0x0c и новую контрольную сумму в 0x7e как слово.

Запись SPD


Теперь я знал, что писать, и наконец осмелился попробовать. Дрожащими руками я набрал y, нажал Enter для окончательного подтверждения и…

$ i2cset 9 0x50 0x0c 0x0f
WARNING! This program can confuse your I2C bus, cause data loss and worse!
DANGEROUS! Writing to a serial EEPROM on a memory DIMM
may render your memory USELESS and make your system UNBOOTABLE!
I will write to device file /dev/i2c-9, chip address 0x50, data address
0x0c, data 0x0f, mode byte.
Continue? [y/N] y
Error: Write failed

Ошибка. Погодите, что?

Будучи педантичным парнем, я начал изучать исходники i2cset, а также соответствующих модулей ядра. В какой-то момент я понял, что это может быть вызвано защитой от записи.

Я достал модуль памяти, посмотрел на него и узнал микросхему EEPROM. На ней написано 97B, 321 и некоторые другие вещи. Погуглив, я узнал, что это чип SE97B. Я просмотрел таблицу данных и несколько раз внимательно прочитал раздел о защите от записи. С помощью программ я предпринял несколько попыток удаления временной защиты от записи, но неудачно. Защита от записи, вероятно, была постоянной, поэтому я просто решил поискать модуль, у которого нет защиты от записи.

Забавный факт, кстати, заключается в том, что постоянная защита от записи включается записью чего-то на определённый адрес. Я не думаю, что i2cdetect нормально это делает, но запуск i2cget 9 0x30 <any-address>, вероятно, установит постоянную защиту от записи, которая действительно постоянна. Я не пробовал этого делать.

Я взял следующий модуль, и там не было никакого сообщения об ошибке. EEPROM просто не изменился.

Наконец-то, успех!


С третьим модулем наконец-то операция получилась. Я рассчитал CRC и записал его вместе с временем цикла. После загрузки модуля ядра eeprom и запуска decode-dimms модуль выглядел как обычный 4GB PC3-8500. Когда я установил его в MacBook Pro, у меня, наконец, загрузилась система с памятью 8 ГБ.


DDR3 SODIMM после ребиннинга готов к работе в MacBook Pro

До: оригинальный DDR3-1333


     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 92 10 0b 03 03 19 00 09 03 52 01 08 0c 00 3e 00    ??????.??R???.>.
10: 69 78 69 30 69 11 20 89 00 05 3c 3c 00 f0 83 01    ixi0i? ?.?<<.???
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 0f 11 45 00    ............??E.
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 80 ce 02 11 30 b1 5b 13 a1 0e 59    .....????0?[???Y
80: 4d 34 37 31 42 35 32 37 33 43 48 30 2d 43 48 39    M471B5273CH0-CH9
90: 20 20 00 00 80 ce 00 00 00 53 31 42 4e 30 30 30      ..??...S1BN000
a0: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 03    ?.?............?
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 32 59 00    .............2Y.
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

После: выглядит как DDR3-1066


     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 92 10 0b 03 03 19 00 09 03 52 01 08 0f 00 3e 00    ??????.??R???.>.
10: 69 78 69 30 69 11 20 89 00 05 3c 3c 00 f0 83 01    ixi0i? ?.?<<.???
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 0f 11 45 00    ............??E.
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 80 ce 02 11 30 b1 5b 13 a1 06 54    .....????0?[???T
80: 4d 34 37 31 42 35 32 37 33 43 48 30 2d 43 48 39    M471B5273CH0-CH9
90: 20 20 00 00 80 ce 00 00 00 53 31 42 4e 30 30 30      ..??...S1BN000
a0: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 03    ?.?............?
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 32 59 00    .............2Y.
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

Если сразу не видите разницу, то вы не копались в этих свалках так долго, как я.

Свои мысли


Стоит этим заниматься? Финансово, конечно, нет!

Но это было весело и я многому научился. Понятия не имею, где именно можно применить эти знания, но я чувствую, что в определённый момент они понадобятся. И просто само ощущение, что вы можете правильно решить задачу, действительно приятно и даёт уверенность.



1. Моё предположение, что RAM будет работает на данном оборудовании, если оно проходит memtest86, было очевидно неправильным. Тем не менее, даже оглядываясь назад, предположение не кажется глупым. По опыту, не так уж редко встречается странная комбинация аппаратного обеспечения, из-за которой падает стандартный тест.

2. Я недавно я узнал об использовании I²C в другом проекте. Думаю, что смогу считывать и записывать EEPROM на микроконтроллере Cortex-M с помощью собственной программы, но на практике пайка разъёма будет очень сложной, и написание кода — слишком большая работа, чтобы я этим заинтересовался. Тем не менее, я действительно счастлив, что теоретически способен на такое!
Tags:
Hubs:
+51
Comments 25
Comments Comments 25

Articles