PCF-3

Questões comentadas, artigos e notícias

Software Illustrated: Como os computadores inicializam

Posted by papacharliefox3 em 06/03/2009

No post anterior da série, fiz uma tradução livre do artigo do Gustavo Duarte sobre chipset de placa-mãe e mapeamento de memória em computadores Intel. Desta vez, o artigo trata do processo de inicialização (boot) do computador.

Um esboço da sequência de boot

Tudo começa quando pressiona-se o botão de energia (power). Desta forma, assim que a placa-mãe energiza-se, o firmware desta é inicializado, ou seja, o chipset e os outros componentes da placa. Se acontece algum problema neste momento, seja por falha no processador ou mesmo por ausência de algum componente, a única coisa que parece funcionar são as ventoinhas da fonte de alimentação. Algumas placas ainda emitem diferentes sinais sonoros (beeps), os quais podem ser interpretados, de forma a indicar qual é o problema. Algumas vezes, dispositivos USB podem ser a causa do problema, que pode ser solucionado ao retirar-se os dispositivos pouco utilizados. Ao final, por eliminação, chega-se ao dispositivo defeituoso, responsável pelo problema.

Se tudo está OK, a CPU começa a funcionar. Em sistemas multiprocessados ou com mais de um core (multi-cores), um processador é escolhido dinamicamente para ser o bootstrap processor (BSP), responsável por rodar os códigos de inicialização do BIOS e do kernel. Os processadores restantes, chamados de processadores de aplicação neste momento, mantêm-se inativos até o momento em que eles serão explicitamente ativados pelo kernel. Apesar de as CPUs Intel terem desenvolvido-se ao longo dos anos, elas mantêm compatibilidade com a arquitetura, comportando-se de maneira igual a um processador de 1978, como o Intel 8086. Nesse estatdo de inicialização primitivo, o processador encontra-se em modo real, com paginação de memória desabilitada. Assim como nos tempos do antigo MS-DOS, quando apenas 1MB de memória podia ser endereçado e qualquer código podia escrever em qualquer região da memória; sem o mínimo tratamento de privilégio ou proteção.

A maioria dos resgistradores já recebe carga de valores logo após o boot, incluindo o ponteiro de instrução (EIP) cujo valor é um endereço de memória relativo à instrução que está sendo executada pelo processador. Na arquitetura Intel existe um ‘hack’: embora apenas 1MB possa ser endereçado durante o boot, um endereço base oculto (um offset, essencialmente) é carregado no registrador EIP, de maneira que a primeira instrução executada reside no endereço 0xFFFFFFF0, endereço a 16 bytes do final dos 4GB de memória endereçável (32bits) e bem acima de 1MB. Este endereço mágico é chamado de vetor de inicialização (reset vector), padrão na arquitetura Intel moderna.

A placa-mãe assegura-se de que a instrução contida no vetor de inicialização é um jump para a localização de memória mapeada para a entrada do BIOS. Esse jump, implicitamente, limpa o endereço base oculto presente anteriormente. Todas as loacalizações de memória contêm os valores corretos, dos quais a CPU necessita; isso, graças ao mapa de memória, mantido pelo chipset. Todos esses endereços são mapeados para a memória flash (que contém os códigos da BIOS). Neste momento, os módulos de memória ainda podem possuir dados randômicos. Um exemplo das regiões de memória mais relevantes é mostrado abaixo:

Regiões mais importantes da memória durante o boot

Regiões mais importantes da memória durante o boot

A CPU começa a executar o código do BIOS, responsável pela inicialização de parte do hardware. Em seguida, o BIOS dispara o processo POST que realiza o teste de vários componentes do computador. A falta de alguns dispositivos, como a placa de vídeo, pode gerar a emissão de sons (beeps), estes podem ser interpretados e assim ajudar no processo de identificação de problemas, visto que não há o que enxergar na tela. Uma placa de vídeo que funciona perfeitamente proporciona o diagnóstico por meio de imagens (logos) e mensagens de erro ou status (testes de memória). A falta de teclado neste estágio (POST) pode inclusive abortar o processo de boot, problema visível por meio de uma mensagem de erro.

O POST é um processo misto, quando ocorrem tanto testes como inicialização de recursos – interrupções, ranges de memória, portas E/S – do barramento PCI. BIOS modernos, de acordo com o padrão ACPI, constroem tabelas que descrevem os dispositivos presentes em um computador que serão utilizadas mais tarde pelo kernel do sistema.

