Você PODE fazer com que o código seja executado mexendo com a linha de comando do kernel. O método mais óbvio é substituir init por outra coisa. A aplicação mais comum disso é iniciar um shell muito cedo no processo de inicialização, geralmente porque você precisa corrigir alguma coisa ou porque todo o resto está muito danificado, por exemplo:
init=/bin/bash
Lembre-se de que, neste ponto do processo de inicialização, os sistemas de arquivos ainda estão todos montados somente leitura. Além disso, há um monte de coisas que simplesmente não funcionam corretamente. Como você não tem um init real em execução, o desligamento e a reinicialização não funcionarão. É necessário remontar manualmente o sistema de arquivos raiz somente leitura e chamar reboot -f
a reinicialização, por exemplo.
Não tenho idéia se você pode passar argumentos para o bash dessa maneira. Eu nunca tentei. Em teoria, se você pode passar -c
para o bash, pode dizer ao processo do bash para fazer qualquer coisa. Mas pode se transformar em um argumento bastante longo, e não sei se o kernel permitiria essas coisas.
Segunda coisa que você pode fazer. Você pode copiar um ramfs inicial (initramfs) para o sistema de arquivos e configurar o gerenciador de inicialização para usá-lo config.txt
. Existem várias maneiras de inserir scripts em um initramfs para fazer coisas especiais. Você precisará preparar um initramfs especial para esse fim (consulte initramfs-tools (8)), portanto, não tenho certeza se esta é uma solução melhor do que uma imagem personalizada.
Você pode incluir o script em / boot (eu ri de sua sugestão sobre máquinas "regulares", mas seria o pouco que você pode acessar a partir dessas máquinas) e tente iniciá-lo usando a linha init do kernel, mas os arquivos dos sistemas de arquivos não são é executável, a menos que você o faça para todo o sistema de arquivos.
Se fosse eu, eu faria uma imagem personalizada que usa dhcp para configurar a rede e que contém um script personalizado que é executado na inicialização. Este script verifica um arquivo específico que atua como um sinalizador. Se o arquivo existir, não faça nada. Caso contrário, configure as coisas e crie o arquivo de sinalizador.
Seu script de configuração pode até extrair a coisa real de um servidor http. Isso significa que você não precisa criar uma nova imagem se precisar ajustar algo.
Essa deve ser a solução menos estressante.
Uma possibilidade final, mas você terá que fazer isso em uma máquina "não-regular" :-) Você pode montar o sistema de arquivos ext4 em um dispositivo de loop e copiar arquivos para ele sem escrever primeiro no sdcard. Para uma imagem Jessie Raspbian padrão, seria algo como isto:
sudo losetup /dev/loop0 /tmp/gw.img -o 62914560
sudo mount /dev/loop0 /mnt
sudo cp /my/superduper/script.sh /mnt
sudo umount /dev/loop0
sudo fsck -f /dev/loop0 # This is optional
sudo losetup -d /dev/loop0
Eu gosto de fazer um fsck forçado nos meus sistemas de arquivos antes de fazer imagens. Define a contagem de montagem como zero na primeira inicialização :-)
EDIT : Depois de muitos meses e mais experiência. Você quer olhar para o u-boot. Substitua o carregador de inicialização por u-boot. Isso pode ser feito a partir de uma "máquina comum". Depois de inicializar o u-boot, você pode inicializar em rede uma distribuição a partir da qual pode facilmente exibir o cartão sd ou, em teoria, o cartão diretamente, embora eu não tenha ideia de quão difícil isso seria.
Essencialmente, o u-boot traz o boot de rede para o Raspberry Pi, algo que ele não suporta por si só.