domingo, 19 de janeiro de 2014

UEFI x Sistemas Operacionais

Introdução

UEFI (Unified Extensible Firmware Interface) é uma especificação aberta para firmwares criada pela Intel na metade dos anos 90 para a arquitetura IA-64 — chamada naquela época EFI, sem o "U" — e adaptada para x86 e ARM posteriormente. A indústria precisava rapidamente de um substituto para o BIOS e suas limitações de décadas.

Mais ou menos a partir de 2009, os "BIOS" usados por muitos fabricantes de hardware na verdade não eram mais BIOS. Eram UEFI "Class 1", que ofereciam para o sistema operacional apenas o CSM através do modo Legacy. Na época do lançamento do Windows 8, as implementações já eram "Class 2", que podem operar em três modos:

1 - Legacy: o CSM (Compatibility Support Module) é habilitado e emula as interfaces do BIOS para o sistema operacional.
2 - UEFI: o CSM não é habilitado e apenas sistemas operacionais que suportem a especificação funcionam.
3 - Híbrido: ambos juntos funcionando ao mesmo tempo.

A partir do Windows 8, a Microsoft exige que os fabricantes que vendam máquinas com seu sistema pré-instalado usem UEFI com Secure Boot (ver abaixo) habilitado. Com Secure Boot, o CSM obrigatoriamente é desabilitado.

O Windows suporta UEFI a partir do Vista Service Pack 1 e em suas versões 64-bit apenas. As versões 32-bit não suportam e, portanto, só funcionam no modo Legacy.

Nas versões 64-bit do Windows Vista e 7, a versão implementada da especificação UEFI é a 2.0, enquanto estamos hoje na 2.4 (sendo a 2.3.1 a mais popular enquanto escrevo). Vista e 7 ainda requerem funções do CSM, em particular as chamadas INT 10h para lidar com o vídeo até o driver nativo ser carregado. Por isso, não funcionarão em máquinas que encaixem-se no item 2 acima. Alguns firmwares oferecem o modo híbrido, outros não. Distribuições Linux, das que suportem UEFI, não possuem essa limitação.

Firmwares "Class 3" removerão o CSM e acabarão com o modo Legacy, subindo a exigência mínima, dentre os Windows, para o 8. Ainda demorará alguns anos para chegarmos lá.

Particionamento GPT

A especificação UEFI exige que os firmwares suportem MBR e GPT. Na prática, em UEFI, usa-se GPT, que é um esquema de particionamento mais robusto e sem as limitações do MBR. GPT é suportado desde o Windows Vista por todas as versões (e na versão 64-bit do XP, já defunto). Contudo, como volume do sistema, GPT apenas pode ser usado se a instalação for em UEFI. As distribuições Linux podem, em teoria, ser instaladas em GPT ao usar BIOS, porém não é uma configuração recomendada pois existem BIOS bugados que se negam a dar boot assim.

O particionamento GPT usa estruturas diferentes do MBR (também chamado MSDOS) usado pelos BIOS. Para evitar desastres, o primeiro setor de um disco particionado em GPT tem um protective MBR, que é um MBR xing-ling com uma partição fictícia englobando todo o tamanho do disco (ou 2,19 TB em caso de discos maiores, dependendo da implementação). Seu objetivo é única e exclusivamente prevenir que sistemas operacionais caducos, que não suportem GPT, pensem que o disco está vazio. Coisas muito ruins aconteceriam do contrário, convenhamos.

Com GPT, não existe o limite de 2,19 TB do particionamento MBR.

Ao carregar o instalador do Windows no modo Legacy (um BIOS do ponto de vista do sistema operacional) num disco que está particionado em GPT, ele não deixa continuar. O contrário idem. Para o seu bem.

Boot via modo Legacy; disco em GPT

Boot via modo UEFI; disco em MBR