Após o POST, o BIOS procura carregar o SO, este deve estar localizado em um HD, floppy, CD-ROM ou mesmo em um pendrive. A ordem pela qual o BIOS busca o dispositivo de boot é definida pelo usuário. Se não há dispositivo de boot adequado, o processo de boot é abortado com a seguinte menagem: “Sem disco de sistema ou erro no disco”. Um problema no disco também pode apresentar este sintoma. Se tudo está OK, o processo de boot continua.

O BIOS lê o setor 0 (zero) do disco, ou seja, os primeiros 512 bytes. A esta área dar-se o nome de Master Boot Record (MBR), ela normalmente contém dois componentes vitais: o bootstrapping seguido da tabela de partições. Entretanto, o BIOS não se importa com o que está lá, apenas o carrega em memória, na localização 0x7c00 e então passa a executar instruções a partir dessa localização, ou seja, o código que está na MBR.

MBR

MBR

O código que está na MBR pode ser tanto um carregador ou gerenciador de boot do Windows ou Linux (LILO, GRUB), assim como um vírus. Em contrate com isso, a tabela de partições é padrão: uma área de 64 bytes, dividida em 4 entradas de 16 bytes, que descrevem a divisão do disco. Tradicionalmente, o código MBR da Microsoft procura apenas pela partição marcada como ‘ativa’ e carrega o código armazenado no setor de boot daquela partição. O setor de boot é o primeiro setor de uma partição, diferente do primeiro setor do disco. Se a tabela de partições está corrompida, uma mensagem do tipo “Tabela de partições inválida” ou “Sem sistema operacional” é mostrada. Esta mensagem é gerada pelo código carregado da MBR e não pelo BIOS.

O processo de boot se torna cada vez mais flexível e sofisticado ao longo do tempo. Os gerenciadores de boot do Linux, por exemplo, suportam uma grande variedade de opções e configurações, para tanto, eles não seguem o padrão “realize o boot pela partição ativa”. O processo acontece da seguinte forma:

  1. O chamado ‘estágio 1’ trata-se da execução do código que reside na MBR;
  2. Devido ao tamanho reduzido, o código MBR simplesmente carrega código (bootstrapping) adicional de outra região do disco. Este código pode ser tanto o setor de boot de uma partição ou qualquer código hardcoded quando da instalação da MBR;
  3. O código MBR somado ao código do passo 2 são responsáveis pela leitura de um arquivo que contém o ‘estágio 2’ do gerenciador de boot. No GRUB chama-se ‘GRUB Stage 2’, no Windows, ‘C:\NTLDR)’. Assim, se este passo falhar no Windows, uma mensagem contendo ‘NTLDR não encontrado’ será mostrada. O código so estágio 2 lê o arquivo de configuração de boot (boot.ini, grub.conf, etc.) para poder oferecer as opções ao usuário ou simplesmente carregar um único SO;
  4. Neste ponto, o gerenciador de boot precisa carregar um kernel. Para tanto, ele deve conhecer o suficiente do sistema de arquivos (partição de boot) que contém a imagem do kernel. No Linux, usualmente, carrega-se o arquivo ‘vmlinuz-versão-kernel’, enquanto no Windows, parte do código de inicialização está no próprio NTLDR. Após alguns processos de inicialização, o NTLDR carrega a imagem do kernel a partir do arquivo C:\Windows\System32\ntoskrnl.exe (Windows 2003).

Existe uma complicação (nem é necessário mencionar, muita coisa trata-se de um hack aqui). A imagem do kernel, mesmo compactada não cabe em 640K de memória RAM (lembre-se, modo real). Em um Ubunto (distro Linux) recém instalado, a imagem possui 1.7MB compactada. Mesmo assim, o gerenciador de boot deve rodar em modo real para chamar as rotinas do BIOS para lerem dados do disco, visto que o kernel, claramente, não está disponível neste momento. A solução é o venerável unreal mode. Este não é um modo verdadeiro do processador, mas uma técnica que utiliza-se da entrada e saída dos modos real e protegido com o intuito de acessar mais que 1MB de memória enquanto no contexto do BIOS. Ao analisar-se o código-fonte do GRUB, percebe-se isso. Ao final deste complexo e difícil processo, o kernel estará confortavelmente carregado na memória, “assim ou assado”, entretanto, volta-se ao modo real ao terminar-se.

No próximo post: a inicialização do Linux Kernel. Parabéns ao Gabriel pelo ótimo artigo!

Uma resposta to “Software Illustrated: Como os computadores inicializam”

  1. […] post anterior tratou do processo de boot até o ponto em que o gerenciador de boot carrega a imagem do kernel na […]

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

 
%d blogueiros gostam disto: