bztsrc--bootboot/mkbootimg/OLVASSEL.md

16 KiB

BOOTBOOT Bootolható Lemezkép Készítő

Általános leírásért lásd a BOOTBOOT Protokollt.

Ez egy minden az egyben, többplatformos, függőség nélküli lemezkép kreáló (na jó, zlib kell neki, de az statikusan bele van forgatva). Egy lemezkonfigurációt kell megadni neki JSON-ben, és létrehozza az ESP FAT boot partíciót a szükséges betöltő fájlokkal, GPT táblával, PMBR-el, stb. Továbbá képes létrehozni az induló memórialemezképet egy könyvtár tartalmából. Támogatott fájlrendszerek:

Formátum Initrd Partíció Specifikáció, forrás
jamesm ✔Yes ✗No James Molloy oktatóanyagok
cpio ✔Yes ✗No wikipédia
tar ✔Yes ✔Yes wikipédia
echfs ✔Yes ✔Yes spec, forrás
FS/Z ✔Yes ✔Yes spec, forrás
boot ✗No ✔Yes spec (csak ESP, 8+3 nevek)
fat ✗No ✔Yes spec (csak nem-ESP, LFN-el)
minix ✗No ✔Yes V2 spec, V3 forrás (V3 támogatott, de csak V2-höz van spec)
ext2 ✗No ✔Yes spec, dokumentáció
lean ✗No ✔Yes V0.6 spec, V0.8 spec

A kód úgy lett megírva, hogy könnyű legyen bővíteni új fájlrendszerekkel.

A kigenerált képet leellenőriztem fdisk-el, valamint a gdisk verify funkciójával. A FAT partíció tesztelve lett fsck.vfat-al és UEFI förmverrel, továbbá Raspberry Pi-n. Az ISO9660-es rész iat-vel (ISO9660 Analyzer Tool) és Linux mounttal lett tesztelve.

Áttekintés

Itt a minden komponenst tartalmazó, teljes kép:

Működési módok

$ ./mkbootimg
BOOTBOOT mkbootimg utility - bztsrc@gitlab
 BOOTBOOT Copyright (c) bzt MIT https://gitlab.com/bztsrc/bootboot
 deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler
 Raspbery Pi Firmware Copyright (c) Broadcom Corp, Raspberry Pi (Trading) Ltd

Ellenőrzi, hogy az ELF vagy PE futtatható BOOTBOOT kompatíbilis-e, illetve
hibrid indító lemez képet vagy Option ROM képet generál a hobbi OS-edhez.

Használat:
  ./mkbootimg check <kernel elf / pe>
  ./mkbootimg <konfigurációs json> initrd.rom
  ./mkbootimg <konfigurációs json> bootpart.bin
  ./mkbootimg <konfigurációs json> <kimeneti lemezkép neve>

Példák:
  ./mkbootimg check mykernel/mykernel.x86_64.elf
  ./mkbootimg myos.json initrd.rom
  ./mkbootimg myos.json bootpart.bin
  ./mkbootimg myos.json myos.img

Ha az első paraméter check (ellenőrzés), akkor a második egy kernel fájlnév. A parancs ellenőrizni fogja a futtathatót, hogy megfelel-e a BOOTBOOT-nak, részletesen kijelzi a hibákat, és ha átment az ellenőrzésen, megadja, milyen BOOTBOOT Protokoll szintű betöltő kell a betöltéséhez.

Egyébként az első paraméter a konfigurációs JSON fájl. Ha a második paraméter initrd.rom, akkor BIOS Option ROM-ot generál a megadott initrd könyvtár tartalmából. Ha bootpart.bin, akkor a boot partíció képét menti le (és csakis a partíció képét). Minden más fájlnévre egy teljes lemezképet hoz létre GPT-vel.

