Bootowanie freeBSD.

Materiał nie był używany w czasie prezentacji.

Bootowanie systemu.
  Zawsze interesowało mnie co dzieje sie w komputerze po jego uruchomieniu.
  Dlatego w poniższej prezentacji spróbuje to przedstawić na przykładzie systemu operacyjnego freeBSD i architektóry i386.

Fazy Bootowania
 Bootowanie systemu freeBsd możemy podzielić na następujące posobie i w zasadie niezależne (w tym sensie że bardzo wyraźnie oddzielone)  fazy
 
 -BIOS POST
 -boot0
 -boot2
 -loader
 -inicjalizacja jądra

To co jest wyświetlane na ekranie w trakcie poszczególnych faz wygląda mniejwięcej tak
 
F1    FreeBSD
F2 BSD
F5 Disk 2


boot0

>>FreeBSD/i386 BOOT
Default: 1:ad(1,a)/boot/loader
boot:


boot2

BTX loader 1.0 BTX version is 1.01
BIOS drive A: is disk0
BIOS drive C: is disk1
BIOS 639kB/64512kB available memory
FreeBSD/i386 bootstrap loader, Revision 0.8
Console internal video/keyboard
(jkh@bento.freebsd.org, Mon Nov 20 11:41:23 GMT 2000)
/kernel text=0x1234 data=0x2345 syms=[0x4+0x3456]
Hit [Enter] to boot immediately, or any other key for command prompt
Booting [kernel] in 9 seconds..._


loader

Copyright (c) 1992-2002 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD 4.6-RC #0: Sat May 4 22:49:02 GMT 2002
devnull@kukas:/usr/obj/usr/src/sys/DEVNULL
Timecounter "i8254" frequency 1193182 Hz


kernel


Teraz pojawia się pytanie co sie dzieje w trakcie poszczególnych faz

BIOS POST
  BIOS oznacza Basic Input Output System i jest to jak wiemy chip na płycie głównej z małą pamięcią która zawiera troche niskopoziomowych, specyficznych dla danej architektóry instrukcji.
 POST oznacza Power On Self Test i jest jedną z rzeczy, obok wybrania kolejności urządzeń przy bootowaniu, które zostaną wykone po uruchomieniu komputera. Na samym końcu tej fazy jest instrukcja INT 0x19 która wczyta do pamieci 512 bajtów z pierwszego sektora wybranego urządzenia pod konkretny adress. Te 512  bajtów pierwszego sektora zwanych jest pod nazwą Master Boot Record.

boot0
Teraz przechodzimy do pierwszej fazy związanej juz z freeBSD
Dokłanie to co znajduje się w MBR można znaleźć w pliku sys/boot/i386/boot0/boot0.s.
W MBR znajduje sie też struktura zwana tablicą partycji ( w terminologi freeBSD zamiast partycji uzywa sie nazwy slice) która zawiera inforamcje o tym jak dysk jest podzielony. Menadzer bootowania wyswietla informacje o tym z której partycji możemy wystartować system.
Natępnie  wczytuje pierwszy sektor wybranej partycji do pamięci i skacze tam

Uwaga  związana z pisaniem programów które mają być bootowalne w architektórze i386. W każdym takim programie po wczytaniu go pod adres w pamieci 0x7C00 pod adresem 0x7DFE musi znajdować się wartość 0xAA55.(Jest to specyficzna wartość dla architektóry i386  nazywana magiczna liczba)


boot2
 Nazwy boot0,boot2 itd są bezpośrednio związane z nazwami plików freeBSD. Plik boot1 oczywiście również istnieje,ale jest odpowiedzialny z za uruchomienie systemu z dyskietki.
