O foco no momento é
acessar a memória superior, mas existe uma herança nos PCs que
torna essa tarefa um tanto ingrata.
Embora eu não tivesse achado que isso seria complicado no início, e realmente não é, tive uma grande dificuldade nesse ponto, e justamente devido a algo que não estava esperando.
Para entender o que realmente acontece devemos conhecer um pouco da história dos PCs.
O IBM-PC e o PC-XT, ambos, utilizavam um processador 8088/86 de 16 bits, porem com um modo de endereçamento de 20 bits, que permitia acessar até 1 MB. Ele trabalhava com um sistema de segmento/offset em que ambos tinham 16 bits e o endereço real era calculado assim:
Endereço_Real = (Segmento * 0x10) + Offset
O último segmento completo era o 0xF000, pois a partir deste o final do segmento fazia um “desdobramento” para o começo da memória. Por exemplo, o endereço 0xFF00:1000 representaria a posição 0x100000 porem, como o endereçamento era feito somente entre 0x00000 e 0xFFFFF, esse valor era truncado na sua parte alta para 0x00000, justamente no 21º bit de endereço, o bit 20 (começando do 0).
Quando o PC-AT foi lançado usando o processador 80286, com endereçamento de 24 bits (que podia acessar até 16 MB), os engenheiros da IBM resolveram manter total compatibilidade com o PC-XT enquanto estivesse rodando em modo real, mas para isso precisavam que ele tivesse a mesma característica de desdobramento de memória, como isso não era possível diretamente no processador, então colocaram um dispositivo, na placa-mãe, que mantinha o bit de endereço 20 sempre zerado, isto foi batizado de A20 e era ativado/desativado pelo controlador de teclado (o primeiro lugar livre que acharam...).
O efeito do A20 quando desativado é que todos os megabytes impares não podem ser acessados, e se for tentado, será acessado o megabyte anterior, basicamente assim:
Para que possamos ter acesso completo à memória devemos ativar o A20, que dependendo do computador pode ser feito pelo controlador de teclado, por Fast Gate ou pela BIOS.
O método do controlador de teclado é o padrão, que deve funcionar em basicamente todos os computadores. Porem o controlador de teclado é bem mais lento que o processador, o que levou a criação do Fast Gate, que é ativado diretamente por uma porta do barramento, o que torna a sua ativação/desativação muito mais rápida. Já em computadores mais novos existe a possibilidade de se usar uma função da BIOS que se encarrega de fazer o chaveamento.
Uma maneira segura de se saber se realmente o A20 está habilitado é fazer o teste de “wrap around”, ou seja, o teste de desdobramento de memória em que grava-se dois valores diferentes, em dois endereços diferentes, mas que levam ao mesmo endereço físico se o A20 estiver desabilitado. Primeiro grava-se no endereço alto, acima da marca de 1 MB, depois no endereço baixo, no começo da memória. Então o endereço alto é lido novamente, se o valor lido é o mesmo que foi gravado, o A20 está habilitado, caso contrário está desabilitado.
Mas o meu problema surgiu pelo fato de estar utilizando um disco de boot do Windows 98. Na verdade eu carreguei o CD do Windows 98 na máquina virtual e fiz um “FORMAT A: /S” que gerou uma imagem de disquete iniciável sem gerenciadores de memória expandida, o que normalmente deveria deixar o A20 desabilitado.
Então resolvi fazer uma habilitação rápida, sem muita frescura, tipo testa o A20, habilita e testa novamente. Sendo que o primeiro teste deveria indicar desativado e o segundo ativado. Porem eu não contava que o A20 já estava ativado, e acabei cometendo o equívoco de achar que a função de teste estava invertida e a “corrigi” para indicar desativado, mas quando tentava habilitar, o segundo teste continuava dando desativado, meio óbvio isso agora :(
Fiquei tentando achar um erro no procedimento de habilitação do A20 sem sucesso e somente consegui descobrir quando resolvi fazer um programa separado de teste do A20, implementado o acesso por todos os meios possíveis. Foi quando descobri que ele já estava habilitado no boot do DOS.
Tanto tempo perdido por uma bobeira, mas o resultado final foi bom, porque adquiri algum conhecimento extra, que não sei se funciona em todo hardware, trata-se do Fast Gate.
Tentar habilitar o A20 por Fast Gate quando o computador não tem suporte para ele pode causar uma falha no sistema, e não encontrei uma maneira, em qualquer lugar, de descobrir se o computador tem suporte ao Fast Gate (exceto pela BIOS, o que não vale para computadores mais antigos).
Porem durante os testes no VirtualBox descobri que quando habilitamos, ou desabilitamos, o A20 pelo controlador de teclado podemos pegar o seu status pela porta do Fast Gate, e conclui que se o estado detectado combinar com a condição real, podemos considerar que o Fast Gate é suportado, mas não encontrei nada oficial sobre isso...
Depois dos testes em separado passei a implementação para o bootloader, ele primeiro testa se a BIOS tem suporte ao A20, se tiver ele obtém o suporte a Fast Gate por ela. Então testa os procedimentos pela BIOS, depois testa pelo controlador de teclado, tenta detectar o Fast Gate e então testa pelo Fast Gate, se presente.
Após isso ele habilita o A20, se já não estiver habilitado, pelo modo mais fácil (BIOS, Fast Gate ou KBC) e continua o carregamento do kernel com a única diferença que os parâmetros da GDT agora são exibidos na tela. Os segmento são exatamente os mesmos e continuam na memória convencional.
Após ter implementado o suporte a A20 modifiquei o código para que os segmentos de dados e pilha residissem na memória superior mas ainda como segmentos de 16 bits. O segmento de código ainda está na memoria convencional.
Download dos fontes e binários:
<< Anterior - Boot, fase 4 - Entrando no Modo Protegido
Embora eu não tivesse achado que isso seria complicado no início, e realmente não é, tive uma grande dificuldade nesse ponto, e justamente devido a algo que não estava esperando.
Para entender o que realmente acontece devemos conhecer um pouco da história dos PCs.
O IBM-PC e o PC-XT, ambos, utilizavam um processador 8088/86 de 16 bits, porem com um modo de endereçamento de 20 bits, que permitia acessar até 1 MB. Ele trabalhava com um sistema de segmento/offset em que ambos tinham 16 bits e o endereço real era calculado assim:
Endereço_Real = (Segmento * 0x10) + Offset
O último segmento completo era o 0xF000, pois a partir deste o final do segmento fazia um “desdobramento” para o começo da memória. Por exemplo, o endereço 0xFF00:1000 representaria a posição 0x100000 porem, como o endereçamento era feito somente entre 0x00000 e 0xFFFFF, esse valor era truncado na sua parte alta para 0x00000, justamente no 21º bit de endereço, o bit 20 (começando do 0).
Quando o PC-AT foi lançado usando o processador 80286, com endereçamento de 24 bits (que podia acessar até 16 MB), os engenheiros da IBM resolveram manter total compatibilidade com o PC-XT enquanto estivesse rodando em modo real, mas para isso precisavam que ele tivesse a mesma característica de desdobramento de memória, como isso não era possível diretamente no processador, então colocaram um dispositivo, na placa-mãe, que mantinha o bit de endereço 20 sempre zerado, isto foi batizado de A20 e era ativado/desativado pelo controlador de teclado (o primeiro lugar livre que acharam...).
O efeito do A20 quando desativado é que todos os megabytes impares não podem ser acessados, e se for tentado, será acessado o megabyte anterior, basicamente assim:
- 0-1M – acessível;
- 1M-2M – não acessível, acessa o endereço de 0-1M;
- 2M-3M – acessível;
- 3M-4M – não acessível, acessa o endereço de 2M-3M;
- …
Para que possamos ter acesso completo à memória devemos ativar o A20, que dependendo do computador pode ser feito pelo controlador de teclado, por Fast Gate ou pela BIOS.
O método do controlador de teclado é o padrão, que deve funcionar em basicamente todos os computadores. Porem o controlador de teclado é bem mais lento que o processador, o que levou a criação do Fast Gate, que é ativado diretamente por uma porta do barramento, o que torna a sua ativação/desativação muito mais rápida. Já em computadores mais novos existe a possibilidade de se usar uma função da BIOS que se encarrega de fazer o chaveamento.
Uma maneira segura de se saber se realmente o A20 está habilitado é fazer o teste de “wrap around”, ou seja, o teste de desdobramento de memória em que grava-se dois valores diferentes, em dois endereços diferentes, mas que levam ao mesmo endereço físico se o A20 estiver desabilitado. Primeiro grava-se no endereço alto, acima da marca de 1 MB, depois no endereço baixo, no começo da memória. Então o endereço alto é lido novamente, se o valor lido é o mesmo que foi gravado, o A20 está habilitado, caso contrário está desabilitado.
Mas o meu problema surgiu pelo fato de estar utilizando um disco de boot do Windows 98. Na verdade eu carreguei o CD do Windows 98 na máquina virtual e fiz um “FORMAT A: /S” que gerou uma imagem de disquete iniciável sem gerenciadores de memória expandida, o que normalmente deveria deixar o A20 desabilitado.
Então resolvi fazer uma habilitação rápida, sem muita frescura, tipo testa o A20, habilita e testa novamente. Sendo que o primeiro teste deveria indicar desativado e o segundo ativado. Porem eu não contava que o A20 já estava ativado, e acabei cometendo o equívoco de achar que a função de teste estava invertida e a “corrigi” para indicar desativado, mas quando tentava habilitar, o segundo teste continuava dando desativado, meio óbvio isso agora :(
Fiquei tentando achar um erro no procedimento de habilitação do A20 sem sucesso e somente consegui descobrir quando resolvi fazer um programa separado de teste do A20, implementado o acesso por todos os meios possíveis. Foi quando descobri que ele já estava habilitado no boot do DOS.
Tanto tempo perdido por uma bobeira, mas o resultado final foi bom, porque adquiri algum conhecimento extra, que não sei se funciona em todo hardware, trata-se do Fast Gate.
Tentar habilitar o A20 por Fast Gate quando o computador não tem suporte para ele pode causar uma falha no sistema, e não encontrei uma maneira, em qualquer lugar, de descobrir se o computador tem suporte ao Fast Gate (exceto pela BIOS, o que não vale para computadores mais antigos).
Porem durante os testes no VirtualBox descobri que quando habilitamos, ou desabilitamos, o A20 pelo controlador de teclado podemos pegar o seu status pela porta do Fast Gate, e conclui que se o estado detectado combinar com a condição real, podemos considerar que o Fast Gate é suportado, mas não encontrei nada oficial sobre isso...
Depois dos testes em separado passei a implementação para o bootloader, ele primeiro testa se a BIOS tem suporte ao A20, se tiver ele obtém o suporte a Fast Gate por ela. Então testa os procedimentos pela BIOS, depois testa pelo controlador de teclado, tenta detectar o Fast Gate e então testa pelo Fast Gate, se presente.
Após isso ele habilita o A20, se já não estiver habilitado, pelo modo mais fácil (BIOS, Fast Gate ou KBC) e continua o carregamento do kernel com a única diferença que os parâmetros da GDT agora são exibidos na tela. Os segmento são exatamente os mesmos e continuam na memória convencional.
Após ter implementado o suporte a A20 modifiquei o código para que os segmentos de dados e pilha residissem na memória superior mas ainda como segmentos de 16 bits. O segmento de código ainda está na memoria convencional.
Download dos fontes e binários:
- LoadLOS.006 - Suporte ao A20 adicionado;
- LoadLOS.007 - Segmentos de dados e pilha na memória superior;
<< Anterior - Boot, fase 4 - Entrando no Modo Protegido
Muito bom ta no caminho certo
ResponderExcluirObrigado!
Excluir