Konfiguracja Systemów Operacyjnych - GRUBPC - LINUX - PRAKTYKA Program rozruchowy (bootloader) to element, który rzadko przykuwa uwagę początkujących użytkowników.
Część 1
Warto jednak przyjrzeć mu się trochę bliżej, ponieważ odpowiedni jego wybór i konfiguracja potrafią bardzo ułatwić życie – szczególnie tym,zainteresowanym posiadaniem wielu systemów operacyjnych, eksperymentującym z kompilacją jądra Linuksa (Linux), czy choćby korzystającym z klawiatury USB
Po uruchomieniu komputera BIOS (Basic Input-Output System) testuje sprzęt (POST - Power On Self Test), inicjalizuje ważne struktury systemu (programuje kontrolery przerwań, DMA, inicjuje tablicę wektorów przerwań) i przekazuje sterowanie do urządzenia, które ustawiono jako rozruchowe. Najczęściej będzie to dysk twardy. Jego pierwszy sektor – zwany MBR (Master Boot Record (Sector)) – powinien zawierać program, który zapewni prawidłowy start systemu operacyjnego. Użytkownicy oprogramowania opartego na wolnych źródłach (Open Source) mają do wyboru właściwie dwa takie programy – LILO (LInux LOader) oraz GRUB (GRand Unified Bootloader). Ten drugi posiada nieporównywalnie większe możliwości, jest elastyczniejszy i lepiej konfigurowalny. 
KILKA SŁÓW O MBR MBR ma wielkość 512 bajtów, można go podzielić funkcjonalnie na trzy obszary. Pierwsze 446 bajty to tzw. bootstrap. Dalsze 64 b zajmuje główna tablica partycji, składająca się z czterech 16-bajtowych pól (opisujących cztery partycje podstawowe). Końcowe dwa bajty to sygnatura – 0x55aa (w notacji szesnastkowej). Nas interesuje wyłącznie bootstrap – to tam (w zaledwie 446 bajtach!) musi się zmieścić cały kod programu rozruchowego. Zawartość MBR dysku /dev/hda można obejrzeć dzięki poleceniu: # cfdisk -P r /dev/hda
Tak niewielka przestrzeń zdeterminowała dwa różne podejścia programistów LILO i GRUB-a. LILO w całości znajduje się właśnie w sektorze rozruchowym, GRUB zaś podzielony jest na części, tak zwane piętra (stage), z których tylko jedna - stage1 – zlokalizowana jest w MBR. Każde z rozwiązań ma swoje zalety i wady. LILO jest niezależne od dalszej zawartości dysku, będzie działać nawet po usunięciu czy całkowitej reorganizacji partycji. GRUB musi zawsze posiadać swoje pliki konfiguracyjne i obraz drugiego piętra (stage2) w systemie plików. Ze względu na tę cechę korzystający z GRUB-a powinni posiadać odrobinę większą wiedzę o działaniu swojego programu rozruchowego – choć także nieszczególnie tajemną czy trudną do przyswojenia. Z drugiej strony przeniesienie części programu w inne partie dysku usunęło ograniczenie wynikające z niewielkiego rozmiaru MBR – dzięki czemu GRUB mógł stać się tak elastycznym narzędziem, wyposażonym we własną powłokę (shell) z dopełnianiem poleceń (tab-complementation) oraz w obsługę systemów plików.
INSTALACJA 
Zwykle instalatory najnowszych dystrybucji GNU/Linuksa w swej podstawowej funkcjonalności (bez specjalnych zabiegów, jak np. przełączenie się w tryb expert) nie pozostawiają nam wyboru i instalują wybrany przez developerów program rozruchowy. Co zrobić, gdy jest nim akurat LILO? Przejście na GRUB-a jest operacją bezbolesną i nie wiąże się z żadnym niebezpieczeństwem dla naszych danych. (W ten sposób możemy stwierdzić, czy w naszym systemie znajduje się grub:) Aby dowiedzieć się, czy w naszym systemie znajduje się grub, należy wydać polecenie: $ whereis grub
Odpowiedź podobna do tej: grub: /sbin/grub /lib/grub /usr/share/man/man8/grub.8.gz oznacza, że binaria są obecne i gotowe do instalacji w MBR. Jak zdobyć GRUB-a? Wszystkie znane mi dystrybucję (z pominięciem oczywiście tych najmniejszych, dyskietkowych) posiadają go w swoich repozytoriach. W popularnych wydaniach GNU/Linuksa zalecanym sposobem instalacji jest posłużenie się menedżerem pakietów. Jeżeli jednak z jakiegoś powodu chcemy kompilować ze źródeł, to musimy posiadać w systemie: gcc w wersji 2.95 lub wyższej; GNU Make; GNU binutils w wersji 2.9.1.0.23 lub wyższej. Ściągamy i rozpakowujemy archiwum z kodem źródłowym: $ wget ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz $ tar -xzvf grub-0.97.tar.gz Konfigurujemy i kompilujemy: $ cd grub-0.97 $ ./configure && make Jeżeli pojawiły się komunikaty o błędach, to musimy doinstalować brakujące składniki i krok powtórzyć. W przeciwnym wypadku logujemy się na konto root i instalujemy (będąc cały czas w tym samym katalogu): # make install Przyjrzyjmy się teraz zawartości katalogu /usr/local/lib/grub/i386-pc (zakładając, że w naszym systemie domyślny prefix instalowanych przez użytkownika programów to /usr/local/lib):
Zawartości katalogu
/usr/local/lib/grub/i386-pc $ ls /usr/local/lib/grub/i386-pc efs2_stage1_5 jfs_stage1_5 stage1 ufs2_stage1_5 fat_stage1_5 minix_stage1_5 stage2 vstafs_stage1_5 ffs_stage1_5 reiserfs_stage1_5 stage2_eltorito xfs_stage1_5 iso9660_stage1_5
Właściwy program rozruchowy zawarty jest w obrazie stage2. Żeby ten załadował się z systemu plików, potrzebny jest pomost w postaci stage1.5 (ładowany przez stage1) – który to potrafi rozumieć określony system plików. Stage1.5 zwykle zapisany zostaje w kolejnych 153 sektorach, bezpośrednio za MBR – standardowo miejsce to nie jest używane. Stage1.5 nie jest obligatoryjny – stage1 może bezpośrednio załadować stage2, pod warunkiem, że ten ostatni jest w ściśle określonym sektorze dysku i informacja ta jest zapisana w stage1.  INSTALACJA NA TWARDYM DYSKU W MBR Istnieją dwa sposoby instalacji GRUB-a na twardym dysku. Pierwszy polega na uruchomieniu programu grub-install. Jeżeli nie mamy stacji dyskietek, to możemy dodać --no-floppy, co skróci znacznie czas oczekiwania podczas skanowania urządzeń. Jako parametr podajemy urządzenie, na którym ma zostać zainstalowany GRUB: # grub-install –-no-floppy /dev/hda Dodatkowo polecenie samo zadba o skopiowanie plików z /usr/local/lib/grub/i386-pc/ (przydatne, jeżeli kompilowaliśmy ze źródeł) do odpowiedniego katalogu (domyślnie /boot/grub, katalog /boot możemy zmienić dodając opcję --root-directory=KATALOG). Inny sposób bazuje na operacjach w powłoce GRUB: # grub –no-floppy Po chwili powinien pojawić się znak zachęty: grub > Listę dostępnych poleceń wyświetli komenda help. Pierwsze, co musimy zrobić, to wskazać urządzenie, na którym znajduje katalog główny GRUB – służą do tego komendy root i rootnoverify. Wszystkie istniejące (i tylko takie) urządzenia ponumerowane są od zera. Dyski twarde to hd0, hd1, ... hdn – najpierw liczone są te z interfejsem ATA, następnie SCSI/SATA; stacje dyskietek – fd0, fd1, ..., fdn. Numeracja ta zapisana jest w pliku device.map (standardowo /boot/grub/device.map). Przykłady takich plików dla różnych konfiguracji: jeden dysk twardy ATA podłączony jako master na pierwszym kanale (/dev/hda) i jedna stacja dyskietek (/dev/fd0); device.map: (hd0) /dev/hda (fd0) /dev/fd0 dwa dyski twarde ATA, obydwa na drugim kanale, jeden master (/dev/hdc), drugi slave (/dev/hdd): (hd0) /dev/hdc (hd1) /dev/hdd trzy dyski SCSI (/dev/sda, /dev/sdb, /dev/sdc) na jednym kanale, jeden ATA jako master na drugim kanale (/dev/hdc): (hd0) /dev/hdc (hd1) /dev/sda (hd2) /dev/sdb (hd3) /dev/sdc Ponadto dyski może reprezentować numer, pod jakim widzi je BIOS. Dla hda będzie to (0x80) lub (128) zależnie od tego, czy posługujemy się notacją szesnastkową, czy dziesiętną. Partycje numerowane są także od zera. Podstawowe mogą być tylko cztery, więc zarezerwowane są dla nich oznaczenia 0, 1, 2, 3. Partycje logiczne zawsze zaczynają się od czwórki, nawet wtedy, gdy w rzeczywistości wszystkie podstawowe nie zostały utworzone i wolne są niższe numery. Numer podajemy w nawiasie, oddzielony od numeru urządzenia przecinkiem: /dev/hda1 – pierwsza partycja podstawowa na dysku ATA master pierwszego kanału – (hd0,0) /dev/hdc5 – pierwsza partycja logiczna dysku ATA master drugiego kanału, zakładając, że jest to drugi dysk w systemie – (hd1,4) /dev/sda6 – druga partycja logiczna dysku SCSI, jedynego napędu w systemie – (hd0,5) Znając już te zasady, bez problemu powinniśmy podać w powłoce lokalizację katalogu głównego GRUB. Możemy także posłużyć się dopełnianiem poleceń po naciśnięciu klawisza TAB (tab-complementation): <<LISTING lang=C++ posx=5;0l posy=t fit=W grow=H>> Listing 2. Dopełnianiem poleceń po naciśnięciu klawisza TAB grub> ro [NACISKAMY TAB] Possible commands are: root rootnoverify grub> root (hd [NACISKAMY TAB] Possible disk are: hd0 hd1 hd2 hd3 hd4 grub> root (hd0, [NACISKAMY TAB] Possible partitions are: Partition num: 0, Filesystem type is reiserfs, partition type 0x83 Partition num: 1, Filesystem type is reiserfs, partition type 0x83 grub> root (hd0,0) Filesystem type is reiserfs, partition type 0x83 <</LISTING>> Inną metodą odnalezienia właściwej partycji jest użycie komendy find: grub> find /grub/stage2 (hd0,0) grub> root (hd0,0) Polecenie rootnoverify jest bardzo podobne, z tym, że GRUB nie próbuje wtedy montować partycji – przydatne jest w sytuacjach, kiedy uruchamiamy system operacyjny znajdujący się w obszarze dysku, którego nasz program rozruchowy nie potrafi przeczytać. Rootnoverify będziemy stosować do ładowania np. systemu Windows. Następnym krokiem jest uruchomienie samej instalacji w MBR pierwszego dysku: grub> setup (hd0) Checking if ”/boot/grub/stage1” exists... no Checking if ”/grub/stage1” exists... yes Checking if ”/grub/stage2” exists... yes Checking if ”/grub/e2fs_stage1_5 exists... yes Running ”embed /grub/ef2fs_stage1_5 (hd0)”... 15 sectors are embedded. succeeded Running ”install /grub/stage1 (hd0)1+15 p (hd0,0)/grub/stage2 /grub/menu.lst”... succeeded Done.
INSTALACJA NA TWARDYM DYSKU, NA POCZĄTKU PARTYCJI Instalacja wygląda bardzo podobnie, jednak zamiast oznaczenia dysku podajemy nazwę partycji. Np. instalacja na początku pierwszej partycji podstawowej dysku hda:
# grub grub> root (hd0,0) grub> setup (hd0,0) <- teraz tu jest numer partycji, nie dysku grub> quit Analogicznie, z użyciem programu grub-install: # grub-install –-no-floppy /dev/hda1 Uwaga! Tak zainstalowany GRUB nie będzie się w stanie uruchomić samoczynnie po włączeniu komputera. W MBR dysku, do którego BIOS przekazuje sterowanie, musi już znajdować się jakiś program rozruchowy (np. kolejny GRUB, LILO, isolinux, syslinux, ntldr – loader Windows), który poprzez mechanizm chainload wczyta i uruchomi kod z zerowego sektora tej właśnie partycji. Przykład uruchomienia GRUB-a z partycji (hd0,0) za pomocą innego GRUB-a z MBR – fragment pliku konfiguracyjnego tego drugiego: title GRUB z hd0,0 root (hd0,0)
chainload +1
INSTALACJA NA DYSKIETCE BEZ SYSTEMU PLIKÓW Dyskietka z programem rozruchowym może być bardzo przydatna w sytuacjach awaryjnych – daje dostęp do powłoki GRUB, co umożliwia znalezienie na dysku jądra i uruchomienie go. Równie dobrze może posłużyć także jako loader Windows. Zrobienie takiej dyskietki będzie polegało na zapisaniu do jej zerowego sektora obrazu stage1, następnie bezpośrednio za nim, w kolejnych 153 sektorach, stage2. Wykorzystamy program do kopiowania blokowego – dd. Dyskietki nie montujemy, nie musimy tworzyć na niej systemu plików. Zakładam, że mamy poprawnie zainstalowany GRUB ze swoim katalogiem głównym w /boot: # cd /boot/grub
# dd if=stage1 of=/dev/fd0 bs=512 count=1 1+0 records in 1+0 records out # dd if=stage2 of=/dev/fd0 bs=512 seek=1 153+1 records in 153+1 records out Gotowe.
INSTALACJA NA DYSKIETCE Z SYSTEMEM PLIKÓW Tworzymy system plików (tutaj ext2) i montujemy dyskietkę: # mke2fs /dev/fd0 # mkdir -p /media/floppy && mount -t ext2 /dev/fd0 /media/floppy I tutaj podstawowa różnica – zmieniamy katalog główny (root): # grub-install -–root-directory=/media/floppy /dev/fd0 Nie zapominamy odmontować! # umount /media/floppy
INSTALACJA NA PŁYCIE CD Konieczny będzie plik stage2_eltorito z katalogu GRUB-a oraz program do tworzenia obrazu iso – mkisofs. Do wypalenia płyty zastosujemy cdrecord. Tworzymy katalog: $ mkdir grub-cd W nim przygotowujemy odpowiedni dla GRUB-a układ katalogów i plików: $ mkdir -p grub-cd/boot/grub $ find /usr -name stage2_eltorito -exec cp '{}' grub-cd/boot/grub/ \; Oczywiście możemy także umieścić własny plik konfiguracyjny menu.lst. Z katalogu grub-cd robimy uruchamialny obraz iso: $ mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o grub-cd.iso grub-cd Nagrywamy płytę (odpowiednio zmieniając w razie potrzeby /dev/hdc i wartość speed): # cdrecord -dev=/dev/hdc -speed=8 grub-cd.iso PLIK KONFIGURACYJNY MENU.LST Posługiwanie się powłoką podczas każdego uruchomienia komputera w celu wskazania właściwego do załadowania jądra (i przekazania odpowiednich parametrów) byłoby dość niewygodne. Dlatego mamy do dyspozycji plik menu.lst (standardowo /boot/grub/menu.lst, lokalizacja może zostać zmieniona za pomocą komendy powłoki GRUB configfile). Tutaj, w przeciwieństwie do LILO, po wprowadzeniu zmian w konfiguracji nie musimy robić nic więcej – jest ona czytana bezpośrednio z pliku. LILO po edycji /etc/lilo.conf wymagał przeładowania, gdyż swoje ustawienia przechowywał w MBR. Spójrzmy na kilka typowych sytuacji i przygotujmy odpowiednie pliki menu.lst (linie zaczynające się od znaku # są komentarzem i nie będą brane pod uwagę):
Mamy tylko GNU/Linuksa, jedno jądro. Chcemy, żeby system uruchamiał się od razu, bez wyświetlania menu.
Uruchamianie systemu
# sekcja globalna, dotyczy wszystkich wpisów: default 0 # (default określa numer wpisu, który ma uruchomić się domyślnie; # tutaj właściwie niepotrzebny, gdyż wartość 0 jest domyślna) timeout 0 # (po timeout podajemy liczbę sekund, jaką GRUB ma odczekać # przed uruchomieniem domyślnego wpisu) hiddenmenu # (nie chcemy wyświetlania menu; nie będzie widoczne domyślnie, jednak będzie # można je wywołać przez przytrzymanie klawisza ESC) # tu (się) zaczynają się właściwe wpisy: title Nazwa wyswietlana w menu root (hd0,0) # (root określa partycję główną GRUB-a, nie mylić z partycją root systemu (/)!) kernel (hd0,0)/boot/vmlinuz root=/dev/hda1 ro # (wskazuje lokalizację jądra # po root= podajemy partycję główną – ale tym razem systemu, tj. / # ro oznacza, że system plików znajdujący się na niej zostanie zamontowany w trybie # tylko do odczytu) initrd (hd0,0)/boot/initrd.img # (wskazuje lokalizację obrazu initrd, jeżeli nie korzystamy z initrd.img # to opcje tę pomijamy)
Dwa jądra Linux dwóch różnych dystrybucji i system Windows. Wspólna partycja /boot, dwie partycje /. Chcemy mieć menu w estetycznych kolorach. Jeżeli nie wskażemy inaczej, to po 5 sekundach zostaje załadowany system, który wybrany był przy poprzednim uruchomieniu komputera. <<LISTING lang=C++ posx=8;0l posy=b fit=W grow=H>> Listing 4. System, który wybrany był przy poprzednim uruchomieniu komputera default saved # (w połączeniu z występującą dalej opcją savedefaults sprawia, że uruchomiony zostaje # wpis wybrany przy poprzednim rozruchu) timeout 5 color cyan/blue white/blue # (zmieniamy kolory menu – domyślnie była czerń i biel) title Debian GNU/Linux, kernel 2.6.15 root (hd0,0) # (root wskazuje na naszą partycję /boot) kernel /vmlinuz-2.6.15 root=/dev/hda2 ro # (GRUB będzie szukał pliku z jądrem na partycji określonej wcześniej przez parametr root # równie dobrze można było podać, jak w poprzednim przykładzie, # jawnie (hd0,0)/vmlinuz-2.6.15; /dev/hda2 to partycja / Debiana) savedefault title Mandriva, kernel 2.6.15fb root (hd0,0) kernel /vmlinuz-2.6.15fb root=/dev/hda3 ro vga=0x305 # (po vga podajemy żądany tryb wideo, w którym będzie pracowała konsola # tu mamy jądro z buforem ramki (framebuffer), więc możemy użyć trybu 0x305 # tryby będą wyszczególnione dalej; dwie specjalne wartości dla vga, to # normal – standardowy tryb vga dostępny dla wszystkich standardowych kart # ask – podczas uruchamiania wybieramy tryb z wyświetlonej listy) initrd /initrd.img-2.6.15fb savedefault title Windows rootnoverify (hd0,4) # (Windows na pierwszej partycji logicznej, nie próbujemy jej montować) chainloader (hd0,4)+1 # (wczytujemy jeden sektor z początku partycji (hd0,4); # tam znajduje się ntldr – loader windowsa; # w związku z tym, że partycja (hd0,4) jest wskazana przez rootnoverify, moglibyśmy # użyć samego chainloader +1) savedefault
Linux i Windows. Windows na dysku slave pierwszego kanału ATA (/dev/hdb). Domyślnie po pięciu sekundach uruchamiany Linux. Jeżeli uruchomienie Linuksa się nie powiedzie, to uruchamiane inne jądro w trybie single. <<LISTING lang=C++ posx=9;0l posy=t fit=W grow=H>> Listing 5 Linux i Windows default 0 timeout 5 fallback 1 # (jeżeli uruchomienie domyślnego wpisu 0 się nie powiedzie, ładowany wpis nr 1) color cyan/blue white/blue title Linux root (hd0,0) kernel /boot/vmlinuz ro vga=0x305 title Linux single root (hd0,0) kernel /boot/vmlinuz-generic ro init=/bin/bash # (opcja init=/bin/bash wymusza załadowanie powłoki bash z pominięciem skryptów # init; od razu dostajemy konto root) title Windows rootnoverify (hd1,0) makeactive # (czynimy partycję aktywną) map (hd0) (hd1) map (hd1) (hd0) # (oszukujemy system zmieniając kolejność dysków; Windows będzie odnosił wrażenie, # że startuje z pierwszego napędu) chainloader (hd1,0)+1 ---
Autor / Adam Becmer Materiał publikujemy dzięki Linux+
|