Meu Game Stick GD10 veio com o cartão corrompido, e reinstalar o sistema me ensinou mais sobre boot Amlogic do que eu gostaria
Comprei na Shopee um Game Stick GD10 daqueles genéricos, com dois controles sem fio e a promessa de "40 mil jogos", para dar de presente. O anúncio dizia Amlogic S905X com 2 GB de RAM.
Funcionou exatamente um dia. No dia seguinte a TV mostrou uma tela de erro de sistema de arquivos e o aparelho não subiu mais. Presente estreado e quebrado antes de completar 48 horas.

A conclusão óbvia era que o cartão SD que veio de fábrica tinha morrido. Comprei um Kodak de 32 GB e achei que seria coisa de vinte minutos: baixar uma imagem do EmuELEC, gravar, plugar e jogar. Foram várias horas, três problemas que eu não fazia ideia que existiam, e uma boa dose de erros meus. Este artigo é o registro disso, com todos os links e comandos, principalmente para quando eu (ou você) comprar outro desses.
Primeiro, um banho de realidade no hardware
Antes de baixar qualquer coisa, resolvi espiar o cartão original no notebook. Ele ainda montava parcialmente, e a partição de boot tinha os arquivos de sempre de um sistema Amlogic:
aml_autoscript
dtb.img
kernel.img
SYSTEM
O dtb.img é o device tree, o arquivo que descreve o hardware para o kernel. Rodei strings nele e a primeira linha entregou tudo:
gxl_p281_1g
p281 é a placa de referência do S905W. E 1g é a quantidade de RAM: 1 GB. Ou seja, o anúncio mentiu duas vezes. Não é S905X e não são 2 GB.
Isso não é detalhe cosmético. Se eu tivesse confiado no anúncio e usado o device tree de um S905X com 2 GB, o aparelho simplesmente não daria vídeo, e eu passaria horas procurando o problema no lugar errado. A lição aqui é direta: não confie na descrição do anúncio, leia o dtb.img do cartão que veio no aparelho.
O cartão de fábrica não estava só corrompido, era falsificado
Olhando o tamanho do cartão original, apareceu algo estranho:
sda 48,83 GiB (52,4 GB)
Não existe cartão SD de 52,4 GB. Um 64 GB real reporta cerca de 59,5 GiB. Aquele número quebrado é a assinatura clássica de um cartão adulterado, daqueles que têm o controlador modificado para declarar mais capacidade do que a memória física realmente tem. Tudo que é gravado além do limite real vira lixo silenciosamente.
Isso explicava a corrupção, e explicava por que a partição de jogos dizia ter 46 GB ocupados. Boa parte daquilo nunca existiu de fato. Não consigo provar qual gravação específica derrubou o sistema, mas num cartão assim é questão de tempo: qualquer escrita que caia numa região inexistente se perde em silêncio, e um dia ela cai numa estrutura de que o sistema depende.
O Kodak de 32 GB que comprei reportou 29,12 GiB (31,3 GB), que é exatamente o esperado de um cartão honesto. Se quiser ter certeza antes de confiar num cartão, a ferramenta certa é o f3 (Fight Flash Fraud), que grava e relê o cartão inteiro para detectar capacidade adulterada. A documentação dele explica os modos de uso; no Fedora está no repositório oficial como f3.
Escolhendo a versão: a mais nova não serve
Aqui está a primeira armadilha real. O EmuELEC tem duas linhas de build para Amlogic:
- Amlogic-ng, com kernel 4.9, para S905X2, X3, X4 e S922X
- Amlogic (legacy), com kernel 3.14, para S905, S905X, S905W e S912
O S905W do Game Stick está na linha legacy. E consultando os releases do projeto, a 4.3 é a última versão que ainda publicou build legacy. Da 4.4 em diante só existe Amlogic-ng, que não roda nesse chip de jeito nenhum.
Ou seja, baixar a versão mais recente é garantia de tela preta. É preciso descer até a release v4.3 e pegar o EmuELEC-Amlogic.aarch64-4.3-Generic.img.gz. Repare no nome: se tiver -ng, é a imagem errada.
curl -LO https://github.com/EmuELEC/EmuELEC/releases/download/v4.3/EmuELEC-Amlogic.aarch64-4.3-Generic.img.gz
curl -LO https://github.com/EmuELEC/EmuELEC/releases/download/v4.3/EmuELEC-Amlogic.aarch64-4.3-Generic.img.gz.sha256
sha256sum -c EmuELEC-Amlogic.aarch64-4.3-Generic.img.gz.sha256
gunzip EmuELEC-Amlogic.aarch64-4.3-Generic.img.gz
Gravar é o dd de sempre, conferindo antes com lsblk qual é o dispositivo do cartão:
sudo dd if=EmuELEC-Amlogic.aarch64-4.3-Generic.img of=/dev/sdX bs=4M conv=fsync status=progress
sync
Dentro da imagem existe uma pasta device_trees com dezenas de arquivos. Peguei o gxl_p281_1g.dtb e comparei com o dtb.img do cartão de fábrica:
29787d812a3d7276456f34531ef083be gxl_p281_1g.dtb
29787d812a3d7276456f34531ef083be dtb-original.img
MD5 idêntico. Isso me deu certeza absoluta de que era o device tree certo, sem tentativa e erro.
Com a imagem já gravada, a troca é montar a primeira partição do cartão e sobrescrever o dtb.img. Note que a imagem traz um dtb.img genérico de 344 KB, que é um contêiner com vários device trees; ele é substituído por um único arquivo de cerca de 41 KB:
sudo mount /dev/sdX1 /mnt
sudo cp /caminho/para/gxl_p281_1g.dtb /mnt/dtb.img
sync && sudo umount /mnt
Aproveitei para expandir a segunda partição, que vem com apenas 32 MB e ocuparia o cartão inteiro sozinha no primeiro boot. Fazer isso manualmente dá mais controle:
sudo parted -s /dev/sdX resizepart 2 100%
sudo e2fsck -f -y /dev/sdX2
sudo resize2fs /dev/sdX2
Se você expandir por conta própria, remova depois o arquivo /storage/.please_resize_me da segunda partição, senão o sistema tenta redimensionar de novo no primeiro boot. Volto a esse detalhe adiante.
Tela preta: o problema que quase me fez desistir
Gravei a imagem, troquei o device tree, expandi a partição de dados, coloquei no aparelho. Tela preta. Nem logo, nem splash, absolutamente nada.
O cartão antigo, mesmo quebrado, ainda mostrava a tela de erro. Então o hardware estava vivo e o problema era o cartão novo. Comecei a eliminar suspeitos.
Os arquivos de boot estavam íntegros, o MD5 do kernel.img e do SYSTEM batiam com os arquivos .md5 da própria imagem, e o device tree estava correto. Sobrou o aml_autoscript, o script que o u-boot executa para dar boot pelo cartão. Comparei os dois e o MD5 era diferente. Achei que tinha encontrado a causa.
Mas era pista falsa. O aml_autoscript é um arquivo com 64 bytes de cabeçalho u-boot seguido do payload. Descontando o cabeçalho, os 731 bytes de conteúdo eram byte a byte idênticos. O que diferia era só o timestamp de compilação e, por consequência, o CRC. Descartar essa pista foi o que me levou ao lugar certo.
O lugar certo é a área reservada antes da primeira partição. Chips Amlogic têm uma BootROM que procura o bootloader no setor 1 do cartão. Medi quantos bytes não-zero existiam ali nos dois cartões:
cartão de fábrica : 733.938 bytes não-zero (de 1.048.064)
cartão novo : 0 bytes não-zero
Zero. A imagem oficial do EmuELEC não traz bootloader na área reservada. Ela pressupõe que o aparelho tenha um u-boot interno capaz de encadear o aml_autoscript, o que vale para a maioria das TV Boxes, mas não vale para esses Game Sticks. A BootROM procurava o bootloader, encontrava zeros e desistia antes de qualquer coisa chegar à tela. Daí a tela preta absoluta.
A correção é copiar essa área de um cartão que funcione. No meu caso, a primeira partição do cartão de fábrica começa no setor 2048 e a do cartão novo no setor 8192, então copiar os setores 1 a 2047 é seguro, sem risco de encostar nos dados:
# sdX = cartão de fábrica (origem), sdY = cartão novo (destino)
# preserva o setor 0 (tabela de partições) e para bem antes da primeira partição
sudo dd if=/dev/sdX of=/dev/sdY bs=512 skip=1 seek=1 count=2047 conv=fsync
Confira os setores iniciais das suas partições antes de rodar isso. Dá para ler sem root:
cat /sys/block/sdX/sdX1/start
Depois dessa cópia, deu imagem na TV. Esse é, na minha opinião, o ponto mais importante deste artigo: guarde o cartão original mesmo depois de aposentado, porque aqueles 717 KB podem ser insubstituíveis.
"We can't find any systems": esse aqui foi culpa minha
O EmulationStation subiu, mas com uma mensagem dizendo que não encontrou nenhum sistema. Os jogos estavam todos no cartão, nos diretórios certos.

O problema é que eu tinha tentado ser esperto. Antes do primeiro boot, criei pastas dentro de /storage para já deixar idioma e fuso configurados. Parecia inofensivo. Não é. Olhe o que o emuelec_autostart.sh faz:
CONFIG_DIR="/storage/.emulationstation"
CONFIG_DIR2="/storage/.config/emulationstation"
if [ ! -L "$CONFIG_DIR" ]; then
ln -sf $CONFIG_DIR2 $CONFIG_DIR
fi
O teste é "se não for um symlink". Como eu tinha criado um diretório de verdade ali, a condição deu verdadeira e o ln -sf rodou. Só que ln -sf com um diretório existente como destino não substitui a pasta: ele cria o link dentro dela. O resultado foi um .emulationstation/emulationstation inútil, e o EmulationStation acabou lendo o es_systems.cfg de exemplo que sobrou na pasta.
Dá para ver o estrago pelo tamanho do arquivo:
.emulationstation/es_systems.cfg 1.791 bytes (exemplo genérico, 1 sistema)
.config/emulationstation/es_systems.cfg 75.131 bytes (o real, 101 sistemas)
O arquivo de exemplo declara só um sistema nes aceitando extensões .nes e .NES. Como as ROMs são .zip, nenhum jogo casou, o sistema foi escondido e veio a mensagem de erro.
A correção foi trocar o diretório pelo symlink que deveria estar lá:
rm -rf /storage/.emulationstation
ln -sfn /storage/.config/emulationstation /storage/.emulationstation
Se estiver fazendo isso com o cartão montado no PC, atenção: o alvo do link tem que ser o caminho como o aparelho enxerga (/storage/...), não o ponto de montagem do seu computador. No PC ele vai parecer quebrado, e está certo assim.
A lição vale para qualquer coisa: grave a imagem limpa, deixe o aparelho bootar uma vez e só então ajuste as configurações. O mesmo erro também tinha disparado um reboot com mensagem de erro na tela, porque o fs-resize usa a existência dessas pastas como sinal de que o sistema já foi inicializado.
As configurações que se apagam sozinhas
Configurei o idioma para português e o fuso para São Paulo editando o es_settings.cfg e o .cache/timezone. No boot seguinte, voltou tudo para inglês e México.
O motivo está no emustation-config:
TZ=$(get_ee_setting system.timezone)
echo "TIMEZONE=$TZ" > /storage/.cache/timezone
O .cache/timezone é um arquivo derivado, regerado a cada boot. Editar ele não adianta. O mesmo vale para o idioma no es_settings.cfg. As chaves de verdade ficam no emuelec.conf, e vêm assim de fábrica:
system.language=en_US
system.timezone=America/Mexico_City
Para português do Brasil e horário de São Paulo, o que persiste é trocar por:
system.language=pt_BR
system.timezone=America/Sao_Paulo
Esse arquivo fica em /storage/.config/emuelec/configs/emuelec.conf, e o modelo original está no repositório com todas as chaves comentadas — vale a leitura, tem bastante coisa útil ali além dessas três.
Trocar ali persiste. E sim, o padrão do EmuELEC é México, então isso não vem do fabricante do stick. A regra geral é: configuração de sistema mora no emuelec.conf; o resto é cache.
Bônus: copiar arquivos de um cartão com FAT corrompido
Para migrar os jogos do cartão antigo, esbarrei em outro detalhe. Rodei um du para medir as pastas e o processo travou por vários minutos. Investigando:
setores lidos do cartão em 6s : 0
erros de FAT nos últimos 2min : 27.574
estado do processo : R (queimando CPU)
Zero leitura, 27 mil erros de sistema de arquivos, e o processo consumindo CPU em vez de esperar I/O. O du tinha entrado em loop infinito percorrendo uma entrada de diretório corrompida. Não ia terminar nunca.
A mesma corrupção também inflava tamanhos. Uma pasta de Famicom Disk System, cujos jogos têm cerca de 128 KB cada, aparecia com 36 GB.
A solução foi envolver toda operação em timeout, tanto a medição quanto a cópia, e aceitar resultado parcial:
TAM=$(timeout 120 du -sm "$PASTA" | cut -f1)
timeout 3600 rsync -a --ignore-errors "$ORIGEM" "$DESTINO"
Assim uma pasta doente é abandonada e registrada, em vez de derrubar o processo inteiro. Vale também checar o espaço livre antes de cada pasta, senão um diretório com tamanho fantasma tenta copiar dezenas de gigabytes inexistentes.
Um último detalhe que quase passou batido: os arquivos de BIOS estavam com nomes em caixa mista, tipo scph5501.BIN. No cartão antigo, formatado em FAT, isso não importa porque o sistema de arquivos ignora maiúsculas. A partição nova é ext4, que diferencia. Os emuladores de PlayStation procuram o nome em minúsculo e não encontrariam o arquivo, sem nenhuma mensagem de erro clara. Basta criar as cópias em minúsculo.
Conclusão
No fim, o aparelho está rodando EmuELEC 4.3, com NES, SNES, Mega Drive, PlayStation, Neo Geo, arcade e com uma folga confortável de espaço. O N64 eu acabei removendo porque 1 GB de RAM não dá conta de forma decente.