Nada impediria o instalador ter um botão "recriar o particionamento" ou similar. A Microsoft preferiu ser cautelosa. Para continuar a instalação, precisamos recriar o particionamento. Dá para usar o GParted de uma mídia live Linux qualquer (Dispositivo → Criar tabela de partição...), ou o diskpart do próprio Windows, que pode ser chamado durante a instalação.

Na segunda tela do instalador, após selecionar o layout do teclado, pressione Shift+F10. No prompt, digite:

diskpart
list disk

Se "Disco 0" for o correto (observe pelo tamanho):

select disk 0

No caso de mais de um disco com o mesmo tamanho, depois de selecioná-lo, exiba detalhes com detail disk.

Por fim, limpe o particionamento (apagará tudo que estiver no disco!) e saia do diskpart:

clean
exit

Feche o prompt e prossiga a instalação. Estando o disco rígido não particionado, o instalador deixará continuar em ambos os modos.

Bootloaders

A forma como o bootoader é carregado é completamente diferente em UEFI. Além de um identificador do disco (similar ao MBR), o particionamento GPT possui dois identificadores por partição, todos no formato GUID. Um randômico e outro de tipo, que padroniza diferentes tipos de partição de acordo com o sistema de arquivos e sistema operacional. Veja uma lista na Wikipedia (e um post relacionado aqui).

Um desses identificadores de tipo é EFI System Partition (ESP). A especificação UEFI requer que essa partição seja formatada em FAT, um sistema de arquivos que o firmware conhece e sabe acessar sem chainload e coisas do tipo do tempo dos BIOS. Para o processo de boot, a partição ESP é só o que interessa para o firmware.

Outro mecanismo usado são as variáveis de boot. As variáveis são entradas gravadas pelo sistema operacional (geralmente durante sua instalação) na flash ROM, que dizem para o firmware onde os bootloaders estão na partição EFI e em qual ordem devem ser carregados. A especificação define também que, na ausência de variáveis de boot, o firmware carrega por padrão \EFI\BOOT\BOOT<arquitetura>.EFI (em x86-64, BOOTX64.EFI).

Assim sendo, o processo de boot é simples:

- O firmware procura no particionamento GPT uma partição com o identificador de tipo EFI System Partition. Os bootloaders precisam estar nela.
- Olha em suas variáveis qual a ordem dos bootloaders que deve executar.
- Acessa o sistema de arquivos FAT e executa o binário EFI.
- Se não tiver nada em suas variáveis, executa \EFI\BOOT\BOOT<arquitetura>.EFI

Cada empresa/organização possui sua pasta dentro da partição ESP.

Nos BIOS, o código de boot é extremamente diminuto e limitado e roda em 16-bit, com o processador em modo real, acessando 1 MiB de memória. Idem ao que era em 1981 no IBM PC! Uma das grandes vantagens de escrever bootloaders EFI está aí. Existem toolchains para compilar os binários que rodarão em qualquer firmware. O GCC tem o seu, a Microsoft tem o seu, etc. É uma ABI padronizada cujos binários rodam no modo nativo do processador: 32-bit em x86-32* e ARMv7; 64-bit em x86-64, IA-64 e ARMv8 (ARMv8 é uma arquitetura suportada a partir da versão 2.4).

* x86-32 praticamente não é implementado pelos fabricantes de hardware.

Secure Boot

Secure Boot é um recurso opcional da especificação que diz para o firmware apenas executar binários EFI assinados e cuja chave tenha em seu banco de dados (ou hash para binários não assinados). Todos os fabricantes de hardware colocam as chaves da Microsoft, é óbvio, para o Windows 8 poder ser carregado. A certificação da empresa exige que, em hardware x86, o usuário possa desativar o recurso por completo e gerenciar as chaves. Isso permite até mesmo que as chaves da Microsoft sejam removidas. Os firmwares têm no Setup uma seção para modificar tais parâmetros e uma opção para restaurar o padrão de fábrica se você se arrepender.

Existem três níveis de chaves:

- PK (Plataform Key) é a chave do fabricante do hardware. Autoridade máxima, pode alterar as demais. Excluindo-se a PK, o firmware desativa o Secure Boot.
- KEK (Key Exchange Key) é a chave que libera acesso para modificar os bancos DB e DBX (inclusive após o kernel ser carregado). Todas as máquinas com Windows 8 têm a chave da Microsoft aqui. É possível ter mais de uma chave simultaneamente.
- DB e DBX contêm as chaves (ou hashes) que liberarão a execução dos binários EFI. A primeira é uma lista branca e a segunda negra. A lista negra tem prioridade. Máquinas com o Windows 8 possuem três chaves da Microsoft no banco DB.

O ecossistema Linux — kernel e bootloaders — já foi adaptado para funcionar com UEFI e Secure Boot. O barulho geral no início foi devido à questão das chaves. Chegou-se à conclusão que assinar os componentes de cada distribuição com uma chave própria não resolveria nada: a Red Hat, por exemplo, poderia convencer algum fabricante a carregar sua chave, porém daí quem fosse instalar o openSUSE com Secure Boot bateria na porta.

A forma como o Setup oferece as opções varia. Costuma estar na seção "Security".

Lenovo G485

Shim

O Shim é um pré-bootloader que, quando assinado com a chave da Microsoft (umas das presentes no banco DB), faz o meio campo entre o firmware e um outro bootloader (comumente o GRUB) também assinado, porém com uma chave da distribuição. O Shim conhece as duas chaves. Tendo bootloader de verdade carregado, este verifica se o kernel é assinado com a chave da distribuição e o boot continua normalmente com Secure Boot habilitado. Do GRUB em diante, tudo é assinado com a chave da distribuição. Também suporta liberar por hashes binários não assinados através da ferramenta de modo texto MokManager (ver abaixo).

As distribuições, das que conheço, que funcionam de primeira assim são: Fedora, openSUSE, Ubuntu. No caso de outras, que não tenham suporte, existem duas opções:

- Desativar o Secure Boot, mantendo o modo UEFI.

- Usar o modo Legacy, que desabilita o Secure Boot. Se possível, prefira a primeira opção.

Machine Owner Key List (MOKList)

Como comentado anteriormente, os firmwares oferecem opção para gerenciar as chaves, mas não existe nenhuma padronização de como deve ser feito de máquina para máquina. É algo impossível de documentar.

Com o intuito de facilitar a adição de chaves, a SUSE inventou o banco MOK: nada mais do que uma variável do firmware apenas acessível via Boot Services; para ler e alterá-la, o código precisa passar pela validação do firmware. Quando presente, o Shim consulta, além de DB e DBX, o banco MOK, procurando tanto por chave quanto por hash. Sendo o Shim assinado com a chave da Microsoft, poderá acessar/modificar essa variável e assim adiciona a possibilidade do usuário instalar suas próprias chaves/hashes sem mexer em DB e DBX — lembre que o pré-bootloader é assinado com uma chave de DB, que não permite a alteração de DB e DBX (KEK seria necessária).

PreLoader

Parte do pacote da Linux Fundation. Diferente do Shim, funciona com bootloaders da nova geração (Gummiboot, efilinux). O papel do PreLoader é o mesmo do Shim, porém a nova geração de bootloaders, ao invés de carregar e executar binários por conta, o faz via Boot Services. Aí existe um problema: ao usar Boot Services (LoadImage e StartImage), o firmware consulta só os bancos que ele tem conhecimento, DB e DBX, e ignora a MOKList, que é um banco de terceiros, por assim dizer, sobre o qual desconhece.

A solução veio do desenvolvedor do pacote, o mago James Bottomley. O PreLoader intercepta o sistema de autenticação através do protocolo UEFI Security Architecture Protocol e adiciona consulta à MOKList, permitindo os bootloaders executarem binários assinados com chaves presentes nela (ou via hashes). Esse protocolo faz parte de uma especificação separada, UEFI Platform Initialization, não presente na certificação da Microsoft. James, entretanto, diz que todos os sistemas com Windows 8 onde testou implementavam-a.

