Movendo o Fastboot para o Userspace

O Android 10 e superior oferece suporte a partições redimensionáveis, realocando a implementação do fastboot do carregador de inicialização para o espaço do usuário. Essa realocação permite mover o código intermitente para um local comum passível de manutenção e testável com apenas as partes específicas do fornecedor do fastboot implementadas por uma camada de abstração de hardware (HAL). Além disso, o Android 12 e superior oferece suporte a ramdisks intermitentes por meio de um comando fastboot adicionado.

Unificação de inicialização rápida e recuperação

Como o fastboot e a recuperação do espaço do usuário são semelhantes, você pode mesclá-los em uma partição ou binário. Isso oferece vantagens como usar menos espaço, ter menos partições em geral e ter o fastboot e a recuperação compartilhando seu kernel e bibliotecas.

Para oferecer suporte ao fastbootd , o carregador de inicialização deve implementar um novo comando de bloco de controle de inicialização (BCB) de boot-fastboot . Para entrar no modo fastbootd , o bootloader grava boot-fastboot no campo de comando da mensagem do BCB e deixa o campo de recovery do BCB inalterado (para habilitar a reinicialização de quaisquer tarefas de recuperação interrompidas). Os campos status , stage e reserved também permanecem inalterados. O carregador de inicialização carrega e inicializa na imagem de recuperação ao ver boot-fastboot no campo de comando BCB. A recuperação então analisa a mensagem BCB e alterna para o modo fastbootd .

Comandos ADB

Esta seção descreve o comando adb para integrar fastbootd . O comando tem resultados diferentes, dependendo se é executado por sistema ou por recuperação.

Comando Descrição
reboot fastboot
  • Reinicia em fastbootd (sistema).
  • Entra no fastbootd diretamente sem uma reinicialização (recuperação).

Comandos de inicialização rápida

Esta seção descreve os comandos fastboot para integrar fastbootd , incluindo novos comandos para flashear e gerenciar partições lógicas. Alguns comandos têm resultados diferentes, dependendo de terem sido executados pelo bootloader ou pelo fastbootd .

Comando Descrição
reboot recovery
  • Reinicia na recuperação (bootloader).
  • Entra na recuperação diretamente sem reinicialização ( fastbootd ).
reboot fastboot Reinicia em fastbootd .
getvar is-userspace
  • Retorna yes ( fastbootd ).
  • Retorna no (carregador de inicialização).
getvar is-logical: <partition> Retorna yes se a partição especificada for uma partição lógica, caso contrário, no . As partições lógicas suportam todos os comandos listados abaixo.
getvar super-partition-name Retorna o nome da superpartição. O nome inclui o sufixo do slot atual se a superpartição for uma partição A/B (geralmente não é).
create-logical-partition <partition> <size> Cria uma partição lógica com o nome e tamanho fornecidos. O nome ainda não deve existir como uma partição lógica.
delete-logical-partition <partition> Exclui a partição lógica fornecida (limpa efetivamente a partição).
resize-logical-partition <partition> <size> Redimensiona a partição lógica para o novo tamanho sem alterar seu conteúdo. Falha se não houver espaço suficiente disponível para realizar o redimensionamento.
update-super <partition> Mescla as alterações nos metadados da superpartição. Se uma mesclagem não for possível (por exemplo, o formato no dispositivo é uma versão sem suporte), esse comando falhará. Um parâmetro de wipe opcional substitui os metadados do dispositivo, em vez de realizar uma mesclagem.
flash <partition> [ <filename> ] Grava um arquivo em uma partição flash. O dispositivo deve estar no estado desbloqueado.
erase <partition> Apaga uma partição (não é necessário que seja um apagamento seguro). O dispositivo deve estar no estado desbloqueado.
getvar <variable> | all Exibe uma variável do carregador de inicialização ou todas as variáveis. Se a variável não existir, retorna um erro.
set_active <slot>

