Пользовательский раздел восстановления


9

Я работаю над проектом, в котором обновление до Raspberry PI выполняется по протоколу HTTP, а Raspberry PI не будет доступен напрямую (нельзя просто поменять местами карты).

Я хотел бы настроить раздел следующим образом:

  • Раздел 1- / boot (содержит ядра для обоих разделов)
  • Раздел 2- / (раздел восстановления)
  • Раздел 3- / (основной раздел)

Когда обновление идет плохо и Raspberry PI попадает в цикл перезагрузки или зависает при загрузке, я бы хотел, чтобы пользователь мог нажать кнопку, которая запускает линию GPIO, которая заставляет загрузчик загружаться в раздел восстановления вместо основного раздела.

Раздел восстановления никогда не будет обновлен, так что это будет безопасно.

Я вижу пару вариантов:

  1. Всегда загружайтесь в раздел восстановления, проверьте GPIO, затем загрузитесь в основной раздел без нажатия кнопки
  2. GPIO проверяется загрузчиком напрямую

Я в основном пытаюсь сделать что-то похожее на то, что делают маршрутизаторы, где, если вы удерживаете перезагрузку во время загрузки, вы можете использовать TFTP поверх нового образа или чего-то еще.

Это возможно с Raspberry PI? Если да, есть ли документация для такого рода вещей?

Редактировать:

Я нашел ответ на этот связанный вопрос: возможно ли двойная загрузка с SD-карты?

Комментарий по вышеупомянутому вопросу привел меня сюда: http://www.berryterminal.com/doku.php/berryboot . Это выглядит многообещающе, но мне придется больше исследовать его, чтобы посмотреть, смогу ли я получить из него GPIO. Если у кого-то есть опыт, я был бы очень заинтересован.


Дайте нам знать, как вы
справляетесь

1
Я думаю, что нашел способ сделать это, написав простой загрузчик 2-го этапа, поэтому я обязательно документирую его здесь, если смогу обойти это. Все еще надеясь на простое решение, хотя ...
beatgammit

1
К сожалению, нет, но я значительно снизил вероятность повреждения с помощью файловой системы RO: /boot(RO), /(RO), /var(RW), /home(RW). Первоначальной проблемой было повреждение файловой системы при отключении питания во время загрузки. Я все еще хотел бы написать / найти загрузчик 2-го этапа, хотя.
beatgammit

1
Вы можете посмотреть, что делает загрузчик NOOBS ( raspberrypi.org/archives/4100 ) для Pi. Это может на самом деле соответствовать вашим целям только для его использования, так как он предусматривает восстановление разделов и установку.
Фред

1
Я предлагаю «против» использования собственного загрузчика, но используйте хаки, которые запускаются после запуска системы. Это будет легче реализовать и безопаснее отлаживать. Неисправный загрузчик может поджарить ваш пи.
Maxthon Chan

Ответы:


5

Если ошибка может произойти в любое время после запуска системы, вы можете использовать сторожевой таймер и некоторый загрузочный скрипт.

Принцип этого метода заключается в том, что всякий раз, когда система перезагружается без надлежащего выключения, она переходит в раздел восстановления.

Вам нужно написать скрипт, который запускается каждый раз, когда система запускается и правильно завершает работу. Перейдите /boot/cmdline.txtв раздел восстановления при запуске системы и вернитесь обратно, прежде чем правильно завершить работу.

Затем настройте сторожевой таймер. Вы можете использовать встроенный в микросхему BCM2835 или (при использовании платы ревизии 2) построить свой собственный, используя два вывода GPIO, разъем сброса P6 и микросхему 555. Когда запускается критическая программа, запустите сторожевой таймер и периодически пинайте собаку, если система работает правильно. При сбое системы сторожевой таймер отключается и сбрасывает процессор, отправляя его в раздел восстановления. Это также не требует взаимодействия с пользователем, а если используется встроенный таймер, нет GPIO.

Используя этот метод, вы также можете реализовать кнопку сброса, которая гарантирует отправку системы для восстановления вручную на плате Rev. 2 путем установки кнопки в заголовок P6.


Ваш первый ответ немного ближе к тому, что я, вероятно, сделаю, но мне нравится идея использования GPIO в пользовательском пространстве и сторожевом таймере. Хотя я, вероятно, не буду использовать какие-либо идеи оптом, вы дали мне несколько хороших идей. Спасибо!
beatgammit

1

У меня есть способ сделать это без взлома ядра, который включает в себя защиту системы от несвоевременной перезагрузки:

  1. Загрузите образ обновления, проверьте его и разверните в пустое место.
  2. Измените /boot/cmdline.txt, чтобы при следующей загрузке системы она использовала раздел восстановления в качестве корневого блочного устройства.
  3. Установите обновление с нуля и убедитесь, что оно работает.
  4. Если обновление работает, измените /boot/cmdline.txt обратно.
  5. При необходимости перезагрузите компьютер.

При неудачном обновлении система будет автоматически загружена в систему восстановления. GPIO не требуется.


Единственная проблема здесь - это (в зависимости от системы) ошибка может быть обнаружена через несколько часов после завершения обновления, после чего у пользователя нет возможности вернуться в раздел восстановления.

1
@DanNixon Я отправляю другой ответ, чтобы решить эту новую проблему.
Maxthon Chan

1

Кроме того, существует третье возможное решение, но оно потребует, чтобы вы проанализировали initrdнекоторую версию дистрибутива Linux для ПК, чтобы выяснить, как pivot_init()работает системный вызов . Я не уверен, что ядро ​​Пи имеет этот системный вызов. Если это так, этот метод возможен, взлом ядра также не требуется, и он использует один GPIO.

Для этого вам нужно написать пользовательскую initпрограмму в производственной системе. проверьте, включен ли GPIO. Если так, то pivot_root()до восстановления. Затем exec()оригинал, initчтобы система продолжала загружаться. В производственной системе вы можете найти способ обеспечить непрерывную работу этого устройства наблюдения за GPIO init(PID = 2) с оригиналом init(PID = 1), следить за GPIO и перезагружаться для восстановления, если кнопка нажата.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.