Se você for fazer o mesmo caminho, o resumo é este:
- Leia o
dtb.imgdo cartão de fábrica para descobrir o hardware real, ignorando o anúncio - Confira se o cartão original não é de capacidade falsificada, olhando se o tamanho é um número plausível
- Use EmuELEC 4.3, build
Amlogicsem o sufixo-ng - Substitua o
dtb.imgpelo device tree correto e confirme pelo MD5 - Copie os setores 1 a 2047 do cartão original para o novo, senão não dá boot
- Deixe bootar uma vez antes de configurar qualquer coisa
- Configure idioma e fuso no
emuelec.conf, não nos arquivos derivados
O que mais me surpreendeu foi que o problema decisivo, aquele que impedia qualquer imagem na tela, não estava em nenhum arquivo visível: estava em 717 KB de bootloader escondidos antes da primeira partição, que nenhuma imagem oficial distribui. É o tipo de coisa que só aparece comparando um cartão que funciona com um que não funciona.
Alguém mais aqui já reaproveitou um desses Game Sticks? Fiquei curioso para saber se os modelos com RK3566 sofrem do mesmo problema de bootloader, porque a arquitetura de boot é bem diferente da Amlogic.
Links
EmuELEC
- Repositório do projeto
- Todos os releases — confira aqui se sua versão ainda tem build legacy
- Release v4.3, a última com
Amlogiclegacy - Download direto da imagem (727 MB) e o SHA256
- Wiki oficial
Código-fonte citado no artigo
emuelec_autostart.sh— oln -sfdo.emulationstationemustation-config— regera o.cache/timezonee exporta o locale a cada bootemuelec.conf— todas as chaves de configuração, comentadasfs-resize— o.please_resize_mee a detecção de sistema já inicializado
Ferramentas
- f3 — detecta cartões de capacidade falsificada (documentação)
dtc(device-tree-compiler) para inspecionar odtb.img, embora umstringsjá resolvadd,parted,resize2fsersync, todos presentes em qualquer distro
Os comandos deste artigo foram executados no Fedora, mas nada aqui é específico de distribuição.