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