Az eszköz többnyelvű. Automatikusan detektálja az operációs rendszered nyelvét, és ha van szótára hozzá, akkor azt használja. Ez felülbírálható parancssorból a -l <nyelv> kapcsolóval, mint első paraméterrel (minden működési mód esetén megadható). A nyelvkód két karakteres, és az alapértelmezett az en. A magyarhoz -l hu-t kell megadni.

Konfiguráció

A JSON egyszerű és rugalmas, többféle variációt is elfogad. A legfelső szinten lehet megadni a lemezre vonatkozó paramétereket.

Legfelső szint

Mező Típus Leírás
diskguid GUID opcionális, a lemez GUID-ja. Ha nincs megadva, vagy csupa nulla, akkor generálódik
disksize szám opcionális, a lemezkép mérete Megabájtban. Ha nincs megadva, kiszámolja
align szám opcionális, partíció igazítás Kilobájtban. Nullával szektorméretre igazít
iso9660 logikai opcionális, generáljon-e ISO9660 Boot Katalógust a lemezképbe. Alapból ne, false
config fájlnév a BOOTBOOT konfigurációs fájl. Ebből olvassa ki a kernel fájlnevét
initrd struktúra az induló lemezkép definícíója, lásd alább
partitions tömb a partícíók definíciói, lásd alább

Példa:

{
    "diskguid": "00000000-0000-0000-0000-000000000000",
    "disksize": 512,
    "align": 1024,
    "iso9660": true,
    "config": "boot/sys/config",
    "initrd": { "type": "tar", "gzip": true, "directory": "boot" },
    "partitions": [
        { "type": "boot", "size": 16 },
        { "type": "ext4", "size": 128, "name": "Linux Exchange" },
        { "type": "ntfs", "size": 128, "name": "Windows Exchange" },
        { "type": "Microsoft basic data", "size": 32, "name": "MyOS usr", "file": "usrpart.bin" },
        { "type": "00000000-0000-0000-0000-000000000000", "size": 32, "name": "MyOS var", "file": "varpart.bin" }
    ]
}

Initrd

Mező Típus Leírás
gzip logikai opcionális, tömörítse-e az induló memórialemezképet, alapértelmezetten igen, true
type sztring az induló memórialemezkép formátuma. Érvénytelen esetén listázza a lehetőségeket
file fájlnév a használandó lemezkép fájlneve
directory mappa mappa elérési útja, a tarmalmából fogja generálni az induló memórialemezképet
file tömb többarchitektúrás lemezképekhez
directory tömb többarchitektúrás lemezképekhez

A file és a directory kölcsönösen kizárja egymást. Mindkettő lehet sztring (ha csak egy architektúrához generálunk), vagy tömb (egy elem minden architektúrához). Jelenleg három támogatott, azaz minden tömb maximum három elemű lehet. Hogy melyik architektúrát jelenti, azt az dönti el, hogy a mabbában vagy lemezképben milyen architektúrájú kernel található. A type típust csak directory esetén kötelező megadni.

Példák:

    "initrd": { "file": "initrd.bin" },
    "initrd": { "type": "tar", "gzip": 0, "directory": "boot" },
    "initrd": { "gzip": true, "file": [ "initrd-x86.bin", "initrd-arm.bin", "initrd-rv64.bin" ] },
    "initrd": { "type": "cpio", "gzip": true, "directory": [ "boot/arm", "boot/x86", "boot/riscv64" ] },

Partíciók

Kicsit szokatlan, a legelső elem különbözik a többitől. Az a boot partíciót definiálja, ezért eltérő típusokat használ, és a file / directory valamint a name nem használható, mivel az a partíció mindig dinamikusan generált, fix "EFI System Partition" névvel. Ugyanezért a size méret megadása kötelező az első (boot) partíciónál.

Mező Típus Leírás
size szám opcionális, a partíció mérete Megabájtban. Ha nincs megadva, kiszámolja
file fájlnév opcionális, a használandó partíciókép elérési útja
directory mappa opcionális, mappa elérési útja, a tarmalmából fogja generálni a partícióképet
driver sztring opcionális, ha a paríció típusa nem határozná meg egyértelműen a formátumot
type sztring a partíció formátuma. Érvénytelen esetén listázza a lehetőségeket
name sztring UTF-8 partíciónév, korlátozva a 32 és 65535 közötti UNICODE kódpontokra (BMP)