Podstawowe zadanie fazy boot2 to załadowanie i uruchomienie pliku /boot/loader . Oczywiście musi przy tym korzystać tylko z tego że zna system plików i że ma dostęp do podstawowych usług BIOSowych . Umożliwia on również użytkownikowi wybranie innego loader'a.Ważną struktórą która powstaje w tej fazie jest bootinfo. boot2 jest klientem BTX co jest skrótem od BooT eXtender. Oznacza to tyle że plik boot2 w czasie instalacji systemu jest linkowany programem btxld  z BTX. Nastepnie po uruchomieniu tak zlinkowanego boot2 BTX majpierw przełączy procesor w tryb protected i stworzy proste środowisko w którym zostanie uruchomiony klient.
Składa się ono z
     -podstawowego virtual v86 trybu adresowania pamięci.
     -ustawionej  Interrupt Descriptor Table (IDT) tak że przerwania sprzętowe są domyślnie obsługiwane przez bios a przerwanie 0x30 jest ustawione na bramke wywołań systemowych.
      -ustawionych dwóch wywołań systemowych exit i exec.
      -Global Descriptor Table (GDT).
Podstawową zaletą BTX jest to że zapewnia elastyczność  wystarczjącą na to żeby napisać mały program z przyjemnym interfejsem albo dużo łatwiej załadować jądro.

loader
 Loader jest również klientem BTX. Zapewnia on język skryptowy  Forth. Umożliwia dobieranie modulów które moją byc uruchomione, naprawe i debugowanie systemu, zmiane pewnych zmiennych systemowych, i wreszcie załadowanie jądra.

Inicjalizacja jądra  
                            
 Inicjalizacja jądra jest procesem dość skąplikowanym i wiele rzeczy które w tym momencie się dzieją zostanie przezemnie pominiętych.
 Po załadowaniu ido pamięci i przejęciu kontroli jądro wykonuje następujące zadania

     recover_bootinfo - tu jest ustalane jak jądro zostało uruchomione (przez loadera,z dyskietki, czy też przez starą bezdyskietkową procedure)
                                   oraz jest zapamientuje gdzieś w pamięci strukture bootinfo jak i parametry wywołania z poprzednich krokow.
     identify_cpu           staramy się określić jaki mamy procesor i zapisujemy to w pamięci.
     create_pagetables  zajmuje początek pamięci jądra oraz  wypełniamy i wstawia tam Page Table Directory

Kolejne kroki składają się z
   -sprawdzenia czy CPU wspiera VME (Virtual Machine Environment) .
   -włączenie stronicowania
   -wywołania funkcji init386()
   -wywołania funkcji  mi_startup()

init386()
 Jest wywoływana ze wskażnikiem do pierwszej wolnej fizycznej strony pamięci. Wykonuje przede wszystkim operacje które są niezbędne aby wykonywać się w trybie protected. Sa to przedewszystkim
 -ustawienie parametrów przekazanych z poprzednich faz.
 -przygotowanie GDT
 -przygotowanie IDT
 -zainicjowanie konsoli systemowej
 -(opcjonalnie) zainicjowanie DDB (
Interaktywny debuger jądra BSD)
 -zainicjowanie  TSS (Task State Segment) (Związana z trybem protected,służy do przechowywania informacji przy przełączaniu zadań)
 -przygotowanie LDT (Local Descriptors Table)
 -ustawienie Process Control Block  dla struktury proc0 która opisuje proces jądra(Jest ona globalna i zawsze obecna gdy jądro działa)

mi_startup()  
  Ta funkcja  sortuje bombelkowo wszystkie objekty inicjalizacji jądra a następnie wywołuje po koleji wejście każdego z nich.Wywołanie tej funkcji nigdy się nie kończy a jej wywołanie jest końcem procesu bootowania. 
Ostatnim objektem wywołanym przez mi_startup() jest scheduler. Jest on nieskończąną pentlą i jest reprezentowany przez proces o PID 0. Struktura proc0 jest używana właśnie po to aby go opisać. Z kolej pierwszy proces jest wywoływany przez objekt init i też nazywa sie init. Jest on alokowany wtedy funkcja create_init(), ale tworzony dopiero funkcją start_init() wywoływaną przez scheduler.