Define o slot de inicialização A/B fornecido como active . Na próxima tentativa de inicialização, o sistema inicializa a partir do slot especificado.

Para suporte A/B, os slots são conjuntos duplicados de partições que podem ser inicializadas de forma independente. Os slots são nomeados a , b e assim por diante e diferenciados adicionando os sufixos _a , _b e assim por diante ao nome da partição.

reboot Reinicia o dispositivo normalmente.
reboot-bootloader (ou reboot bootloader ) Reinicia o dispositivo no bootloader.
fastboot fetch vendor_boot <out.img>

Use no Android 12 e superior para oferecer suporte a ramdisks de fornecedores em flash.

Obtém todo o tamanho da partição e o tamanho do bloco. Obtém dados para cada pedaço e, em seguida, une os dados para <out.img>

Para obter detalhes, consulte fastboot fetch vendor_boot <out.img> .

fastboot flash vendor_boot:default <vendor-ramdisk.img>

Use no Android 12 e superior para oferecer suporte a ramdisks de fornecedores em flash.

Esta é uma variante especial do comando flash. Ele executa uma função de imagem fetch vendor_boot , como se fastboot fetch fosse chamado. A nova imagem vendor_boot que ela pisca depende se a versão do cabeçalho de inicialização é a versão 3 ou a versão 4.

Para obter detalhes, consulte fastboot flash vendor_boot:default <vendor-ramdisk.img> .

fastboot flash vendor_boot: <foo> <vendor-ramdisk.img> Use no Android 12 e superior para oferecer suporte a ramdisks de fornecedores em flash.

Busca a imagem vendor_boot . Retorna um erro se o cabeçalho de inicialização do fornecedor for a versão 3. Se for a versão 4, ele encontra o fragmento de disco ram do fornecedor correto (se disponível). Ele substitui isso pela imagem fornecida, recalcula tamanhos e deslocamentos e exibe a nova vendor_boot image .

Para obter detalhes, consulte fastboot flash vendor_boot: <foo> <vendor-ramdisk.img>

Fastboot e bootloader

O bootloader pisca as partições bootloader , radio e boot/recovery , após o que o dispositivo inicializa no fastboot (userspace) e pisca todas as outras partições. O bootloader deve suportar os seguintes comandos.

Comando Descrição
download Baixa a imagem para flash.
flash recovery <image> / flash boot <image> / flash bootloader <image> / Pisca a partição recovery/boot e o carregador de inicialização.
reboot Reinicia o dispositivo.
reboot fastboot Reinicia para fastboot.
reboot recovery Reinicializa para recuperação.
getvar Obtém uma variável do carregador de inicialização necessária para o flash da imagem de recuperação/inicialização (por exemplo, current-slot e max-download-size ).
oem <command> Comando definido pelo OEM.

Partições dinâmicas

O bootloader não deve permitir o flash ou apagamento de partições dinâmicas e deve retornar um erro se essas operações forem tentadas. Para dispositivos de partição dinâmica adaptados, a ferramenta fastboot (e bootloader) suporta um modo de força para piscar diretamente uma partição dinâmica enquanto estiver no modo bootloader. Por exemplo, se system for uma partição dinâmica no dispositivo adaptado, usar o comando fastboot --force flash system permite que o carregador de inicialização (em vez de fastbootd ) atualize a partição.

Carregamento fora do modo

Se um dispositivo suporta carregamento off-mode ou autoinicialização em um modo especial quando a energia é aplicada, uma implementação do comando fastboot oem off-mode-charge 0 deve ignorar esses modos especiais, para que o dispositivo inicialize como se o usuário tivesse pressionado o botão de energia.

Fastboot OEM HAL

