Hogyan írjunk saját BootManagert – I. rész
Manapság gyakran előfordul, hogy
valamilyen oknál fogva egy számítógépen több operációsrendszert is szeretnénk
használni. Ahhoz hogy ezt megtehessük, egy bootmanagert kell telepítenünk.
Ezekből már meglehetősen sokfajta létezik és néhány operációs
rendszer alapból felrak egyet, én mégis ahhoz próbálok meg ötleteket adni hogy
hogyan kell sajátok készíteni.
Szeretném felhívni az olvasó
figyelmét, hogy csak saját felelősségére fogjon bele, és csak akkor, ha rendelkezik a
megfelelő programozási – elsősorban assembly – ismeretekkel. A
winchester szektorainak közvetlen írása igen veszélyes művelet, ha
figyelmetlenek vagyunk könnyen adatvesztést okozhat.
A cikksorozat első részében az
alapvetőbb elméleti dolgokat fogom leírni, majd átnézzük az Int0x13 megszakítás paraméterezését és használatát, ezután
remélhetőleg megpróbáljuk megvalósítani assembly nyelven, végül pedig
felmásoljuk a Master Boot Record-ba. Elsősorban a kezdeti segítséget
szeretném megadni egy egyszerű bootmanager írásához, az alapján már
mindenki elkészítheti a saját igényeinek megfelelőt.
Az MBR felépítése:
Az operációs rendszer betöltődése
előtt teljes mértékben a BIOS vezérli a számítógépet. Ha a BIOS setup
programjában merevlemezről való indítás van beállítva, a BIOS beolvassa a 0x13-as megszakítással a merevlemez 0. oldal, 0. sáv 1.
szektorát. Ez az un. MBR a Master Boot Record. Itt található a partíciós
táblázat is, ami egy 4x16 bájtos rekord.
A táblázat előtt egy normál bootloader vagy bootmanager van, a szektort
pedig az 0x55AA szó zárja. A partíciós táblázat az MBR 0x1BE offsetjétől
kezdődik és az 0x1FD-ig tart.
1x16 bájtosos, egy partícióra
vonatkozó része:
Byte hossz |
Offset |
Funkció |
1 |
0x1BE |
Ez jelzi hogy aktív-e a
partíció. Két értéket vehet fel 0x80 (bootolható) vagy 0x00 (nem bootolható).
Egyszerre csak egy partíció lehet aktív, ugyanis a bootloaderek ez alapján
választják ki hogy melyik operációs rendszert kell elindítani. |
1 |
0x1BF |
A következő 3 byte a partíció
kezdetét adja meg fizikai CHS jelölésben (cilinder, head, szektor). Ez a byte
azt a fejet jelöli ahol a partíció kezdődik. |
2 |
0x1C0 |
A fenti bájthoz tartozó szektor és a sávszám 6-10 bites
megosztásban. Erről még bővebben
később. |
1 |
0x1C2 |
A partíció típusát
meghatározó byte. (pl FAT32, NTFS, Ext2) Ezzel most nem foglalkozunk. |
1 |
0x1C3 |
A partíció vége CHS-ben.
Fejszám |
2 |
0x1C4 |
A partíció vége CHS-ben.
Sáv+szektor 6-10 bites megosztásban |
4 |
0x1C6 |
A partíció kezdete abszolút
szektorszámban. Ennél a szektor címzésnél csak a szektorszámot használjuk a
winchester írás/olvasásához. Ilyenkor a szekorokat 0-tól számozzuk. |
4 |
0x1CA |
A partíció mérete szektorban. |
A fenti táblázatból van 4 darab, így
maximum 4 elsődleges partíciónk lehet. A kiterjesztett partíciókkal most
nem foglalkozunk, operációs rendszert úgyis primary partícióra szokás rakni.
Láthatjuk hogy a partíció kezdete és vége is kétféleképpen van megadva. Az
elsőnél 3 adatot használunk a címzésre, fej, sáv, és szektorszám. A sáv és
a szektor közösen osztoznak két bájton.
15. |
14. |
13. |
12. |
11. |
10. |
9. |
8. |
7. |
6. |
5. |
4. |
3. |
2. |
1. |
0.bit |
c |
c |
c |
c |
C |
c |
c |
c |
c |
c |
sz |
sz |
sz |
sz |
sz |
sz |
A "c" jelöli a cilindert
vagyis sávot, az "sz" pedig a szektort. A sávnak 10 bit van fenntartva, így maximum 1024 sávon belül lévő
szektorokat érhetjük el. Az ettől távolabb lévőket csak a lineáris címzéssel
tudjuk írni/olvasni. A most használt BIOS-ok már támogatják ezt a funkciót
(int0x13 ah=0x42, int0x13 ah=0x43) , de mivel 64bites szektorszámot kérnek, a
felső dword-öt majd nulláznunk kell, mert a partíciós táblában csak
32bites lineáris szektorszám szerepel.
A bootolás folyamata:
A BIOS beolvassa az MBR-t a 0000:7C00 címre a
memóriába, majd erre a címre ugrik, vagyis az itt tálalható bootloadert vagy
bootmanagert lefuttatja. Ennek a kis programnak az első feladata hogy
átmásolja önmagát a memória egy másik részébe. Egy normál bootloader ezután
végignézi a partíciós táblát és megkeresi hogy melyik az aktív partíció (első byte 0x80),
ennek a legelső szektorát a bootsektort beolvassa az 0x13 megszakítással a
0000:7C00 címre (ezért kellett átmásolnia önmagát máshova), és ráugrik. A
bootsektor programja pedig elindítja az operációsrendszert. Egy bootmanager
annyiban tud többet ennél hogy megengedi a felhasználónak hogy kiválassza hogy
melyik partícióról akar bootolni, vagyis melyik operációsrendszert akarja elindítani. Ehhez
rendelkeznie kell egy kis menüvel amiből választhatunk a felsoroltak
közül.
Nézzük meg egy példán keresztül. Ez az én partíciós
táblázatom. (az adatok little endian-ban vannak vagyis fordított byte sorrendben)
|
‘Bootflag’ |
Kezdet fejszám |
Kezdet Sáv+szektor |
Típus |
Vég Fejszám |
Vég sáv+szektor |
Kezdet szektorban |
Méret szektorban |
1. |
00 |
01 |
0100 |
0C |
0F |
FFFF |
3F000000 |
91DB5F00 |
2. |
80 |
0F |
FFFF |
0C |
0F |
FFFF |
D0DB5F00 |
40A79F00 |
3. |
00 |
0F |
FFFF |
83 |
0F |
FFFF |
1083FF00 |
86A63F00 |
4. |
00 |
0F |
FFFF |
0C |
0F |
FFFF |
50303F01 |
D0986903 |
Az FFFF-eknél már nem fért ki a CHS-es jelöléssel,
ilyenkor majd lineáris címet kell hásználnunk. Láthatjuk hogy
a második partícó az aktív, vagyis az ezen lévő oprendszer fut miközben
gépelem a cikket. A típuskódokból pedig látszik hogy 3 FAT32 és 1 ext2-es
partíció van. Az elsőn win98, a másodikon XP, a harmadikon pedig Linux
van. A felhasználónak a 3-ból kell választani a bootmanager segítségével.
Nézzük meg, mi történik ha pl az
elsőt választjuk. Ennek a szektorban mért mérete 0x5FDB91 (decimálisan
6282129), mivel egy szektor 512byte, így 6282129*512/1024/1024/1024=3Gb. Típusa
pedig fat32.
A teljes MBR a 0000:7C00 címen van
ugyanis a BIOS oda olvasta be. Először is ezt át kell másolnunk máshova,
majd oda kell ugranunk. Ezután megjelenítünk egy menüt amiből a felhasználó
kiválasztja pl az első partíción lévő operációs rendszert. Ekkor
ennek a bootsektorát kell beolvasnunk a 0000:7C00 címre. Vagyis a fenti
táblázat első sor, második, harmadik oszlopában lévő fej, sáv és
szektorszámokat kell kiolvasunk (01, 0100 vagyis 1. fej, 0. sáv, 1. szektor) ,
és ezt a szektort kell betöltenünk a
0000:7C00 címre, mert a win98 bootsektora itt kezdődik. Ha 1024 sávon
kívül lenne ez a szektor akkor csak a bővített BIOS megszakítását
használhatnánk. Most például a hetedik
oszlopban lévő lineáris szekorszámot kellene használnunk, vagyis a 0000003F-edik (3F000000 little endian) szektort kéne
beolvasunk. Ez a 63. szektor ugyanazt jelöli mint az előbb említett, CHS
–ben megadott érték. Miután beolvastuk a megfelelő bootszektort, a
kiválasztott partíciót aktívra kell állítanunk, és rá kell ugrani a bootszektor
betöltő rutinjára. Innentől a bootmanagerünk feladata
befejeződött, a továbbiakat már ez a kis programocska intézi, és
remélhetőleg, ha mindent rendben talál akkor elindítja az
operációsrendszer.
A következő részben gyakorlati dolgokkal
fogunk foglalkozni, és átvesszük az int0x13 megszakítás paramétereit, és
használatát.
Magyar Attila