Az első elem esetén a type lehetséges értékei: boot (vagy explicit fat16 és fat32). Csak 8+3 fájlneveket generál. A parancs igyekszik kényelmesen kezelni ezt, ha lehet FAT16-ot választva, helytakarékosság miatt. A boot partíció minimális mérete 8 Megabájt. Bár mind a lemezkép készítő, mind a BOOTBOOT betöltő képes lenne kezelni kissebb méretet, néhány UEFI förmver helytelenül FAT12-nek hiszi, ha túl kevés kluszter van a fájlrendszeren. Ha a partíció mérete meghaladja a 128 Megabájtot, akkor automatikusan FAT32-t választ. Ha nem használsz iso9660-t, akkor kissebb méretű is lehet, de legalább 33 Megabájt (ez a FAT32 minimális mérete). Ugyanakkor iso9660 használata esetén garantálni kell, hogy minden kluszter 2048 bájtos címen kezdődjön, amit 4 szektor per kluszterrel a legegyszerűbb elérni. Itt is ugyanaz a probléma merül fel, mind a lemezkép készítő, mind a BOOTBOOT betöltők képesek lennének kevessebb kluszterrel is használni a FAT32-t, de néhány UEFI förmver nem, és hibásan FAT16-nak látná. Hogy ezt elkerüljük a minimális kluszterszámmal, az ISO9960 és FAT32 együttes használata esetén a partíció minimális mérete 128 Megabájt (128*1024*1024/512/4 = 65536, ami pont eggyel több, mint ami még 16 bitbe belefér).

A többi (a másodiktól kezdve) bejegyzés esetén a type vagy egy GUID, vagy egy az előre definiált aliaszok közül. Itt a fat meghajtó csakis a kluszterek száma alapján dönt, hogy FAT16 vagy FAT32 legyen-e, és hosszú fájlneveket is generál. Érvénytelen sztring esetén a parancs listázza az összes lehetséges értéket.

Példa:

mkbootimg: partition #2 nincs érvényes type típusa. Lehetséges értékek:
  "65706154-4120-6372-6968-766520465320" / "tar"
  "5A2F534F-0000-5346-2F5A-000000000000" / "FS/Z"
  "6A898CC3-1DD2-11B2-99A6-080020736631" / "ZFS"
  "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" / "ntfs"
  "0FC63DAF-8483-4772-8E79-3D69D8477DE4" / "ext4"
  "516E7CB6-6ECF-11D6-8FF8-00022D09712B" / "ufs"
  "C91818F9-8025-47AF-89D2-F030D7000C2C" / "p9"
  "D3BFE2DE-3DAF-11DF-BA40-E3A556D89593" / "Intel Fast Flash"
  "21686148-6449-6E6F-744E-656564454649" / "BIOS boot"
     ...
  "77719A0C-A4A0-11E3-A47E-000C29745A24" / "VMware Virsto"
  "9198EFFC-31C0-11DB-8F78-000C2911D1B8" / "VMware Reserved"
  "824CC7A0-36A8-11E3-890A-952519AD3F61" / "OpenBSD data"
  "CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1" / "QNX6 file system"
  "C91818F9-8025-47AF-89D2-F030D7000C2C" / "Plan 9 partition"
  "5B193300-FC78-40CD-8002-E86C45580B47" / "HiFive Unleashed FSBL"
  "2E54B353-1271-4842-806F-E436D6AF6985" / "HiFive Unleashed BBL"
  ...vagy bármilyen nem csupa nulla GUID ilyen formátumban "%08X-%04X-%04X-%04X-%12X"