KeyTool e HashTool são ferramentas que permitem editar as chaves/hashes numa interface à la ncurses.

Fique avisado que a dupla Shim+GRUB é o padrão das distribuições Linux. Pessoalmente torço para que algum dia seja substituída por algo melhor.

Para usuários leigos, a minha recomendação é simplesmente escolher uma distribuição que suporte Secure Boot sem se preocupar com os detalhes técnicos. Ou, se sua distribuição preferida não suportar (porém ao menos funcionar com UEFI), desabilitar no Setup. No caso de dual boot, o Windows 8 continuará iniciando com Secure Boot desabilitado sem reclamar. O 8.1 reclamou um pouquinho com uma marca d'água intempestiva por um tempo, mas a Microsoft acabou mudando de ideia.

Downgrade de Windows

Quem quiser fazer downgrade numa máquina com o Windows 8 pré-instaldo para o Vista/7, pode, usando uma mídia de instalação 64-bit:

- Desativar o Secure Boot, mantendo o modo UEFI. É preciso que o firmware ofereça o CSM mesmo nesse modo, pois, do contrário, o vídeo não funcionará com o driver genérico. Se o firmware não oferecer essa opção, só sobra o modo Legacy. Os notebooks da Acer, por exemplo, não oferecem opção para habilitar o CSM no modo UEFI, enquanto desktops da HP e notebooks da Lenovo oferecem.

- Mudar para o modo Legacy. Nota: instalações piratas funcionarão apenas nesse modo.

Para o carcomido XP e versões 32-bit do Vista/7, a única forma é através do modo Legacy, haja vista que não possuem suporte à UEFI.

Entrando no Setup

A certificação da Microsoft também exige que o tempo gasto no POST não seja maior do que dois segundos. Para ajudar a atingir tal marca, um dos processos mais tomadores de tempo — a enumeração dos dispositivo USB — geralmente não é mais feito pelo firmware. O sistema operacional fará depois de qualquer forma. Teclados USB podem não funcionar para teclar algo e disparar o Setup.

Em notebooks, quase sempre o teclado não usa o barramento USB e sim a velha conexão PS/2 internamente, o que permite detecção por parte do firmware quando uma tecla é pressionada no POST. Isso varia muito de acordo com a implementação, contudo. Existem firmwares que aceitam [Del], [F2], etc, para entrar no Setup e outros que não. Independentemente, a especificação UEFI define uma interface chamada OsIndications, pela qual o sistema operacional pode avisar o firmware para no próximo boot entrar no Setup automaticamente. No Windows 8, você aciona o recurso clicando em "Reiniciar" com a tecla Shift pressionada ou com a opção "/o" do comando shutdown (ex. shutdown.exe /r /o). Você pode fazer o mesmo através da mídia de instalação (64-bit) do Windows 8. Na segunda tela do instalador, após selecionar o layout do teclado, vá em "Reparar o computador → Solução de Problemas → Opções avançadas → Configurações de Firmware UEFI → Reiniciar".

[Atualização - 23/01/2014] Esclarecer na introdução que o Vista precisa do Service Pack 1.
[Atualização - 07/02/2016] A especificação UEFI exige que os firmwares suportem MBR e GPT.
[Atualização - 27/04/2016] Adicionar detail disk na parte do diskpart.