Para substituir completamente o bootloader fastboot, o fastboot deve manipular todos os comandos fastboot existentes. Muitos desses comandos são de OEMs e estão documentados, mas exigem uma implementação personalizada. Muitos comandos específicos de OEM não estão documentados. Para lidar com esses comandos, o fastboot HAL especifica os comandos OEM necessários. Os OEMs também podem implementar seus próprios comandos.

A definição de fastboot HAL é a seguinte:

import IFastbootLogger;

/**
 * IFastboot interface implements vendor specific fastboot commands.
 */
interface IFastboot {
    /**
     * Returns a bool indicating whether the bootloader is enforcing verified
     * boot.
     *
     * @return verifiedBootState True if the bootloader is enforcing verified
     * boot and False otherwise.
     */
    isVerifiedBootEnabled() generates (bool verifiedBootState);

    /**
     * Returns a bool indicating the off-mode-charge setting. If off-mode
     * charging is enabled, the device autoboots into a special mode when
     * power is applied.
     *
     * @return offModeChargeState True if the setting is enabled and False if
     * not.
     */
    isOffModeChargeEnabled() generates (bool offModeChargeState);

    /**
     * Returns the minimum battery voltage required for flashing in mV.
     *
     * @return batteryVoltage Minimum battery voltage (in mV) required for
     * flashing to be successful.
     */
    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);

    /**
     * Returns the file system type of the partition. This is only required for
     * physical partitions that need to be wiped and reformatted.
     *
     * @return type Can be ext4, f2fs or raw.
     * @return result SUCCESS if the operation is successful,
     * FAILURE_UNKNOWN if the partition is invalid or does not require
     * reformatting.
     */
    getPartitionType(string partitionName) generates (FileSystemType type, Result result);

    /**
     * Executes a fastboot OEM command.
     *
     * @param oemCmd The oem command that is passed to the fastboot HAL.
     * @response result Returns the status SUCCESS if the operation is
     * successful,
     * INVALID_ARGUMENT for bad arguments,
     * FAILURE_UNKNOWN for an invalid/unsupported command.
     */
    doOemCommand(string oemCmd) generates (Result result);

};

Ativando fastbootd

Para habilitar fastbootd em um dispositivo:

  1. Adicione fastbootd a PRODUCT_PACKAGES em device.mk : PRODUCT_PACKAGES += fastbootd .

  2. Certifique-se de que o fastboot HAL, o boot control HAL e o health HAL sejam empacotados como parte da imagem de recuperação.

  3. Adicione quaisquer permissões de SEPolicy específicas do dispositivo exigidas pelo fastbootd . Por exemplo, fastbootd requer acesso de gravação a uma partição específica do dispositivo para fazer o flash dessa partição. Além disso, a implementação do fastboot HAL também pode exigir permissões específicas do dispositivo.

Para validar o fastboot do espaço do usuário, execute o Vendor Test Suite (VTS) .

ramdisks de fornecedor piscando

O Android 12 e superior oferece suporte para flashes ramdisks com um comando fastboot adicionado que extrai a imagem vendor_boot completa de um dispositivo. O comando solicita que a ferramenta fastboot do lado do host leia o cabeçalho de inicialização do fornecedor, faça uma nova imagem e atualize a nova imagem.

Para extrair a imagem vendor_boot completa, o comando fetch:vendor_boot foi adicionado ao protocolo fastboot e à implementação fastbootd do protocolo no Android 12. Observe que o fastbootd implementa isso , mas o próprio carregador de inicialização pode não. Os OEMs podem adicionar o comando fetch:vendor_boot à implementação do protocolo de carregador de inicialização. No entanto, se o comando não for reconhecido no modo de carregador de inicialização, a atualização de ramdisks de fornecedores individuais no modo de carregador de inicialização não é uma opção com suporte do fornecedor.

Alterações do carregador de inicialização

Os comandos getvar:max-fetch-size e fetch:name são implementados em fastbootd . Para oferecer suporte a ramdisks do fornecedor no bootloader, você deve implementar esses dois comandos.

Alterações de inicialização rápida

