1. Visão geral do subsistema de firmware do Linux
Firmware é um pedaço de programa que o próprio dispositivo de hardware executa. O firmware geralmente é armazenado no flash do dispositivo. Por uma questão de custo e conveniência, o programa operacional do dispositivo de hardware geralmente é empacotado em um arquivo de firmware em um formato específico, armazenado no sistema do terminal, e o dispositivo de hardware é atualizado por meio do sistema do terminal. Durante o processo de desenvolvimento do kernel do Linux, os desenvolvedores depuram os dispositivos periféricos, como toque, carregamento, motores lineares, armazenamento, dispositivos WIFI, etc., e também há casos em que o firmware precisa ser atualizado. No sistema Linux, o driver do dispositivo está no estado do kernel e o arquivo do firmware está no estado do usuário, portanto, é necessário um mecanismo seguro, estável e confiável para garantir que o driver do dispositivo carregue com êxito o arquivo do firmware. Para resolver o problema dos drivers de dispositivo que carregam arquivos de firmware do modo de usuário de forma estável a partir do modo kernel, o sistema Linux fornece um subsistema de firmware.
2. Mecanismo de implementação do subsistema de firmware do Linux
1. Introdução ao processo:
O subsistema de firmware do Linux é implementado com base no mecanismo sysfs e uevent.
Depois que o driver chama a interface de função do sistema de firmware para solicitar o firmware, o subsistema de firmware usa o método de compilação do kernel para obter o firmware; se a aquisição falhar, ele usa o cache do firmware para obter o firmware; se a aquisição ainda falhar , ele usa o caminho padrão para procurar diretamente a maneira do kernel de obter o firmware. Se a aquisição ainda falhar, reporte a mensagem uevent ao processo init. O processo init recebe a mensagem uevent e filtra as mensagens cujo tipo de subsistema é firmware. O processo init procura o firmware de acordo com as informações do firmware apontadas na mensagem uevent e grava o conteúdo do firmware obtido do estado do usuário para o estado do kernel através da interface do nó de arquivo fornecida pelo sysfs, para que o driver possa obter os dados do arquivo de firmware.
O sistema de firmware Linux fornece uma variedade de métodos para obter arquivos de firmware em diferentes cenários.
1) O método de compilar diretamente para o kernel;
2) O modo de cache do firmware;
3) Especifique diretamente o caminho de acordo com o kernel:
4) A forma de auxiliar no processamento através do processo init;
2. Fluxograma:
3. Interface de função principal:
Interface de função principal: Os principais tipos de interfaces de firmware de aplicativo são divididos em síncrono e assíncrono.
Normalmente, o processo de solicitação de firmware é demorado e o processo de processamento de atualizações de firmware é demorado, portanto, pode ser realizado usando uma interface de função assíncrona ou criando uma fila de trabalho no driver para chamar uma interface de função síncrona . em:
- O kernel aplica-se a um arquivo de firmware chamando a função request_firmware.
- Depois que o kernel obtém o arquivo de firmware, ele chama release_firmware para liberar a memória relacionada.
em:
- A interface request_firmware_direct apenas procura firmware no caminho especificado pelo kernel e não usa o mecanismo uevent para obter firmware.
- A interface request_firmware_nowait obtém o firmware por meio de uma fila de trabalho assíncrona, que pode desempenhar um papel em não bloquear o tempo de investigação de condução.
4. Processo de implementação:
(1) processo de implementação request_firmware:
A função request_firmware define diferentes bits de sinalizador chamando a função _request_firmware_prepare para realizar diferentes funções de diferença.
a. função _request_firmware_prepare:
Com base na ativação da chave de macro CONFIG_FW_LOADER, primeiro verifique se o arquivo de firmware está compilado no kernel chamando a função fw_get_builtin_firmware.
Em seguida, chame a função fw_lookup_and_allocate_buf para determinar se a lista vinculada na estrutura global fw_cache registrou o nome do firmware de solicitação atual. Se o nome do firmware solicitado atualmente não existir, aloque dinamicamente o espaço de memória correspondente e adicione o nome do firmware solicitado atualmente à lista vinculada na estrutura fw_cache global.
b. função fw_get_filesystem_firmware:
Principalmente através do caminho padrão fornecido pelo kernel para encontrar o arquivo de firmware, chame a função kernel_read_file_from_path. Se o arquivo de firmware não for encontrado, julgue se deseja ativar o modo USER_HELPER por meio do bit de sinalização FW_OPT_USERHELPER.
em:
O caminho padrão no sistema de firmware é o seguinte:
O caminho padrão pode adicionar um caminho por meio da linha de comando do kernel e passá-lo para o caminho variável por meio da interface module_param_string para personalizar o novo caminho.
Informações por meio do trem: rota de aprendizado da tecnologia de código-fonte do kernel do Linux + tutorial em vídeo do código-fonte do kernel
Learning through train: Linux kernel code memory tuning file system process management device driver/network protocol stack
(2) Modo USER_HELPER:
Este recurso só é suportado depois que o kernel abre CONFIG_FW_LOADER_USER_HELPER. A função principal é relatar a mensagem uevent para o processo init por meio do kernel e obter as informações do firmware por meio do processo init e gravá-las no nó sysfs subjacente.
a. função fw_load_from_user_helper:
Primeiro, chame a função fw_create_instance para criar o dispositivo, o arquivo de classe e o arquivo de atributo e aloque a estrutura firmware_priv.
Um diretório será então criado em /sys/class/firmware com o nome do dispositivo como seu nome de diretório.
Este diretório contém três propriedades:
- carregando:
Definido como 1: Este atributo é definido como 1 pelo espaço do usuário responsável por carregar o firmware;
Defina como 0: quando o processo de carregamento estiver concluído;
Definido como -1: encerrará o processo de carregamento do firmware.
- dados:
É usado para receber dados de firmware. Após o carregamento ser definido, o processo de espaço do usuário grava o firmware neste atributo.
- dispositivo:
Um link simbólico para a entrada correspondente em /sys/devices.
- tempo esgotado:
Por padrão, o período de tempo limite máximo de solicitação de firmware por meio do uevent é 60S, e o período de tempo limite de gravação da camada superior é suportado. b. Função _request_firmware_load:
Primeiro, desabilite o relatório uevent, adicione um dispositivo chamando a função device_add e dispare a chamada para a função firmware_uevent. Entre eles, preencha o formato das informações informadas pelo uevent, incluindo o nome do firmware, tempo limite e se é assíncrono.
A próxima etapa é ativar a função de relatório uevent e, ao mesmo tempo, chamar a função kobject_uevent para relatar o tipo de ação de adição à camada superior ueventd.
Em seguida, chame a função fw_state_wait_timeout para aguardar o processamento do ueventd da camada superior dentro do período de tempo limite predefinido.
Se o período de tempo limite for atingido ou o despertar for recebido, a memória solicitada anteriormente será liberada e as informações de memória, como dispositivo e classe, serão liberadas.
(3) fluxo de processamento de firmware relacionado a ueventd
Ueventd é um módulo importante no processo init. Ele lida principalmente com selinux, criação de dispositivos de desenvolvimento, ouvindo o kernel para relatar mensagens uevent, carregamento de firmware, etc.
a. Fluxo de processamento do FirmwareHandler:
O método HandleUevent em FirmwareHandler lida principalmente com o processo de interação entre o carregamento do firmware e os nós subjacentes.
Em primeiro lugar, julga-se que o tipo de subsistema da mensagem uevent é o campo de firmware antes do processamento.Este tipo é relatado apenas pelo módulo de firmware no kernel.
HandleUevent cria principalmente diferentes sub-threads por meio de um thread principal e processa solicitações de firmware de diferentes drivers do kernel em paralelo.
b. Função ProcessFirmwareEvent:
A primeira etapa é fazer um loop para determinar se o arquivo de firmware de pesquisa existe no caminho suportado por ueventd; se existir, grave o arquivo de atributo de carregamento subjacente em 1, copie o arquivo de firmware obtido e grave-o no arquivo de dados subjacente. Após a conclusão, ele será gravado no arquivo de propriedade de carregamento subjacente como 0.
Até agora, o kernel obteve as informações do arquivo de firmware gravadas pelo espaço do usuário.
em:
O ueventd suporta o caminho para procurar firmware por padrão:
Do firmware_directory especificado no arquivo ueventd.rc.
Autor Original: Kernel Craftsman