15 comentários:

  1. Deixo aqui meus agradecimentos ao Marcos FRM. Necessitei de informações baseadas em UEFI, CSM e Legacy. Como desbravador de Internet à procura de conhecimentos e, especificamente, precisei resolver questão de "dual boot" win 8 x instalação do Linux Mint Rafaela ao lado do win, com este extraordinário conhecimento e fluidêz de explicações, conseguí resolver o referido problema que vinha tendo com o meu note Ultra Thin S345 da CCE. Por outro lado, me impressionou a falta de comentários. Provavelmente, muita gente não descobriu esta maravilhosa aula sobre UEFI. Luiz, agradece a oportunidade.

    ResponderExcluir
  2. Excelente artigo. Como já foi comentado, demorei para descobrir esta maravilhosa aula sobre UEFI.

    ResponderExcluir
  3. Boa tarde, estou perdido.
    vou testar.
    blog c muit propriedade ao passar as informações

    ResponderExcluir
  4. Muito bom, formatei meu HD e perdi toas as partições é possível recria-las, tentei fazer pelo diskpart em uma maquina virtual, mas não consigo instalar o windows 8 em disco GPT, Poderia me ajudar ?

    ResponderExcluir
    Respostas
    1. Considerando que não haja necessidade de recuperar dados, limpe o particionamento como comento no texto.

      Excluir
  5. Muito bom seu conteúdo MARCOS FRM. Obrigado por compartilhar seu conhecimento de forma detalhada.

    ResponderExcluir
  6. Meus sinceros agradecimentos ao Marcos FRM. Usei as dicas em um notebook Sansung NP270E3E e resolvi o meu problema que apareceu durante o upgrade do SO Windows 8 para Windows 10. Com mais de 30 anos de garimpagem em microcomputadores (desde o Apple II) eu desconhecia o funcionamento do EFI, que ele explica com clareza e propriedade. Parabéms Marcos, e obrigado por compartilhar seus conhecimentos.

    ResponderExcluir
  7. Cara, eu usei um detalhe do seu artigo para resolver um problemão. Sorte minha que vim parar aqui, tem muita porcaria e muita informação incompleta na internet. Resumindo, você ter dito que a partição GPT demanda o sistema de arquivos FAT era toda a informação que eu precisava, mas nunca imaginara que era isso que estava causando o erro aqui. Obrigado!

    ResponderExcluir
  8. Ola marcos. se puder me ajudar agradeceria muito.
    Estou com um ultrabook samsung com win8, consegui entrar no setup e fiz a burrice de apenas alterar a ordem do boot. Não desabilitei o FASTBOOT e desabilitei o UEFI. Pronto foi o necessário para dar merda. O ultrabook depois que formatado e instalado o win10 entrou em looping infinito. E não consigo mais acessar o setup do samsung que é travado de fabrica. Eu ja resetei a bios fisicamente mas continuou a mesma coisa. Eu queria mesmo era reativar o UEFI. Séra que retirando o HD e instalando o win7 e ativando com o Looder, ele voltaria ao normal?

    ResponderExcluir
    Respostas
    1. Sim, ligue-o sem disco rígido e veja se consegue acessar.

      Excluir
    2. Não consigo.O Samsung é o: Samsung Series 5 Ultra Touch Ultrabook. Com uma breve busca sobre esse modelo voce vai ver que muitos estão com o mesmo problema de looping infinito.

      Excluir
  9. No caso iniciando o PC pelo Hirens-boot com HD particionado em GPT.

    Quando entro no mini windows do Hirens, os programas para edição etc. Não aparecem, somente alguns intrínsecos próprio Mini Windos xp mesmo.

    Lembro que para os programas serem identificados eu tinha que mudar de UEFI para IDE no setup (Não lembro qual a parte) e fazer uma outra coisa a mais que não me lembro o que era também.

    Fazendo isso ao menos aparecia os programas que identificavam as partições. Mas não dá para editar, somente formatar.

    Sabe como fazer para que o programa reconheça as partições do HD ?
    Será que tem como fazer o hirens reconhecer outro hd para que possa edita-los, mesmo o principal estar particionado em GPT?

    ResponderExcluir
    Respostas
    1. Windows XP é peça de museu. Use algo mais moderno. Parece que versões mais novas do Hiren vêm com um Mini Windows 7, daí deve funcionar.

      Excluir