Ha a file meg van adva, akkor a partíció fel lesz tölve a fájl tartalmával. Ha a size méret nincs megadva, vagy kissebb, mint a fájl mérete, akkor a fájl mérete lesz a partíció mérete. Ha mindkettő meg van adva, és a size nagyobb, akkor a kölönbséget nullákkal tölti fel. A partíció mérete mindig align Kilobájt többszöröse lesz. 1024 megadásával a partíciók 1 Megabájtos címekre lesznek igazítva. Az első bejegyzés esetén csak a size használható, a file nem. Alternatívaként esetleg használható a directory a file helyett, amennyiben a type-nál megadott típushoz van fájlrendszer meghajtó implementálva. Ekkor a megadott mappa tartalmából generálódik a partíció tartalma. Mivel nem feltétlenül van egy-az-egyhez megfeleltetés a partíció típus és a fájlrendszer típus között, ezért használható a driver az utóbbi explicit megadására. Erre csak a directory direktíva használata esetén lehet szükség. Példák:

    { "type": "5A2F534F-8664-5346-2F5A-000075737200", "driver": "FS/Z",  "size": 32, "name": "usr",  "directory": "myusr" },
    { "type": "Linux home",                           "driver": "minix", "size": 32, "name": "home", "directory": "myhome" },
    { "type": "Microsoft basic data",                 "driver": "fat",   "size": 32, "name": "data", "directory": "mydata" },

Végezetül a name egy sima UTF-8 sztring, a partíció neve. Maximális hossza 35 karakter. Az első partíciónál nem használható.

Újabb fájlrendszerek hozzáadása

Ezeket az fs registry listázza, az fs.h fájlban. Szabadon hozzáadhatsz új típusokat. Azoknál a fájlrendszereknél, amiket indító memórialemezképhez vagy partícióképhez is szeretnél használni, implementálni kell három funkciót, például:

void somefs_open(gpt_t *gpt_entry);
void somefs_add(struct stat *st, char *name, int pathlen, unsigned char *content, int size);
void somefs_close();

Az első, az "open" akkor hívódik, amikor egy új fájlrendszert kell létrehozni. Itt a gpt_entry mutató NULL, ha memórialemezkép kreáláshoz hívódik a meghajtó. Ahogy a megadott mappát rekurzívan bejárja, minden almappa és fájl esetén meghívódik az "add". Ez hozzá kell adja a fájlt vagy mappát a fájlrendszer képéhez. Az st a stat struktúra, name a fájl neve teljes elérési úttal, a content és a size pedig a fájl tartalma, illetve szimbolikus hivatkozások esetén a mutatott elérési út. Végezetül amikor a bejárásnak vége, a "close" hívódik meg, hogy lezárja és véglegesítse a lemezképet. Ezek közül csak az "add" a kötelező, a másik kettő opcionális.

Ezek a funkciók elérnek két globális változót, az fs_base-t és fs_len-t, amik a lemezkép memóriabeli bufferét jelölik (ebből következik, hogy a partíciók mérete pár gigabájt lehet, amennyi szabad memória van a gépedben). Ha hibát kell jelenteni, az fs_no változó tartalmazza annak a partíciónak a számát, amihez a meghajtó éppen generál.

Ezen függvények hiányában, a fájlrendszer továbbra is használható a partíciók type mezőjében, de ekkor csak a GPT bejegyzést hozza létre, magát a partíció tartalmát nem. A driver mezőben csak olyan fájlrendszer típus adható meg, ami rendelkezik ezekkel a funkciókkal.

A beépített binárisok naprakészen tartása

Hogy ne legyen függősége, a lemezkép készítő minden szükséges binárist tartalmaz. Ha ezek frissülnek, akkor le kell törölni a data.c fájlt, amit a make parancs újragenerál. Ha hiányol fájlokat, akkor a aarch64-rpi mappában kell kiadni a make getfw parancsot, ami letölti a legfrissebb Raspberry Pi förmver fájlokat. Utánna már menni fog a make ebben a könyvtárban.