getvar:max-fetch-size é semelhante a max-download-size . Especifica o tamanho máximo que o dispositivo pode enviar em uma resposta DATA. O driver não deve buscar um tamanho maior que este valor.

fetch:name[:offset[:size]] executa uma série de verificações no dispositivo. Se todos os itens a seguir forem verdadeiros, o comando fetch:name[:offset[:size]] retornará dados:

  • O dispositivo está executando uma compilação depurável.
  • O dispositivo está desbloqueado (estado de inicialização laranja).
  • O nome da partição buscada é vendor_boot .
  • O valor do size está dentro de 0 < size <= max-fetch-size .

Quando eles são verificados, fetch:name[:offset[:size]] retorna o tamanho e o deslocamento da partição. Observe o seguinte:

  • fetch:name é equivalente a fetch:name:0 , que é equivalente a fetch:name:0:partition_size .
  • fetch:name:offset é equivalente a fetch:name:offset:(partition_size - offset)

Portanto fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset)

Quando offset ou partition_size (ou ambos) não são especificados, os valores padrão são usados, que para offset é 0 e para size é o valor calculado de partition_size - offset .

  • Deslocamento especificado, tamanho não especificado: size = partition_size - offset
  • Nenhum especificado: valores padrão usados ​​para ambos, size = partition_size - 0.

Por exemplo, fetch:foo busca toda a partição foo no deslocamento 0.

Mudanças de driver

Comandos foram adicionados à ferramenta fastboot para implementar alterações de driver. Cada um está vinculado à sua definição completa na tabela de comandos do Fastboot .

  • fastboot fetch vendor_boot out.img

    • Chama getvar max-fetch-size para determinar o tamanho do bloco.
    • Chama getvar partition-size:vendor_boot[_a] para determinar o tamanho de toda a partição.
    • Chama fastboot fetch vendor_boot[_a]:offset:size para cada pedaço. (O tamanho do pedaço é maior que o tamanho do vendor_boot , então normalmente há apenas um pedaço.)
    • Costura os dados juntos, para out.img .
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    Esta é uma variante especial do comando flash. Ele busca a imagem vendor_boot , como se fastboot fetch fosse chamado.

    • Se a inicialização do fornecedor for a versão de cabeçalho 3 , ela fará o seguinte:
      • Substitui o ramdisk do fornecedor pela imagem fornecida.
      • Pisca a nova imagem vendor_boot .
    • Se o cabeçalho de inicialização do fornecedor for a versão 4 , ele fará o seguinte:
      • Substitui todo o ramdisk do fornecedor pela imagem fornecida para que a imagem fornecida se torne o único fragmento de ramdisk do fornecedor na imagem vendor_boot .
      • Recalcula o tamanho e o deslocamento na tabela de ramdisk do fornecedor.
      • Pisca a nova imagem vendor_boot .
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    Busca vendor_boot image , como se fastboot fetch fosse chamado.

    • Se o cabeçalho de inicialização do fornecedor for a versão 3, ele retornará um erro.
    • Se o cabeçalho de inicialização do fornecedor for a versão 4, ele fará o seguinte:

      • Localiza o fragmento de ramdisk do fornecedor com o nome foo . Se não for encontrado ou se houver várias correspondências, retornará um erro.
      • Substitui o fragmento de ramdisk do fornecedor pela imagem fornecida.
      • Recalcula cada tamanho e deslocamento na tabela de ramdisk do fornecedor.
      • Pisca a nova imagem vendor_boot .

mkbootmg

O nome default é reservado para nomear fragmentos de disco ram do fornecedor no Android 12 e superior. Embora a semântica do fastboot flash vendor_boot:default permaneça a mesma, você não deve nomear seus fragmentos de ramdisk como default .

Alterações do SELinux

Uma mudança foi feita no fastbootd.te para oferecer suporte a ramdisks de fornecedores intermitentes.