Partição de recuperação personalizada

9

Estou trabalhando em um projeto em que as atualizações para o Raspberry PI serão feitas por HTTP e o Raspberry PI não estará diretamente acessível (não é possível trocar apenas cartões).

Eu gostaria de ter uma configuração de partição assim:

  • Partição 1- / boot (contém kernels para ambas as partições)
  • Partição 2- / (partição de recuperação)
  • Partição 3- / (partição primária)

Quando uma atualização falha e o Raspberry PI entra em um loop de reinicialização ou trava na inicialização, eu gostaria que o usuário pudesse pressionar um botão, que aciona uma linha GPIO, o que faria com que o carregador de inicialização inicializasse no partição de recuperação em vez da partição primária.

A partição de recuperação nunca seria atualizada, portanto seria seguro.

Vejo algumas opções:

  1. Sempre inicialize na partição de recuperação, verifique o GPIO e, em seguida, inicialize na partição primária sem pressionar nenhum botão
  2. O GPIO é verificado diretamente pelo carregador de inicialização

Basicamente, estou tentando fazer algo parecido com o que os roteadores fazem, onde, se você mantiver a redefinição enquanto inicializa, poderá usar o TFTP sobre uma nova imagem ou algo assim.

Isso é possível com o Raspberry PI? Em caso afirmativo, existe alguma documentação para fazer esse tipo de coisa?

Editar:

Encontrei esta resposta para esta pergunta relacionada: É possível fazer dual boot a partir do cartão SD?

Um comentário sobre a pergunta acima me levou aqui: http://www.berryterminal.com/doku.php/berryboot . Isso parece promissor, mas vou ter que pesquisar mais para ver se consigo ler um GPIO. Se alguém tiver alguma experiência com isso, eu ficaria muito interessado.

beatgammit
fonte
Deixe-nos saber como chegar lá com isso, parece :) interessante
Jivings
11
Eu acho que encontrei uma maneira de fazer isso escrevendo um carregador de inicialização simples de 2º estágio, por isso vou me certificar de documentá-lo aqui, se eu conseguir. Ainda esperando por uma solução simples ...
beatgammit 4/12/12
11
Infelizmente não, mas reduzi significativamente a chance de corrupção usando um sistema de arquivos RO: /boot(RO), /(RO), /var(RW), /home(RW). O problema inicial foi a corrupção do sistema de arquivos quando a energia foi cortada durante a inicialização. Eu ainda gostaria de escrever / encontrar um gerenciador de inicialização de segundo estágio.
beatgammit
11
Você pode ver o que o gerenciador de inicialização NOOBS ( raspberrypi.org/archives/4100 ) para o Pi faz. Na verdade, pode atender às suas finalidades apenas para usá-lo, pois fornece partições e instalação de recuperação.
Fred Fred
11
Estou sugerindo '' contra '' o uso de um gerenciador de inicialização personalizado, mas use hacks executados após o início do sistema. Será mais fácil de implementar e mais seguro para depurar. Um gerenciador de inicialização com defeito pode fritar seu Pi.
precisa

Respostas:

5

Se o erro ocorrer a qualquer momento após a inicialização do sistema, você pode usar um timer de watchdog e algum script de inicialização.

O princípio desse método é que, sempre que o sistema reiniciar sem desligar corretamente, ele será direcionado para a partição de recuperação.

Você precisa escrever um script que seja executado sempre que o sistema iniciar e desligar corretamente. Mude /boot/cmdline.txtpara a partição de recuperação quando o sistema for iniciado e volte a funcionar antes de desligar corretamente.

Em seguida, configure o cronômetro do watchdog. Você pode usar o embutido no chip BCM2835 ou (se estiver usando uma placa de revisão 2) construir o seu próprio usando dois pinos GPIO, o cabeçalho de redefinição P6 e um chip 555. Quando o programa crítico for iniciado, inicie o cronômetro do cão de guarda e chute o cão periodicamente se o sistema estiver funcionando corretamente. Quando o sistema falha, o timer do watchdog é acionado e redefine o processador, enviando-o para a partição de recuperação. Isso também não requer interação do usuário e, se estiver usando o timer interno, não haverá GPIO.

Usando esse método, você também pode implementar um botão de redefinição que garantirá o envio manual do sistema à recuperação em uma placa Rev. 2 instalando um botão no cabeçalho P6.

Maxthon Chan
fonte
Sua primeira resposta está um pouco mais próxima do que eu provavelmente faria, mas eu gosto da ideia de usar GPIOs no espaço do usuário e em um cão de guarda. Embora eu provavelmente não use nenhuma das idéias por atacado, você me deu boas idéias. Obrigado!
Beatgammit 24/03/2014
1

Eu tenho uma maneira de fazer isso sem hackear o kernel, que envolve a proteção do sistema contra uma reinicialização prematura:

  1. Faça o download da imagem de atualização, soma de verificação e expanda-a para o espaço disponível.
  2. Altere /boot/cmdline.txt para que, na próxima inicialização do sistema, use a partição de recuperação como o dispositivo de bloco raiz.
  3. Instale a atualização a partir do espaço de trabalho e verifique se está funcionando.
  4. Se a atualização estiver funcionando, altere /boot/cmdline.txt de volta.
  5. Se necessário, reinicie.

Uma atualização com falha fará com que o sistema seja inicializado automaticamente na recuperação. Não é necessário GPIO.

Maxthon Chan
fonte
O único problema aqui é (dependendo do sistema) que uma falha pode ser detectada horas após a conclusão da atualização, momento em que o usuário não tem opção de reverter para a partição de recuperação.
11
@ DanNixon Estou postando outra resposta para resolver esse novo problema.
Maxthon Chan
1

Além disso, existe uma terceira solução possível, mas será necessário que você disseca initrdalgumas versões de PC da distribuição Linux para descobrir como o syscall pivot_init()funciona. Não tenho certeza se o kernel do Pi tem esse syscall. Caso isso aconteça, esse método é possível, também não é necessário hackear o kernel e ele usa um GPIO.

Para fazer isso, você precisará escrever um initprograma personalizado no sistema de produção. verifique se o GPIO está ativado. Se assim for, pivot_root()a recuperação. Em seguida, exec()o original initpara que o sistema continue inicializando. Você pode, no sistema de produção, descobrir uma maneira de manter essa observação de GPIO construída em initexecução lado a lado (PID = 2) com o original init(PID = 1) e ficar de olho no GPIO e reiniciar a recuperação se o botão é pressionado.

Maxthon Chan
fonte