Suporte a módulos do kernel

Uma imagem genérica de kernel (GKI, na sigla em inglês) pode não conter o suporte necessário ao driver para permitir que um dispositivo ative partições. Para permitir que um dispositivo ative partições e continue a inicialização, o init de primeiro estágio é aprimorado para carregar os módulos do kernel presentes em um ramdisk. O ramdisk é dividido em genéricos e de fornecedores. Os módulos de kernel do fornecedor são armazenados no ramdisk do fornecedor. A ordem em que os módulos do kernel são carregados é configurável.

Local do módulo

O ramdisk é o sistema de arquivos do init, de primeiro estágio e da imagem de recuperação/fastbootd em dispositivos A/B e A/B virtuais. Ele é um initramfs composto por dois arquivos cpio que são concatenados pelo carregador de inicialização. O primeiro arquivo cpio, que é armazenado como o ramdisk do fornecedor na partição de inicialização do fornecedor, contém estes componentes:

  • Módulos de kernel do fornecedor init de primeiro estágio, localizados em /lib/modules/.
  • Arquivos de configuração modprobe, localizados em /lib/modules/: modules.dep, modules.softdep, modules.alias, modules.options.
  • Um arquivo modules.load que indica quais módulos serão carregados durante a inicialização do primeiro estágio e em que ordem, em /lib/modules/.
  • Módulos de kernel de recuperação do fornecedor, para dispositivos A/B e A/B virtuais, em /lib/modules/
  • modules.load.recovery, que indica os módulos a serem carregados e em qual ordem, para dispositivos A/B e A/B virtuais, em /lib/modules.

O segundo arquivo cpio, fornecido com a GKI como o ramdisk do boot.img e aplicado sobre o primeiro, contém first_stage_init e as bibliotecas de que ele depende.

Carregamento de módulo no init de primeiro estágio

O init de primeiro estágio começa lendo os arquivos de configuração modprobe de /lib/modules/ no ramdisk. Em seguida, ele lê a lista de módulos especificados em /lib/modules/modules.load (ou, no caso de recuperação, /lib/modules/modules.load.recovery) e tenta carregar cada um desses módulos em ordem, seguindo a configuração especificada nos arquivos carregados anteriormente. A ordem solicitada pode ser desviada para satisfazer dependências rígidas ou flexíveis.

Suporte a build, init de primeiro estágio

Para especificar os módulos do kernel a serem copiados para o cpio do ramdisk do fornecedor, liste eles em BOARD_VENDOR_RAMDISK_KERNEL_MODULES. O build executa depmod nesses módulos e coloca os arquivos de configuração modprobe resultantes no cpio do ramdisk do fornecedor.

O build também cria um arquivo modules.load e o armazena no cpio do ramdisk do fornecedor. Por padrão, ele contém todos os módulos listados em BOARD_VENDOR_RAMDISK_KERNEL_MODULES. Para substituir o conteúdo desse arquivo, use BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD, conforme mostrado neste exemplo:

BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := \
    device/vendor/mydevice-kernel/first.ko \
    device/vendor/mydevice-kernel/second.ko \
    device/vendor/mydevice-kernel/third.ko

Suporte de build, Android completo

Como acontece no Android 10 e nas versões anteriores, os módulos do kernel listados em BOARD_VENDOR_KERNEL_MODULES são copiados pelo build da plataforma Android na partição do fornecedor em /vendor/lib/modules. O build da plataforma executa depmod nesses módulos e copia os arquivos de saída depmod na partição do fornecedor no mesmo local. O mecanismo para carregar módulos do kernel do /vendor permanece o mesmo das versões anteriores do Android. Cabe a você decidir como e quando carregar esses módulos, embora isso geralmente seja feito usando scripts init.rc.

Caracteres curinga e builds de kernel integrados

Os fornecedores que combinam o build do kernel do dispositivo com o build da plataforma Android podem ter problemas ao usar as macros BOARD mencionadas acima para especificar os módulos do kernel a serem copiados para o dispositivo. Se o fornecedor quiser evitar a listagem de módulos do kernel nos arquivos de build da plataforma do dispositivo, ele poderá usar um caractere curinga ($(wildcard device/vendor/mydevice/*.ko). O caractere curinga não funciona no caso de um build integrado do kernel, porque quando o make é invocado e as macros são expandidas em makefiles, os módulos do kernel não foram criados, portanto, as macros estão vazias.

Para contornar esse problema, o fornecedor pode fazer com que o build do kernel crie um arquivo zip que contenha os módulos do kernel a serem copiados em cada partição. Defina o caminho desse arquivo ZIP em BOARD_*_KERNEL_MODULES_ARCHIVE, em que * é o nome da partição (como BOARD_VENDOR_KERNEL_MODULES_ARCHIVE). O build da plataforma Android extrai esse arquivo ZIP no local adequado e executa depmod nos módulos.

O arquivo ZIP do módulo do kernel precisa ter uma regra de criação que garanta que o build da plataforma possa gerar o arquivo quando necessário.

Recuperação

Em versões anteriores do Android, os módulos do kernel necessários para recuperação eram especificados em BOARD_RECOVERY_KERNEL_MODULES. No Android 12, os módulos do kernel necessários para a recuperação ainda são especificados usando essa macro. No entanto, os módulos do kernel de recuperação são copiados para o cpio do ramdisk do fornecedor, em vez do cpio genérico do ramdisk. Por padrão, todos os módulos do kernel listados em BOARD_RECOVERY_KERNEL_MODULES são carregados durante o init do primeiro estágio. Se você quiser que apenas um subconjunto desses módulos seja carregado, especifique o conteúdo desse subconjunto em BOARD_RECOVERY_KERNEL_MODULES_LOAD.

Para saber como criar uma partição de inicialização do fornecedor (que contém o ramdisk do fornecedor mencionado nesta página), consulte Partições de inicialização.