Drivers de Boot no Windows

17 de December de 2009 - Fernando Roberto

Tenho acompanhado o trabalho do meu amigo Lesma, que em seu blog tem descrito como o processo de boot transforma um apanhado de bytes no disco rígido em um sistema operacional vivo. Pegando carona nesse tema, vou aproveitar para comentar sobre a ordem de carga dos drivers durante este processo. Com isso posso tentar responder uma pergunta frequente dos leitores: “Como fazer para que meu driver seja o primeiro a ser carregado?”. Talvez este post possa clarear um pouco as coisas neste sentido, ou não.

Eu primeiro! Eu primeiro!

Um ponto importante a ser considerado no modelo Legacy quando escrevemos um driver é o referente ao momento no qual seu driver é carregado. Isso é configurado no valor “Start” na chave do driver no registro. Quatro valores configuram o momento da carga do seu driver, sendo eles:

  • Boot (0) – Drivers são carregados durante o boot, antes mesmo sistema operacional estar completamente pronto para execução.
  • System (1) – Drivers são carregados depois dos drivers de boot, quando o Kernel já está completamente funcional.
  • Automatic (2) – Neste grupo os drivers são carregados quando os subsistemas forem carregados. Basicamente junto com os serviços de User Mode.
  • Manual (3) – Nenhuma carga automática é realizada aqui, o driver é carregado somente quando alguém, ou algum componente, solicita sua carga.
  • Disabled (4)- Mesmo que o driver seja solicitado, sua carga é negada.


“Bom, então para meu driver ser o primeiro a ser carregado ele precisa ser iniciado como boot e pronto?”

Na verdade seu driver vai disputar um lugar na fila de drivers que querem ser iniciados no boot. Vários drivers estão configurados para ser iniciados nesse momento e o seu será apenas mais um. Mesmo entre os drivers de boot, uma ordem de carga precisa ser seguida para que certos drivers possam contar com os serviços de outros drivers. Por esse motivo, drivers se separam em grupos. Um grupo de cada vez vai sendo iniciado até que todos os drivers de boot passem por esse processo.

Drivers identificam seu grupo pelo valor “Group” encontrado em sua chave de registro. Esta chave deve conter o nome do grupo ao qual o driver pertence. Os nomes de todos os grupos podem ser encontrados na chave HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ServiceGroupOrder. Nela existe um valor do tipo REG_MULTI_SZ chamado “List” que contém a lista de todos os grupos existentes dispostos em sua ordem de carga.


“Tudo bem, meu driver está configurado para ser iniciado em Boot e está configurado para iniciar com o primeiro grupo de drivers. Pronto agora?”

Quase. Quando falamos em iniciar grupos de drivers, já fica sub-entendido que mais de um driver será carregado. A ordem que tais drivers são carregados dentro de cada grupo também pode ser determinada.

A chave KHEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList mantém uma série de valores, cada um com o nome de um grupo. O valor é do tipo REG_BINARY e sua interpretação é um array de conjuntos de quatro bytes. O primeiro conjunto indica quantas tags estão contidas naquele buffer binário. Os demais conjuntos são as representações numéricas de cada tag. Dessa forma, a interpretação do buffer exibido na figura abaixo nos dá a informação de que temos seis tags, sendo elas: 1, 2, 3, 4, 5 e 6.


“Mas o que é uma tag?”

Uma tag é a identificação numérica de um driver dentro de um determinado grupo. Um driver se identifica pelo valor “Tag” que podemos encontrar na chave do driver no registro.

Apesar de o exemplo nos mostrar uma ordem crescente de tags, o valor da tag não determina a ordem de carga dos drivers. A ordem é determinada por sua posição dentro do buffer binário.

Ficou com nojinho de mexer em buffers binários? Você pode utilizar o OSR Driver Loader que configura tudo isso pra você quando utilizado para instalar um driver.


Colocar sua tag como primeiro na lista de tags classifica sua ordem de carga dentro de um determinado grupo, mas ainda não é fator determinante para ter seu driver carregado antes de todos os drivers do universo. Um novo grupo sempre pode ser criado e ter sua ordem de carga configurada para antes do seu grupo.

Todas essas regras sobre grupos, tags e afins não fazem sentido nos drivers gerenciados pelo Plug-And-Play (Pnp) Manager, já que a carga de tais drivers é solicitada quando o dispositivo ao qual seu driver está relacionado é detectado pelo driver de barramento.

“Aff! Fernando, pega leve e tenta explicar isso de novo.”

Tudo bem, vamos lá. Quando você instala um driver Pnp, você o associa a um determinado dispositivo. Apenas como exemplo, digamos que esse dispositivo seja um conversor USB/Serial. Seu driver será carregado automagicamente quando seu dispositivo for detectado e será descarregado quando o dispositivo for removido.

Para que ele seja detectado, outros dispositivos precisam ser detectados antes, tais como controladora PCI, controladora USB e hub USB. Essa lista de dependência cria a pilha de dispositivos USB.

A controladora PCI, ao ser detectada, tem seu driver carregado e este enumera seus dispositivos filhos, já que PCI é um barramento. Para cada disposivito detectado, esse driver utiliza o barramento para detectar a identidade de cada dispositivo e cria um Phisical Device Object (PDO) para cada um deles. O Pnp Manager carrega o driver de cada dispositivo atachado a esse barramento. Esse driver criará o Functional Device Object (FDO) do dispositivo, dando funcionalidade a ele.

Um desses dispositivos é a controladora do barramento USB. Seguindo o ritual, o driver de barramento USB enumera seus dispositivos filhos, criando novos PDOs. Assim, os hubs USB são detectados e seu driver será carregado. Este driver criará um novo FDO para cada hub. O driver de hub USB vai enumerar seus dispositivos filhos e é nesse momento que seu dispositivo é detectado. O driver que você escreveu será carregado e o Pnp Manager irá chamar sua rotina AddDevice, que receberá o PDO que o driver de hub criou referente ao seu dispositivo.

