MyToyOS: Começo do projeto (de novo)…

Well… Há algum tempo iniciei um projetinho que chamei de “Heisenberg OS”. A ideia era apresentar, passo a passo, o desenvolvimento de um OS “incerto” com a colaboração de desenvolvedores que quisessem participar do projeto lá do grupo “C & Assembly para arquitetura x86-64”, no Facebook. Desanimei porque, depois de algumas semanas, nenhum “forkzinho” foi feito, no GitHub.

Recentemente conheci, de novo pelo Facebook, um sujeito chamado Luciano Gonçalez (o Lucky) que tem um projeto de OS de brinquedo, tal qual como o meu, mas num estágio mais avançado… Só que usando PASCAL como linguagem de programação de alto nível, ao invés de C… Assim como eu, o Lucky só quer ver se consegue fazer um OS simples, sem nenhuma ambição de criar um ambiente de producção completo ou seguro o suficiente para ser usado por alguém que não ele mesmo. Bem… animei em levar o meu projeto a termo, de novo, mas dessa vez com algumas considerações:

  • Esse OS será desenvolvido para o modo x86-64, não apenas para o modo i386;
  • A ideia é evitar o uso extensivo da BIOS e do barramento ISA. Quero desenvolver uma BIOS própria, em modo protegido… A ideia não é nova e explico adiante;
  • Apenas os processadores da família Intel (e AMD) serão contemplados, mas apenas aqueles que suportem um instruction set mais “moderno”… CPUID, SSE4.1, instruções como XSAVE e XRSTOR serão consideradas como existentes (checarei antes). Isso exclui processadores mais antidos como 386, 486 e Pentium (até o Pentium 4, acredito);
  • O OS funcionará como uma espécie de MS-DOS em modo protegido. Não pretendo implementar um sistema multiusuario, mas que suporte multitarefa simétrica…
  • Além das rotinas de pré-carga, não pretendo me ater a padrões de software, exceto no caso de filesystems e interação com hardware; A ideia é tentar descobrir como resolver certos problemas do zero!
  • Inicialmente o sistema não será portável… Um dia, quem sabe, se o troço chegar a sair do papel, posso incorporar camadas de abstração para suportar outros processadores e arquiteturas;
  • Não usarei gambiarras do tipo “modo Unreal”. Apenas recursos documentados serão usados; Isso não contradiz o item acima (sobre “não ater-me aos padrões de software”), apenas quero dizer que macetes que funcionam hoje e poderão não funcionar amanhão não serão usados;
  • As únicas ferramentas usadas para desenvolvimento do bicho serão o GCC (4.8 ou superior), o LD (2.25 ou superior)  e o NASM (2.11.05 ou superior). Esses são os compiladores e linker. No mais, ferramenta de debug: GDB (7.7.1 ou superior); Para editar o código uso o VIM (7.4 ou superior) e acrescentarei modelines em todos os códigos para que a formatação seja formalizada.

Quanto à formatação do código, tenho minhas preferências e as documentarei em algum momento. Eis um exemplo:

  • Eu não gosto do formato ao estilo do java. Códigos como abaixo eu considero feios:
// Código inaceitável para mim:
if (x != 0) {                // <-- Essas chave aqui, ó!
  for (i = 0; i < x; i++) {  // <-------------+
    ...
  }
}

// Como eu gosto:
if (x != 0)
{
  for (i = 0; i < x; i++)
  {
  }
}
  • Eu não gosto de expressões “coladinhas”:
x=0;                     /* Prefiro x = 0; */
for(i=0;i<10;i++){a+=i;} /* Argh! */

// prefiro:
for (i = 0; i < 10; i++) { a += i; }
  • Código não comentado é código inútil. Daqui a umas semanas, quando tiver que modificar alguma coisa, não quero ter que perguntar “Por que diabos eu fiz isso assim?”. A documentação poderá ser tão extensa quanto indicar alguma estrutura em forma de comentário, como em:
...
; i386 descriptors structure:
;
; 31                            16 15                           0
; +---------------+-+-+-+-+-------+-+--+-+-------+---------------+
; |               | |D| |A|  Seg  | | D| |       |               |
; |  Base 31..24  |G|/|L|V| Limit |P| P|S|  Type |  Base 23..16  | 4
; |               | |B| |L| 19..16| | L| |       |               |
; +---------------+-+-+-+-+-------+-+--+-+-------+---------------+
; +-------------------------------+------------------------------+
; |                               |                              |
; |        Base 15..0             |      Seg Limit 15..0         | 0
; |                               |                              |
; +-------------------------------+------------------------------+
;
gdt:
  dq 0      ; NULL descriptor.

  dw 0xffff ; 32 bit code descriptor (executable r/w accessed, dpl=0,
  dw 0      ;   4 KiB granulity - base 0, limit: 4 GiB.
  db 0
  db 0x9b
  db 0xcf
  db 0

  dw 0xffff ; 32 bit data descriptor (r/w accessed, dpl=0,
  dw 0      ;   4 KiB granulity - base 0, limit: 4 GiB.
  db 0
  db 0x9b
  db 0xcf
  db 0
...
  • Todos os comentários serão feito em inglês! Quem sabe algum desenvolvedor gringo não se interessa em participar, algum dia?
  • Uso de atalhos em comentários… FIX, indica algum acerto feito desde a última versão; FIXME: Indica que o método usado pode não ser dos melhores e tem algum probleminha que pode ser resolvido depois; TODO, well…. “a fazer”. Se não há atalhos é uma nota que pode ou não ter o atalho NOTE. Isso facilita a busca por partes do código problemáticos… Se eu sei que existem problemas, basta usar grep e procurar por FIXME. Eis um exemplo de uso desses atalhos:
// FIXME: check_fs_integrity() isn't returning the apropriate value 
//        when x == 0.
if (check_fs_integrity(x)) ...
  • Cada macaco no seu galho: Códigos que fazem coisas específicas ficam em diretórios específicos. Exemplo: src/video/ é o diretório que contém código fonte para rotinas de lidam com vídeo. Algumas misturas podem ser toleradas, dependendo do contexto;
  • Todos os códigos devem ser feitos de maneira a serem tão pequenos quanto possível e o mais rápidos possível. Sem exceções! Ao criar um código devo me perguntar: “Dá pra fazer ficar mais rápido?” e, também, “Dá pra fazer ficar menor?”;

A lista completa do padrão de desenvolvimento publicarei depois.

Quanto ao compartilhamento de código. O Workflow de trabalho, no GitHub, será:

  • Manterei um branch master com as últimas alterações estáveis;
  • Existira’um branch development com as últimas alterações sob teste;
  • Todos os branches do desenvolvedor devem ser forkados de “development”, porque este é um branch “unstable”, mas com as últimas modificações feitas por outros colaboradores;
  • Eu atualizarei esses dois branches à medida que os testes das modificações feitas por outros forem sendo testadas e aprovadas por mim.
  • O colaborador, é claro, é livre para escolher o nome de seu branch local, aquele em que ele vai realizar o pull request, se quiser.
  • Existirão regras estritas para o aceite de um pull request (como as que listei acima).

Eu não espero que alguém venha a forkar meu projeto no GitHub, mas é assim que vai ser…

Padrão dos arquivos binários “executáveis”. Usarei apenas 2: raw e elf. O padrão ELF poderá usará duas especificações: ELF32 e ELF64. No primeiro caso é para o kernel, no segundo, para todos os outros programas, exceto para o bootstrap.

Quanto à documentação: A medida que as coisas forem sendo feitas, documentos texto, contendo informações sobre problemas, soluções, métodos e procedimentos, serão criados…. Tanto por mim quanto pelo colaborador que desejar compartilhar suas modificações no meu github… Em inglês!

Nenhuma modificação será aceita sem discussão prévia… O Github é, além de um repositório para controle de versões, uma rede social… Apontarei erros (tanto de código quanto de não conformidade às regras e até mesmo na gramática!) por lá, até que a coisa esteja certa e possa ser incorporada, não importa o quão boa seja a ideia…

Em resumo: Como pretendi com o Heisenberg OS, esse é um projeto sério, mesmo que seja complexo pra caramba e de muito longo prazo…