Ufa! Tudo bem, tenham calma. O assunto Plug-And-Play não é o foco deste post e já está na minha lista de posts futuros.

Toda essa atividade que age recursivamente serve para montar a árvore de dispositivos do sistema. Sabendo que esta árvore é formada pelos nossos drivers e seus devices, fica explícito aqui que no fundo “As árveres somos nozes”. A figura abaixo dá uma idéia de como a árvore de dispositivos é organizada.


Ainda falando sobre ordem de carga de drivers, não faria sentido ter seu driver carregado antes de todos os outros drivers, já que os componentes básicos para a comunicação com seu dispositivo ainda não foram carregados, e por isso, não possuem funcionalidade nenhuma. Além do mais, ter seu driver carregado muito cedo lhe trará problemas em lidar com outros componentes do sistema que ainda não estarão prontos para atender seu pedido. Mais detalhes neste post.

Depurando no Boot

Outro assunto curioso e que pode gerar alguma confusão é o referente ao debug de drivers que são carregados no boot. Apesar de a conexão de Debug usar o meio serial, firewire ou mesmo USB, os drivers referentes a estes meios não precisam estar carregados para que você possa realizar o debug do sistema. Em outras palavras, o driver de porta serial não é utilizado para fazer debug do sistema quando se usa o meio serial. Isso seria um problema se pensarmos que alguns drivers são carregados e inciados antes do driver de porta serial. Como estes drivers seriam depurados?

O fato é que o algoritmo que lida com os meios de depuração do sistema são definidos no próprio Kernel (mais precisamente no módulo ntoskrnl.exe e seus irmãos). Este módulo lida diretamente com o hardware responsável pelo meio utilizado. Essa é também a explicação para outra pergunta frequente: “Meu computador não tem porta serial. Posso usar um conversor USB/Serial do lado Target para fazer debug do sistema?”. Como acabamos de ver, um conversor USB/Serial depende de toda uma pilha de dispositivos para que a porta serial esteja disponível. Tal funcionalidade não está implementada no algoritmo de debug do sistema, e como comentei neste outro post, sistemas mais novos implementam novas funcionalidades de debug no Kernel.

Mesmo que seu driver seja de boot, ele ainda pode ser depurado. Este outro post mostra ainda como fazer mapeamento de um driver de boot pelo WinDbg. Não sabe do que estou falando? É sobre ter seu driver substituído por uma nova versão automaticamente no lado target quando este for carregado. Vale a pena dar uma olhada.

Have fun!

6 Responses to “Drivers de Boot no Windows”

  1. Fabio says:

    Muito bom post. Se fosse a algum tempo atraz eu me perguntaria: -Como esse cara sabe tudo isso? Muuito estranho, ele deve ser um alienígena vindo de uma civilização anos luz a nossa frente, que por sinal aprendeu e dominou a técnica de ler a mente humana. Faz sentido não? Ele se disfarçou como nós pobres mortais, se infiltrou em meio os mais renomados engenheiros da Microsoft e adquiriu todos seus conhecimentos.
    Isso até faria sentido se eu não estivesse lendo o livro Windows Internals. Nele é explicada a ordem de inicialização dos drivers segundo seus grupos e muito mais… Pra quem estiver lendo este post recomendo veemente a leitura do livro, além de aprender como parte do kernel funciona você aprende a conviver mais tranquilamente com seu brinquedinho gerador de telas azuis 😉
    Ah e evita comentar com posts longos e sem importância (como o meu) só pra mostrar que o Brasil precisa de mais bons programadores e que ler não faz mal a ninguém 😉

  2. Júlio César says:

    Fernando parabéns pelo post. Excelente !
    Gostaria de te dar uma sugestão de tópico.
    Sobre drivers para Windows Vista x64. Sei que é necessário assinar digitalmente o driver (já vi também maneiras de burlar o sistema). Mas seguindo os passos corretos, como assinar um driver de x64 ? Onde encontro os certificados mais baratos para conseguir assinar drivers x64 ?
    Obrigado.

  3. Anonymous says:

    Parabéns Fernando, como sempre você trás um conteúdo excelente para a comunidade.

    Estou em dúvida como um kernel driver pode se “auto-atualizar”, verificando e fazendo download de uma versão mais recente do próprio driver. Isso é possível? Você possui algum exemplo de tal funcionalidade?

    Abraço.

    • Olá er… Anonymous,

      Atualização de drivers normalmente é realizada por um componente user-mode que foi instalado junto com o driver do produto. Não que seja impossível fazer em Kernel, mas esse tipo de tarefa, que não exige “super poderes”, pode ser desenvolvida sobre algo mais fácil de manter e depurar.

      Os mais grandinhos submetem seus drivers aos testes da Microsoft para obter o Windows Logo e assim são capazes de ter seus drivers atualizados pelo Windows Update (olha que chique!).

      Windows Update Driver Publishing

      Um abraço.

  4. caio says:

    legal seu site =)

  5. vagner Casanova says:

    Meus Parabéns , até o presente momento li os melhores posts que tenho visto aqui no Brasil .
    Você é fantástico em sua explicação do assunto , espero que continue com este site maravilhoso porque no nosso Brasil varonil está dificil encontrar bons artigos temos muitas pessoas inteligentes aqui no Brasil pessoas fantásticas , mas que infelizmente não compartilham do conhecimentos que tem , é uma pena .

    Mas você está de PARABÉNS !!! CONTINUE ASSIM ….

Deixe um comentário