diff --git a/libs/posix-uefi/LICENSE b/libs/posix-uefi/LICENSE
new file mode 100644
index 0000000..f863cbc
--- /dev/null
+++ b/libs/posix-uefi/LICENSE
@@ -0,0 +1,21 @@
+ Copyright (C) 2021 bzt (bztsrc@gitlab)
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
diff --git a/libs/posix-uefi/OLVASSEL.md b/libs/posix-uefi/OLVASSEL.md
new file mode 100644
index 0000000..c049658
--- /dev/null
+++ b/libs/posix-uefi/OLVASSEL.md
@@ -0,0 +1,385 @@
+POSIX-UEFI
+==========
+
+
Hányunk attól az ocsmány UEFI API-tól, a megszokott POSIX-ot akarjuk!
+
+Ez egy nagyon minimális fordító környezet, ami segít UEFI-re fejleszteni Linux (vagy más POSIX kompatíbilis) rendszer alatt.
+Nagy hatással volt rá a [gnu-efi](https://sourceforge.net/projects/gnu-efi) (minden elismerésem nekik), de annál kissebb,
+egyszerűbb és könnyebben integrálható (működik LLVM Clang és GNU gcc környezettel is), valamint könnyebben is használható,
+mivel POSIX-szerű API-t biztosít az UEFI alkalmazásod felé.
+
+Az UEFI környezet két komponensből áll: a GUID protokoll interfészű firmverből és egy felhasználói könyvtárból. Az előbbit
+nem tudjuk lecserélni, de az utóbbit barátságosabbá tehetjük. És pont ez az, amit a POSIX-UEFI csinál. Egy vékony
+függvénykönyvtár ami becsomagolja a GUID protokollos API-t, nem több, nem kevesebb, nem egy teljes értékű libc implementáció.
+
+Kétféleképp tudod integrálni a projektedbe:
+
+Statikus Függvénykönyvtárként
+-----------------------------
+
+Azonos metódus, mint a gnu-efi-nél, nem igazán javasolt. Az `uefi` könyvtárban futtasd a következő parancsot
+```sh
+$ USE_GCC=1 make
+```
+Ez létrehozza az `build/uefi` mappát, minden szükséges fájllal együtt. Ezek:
+
+ - **crt0.o**, futásidejű kód, ami elind0tja a POSIX-UEFI-t
+ - **link.ld**, linkelő szkript, amit a POSIX-UEFI-vel használni kell (ugyanaz, mint gnu-efi esetén)
+ - **libuefi.a**, a függvénykönyvtár maga
+ - **uefi.h**, minden az egyben C / C++ fejlécfájl
+
+Ezzel összeszerkesztheted a programodat, de nem fogod tudni újrafordítani, és a linkeléssel és konvertálással is magadra
+maradsz.
+
+Szigorúan véve csak a **crt0.o** és a **link.ld** fájlokra van szükség, ez elég ahhoz, hogy elindítsa és meghívja az alkalmazásod
+"main()" eljárását. Viszont ahhoz, hogy a libc funkciókat (mint pl. memcmp, strcpy, malloc vagy fopen) használhasd, linkelned
+kell a **libuefi.a** fájllal is.
+
+Egyenlőre ez a metódus csak gcc-vel működik, mivel a Clang úgy van beállítva, hogy direktben PE fájlokat hoz létre, ezért nem tud
+statikus ELF .a fájlokat generálni, sem linkelni velük.
+
+Forrásként terjesztve
+---------------------
+
+Ez a javasolt mód, mivel ez biztosít egy Makefile-t is ami megfelelően beállítja a fordítókörnyezetedet.
+
+ 1. másold be a `uefi` könyvtárat a forrásfádba (vagy állíts be egy git submodule-t és egy symlinket). Egy tucat fájl, kb. 132K összesen.
+ 2. csinálj egy hihetetlenül egyszerű **Makefile**-t, mint például az alábbi
+ 3. fordítsd le a programodat UEFI-re egy `make` hívással
+
+```
+TARGET = helloworld.efi
+include uefi/Makefile
+```
+Egy minta **helloworld.c** így néz ki:
+```c
+#include
+
+int main(int argc, char **argv)
+{
+ printf("Hello World!\n");
+ return 0;
+}
+```
+Alapértelmezetten Clang + lld környezetet keres és állít be, ami direktben PE fájlt hoz létre konvertálás nélkül. Ha a `USE_GCC`
+környezeti változó be van állítva, akkor a hoszt natív GNU gcc + ld használatával egy megosztott függvénykönyvtárat fordít, amit
+aztán objcopy-val átkonvertál .efi fájllá, pont, mint ahogy a gnu-efi is csinálja.
+
+**MEGJEGYZÉS**: ha nem akarod az egész repót klónozni, csakis az `uefi` könyvtárat, akkor
+```
+git clone --no-checkout https://gitlab.com/bztsrc/posix-uefi.git .
+git sparse-checkout set --no-cone '/uefi/*'
+git checkout
+```
+
+### Elérhető Makefile opciók
+
+| Változó | Leírás |
+|------------|------------------------------------------------------------------------------------------------------|
+| `TARGET` | a cél program (szükséges megadni) |
+| `SRCS` | források listája, amiket fordítani kell (alapértelmezetten minden \*.c \*.S fájl) |
+| `CFLAGS` | további fordító opciók (alapértelmezetten üres, pl. "-Wall -pedantic -std=c99") |
+| `LDFLAGS` | további linkelő opciók (nem hiszem, hogy valaha is szükség lesz erre, csak a teljesség kedvéért) |
+| `LIBS` | további függvénykönyvtárak, amikkel linkelni szeretnél (pl "-lm", csak statikus .a jöhet szóba) |
+| `EXTRA` | bármi további obj fájl, amit még hozzá szeretnél linkelni |
+| `ALSO` | további make szabályok futtatása |
+| `OUTDIR` | ha meg van adva, akkor ide generálja a projekted obj fájljait (alapértelmezetten nincs beállítva) |
+| `USE_GCC` | ha beállítod, akkor natív GNU gcc + ld + objcopy környzetet használ LLVM Clang + Lld helyett |
+| `ARCH` | a cél architektúra |
+
+Itt van egy teljesebb **Makefile** példa:
+```
+ARCH = x86_64
+TARGET = helloworld.efi
+SRCS = $(wildcard *.c)
+CFLAGS = -pedantic -Wall -Wextra -Werror --std=c11 -O2
+LDFLAGS =
+LIBS = -lm
+OUTDIR = build/loader
+
+USE_GCC = 1
+include uefi/Makefile
+```
+A fordítási környezet konfiguráló úgy lett kialakítva, hogy akárhány architektúrával elboldogul, azonban eddig csak az
+`x86_64` crt0 lett alaposan letesztelve. Van `aarch64` és `riscv64` crt0 is, de mivel nekem nincs sem ARM UEFI-s, sem
+RISC-V UEFI-s gépem, **mindkettő teszteletlen**. Elvileg kéne működnie. Ha új architectúrára akarod portolni, akkor a
+setjmp struct-ot kell megadni az uefi.h-ban, valamint csinálni neki egy crt0_X.c fájlt. Ennyi. Minden más
+platformfüggetlenül lett megírva.
+
+### Elérhető konfigurációs opciók
+
+Ezeket az `uefi.h` elején lehet állítani.
+
+| Define | Leírás |
+|-----------------------|-------------------------------------------------------------------------------------------|
+| `UEFI_NO_UTF8` | Ne használjon transzparens UTF-8 konverziót az alkalmazás és az UEFI interfész között |
+| `UEFI_NO_TRACK_ALLOC` | Ne tartsa nyilván a foglalt méreteket (gyorsabb, de bufferen kívülről olvas realloc-nál) |
+
+Lényeges eltérések a POSIX libc-től
+-----------------------------------
+
+Ez a függvénykönyvtár korántsem annyira teljes, mint a glibc vagy a musl például. Csakis a legszükségesebb libc funkciókat
+biztosítja, mivel egyszerűségre törekszik. A legjobb talán UEFI API burkolóként tekinteni rá, és nem pedig egy teljes POSIX
+kompatíbilis libc-ként.
+
+UEFI alatt minden sztring 16 bit széles karakterekkel van tárolva. A függvénykönyvtár biztosít egy `wchar_t` típust ehhez,
+és egy `UEFI_NO_UTF8` define opciót a transzparens `char` és `wchar_t` közötti konvertáláshoz. Ha megadod az `UEFI_NO_UTF8`-at,
+akkor például a main() függvényed NEM `main(int argc, char **argv)` lesz, hanem `main(int argc, wchar_t **argv)`. Az összes
+többi sztring függvény (mint például az strlen() is) ezt a széles karaktertípust fogja használni. Emiatt az összes sztring
+konstansot `L""`-el, a karakterkonstansokat pedig `L''`-el kell definiálni. Hogy mindkét konfigurációt kezelni lehessen,
+adott egy `char_t` típus, ami vagy `char` vagy `wchar_t`, és a `CL()` makró, ami `L` előtagot ad a konstansokhoz, amikor kell.
+Azok a funkciók, amik a karaktereket int típusként kezelik (pl. `getchar`, `putchar`), nem unsigned char-ra csonkítanak, hanem
+wchar_t-re.
+
+Sajnos az UEFI-ben nincs olyan, hogy buffer átméretezés. Az AllocatePool nem fogad bemenetet, és nincs mód egymár allokált
+buffer méretének lekérésére sem. Szóval két rossz közül válaszhatunk a `realloc`-nál:
+1. magunk tartjuk nyilván a méreteket, ami bonyolultabb kódot és lassabb futást jelent.
+2. megbékélünk vele, hogy az adatok másolása az új bufferbe elkerülhetetlenül a régi bufferen túli olvasást eredményez.
+Ez utőbbi opció választható az `UEFI_NO_TRACK_ALLOC` define megadásával.
+
+A fájl típusok a dirent-ben nagyon limitáltak, csak könyvtár és fájl megengedett (DT_DIR, DT_REG), de a stat pluszban az
+S_IFDIR és S_IFREG típusokhoz, S_IFIFO (konzol folyamok: stdin, stdout, stderr), S_IFBLK (Block IO esetén) és S_IFCHR
+(Serial IO esetén) típusokat is visszaadhat.
+
+Továbbá a `getenv` és `setenv` sem POSIX sztandard, mivel az UEFI környezeti változók bináris bitkolbászok.
+
+Nagyjából ennyi, minden más a megszokott.
+
+Az elérhető POSIX funkciók listája
+----------------------------------
+
+### dirent.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| opendir | megszokott, de széles karakterű sztringet is elfogadhat |
+| readdir | megszokott |
+| rewinddir | megszokott |
+| closedir | megszokott |
+
+Mivel az UEFI számára ismeretlen az eszközfájl és a szimbólikus link, a dirent mezők eléggé limitáltak, és csak DT_DIR
+valamint DT_REF típusok támogatottak.
+
+### stdlib.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| atoi | megszokott, de széles karakterű sztringet és "0x" prefixet is elfogadhat |
+| atol | megszokott, de széles karakterű sztringet és "0x" prefixet is elfogadhat |
+| strtol | megszokott, de széles karakterű sztringet is elfogadhat |
+| malloc | megszokott |
+| calloc | megszokott |
+| realloc | megszokott |
+| free | megszokott |
+| abort | megszokott |
+| exit | megszokott |
+| exit_bs | az egész UEFI szörnyűség elhagyása (exit Boot Services) |
+| mbtowc | megszokott (UTF-8 karakter wchar_t-á) |
+| wctomb | megszokott (wchar_t-ról UTF-8 karakterré) |
+| mbstowcs | megszokott (UTF-8 sztringről wchar_t sztringé) |
+| wcstombs | megszokott (wchar_t sztringről UTF-8 sztringé) |
+| srand | megszokott |
+| rand | megszokott, de EFI_RNG_PROTOCOL-t használ, ha lehetséges |
+| getenv | eléggé UEFI specifikus |
+| setenv | eléggé UEFI specifikus |
+
+```c
+int exit_bs();
+```
+Exit Boot Services, az UEFI sárkánylakta vidékének elhagyása. Siker esetén 0-át ad vissza. A sikeres hívást követően nem fogsz
+tudni visszatérni a main()-ből, direktben kell átadnod a vezérlést.
+
+```c
+uint8_t *getenv(char_t *name, uintn_t *len);
+```
+A `name` környezeti változó értékének lekérdezése. Siker esetén a `len` be lesz állítva, és egy frissen allokált buffert
+ad vissza. A hívó felelőssége a visszaadott buffer felszabadítása, ha már nem kell. Hiba esetén NULL-t ad vissza.
+
+```c
+int setenv(char_t *name, uintn_t len, uint8_t *data);
+```
+A `name` környezeti változó beállítása `len` hosszú `data` értékkel. Siker esetén 1-el tér vissza, hibánál 0-val.
+
+### stdio.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| remove | megszokott, de széles karakterű sztringet is elfogadhat |
+| fopen | megszokott, de széles karakterű sztringet is elfogadhat, mode esetén is |
+| fclose | megszokott |
+| fflush | megszokott |
+| fread | megszokott, csak igazi fájlok és blk io (nem stdin) |
+| fwrite | megszokott, csak igazi fájlok és blk io (nem lehet stdout se stderr) |
+| fseek | megszokott, csak igazi fájlok és blk io (nem stdin, stdout, stderr) |
+| ftell | megszokott, csak igazi fájlok és blk io (nem stdin, stdout, stderr) |
+| feof | megszokott, csak igazi fájlok és blk io (nem stdin, stdout, stderr) |
+| fprintf | megszokott, de széles sztring is lehet, BUFSIZ, fájl, ser, stdout, stderr |
+| printf | megszokott, de széles sztring is lehet, max BUFSIZ, csak stdout |
+| sprintf | megszokott, de széles sztring is lehet, max BUFSIZ |
+| vfprintf | megszokott, de széles sztring is lehet, BUFSIZ, fájl, ser, stdout, stderr |
+| vprintf | megszokott, de széles sztring is lehet, max BUFSIZ, csak stdout |
+| vsprintf | megszokott, de széles sztring is lehet, max BUFSIZ |
+| snprintf | megszokott, de széles sztring is lehet |
+| vsnprintf | megszokott, de széles sztring is lehet |
+| getchar | megszokott, blokkol, csak stdin (nincs átirányítás), UNICODE-ot ad vissza |
+| getchar_ifany | nem blokkoló, 0-át ad vissza ha nem volt billentyű, egyébként UNICODE-ot |
+| putchar | megszokott, csak stdout (nincs átriányítás) |
+
+A sztring formázás limitált: csak pozitív számokat fogad el prefixnek, `%d` és `%i`, `%x`, `%X`, `%c`, `%s`, `%q` és `%p` (nincs `%e`,
+`%f`, `%g`, nincs csillag és dollárjel). Ha a `UEFI_NO_UTF8` definiálva van, akkor a formázás wchar_t-t használ, ezért ilyenkor
+támogatott a nem szabványos `%S` (UTF-8 sztring kiírás) és `%Q` (eszképelt UTF-8 sztring kiírás) is. Ezek a funkciók nem
+foglalnak le memóriát, cserébe a teljes hossz `BUFSIZ` lehet (8k ha nem definiálták másképp), kivéve azokat a variánsokat,
+amik elfogadnak maxlen hossz paramétert. Kényelmi okokból támogatott a `%D` aminek `efi_physical_address_t` paramétert kell
+adni, és a memóriát dumpolja, 16 bájtos sorokban. A szám módosítókkal lehet több sort is dumpoltatni, például `%5D` 5 sort
+fog dumpolni (80 bájt).
+
+Fájl megnyitási módok: `"r"` olvasás, `"w"` írás, `"a"` hozzáfűzés. UEFI sajátosságok miatt, `"wd"` könyvtárat hoz létre.
+
+Speciális "eszköz fájlok", amiket meg lehet nyitni:
+
+| Név | Leírás |
+|---------------------|----------------------------------------------------------------------|
+| `/dev/stdin` | ST->ConIn |
+| `/dev/stdout` | ST->ConOut, fprintf |
+| `/dev/stderr` | ST->StdErr, fprintf |
+| `/dev/serial(baud)` | Serial IO protokoll, fread, fwrite, fprintf |
+| `/dev/disk(n)` | Block IO protokoll, fseek, ftell, fread, fwrite, feof |
+
+Block IO esetén az fseek és a buffer méret fread és fwritenál az eszköz blokméretére lesz igazítva. Például fseek(513)
+az 512. bájtra pozicionál szabvány blokkméretnél, de 0-ra nagy 4096-os blokkoknál. A blokkméret detektálásához az fstat-ot
+lehet használni.
+```c
+if(!fstat(f, &st))
+ block_size = st.st_size / st.st_blocks;
+```
+A partíciós GPT tábla értelmezéséhez típusdefiníciók állnak a rendelkezésre, mint `efi_partition_table_header_t` és
+`efi_partition_entry_t`, amikkel a beolvasott adatokra lehet mutatni.
+
+### string.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| memcpy | megszokott, mindenképp bájt |
+| memmove | megszokott, mindenképp bájt |
+| memset | megszokott, mindenképp bájt |
+| memcmp | megszokott, mindenképp bájt |
+| memchr | megszokott, mindenképp bájt |
+| memrchr | megszokott, mindenképp bájt |
+| memmem | megszokott, mindenképp bájt |
+| memrmem | megszokott, mindenképp bájt |
+| strcpy | széles karakterű sztringet is elfogadhat |
+| strncpy | széles karakterű sztringet is elfogadhat |
+| strcat | széles karakterű sztringet is elfogadhat |
+| strncat | széles karakterű sztringet is elfogadhat |
+| strcmp | széles karakterű sztringet is elfogadhat |
+| strncmp | széles karakterű sztringet is elfogadhat |
+| strdup | széles karakterű sztringet is elfogadhat |
+| strchr | széles karakterű sztringet is elfogadhat |
+| strrchr | széles karakterű sztringet is elfogadhat |
+| strstr | széles karakterű sztringet is elfogadhat |
+| strtok | széles karakterű sztringet is elfogadhat |
+| strtok_r | széles karakterű sztringet is elfogadhat |
+| strlen | széles karakterű sztringet is elfogadhat |
+
+### sys/stat.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| stat | megszokott, de széles karakterű sztringet is elfogadhat |
+| fstat | UEFI alatt nincs fd, ezért FILE\*-ot használ |
+| mkdir | megszokott, de széles karakterű sztringet is elfogadhat, mode nem használt |
+
+Mivel az UEFI számára ismeretlen az eszköz major és minor valamint az inode szám, a struct stat mezői limitáltak.
+Az `fstat` implementációja az stdio.c-ben található, mivel el kell érnie bizonyos ott definiált statikus változókat.
+
+### time.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| localtime | paraméterek nem használtak, mindig a pontos időt adja vissza struct tm-ben |
+| mktime | megszokott |
+| time | megszokott |
+
+### unistd.h
+
+| Funkció | Leírás |
+|---------------|----------------------------------------------------------------------------|
+| usleep | megszokott (BS->Stall hívást használ) |
+| sleep | megszokott |
+| unlink | megszokott, de széles karakterű sztringet is elfogadhat |
+| rmdir | megszokott, de széles karakterű sztringet is elfogadhat |
+
+UEFI szolgáltatások elérése
+---------------------------
+
+Elég valószínű, hogy direktben UEFI szolgáltatást kell majd hívni. Ehhez a POSIX-UEFI néhány globális változót biztosít
+az `uefi.h`-ban definiálva:
+
+| Globális változó | Leírás |
+|------------------|----------------------------------------------------------|
+| `*BS`, `gBS` | *efi_boot_services_t*, mutató a Boot Time Services-ra |
+| `*RT`, `gRT` | *efi_runtime_t*, mutató a Runtime Services-ra |
+| `*ST`, `gST` | *efi_system_table_t*, mutató az UEFI System Table-re |
+| `IM` | a betöltött fájlod *efi_handle_t*-je (loaded image) |
+
+Az EFI struktúrák, enumok, típusdefiníciók, defineok mind ANSI C szabványos POSIX stílusúra lettek konvertálva, például
+BOOLEAN -> boolean_t, UINTN -> uintn_t, EFI_MEMORY_DESCRIPTOR -> efi_memory_descriptor_t, és persze
+EFI_BOOT_SERVICES -> efi_boot_services_t.
+
+UEFI funkciók hívása pont olyan egyszerű, mint EDK II esetén, csak meg kell hívni, nincs szükség "uefi_call_wrapper"-re:
+```c
+ ST->ConOut->OutputString(ST->ConOut, L"Hello World!\r\n");
+```
+(Megjegyzés: a printf-el ellentétben az OutputString-nél mindig kell `L""` és ki kell írni `L"\r"`-t a `L"\n"` előtt. Ezek
+azok az apróságok, amikkel a POSIX-UEFI kényelmesebbé teszi az életedet.)
+
+Van továbbá két, nem POSIX szabványos függvény a könyvtárban. Az egyik az `exit_bs()` az UEFI elhagyására, a másik a nem
+blokkoló `getchar_ifany()`.
+
+A gnu-efi-vel ellentétben a POSIX-UEFI nem szennyezi a névteret nemhasznált GUID változókkal. Csak define-okat biztosít,
+ezért mindig neked kell létrehozni a GUID példányt, ha és amikor szükséged van rá.
+
+Példa:
+```c
+efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+efi_gop_t *gop = NULL;
+
+status = BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
+```
+
+Szintén a gnu-efi-vel ellentétben a POSIX-UEFI nem biztosítja a szabványos UEFI fejlécfájlokat. Úgy veszi, hogy azokat
+vagy az EDk II-ből vagy a gnu.efi-ből átmásoltad az /usr/include/efi alá, és biztosítja, hogy be legyenek húzva névtér
+ütközés nélkül. Maga a POSIX-UEFI csak egy nagyon minimális mennyiségű típusdefiniciót biztosít (és azokat is POSIX-osított
+névvel).
+```c
+#include
+#include /* ez működik! Mind a POSIX-UEFI és az EDK II / gnu-efi typedef-ek elérhetők */
+```
+Ennek az az előnye, hogy használhatod a POSIX-UEFI egyszerű könyvtárát és fordító környezetét, ugyanakkor hozzáférhetsz
+a legfrissebb protokoll és interfész definíciókoz egyaránt.
+
+__FONTOS FIGYELMEZTETÉS__
+
+Bizonyos esetekben a GNU-EFI hedörök és a Clang kombinációja hibásan 32 bites `uint64_t` típust eredményezhet. Ha ez előjön,
+akkor a
+```c
+#undef __STDC_VERSION__
+#include
+#include
+```
+kerülőmegoldás lehet a problémára, mivel így nem húzza be az stdint.h-t, helyette az efibind.h fogja definiálni az uint64_t
+típust mint `unsigned long long`.
+
+Licensz
+-------
+
+POSIX_UEFI az MIT licensz alatt kerül terjesztésre.
+
+Hozzájárulások
+--------------
+
+Szeretnék köszönetet mondani @vladimir132 -nek az alapos tesztelésért és a pontos és részletes visszajelzésekért.
+
+Ez minden,
+
+bzt
diff --git a/libs/posix-uefi/README.md b/libs/posix-uefi/README.md
new file mode 100644
index 0000000..ac4cf6d
--- /dev/null
+++ b/libs/posix-uefi/README.md
@@ -0,0 +1,389 @@
+POSIX-UEFI
+==========
+
+We hate that horrible and ugly UEFI API, we want the usual POSIX!
+
+------------------------------------------------------------------------------------------------------------------------
+
+NOTE: a smartypants on reddit is worried that I'm supposedly "hiding something" because of the use of `-Wno-builtin-declaration-mismatch`
+(gcc) and `-Wno-incompatible-library-redeclaration` (Clang) flags. **Here's my answer to you: I hide nothing**, that flag is only
+needed because you can disable transparent UTF-8 conversion. You see, under the hood UEFI uses 16 bit characters, and for example
+`strlen(wchar_t *str)` or `main(int argc, wchar_t *argv)` isn't exactly POSIX-standard, that's why there's a need for that flag.
+You should know that had you have spent more time learning or just *reading this README* instead of falsely accusing others on reddit.
+
+------------------------------------------------------------------------------------------------------------------------
+
+This is a very small build environment that helps you to develop for UEFI under Linux (and other POSIX systems). It was
+greatly inspired by [gnu-efi](https://sourceforge.net/projects/gnu-efi) (big big kudos to those guys), but it is a lot
+smaller, easier to integrate (works with LLVM Clang and GNU gcc both) and easier to use because it provides a POSIX like
+API for your UEFI application.
+
+An UEFI environment consist of two parts: a firmware with GUID protocol interfaces and a user library. We cannot change
+the former, but we can make the second friendlier. That's what POSIX-UEFI does for your application. It is a small API
+wrapper library around the GUID protocols, not a fully blown POSIX compatible libc implementation.
+
+You have two options on how to integrate it into your project:
+
+Distributing as Static Library
+------------------------------
+
+Same method as with gnu-efi, not really recommended. In the `uefi` directory, run
+```sh
+$ USE_GCC=1 make
+```
+This will create `build/uefi` with all the necessary files in it. These are:
+
+ - **crt0.o**, the run-time that bootstraps POSIX-UEFI
+ - **link.ld**, the linker script you must use with POSIX-UEFI (same as with gnu-efi)
+ - **libuefi.a**, the library itself
+ - **uefi.h**, the all-in-one C / C++ header
+
+You can use this and link your application with it, but you won't be able to recompile it, plus you're on your own with
+the linking and converting.
+
+Strictly speaking you'll only need **crt0.o** and **link.ld**, that will get you started and will call your application's
+"main()", but to get libc functions like memcmp, strcpy, malloc or fopen, you'll have to link with **libuefi.a** too.
+
+For now this only works with gcc, because Clang is configured in a way to directly create PE files, so it cannot create
+nor link with static ELF .a files.
+
+Distributing as Source
+----------------------
+
+This is the preferred way, as it also provides a Makefile to set up your toolchain properly.
+
+ 1. simply copy the `uefi` directory into your source tree (or set up a git submodule and a symlink). A dozen files, about 132K in total.
+ 2. create an extremely simple **Makefile** like the one below
+ 3. compile your code for UEFI by running `make`
+
+```
+TARGET = helloworld.efi
+include uefi/Makefile
+```
+An example **helloworld.c** goes like this:
+```c
+#include
+
+int main(int argc, char **argv)
+{
+ printf("Hello World!\n");
+ return 0;
+}
+```
+By default it uses Clang + lld, and PE is generated directly without conversion. If `USE_GCC` is set, then the host native's
+GNU gcc + ld is used to create a shared object and get converted into an .efi file with objcopy, just like how gnu-efi does.
+
+**NOTE**: if you don't want to clone this entire repo, just the `uefi` directory,
+```
+git clone --no-checkout https://gitlab.com/bztsrc/posix-uefi.git .
+git sparse-checkout set --no-cone '/uefi/*'
+git checkout
+```
+
+### Available Makefile Options
+
+| Variable | Description |
+|------------|-------------------------------------------------------------------------------------------------------------------|
+| `TARGET` | the target application (required) |
+| `SRCS` | list of source files you want to compile (defaults to \*.c \*.S) |
+| `CFLAGS` | compiler flags you want to use (empty by default, like "-Wall -pedantic -std=c99") |
+| `LDFLAGS` | linker flags you want to use (I don't think you'll ever need this, just in case) |
+| `LIBS` | additional libraries you want to link with (like "-lm", only static .a libraries allowed) |
+| `EXTRA` | any additional object files you might want to link with, these are also called as makefile rules before compiling |
+| `ALSO` | additional makefile rules to be called after compiling |
+| `OUTDIR` | if given, then your project's object files are generated into this directory (by default not set) |
+| `USE_GCC` | set this if you want native GNU gcc + ld + objcopy instead of LLVM Clang + Lld |
+| `ARCH` | the target architecture |
+
+Here's a more advanced **Makefile** example:
+```
+ARCH = x86_64
+TARGET = helloworld.efi
+SRCS = $(wildcard *.c)
+CFLAGS = -pedantic -Wall -Wextra -Werror --std=c11 -O2
+LDFLAGS =
+LIBS = -lm
+OUTDIR = build/loader
+
+USE_GCC = 1
+include uefi/Makefile
+```
+The build environment configurator was created in a way that it can handle any number of architectures, however only
+`x86_64` crt0 has been throughfully tested for now. There's an `aarch64` and a `riscv64` crt0 too, but since I don't
+have neither an ARM UEFI, nor a RISC-V UEFI board, these **haven't been tested at all**. Should work though. If you want
+to port it to another architecture, all you need is a setjmp struct in uefi.h, and an appropriate crt_X.c file. That's
+it. Everything else was coded in an architecture independent way.
+
+### Available Configuration Options
+
+These can be set at the beginning of `uefi.h`.
+
+| Define | Description |
+|-----------------------|-------------------------------------------------------------------------------------------|
+| `UEFI_NO_UTF8` | Do not use transparent UTF-8 conversion between the application and the UEFI interface |
+| `UEFI_NO_TRACK_ALLOC` | Do not keep track of allocated buffers (faster, but causes out of bound reads on realloc) |
+
+Notable Differences to POSIX libc
+---------------------------------
+
+This library is nowhere near as complete as glibc or musl for example. It only provides the very basic libc functions
+for you, because simplicity was one of its main goals. It is the best to say this is just wrapper around the UEFI API,
+rather than a POSIX compatible libc.
+
+All strings in the UEFI environment are stored with 16 bits wide characters. The library provides `wchar_t` type for that,
+and the `UEFI_NO_UTF8` define to convert between `char` and `wchar_t` transparently. If you have `UEFI_NO_UTF8`, then for
+example your main() will NOT be like `main(int argc, char **argv)`, but `main(int argc, wchar_t **argv)` instead. All
+the other string related libc functions (like strlen() for example) will use this wide character type too. For this reason,
+you must specify your string literals with `L""` and characters with `L''`. To handle both configurations, `char_t` type is
+defined, which is either `char` or `wchar_t`, and the `CL()` macro which might add the `L` prefix to constant literals.
+Functions that are supposed to handle characters in int type (like `getchar`, `putchar`), do not truncate to unsigned char,
+rather to wchar_t.
+
+Sadly UEFI has no concept of reallocation. AllocatePool does not accept input, and there's no way to query the size of an
+already allocated buffer. So we are left with two bad options with `realloc`:
+1. we keep track of sizes ourselves, which means more complexcity and a considerable overhead, so performance loss.
+2. make peace with the fact that copying data to the new buffer unavoidably reads out of bounds from the old buffer.
+You can choose this latter with the `UEFI_NO_TRACK_ALLOC` define.
+
+File types in dirent are limited to directories and files only (DT_DIR, DT_REG), but for stat in addition to S_IFDIR and
+S_IFREG, S_IFIFO (for console streams: stdin, stdout, stderr), S_IFBLK (for Block IO) and S_IFCHR (for Serial IO) also
+returned.
+
+Note that `getenv` and `setenv` aren't POSIX standard, because UEFI environment variables are binary blobs.
+
+That's about it, everything else is the same.
+
+List of Provided POSIX Functions
+--------------------------------
+
+### dirent.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| opendir | as usual, but might accept wide char strings |
+| readdir | as usual |
+| rewinddir | as usual |
+| closedir | as usual |
+
+Because UEFI has no concept of device files nor of symlinks, dirent fields are limited and only DT_DIR and DT_REG supported.
+
+### stdlib.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| atoi | as usual, but might accept wide char strings and understands "0x" prefix |
+| atol | as usual, but might accept wide char strings and understands "0x" prefix |
+| strtol | as usual, but might accept wide char strings |
+| malloc | as usual |
+| calloc | as usual |
+| realloc | as usual |
+| free | as usual |
+| abort | as usual |
+| exit | as usual |
+| exit_bs | leave this entire UEFI bullshit behind (exit Boot Services) |
+| mbtowc | as usual (UTF-8 char to wchar_t) |
+| wctomb | as usual (wchar_t to UTF-8 char) |
+| mbstowcs | as usual (UTF-8 string to wchar_t string) |
+| wcstombs | as usual (wchar_t string to UTF-8 string) |
+| srand | as usual |
+| rand | as usual, but uses EFI_RNG_PROTOCOL if possible |
+| getenv | pretty UEFI specific |
+| setenv | pretty UEFI specific |
+
+```c
+int exit_bs();
+```
+Exit Boot Services. Returns 0 on success. You won't be able to return from main() after calling this successfully, you must
+transfer control directly.
+
+```c
+uint8_t *getenv(char_t *name, uintn_t *len);
+```
+Query the value of environment variable `name`. On success, `len` is set, and a malloc'd buffer returned. It is
+the caller's responsibility to free the buffer later. On error returns NULL.
+```c
+int setenv(char_t *name, uintn_t len, uint8_t *data);
+```
+Sets an environment variable by `name` with `data` of length `len`. On success returns 1, otherwise 0 on error.
+
+### stdio.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| remove | as usual, but might accept wide char strings |
+| fopen | as usual, but might accept wide char strings, also for mode |
+| fclose | as usual |
+| fflush | as usual |
+| fread | as usual, only real files and blk io accepted (no stdin) |
+| fwrite | as usual, only real files and blk io accepted (no stdout nor stderr) |
+| fseek | as usual, only real files and blk io accepted (no stdin, stdout, stderr) |
+| ftell | as usual, only real files and blk io accepted (no stdin, stdout, stderr) |
+| feof | as usual, only real files and blk io accepted (no stdin, stdout, stderr) |
+| fprintf | as usual, might be wide char strings, BUFSIZ, files, ser, stdout, stderr |
+| printf | as usual, might be wide char strings, max BUFSIZ, stdout only |
+| sprintf | as usual, might be wide char strings, max BUFSIZ |
+| vfprintf | as usual, might be wide char strings, BUFSIZ, files, ser, stdout, stderr |
+| vprintf | as usual, might be wide char strings, max BUFSIZ, stdout only |
+| vsprintf | as usual, might be wide char strings, max BUFSIZ |
+| snprintf | as usual, might be wide char strings |
+| vsnprintf | as usual, might be wide char strings |
+| getchar | as usual, blocking, stdin only (no stream redirects), returns UNICODE |
+| getchar_ifany | non-blocking, returns 0 if there was no key press, UNICODE otherwise |
+| putchar | as usual, stdout only (no stream redirects) |
+
+String formating is limited; only supports padding via positive number prefixes, `%d`, `%i`, `%x`, `%X`, `%c`, `%s`, `%q` and
+`%p` (no `%e`, `%f`, `%g`, no asterisk and dollar). When `UEFI_NO_UTF8` is defined, then formating operates on wchar_t, so
+it also supports the non-standard `%S` (printing an UTF-8 string) and `%Q` (printing an escaped UTF-8 string). These
+functions don't allocate memory, but in return the total length of the output string cannot be longer than `BUFSIZ`
+(8k if you haven't defined otherwise), except for the variants which have a maxlen argument. For convenience, `%D` requires
+`efi_physical_address_t` as argument, and it dumps memory, 16 bytes or one line at once. With the padding modifier you can
+dump more lines, for example `%5D` gives you 5 lines (80 dumped bytes).
+
+File open modes: `"r"` read, `"w"` write, `"a"` append. Because of UEFI peculiarities, `"wd"` creates directory.
+
+Special "device files" you can open:
+
+| Name | Description |
+|---------------------|----------------------------------------------------------------------|
+| `/dev/stdin` | returns ST->ConIn |
+| `/dev/stdout` | returns ST->ConOut, fprintf |
+| `/dev/stderr` | returns ST->StdErr, fprintf |
+| `/dev/serial(baud)` | returns Serial IO protocol, fread, fwrite, fprintf |
+| `/dev/disk(n)` | returns Block IO protocol, fseek, ftell, fread, fwrite, feof |
+
+With Block IO, fseek and buffer size for fread and fwrite is always truncated to the media's block size. So fseek(513)
+for example will seek to 512 with standard block sizes, and 0 with large 4096 block sizes. To detect the media's block
+size, use fstat.
+```c
+if(!fstat(f, &st))
+ block_size = st.st_size / st.st_blocks;
+```
+To interpret a GPT, there are typedefs like `efi_partition_table_header_t` and `efi_partition_entry_t` which you can point
+to the read data.
+
+### string.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| memcpy | as usual, works on bytes |
+| memmove | as usual, works on bytes |
+| memset | as usual, works on bytes |
+| memcmp | as usual, works on bytes |
+| memchr | as usual, works on bytes |
+| memrchr | as usual, works on bytes |
+| memmem | as usual, works on bytes |
+| memrmem | as usual, works on bytes |
+| strcpy | might work on wide char strings |
+| strncpy | might work on wide char strings |
+| strcat | might work on wide char strings |
+| strncat | might work on wide char strings |
+| strcmp | might work on wide char strings |
+| strncmp | might work on wide char strings |
+| strdup | might work on wide char strings |
+| strchr | might work on wide char strings |
+| strrchr | might work on wide char strings |
+| strstr | might work on wide char strings |
+| strtok | might work on wide char strings |
+| strtok_r | might work on wide char strings |
+| strlen | might work on wide char strings |
+
+### sys/stat.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| stat | as usual, but might accept wide char strings |
+| fstat | UEFI doesn't have fd, so it uses FILE\* |
+| mkdir | as usual, but might accept wide char strings, and mode unused |
+
+Because UEFI has no concept of device major and minor number nor of inodes, struct stat's fields are limited.
+The actual implementation of `fstat` is in stdio.c, because it needs to access static variables defined there.
+
+### time.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| localtime | argument unused, always returns current time in struct tm |
+| mktime | as usual |
+| time | as usual |
+
+### unistd.h
+
+| Function | Description |
+|---------------|----------------------------------------------------------------------------|
+| usleep | as usual (uses BS->Stall) |
+| sleep | as usual |
+| unlink | as usual, but might accept wide char strings |
+| rmdir | as usual, but might accept wide char strings |
+
+Accessing UEFI Services
+-----------------------
+
+It is very likely that you want to call UEFI specific functions directly. For that, POSIX-UEFI specifies some globals
+in `uefi.h`:
+
+| Global Variable | Description |
+|-----------------|----------------------------------------------------------|
+| `*BS`, `gBS` | *efi_boot_services_t*, pointer to the Boot Time Services |
+| `*RT`, `gRT` | *efi_runtime_t*, pointer to the Runtime Services |
+| `*ST`, `gST` | *efi_system_table_t*, pointer to the UEFI System Table |
+| `IM` | *efi_handle_t* of your Loaded Image |
+
+The EFI structures, enums, typedefs and defines are all converted to ANSI C standard POSIX style, for example
+BOOLEAN -> boolean_t, UINTN -> uintn_t, EFI_MEMORY_DESCRIPTOR -> efi_memory_descriptor_t, and of course
+EFI_BOOT_SERVICES -> efi_boot_services_t.
+
+Calling UEFI functions is as simple as with EDK II, just do the call, no need for "uefi_call_wrapper":
+```c
+ ST->ConOut->OutputString(ST->ConOut, L"Hello World!\r\n");
+```
+(Note: unlike with printf, with OutputString you must use `L""` and also print carrige return `L"\r"` before `L"\n"`. These
+are the small things that POSIX-UEFI does for you to make your life comfortable.)
+
+There are two additional, non-POSIX calls in the library. One is `exit_bs()` to exit Boot Services, and the other is
+a non-blocking version `getchar_ifany()`.
+
+Unlike gnu-efi, POSIX-UEFI does not pollute your application's namespace with unused GUID variables. It only provides
+header definitions, so you must create each GUID instance if and when you need them.
+
+Example:
+```c
+efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+efi_gop_t *gop = NULL;
+
+status = BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
+```
+
+Also unlike gnu-efi, POSIX-UEFI does not provide standard EFI headers. It expects that you have installed those under
+/usr/include/efi from EDK II or gnu-efi, and POSIX-UEFI makes it possible to use those system wide headers without
+naming conflicts. POSIX-UEFI itself ships the very minimum set of typedefs and structs (with POSIX-ized names).
+```c
+#include
+#include /* this will work as expected! Both POSIX-UEFI and EDK II / gnu-efi typedefs available */
+```
+The advantage of this is that you can use the simplicity of the POSIX-UEFI library and build environment, while getting
+access to the most up-to-date protocol and interface definitions at the same time.
+
+__IMPORTANT NOTE__
+
+In some cases the combination of GNU-EFI headers and Clang might incorrectly define `uint64_t` as 32 bits. If this happens,
+then
+```c
+#undef __STDC_VERSION__
+#include
+#include
+```
+should workaround the problem by avoiding the inclusion of stdint.h and defining uint64_t by efibind.h as `unsigned long long`.
+
+License
+-------
+
+POSIX_UEFI is licensed under the terms of the MIT license.
+
+Contributors
+------------
+
+I'd like to say thanks to @vladimir132 for a through testing and very accurate and detailed feedbacks.
+
+Cheers,
+
+bzt
diff --git a/libs/posix-uefi/uefi/crt_aarch64.c b/libs/posix-uefi/uefi/crt_aarch64.c
new file mode 100644
index 0000000..82324a5
--- /dev/null
+++ b/libs/posix-uefi/uefi/crt_aarch64.c
@@ -0,0 +1,239 @@
+/*
+ * crt_aarch64.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief C runtime, bootstraps an EFI application to call standard main()
+ *
+ */
+
+#include
+
+/* this is implemented by the application */
+extern int main(int argc, char_t **argv);
+
+/* definitions for elf relocations */
+#ifndef __clang__
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+typedef uint64_t Elf64_Addr;
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define R_AARCH64_RELATIVE 1027 /* Adjust by program base */
+#endif
+
+/* globals to store system table pointers */
+efi_handle_t IM = NULL;
+efi_system_table_t *ST = NULL;
+efi_boot_services_t *BS = NULL;
+efi_runtime_services_t *RT = NULL;
+efi_loaded_image_protocol_t *LIP = NULL;
+#ifndef UEFI_NO_UTF8
+char *__argvutf8 = NULL;
+#endif
+
+/* we only need one .o file, so use inline Assembly here */
+void bootstrap(void)
+{
+ __asm__ __volatile__ (
+ /* call init in C */
+ " .align 4\n"
+#ifndef __clang__
+ " .globl _start\n"
+ "_start:\n"
+ " ldr x2, =ImageBase\n"
+ " adrp x3, _DYNAMIC\n"
+ " add x3, x3, #:lo12:_DYNAMIC\n"
+ " bl uefi_init\n"
+ " ret\n"
+
+ /* fake a relocation record, so that EFI won't complain */
+ " .data\n"
+ "dummy: .long 0\n"
+ " .section .reloc, \"a\"\n"
+ "label1:\n"
+ " .long dummy-label1\n"
+ " .long 10\n"
+ " .word 0\n"
+ ".text\n"
+#else
+ " .globl __chkstk\n"
+ "__chkstk:\n"
+ " ret\n"
+#endif
+ );
+
+ /* setjmp and longjmp */
+ __asm__ __volatile__ (
+ " .p2align 3\n"
+ " .globl setjmp\n"
+ "setjmp:\n"
+ " mov x16, sp\n"
+ " stp x19, x20, [x0, #0]\n"
+ " stp x21, x22, [x0, #16]\n"
+ " stp x23, x24, [x0, #32]\n"
+ " stp x25, x26, [x0, #48]\n"
+ " stp x27, x28, [x0, #64]\n"
+ " stp x29, x30, [x0, #80]\n"
+ " str x16, [x0, #96]\n"
+ " stp d8, d9, [x0, #112]\n"
+ " stp d10, d11, [x0, #128]\n"
+ " stp d12, d13, [x0, #144]\n"
+ " stp d14, d15, [x0, #160]\n"
+ " mov w0, #0\n"
+ " ret\n"
+ );
+ __asm__ __volatile__ (
+ " .globl longjmp\n"
+ "longjmp:\n"
+ " ldp x19, x20, [x0, #0]\n"
+ " ldp x21, x22, [x0, #16]\n"
+ " ldp x23, x24, [x0, #32]\n"
+ " ldp x25, x26, [x0, #48]\n"
+ " ldp x27, x28, [x0, #64]\n"
+ " ldp x29, x30, [x0, #80]\n"
+ " ldr x16, [x0, #96]\n"
+ " ldp d8, d9, [x0, #112]\n"
+ " ldp d10, d11, [x0, #128]\n"
+ " ldp d12, d13, [x0, #144]\n"
+ " ldp d14, d15, [x0, #160]\n"
+ " mov sp, x16\n"
+ " cmp w1, #0\n"
+ " mov w0, #1\n"
+ " csel w0, w1, w0, ne\n"
+ " br x30\n"
+ );
+}
+
+/**
+ * Initialize POSIX-UEFI and call the application's main() function
+ */
+efi_status_t uefi_init (
+ efi_handle_t image, efi_system_table_t *systab
+#ifndef __clang__
+ , uintptr_t ldbase, Elf64_Dyn *dyn
+#endif
+) {
+ efi_guid_t shpGuid = EFI_SHELL_PARAMETERS_PROTOCOL_GUID;
+ efi_shell_parameters_protocol_t *shp = NULL;
+ efi_guid_t shiGuid = SHELL_INTERFACE_PROTOCOL_GUID;
+ efi_shell_interface_protocol_t *shi = NULL;
+ efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+ efi_status_t status;
+ int argc = 0, i, ret;
+ wchar_t **argv = NULL;
+#ifndef UEFI_NO_UTF8
+ int j;
+ char *s;
+#endif
+#ifndef __clang__
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ uintptr_t *addr;
+ /* handle relocations */
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA: rel = (Elf64_Rel*)((unsigned long)dyn[i].d_un.d_ptr + ldbase); break;
+ case DT_RELASZ: relsz = dyn[i].d_un.d_val; break;
+ case DT_RELAENT: relent = dyn[i].d_un.d_val; break;
+ default: break;
+ }
+ }
+ if (rel && relent) {
+ while (relsz > 0) {
+ if(ELF64_R_TYPE (rel->r_info) == R_AARCH64_RELATIVE)
+ { addr = (unsigned long *)(ldbase + rel->r_offset); *addr += ldbase; }
+ rel = (Elf64_Rel*) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ }
+#else
+ (void)i;
+#endif
+ /* failsafes, should never happen */
+ if(!image || !systab || !systab->BootServices || !systab->BootServices->HandleProtocol ||
+ !systab->BootServices->OpenProtocol || !systab->BootServices->AllocatePool || !systab->BootServices->FreePool)
+ return EFI_UNSUPPORTED;
+ /* save EFI pointers and loaded image into globals */
+ IM = image;
+ ST = systab;
+ BS = systab->BootServices;
+ RT = systab->RuntimeServices;
+ BS->HandleProtocol(image, &lipGuid, (void **)&LIP);
+ /* get command line arguments */
+ status = BS->OpenProtocol(image, &shpGuid, (void **)&shp, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shp) { argc = (int)shp->Argc; argv = shp->Argv; }
+ else {
+ /* if shell 2.0 failed, fallback to shell 1.0 interface */
+ status = BS->OpenProtocol(image, &shiGuid, (void **)&shi, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shi) { argc = (int)shi->Argc; argv = shi->Argv; }
+ }
+ /* call main */
+#ifndef UEFI_NO_UTF8
+ if(argc && argv) {
+ ret = (argc + 1) * ((int)sizeof(uintptr_t) + 1);
+ for(i = 0; i < argc; i++)
+ for(j = 0; argv[i] && argv[i][j]; j++)
+ ret += argv[i][j] < 0x80 ? 1 : (argv[i][j] < 0x800 ? 2 : 3);
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, (uintn_t)ret, (void **)&__argvutf8);
+ if(EFI_ERROR(status) || !__argvutf8) { argc = 0; __argvutf8 = NULL; }
+ else {
+ s = __argvutf8 + argc * (int)sizeof(uintptr_t);
+ *((uintptr_t*)s) = (uintptr_t)0; s += sizeof(uintptr_t);
+ for(i = 0; i < argc; i++) {
+ *((uintptr_t*)(__argvutf8 + i * (int)sizeof(uintptr_t))) = (uintptr_t)s;
+ for(j = 0; argv[i] && argv[i][j]; j++) {
+ if(argv[i][j]<0x80) { *s++ = argv[i][j]; } else
+ if(argv[i][j]<0x800) { *s++ = ((argv[i][j]>>6)&0x1F)|0xC0; *s++ = (argv[i][j]&0x3F)|0x80; } else
+ { *s++ = ((argv[i][j]>>12)&0x0F)|0xE0; *s++ = ((argv[i][j]>>6)&0x3F)|0x80; *s++ = (argv[i][j]&0x3F)|0x80; }
+ }
+ *s++ = 0;
+ }
+ }
+ }
+ ret = main(argc, (char**)__argvutf8);
+ if(__argvutf8) BS->FreePool(__argvutf8);
+ return ret;
+#else
+ ret = main(argc, argv);
+#endif
+ return ret ? EFIERR(ret) : EFI_SUCCESS;
+}
diff --git a/libs/posix-uefi/uefi/crt_riscv64.c b/libs/posix-uefi/uefi/crt_riscv64.c
new file mode 100644
index 0000000..77b52ae
--- /dev/null
+++ b/libs/posix-uefi/uefi/crt_riscv64.c
@@ -0,0 +1,270 @@
+/*
+ * crt_riscv64.c
+ *
+ * Copyright (C) 2023 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief C runtime, bootstraps an EFI application to call standard main()
+ *
+ */
+
+#include
+
+/* this is implemented by the application */
+extern int main(int argc, char_t **argv);
+
+/* definitions for elf relocations */
+#ifndef __clang__
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+typedef uint64_t Elf64_Addr;
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define R_RISCV_RELATIVE 3 /* Adjust by program base */
+#endif
+
+/* globals to store system table pointers */
+efi_handle_t IM = NULL;
+efi_system_table_t *ST = NULL;
+efi_boot_services_t *BS = NULL;
+efi_runtime_services_t *RT = NULL;
+efi_loaded_image_protocol_t *LIP = NULL;
+#ifndef UEFI_NO_UTF8
+char *__argvutf8 = NULL;
+#endif
+
+/* we only need one .o file, so use inline Assembly here */
+void bootstrap(void)
+{
+ __asm__ __volatile__ (
+ /* call init in C */
+ " .align 4\n"
+#ifndef __clang__
+ " .globl _start\n"
+ "_start:\n"
+ " lla a2, ImageBase\n"
+ " lui a3, %hi(_DYNAMIC)\n"
+ " addi a3, a3, %lo(_DYNAMIC)\n"
+ " call uefi_init\n"
+ " ret\n"
+
+ /* fake a relocation record, so that EFI won't complain */
+ " .data\n"
+ "dummy: .long 0\n"
+ " .section .reloc, \"a\"\n"
+ "label1:\n"
+ " .long dummy-label1\n"
+ " .long 10\n"
+ " .word 0\n"
+ ".text\n"
+#else
+ " .globl __chkstk\n"
+ "__chkstk:\n"
+ " ret\n"
+#endif
+ );
+
+ /* setjmp and longjmp */
+ __asm__ __volatile__ (
+ " .p2align 3\n"
+ " .globl setjmp\n"
+ "setjmp:\n"
+ " sd ra, 0(a0)\n"
+ " sd sp, 8(a0)\n"
+ " sd s0, 16(a0)\n"
+ " sd s1, 24(a0)\n"
+ " sd s2, 32(a0)\n"
+ " sd s3, 40(a0)\n"
+ " sd s4, 48(a0)\n"
+ " sd s5, 56(a0)\n"
+ " sd s6, 64(a0)\n"
+ " sd s7, 72(a0)\n"
+ " sd s8, 80(a0)\n"
+ " sd s9, 88(a0)\n"
+ " sd s10, 96(a0)\n"
+ " sd s11, 104(a0)\n"
+#ifndef __riscv_float_abi_soft
+ " fsd fs0, 112(a0)\n"
+ " fsd fs1, 120(a0)\n"
+ " fsd fs2, 128(a0)\n"
+ " fsd fs3, 136(a0)\n"
+ " fsd fs4, 144(a0)\n"
+ " fsd fs5, 152(a0)\n"
+ " fsd fs6, 160(a0)\n"
+ " fsd fs7, 168(a0)\n"
+ " fsd fs8, 176(a0)\n"
+ " fsd fs9, 184(a0)\n"
+ " fsd fs10,192(a0)\n"
+ " fsd fs11,200(a0)\n"
+#endif
+ " li a0, 0\n"
+ " ret\n"
+ );
+ __asm__ __volatile__ (
+ " .globl longjmp\n"
+ "longjmp:\n"
+ " ld ra, 0(a0)\n"
+ " ld sp, 8(a0)\n"
+ " ld s0, 16(a0)\n"
+ " ld s1, 24(a0)\n"
+ " ld s2, 32(a0)\n"
+ " ld s3, 40(a0)\n"
+ " ld s4, 48(a0)\n"
+ " ld s5, 56(a0)\n"
+ " ld s6, 64(a0)\n"
+ " ld s7, 72(a0)\n"
+ " ld s8, 80(a0)\n"
+ " ld s9, 88(a0)\n"
+ " ld s10, 96(a0)\n"
+ " ld s11, 104(a0)\n"
+#ifndef __riscv_float_abi_soft
+ " fld fs0, 112(a0)\n"
+ " fld fs1, 120(a0)\n"
+ " fld fs2, 128(a0)\n"
+ " fld fs3, 136(a0)\n"
+ " fld fs4, 144(a0)\n"
+ " fld fs5, 152(a0)\n"
+ " fld fs6, 160(a0)\n"
+ " fld fs7, 168(a0)\n"
+ " fld fs8, 176(a0)\n"
+ " fld fs9, 184(a0)\n"
+ " fld fs10,192(a0)\n"
+ " fld fs11,200(a0)\n"
+#endif
+ " seqz a0, a1\n"
+ " add a0, a0, a1\n"
+ " ret\n"
+ );
+}
+
+/**
+ * Initialize POSIX-UEFI and call the application's main() function
+ */
+efi_status_t uefi_init (
+ efi_handle_t image, efi_system_table_t *systab
+#ifndef __clang__
+ , uintptr_t ldbase, Elf64_Dyn *dyn
+#endif
+) {
+ efi_guid_t shpGuid = EFI_SHELL_PARAMETERS_PROTOCOL_GUID;
+ efi_shell_parameters_protocol_t *shp = NULL;
+ efi_guid_t shiGuid = SHELL_INTERFACE_PROTOCOL_GUID;
+ efi_shell_interface_protocol_t *shi = NULL;
+ efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+ efi_status_t status;
+ int argc = 0, i, ret;
+ wchar_t **argv = NULL;
+#ifndef UEFI_NO_UTF8
+ int j;
+ char *s;
+#endif
+#ifndef __clang__
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ uintptr_t *addr;
+ /* handle relocations */
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA: rel = (Elf64_Rel*)((unsigned long)dyn[i].d_un.d_ptr + ldbase); break;
+ case DT_RELASZ: relsz = dyn[i].d_un.d_val; break;
+ case DT_RELAENT: relent = dyn[i].d_un.d_val; break;
+ default: break;
+ }
+ }
+ if (rel && relent) {
+ while (relsz > 0) {
+ if(ELF64_R_TYPE (rel->r_info) == R_RISCV_RELATIVE)
+ { addr = (unsigned long *)(ldbase + rel->r_offset); *addr += ldbase; }
+ rel = (Elf64_Rel*) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ }
+#else
+ (void)i;
+#endif
+ /* failsafes, should never happen */
+ if(!image || !systab || !systab->BootServices || !systab->BootServices->HandleProtocol ||
+ !systab->BootServices->OpenProtocol || !systab->BootServices->AllocatePool || !systab->BootServices->FreePool)
+ return EFI_UNSUPPORTED;
+ /* save EFI pointers and loaded image into globals */
+ IM = image;
+ ST = systab;
+ BS = systab->BootServices;
+ RT = systab->RuntimeServices;
+ BS->HandleProtocol(image, &lipGuid, (void **)&LIP);
+ /* get command line arguments */
+ status = BS->OpenProtocol(image, &shpGuid, (void **)&shp, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shp) { argc = (int)shp->Argc; argv = shp->Argv; }
+ else {
+ /* if shell 2.0 failed, fallback to shell 1.0 interface */
+ status = BS->OpenProtocol(image, &shiGuid, (void **)&shi, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shi) { argc = (int)shi->Argc; argv = shi->Argv; }
+ }
+ /* call main */
+#ifndef UEFI_NO_UTF8
+ if(argc && argv) {
+ ret = (argc + 1) * ((int)sizeof(uintptr_t) + 1);
+ for(i = 0; i < argc; i++)
+ for(j = 0; argv[i] && argv[i][j]; j++)
+ ret += argv[i][j] < 0x80 ? 1 : (argv[i][j] < 0x800 ? 2 : 3);
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, (uintn_t)ret, (void **)&__argvutf8);
+ if(EFI_ERROR(status) || !__argvutf8) { argc = 0; __argvutf8 = NULL; }
+ else {
+ s = __argvutf8 + argc * (int)sizeof(uintptr_t);
+ *((uintptr_t*)s) = (uintptr_t)0; s += sizeof(uintptr_t);
+ for(i = 0; i < argc; i++) {
+ *((uintptr_t*)(__argvutf8 + i * (int)sizeof(uintptr_t))) = (uintptr_t)s;
+ for(j = 0; argv[i] && argv[i][j]; j++) {
+ if(argv[i][j]<0x80) { *s++ = argv[i][j]; } else
+ if(argv[i][j]<0x800) { *s++ = ((argv[i][j]>>6)&0x1F)|0xC0; *s++ = (argv[i][j]&0x3F)|0x80; } else
+ { *s++ = ((argv[i][j]>>12)&0x0F)|0xE0; *s++ = ((argv[i][j]>>6)&0x3F)|0x80; *s++ = (argv[i][j]&0x3F)|0x80; }
+ }
+ *s++ = 0;
+ }
+ }
+ }
+ ret = main(argc, (char**)__argvutf8);
+ if(__argvutf8) BS->FreePool(__argvutf8);
+ return ret;
+#else
+ ret = main(argc, argv);
+#endif
+ return ret ? EFIERR(ret) : EFI_SUCCESS;
+}
diff --git a/libs/posix-uefi/uefi/crt_x86_64.c b/libs/posix-uefi/uefi/crt_x86_64.c
new file mode 100644
index 0000000..b146bb3
--- /dev/null
+++ b/libs/posix-uefi/uefi/crt_x86_64.c
@@ -0,0 +1,241 @@
+/*
+ * crt_x86_64.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief C runtime, bootstraps an EFI application to call standard main()
+ *
+ */
+
+#include
+
+/* this is implemented by the application */
+extern int main(int argc, char_t **argv);
+
+/* definitions for elf relocations */
+#ifndef __clang__
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+typedef uint64_t Elf64_Addr;
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#endif
+
+/* globals to store system table pointers */
+efi_handle_t IM = NULL;
+efi_system_table_t *ST = NULL;
+efi_boot_services_t *BS = NULL;
+efi_runtime_services_t *RT = NULL;
+efi_loaded_image_protocol_t *LIP = NULL;
+#ifndef UEFI_NO_UTF8
+char *__argvutf8 = NULL;
+#endif
+
+/* we only need one .o file, so use inline Assembly here */
+void bootstrap(void)
+{
+ __asm__ __volatile__ (
+ /* call init in C */
+ " .align 4\n"
+#ifndef __clang__
+ " .globl _start\n"
+ "_start:\n"
+ " lea ImageBase(%rip), %rdi\n"
+ " lea _DYNAMIC(%rip), %rsi\n"
+ " call uefi_init\n"
+ " ret\n"
+
+ /* fake a relocation record, so that EFI won't complain */
+ " .data\n"
+ "dummy: .long 0\n"
+ " .section .reloc, \"a\"\n"
+ "label1:\n"
+ " .long dummy-label1\n"
+ " .long 10\n"
+ " .word 0\n"
+ ".text\n"
+#else
+ " .globl __chkstk\n"
+ "__chkstk:\n"
+ " ret\n"
+#endif
+ );
+
+ /* setjmp and longjmp */
+ __asm__ __volatile__ (
+ " .globl setjmp\n"
+ "setjmp:\n"
+ " pop %rsi\n"
+ " movq %rbx,0x00(%rdi)\n"
+ " movq %rsp,0x08(%rdi)\n"
+ " push %rsi\n"
+ " movq %rbp,0x10(%rdi)\n"
+ " movq %r12,0x18(%rdi)\n"
+ " movq %r13,0x20(%rdi)\n"
+ " movq %r14,0x28(%rdi)\n"
+ " movq %r15,0x30(%rdi)\n"
+ " movq %rsi,0x38(%rdi)\n"
+ " xor %rax,%rax\n"
+ " ret\n"
+ );
+ __asm__ __volatile__ (
+ " .globl longjmp\n"
+ "longjmp:\n"
+ " movl %esi, %eax\n"
+ " movq 0x00(%rdi), %rbx\n"
+ " movq 0x08(%rdi), %rsp\n"
+ " movq 0x10(%rdi), %rbp\n"
+ " movq 0x18(%rdi), %r12\n"
+ " movq 0x20(%rdi), %r13\n"
+ " movq 0x28(%rdi), %r14\n"
+ " movq 0x30(%rdi), %r15\n"
+ " xor %rdx,%rdx\n"
+ " mov $1,%rcx\n"
+ " cmp %rax,%rdx\n"
+ " cmove %rcx,%rax\n"
+ " jmp *0x38(%rdi)\n"
+ );
+}
+
+/**
+ * Initialize POSIX-UEFI and call the application's main() function
+ */
+efi_status_t uefi_init (
+#ifndef __clang__
+ uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_handle_t image
+#else
+ efi_handle_t image, efi_system_table_t *systab
+#endif
+) {
+ efi_guid_t shpGuid = EFI_SHELL_PARAMETERS_PROTOCOL_GUID;
+ efi_shell_parameters_protocol_t *shp = NULL;
+ efi_guid_t shiGuid = SHELL_INTERFACE_PROTOCOL_GUID;
+ efi_shell_interface_protocol_t *shi = NULL;
+ efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+ efi_status_t status;
+ int argc = 0, i, ret;
+ wchar_t **argv = NULL;
+#ifndef UEFI_NO_UTF8
+ int j;
+ char *s;
+#endif
+#ifndef __clang__
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ uintptr_t *addr;
+ /* handle relocations */
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA: rel = (Elf64_Rel*)((unsigned long)dyn[i].d_un.d_ptr + ldbase); break;
+ case DT_RELASZ: relsz = dyn[i].d_un.d_val; break;
+ case DT_RELAENT: relent = dyn[i].d_un.d_val; break;
+ default: break;
+ }
+ }
+ if (rel && relent) {
+ while (relsz > 0) {
+ if(ELF64_R_TYPE (rel->r_info) == R_X86_64_RELATIVE)
+ { addr = (unsigned long *)(ldbase + rel->r_offset); *addr += ldbase; }
+ rel = (Elf64_Rel*) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ }
+#else
+ (void)i;
+#endif
+ /* make sure SSE is enabled, because some say there are buggy firmware in the wild not doing that */
+ __asm__ __volatile__ (
+ " movq %cr0, %rax\n"
+ " andb $0xF1, %al\n"
+ " movq %rax, %cr0\n"
+ " movq %cr4, %rax\n"
+ " orw $3 << 9, %ax\n"
+ " mov %rax, %cr4\n"
+ );
+ /* failsafes, should never happen */
+ if(!image || !systab || !systab->BootServices || !systab->BootServices->HandleProtocol ||
+ !systab->BootServices->OpenProtocol || !systab->BootServices->AllocatePool || !systab->BootServices->FreePool)
+ return EFI_UNSUPPORTED;
+ /* save EFI pointers and loaded image into globals */
+ IM = image;
+ ST = systab;
+ BS = systab->BootServices;
+ RT = systab->RuntimeServices;
+ BS->HandleProtocol(image, &lipGuid, (void **)&LIP);
+ /* get command line arguments */
+ status = BS->OpenProtocol(image, &shpGuid, (void **)&shp, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shp) { argc = (int)shp->Argc; argv = shp->Argv; }
+ else {
+ /* if shell 2.0 failed, fallback to shell 1.0 interface */
+ status = BS->OpenProtocol(image, &shiGuid, (void **)&shi, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if(!EFI_ERROR(status) && shi) { argc = (int)shi->Argc; argv = shi->Argv; }
+ }
+ /* call main */
+#ifndef UEFI_NO_UTF8
+ if(argc && argv) {
+ ret = (argc + 1) * ((int)sizeof(uintptr_t) + 1);
+ for(i = 0; i < argc; i++)
+ for(j = 0; argv[i] && argv[i][j]; j++)
+ ret += argv[i][j] < 0x80 ? 1 : (argv[i][j] < 0x800 ? 2 : 3);
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, (uintn_t)ret, (void **)&__argvutf8);
+ if(EFI_ERROR(status) || !__argvutf8) { argc = 0; __argvutf8 = NULL; }
+ else {
+ s = __argvutf8 + argc * (int)sizeof(uintptr_t);
+ *((uintptr_t*)s) = (uintptr_t)0; s += sizeof(uintptr_t);
+ for(i = 0; i < argc; i++) {
+ *((uintptr_t*)(__argvutf8 + i * (int)sizeof(uintptr_t))) = (uintptr_t)s;
+ for(j = 0; argv[i] && argv[i][j]; j++) {
+ if(argv[i][j]<0x80) { *s++ = argv[i][j]; } else
+ if(argv[i][j]<0x800) { *s++ = ((argv[i][j]>>6)&0x1F)|0xC0; *s++ = (argv[i][j]&0x3F)|0x80; } else
+ { *s++ = ((argv[i][j]>>12)&0x0F)|0xE0; *s++ = ((argv[i][j]>>6)&0x3F)|0x80; *s++ = (argv[i][j]&0x3F)|0x80; }
+ }
+ *s++ = 0;
+ }
+ }
+ }
+ ret = main(argc, (char**)__argvutf8);
+ if(__argvutf8) BS->FreePool(__argvutf8);
+#else
+ ret = main(argc, argv);
+#endif
+ return ret ? EFIERR(ret) : EFI_SUCCESS;
+}
diff --git a/libs/posix-uefi/uefi/dirent.c b/libs/posix-uefi/uefi/dirent.c
new file mode 100644
index 0000000..402011c
--- /dev/null
+++ b/libs/posix-uefi/uefi/dirent.c
@@ -0,0 +1,76 @@
+/*
+ * dirent.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in dirent.h
+ *
+ */
+
+#include
+
+extern void __stdio_seterrno(efi_status_t status);
+static struct dirent __dirent;
+
+DIR *opendir (const char_t *__name)
+{
+ DIR *dp = (DIR*)fopen(__name, CL("rd"));
+ if(dp) rewinddir(dp);
+ return dp;
+}
+
+struct dirent *readdir (DIR *__dirp)
+{
+ efi_status_t status;
+ efi_file_info_t info;
+ uintn_t bs = sizeof(efi_file_info_t);
+ memset(&__dirent, 0, sizeof(struct dirent));
+ status = __dirp->Read(__dirp, &bs, &info);
+ if(EFI_ERROR(status) || !bs) {
+ if(EFI_ERROR(status)) __stdio_seterrno(status);
+ else errno = 0;
+ return NULL;
+ }
+ __dirent.d_type = info.Attribute & EFI_FILE_DIRECTORY ? DT_DIR : DT_REG;
+#ifndef UEFI_NO_UTF8
+ __dirent.d_reclen = (unsigned short int)wcstombs(__dirent.d_name, info.FileName, FILENAME_MAX - 1);
+#else
+ __dirent.d_reclen = strlen(info.FileName);
+ strncpy(__dirent.d_name, info.FileName, FILENAME_MAX - 1);
+#endif
+ return &__dirent;
+}
+
+void rewinddir (DIR *__dirp)
+{
+ if(__dirp)
+ __dirp->SetPosition(__dirp, 0);
+}
+
+int closedir (DIR *__dirp)
+{
+ return fclose((FILE*)__dirp);
+}
+
+
diff --git a/libs/posix-uefi/uefi/elf_aarch64_efi.lds b/libs/posix-uefi/uefi/elf_aarch64_efi.lds
new file mode 100644
index 0000000..836d982
--- /dev/null
+++ b/libs/posix-uefi/uefi/elf_aarch64_efi.lds
@@ -0,0 +1,63 @@
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+ .text 0x0 : {
+ _text = .;
+ *(.text.head)
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ *(.srodata)
+ *(.rodata*)
+ . = ALIGN(16);
+ }
+ _etext = .;
+ _text_size = . - _text;
+ .dynamic : { *(.dynamic) }
+ .data : ALIGN(4096)
+ {
+ _data = .;
+ *(.sdata)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+ *(.got.plt)
+ *(.got)
+
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ it all into .data: */
+ . = ALIGN(16);
+ _bss = .;
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(16);
+ _bss_end = .;
+ }
+
+ .rela.dyn : { *(.rela.dyn) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.got : { *(.rela.got) }
+ .rela.data : { *(.rela.data) *(.rela.data*) }
+ . = ALIGN(512);
+ _edata = .;
+ _data_size = . - _data;
+
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ /DISCARD/ :
+ {
+ *(.rel.reloc)
+ *(.eh_frame)
+ *(.note.GNU-stack)
+ }
+ .comment 0 : { *(.comment) }
+}
diff --git a/libs/posix-uefi/uefi/elf_riscv64_efi.lds b/libs/posix-uefi/uefi/elf_riscv64_efi.lds
new file mode 100644
index 0000000..6f1936b
--- /dev/null
+++ b/libs/posix-uefi/uefi/elf_riscv64_efi.lds
@@ -0,0 +1,64 @@
+OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+SECTIONS
+{
+ .text 0x0 : {
+ _text = .;
+ *(.text.head)
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ *(.srodata)
+ *(.rodata*)
+ . = ALIGN(16);
+ }
+ _etext = .;
+ _text_size = . - _text;
+ .dynamic : { *(.dynamic) }
+ .data : ALIGN(4096)
+ {
+ _data = .;
+ *(.sdata)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+ *(.got.plt)
+ *(.got)
+
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ it all into .data: */
+ . = ALIGN(16);
+ _bss = .;
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(16);
+ _bss_end = .;
+ }
+
+ .rela.text : { *(.rela.text) *(.rela.text*) }
+ .rela.dyn : { *(.rela.dyn) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.got : { *(.rela.got) }
+ .rela.data : { *(.rela.data) *(.rela.data*) }
+ . = ALIGN(512);
+ _edata = .;
+ _data_size = . - _data;
+
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ /DISCARD/ :
+ {
+ *(.rel.reloc)
+ *(.eh_frame)
+ *(.note.GNU-stack)
+ }
+ .comment 0 : { *(.comment) }
+}
diff --git a/libs/posix-uefi/uefi/elf_x86_64_efi.lds b/libs/posix-uefi/uefi/elf_x86_64_efi.lds
new file mode 100644
index 0000000..7be5902
--- /dev/null
+++ b/libs/posix-uefi/uefi/elf_x86_64_efi.lds
@@ -0,0 +1,76 @@
+/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0;
+ ImageBase = .;
+ /* .hash and/or .gnu.hash MUST come first! */
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ . = ALIGN(4096);
+ .eh_frame :
+ {
+ *(.eh_frame)
+ }
+ . = ALIGN(4096);
+ .text :
+ {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(16);
+ }
+ _etext = .;
+ _text_size = . - _text;
+ . = ALIGN(4096);
+ .reloc :
+ {
+ *(.reloc)
+ }
+ . = ALIGN(4096);
+ .data :
+ {
+ _data = .;
+ *(.rodata*)
+ *(.got.plt)
+ *(.got)
+ *(.data*)
+ *(.sdata)
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ it all into .data: */
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ *(.rel.local)
+ }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+
+ _edata = .;
+ _data_size = . - _etext;
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .rela :
+ {
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.stab)
+ }
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .ignored.reloc :
+ {
+ *(.rela.reloc)
+ *(.eh_frame)
+ *(.note.GNU-stack)
+ }
+ .comment 0 : { *(.comment) }
+}
diff --git a/libs/posix-uefi/uefi/qsort.c b/libs/posix-uefi/uefi/qsort.c
new file mode 100644
index 0000000..d6563c9
--- /dev/null
+++ b/libs/posix-uefi/uefi/qsort.c
@@ -0,0 +1,154 @@
+/*
+ * qsort.c
+ *
+ * @brief from OpenBSD
+ */
+
+/* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include
+
+static __inline char *med3(char *, char *, char *, __compar_fn_t cmp);
+static __inline void swapfunc(char *, char *, int, int);
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+static __inline void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if (swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+static __inline char *
+med3(char *a, char *b, char *c, __compar_fn_t cmp)
+{
+ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
+ :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+}
+
+void qsort(void *aa, size_t n, size_t es, __compar_fn_t cmp)
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+ char *a = aa;
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp);
+ pm = med3(pm - d, pm, pm + d, cmp);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp);
+ }
+ pm = med3(pl, pm, pn, cmp);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - (int)es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > (int)es)
+ qsort(a, r / es, es, cmp);
+ if ((r = pd - pc) > (int)es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* qsort(pn - r, r / es, es, cmp);*/
+}
diff --git a/libs/posix-uefi/uefi/stat.c b/libs/posix-uefi/uefi/stat.c
new file mode 100644
index 0000000..017a4f8
--- /dev/null
+++ b/libs/posix-uefi/uefi/stat.c
@@ -0,0 +1,68 @@
+/*
+ * stat.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in sys/stat.h
+ *
+ */
+
+#include
+
+/* fstat is in stdio.c because we can't access static variables otherwise... */
+
+int stat (const char_t *__file, struct stat *__buf)
+{
+ int ret;
+ FILE *f;
+
+ if(!__file || !*__file || !__buf) {
+ errno = EINVAL;
+ return -1;
+ }
+ f = fopen(__file, CL("*"));
+ if(!f) {
+ memset(__buf, 0, sizeof(struct stat));
+ return -1;
+ }
+ ret = fstat(f, __buf);
+ fclose(f);
+ return ret;
+}
+
+extern int mkdir (const char_t *__path, mode_t __mode)
+{
+ FILE *f;
+ (void)__mode;
+ if(!__path || !*__path) {
+ errno = EINVAL;
+ return -1;
+ }
+ f = fopen(__path, CL("wd"));
+ if(!f) {
+ return -1;
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/libs/posix-uefi/uefi/stdio.c b/libs/posix-uefi/uefi/stdio.c
new file mode 100644
index 0000000..350ff7b
--- /dev/null
+++ b/libs/posix-uefi/uefi/stdio.c
@@ -0,0 +1,816 @@
+/*
+ * stdio.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in stdio.h
+ *
+ */
+
+#include
+
+static efi_file_handle_t *__root_dir = NULL;
+static efi_serial_io_protocol_t *__ser = NULL;
+static block_file_t *__blk_devs = NULL;
+static uintn_t __blk_ndevs = 0;
+extern time_t __mktime_efi(efi_time_t *t);
+void __stdio_cleanup(void);
+void __stdio_seterrno(efi_status_t status);
+int __remove (const char_t *__filename, int isdir);
+
+void __stdio_cleanup(void)
+{
+#ifndef UEFI_NO_UTF8
+ if(__argvutf8)
+ BS->FreePool(__argvutf8);
+#endif
+ if(__blk_devs) {
+ free(__blk_devs);
+ __blk_devs = NULL;
+ __blk_ndevs = 0;
+ }
+}
+
+void __stdio_seterrno(efi_status_t status)
+{
+ switch((int)(status & 0xffff)) {
+ case EFI_WRITE_PROTECTED & 0xffff: errno = EROFS; break;
+ case EFI_ACCESS_DENIED & 0xffff: errno = EACCES; break;
+ case EFI_VOLUME_FULL & 0xffff: errno = ENOSPC; break;
+ case EFI_NOT_FOUND & 0xffff: errno = ENOENT; break;
+ case EFI_INVALID_PARAMETER & 0xffff: errno = EINVAL; break;
+ default: errno = EIO; break;
+ }
+}
+
+int fstat (FILE *__f, struct stat *__buf)
+{
+ efi_guid_t infGuid = EFI_FILE_INFO_GUID;
+ efi_file_info_t info;
+ uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t);
+ efi_status_t status;
+ uintn_t i;
+
+ if(!__f || !__buf) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(__buf, 0, sizeof(struct stat));
+ if(__f == stdin) {
+ __buf->st_mode = S_IREAD | S_IFIFO;
+ return 0;
+ }
+ if(__f == stdout || __f == stderr) {
+ __buf->st_mode = S_IWRITE | S_IFIFO;
+ return 0;
+ }
+ if(__ser && __f == (FILE*)__ser) {
+ __buf->st_mode = S_IREAD | S_IWRITE | S_IFCHR;
+ return 0;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__f == (FILE*)__blk_devs[i].bio) {
+ __buf->st_mode = S_IREAD | S_IWRITE | S_IFBLK;
+ __buf->st_size = (off_t)__blk_devs[i].bio->Media->BlockSize * ((off_t)__blk_devs[i].bio->Media->LastBlock + 1);
+ __buf->st_blocks = __blk_devs[i].bio->Media->LastBlock + 1;
+ return 0;
+ }
+ status = __f->GetInfo(__f, &infGuid, &fsiz, &info);
+ if(EFI_ERROR(status)) {
+ __stdio_seterrno(status);
+ return -1;
+ }
+ __buf->st_mode = S_IREAD |
+ (info.Attribute & EFI_FILE_READ_ONLY ? 0 : S_IWRITE) |
+ (info.Attribute & EFI_FILE_DIRECTORY ? S_IFDIR : S_IFREG);
+ __buf->st_size = (off_t)info.FileSize;
+ __buf->st_blocks = (blkcnt_t)info.PhysicalSize;
+ __buf->st_atime = __mktime_efi(&info.LastAccessTime);
+ __buf->st_mtime = __mktime_efi(&info.ModificationTime);
+ __buf->st_ctime = __mktime_efi(&info.CreateTime);
+ return 0;
+}
+
+int fclose (FILE *__stream)
+{
+ efi_status_t status = EFI_SUCCESS;
+ uintn_t i;
+ if(!__stream) {
+ errno = EINVAL;
+ return 0;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr || (__ser && __stream == (FILE*)__ser)) {
+ return 1;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio)
+ return 1;
+ status = __stream->Close(__stream);
+ free(__stream);
+ return !EFI_ERROR(status);
+}
+
+int fflush (FILE *__stream)
+{
+ efi_status_t status = EFI_SUCCESS;
+ uintn_t i;
+ if(!__stream) {
+ errno = EINVAL;
+ return 0;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr || (__ser && __stream == (FILE*)__ser)) {
+ return 1;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ return 1;
+ }
+ status = __stream->Flush(__stream);
+ return !EFI_ERROR(status);
+}
+
+int __remove (const char_t *__filename, int isdir)
+{
+ efi_status_t status;
+ efi_guid_t infGuid = EFI_FILE_INFO_GUID;
+ efi_file_info_t info;
+ uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t), i;
+ /* little hack to support read and write mode for Delete() and stat() without create mode or checks */
+ FILE *f = fopen(__filename, CL("*"));
+ if(errno)
+ return 1;
+ if(!f || f == stdin || f == stdout || f == stderr || (__ser && f == (FILE*)__ser)) {
+ errno = EBADF;
+ return 1;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(f == (FILE*)__blk_devs[i].bio) {
+ errno = EBADF;
+ return 1;
+ }
+ if(isdir != -1) {
+ status = f->GetInfo(f, &infGuid, &fsiz, &info);
+ if(EFI_ERROR(status)) goto err;
+ if(isdir == 0 && (info.Attribute & EFI_FILE_DIRECTORY)) {
+ fclose(f); errno = EISDIR;
+ return -1;
+ }
+ if(isdir == 1 && !(info.Attribute & EFI_FILE_DIRECTORY)) {
+ fclose(f); errno = ENOTDIR;
+ return -1;
+ }
+ }
+ status = f->Delete(f);
+ if(EFI_ERROR(status)) {
+err: __stdio_seterrno(status);
+ fclose(f);
+ return -1;
+ }
+ /* no need for fclose(f); */
+ free(f);
+ return 0;
+}
+
+int remove (const char_t *__filename)
+{
+ return __remove(__filename, -1);
+}
+
+FILE *fopen (const char_t *__filename, const char_t *__modes)
+{
+ FILE *ret;
+ efi_status_t status;
+ efi_guid_t sfsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+ efi_simple_file_system_protocol_t *sfs = NULL;
+ efi_guid_t infGuid = EFI_FILE_INFO_GUID;
+ efi_file_info_t info;
+ uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t), par, i;
+#ifndef UEFI_NO_UTF8
+ wchar_t wcname[BUFSIZ];
+#endif
+ errno = 0;
+ if(!__filename || !*__filename || !__modes || (__modes[0] != CL('r') && __modes[0] != CL('w') && __modes[0] != CL('a') &&
+ __modes[0] != CL('*')) || (__modes[1] != 0 && __modes[1] != CL('d') && __modes[1] != CL('+'))) {
+ errno = EINVAL;
+ return NULL;
+ }
+ /* fake some device names. UEFI has no concept of device files */
+ if(!strcmp(__filename, CL("/dev/stdin"))) {
+ if(__modes[0] == CL('w') || __modes[0] == CL('a')) { errno = EPERM; return NULL; }
+ return stdin;
+ }
+ if(!strcmp(__filename, CL("/dev/stdout"))) {
+ if(__modes[0] == CL('r')) { errno = EPERM; return NULL; }
+ return stdout;
+ }
+ if(!strcmp(__filename, CL("/dev/stderr"))) {
+ if(__modes[0] == CL('r')) { errno = EPERM; return NULL; }
+ return stderr;
+ }
+ if(!memcmp(__filename, CL("/dev/serial"), 11 * sizeof(char_t))) {
+ par = (uintn_t)atol(__filename + 11);
+ if(!__ser) {
+ efi_guid_t serGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
+ status = BS->LocateProtocol(&serGuid, NULL, (void**)&__ser);
+ if(EFI_ERROR(status) || !__ser) { errno = ENOENT; return NULL; }
+ }
+ __ser->SetAttributes(__ser, par > 9600 ? par : 115200, 0, 1000, NoParity, 8, OneStopBit);
+ return (FILE*)__ser;
+ }
+ if(!memcmp(__filename, CL("/dev/disk"), 9 * sizeof(char_t))) {
+ par = (uintn_t)atol(__filename + 9);
+ if(!__blk_ndevs) {
+ efi_guid_t bioGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+ efi_handle_t handles[128];
+ uintn_t handle_size = sizeof(handles);
+ status = BS->LocateHandle(ByProtocol, &bioGuid, NULL, &handle_size, (efi_handle_t*)&handles);
+ if(!EFI_ERROR(status)) {
+ handle_size /= (uintn_t)sizeof(efi_handle_t);
+ /* workaround a bug in TianoCore, it reports zero size even though the data is in the buffer */
+ if(handle_size < 1)
+ handle_size = (uintn_t)sizeof(handles) / sizeof(efi_handle_t);
+ __blk_devs = (block_file_t*)malloc(handle_size * sizeof(block_file_t));
+ if(__blk_devs) {
+ memset(__blk_devs, 0, handle_size * sizeof(block_file_t));
+ for(i = __blk_ndevs = 0; i < handle_size; i++)
+ if(handles[i] && !EFI_ERROR(BS->HandleProtocol(handles[i], &bioGuid, (void **) &__blk_devs[__blk_ndevs].bio)) &&
+ __blk_devs[__blk_ndevs].bio && __blk_devs[__blk_ndevs].bio->Media &&
+ __blk_devs[__blk_ndevs].bio->Media->BlockSize > 0)
+ __blk_ndevs++;
+ } else
+ __blk_ndevs = 0;
+ }
+ }
+ if(__blk_ndevs && par < __blk_ndevs)
+ return (FILE*)__blk_devs[par].bio;
+ errno = ENOENT;
+ return NULL;
+ }
+ if(!__root_dir && LIP) {
+ status = BS->HandleProtocol(LIP->DeviceHandle, &sfsGuid, (void **)&sfs);
+ if(!EFI_ERROR(status))
+ status = sfs->OpenVolume(sfs, &__root_dir);
+ }
+ if(!__root_dir) {
+ errno = ENODEV;
+ return NULL;
+ }
+ ret = (FILE*)malloc(sizeof(FILE));
+ if(!ret) return NULL;
+ /* normally write means read,write,create. But for remove (internal '*' mode), we need read,write without create
+ * also mode 'w' in POSIX means write-only (without read), but that's not working on certain firmware, we must
+ * pass read too. This poses a problem of truncating a write-only file, see issue #26, we have to do that manually */
+#ifndef UEFI_NO_UTF8
+ mbstowcs((wchar_t*)&wcname, __filename, BUFSIZ - 1);
+ status = __root_dir->Open(__root_dir, &ret, (wchar_t*)&wcname,
+#else
+ status = __root_dir->Open(__root_dir, &ret, (wchar_t*)__filename,
+#endif
+ __modes[0] == CL('w') || __modes[0] == CL('a') ? (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE) :
+ EFI_FILE_MODE_READ | (__modes[0] == CL('*') || __modes[1] == CL('+') ? EFI_FILE_MODE_WRITE : 0),
+ __modes[1] == CL('d') ? EFI_FILE_DIRECTORY : 0);
+ if(EFI_ERROR(status)) {
+err: __stdio_seterrno(status);
+ free(ret); return NULL;
+ }
+ if(__modes[0] == CL('*')) return ret;
+ status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
+ if(EFI_ERROR(status)) goto err;
+ if(__modes[1] == CL('d') && !(info.Attribute & EFI_FILE_DIRECTORY)) {
+ ret->Close(ret); free(ret); errno = ENOTDIR; return NULL;
+ }
+ if(__modes[1] != CL('d') && (info.Attribute & EFI_FILE_DIRECTORY)) {
+ ret->Close(ret); free(ret); errno = EISDIR; return NULL;
+ }
+ if(__modes[0] == CL('a')) fseek(ret, 0, SEEK_END);
+ if(__modes[0] == CL('w')) {
+ /* manually truncate file size
+ * See https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c
+ * function FileHandleSetSize */
+ info.FileSize = 0;
+ ret->SetInfo(ret, &infGuid, fsiz, &info);
+ }
+ return ret;
+}
+
+size_t fread (void *__ptr, size_t __size, size_t __n, FILE *__stream)
+{
+ uintn_t bs = __size * __n, i, n;
+ efi_status_t status;
+ if(!__ptr || __size < 1 || __n < 1 || !__stream) {
+ errno = EINVAL;
+ return 0;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr) {
+ errno = ESPIPE;
+ return 0;
+ }
+ if(__ser && __stream == (FILE*)__ser) {
+ status = __ser->Read(__ser, &bs, __ptr);
+ } else {
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ n = __blk_devs[i].offset / __blk_devs[i].bio->Media->BlockSize;
+ bs = (bs / __blk_devs[i].bio->Media->BlockSize) * __blk_devs[i].bio->Media->BlockSize;
+ status = __blk_devs[i].bio->ReadBlocks(__blk_devs[i].bio, __blk_devs[i].bio->Media->MediaId, n, bs, __ptr);
+ if(EFI_ERROR(status)) {
+ __stdio_seterrno(status);
+ return 0;
+ }
+ __blk_devs[i].offset += bs;
+ return bs / __size;
+ }
+ status = __stream->Read(__stream, &bs, __ptr);
+ }
+ if(EFI_ERROR(status)) {
+ __stdio_seterrno(status);
+ return 0;
+ }
+ return bs / __size;
+}
+
+size_t fwrite (const void *__ptr, size_t __size, size_t __n, FILE *__stream)
+{
+ uintn_t bs = __size * __n, n, i;
+ efi_status_t status;
+ if(!__ptr || __size < 1 || __n < 1 || !__stream) {
+ errno = EINVAL;
+ return 0;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr) {
+ errno = ESPIPE;
+ return 0;
+ }
+ if(__ser && __stream == (FILE*)__ser) {
+ status = __ser->Write(__ser, &bs, (void*)__ptr);
+ } else {
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ n = __blk_devs[i].offset / __blk_devs[i].bio->Media->BlockSize;
+ bs = (bs / __blk_devs[i].bio->Media->BlockSize) * __blk_devs[i].bio->Media->BlockSize;
+ status = __blk_devs[i].bio->WriteBlocks(__blk_devs[i].bio, __blk_devs[i].bio->Media->MediaId, n, bs, (void*)__ptr);
+ if(EFI_ERROR(status)) {
+ __stdio_seterrno(status);
+ return 0;
+ }
+ __blk_devs[i].offset += bs;
+ return bs / __size;
+ }
+ status = __stream->Write(__stream, &bs, (void *)__ptr);
+ }
+ if(EFI_ERROR(status)) {
+ __stdio_seterrno(status);
+ return 0;
+ }
+ return bs / __size;
+}
+
+int fseek (FILE *__stream, long int __off, int __whence)
+{
+ off_t off = 0;
+ efi_status_t status;
+ efi_guid_t infoGuid = EFI_FILE_INFO_GUID;
+ efi_file_info_t info;
+ uintn_t fsiz = sizeof(efi_file_info_t), i;
+ if(!__stream || (__whence != SEEK_SET && __whence != SEEK_CUR && __whence != SEEK_END)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr) {
+ errno = ESPIPE;
+ return -1;
+ }
+ if(__ser && __stream == (FILE*)__ser) {
+ errno = EBADF;
+ return -1;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ off = (uint64_t)__blk_devs[i].bio->Media->BlockSize * (uint64_t)__blk_devs[i].bio->Media->LastBlock;
+ switch(__whence) {
+ case SEEK_END:
+ __blk_devs[i].offset = off + __off;
+ break;
+ case SEEK_CUR:
+ __blk_devs[i].offset += __off;
+ break;
+ case SEEK_SET:
+ __blk_devs[i].offset = __off;
+ break;
+ }
+ if(__blk_devs[i].offset < 0) __blk_devs[i].offset = 0;
+ if(__blk_devs[i].offset > off) __blk_devs[i].offset = off;
+ __blk_devs[i].offset = (__blk_devs[i].offset / __blk_devs[i].bio->Media->BlockSize) *
+ __blk_devs[i].bio->Media->BlockSize;
+ return 0;
+ }
+ switch(__whence) {
+ case SEEK_END:
+ status = __stream->GetInfo(__stream, &infoGuid, &fsiz, &info);
+ if(!EFI_ERROR(status)) {
+ off = info.FileSize + __off;
+ status = __stream->SetPosition(__stream, off);
+ }
+ break;
+ case SEEK_CUR:
+ status = __stream->GetPosition(__stream, &off);
+ if(!EFI_ERROR(status)) {
+ off += __off;
+ status = __stream->SetPosition(__stream, off);
+ }
+ break;
+ default:
+ status = __stream->SetPosition(__stream, __off);
+ break;
+ }
+ return EFI_ERROR(status) ? -1 : 0;
+}
+
+long int ftell (FILE *__stream)
+{
+ uint64_t off = 0;
+ uintn_t i;
+ efi_status_t status;
+ if(!__stream) {
+ errno = EINVAL;
+ return -1;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr) {
+ errno = ESPIPE;
+ return -1;
+ }
+ if(__ser && __stream == (FILE*)__ser) {
+ errno = EBADF;
+ return -1;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ return (long int)__blk_devs[i].offset;
+ }
+ status = __stream->GetPosition(__stream, &off);
+ return EFI_ERROR(status) ? -1 : (long int)off;
+}
+
+int feof (FILE *__stream)
+{
+ uint64_t off = 0;
+ efi_guid_t infGuid = EFI_FILE_INFO_GUID;
+ efi_file_info_t info;
+ uintn_t fsiz = (uintn_t)sizeof(efi_file_info_t), i;
+ efi_status_t status;
+ if(!__stream) {
+ errno = EINVAL;
+ return 0;
+ }
+ if(__stream == stdin || __stream == stdout || __stream == stderr) {
+ errno = ESPIPE;
+ return 0;
+ }
+ if(__ser && __stream == (FILE*)__ser) {
+ errno = EBADF;
+ return 0;
+ }
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ errno = EBADF;
+ return __blk_devs[i].offset == (off_t)__blk_devs[i].bio->Media->BlockSize * (off_t)__blk_devs[i].bio->Media->LastBlock;
+ }
+ status = __stream->GetPosition(__stream, &off);
+ if(EFI_ERROR(status)) {
+err: __stdio_seterrno(status);
+ return 1;
+ }
+ status = __stream->GetInfo(__stream, &infGuid, &fsiz, &info);
+ if(EFI_ERROR(status)) goto err;
+ __stream->SetPosition(__stream, off);
+ return info.FileSize == off;
+}
+
+int vsnprintf(char_t *dst, size_t maxlen, const char_t *fmt, __builtin_va_list args)
+{
+#define needsescape(a) (a==CL('\"') || a==CL('\\') || a==CL('\a') || a==CL('\b') || a==CL('\033') || a==CL('\f') || \
+ a==CL('\r') || a==CL('\n') || a==CL('\t') || a==CL('\v'))
+ efi_physical_address_t m;
+ uint8_t *mem;
+ int64_t arg;
+ int len, sign, i, j;
+ char_t *p, *orig=dst, *end = dst + maxlen - 1, tmpstr[24], pad, n;
+#ifdef UEFI_NO_UTF8
+ char *c;
+#endif
+ if(dst==NULL || fmt==NULL)
+ return 0;
+
+ arg = 0;
+ while(*fmt && dst < end) {
+ if(*fmt==CL('%')) {
+ fmt++;
+ if(*fmt==CL('%')) goto put;
+ len=0; pad=CL(' ');
+ if(*fmt==CL('0')) pad=CL('0');
+ while(*fmt>=CL('0') && *fmt<=CL('9')) {
+ len *= 10;
+ len += *fmt-CL('0');
+ fmt++;
+ }
+ if(*fmt==CL('l')) fmt++;
+ if(*fmt==CL('c')) {
+ arg = __builtin_va_arg(args, uint32_t);
+#ifndef UEFI_NO_UTF8
+ if(arg<0x80) { *dst++ = arg; } else
+ if(arg<0x800) { *dst++ = ((arg>>6)&0x1F)|0xC0; *dst++ = (arg&0x3F)|0x80; } else
+ { *dst++ = ((arg>>12)&0x0F)|0xE0; *dst++ = ((arg>>6)&0x3F)|0x80; *dst++ = (arg&0x3F)|0x80; }
+#else
+ *dst++ = (wchar_t)(arg & 0xffff);
+#endif
+ fmt++;
+ continue;
+ } else
+ if(*fmt==CL('d') || *fmt==CL('i')) {
+ arg = __builtin_va_arg(args, int64_t);
+ sign=0;
+ if(arg<0) {
+ arg*=-1;
+ sign++;
+ }
+ i=23;
+ tmpstr[i]=0;
+ do {
+ tmpstr[--i]=CL('0')+(arg%10);
+ arg/=10;
+ } while(arg!=0 && i>0);
+ if(sign) {
+ tmpstr[--i]=CL('-');
+ }
+ if(len>0 && len<23) {
+ while(i && i>23-len) {
+ tmpstr[--i]=pad;
+ }
+ }
+ p=&tmpstr[i];
+ goto copystring;
+ } else
+ if(*fmt==CL('p')) {
+ arg = __builtin_va_arg(args, uint64_t);
+ len = 16; pad = CL('0'); goto hex;
+ } else
+ if(*fmt==CL('x') || *fmt==CL('X')) {
+ arg = __builtin_va_arg(args, int64_t);
+hex: i=16;
+ tmpstr[i]=0;
+ do {
+ n=arg & 0xf;
+ /* 0-9 => '0'-'9', 10-15 => 'A'-'F' */
+ tmpstr[--i]=n+(n>9?(*fmt==CL('X')?0x37:0x57):0x30);
+ arg>>=4;
+ } while(arg!=0 && i>0);
+ /* padding, only leading zeros */
+ if(len>0 && len<=16) {
+ while(i>16-len) {
+ tmpstr[--i]=CL('0');
+ }
+ }
+ p=&tmpstr[i];
+ goto copystring;
+ } else
+ if(*fmt==CL('s') || *fmt==CL('q')) {
+ p = __builtin_va_arg(args, char_t*);
+copystring: if(p==NULL) {
+ p=CL("(null)");
+ }
+ while(*p && dst + 2 < end) {
+ if(*fmt==CL('q') && needsescape(*p)) {
+ *dst++ = CL('\\');
+ switch(*p) {
+ case CL('\a'): *dst++ = CL('a'); break;
+ case CL('\b'): *dst++ = CL('b'); break;
+ case 27: *dst++ = CL('e'); break; /* gcc 10.2 doesn't like CL('\e') in ansi mode */
+ case CL('\f'): *dst++ = CL('f'); break;
+ case CL('\n'): *dst++ = CL('n'); break;
+ case CL('\r'): *dst++ = CL('r'); break;
+ case CL('\t'): *dst++ = CL('t'); break;
+ case CL('\v'): *dst++ = CL('v'); break;
+ default: *dst++ = *p++; break;
+ }
+ } else {
+ if(*p == CL('\n') && (orig == dst || *(dst - 1) != CL('\r'))) *dst++ = CL('\r');
+ *dst++ = *p++;
+ }
+ }
+ } else
+#ifdef UEFI_NO_UTF8
+ if(*fmt==L'S' || *fmt==L'Q') {
+ c = __builtin_va_arg(args, char*);
+ if(c==NULL) goto copystring;
+ while(*p && dst + 2 < end) {
+ arg = *c;
+ if((*c & 128) != 0) {
+ if((*c & 32) == 0 ) {
+ arg = ((*c & 0x1F)<<6)|(*(c+1) & 0x3F);
+ c += 1;
+ } else
+ if((*c & 16) == 0 ) {
+ arg = ((*c & 0xF)<<12)|((*(c+1) & 0x3F)<<6)|(*(c+2) & 0x3F);
+ c += 2;
+ } else
+ if((*c & 8) == 0 ) {
+ arg = ((*c & 0x7)<<18)|((*(c+1) & 0x3F)<<12)|((*(c+2) & 0x3F)<<6)|(*(c+3) & 0x3F);
+ c += 3;
+ } else
+ arg = L'?';
+ }
+ if(!arg) break;
+ if(*fmt==L'Q' && needsescape(arg)) {
+ *dst++ = L'\\';
+ switch(arg) {
+ case L'\a': *dst++ = L'a'; break;
+ case L'\b': *dst++ = L'b'; break;
+ case 27: *dst++ = L'e'; break; /* gcc 10.2 doesn't like L'\e' in ansi mode */
+ case L'\f': *dst++ = L'f'; break;
+ case L'\n': *dst++ = L'n'; break;
+ case L'\r': *dst++ = L'r'; break;
+ case L'\t': *dst++ = L't'; break;
+ case L'\v': *dst++ = L'v'; break;
+ default: *dst++ = arg; break;
+ }
+ } else {
+ if(arg == L'\n') *dst++ = L'\r';
+ *dst++ = (wchar_t)(arg & 0xffff);
+ }
+ }
+ } else
+#endif
+ if(*fmt==CL('D')) {
+ m = __builtin_va_arg(args, efi_physical_address_t);
+ for(j = 0; j < (len < 1 ? 1 : (len > 16 ? 16 : len)); j++) {
+ for(i = 44; i >= 0; i -= 4) {
+ n = (m >> i) & 15; *dst++ = n + (n>9?0x37:0x30);
+ if(dst >= end) goto zro;
+ }
+ *dst++ = CL(':'); if(dst >= end) goto zro;
+ *dst++ = CL(' '); if(dst >= end) goto zro;
+ mem = (uint8_t*)m;
+ for(i = 0; i < 16; i++) {
+ n = (mem[i] >> 4) & 15; *dst++ = n + (n>9?0x37:0x30); if(dst >= end) goto zro;
+ n = mem[i] & 15; *dst++ = n + (n>9?0x37:0x30); if(dst >= end) goto zro;
+ *dst++ = CL(' ');if(dst >= end) goto zro;
+ }
+ *dst++ = CL(' '); if(dst >= end) goto zro;
+ for(i = 0; i < 16; i++) {
+ *dst++ = (mem[i] < 32 || mem[i] >= 127 ? CL('.') : (char_t)mem[i]);
+ if(dst >= end) goto zro;
+ }
+ *dst++ = CL('\r'); if(dst >= end) goto zro;
+ *dst++ = CL('\n'); if(dst >= end) goto zro;
+ m += 16;
+ }
+ }
+ } else {
+put: if(*fmt == CL('\n') && (orig == dst || *(dst - 1) != CL('\r'))) *dst++ = CL('\r');
+ *dst++ = *fmt;
+ }
+ fmt++;
+ }
+zro:*dst=0;
+ return (int)(dst-orig);
+#undef needsescape
+}
+
+int vsprintf(char_t *dst, const char_t *fmt, __builtin_va_list args)
+{
+ return vsnprintf(dst, BUFSIZ, fmt, args);
+}
+
+int sprintf(char_t *dst, const char_t* fmt, ...)
+{
+ int ret;
+ __builtin_va_list args;
+ __builtin_va_start(args, fmt);
+ ret = vsnprintf(dst, BUFSIZ, fmt, args);
+ __builtin_va_end(args);
+ return ret;
+}
+
+int snprintf(char_t *dst, size_t maxlen, const char_t* fmt, ...)
+{
+ int ret;
+ __builtin_va_list args;
+ __builtin_va_start(args, fmt);
+ ret = vsnprintf(dst, maxlen, fmt, args);
+ __builtin_va_end(args);
+ return ret;
+}
+
+int vprintf(const char_t* fmt, __builtin_va_list args)
+{
+ int ret;
+ wchar_t dst[BUFSIZ];
+#ifndef UEFI_NO_UTF8
+ char_t tmp[BUFSIZ];
+ ret = vsnprintf(tmp, BUFSIZ, fmt, args);
+ mbstowcs(dst, tmp, BUFSIZ - 1);
+#else
+ ret = vsnprintf(dst, BUFSIZ, fmt, args);
+#endif
+ ST->ConOut->OutputString(ST->ConOut, (wchar_t *)&dst);
+ return ret;
+}
+
+int printf(const char_t* fmt, ...)
+{
+ int ret;
+ __builtin_va_list args;
+ __builtin_va_start(args, fmt);
+ ret = vprintf(fmt, args);
+ __builtin_va_end(args);
+ return ret;
+}
+
+int vfprintf (FILE *__stream, const char_t *__format, __builtin_va_list args)
+{
+ wchar_t dst[BUFSIZ];
+ char_t tmp[BUFSIZ];
+ uintn_t ret, i;
+#ifndef UEFI_NO_UTF8
+ ret = (uintn_t)vsnprintf(tmp, BUFSIZ, __format, args);
+ ret = mbstowcs(dst, tmp, BUFSIZ - 1);
+#else
+ ret = vsnprintf(dst, BUFSIZ, __format, args);
+#endif
+ if(ret < 1 || !__stream || __stream == stdin) return 0;
+ for(i = 0; i < __blk_ndevs; i++)
+ if(__stream == (FILE*)__blk_devs[i].bio) {
+ errno = EBADF;
+ return -1;
+ }
+ if(__stream == stdout)
+ ST->ConOut->OutputString(ST->ConOut, (wchar_t*)&dst);
+ else if(__stream == stderr)
+ ST->StdErr->OutputString(ST->StdErr, (wchar_t*)&dst);
+ else if(__ser && __stream == (FILE*)__ser) {
+#ifdef UEFI_NO_UTF8
+ wcstombs((char*)&tmp, dst, BUFSIZ - 1);
+#endif
+ __ser->Write(__ser, &ret, (void*)&tmp);
+ } else
+#ifndef UEFI_NO_UTF8
+ __stream->Write(__stream, &ret, (void*)&tmp);
+#else
+ __stream->Write(__stream, &ret, (void*)&dst);
+#endif
+ return (int)ret;
+}
+
+int fprintf (FILE *__stream, const char_t *__format, ...)
+{
+ int ret;
+ __builtin_va_list args;
+ __builtin_va_start(args, __format);
+ ret = vfprintf(__stream, __format, args);
+ __builtin_va_end(args);
+ return ret;
+}
+
+int getchar_ifany (void)
+{
+ efi_input_key_t key = { 0 };
+ efi_status_t status = ST->ConIn->ReadKeyStroke(ST->ConIn, &key);
+ return EFI_ERROR(status) ? 0 : key.UnicodeChar;
+}
+
+int getchar (void)
+{
+ uintn_t idx;
+ BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &idx);
+ return getchar_ifany();
+}
+
+int putchar (int __c)
+{
+ wchar_t tmp[2];
+ tmp[0] = (wchar_t)__c;
+ tmp[1] = 0;
+ ST->ConOut->OutputString(ST->ConOut, (__c == L'\n' ? (wchar_t*)L"\r\n" : (wchar_t*)&tmp));
+ return (int)tmp[0];
+}
diff --git a/libs/posix-uefi/uefi/stdlib.c b/libs/posix-uefi/uefi/stdlib.c
new file mode 100644
index 0000000..81b33df
--- /dev/null
+++ b/libs/posix-uefi/uefi/stdlib.c
@@ -0,0 +1,365 @@
+/*
+ * stdlib.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in stdlib.h
+ *
+ */
+
+#include
+
+int errno = 0;
+static uint64_t __srand_seed = 6364136223846793005ULL;
+extern void __stdio_cleanup(void);
+#ifndef UEFI_NO_TRACK_ALLOC
+static uintptr_t *__stdlib_allocs = NULL;
+static uintn_t __stdlib_numallocs = 0;
+#endif
+
+int atoi(const char_t *s)
+{
+ return (int)atol(s);
+}
+
+int64_t atol(const char_t *s)
+{
+ int64_t sign = 1;
+ if(!s || !*s) return 0;
+ if(*s == CL('-')) { sign = -1; s++; }
+ if(s[0] == CL('0')) {
+ if(s[1] == CL('x'))
+ return strtol(s + 2, NULL, 16) * sign;
+ if(s[1] >= CL('0') && s[1] <= CL('7'))
+ return strtol(s, NULL, 8) * sign;
+ }
+ return strtol(s, NULL, 10) * sign;
+}
+
+int64_t strtol (const char_t *s, char_t **__endptr, int __base)
+{
+ int64_t v=0, sign = 1;
+ if(!s || !*s) return 0;
+ if(*s == CL('-')) { sign = -1; s++; }
+ while(!(*s < CL('0') || (__base < 10 && *s >= __base + CL('0')) || (__base >= 10 && ((*s > CL('9') && *s < CL('A')) ||
+ (*s > CL('F') && *s < CL('a')) || *s > CL('f'))))) {
+ v *= __base;
+ if(*s >= CL('0') && *s <= (__base < 10 ? __base + CL('0') : CL('9')))
+ v += (*s)-CL('0');
+ else if(__base == 16 && *s >= CL('a') && *s <= CL('f'))
+ v += (*s)-CL('a')+10;
+ else if(__base == 16 && *s >= CL('A') && *s <= CL('F'))
+ v += (*s)-CL('A')+10;
+ s++;
+ }
+ if(__endptr) *__endptr = (char_t*)s;
+ return v * sign;
+}
+
+void *malloc (size_t __size)
+{
+ void *ret = NULL;
+ efi_status_t status;
+#ifndef UEFI_NO_TRACK_ALLOC
+ uintn_t i;
+ for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] != 0; i += 2);
+ if(i == __stdlib_numallocs) {
+ /* no free slots found, (re)allocate the housekeeping array */
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, (__stdlib_numallocs + 2) * sizeof(uintptr_t), &ret);
+ if(EFI_ERROR(status) || !ret) { errno = ENOMEM; return NULL; }
+ if(__stdlib_allocs) memcpy(ret, __stdlib_allocs, __stdlib_numallocs * sizeof(uintptr_t));
+ __stdlib_allocs = (uintptr_t*)ret;
+ __stdlib_allocs[i] = __stdlib_allocs[i + 1] = 0;
+ __stdlib_numallocs += 2;
+ ret = NULL;
+ }
+#endif
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, __size, &ret);
+ if(EFI_ERROR(status) || !ret) { errno = ENOMEM; ret = NULL; }
+#ifndef UEFI_NO_TRACK_ALLOC
+ __stdlib_allocs[i] = (uintptr_t)ret;
+ __stdlib_allocs[i + 1] = (uintptr_t)__size;
+#endif
+ return ret;
+}
+
+void *calloc (size_t __nmemb, size_t __size)
+{
+ void *ret = malloc(__nmemb * __size);
+ if(ret) memset(ret, 0, __nmemb * __size);
+ return ret;
+}
+
+void *realloc (void *__ptr, size_t __size)
+{
+ void *ret = NULL;
+ efi_status_t status;
+#ifndef UEFI_NO_TRACK_ALLOC
+ uintn_t i;
+#endif
+ if(!__ptr) return malloc(__size);
+ if(!__size) { free(__ptr); return NULL; }
+#ifndef UEFI_NO_TRACK_ALLOC
+ /* get the slot which stores the old size for this buffer */
+ for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] != (uintptr_t)__ptr; i += 2);
+ if(i == __stdlib_numallocs) { errno = ENOMEM; return NULL; }
+ /* allocate a new buffer and copy data from old buffer */
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, __size, &ret);
+ if(EFI_ERROR(status) || !ret) { errno = ENOMEM; ret = NULL; }
+ else {
+ memcpy(ret, (void*)__stdlib_allocs[i], __stdlib_allocs[i + 1] < __size ? __stdlib_allocs[i + 1] : __size);
+ if(__size > __stdlib_allocs[i + 1]) memset((uint8_t*)ret + __stdlib_allocs[i + 1], 0, __size - __stdlib_allocs[i + 1]);
+ /* free old buffer and store new buffer in slot */
+ BS->FreePool((void*)__stdlib_allocs[i]);
+ __stdlib_allocs[i] = (uintptr_t)ret;
+ __stdlib_allocs[i + 1] = (uintptr_t)__size;
+ }
+#else
+ status = BS->AllocatePool(LIP ? LIP->ImageDataType : EfiLoaderData, __size, &ret);
+ if(EFI_ERROR(status) || !ret) { errno = ENOMEM; return NULL; }
+ /* this means out of bounds read, but fine with POSIX as the end of new buffer supposed to be left uninitialized) */
+ memcpy(ret, (void*)__ptr, __size);
+ BS->FreePool((void*)__ptr);
+#endif
+ return ret;
+}
+
+void free (void *__ptr)
+{
+ efi_status_t status;
+#ifndef UEFI_NO_TRACK_ALLOC
+ uintn_t i;
+#endif
+ if(!__ptr) { errno = ENOMEM; return; }
+#ifndef UEFI_NO_TRACK_ALLOC
+ /* find and clear the slot */
+ for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] != (uintptr_t)__ptr; i += 2);
+ if(i == __stdlib_numallocs) { errno = ENOMEM; return; }
+ __stdlib_allocs[i] = 0;
+ __stdlib_allocs[i + 1] = 0;
+ /* if there are only empty slots, free the housekeeping array too */
+ for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] == 0; i += 2);
+ if(i == __stdlib_numallocs) { BS->FreePool(__stdlib_allocs); __stdlib_allocs = NULL; __stdlib_numallocs = 0; }
+#endif
+ status = BS->FreePool(__ptr);
+ if(EFI_ERROR(status)) errno = ENOMEM;
+}
+
+void abort ()
+{
+#ifndef UEFI_NO_TRACK_ALLOC
+ if(__stdlib_allocs)
+ BS->FreePool(__stdlib_allocs);
+ __stdlib_allocs = NULL;
+ __stdlib_numallocs = 0;
+#endif
+ __stdio_cleanup();
+ BS->Exit(IM, EFI_ABORTED, 0, NULL);
+}
+
+void exit (int __status)
+{
+#ifndef UEFI_NO_TRACK_ALLOC
+ if(__stdlib_allocs)
+ BS->FreePool(__stdlib_allocs);
+ __stdlib_allocs = NULL;
+ __stdlib_numallocs = 0;
+#endif
+ __stdio_cleanup();
+ BS->Exit(IM, !__status ? 0 : (__status < 0 ? EFIERR(-__status) : EFIERR(__status)), 0, NULL);
+}
+
+int exit_bs()
+{
+ efi_status_t status = 0;
+ efi_memory_descriptor_t *memory_map = NULL;
+ uintn_t cnt = 3, memory_map_size=0, map_key=0, desc_size=0;
+#ifndef UEFI_NO_TRACK_ALLOC
+ if(__stdlib_allocs)
+ BS->FreePool(__stdlib_allocs);
+ __stdlib_allocs = NULL;
+ __stdlib_numallocs = 0;
+#endif
+ __stdio_cleanup();
+ while(cnt--) {
+ status = BS->GetMemoryMap(&memory_map_size, memory_map, &map_key, &desc_size, NULL);
+ if (status!=EFI_BUFFER_TOO_SMALL) break;
+ status = BS->ExitBootServices(IM, map_key);
+ if(!EFI_ERROR(status)) return 0;
+ }
+ return (int)(status & 0xffff);
+}
+
+void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, __compar_fn_t cmp)
+{
+ uint64_t s=0, e=nmemb, m;
+ int ret;
+ while (s < e) {
+ m = s + (e-s)/2;
+ ret = cmp(key, (uint8_t*)base + m*size);
+ if (ret < 0) e = m; else
+ if (ret > 0) s = m+1; else
+ return (void *)((uint8_t*)base + m*size);
+ }
+ return NULL;
+}
+
+int mblen(const char *s, size_t n)
+{
+ const char *e = s+n;
+ int c = 0;
+ if(s) {
+ while(s < e && *s) {
+ if((*s & 128) != 0) {
+ if((*s & 32) == 0 ) s++; else
+ if((*s & 16) == 0 ) s+=2; else
+ if((*s & 8) == 0 ) s+=3;
+ }
+ c++;
+ s++;
+ }
+ }
+ return c;
+}
+
+int mbtowc (wchar_t * __pwc, const char *s, size_t n)
+{
+ wchar_t arg;
+ int ret = 1;
+ if(!s || !*s) return 0;
+ arg = (wchar_t)*s;
+ if((*s & 128) != 0) {
+ if((*s & 32) == 0 && n > 0) { arg = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); ret = 2; } else
+ if((*s & 16) == 0 && n > 1) { arg = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); ret = 3; } else
+ if((*s & 8) == 0 && n > 2) { arg = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); ret = 4; }
+ else return -1;
+ }
+ if(__pwc) *__pwc = arg;
+ return ret;
+}
+
+int wctomb (char *s, wchar_t u)
+{
+ int ret = 0;
+ if(u<0x80) {
+ *s = u;
+ ret = 1;
+ } else if(u<0x800) {
+ *(s+0)=((u>>6)&0x1F)|0xC0;
+ *(s+1)=(u&0x3F)|0x80;
+ ret = 2;
+ } else {
+ *(s+0)=((u>>12)&0x0F)|0xE0;
+ *(s+1)=((u>>6)&0x3F)|0x80;
+ *(s+2)=(u&0x3F)|0x80;
+ ret = 3;
+ }
+ return ret;
+}
+
+size_t mbstowcs (wchar_t *__pwcs, const char *__s, size_t __n)
+{
+ int r;
+ wchar_t *orig = __pwcs;
+ if(!__s || !*__s) return 0;
+ while(*__s) {
+ r = mbtowc(__pwcs, __s, __n - (size_t)(__pwcs - orig));
+ if(r < 0) return (size_t)-1;
+ __pwcs++;
+ __s += r;
+ }
+ *__pwcs = 0;
+ return (size_t)(__pwcs - orig);
+}
+
+size_t wcstombs (char *__s, const wchar_t *__pwcs, size_t __n)
+{
+ int r;
+ char *orig = __s;
+ if(!__s || !__pwcs || !*__pwcs) return 0;
+ while(*__pwcs && ((size_t)(__s - orig + 4) < __n)) {
+ r = wctomb(__s, *__pwcs);
+ if(r < 0) return (size_t)-1;
+ __pwcs++;
+ __s += r;
+ }
+ *__s = 0;
+ return (size_t)(__s - orig);
+}
+
+void srand(unsigned int __seed)
+{
+ __srand_seed = __seed - 1;
+}
+
+int rand()
+{
+ efi_guid_t rngGuid = EFI_RNG_PROTOCOL_GUID;
+ efi_rng_protocol_t *rng = NULL;
+ efi_status_t status;
+ int ret = 0;
+
+ __srand_seed = 6364136223846793005ULL*__srand_seed + 1;
+ status = BS->LocateProtocol(&rngGuid, NULL, (void**)&rng);
+ if(!EFI_ERROR(status) && rng)
+ rng->GetRNG(rng, NULL, (uintn_t)sizeof(int), (uint8_t*)&ret);
+ ret ^= (int)(__srand_seed>>33);
+ return ret;
+}
+
+uint8_t *getenv(char_t *name, uintn_t *len)
+{
+ efi_guid_t globGuid = EFI_GLOBAL_VARIABLE;
+ uint8_t tmp[EFI_MAXIMUM_VARIABLE_SIZE], *ret;
+ uint32_t attr;
+ efi_status_t status;
+#ifndef UEFI_NO_UTF8
+ wchar_t wcname[256];
+ mbstowcs((wchar_t*)&wcname, name, 256);
+ status = RT->GetVariable((wchar_t*)&wcname, &globGuid, &attr, len, &tmp);
+#else
+ status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
+#endif
+ if(EFI_ERROR(status) || *len < 1 || !(ret = malloc((*len) + 1))) {
+ *len = 0;
+ return NULL;
+ }
+ memcpy(ret, tmp, *len);
+ ret[*len] = 0;
+ return ret;
+}
+
+int setenv(char_t *name, uintn_t len, uint8_t *data)
+{
+ efi_guid_t globGuid = EFI_GLOBAL_VARIABLE;
+ efi_status_t status;
+#ifndef UEFI_NO_UTF8
+ wchar_t wcname[256];
+ mbstowcs((wchar_t*)&wcname, name, 256);
+ status = RT->SetVariable(wcname, &globGuid, 0, len, data);
+#else
+ status = RT->SetVariable(name, &globGuid, 0, len, data);
+#endif
+ return !EFI_ERROR(status);
+}
diff --git a/libs/posix-uefi/uefi/string.c b/libs/posix-uefi/uefi/string.c
new file mode 100644
index 0000000..5a00aa6
--- /dev/null
+++ b/libs/posix-uefi/uefi/string.c
@@ -0,0 +1,262 @@
+/*
+ * string.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in string.h
+ *
+ */
+
+#include
+
+void *memcpy(void *dst, const void *src, size_t n)
+{
+ uint8_t *a=(uint8_t*)dst,*b=(uint8_t*)src;
+ if(src && dst && src != dst && n>0) {
+ while(n--) *a++ = *b++;
+ }
+ return dst;
+}
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+ uint8_t *a=(uint8_t*)dst,*b=(uint8_t*)src;
+ if(src && dst && src != dst && n>0) {
+ if(a>b && a0) *a--=*b--;
+ } else {
+ while(n--) *a++ = *b++;
+ }
+ }
+ return dst;
+}
+
+void *memset(void *s, int c, size_t n)
+{
+ uint8_t *p=(uint8_t*)s;
+ if(s && n>0) {
+ while(n--) *p++ = (uint8_t)c;
+ }
+ return s;
+}
+
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+ uint8_t *a=(uint8_t*)s1,*b=(uint8_t*)s2;
+ if(s1 && s2 && s1 != s2 && n>0) {
+ while(n--) {
+ if(*a != *b) return *a - *b;
+ a++; b++;
+ }
+ }
+ return 0;
+}
+
+void *memchr(const void *s, int c, size_t n)
+{
+ uint8_t *e, *p=(uint8_t*)s;
+ if(s && n>0) {
+ for(e=p+n; p0) {
+ for(e=p+n; p hl) return NULL;
+ hl -= nl - 1;
+ while(hl) {
+ if(!memcmp(c, needle, nl)) return c;
+ c++; hl--;
+ }
+ return NULL;
+}
+
+void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl)
+{
+ uint8_t *c = (uint8_t*)haystack;
+ if(!haystack || !needle || !hl || !nl || nl > hl) return NULL;
+ hl -= nl;
+ c += hl;
+ while(hl) {
+ if(!memcmp(c, needle, nl)) return c;
+ c--; hl--;
+ }
+ return NULL;
+}
+
+char_t *strcpy(char_t *dst, const char_t *src)
+{
+ char_t *s = dst;
+ if(src && dst && src != dst) {
+ while(*src) {*dst++=*src++;} *dst=0;
+ }
+ return s;
+}
+
+char_t *strncpy(char_t *dst, const char_t *src, size_t n)
+{
+ char_t *s = dst;
+ const char_t *e = src+n;
+ if(src && dst && src != dst && n>0) {
+ while(*src && src0) {
+ dst += strlen(dst);
+ while(*src && src0) {
+ while(s1
+
+static struct tm __tm;
+time_t __mktime_efi(efi_time_t *t);
+
+/* from musl */
+static uint64_t __year_to_secs(uint64_t year, int *is_leap)
+{
+ int y, cycles, centuries, leaps, rem;
+
+ if (year-2ULL <= 136) {
+ y = (int)year;
+ leaps = (y-68)>>2;
+ if (!((y-68)&3)) {
+ leaps--;
+ if (is_leap) *is_leap = 1;
+ } else if (is_leap) *is_leap = 0;
+ return 31536000ULL*(uint64_t)(y-70) + 86400ULL*(uint64_t)leaps;
+ }
+
+ if (!is_leap) is_leap = &(int){0};
+ cycles = (int)((year-100) / 400);
+ rem = (year-100) % 400;
+ if (rem < 0) {
+ cycles--;
+ rem += 400;
+ }
+ if (!rem) {
+ *is_leap = 1;
+ centuries = 0;
+ leaps = 0;
+ } else {
+ if (rem >= 200) {
+ if (rem >= 300) { centuries = 3; rem -= 300; }
+ else { centuries = 2; rem -= 200; }
+ } else {
+ if (rem >= 100) { centuries = 1; rem -= 100; }
+ else centuries = 0;
+ }
+ if (!rem) {
+ *is_leap = 0;
+ leaps = 0;
+ } else {
+ leaps = rem / 4;
+ rem %= 4;
+ *is_leap = !rem;
+ }
+ }
+
+ leaps += 97*cycles + 24*centuries - *is_leap;
+
+ return (uint64_t)(year-100) * 31536000ULL + (uint64_t)leaps * 86400ULL + 946684800ULL + 86400ULL;
+}
+
+time_t __mktime_efi(efi_time_t *t)
+{
+ __tm.tm_year = t->Year + (/* workaround some buggy firmware*/ t->Year > 2000 ? -1900 : 98);
+ __tm.tm_mon = t->Month - 1;
+ __tm.tm_mday = t->Day;
+ __tm.tm_hour = t->Hour;
+ __tm.tm_min = t->Minute;
+ __tm.tm_sec = t->Second;
+ __tm.tm_isdst = t->Daylight;
+ return mktime(&__tm);
+}
+
+/**
+ * This isn't POSIX, no arguments. Just returns the current time in struct tm
+ */
+struct tm *localtime (const time_t *__timer)
+{
+ efi_time_t t = {0};
+ (void)__timer;
+ ST->RuntimeServices->GetTime(&t, NULL);
+ __mktime_efi(&t);
+ return &__tm;
+}
+
+time_t mktime(const struct tm *tm)
+{
+ static const uint64_t secs_through_month[] = {
+ 0, 31*86400, 59*86400, 90*86400,
+ 120*86400, 151*86400, 181*86400, 212*86400,
+ 243*86400, 273*86400, 304*86400, 334*86400 };
+ int is_leap;
+ uint64_t year = (uint64_t)tm->tm_year, t, adj;
+ int month = tm->tm_mon;
+ if (month >= 12 || month < 0) {
+ adj = (uint64_t)month / 12;
+ month %= 12;
+ if (month < 0) {
+ adj--;
+ month += 12;
+ }
+ year += adj;
+ }
+ t = __year_to_secs(year, &is_leap);
+ t += secs_through_month[month];
+ if (is_leap && month >= 2) t += 86400;
+ t += 86400ULL * (uint64_t)(tm->tm_mday-1);
+ t += 3600ULL * (uint64_t)tm->tm_hour;
+ t += 60ULL * (uint64_t)tm->tm_min;
+ t += (uint64_t)tm->tm_sec;
+ return (time_t)t;
+}
+
+time_t time(time_t *__timer)
+{
+ time_t ret;
+ efi_time_t t = {0};
+ ST->RuntimeServices->GetTime(&t, NULL);
+ ret = __mktime_efi(&t);
+ if(__timer) *__timer = ret;
+ return ret;
+}
+
diff --git a/libs/posix-uefi/uefi/uefi.h b/libs/posix-uefi/uefi/uefi.h
new file mode 100644
index 0000000..256a10f
--- /dev/null
+++ b/libs/posix-uefi/uefi/uefi.h
@@ -0,0 +1,1433 @@
+/*
+ * uefi.h
+ * https://gitlab.com/bztsrc/posix-uefi
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Main (and only) header file
+ *
+ */
+
+#ifndef _UEFI_H_
+#define _UEFI_H_
+
+/*** configuration ***/
+/* #define UEFI_NO_UTF8 */ /* use wchar_t in your application */
+/* #define UEFI_NO_TRACK_ALLOC */ /* do not track allocated buffers' size */
+/*** configuration ends ***/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* get these from the compiler or the efi headers, only define if we have neither */
+#if !defined(_STDINT_H) && !defined(_GCC_STDINT_H) && !defined(_EFI_INCLUDE_)
+#define _STDINT_H
+typedef char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+#ifndef __clang__
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+typedef unsigned long int uintptr_t;
+#else
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long long uintptr_t;
+#endif
+#endif
+extern char c_assert1[sizeof(uint32_t) == 4 ? 1 : -1];
+extern char c_assert2[sizeof(uint64_t) == 8 ? 1 : -1];
+extern char c_assert3[sizeof(uintptr_t) == 8 ? 1 : -1];
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+/*** common defines and typedefs ***/
+typedef int64_t intn_t;
+typedef uint8_t boolean_t;
+typedef uint16_t wchar_t;
+typedef uint64_t uintn_t;
+typedef uint64_t size_t;
+typedef uint64_t time_t;
+typedef uint64_t mode_t;
+typedef uint64_t off_t;
+typedef uint64_t blkcnt_t;
+typedef uint64_t efi_status_t;
+typedef uint64_t efi_tpl_t;
+typedef uint64_t efi_lba_t;
+typedef uint64_t efi_physical_address_t;
+typedef uint64_t efi_virtual_address_t;
+typedef void *efi_handle_t;
+typedef void *efi_event_t;
+#ifndef UEFI_NO_UTF8
+typedef char char_t;
+#define CL(a) a
+extern char *__argvutf8;
+#else
+typedef wchar_t char_t;
+#define CL(a) L ## a
+#endif
+
+typedef struct {
+ uint32_t Data1;
+ uint16_t Data2;
+ uint16_t Data3;
+ uint8_t Data4[8];
+} efi_guid_t;
+
+typedef struct {
+ uint8_t Type;
+ uint8_t SubType;
+ uint8_t Length[2];
+} efi_device_path_t;
+
+typedef struct {
+ uint32_t Type;
+ uint32_t Pad;
+ efi_physical_address_t PhysicalStart;
+ efi_virtual_address_t VirtualStart;
+ uint64_t NumberOfPages;
+ uint64_t Attribute;
+} efi_memory_descriptor_t;
+
+typedef struct {
+ uint64_t Signature;
+ uint32_t Revision;
+ uint32_t HeaderSize;
+ uint32_t CRC32;
+ uint32_t Reserved;
+} efi_table_header_t;
+
+/*** definitions only needed when efi.h (either from EDK II or gnu-efi) is NOT included ***/
+
+#ifndef EFI_SPECIFICATION_MAJOR_REVISION
+
+/* efibind.h */
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+#define EFIERR(a) (0x8000000000000000 | (unsigned int)(a))
+#define EFI_ERROR_MASK 0x8000000000000000
+#define EFIERR_OEM(a) (0xc000000000000000 | (unsigned int)(a))
+
+#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((uint64_t)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#ifndef EFIAPI
+# ifdef _MSC_EXTENSIONS
+# define EFIAPI __cdecl
+# elif defined(HAVE_USE_MS_ABI)
+# define EFIAPI __attribute__((ms_abi))
+# else
+# define EFIAPI
+# endif
+#endif
+
+/* efistdarg.h */
+typedef __builtin_va_list va_list;
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+#define va_copy(d,s) __builtin_va_copy(d,s)
+
+/* efierr.h */
+#define EFIWARN(a) (a)
+#define EFI_ERROR(a) (((intn_t) a) < 0)
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR EFIERR(1)
+#define EFI_INVALID_PARAMETER EFIERR(2)
+#define EFI_UNSUPPORTED EFIERR(3)
+#define EFI_BAD_BUFFER_SIZE EFIERR(4)
+#define EFI_BUFFER_TOO_SMALL EFIERR(5)
+#define EFI_NOT_READY EFIERR(6)
+#define EFI_DEVICE_ERROR EFIERR(7)
+#define EFI_WRITE_PROTECTED EFIERR(8)
+#define EFI_OUT_OF_RESOURCES EFIERR(9)
+#define EFI_VOLUME_CORRUPTED EFIERR(10)
+#define EFI_VOLUME_FULL EFIERR(11)
+#define EFI_NO_MEDIA EFIERR(12)
+#define EFI_MEDIA_CHANGED EFIERR(13)
+#define EFI_NOT_FOUND EFIERR(14)
+#define EFI_ACCESS_DENIED EFIERR(15)
+#define EFI_NO_RESPONSE EFIERR(16)
+#define EFI_NO_MAPPING EFIERR(17)
+#define EFI_TIMEOUT EFIERR(18)
+#define EFI_NOT_STARTED EFIERR(19)
+#define EFI_ALREADY_STARTED EFIERR(20)
+#define EFI_ABORTED EFIERR(21)
+#define EFI_ICMP_ERROR EFIERR(22)
+#define EFI_TFTP_ERROR EFIERR(23)
+#define EFI_PROTOCOL_ERROR EFIERR(24)
+#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
+#define EFI_SECURITY_VIOLATION EFIERR(26)
+#define EFI_CRC_ERROR EFIERR(27)
+#define EFI_END_OF_MEDIA EFIERR(28)
+#define EFI_END_OF_FILE EFIERR(31)
+#define EFI_INVALID_LANGUAGE EFIERR(32)
+#define EFI_COMPROMISED_DATA EFIERR(33)
+
+#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1)
+#define EFI_WARN_UNKNOWN_GLYPH EFIWARN(1)
+#define EFI_WARN_DELETE_FAILURE EFIWARN(2)
+#define EFI_WARN_WRITE_FAILURE EFIWARN(3)
+#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4)
+
+/* efisetjmp.h */
+#ifdef __x86_64__
+typedef struct {
+ uint64_t Rbx;
+ uint64_t Rsp;
+ uint64_t Rbp;
+ uint64_t Rdi;
+ uint64_t Rsi;
+ uint64_t R12;
+ uint64_t R13;
+ uint64_t R14;
+ uint64_t R15;
+ uint64_t Rip;
+ uint64_t MxCsr;
+ uint8_t XmmBuffer[160];
+} __attribute__((aligned(8))) jmp_buf[1];
+#endif
+#ifdef __aarch64__
+typedef struct {
+ uint64_t X19;
+ uint64_t X20;
+ uint64_t X21;
+ uint64_t X22;
+ uint64_t X23;
+ uint64_t X24;
+ uint64_t X25;
+ uint64_t X26;
+ uint64_t X27;
+ uint64_t X28;
+ uint64_t FP;
+ uint64_t LR;
+ uint64_t IP0;
+ uint64_t reserved;
+ uint64_t D8;
+ uint64_t D9;
+ uint64_t D10;
+ uint64_t D11;
+ uint64_t D12;
+ uint64_t D13;
+ uint64_t D14;
+ uint64_t D15;
+} __attribute__((aligned(8))) jmp_buf[1];
+#endif
+#if defined(__riscv) && __riscv_xlen == 64
+typedef struct {
+ uint64_t pc;
+ uint64_t sp;
+ uint64_t regs[12];
+ double fp[12];
+} __attribute__((aligned(8))) jmp_buf[1];
+#endif
+extern uintn_t setjmp(jmp_buf env) __attribute__((returns_twice));
+extern void longjmp(jmp_buf env, uintn_t value) __attribute__((noreturn));
+
+/* efidevp.h */
+#define EFI_DEVICE_PATH_PROTOCOL_GUID { 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+#define EFI_DP_TYPE_MASK 0x7F
+#define EFI_DP_TYPE_UNPACKED 0x80
+#define END_DEVICE_PATH_TYPE 0x7f
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
+#define END_DEVICE_PATH_LENGTH (sizeof(efi_device_path_t))
+#define DP_IS_END_TYPE(a)
+#define DP_IS_END_SUBTYPE(a) ( ((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+#define DevicePathType(a) ( ((a)->Type) & EFI_DP_TYPE_MASK )
+#define DevicePathSubType(a) ( (a)->SubType )
+#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
+#define NextDevicePathNode(a) ( (efi_device_path_t *) ( ((uint8_t *) (a)) + DevicePathNodeLength(a)))
+#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE )
+#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) )
+#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )
+#define SetDevicePathNodeLength(a,l) { \
+ (a)->Length[0] = (uint8_t) (l); \
+ (a)->Length[1] = (uint8_t) ((l) >> 8); \
+ }
+#define SetDevicePathEndNode(a) { \
+ (a)->Type = END_DEVICE_PATH_TYPE; \
+ (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \
+ (a)->Length[0] = sizeof(efi_device_path_t); \
+ (a)->Length[1] = 0; \
+ }
+
+/* efiapi.h */
+#define EFI_SPECIFICATION_MAJOR_REVISION 1
+#define EFI_SPECIFICATION_MINOR_REVISION 02
+
+#define TPL_APPLICATION 4
+#define TPL_CALLBACK 8
+#define TPL_NOTIFY 16
+#define TPL_HIGH_LEVEL 31
+#define EFI_TPL_APPLICATION TPL_APPLICATION
+#define EFI_TPL_CALLBACK TPL_CALLBACK
+#define EFI_TPL_NOTIFY TPL_NOTIFY
+#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL
+
+#define NextMemoryDescriptor(Ptr,Size) ((efi_memory_descriptor_t *) (((uint8_t *) Ptr) + Size))
+
+#define EFI_PAGE_SIZE 4096
+#define EFI_PAGE_MASK 0xFFF
+#define EFI_PAGE_SHIFT 12
+
+#define EFI_SIZE_TO_PAGES(a) ( ((a) >> EFI_PAGE_SHIFT) + ((a) & EFI_PAGE_MASK ? 1 : 0) )
+
+#define EFI_MEMORY_UC 0x0000000000000001
+#define EFI_MEMORY_WC 0x0000000000000002
+#define EFI_MEMORY_WT 0x0000000000000004
+#define EFI_MEMORY_WB 0x0000000000000008
+#define EFI_MEMORY_UCE 0x0000000000000010
+#define EFI_MEMORY_WP 0x0000000000001000
+#define EFI_MEMORY_RP 0x0000000000002000
+#define EFI_MEMORY_XP 0x0000000000004000
+#define EFI_MEMORY_RUNTIME 0x8000000000000000
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+#define EVT_TIMER 0x80000000
+#define EVT_RUNTIME 0x40000000
+#define EVT_RUNTIME_CONTEXT 0x20000000
+
+#define EVT_NOTIFY_WAIT 0x00000100
+#define EVT_NOTIFY_SIGNAL 0x00000200
+
+#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201
+#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202
+
+#define EVT_EFI_SIGNAL_MASK 0x000000FF
+#define EVT_EFI_SIGNAL_MAX 4
+
+#define EFI_EVENT_TIMER EVT_TIMER
+#define EFI_EVENT_RUNTIME EVT_RUNTIME
+#define EFI_EVENT_RUNTIME_CONTEXT EVT_RUNTIME_CONTEXT
+#define EFI_EVENT_NOTIFY_WAIT EVT_NOTIFY_WAIT
+#define EFI_EVENT_NOTIFY_SIGNAL EVT_NOTIFY_SIGNAL
+#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES EVT_SIGNAL_EXIT_BOOT_SERVICES
+#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+#define EFI_EVENT_EFI_SIGNAL_MASK EVT_EFI_SIGNAL_MASK
+#define EFI_EVENT_EFI_SIGNAL_MAX EVT_EFI_SIGNAL_MAX
+
+#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
+#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
+#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
+#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
+#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
+#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
+
+#define EFI_OPTIONAL_PTR 0x00000001
+#define EFI_INTERNAL_FNC 0x00000002
+#define EFI_INTERNAL_PTR 0x00000004
+
+#define EFI_GLOBAL_VARIABLE { 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} }
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
+#define EFI_VARIABLE_APPEND_WRITE 0x00000040
+#define EFI_MAXIMUM_VARIABLE_SIZE 1024
+
+#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
+#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
+#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
+
+#define MPS_TABLE_GUID { 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+#define ACPI_TABLE_GUID { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+#define ACPI_20_TABLE_GUID { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} }
+#define SMBIOS_TABLE_GUID { 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+#define SMBIOS3_TABLE_GUID { 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e,0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} }
+#define SAL_SYSTEM_TABLE_GUID { 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+
+#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552
+#define EFI_RUNTIME_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
+
+#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42
+#define EFI_BOOT_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
+
+#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
+#define EFI_SYSTEM_TABLE_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION)
+
+/* eficon.h */
+#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID { 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+#define EFI_BLACK 0x00
+#define EFI_BLUE 0x01
+#define EFI_GREEN 0x02
+#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
+#define EFI_RED 0x04
+#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
+#define EFI_BROWN (EFI_GREEN | EFI_RED)
+#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
+#define EFI_BRIGHT 0x08
+#define EFI_DARKGRAY (EFI_BRIGHT)
+#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
+#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
+#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
+#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
+#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
+#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
+#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
+#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4))
+#define EFI_BACKGROUND_BLACK 0x00
+#define EFI_BACKGROUND_BLUE 0x10
+#define EFI_BACKGROUND_GREEN 0x20
+#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
+#define EFI_BACKGROUND_RED 0x40
+#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define BOXDRAW_HORIZONTAL 0x2500
+#define BOXDRAW_VERTICAL 0x2502
+#define BOXDRAW_DOWN_RIGHT 0x250c
+#define BOXDRAW_DOWN_LEFT 0x2510
+#define BOXDRAW_UP_RIGHT 0x2514
+#define BOXDRAW_UP_LEFT 0x2518
+#define BOXDRAW_VERTICAL_RIGHT 0x251c
+#define BOXDRAW_VERTICAL_LEFT 0x2524
+#define BOXDRAW_DOWN_HORIZONTAL 0x252c
+#define BOXDRAW_UP_HORIZONTAL 0x2534
+#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c
+#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550
+#define BOXDRAW_DOUBLE_VERTICAL 0x2551
+#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552
+#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553
+#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554
+#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555
+#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556
+#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557
+#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558
+#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559
+#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a
+#define BOXDRAW_UP_LEFT_DOUBLE 0x255b
+#define BOXDRAW_UP_DOUBLE_LEFT 0x255c
+#define BOXDRAW_DOUBLE_UP_LEFT 0x255d
+#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e
+#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f
+#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560
+#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561
+#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562
+#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563
+#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564
+#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565
+#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566
+#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567
+#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568
+#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569
+#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a
+#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b
+#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c
+#define BLOCKELEMENT_FULL_BLOCK 0x2588
+#define BLOCKELEMENT_LIGHT_SHADE 0x2591
+#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2
+#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba
+#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc
+#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4
+#define ARROW_UP 0x2191
+#define ARROW_DOWN 0x2193
+
+#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID { 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+#define CHAR_NULL 0x0000
+#define CHAR_BACKSPACE 0x0008
+#define CHAR_TAB 0x0009
+#define CHAR_LINEFEED 0x000A
+#define CHAR_CARRIAGE_RETURN 0x000D
+#define SCAN_NULL 0x0000
+#define SCAN_UP 0x0001
+#define SCAN_DOWN 0x0002
+#define SCAN_RIGHT 0x0003
+#define SCAN_LEFT 0x0004
+#define SCAN_HOME 0x0005
+#define SCAN_END 0x0006
+#define SCAN_INSERT 0x0007
+#define SCAN_DELETE 0x0008
+#define SCAN_PAGE_UP 0x0009
+#define SCAN_PAGE_DOWN 0x000A
+#define SCAN_F1 0x000B
+#define SCAN_F2 0x000C
+#define SCAN_F3 0x000D
+#define SCAN_F4 0x000E
+#define SCAN_F5 0x000F
+#define SCAN_F6 0x0010
+#define SCAN_F7 0x0011
+#define SCAN_F8 0x0012
+#define SCAN_F9 0x0013
+#define SCAN_F10 0x0014
+#define SCAN_F11 0x0015
+#define SCAN_F12 0x0016
+#define SCAN_ESC 0x0017
+
+/* efigpt.h */
+#define PRIMARY_PART_HEADER_LBA 1
+#define EFI_PTAB_HEADER_ID "EFI PART"
+#define EFI_PART_USED_BY_EFI 0x0000000000000001
+#define EFI_PART_REQUIRED_TO_FUNCTION 0x0000000000000002
+#define EFI_PART_USED_BY_OS 0x0000000000000004
+#define EFI_PART_REQUIRED_BY_OS 0x0000000000000008
+#define EFI_PART_BACKUP_REQUIRED 0x0000000000000010
+#define EFI_PART_USER_DATA 0x0000000000000020
+#define EFI_PART_CRITICAL_USER_DATA 0x0000000000000040
+#define EFI_PART_REDUNDANT_PARTITION 0x0000000000000080
+#define EFI_PART_TYPE_UNUSED_GUID { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
+#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID { 0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }
+#define EFI_PART_TYPE_LEGACY_MBR_GUID { 0x024dee41, 0x33e7, 0x11d3, {0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f} }
+
+/* Protocol GUIDs */
+#ifndef INTERNAL_SHELL_GUID
+#define INTERNAL_SHELL_GUID { 0xd65a6b8c, 0x71e5, 0x4df0, {0xa9, 0x09, 0xf0, 0xd2, 0x99, 0x2b, 0x5a, 0xa9} }
+#endif
+
+typedef enum {
+ AllocateAnyPages,
+ AllocateMaxAddress,
+ AllocateAddress,
+ MaxAllocateType
+} efi_allocate_type_t;
+
+typedef enum {
+ EfiReservedMemoryType,
+ EfiLoaderCode,
+ EfiLoaderData,
+ EfiBootServicesCode,
+ EfiBootServicesData,
+ EfiRuntimeServicesCode,
+ EfiRuntimeServicesData,
+ EfiConventionalMemory,
+ EfiUnusableMemory,
+ EfiACPIReclaimMemory,
+ EfiACPIMemoryNVS,
+ EfiMemoryMappedIO,
+ EfiMemoryMappedIOPortSpace,
+ EfiPalCode,
+ EfiPersistentMemory,
+ EfiUnacceptedMemoryType,
+ EfiMaxMemoryType
+} efi_memory_type_t;
+
+typedef enum {
+ TimerCancel,
+ TimerPeriodic,
+ TimerRelative,
+ TimerTypeMax
+} efi_timer_delay_t;
+
+typedef enum {
+ AllHandles,
+ ByRegisterNotify,
+ ByProtocol
+} efi_locate_search_type_t;
+
+typedef enum {
+ EfiResetCold,
+ EfiResetWarm,
+ EfiResetShutdown
+} efi_reset_type_t;
+
+#else
+
+#define efi_allocate_type_t EFI_ALLOCATE_TYPE
+#define efi_memory_type_t EFI_MEMORY_TYPE
+#define efi_timer_delay_t EFI_TIMER_DELAY
+#define efi_locate_search_type_t EFI_LOCATE_SEARCH_TYPE
+#define efi_reset_type_t EFI_RESET_TYPE
+
+#endif
+
+/*** standard input, output and error streams via ConIn, ConOut and StdErr ***/
+typedef struct {
+ uint16_t ScanCode;
+ wchar_t UnicodeChar;
+} efi_input_key_t;
+
+typedef efi_status_t (EFIAPI *efi_input_reset_t)(void *This, boolean_t ExtendedVerification);
+typedef efi_status_t (EFIAPI *efi_input_read_key_t)(void *This, efi_input_key_t *Key);
+
+typedef struct {
+ efi_input_reset_t Reset;
+ efi_input_read_key_t ReadKeyStroke;
+ efi_event_t WaitForKey;
+} simple_input_interface_t;
+
+typedef efi_status_t (EFIAPI *efi_text_reset_t)(void *This, boolean_t ExtendedVerification);
+typedef efi_status_t (EFIAPI *efi_text_output_string_t)(void *This, wchar_t *String);
+typedef efi_status_t (EFIAPI *efi_text_test_string_t)(void *This, wchar_t *String);
+typedef efi_status_t (EFIAPI *efi_text_query_mode_t)(void *This, uintn_t ModeNumber, uintn_t *Column, uintn_t *Row);
+typedef efi_status_t (EFIAPI *efi_text_set_mode_t)(void *This, uintn_t ModeNumber);
+typedef efi_status_t (EFIAPI *efi_text_set_attribute_t)(void *This, uintn_t Attribute);
+typedef efi_status_t (EFIAPI *efi_text_clear_screen_t)(void *This);
+typedef efi_status_t (EFIAPI *efi_text_set_cursor_t)(void *This, uintn_t Column, uintn_t Row);
+typedef efi_status_t (EFIAPI *efi_text_enable_cursor_t)(void *This, boolean_t Enable);
+
+typedef struct {
+ int32_t MaxMode;
+ int32_t Mode;
+ int32_t Attribute;
+ int32_t CursorColumn;
+ int32_t CursorRow;
+ boolean_t CursorVisible;
+} simple_text_output_mode_t;
+
+typedef struct {
+ efi_text_reset_t Reset;
+ efi_text_output_string_t OutputString;
+ efi_text_test_string_t TestString;
+ efi_text_query_mode_t QueryMode;
+ efi_text_set_mode_t SetMode;
+ efi_text_set_attribute_t SetAttribute;
+ efi_text_clear_screen_t ClearScreen;
+ efi_text_set_cursor_t SetCursorPosition;
+ efi_text_enable_cursor_t EnableCursor;
+ simple_text_output_mode_t *Mode;
+} simple_text_output_interface_t;
+
+/*** Runtime Services ***/
+typedef struct {
+ uint16_t Year; /* 1998 - 2XXX */
+ uint8_t Month; /* 1 - 12 */
+ uint8_t Day; /* 1 - 31 */
+ uint8_t Hour; /* 0 - 23 */
+ uint8_t Minute; /* 0 - 59 */
+ uint8_t Second; /* 0 - 59 */
+ uint8_t Pad1;
+ uint32_t Nanosecond; /* 0 - 999,999,999 */
+ int16_t TimeZone; /* -1440 to 1440 or 2047 */
+ uint8_t Daylight;
+ uint8_t Pad2;
+} efi_time_t;
+
+typedef struct {
+ uint32_t Resolution;
+ uint32_t Accuracy;
+ boolean_t SetsToZero;
+} efi_time_capabilities_t;
+
+typedef struct {
+ efi_guid_t CapsuleGuid;
+ uint32_t HeaderSize;
+ uint32_t Flags;
+ uint32_t CapsuleImageSize;
+} efi_capsule_header_t;
+
+#ifndef DataBlock
+#define DataBlock ContinuationPointer
+#endif
+typedef struct {
+ uint64_t Length;
+ efi_physical_address_t ContinuationPointer;
+} efi_capsule_block_descriptor_t;
+
+typedef efi_status_t (EFIAPI *efi_get_time_t)(efi_time_t *Time, efi_time_capabilities_t *Capabilities);
+typedef efi_status_t (EFIAPI *efi_set_time_t)(efi_time_t *Time);
+typedef efi_status_t (EFIAPI *efi_get_wakeup_time_t)(boolean_t *Enable, boolean_t *Pending, efi_time_t *Time);
+typedef efi_status_t (EFIAPI *efi_set_wakeup_time_t)(boolean_t Enable, efi_time_t *Time);
+typedef efi_status_t (EFIAPI *efi_set_virtual_address_map_t)(uintn_t MemoryMapSize, uintn_t DescriptorSize,
+ uint32_t DescriptorVersion, efi_memory_descriptor_t *VirtualMap);
+typedef efi_status_t (EFIAPI *efi_convert_pointer_t)(uintn_t DebugDisposition, void **Address);
+typedef efi_status_t (EFIAPI *efi_get_variable_t)(wchar_t *VariableName, efi_guid_t *VendorGuid, uint32_t *Attributes,
+ uintn_t *DataSize, void *Data);
+typedef efi_status_t (EFIAPI *efi_get_next_variable_name_t)(uintn_t *VariableNameSize, wchar_t *VariableName,
+ efi_guid_t *VendorGuid);
+typedef efi_status_t (EFIAPI *efi_set_variable_t)(wchar_t *VariableName, efi_guid_t *VendorGuid, uint32_t Attributes,
+ uintn_t DataSize, void *Data);
+typedef efi_status_t (EFIAPI *efi_get_next_high_mono_t)(uint64_t *Count);
+typedef efi_status_t (EFIAPI *efi_reset_system_t)(efi_reset_type_t ResetType, efi_status_t ResetStatus, uintn_t DataSize,
+ wchar_t *ResetData);
+typedef efi_status_t (EFIAPI *efi_update_capsule_t)(efi_capsule_header_t **CapsuleHeaderArray, uintn_t CapsuleCount,
+ efi_physical_address_t ScatterGatherList);
+typedef efi_status_t (EFIAPI *efi_query_capsule_capabilities_t)(efi_capsule_header_t **CapsuleHeaderArray, uintn_t CapsuleCount,
+ uint64_t *MaximumCapsuleSize, efi_reset_type_t *ResetType);
+typedef efi_status_t (EFIAPI *efi_query_variable_info_t)(uint32_t Attributes, uint64_t *MaximumVariableStorageSize,
+ uint64_t *RemainingVariableStorageSize, uint64_t *MaximumVariableSize);
+
+typedef struct {
+ efi_table_header_t Hdr;
+
+ efi_get_time_t GetTime;
+ efi_set_time_t SetTime;
+ efi_get_wakeup_time_t GetWakeupTime;
+ efi_set_wakeup_time_t SetWakeupTime;
+
+ efi_set_virtual_address_map_t SetVirtualAddressMap;
+ efi_convert_pointer_t ConvertPointer;
+
+ efi_get_variable_t GetVariable;
+ efi_get_next_variable_name_t GetNextVariableName;
+ efi_set_variable_t SetVariable;
+
+ efi_get_next_high_mono_t GetNextHighMonotonicCount;
+ efi_reset_system_t ResetSystem;
+
+ efi_update_capsule_t UpdateCapsule;
+ efi_query_capsule_capabilities_t QueryCapsuleCapabilities;
+ efi_query_variable_info_t QueryVariableInfo;
+} efi_runtime_services_t;
+extern efi_runtime_services_t *RT;
+#define gRT RT
+
+/** Boot Services ***/
+typedef struct {
+ efi_handle_t AgentHandle;
+ efi_handle_t ControllerHandle;
+ uint32_t Attributes;
+ uint32_t OpenCount;
+} efi_open_protocol_information_entry_t;
+
+typedef efi_tpl_t (EFIAPI *efi_raise_tpl_t)(efi_tpl_t NewTpl);
+typedef efi_tpl_t (EFIAPI *efi_restore_tpl_t)(efi_tpl_t OldTpl);
+typedef efi_status_t (EFIAPI *efi_allocate_pages_t)(efi_allocate_type_t Type, efi_memory_type_t MemoryType,
+ uintn_t NoPages, efi_physical_address_t *Memory);
+typedef efi_status_t (EFIAPI *efi_free_pages_t)(efi_physical_address_t Memory, uintn_t NoPages);
+typedef efi_status_t (EFIAPI *efi_get_memory_map_t)(uintn_t *MemoryMapSize, efi_memory_descriptor_t *MemoryMap,
+ uintn_t *MapKey, uintn_t *DescriptorSize, uint32_t *DescriptorVersion);
+typedef efi_status_t (EFIAPI *efi_allocate_pool_t)(efi_memory_type_t PoolType, uintn_t Size, void **Buffer);
+typedef efi_status_t (EFIAPI *efi_free_pool_t)(void *Buffer);
+typedef void (EFIAPI *efi_event_notify_t)(efi_event_t Event, void *Context);
+typedef efi_status_t (EFIAPI *efi_create_event_t)(uint32_t Type, efi_tpl_t NotifyTpl, efi_event_notify_t NotifyFunction,
+ void *NextContext, efi_event_t *Event);
+typedef efi_status_t (EFIAPI *efi_set_timer_t)(efi_event_t Event, efi_timer_delay_t Type, uint64_t TriggerTime);
+typedef efi_status_t (EFIAPI *efi_wait_for_event_t)(uintn_t NumberOfEvents, efi_event_t *Event, uintn_t *Index);
+typedef efi_status_t (EFIAPI *efi_signal_event_t)(efi_event_t Event);
+typedef efi_status_t (EFIAPI *efi_close_event_t)(efi_event_t Event);
+typedef efi_status_t (EFIAPI *efi_check_event_t)(efi_event_t Event);
+typedef efi_status_t (EFIAPI *efi_handle_protocol_t)(efi_handle_t Handle, efi_guid_t *Protocol, void **Interface);
+typedef efi_status_t (EFIAPI *efi_register_protocol_notify_t)(efi_guid_t *Protocol, efi_event_t Event, void **Registration);
+typedef efi_status_t (EFIAPI *efi_locate_handle_t)(efi_locate_search_type_t SearchType, efi_guid_t *Protocol,
+ void *SearchKey, uintn_t *BufferSize, efi_handle_t *Buffer);
+typedef efi_status_t (EFIAPI *efi_locate_device_path_t)(efi_guid_t *Protocol, efi_device_path_t **DevicePath,
+ efi_handle_t *Device);
+typedef efi_status_t (EFIAPI *efi_install_configuration_table_t)(efi_guid_t *Guid, void *Table);
+typedef efi_status_t (EFIAPI *efi_image_load_t)(boolean_t BootPolicy, efi_handle_t ParentImageHandle, efi_device_path_t *FilePath,
+ void *SourceBuffer, uintn_t SourceSize, efi_handle_t *ImageHandle);
+typedef efi_status_t (EFIAPI *efi_image_start_t)(efi_handle_t ImageHandle, uintn_t *ExitDataSize, wchar_t **ExitData);
+typedef efi_status_t (EFIAPI *efi_exit_t)(efi_handle_t ImageHandle, efi_status_t ExitStatus, uintn_t ExitDataSize,
+ wchar_t *ExitData);
+typedef efi_status_t (EFIAPI *efi_exit_boot_services_t)(efi_handle_t ImageHandle, uintn_t MapKey);
+typedef efi_status_t (EFIAPI *efi_get_next_monotonic_t)(uint64_t *Count);
+typedef efi_status_t (EFIAPI *efi_stall_t)(uintn_t Microseconds);
+typedef efi_status_t (EFIAPI *efi_set_watchdog_timer_t)(uintn_t Timeout, uint64_t WatchdogCode, uintn_t DataSize,
+ wchar_t *WatchdogData);
+typedef efi_status_t (EFIAPI *efi_connect_controller_t)(efi_handle_t ControllerHandle, efi_handle_t *DriverImageHandle,
+ efi_device_path_t *RemainingDevicePath, boolean_t Recursive);
+typedef efi_status_t (EFIAPI *efi_disconnect_controller_t)(efi_handle_t ControllerHandle, efi_handle_t DriverImageHandle,
+ efi_handle_t ChildHandle);
+typedef efi_status_t (EFIAPI *efi_open_protocol_t)(efi_handle_t Handle, efi_guid_t *Protocol, void **Interface,
+ efi_handle_t AgentHandle, efi_handle_t ControllerHandle, uint32_t Attributes);
+typedef efi_status_t (EFIAPI *efi_close_protocol_t)(efi_handle_t Handle, efi_guid_t *Protocol, efi_handle_t AgentHandle,
+ efi_handle_t ControllerHandle);
+typedef efi_status_t (EFIAPI *efi_open_protocol_information_t)(efi_handle_t Handle, efi_guid_t *Protocol,
+ efi_open_protocol_information_entry_t**EntryBuffer, uintn_t *EntryCount);
+typedef efi_status_t (EFIAPI *efi_protocols_per_handle_t)(efi_handle_t Handle, efi_guid_t ***ProtocolBuffer,
+ uintn_t *ProtocolBufferCount);
+typedef efi_status_t (EFIAPI *efi_locate_handle_buffer_t)(efi_locate_search_type_t SearchType, efi_guid_t *Protocol,
+ void *SearchKey, uintn_t *NoHandles, efi_handle_t **Handles);
+typedef efi_status_t (EFIAPI *efi_locate_protocol_t)(efi_guid_t *Protocol, void *Registration, void **Interface);
+typedef efi_status_t (EFIAPI *efi_calculate_crc32_t)(void *Data, uintn_t DataSize, uint32_t *Crc32);
+
+typedef struct {
+ efi_table_header_t Hdr;
+
+ efi_raise_tpl_t RaiseTPL;
+ efi_restore_tpl_t RestoreTPL;
+
+ efi_allocate_pages_t AllocatePages;
+ efi_free_pages_t FreePages;
+ efi_get_memory_map_t GetMemoryMap;
+ efi_allocate_pool_t AllocatePool;
+ efi_free_pool_t FreePool;
+
+ efi_create_event_t CreateEvent;
+ efi_set_timer_t SetTimer;
+ efi_wait_for_event_t WaitForEvent;
+ efi_signal_event_t SignalEvent;
+ efi_close_event_t CloseEvent;
+ efi_check_event_t CheckEvent;
+
+ void* InstallProtocolInterface; /* not defined yet */
+ void* ReinstallProtocolInterface;
+ void* UninstallProtocolInterface;
+ efi_handle_protocol_t HandleProtocol;
+ efi_handle_protocol_t PCHandleProtocol;
+ efi_register_protocol_notify_t RegisterProtocolNotify;
+ efi_locate_handle_t LocateHandle;
+ efi_locate_device_path_t LocateDevicePath;
+ efi_install_configuration_table_t InstallConfigurationTable;
+
+ efi_image_load_t LoadImage;
+ efi_image_start_t StartImage;
+ efi_exit_t Exit;
+ void* UnloadImage; /* not defined in gnu-efi either */
+ efi_exit_boot_services_t ExitBootServices;
+
+ efi_get_next_monotonic_t GetNextHighMonotonicCount;
+ efi_stall_t Stall;
+ efi_set_watchdog_timer_t SetWatchdogTimer;
+
+ efi_connect_controller_t ConnectController;
+ efi_disconnect_controller_t DisconnectController;
+
+ efi_open_protocol_t OpenProtocol;
+ efi_close_protocol_t CloseProtocol;
+ efi_open_protocol_information_t OpenProtocolInformation;
+
+ efi_protocols_per_handle_t ProtocolsPerHandle;
+ efi_locate_handle_buffer_t LocateHandleBuffer;
+ efi_locate_protocol_t LocateProtocol;
+ void* InstallMultipleProtocolInterfaces;
+ void* UninstallMultipleProtocolInterfaces;
+
+ efi_calculate_crc32_t CalculateCrc32;
+} efi_boot_services_t;
+extern efi_boot_services_t *BS;
+#define gBS BS
+
+/*** Loaded Image Protocol ***/
+#ifndef EFI_LOADED_IMAGE_PROTOCOL_GUID
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} }
+#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID
+
+#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000
+#define EFI_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION
+#endif
+
+typedef struct {
+ uint32_t Revision;
+ efi_handle_t ParentHandle;
+ void *SystemTable;
+ efi_handle_t DeviceHandle;
+ efi_device_path_t *FilePath;
+ void *Reserved;
+ uint32_t LoadOptionsSize;
+ void *LoadOptions;
+ void *ImageBase;
+ uint64_t ImageSize;
+ efi_memory_type_t ImageCodeType;
+ efi_memory_type_t ImageDataType;
+} efi_loaded_image_protocol_t;
+extern efi_loaded_image_protocol_t *LIP;
+extern efi_handle_t IM;
+
+/*** System Table ***/
+typedef struct {
+ efi_guid_t VendorGuid;
+ void *VendorTable;
+} efi_configuration_table_t;
+
+typedef struct {
+ efi_table_header_t Hdr;
+
+ wchar_t *FirmwareVendor;
+ uint32_t FirmwareRevision;
+
+ efi_handle_t ConsoleInHandle;
+ simple_input_interface_t *ConIn;
+
+ efi_handle_t ConsoleOutHandle;
+ simple_text_output_interface_t *ConOut;
+
+ efi_handle_t ConsoleErrorHandle;
+ simple_text_output_interface_t *StdErr;
+
+ efi_runtime_services_t *RuntimeServices;
+ efi_boot_services_t *BootServices;
+
+ uintn_t NumberOfTableEntries;
+ efi_configuration_table_t *ConfigurationTable;
+} efi_system_table_t;
+extern efi_system_table_t *ST;
+#define gST ST
+
+/*** Simple File System Protocol ***/
+#ifndef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID { 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000
+#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
+
+#define EFI_FILE_MODE_READ 0x0000000000000001
+#define EFI_FILE_MODE_WRITE 0x0000000000000002
+#define EFI_FILE_MODE_CREATE 0x8000000000000000
+
+#define EFI_FILE_READ_ONLY 0x0000000000000001
+#define EFI_FILE_HIDDEN 0x0000000000000002
+#define EFI_FILE_SYSTEM 0x0000000000000004
+#define EFI_FILE_RESERVED 0x0000000000000008
+#define EFI_FILE_DIRECTORY 0x0000000000000010
+#define EFI_FILE_ARCHIVE 0x0000000000000020
+#define EFI_FILE_VALID_ATTR 0x0000000000000037
+
+#define EFI_FILE_PROTOCOL_REVISION 0x00010000
+#define EFI_FILE_HANDLE_REVISION EFI_FILE_PROTOCOL_REVISION
+#endif
+
+#ifndef EFI_FILE_INFO_GUID
+#define EFI_FILE_INFO_GUID { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+#endif
+
+#ifndef FILENAME_MAX
+#define FILENAME_MAX 262 /* from FAT spec */
+#endif
+
+typedef struct {
+ uint64_t Size;
+ uint64_t FileSize;
+ uint64_t PhysicalSize;
+ efi_time_t CreateTime;
+ efi_time_t LastAccessTime;
+ efi_time_t ModificationTime;
+ uint64_t Attribute;
+ wchar_t FileName[FILENAME_MAX];
+} efi_file_info_t;
+
+typedef struct efi_file_handle_s efi_file_handle_t;
+
+typedef efi_status_t (EFIAPI *efi_volume_open_t)(void *This, efi_file_handle_t **Root);
+typedef struct {
+ uint64_t Revision;
+ efi_volume_open_t OpenVolume;
+} efi_simple_file_system_protocol_t;
+
+typedef efi_status_t (EFIAPI *efi_file_open_t)(efi_file_handle_t *File, efi_file_handle_t **NewHandle, wchar_t *FileName,
+ uint64_t OpenMode, uint64_t Attributes);
+typedef efi_status_t (EFIAPI *efi_file_close_t)(efi_file_handle_t *File);
+typedef efi_status_t (EFIAPI *efi_file_delete_t)(efi_file_handle_t *File);
+typedef efi_status_t (EFIAPI *efi_file_read_t)(efi_file_handle_t *File, uintn_t *BufferSize, void *Buffer);
+typedef efi_status_t (EFIAPI *efi_file_write_t)(efi_file_handle_t *File, uintn_t *BufferSize, void *Buffer);
+typedef efi_status_t (EFIAPI *efi_file_get_pos_t)(efi_file_handle_t *File, uint64_t *Position);
+typedef efi_status_t (EFIAPI *efi_file_set_pos_t)(efi_file_handle_t *File, uint64_t Position);
+typedef efi_status_t (EFIAPI *efi_file_get_info_t)(efi_file_handle_t *File, efi_guid_t *InformationType, uintn_t *BufferSize,
+ void *Buffer);
+typedef efi_status_t (EFIAPI *efi_file_set_info_t)(efi_file_handle_t *File, efi_guid_t *InformationType, uintn_t BufferSize,
+ void *Buffer);
+typedef efi_status_t (EFIAPI *efi_file_flush_t)(efi_file_handle_t *File);
+
+struct efi_file_handle_s {
+ uint64_t Revision;
+ efi_file_open_t Open;
+ efi_file_close_t Close;
+ efi_file_delete_t Delete;
+ efi_file_read_t Read;
+ efi_file_write_t Write;
+ efi_file_get_pos_t GetPosition;
+ efi_file_set_pos_t SetPosition;
+ efi_file_get_info_t GetInfo;
+ efi_file_set_info_t SetInfo;
+ efi_file_flush_t Flush;
+};
+
+/*** Shell Parameter Protocols ***/
+#ifndef EFI_SHELL_PARAMETERS_PROTOCOL_GUID
+#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca} }
+#endif
+
+typedef struct {
+ wchar_t **Argv;
+ uintn_t Argc;
+ efi_handle_t StdIn;
+ efi_handle_t StdOut;
+ efi_handle_t StdErr;
+} efi_shell_parameters_protocol_t;
+
+#ifndef SHELL_INTERFACE_PROTOCOL_GUID
+#define SHELL_INTERFACE_PROTOCOL_GUID { 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+#endif
+
+typedef struct {
+ efi_handle_t ImageHandle;
+ void* *Info;
+ wchar_t **Argv;
+ uintn_t Argc;
+ wchar_t **RedirArgv;
+ uintn_t RedirArgc;
+ efi_handle_t StdIn;
+ efi_handle_t StdOut;
+ efi_handle_t StdErr;
+} efi_shell_interface_protocol_t;
+
+/*** Random Number Generator ***/
+#ifndef EFI_RNG_PROTOCOL_GUID
+#define EFI_RNG_PROTOCOL_GUID { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} }
+#endif
+
+typedef efi_status_t (EFIAPI *efi_rng_get_info_t)(void *This, uintn_t *RNGAlgorithmListSize, efi_guid_t *RNGAlgorithmList);
+typedef efi_status_t (EFIAPI *efi_rng_get_rng_t)(void *This, efi_guid_t *RNGAlgorithm, uintn_t RNGValueLength, uint8_t *RNGValue);
+
+typedef struct {
+ efi_rng_get_info_t GetInfo;
+ efi_rng_get_rng_t GetRNG;
+} efi_rng_protocol_t;
+
+/*** Serial IO Protocol ***/
+#ifndef EFI_SERIAL_IO_PROTOCOL_GUID
+#define EFI_SERIAL_IO_PROTOCOL_GUID { 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD} }
+
+#define SERIAL_IO_INTERFACE_REVISION 0x00010000
+#define EFI_SERIAL_CLEAR_TO_SEND 0x0010
+#define EFI_SERIAL_DATA_SET_READY 0x0020
+#define EFI_SERIAL_RING_INDICATE 0x0040
+#define EFI_SERIAL_CARRIER_DETECT 0x0080
+#define EFI_SERIAL_REQUEST_TO_SEND 0x0002
+#define EFI_SERIAL_DATA_TERMINAL_READY 0x0001
+#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x0100
+#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x0200
+#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x1000
+#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x2000
+#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x4000
+
+typedef enum {
+ DefaultParity,
+ NoParity,
+ EvenParity,
+ OddParity,
+ MarkParity,
+ SpaceParity
+} efi_parity_type_t;
+
+typedef enum {
+ DefaultStopBits,
+ OneStopBit,
+ OneFiveStopBits,
+ TwoStopBits
+} efi_stop_bits_type_t;
+
+#else
+
+#define efi_parity_type_t EFI_PARITY_TYPE
+#define efi_stop_bits_type_t EFI_STOP_BITS_TYPE
+
+#endif
+
+typedef struct {
+ uint32_t ControlMask;
+ uint32_t Timeout;
+ uint64_t BaudRate;
+ uint32_t ReceiveFifoDepth;
+ uint32_t DataBits;
+ uint32_t Parity;
+ uint32_t StopBits;
+} efi_serial_io_mode_t;
+
+typedef efi_status_t (EFIAPI *efi_serial_reset_t)(void *This);
+typedef efi_status_t (EFIAPI *efi_serial_set_attributes_t)(void *This, uint64_t BaudRate, uint32_t ReceiveFifoDepth,
+ uint32_t Timeout, efi_parity_type_t Parity, uint8_t DataBits, efi_stop_bits_type_t StopBits);
+typedef efi_status_t (EFIAPI *efi_serial_set_control_bits_t)(void *This, uint32_t Control);
+typedef efi_status_t (EFIAPI *efi_serial_get_control_bits_t)(void *This, uint32_t *Control);
+typedef efi_status_t (EFIAPI *efi_serial_write_t)(void *This, uintn_t *BufferSize, void *Buffer);
+typedef efi_status_t (EFIAPI *efi_serial_read_t)(void *This, uintn_t *BufferSize, void *Buffer);
+
+typedef struct {
+ uint32_t Revision;
+ efi_serial_reset_t Reset;
+ efi_serial_set_attributes_t SetAttributes;
+ efi_serial_set_control_bits_t SetControl;
+ efi_serial_get_control_bits_t GetControl;
+ efi_serial_write_t Write;
+ efi_serial_read_t Read;
+ efi_serial_io_mode_t *Mode;
+} efi_serial_io_protocol_t;
+
+/*** Block IO Protocol ***/
+#ifndef EFI_BLOCK_IO_PROTOCOL_GUID
+#define EFI_BLOCK_IO_PROTOCOL_GUID { 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
+
+#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
+#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION
+
+#endif
+
+typedef struct {
+ uint32_t MediaId;
+ boolean_t RemovableMedia;
+ boolean_t MediaPresent;
+ boolean_t LogicalPartition;
+ boolean_t ReadOnly;
+ boolean_t WriteCaching;
+ uint32_t BlockSize;
+ uint32_t IoAlign;
+ efi_lba_t LastBlock;
+} efi_block_io_media_t;
+
+typedef efi_status_t (EFIAPI *efi_block_reset_t)(void *This, boolean_t ExtendedVerification);
+typedef efi_status_t (EFIAPI *efi_block_read_t)(void *This, uint32_t MediaId, efi_lba_t LBA, uintn_t BufferSize, void *Buffer);
+typedef efi_status_t (EFIAPI *efi_block_write_t)(void *This, uint32_t MediaId, efi_lba_t LBA, uintn_t BufferSize, void *Buffer);
+typedef efi_status_t (EFIAPI *efi_block_flush_t)(void *This);
+
+typedef struct {
+ uint64_t Revision;
+ efi_block_io_media_t *Media;
+ efi_block_reset_t Reset;
+ efi_block_read_t ReadBlocks;
+ efi_block_write_t WriteBlocks;
+ efi_block_flush_t FlushBlocks;
+} efi_block_io_t;
+
+typedef struct {
+ off_t offset;
+ efi_block_io_t *bio;
+} block_file_t;
+
+/*** Graphics Output Protocol (not used, but could be useful to have) ***/
+#ifndef EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID { 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } }
+
+typedef enum {
+ PixelRedGreenBlueReserved8BitPerColor,
+ PixelBlueGreenRedReserved8BitPerColor,
+ PixelBitMask,
+ PixelBltOnly,
+ PixelFormatMax
+} efi_gop_pixel_format_t;
+
+typedef enum {
+ EfiBltVideoFill,
+ EfiBltVideoToBltBuffer,
+ EfiBltBufferToVideo,
+ EfiBltVideoToVideo,
+ EfiGraphicsOutputBltOperationMax
+} efi_gop_blt_operation_t;
+
+#else
+
+#define efi_gop_pixel_format_t EFI_GRAPHICS_PIXEL_FORMAT
+#define efi_gop_blt_operation_t EFI_GRAPHICS_OUTPUT_BLT_OPERATION
+
+#endif
+
+typedef struct {
+ uint32_t RedMask;
+ uint32_t GreenMask;
+ uint32_t BlueMask;
+ uint32_t ReservedMask;
+} efi_gop_pixel_bitmask_t;
+
+typedef struct {
+ uint32_t Version;
+ uint32_t HorizontalResolution;
+ uint32_t VerticalResolution;
+ efi_gop_pixel_format_t PixelFormat;
+ efi_gop_pixel_bitmask_t PixelInformation;
+ uint32_t PixelsPerScanLine;
+} efi_gop_mode_info_t;
+
+typedef struct {
+ uint32_t MaxMode;
+ uint32_t Mode;
+ efi_gop_mode_info_t *Information;
+ uintn_t SizeOfInfo;
+ efi_physical_address_t FrameBufferBase;
+ uintn_t FrameBufferSize;
+} efi_gop_mode_t;
+
+typedef efi_status_t (EFIAPI *efi_gop_query_mode_t)(void *This, uint32_t ModeNumber, uintn_t *SizeOfInfo,
+ efi_gop_mode_info_t **Info);
+typedef efi_status_t (EFIAPI *efi_gop_set_mode_t)(void *This, uint32_t ModeNumber);
+typedef efi_status_t (EFIAPI *efi_gop_blt_t)(void *This, uint32_t *BltBuffer, efi_gop_blt_operation_t BltOperation,
+ uintn_t SourceX, uintn_t SourceY, uintn_t DestinationX, uintn_t DestionationY, uintn_t Width, uintn_t Height, uintn_t Delta);
+
+typedef struct {
+ efi_gop_query_mode_t QueryMode;
+ efi_gop_set_mode_t SetMode;
+ efi_gop_blt_t Blt;
+ efi_gop_mode_t *Mode;
+} efi_gop_t;
+
+/*** Simple Pointer Protocol (not used, but could be useful to have) ***/
+#ifndef EFI_SIMPLE_POINTER_PROTOCOL_GUID
+#define EFI_SIMPLE_POINTER_PROTOCOL_GUID { 0x31878c87, 0xb75, 0x11d5, { 0x9a, 0x4f, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }
+#endif
+
+typedef struct {
+ int32_t RelativeMovementX;
+ int32_t RelativeMovementY;
+ int32_t RelativeMovementZ;
+ boolean_t LeftButton;
+ boolean_t RightButton;
+} efi_simple_pointer_state_t;
+
+typedef struct {
+ uint64_t ResolutionX;
+ uint64_t ResolutionY;
+ uint64_t ResolutionZ;
+ boolean_t LeftButton;
+ boolean_t RightButton;
+} efi_simple_pointer_mode_t;
+
+typedef efi_status_t (EFIAPI *efi_simple_pointer_reset_t) (void *This, boolean_t ExtendedVerification);
+typedef efi_status_t (EFIAPI *efi_simple_pointer_get_state_t) (void *This, efi_simple_pointer_state_t *State);
+
+typedef struct {
+ efi_simple_pointer_reset_t Reset;
+ efi_simple_pointer_get_state_t GetState;
+ efi_event_t WaitForInput;
+ efi_simple_pointer_mode_t *Mode;
+} efi_simple_pointer_protocol_t;
+
+/*** Option ROM Protocol (not used, but could be useful to have) ***/
+#ifndef EFI_PCI_OPTION_ROM_TABLE_GUID
+#define EFI_PCI_OPTION_ROM_TABLE_GUID { 0x7462660f, 0x1cbd, 0x48da, {0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c} }
+#endif
+
+typedef struct {
+ efi_physical_address_t RomAddress;
+ efi_memory_type_t MemoryType;
+ uint32_t RomLength;
+ uint32_t Seg;
+ uint8_t Bus;
+ uint8_t Dev;
+ uint8_t Func;
+ boolean_t ExecutedLegacyBiosImage;
+ boolean_t DontLoadEfiRom;
+} efi_pci_option_rom_descriptor_t;
+
+typedef struct {
+ uint64_t PciOptionRomCount;
+ efi_pci_option_rom_descriptor_t *PciOptionRomDescriptors;
+} efi_pci_option_rom_table_t;
+
+/*** GPT partitioning table (not used, but could be useful to have) ***/
+typedef struct {
+ efi_table_header_t Header;
+ efi_lba_t MyLBA;
+ efi_lba_t AlternateLBA;
+ efi_lba_t FirstUsableLBA;
+ efi_lba_t LastUsableLBA;
+ efi_guid_t DiskGUID;
+ efi_lba_t PartitionEntryLBA;
+ uint32_t NumberOfPartitionEntries;
+ uint32_t SizeOfPartitionEntry;
+ uint32_t PartitionEntryArrayCRC32;
+} efi_partition_table_header_t;
+
+typedef struct {
+ efi_guid_t PartitionTypeGUID;
+ efi_guid_t UniquePartitionGUID;
+ efi_lba_t StartingLBA;
+ efi_lba_t EndingLBA;
+ uint64_t Attributes;
+ wchar_t PartitionName[36];
+} efi_partition_entry_t;
+
+/*** POSIX definitions ***/
+#define abs(x) ((x)<0?-(x):(x))
+#define min(x,y) ((x)<(y)?(x):(y))
+#define max(x,y) ((x)>(y)?(x):(y))
+
+/* dirent.h */
+#define IFTODT(mode) (((mode) & 0170000) >> 12)
+#define DTTOIF(dirtype) ((dirtype) << 12)
+#define DT_DIR 4
+#define DT_REG 8
+struct dirent {
+ unsigned short int d_reclen;
+ unsigned char d_type;
+ char_t d_name[FILENAME_MAX];
+};
+typedef struct efi_file_handle_s DIR;
+extern DIR *opendir (const char_t *__name);
+extern struct dirent *readdir (DIR *__dirp);
+extern void rewinddir (DIR *__dirp);
+extern int closedir (DIR *__dirp);
+
+/* errno.h */
+extern int errno;
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+
+/* stdlib.h */
+#define RAND_MAX 2147483647
+typedef int (*__compar_fn_t) (const void *, const void *);
+extern int atoi (const char_t *__nptr);
+extern int64_t atol (const char_t *__nptr);
+extern int64_t strtol (const char_t *__nptr, char_t **__endptr, int __base);
+extern void *malloc (size_t __size);
+extern void *calloc (size_t __nmemb, size_t __size);
+extern void *realloc (void *__ptr, size_t __size);
+extern void free (void *__ptr);
+extern void abort (void);
+extern void exit (int __status);
+/* exit Boot Services function. Returns 0 on success. */
+extern int exit_bs(void);
+extern void *bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size, __compar_fn_t __compar);
+extern void qsort (void *__base, size_t __nmemb, size_t __size, __compar_fn_t __compar);
+extern int mblen (const char *__s, size_t __n);
+extern int mbtowc (wchar_t * __pwc, const char * __s, size_t __n);
+extern int wctomb (char *__s, wchar_t __wchar);
+extern size_t mbstowcs (wchar_t *__pwcs, const char *__s, size_t __n);
+extern size_t wcstombs (char *__s, const wchar_t *__pwcs, size_t __n);
+extern void srand(unsigned int __seed);
+extern int rand(void);
+extern uint8_t *getenv(char_t *name, uintn_t *len);
+extern int setenv(char_t *name, uintn_t len, uint8_t *data);
+
+/* stdio.h */
+#ifndef BUFSIZ
+#define BUFSIZ 8192
+#endif
+#define SEEK_SET 0 /* Seek from beginning of file. */
+#define SEEK_CUR 1 /* Seek from current position. */
+#define SEEK_END 2 /* Seek from end of file. */
+#define stdin (FILE*)ST->ConsoleInHandle
+#define stdout (FILE*)ST->ConsoleOutHandle
+#define stderr (FILE*)ST->ConsoleErrorHandle
+typedef struct efi_file_handle_s FILE;
+extern int fclose (FILE *__stream);
+extern int fflush (FILE *__stream);
+extern int remove (const char_t *__filename);
+extern FILE *fopen (const char_t *__filename, const char_t *__modes);
+extern size_t fread (void *__ptr, size_t __size, size_t __n, FILE *__stream);
+extern size_t fwrite (const void *__ptr, size_t __size, size_t __n, FILE *__s);
+extern int fseek (FILE *__stream, long int __off, int __whence);
+extern long int ftell (FILE *__stream);
+extern int feof (FILE *__stream);
+extern int fprintf (FILE *__stream, const char_t *__format, ...);
+extern int printf (const char_t *__format, ...);
+extern int sprintf (char_t *__s, const char_t *__format, ...);
+extern int vfprintf (FILE *__s, const char_t *__format, __builtin_va_list __arg);
+extern int vprintf (const char_t *__format, __builtin_va_list __arg);
+extern int vsprintf (char_t *__s, const char_t *__format, __builtin_va_list __arg);
+extern int snprintf (char_t *__s, size_t __maxlen, const char_t *__format, ...);
+extern int vsnprintf (char_t *__s, size_t __maxlen, const char_t *__format, __builtin_va_list __arg);
+extern int getchar (void);
+/* non-blocking, only returns UNICODE if there's any key pressed, 0 otherwise */
+extern int getchar_ifany (void);
+extern int putchar (int __c);
+
+/* string.h */
+extern void *memcpy(void *__dest, const void *__src, size_t __n);
+extern void *memmove(void *__dest, const void *__src, size_t __n);
+extern void *memset(void *__s, int __c, size_t __n);
+extern int memcmp(const void *__s1, const void *__s2, size_t __n);
+extern void *memchr(const void *__s, int __c, size_t __n);
+extern void *memrchr(const void *__s, int __c, size_t __n);
+void *memmem(const void *haystack, size_t hl, const void *needle, size_t nl);
+void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl);
+extern char_t *strcpy (char_t *__dest, const char_t *__src);
+extern char_t *strncpy (char_t *__dest, const char_t *__src, size_t __n);
+extern char_t *strcat (char_t *__dest, const char_t *__src);
+extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
+extern int strcmp (const char_t *__s1, const char_t *__s2);
+extern int strncmp (const char_t *__s1, const char_t *__s2, size_t __n);
+extern char_t *strdup (const char_t *__s);
+extern char_t *strchr (const char_t *__s, int __c);
+extern char_t *strrchr (const char_t *__s, int __c);
+extern char_t *strstr (const char_t *__haystack, const char_t *__needle);
+extern char_t *strtok (char_t *__s, const char_t *__delim);
+extern char_t *strtok_r (char_t *__s, const char_t *__delim, char_t **__save_ptr);
+extern size_t strlen (const char_t *__s);
+
+/* sys/stat.h */
+#define S_IREAD 0400 /* Read by owner. */
+#define S_IWRITE 0200 /* Write by owner. */
+#define S_IFMT 0170000 /* These bits determine file type. */
+#define S_IFIFO 0010000 /* FIFO. */
+#define S_IFCHR 0020000 /* Character device. */
+#define S_IFDIR 0040000 /* Directory. */
+#define S_IFBLK 0060000 /* Block device. */
+#define S_IFREG 0100000 /* Regular file. */
+#define S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
+#define S_ISCHR(mode) S_ISTYPE((mode), S_IFCHR)
+#define S_ISDIR(mode) S_ISTYPE((mode), S_IFDIR)
+#define S_ISBLK(mode) S_ISTYPE((mode), S_IFBLK)
+#define S_ISREG(mode) S_ISTYPE((mode), S_IFREG)
+#define S_ISFIFO(mode) S_ISTYPE((mode), S_IFIFO)
+struct stat {
+ mode_t st_mode;
+ off_t st_size;
+ blkcnt_t st_blocks;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+};
+extern int stat (const char_t *__file, struct stat *__buf);
+extern int fstat (FILE *__f, struct stat *__buf);
+extern int mkdir (const char_t *__path, mode_t __mode);
+
+/* time.h */
+struct tm {
+ int tm_sec; /* Seconds. [0-60] (1 leap second) */
+ int tm_min; /* Minutes. [0-59] */
+ int tm_hour; /* Hours. [0-23] */
+ int tm_mday; /* Day. [1-31] */
+ int tm_mon; /* Month. [0-11] */
+ int tm_year; /* Year - 1900. */
+ int tm_wday; /* Day of week. [0-6] (not set) */
+ int tm_yday; /* Days in year.[0-365] (not set) */
+ int tm_isdst; /* DST. [-1/0/1]*/
+};
+extern struct tm *localtime (const time_t *__timer);
+extern time_t mktime(const struct tm *__tm);
+extern time_t time(time_t *__timer);
+
+/* unistd.h */
+extern unsigned int sleep (unsigned int __seconds);
+extern int usleep (unsigned long int __useconds);
+extern int unlink (const wchar_t *__filename);
+extern int rmdir (const wchar_t *__filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEFI_H_ */
diff --git a/libs/posix-uefi/uefi/unistd.c b/libs/posix-uefi/uefi/unistd.c
new file mode 100644
index 0000000..0ea6246
--- /dev/null
+++ b/libs/posix-uefi/uefi/unistd.c
@@ -0,0 +1,55 @@
+/*
+ * unistd.c
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief Implementing functions which are defined in unistd.h
+ *
+ */
+
+#include
+
+int __remove(const wchar_t *__filename, int isdir);
+
+int usleep (unsigned long int __useconds)
+{
+ BS->Stall(__useconds);
+ return 0;
+}
+
+unsigned int sleep (unsigned int __seconds)
+{
+ BS->Stall((unsigned long int)__seconds * 1000000UL);
+ return 0;
+}
+
+int unlink (const wchar_t *__filename)
+{
+ return __remove(__filename, 0);
+}
+
+int rmdir (const wchar_t *__filename)
+{
+ return __remove(__filename, 1);
+}
diff --git a/libs/posix-uefi/utils/OLVASSEL.md b/libs/posix-uefi/utils/OLVASSEL.md
new file mode 100644
index 0000000..b19e1db
--- /dev/null
+++ b/libs/posix-uefi/utils/OLVASSEL.md
@@ -0,0 +1,41 @@
+POSIX-UEFI Segédeszközök
+========================
+
+Ezek kis parancsok, amik besegítenek az UEFI toolchain-edbe (csak libc-t használnak, nincs szükség EFI hedörökre). A POSIX-UEFI
+által lefordított .efi kimeneti fájlokat konvertálják olyan különböző formátumú fájlokká, amiket az UEFI firmware használ.
+
+* __efirom__ - ez PCI Option ROM képet készít
+```
+POSIX-UEFI utils - efirom by Michael Brown GPL
+
+./efirom [--vendor=VVVV] [--device=DDDD] bementifájl kimentifájl
+```
+
+* __efiffs__ - ez DXE UEFI eszközmeghajtó képet készít (bővebb infó [ebben a wikiben](https://github.com/pbatard/efifs/wiki/Adding-a-driver-to-a-UEFI-firmware#adding-the-module-to-the-firmware) található arról, hogy hogyan kell a firmwarehez adni).
+```
+POSIX-UEFI utils - efiffs by bztsrc@gitlab MIT
+
+./efiffs [-g ] [-n ] [-v ] [-t ] [-p ] bemenet [kimenet]
+
+ -g a GUID megadása (alapértelmezetten véletlenszám)
+ -n az eszközmeghajtó neve (pl 'FAT')
+ -v az eszközmeghajtó verziója (pl '1.0')
+ -t az ffs típusa (alapértelmezetten 7, EFI_FV_FILETYPE_DRIVER)
+ -p a pe szekció típusa (alapértelmezetten 16, EFI_SECTION_PE32)
+ bemenet a bemeneti .efi fájl neve
+ kimenet a kimeneti fájl neve (alapértelmezetten a bemeneti névből generált)
+```
+
+* __efidsk__ - indítható lemezképet készít EFI Rendszer Partícióval egy könyvtár tartalmából. A POSIX-EFI-vel lefordított
+programodat `EFI/BOOT/BOOTX64.EFI` néven kell bemásolni a könyvtárba, hogy magától elinduljon.
+```
+POSIX-UEFI utils - efidsk by bztsrc@gitlab MIT
+
+./efidsk [-p|-c] [-s ] bekönyvtár kimenet
+
+ -p csak a partíciót mentse, GPT nélkül
+ -c EFI CDROM mentése (ISO9660 El Torito no emulation boot catalog)
+ -s a partíció méretének megadása megabájtban (alapértelmezetten 33M)
+ bekönvtár ennek a könyvtárnak a tartalmából generálja
+ kimenet kimenti lemezképfájl neve
+```
diff --git a/libs/posix-uefi/utils/README.md b/libs/posix-uefi/utils/README.md
new file mode 100644
index 0000000..f9e9197
--- /dev/null
+++ b/libs/posix-uefi/utils/README.md
@@ -0,0 +1,41 @@
+POSIX-UEFI Utilities
+====================
+
+These are small portable commands to help you with the UEFI toolchain (libc only, no EFI headers needed). They convert the .efi
+output that you've compiled with POSIX-UEFI into different file formats required by the UEFI firmware.
+
+* __efirom__ - creates a PCI Option ROM image
+```
+POSIX-UEFI utils - efirom by Michael Brown GPL
+
+./efirom [--vendor=VVVV] [--device=DDDD] infile outfile
+```
+
+* __efiffs__ - creates a DXE UEFI driver image (see [this wiki](https://github.com/pbatard/efifs/wiki/Adding-a-driver-to-a-UEFI-firmware#adding-the-module-to-the-firmware) on how to add it to a firmware).
+```
+POSIX-UEFI utils - efiffs by bztsrc@gitlab MIT
+
+./efiffs [-g ] [-n ] [-v ] [-t ] [-p ] infile [outfile]
+
+ -g specify the GUID (defaults to random)
+ -n specify the driver's name (eg 'FAT')
+ -v specify the driver's version (eg '1.0')
+ -t specify the ffs type (defaults to 7, EFI_FV_FILETYPE_DRIVER)
+ -p specify the pe section type (defaults to 16, EFI_SECTION_PE32)
+ infile input .efi file
+ outfile output file name (default generated from infile)
+```
+
+* __efidsk__ - creates a bootable disk image with EFI System Partition from the contents of a directory. Copy the POSIX-UEFI
+compiled file under the given directory as `EFI/BOOT/BOOTX64.EFI` to get it automatically booted.
+```
+POSIX-UEFI utils - efidsk by bztsrc@gitlab MIT
+
+./efidsk [-p|-c] [-s ] indir outfile
+
+ -p save only the partition image without GPT
+ -c save EFI CDROM (ISO9660 El Torito no emulation boot catalog)
+ -s set the size of partition in megabytes (defaults to 33M)
+ indir use the contents of this directory
+ outfile output image file name
+```
diff --git a/libs/posix-uefi/utils/efidsk.c b/libs/posix-uefi/utils/efidsk.c
new file mode 100644
index 0000000..9fe8308
--- /dev/null
+++ b/libs/posix-uefi/utils/efidsk.c
@@ -0,0 +1,648 @@
+/*
+ * utils/efidsk.c
+ *
+ * Copyright (C) 2022 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief small tool to create a disk image with EFI System Partition
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef struct {
+ uint32_t Data1;
+ uint16_t Data2;
+ uint16_t Data3;
+ uint8_t Data4[8];
+} __attribute__((packed)) guid_t;
+guid_t dguid, pguid;
+
+/**
+ * Print usage
+ */
+void usage(char *cmd)
+{
+ printf("POSIX-UEFI utils - efidsk by bztsrc@gitlab MIT\r\n\r\n");
+ printf("%s [-p|-c] [-s ] indir outfile\r\n\r\n", cmd);
+ printf(" -p save only the partition image without GPT\r\n");
+ printf(" -c save EFI CDROM (ISO9660 El Torito no emulation boot catalog)\r\n");
+ printf(" -s set the size of partition in megabytes (defaults to 33M)\r\n");
+ printf(" indir use the contents of this directory\r\n");
+ printf(" outfile output image file name\r\n");
+ exit(1);
+}
+
+#define SECTOR_PER_CLUSTER 1
+#define FIRST_PARTITION 2048
+
+struct tm *fat_ts;
+int fs_len = 0, skipbytes = 0, fat_nextcluster, fat_bpc, fat_spf, fat_lfncnt, fat_numclu = 67584;
+unsigned char *fs_base = NULL;
+unsigned char *fat_rootdir, *fat_data, fat_lfn[769];
+uint32_t *fat_fat32_1, *fat_fat32_2;
+
+/**
+ * Add a new cluster
+ */
+unsigned char *fat_newclu(int parent)
+{
+ int clu;
+ while(parent != fat_nextcluster && fat_fat32_1[parent] && fat_fat32_1[parent] != 0xFFFFFFF)
+ parent = fat_fat32_1[parent];
+ fat_fat32_1[parent] = fat_fat32_2[parent] = fat_nextcluster;
+ fat_fat32_1[fat_nextcluster] = fat_fat32_2[fat_nextcluster] = 0xFFFFFFF;
+ clu = fat_nextcluster++;
+ if(fat_nextcluster >= fat_numclu) { fprintf(stderr,"efidsk: not enough space on partition\r\n"); exit(1); }
+ return fat_data + clu * fat_bpc;
+}
+
+/**
+ * Read in file name
+ */
+unsigned char *fat_readlfn(unsigned char *dir, int *clu, int *size, int parent)
+{
+ uint16_t uc2[256], *u;
+ unsigned char *s, *d;
+ int i = 0, n;
+ memset(fat_lfn, 0, sizeof(fat_lfn));
+ if(!dir[0]) return dir;
+ while(dir[0] == '.') dir += 32;
+ fat_lfncnt++;
+ if(parent != 2 && !((uint64_t)(dir - fs_base) & (fat_bpc - 1))) {
+ parent = fat_fat32_1[parent];
+ if(!parent || parent == 0xFFFFFFF) return NULL;
+ dir = fat_data + parent * fat_bpc;
+ }
+ if(dir[0xB] != 0xF) {
+ for(s = dir, d = fat_lfn, i = 0; *s && *s != ' ' && i < 8; i++)
+ *d++ = *s++;
+ if(dir[8] && dir[8] != ' ') {
+ *d++ = '.';
+ for(s = dir + 8; *s != ' ' && i < 3; i++)
+ *d++ = *s++;
+ }
+ } else {
+ memset(uc2, 0, sizeof(uc2));
+ n = dir[0] & 0x3F;
+ u = uc2 + (n - 1) * 13;
+ while(n--) {
+ for(i = 0; i < 5; i++)
+ u[i] = dir[i*2+2] << 8 | dir[i*2+1];
+ for(i = 0; i < 6; i++)
+ u[i+5] = dir[i*2+0xF] << 8 | dir[i*2+0xE];
+ u[11] = dir[0x1D] << 8 | dir[0x1C];
+ u[12] = dir[0x1F] << 8 | dir[0x1E];
+ u -= 13;
+ dir += 32;
+ if(!((uint64_t)(dir - fs_base) & (fat_bpc - 1))) {
+ parent = fat_fat32_1[parent];
+ if(!parent || parent == 0xFFFFFFF) return NULL;
+ dir = fat_data + parent * fat_bpc;
+ }
+ }
+ for(d = fat_lfn, u = uc2; *u; u++)
+ if(*u < 0x80) {
+ *d++ = *u;
+ } else if(*u < 0x800) {
+ *d++ = ((*u>>6)&0x1F)|0xC0;
+ *d++ = (*u&0x3F)|0x80;
+ } else {
+ *d++ = ((*u>>12)&0x0F)|0xE0;
+ *d++ = ((*u>>6)&0x3F)|0x80;
+ *d++ = (*u&0x3F)|0x80;
+ }
+ }
+ *clu = (dir[0x15] << 24) | (dir[0x14] << 16) | (dir[0x1B] << 8) | dir[0x1A];
+ *size = (dir[0x1F] << 24) | (dir[0x1E] << 16) | (dir[0x1D] << 8) | dir[0x1C];
+ return dir + 32;
+}
+
+/**
+ * Write file name
+ */
+unsigned char *fat_writelfn(unsigned char *dir, char *name, int type, int size, int parent, int clu)
+{
+ uint16_t uc2[256], *u;
+ unsigned char *s, c = 0, sfn[12];
+ int i, n;
+ if(name[0] == '.') {
+ memset(dir, ' ', 11);
+ memcpy(dir, name, strlen(name));
+ } else {
+ memset(uc2, 0, sizeof(uc2));
+ for(n = 0, u = uc2, s = (unsigned char*)name; *s; n++, u++) {
+ if((*s & 128) != 0) {
+ if((*s & 32) == 0) { *u = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s += 2; } else
+ if((*s & 16) == 0) { *u = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 3; }
+ else { fprintf(stderr,"efidsk: unable to encode file name '%s'\r\n", name); exit(1); }
+ } else
+ *u = *s++;
+ }
+ /* don't convert "Microsoft" to "MICROS~1 ", that's patented... */
+ sprintf((char*)sfn, "~%07xLFN", fat_lfncnt++);
+ for(i = 0; i < 11; i++)
+ c = (((c & 1) << 7) | ((c & 0xfe) >> 1)) + sfn[i];
+ n = (n + 12) / 13;
+ u = uc2 + (n - 1) * 13;
+ i = 0x40;
+ while(n--) {
+ if(parent > 2 && !((uint64_t)(dir - fs_base) & (fat_bpc - 1)))
+ dir = fat_newclu(parent);
+ dir[0] = i | (n + 1);
+ dir[11] = 0xF;
+ dir[0xD] = c;
+ memcpy(dir + 1, (unsigned char*)u, 10);
+ memcpy(dir + 14, (unsigned char*)u + 10, 12);
+ memcpy(dir + 28, (unsigned char*)u + 22, 4);
+ i = 0;
+ u -= 13;
+ dir += 32;
+ }
+ if(parent > 2 && !((uint64_t)(dir - fs_base) & (fat_bpc - 1)))
+ dir = fat_newclu(parent);
+ memcpy(dir, sfn, 11);
+ }
+ if(type) {
+ dir[0xB] = 0x10;
+ } else {
+ dir[0x1C] = size & 0xFF; dir[0x1D] = (size >> 8) & 0xFF;
+ dir[0x1E] = (size >> 16) & 0xFF; dir[0x1F] = (size >> 24) & 0xFF;
+ }
+ if(!clu) clu = size > 0 || type ? fat_nextcluster : 0;
+ if(clu < 3) clu = 0;
+ dir[0x1A] = clu & 0xFF; dir[0x1B] = (clu >> 8) & 0xFF;
+ dir[0x14] = (clu >> 16) & 0xFF; dir[0x15] = (clu >> 24) & 0xFF;
+ i = (fat_ts->tm_hour << 11) | (fat_ts->tm_min << 5) | (fat_ts->tm_sec/2);
+ dir[0xE] = dir[0x16] = i & 0xFF; dir[0xF] = dir[0x17] = (i >> 8) & 0xFF;
+ i = ((fat_ts->tm_year+1900-1980) << 9) | ((fat_ts->tm_mon+1) << 5) | (fat_ts->tm_mday);
+ return dir + 32;
+}
+
+/**
+ * Create a fat file system
+ */
+void fat_open(int start)
+{
+ int i;
+
+ if(fat_numclu < 67584) { fprintf(stderr,"efidsk: not enough clusters\r\n"); exit(1); }
+ /* "format" the partition to FAT32 */
+ fs_len = fat_numclu * 512 * SECTOR_PER_CLUSTER;
+ fs_base = realloc(fs_base, fs_len);
+ if(!fs_base) { fprintf(stderr,"efidsk: unable to allocate memory\r\n"); exit(1); }
+ memset(fs_base, 0, fs_len);
+ memcpy(fs_base + 3, "MSWIN4.1", 8);
+ fs_base[0xC] = 2; fs_base[0x10] = 2; fs_base[0x15] = 0xF8; fs_base[0x1FE] = 0x55; fs_base[0x1FF] = 0xAA;
+ fs_base[0x18] = 0x20; fs_base[0x1A] = 0x40;
+ memcpy(fs_base + 0x1C, &start, 4);
+ memcpy(fs_base + 0x20, &fat_numclu, 4);
+ fat_spf = (fat_numclu*4) / 512;
+ fs_base[0xD] = SECTOR_PER_CLUSTER; fs_base[0xE] = 8;
+ fs_base[0x24] = fat_spf & 0xFF; fs_base[0x25] = (fat_spf >> 8) & 0xFF;
+ fs_base[0x26] = (fat_spf >> 16) & 0xFF; fs_base[0x27] = (fat_spf >> 24) & 0xFF;
+ fs_base[0x2C] = 2; fs_base[0x30] = 1; fs_base[0x32] = 6; fs_base[0x40] = 0x80; fs_base[0x42] = 0x29;
+ memcpy(fs_base + 0x43, &pguid, 4);
+ memcpy(fs_base + 0x47, "EFI System FAT32 ", 19);
+ memcpy(fs_base + 0x200, "RRaA", 4); memcpy(fs_base + 0x3E4, "rrAa", 4);
+ for(i = 0; i < 8; i++) fs_base[0x3E8 + i] = 0xFF;
+ fs_base[0x3FE] = 0x55; fs_base[0x3FF] = 0xAA;
+ fat_bpc = fs_base[0xD] * 512;
+ fat_rootdir = fs_base + (fat_spf*fs_base[0x10]+fs_base[0xE]) * 512;
+ fat_data = fat_rootdir - 2*fat_bpc;
+ fat_fat32_1 = (uint32_t*)(&fs_base[fs_base[0xE] * 512]);
+ fat_fat32_2 = (uint32_t*)(&fs_base[(fs_base[0xE]+fat_spf) * 512]);
+ fat_fat32_1[0] = fat_fat32_2[0] = fat_fat32_1[2] = fat_fat32_2[2] = 0x0FFFFFF8;
+ fat_fat32_1[1] = fat_fat32_2[1] = 0x0FFFFFFF;
+ fat_nextcluster = 3;
+}
+
+/**
+ * Add a file to the file system
+ */
+void fat_add(struct stat *st, char *name, unsigned char *content, int size)
+{
+ int parent = 2, clu, i, j;
+ unsigned char *dir = fat_rootdir;
+ char *end, *fn = strrchr(name, '/');
+ if(!fn) fn = name; else fn++;
+ if(!strcmp(fn, ".") || !strcmp(fn, "..")) return;
+ if(!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) return;
+ fat_ts = gmtime(&st->st_mtime);
+ fn = name;
+ end = strchr(name, '/');
+ if(!end) end = name + strlen(name);
+ fat_lfncnt = 1;
+ do {
+ dir = fat_readlfn(dir, &clu, &j, parent);
+ if(!dir) return;
+ if(!memcmp(fat_lfn, fn, end - fn) && !fat_lfn[end - fn]) {
+ fat_lfncnt = 1;
+ parent = clu;
+ dir = fat_data + parent * fat_bpc + 64;
+ fn = end + 1;
+ end = *end ? strchr(fn, '/') : NULL;
+ if(!end) { end = fn + strlen(fn); break; }
+ }
+ } while(dir[0]);
+ dir = fat_writelfn(dir, fn, S_ISDIR(st->st_mode), size, parent, 0);
+ if(S_ISDIR(st->st_mode)) {
+ dir = fat_newclu(fat_nextcluster);
+ dir = fat_writelfn(dir, ".", 1, 0, 2, fat_nextcluster - 1);
+ dir = fat_writelfn(dir, "..", 1, 0, 2, parent);
+ } else if(content && size > 0) {
+ if(fat_nextcluster * fat_bpc + size >= fs_len) {
+ fprintf(stderr,"efidsk: not enough space on partition\r\n");
+ exit(1);
+ }
+ memcpy(fat_data + fat_nextcluster * fat_bpc, content, size);
+ for(i = 0; i < ((size + fat_bpc-1) & ~(fat_bpc-1)); i += fat_bpc, fat_nextcluster++) {
+ fat_fat32_1[fat_nextcluster] = fat_fat32_2[fat_nextcluster] = fat_nextcluster+1;
+ }
+ fat_fat32_1[fat_nextcluster-1] = fat_fat32_2[fat_nextcluster-1] = 0xFFFFFFF;
+ }
+}
+
+/**
+ * Close the file system
+ */
+void fat_close()
+{
+ int i;
+ if(!fs_base || fs_len < 512) return;
+ fat_nextcluster -= 2;
+ i = ((fs_len - (fat_spf*fs_base[0x10]+fs_base[0xE]) * 512)/fat_bpc) - fat_nextcluster;
+ fs_base[0x3E8] = i & 0xFF; fs_base[0x3E9] = (i >> 8) & 0xFF;
+ fs_base[0x3EA] = (i >> 16) & 0xFF; fs_base[0x3EB] = (i >> 24) & 0xFF;
+ fs_base[0x3EC] = fat_nextcluster & 0xFF; fs_base[0x3ED] = (fat_nextcluster >> 8) & 0xFF;
+ fs_base[0x3EE] = (fat_nextcluster >> 16) & 0xFF; fs_base[0x3EF] = (fat_nextcluster >> 24) & 0xFF;
+ /* copy backup boot sectors */
+ memcpy(fs_base + (fs_base[0x32]*512), fs_base, 1024);
+}
+
+/**
+ * Read a file entirely into memory
+ */
+long int read_size;
+unsigned char* readfileall(char *file)
+{
+ unsigned char *data=NULL;
+ FILE *f;
+ read_size = 0;
+ if(!file || !*file) return NULL;
+ f = fopen(file,"r");
+ if(f) {
+ fseek(f, 0L, SEEK_END);
+ read_size = (long int)ftell(f);
+ fseek(f, 0L, SEEK_SET);
+ data = (unsigned char*)malloc(read_size + 1);
+ if(!data) { fprintf(stderr, "efidsk: unable to allocate memory\r\n"); exit(1); }
+ memset(data, 0, read_size + 1);
+ fread(data, read_size, 1, f);
+ data[read_size] = 0;
+ fclose(f);
+ }
+ return data;
+}
+
+/**
+ * Recursively parse a directory
+ */
+void parsedir(char *directory, int parent)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char full[8192];
+ unsigned char *tmp;
+ struct stat st;
+
+ if(!parent && !skipbytes) skipbytes = strlen(directory) + 1;
+
+ if ((dir = opendir(directory)) != NULL) {
+ while ((ent = readdir(dir)) != NULL) {
+ if(!parent && (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))) continue;
+ full[0] = 0;
+ strncat(full, directory, sizeof(full)-1);
+ strncat(full, "/", sizeof(full)-1);
+ strncat(full, ent->d_name, sizeof(full)-1);
+ if(stat(full, &st)) continue;
+ read_size = 0;
+ if(S_ISDIR(st.st_mode)) {
+ fat_add(&st, full + skipbytes, NULL, 0);
+ if(strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
+ parsedir(full, parent+1);
+ } else
+ if(S_ISREG(st.st_mode)) {
+ tmp = readfileall(full);
+ fat_add(&st, full + skipbytes, tmp, read_size);
+ if(tmp) free(tmp);
+ }
+ }
+ closedir(dir);
+ }
+}
+
+/**
+ * CRC calculation with precalculated lookup table
+ */
+uint32_t crc32_lookup[256]={
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
+ 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
+ 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
+ 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
+ 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
+ 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
+ 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
+ 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
+ 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
+ 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
+ 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
+ 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+uint32_t crc32_calc(unsigned char *start,int length)
+{
+ uint32_t crc32_val=0xffffffff;
+ while(length--) crc32_val=(crc32_val>>8)^crc32_lookup[(crc32_val&0xff)^(unsigned char)*start++];
+ crc32_val^=0xffffffff;
+ return crc32_val;
+}
+
+/**
+ * Write out GUID Partitioning Table
+ */
+void setint(int val, unsigned char *ptr) { memcpy(ptr,&val,4); }
+void writegpt(FILE *f)
+{
+ guid_t efiguid = { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA,0x4B,0x00,0xA0,0xC9,0x3E,0xC9,0x3B} };
+ int i;
+ unsigned char *gpt = malloc(FIRST_PARTITION * 512), gpt2[512], *p;
+ char *name;
+ if(!gpt) { fprintf(stderr, "efidsk: unable to allocate memory\r\n"); exit(1); }
+ memset(gpt, 0, FIRST_PARTITION * 512);
+
+ gpt[0x1FE]=0x55; gpt[0x1FF]=0xAA;
+ memcpy(gpt+0x1B8, &dguid.Data1, 4); /* WinNT disk id */
+ /* MBR, EFI System Partition / boot partition. */
+ gpt[0x1C0-2]=0x80; /* bootable flag */
+ setint(FIRST_PARTITION+1,gpt+0x1C0); /* start CHS */
+ gpt[0x1C0+2]=0xC; /* type, LBA FAT32 (0xC) */
+ setint(fs_len/512,gpt+0x1C0+4); /* end CHS */
+ setint(FIRST_PARTITION,gpt+0x1C0+6); /* start LBA */
+ setint(fs_len/512,gpt+0x1C0+10); /* number of sectors */
+ /* MBR, protective GPT entry */
+ setint(1,gpt+0x1D0); /* start CHS */
+ gpt[0x1D0+2]=0xEE; /* type */
+ setint(FIRST_PARTITION+1,gpt+0x1D0+4); /* end CHS */
+ setint(1,gpt+0x1D0+6); /* start LBA */
+ setint(FIRST_PARTITION,gpt+0x1D0+10); /* number of sectors */
+
+ /* GPT header */
+ p = gpt + 512;
+ memcpy(p,"EFI PART",8); /* magic */
+ setint(1,p+10); /* revision */
+ setint(92,p+12); /* size */
+ setint(1,p+24); /* primary LBA */
+ setint(2*FIRST_PARTITION+fat_numclu-2,p+32);/* secondary LBA */
+ setint(FIRST_PARTITION,p+40); /* first usable LBA */
+ setint(FIRST_PARTITION+fat_numclu,p+48); /* last usable LBA */
+ memcpy(p+56,&dguid,sizeof(guid_t)); /* disk UUID */
+ setint(2,p+72); /* partitioning table LBA */
+ setint((FIRST_PARTITION-2)*512/128,p+80); /* number of entries */
+ setint(128,p+84); /* size of one entry */
+ p += 512;
+
+ /* GPT, EFI System Partition (ESP) */
+ memcpy(p, &efiguid, sizeof(guid_t)); /* entry type */
+ memcpy(p+16, &pguid, sizeof(guid_t)); /* partition UUID */
+ setint(FIRST_PARTITION,p+32); /* start LBA */
+ setint(FIRST_PARTITION+fat_numclu-1,p+40); /* end LBA */
+ name = "EFI System Partition"; /* name */
+ for(i = 0; name[i]; i++) p[56+i*2] = name[i];
+ p += 128;
+
+ /* calculate checksums */
+ setint(crc32_calc(gpt+1024,((gpt[512+81]<<8)|gpt[512+80])*128),gpt+512+88);
+ setint(crc32_calc(gpt+512,92),gpt+512+16);
+ memcpy(gpt2, gpt+512, 512);
+ setint(1,gpt2+32); /* secondary lba */
+ setint(2*FIRST_PARTITION+fat_numclu-2,gpt2+24); /* primary lba */
+ setint(FIRST_PARTITION+fat_numclu,gpt2+72); /* partition lba */
+ setint(0,gpt2+16); /* calculate with zero */
+ setint(crc32_calc(gpt2,92),gpt2+16);
+
+ fwrite(gpt, 1, FIRST_PARTITION * 512, f);
+ fwrite(fs_base, 1, fs_len, f);
+ fwrite(gpt + 1024, 1, (FIRST_PARTITION - 2) * 512, f);
+ fwrite(gpt2, 1, 512, f);
+ free(gpt);
+}
+
+/**
+ * Write out ISO9660 El Torito "no emulation" Boot Catalog
+ */
+void setinte(int val, unsigned char *ptr) { char *v=(char*)&val; memcpy(ptr,&val,4); ptr[4]=v[3]; ptr[5]=v[2]; ptr[6]=v[1]; ptr[7]=v[0]; }
+void writeetbc(FILE *f)
+{
+ int i;
+ time_t t;
+ char isodate[128];
+ unsigned char *gpt = malloc(FIRST_PARTITION * 512), *iso;
+ if(!gpt) { fprintf(stderr, "efidsk: unable to allocate memory\r\n"); exit(1); }
+ memset(gpt, 0, FIRST_PARTITION * 512);
+
+ t = time(NULL);
+ fat_ts = gmtime(&t);
+ sprintf((char*)&isodate, "%04d%02d%02d%02d%02d%02d00",
+ fat_ts->tm_year+1900,fat_ts->tm_mon+1,fat_ts->tm_mday,fat_ts->tm_hour,fat_ts->tm_min,fat_ts->tm_sec);
+ iso = gpt + 16*2048;
+ /* 16th sector: Primary Volume Descriptor */
+ iso[0]=1; /* Header ID */
+ memcpy(&iso[1], "CD001", 5);
+ iso[6]=1; /* version */
+ for(i=8;i<72;i++) iso[i]=' ';
+ memcpy(&iso[40], "EFI CDROM", 9); /* Volume Identifier */
+ setinte((FIRST_PARTITION*512+fs_len+2047)/2048, &iso[80]);
+ iso[120]=iso[123]=1; /* Volume Set Size */
+ iso[124]=iso[127]=1; /* Volume Sequence Number */
+ iso[129]=iso[130]=8; /* logical blocksize (0x800) */
+ iso[156]=0x22; /* root directory recordsize */
+ setinte(20, &iso[158]); /* root directory LBA */
+ setinte(2048, &iso[166]); /* root directory size */
+ iso[174]=fat_ts->tm_year; /* root directory create date */
+ iso[175]=fat_ts->tm_mon+1;
+ iso[176]=fat_ts->tm_mday;
+ iso[177]=fat_ts->tm_hour;
+ iso[178]=fat_ts->tm_min;
+ iso[179]=fat_ts->tm_sec;
+ iso[180]=0; /* timezone UTC (GMT) */
+ iso[181]=2; /* root directory flags (0=hidden,1=directory) */
+ iso[184]=1; /* root directory number */
+ iso[188]=1; /* root directory filename length */
+ for(i=190;i<813;i++) iso[i]=' '; /* Volume data */
+ memcpy(&iso[318], "POSIX-UEFI ", 49);
+ memcpy(&iso[446], "EFIDSK", 6);
+ memcpy(&iso[574], "POSIX-UEFI", 11);
+ for(i=702;i<813;i++) iso[i]=' '; /* file descriptors */
+ memcpy(&iso[813], &isodate, 16); /* volume create date */
+ memcpy(&iso[830], &isodate, 16); /* volume modify date */
+ for(i=847;i<863;i++) iso[i]='0'; /* volume expiration date */
+ for(i=864;i<880;i++) iso[i]='0'; /* volume shown date */
+ iso[881]=1; /* filestructure version */
+ for(i=883;i<1395;i++) iso[i]=' '; /* file descriptors */
+ /* 17th sector: Boot Record Descriptor */
+ iso[2048]=0; /* Header ID */
+ memcpy(&iso[2049], "CD001", 5);
+ iso[2054]=1; /* version */
+ memcpy(&iso[2055], "EL TORITO SPECIFICATION", 23);
+ setinte(19, &iso[2048+71]); /* Boot Catalog LBA */
+ /* 18th sector: Volume Descritor Terminator */
+ iso[4096]=0xFF; /* Header ID */
+ memcpy(&iso[4097], "CD001", 5);
+ iso[4102]=1; /* version */
+ /* 19th sector: Boot Catalog */
+ /* --- UEFI, Validation Entry + Initial/Default Entry + Final --- */
+ iso[6144]=0x91; /* Header ID, Validation Entry, Final */
+ iso[6145]=0xEF; /* Platform EFI */
+ iso[6176]=0x88; /* Bootable, Initial/Default Entry */
+ iso[6182]=1; /* Sector Count */
+ setint(FIRST_PARTITION/4, &iso[6184]); /* ESP Start LBA */
+ /* 20th sector: Root Directory */
+ /* . */
+ iso[8192]=0x21 + 1; /* recordsize */
+ setinte(20, &iso[8194]); /* LBA */
+ setinte(2048, &iso[8202]); /* size */
+ iso[8210]=fat_ts->tm_year; /* date */
+ iso[8211]=fat_ts->tm_mon+1;
+ iso[8212]=fat_ts->tm_mday;
+ iso[8213]=fat_ts->tm_hour;
+ iso[8214]=fat_ts->tm_min;
+ iso[8215]=fat_ts->tm_sec;
+ iso[8216]=0; /* timezone UTC (GMT) */
+ iso[8217]=2; /* flags (0=hidden,1=directory) */
+ iso[8220]=1; /* serial */
+ iso[8224]=1; /* filename length */
+ iso[8225]=0; /* filename '.' */
+ /* .. */
+ iso[8226]=0x21 + 1; /* recordsize */
+ setinte(20, &iso[8228]); /* LBA */
+ setinte(2048, &iso[8236]); /* size */
+ iso[8244]=fat_ts->tm_year; /* date */
+ iso[8245]=fat_ts->tm_mon+1;
+ iso[8246]=fat_ts->tm_mday;
+ iso[8247]=fat_ts->tm_hour;
+ iso[8248]=fat_ts->tm_min;
+ iso[8249]=fat_ts->tm_sec;
+ iso[8250]=0; /* timezone UTC (GMT) */
+ iso[8251]=2; /* flags (0=hidden,1=directory) */
+ iso[8254]=1; /* serial */
+ iso[8258]=1; /* filename length */
+ iso[8259]='\001'; /* filename '..' */
+
+ fwrite(gpt, 1, FIRST_PARTITION * 512, f);
+ fwrite(fs_base, 1, fs_len, f);
+ free(gpt);
+}
+
+/**
+ * Main function
+ */
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int i, part = 0, cdrom = 0;
+ char *in = NULL, *out = NULL;
+
+ /* get random GUIDs */
+ srand(time(NULL));
+ i = rand(); memcpy(&((uint8_t*)&dguid)[0], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&dguid)[4], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&dguid)[8], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&dguid)[12], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&pguid)[0], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&pguid)[4], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&pguid)[8], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&pguid)[12], &i, 4);
+
+ /* parse command line */
+ for(i = 1; i < argc && argv[i]; i++)
+ if(argv[i][0] == '-') {
+ switch(argv[i][1]) {
+ case 'p': part++; break;
+ case 'c': cdrom++; break;
+ case 's': fat_numclu = atoi(argv[++i]) * 2048; break;
+ default: usage(argv[0]); break;
+ }
+ } else
+ if(!in) in = argv[i]; else
+ if(!out) out = argv[i]; else
+ usage(argv[0]);
+ if(!out) usage(argv[0]);
+
+ /* generate file system image */
+ remove(out);
+ fat_open(part ? 0 : FIRST_PARTITION);
+ parsedir(in, 0);
+ fat_close();
+
+ /* write out image */
+ if(fs_base) {
+ f = fopen(out, "wb");
+ if(!f) {
+ fprintf(stderr, "efidsk: unable to write '%s'\r\n", out);
+ return 2;
+ }
+ if(!part) {
+ if(!cdrom)
+ writegpt(f);
+ else
+ writeetbc(f);
+ } else
+ fwrite(fs_base, 1, fs_len, f);
+ fclose(f);
+ free(fs_base);
+ }
+
+ return 0;
+}
diff --git a/libs/posix-uefi/utils/efiffs.c b/libs/posix-uefi/utils/efiffs.c
new file mode 100644
index 0000000..5fcb8ab
--- /dev/null
+++ b/libs/posix-uefi/utils/efiffs.c
@@ -0,0 +1,269 @@
+/*
+ * utils/efiffs.c
+ *
+ * Copyright (C) 2022 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief small tool to convert an .efi file to an .ffs file
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+typedef struct {
+ uint32_t Data1;
+ uint16_t Data2;
+ uint16_t Data3;
+ uint8_t Data4[8];
+} __attribute__((packed)) guid_t;
+
+/**
+ * Print usage
+ */
+void usage(char *cmd)
+{
+ printf("POSIX-UEFI utils - efiffs by bztsrc@gitlab MIT\r\n\r\n");
+ printf("%s [-g ] [-n ] [-v ] [-t ] [-p ] infile [outfile]\r\n\r\n", cmd);
+ printf(" -g specify the GUID (defaults to random)\r\n");
+ printf(" -n specify the driver's name (eg 'FAT')\r\n");
+ printf(" -v specify the driver's version (eg '1.0')\r\n");
+ printf(" -t specify the ffs type (defaults to 7, EFI_FV_FILETYPE_DRIVER)\r\n");
+ printf(" -p specify the pe section type (defaults to 16, EFI_SECTION_PE32)\r\n");
+ printf(" infile input .efi file\r\n");
+ printf(" outfile output file name (default generated from infile)\r\n");
+ exit(1);
+}
+
+/**
+ * Convert hex string into integer
+ */
+unsigned int gethex(char *ptr, int len)
+{
+ unsigned int ret = 0;
+ for(;len--;ptr++) {
+ if(*ptr>='0' && *ptr<='9') { ret <<= 4; ret += (unsigned int)(*ptr-'0'); }
+ else if(*ptr >= 'a' && *ptr <= 'f') { ret <<= 4; ret += (unsigned int)(*ptr-'a'+10); }
+ else if(*ptr >= 'A' && *ptr <= 'F') { ret <<= 4; ret += (unsigned int)(*ptr-'A'+10); }
+ else break;
+ }
+ return ret;
+}
+
+/**
+ * Parse a GUID in string into binary representation
+ */
+void getguid(char *ptr, guid_t *guid)
+{
+ int i;
+
+ if(!ptr || !*ptr || ptr[8] != '-' || ptr[13] != '-' || ptr[18] != '-') {
+ fprintf(stderr, "efiffs: bad GUID format\r\n");
+ return;
+ }
+ guid->Data1 = gethex(ptr, 8); ptr += 9;
+ guid->Data2 = gethex(ptr, 4); ptr += 5;
+ guid->Data3 = gethex(ptr, 4); ptr += 5;
+ guid->Data4[0] = gethex(ptr, 2); ptr += 2;
+ guid->Data4[1] = gethex(ptr, 2); ptr += 2; if(*ptr == '-') ptr++;
+ for(i = 2; i < 8; i++, ptr += 2) guid->Data4[i] = gethex(ptr, 2);
+}
+
+/**
+ * Parse ffs type
+ */
+int gettype(char *str)
+{
+ static const char *types[] = {
+ NULL, "RAW", "FREEFORM", "SECURITY_CORE", "PEI_CORE", "DXE_CORE", "PEIM", "DRIVER", "COMBINED_PEIM_DRIVER",
+ "APPLICATION", "SMM", "FIRMWARE_VOLUME_IMAGE", "COMBINED_SMM_DXE", "SMM_CORE", NULL };
+ int i;
+
+ i = atoi(str);
+ if(i > 0 && i < (int)(sizeof(types)/sizeof(types[0]))) return i;
+
+ if(!memcmp(str, "EFI_FV_FILETYPE_", 16)) str += 16;
+ for(i = 1; types[i] && strcmp(str, types[i]); i++);
+ if(!types[i]) {
+ fprintf(stderr, "efiffs: invalid ffs type, available values:\r\n");
+ for(i = 1; types[i]; i++)
+ fprintf(stderr, " EFI_FV_FILETYPE_%s\r\n", types[i]);
+ return 7; /* EFI_FV_FILETYPE_DRIVER */
+ }
+ return i;
+}
+
+/**
+ * Parse section type
+ */
+int getsec(char *str)
+{
+ static const char *types[] = {
+ "PE32", "PIC", "TE", "DXE_DEPEX", "VERSION", "USER_INTERFACE", "COMPATIBILITY16",
+ "FIRMWARE_VOLUME_IMAGE", "FREEFORM_SUBTYPE_GUID", "RAW", "RESERVED", "PEI_DEPEX", "SMM_DEPEX", NULL };
+ int i;
+
+ i = atoi(str);
+ if(i == 1 || i == 2 || i >= 16) return i;
+
+ if(!memcmp(str, "EFI_SECTION_", 12)) str += 12;
+ if(!strcmp(str, "COMPRESSION")) return 1;
+ if(!strcmp(str, "GUID_DEFINED")) return 2;
+ for(i = 0; types[i] && strcmp(str, types[i]); i++);
+ if(!types[i]) {
+ fprintf(stderr, "efiffs: invalid section type, available values:\r\n");
+ fprintf(stderr, " EFI_SECTION_COMPRESSION\r\n EFI_SECTION_GUID_DEFINED\r\n");
+ for(i = 0; types[i]; i++)
+ fprintf(stderr, " EFI_SECTION_%s\r\n", types[i]);
+ return 16; /* EFI_SECTION_PE32 */
+ }
+ return i + 16;
+}
+
+/**
+ * Calculate checksum
+ */
+uint8_t checksum8(uint8_t *buff, int len)
+{
+ uint8_t ret = 0;
+ int i;
+
+ for(i = 0; i < len; i++)
+ ret = (uint8_t)(ret + buff[i]);
+ return (uint8_t)(0x100 - ret);
+}
+
+/**
+ * Main function
+ */
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int i, size, len;
+ int filetype = 7; /* EFI_FV_FILETYPE_DRIVER */
+ int sectype = 16; /* EFI_SECTION_PE32 */
+ char *in = NULL, *out = NULL, *name = NULL, *ver = NULL;
+ uint8_t *buff = NULL, *sec = NULL;
+ guid_t guid;
+
+ /* get a random GUID */
+ srand(time(NULL));
+ i = rand(); memcpy(&((uint8_t*)&guid)[0], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&guid)[4], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&guid)[8], &i, 4);
+ i = rand(); memcpy(&((uint8_t*)&guid)[12], &i, 4);
+
+ /* parse command line */
+ for(i = 1; i < argc && argv[i]; i++)
+ if(argv[i][0] == '-') {
+ switch(argv[i][1]) {
+ case 'g': getguid(argv[++i], &guid); break;
+ case 'n': name = argv[++i]; break;
+ case 'v': ver = argv[++i]; break;
+ case 't': filetype = gettype(argv[++i]); break;
+ case 'p': sectype = getsec(argv[++i]); break;
+ default: usage(argv[0]); break;
+ }
+ } else
+ if(!in) in = argv[i]; else
+ if(!out) out = argv[i]; else
+ usage(argv[0]);
+ if(!in) usage(argv[0]);
+
+ /* get input data */
+ f = fopen(in, "rb");
+ if(!f) {
+ fprintf(stderr, "efiffs: unable to read '%s'\r\n", in);
+ return 2;
+ }
+ fseek(f, 0L, SEEK_END);
+ size = (int)ftell(f);
+ fseek(f, 0L, SEEK_SET);
+ len = 24 + 12 + 4 + size + (name ? 6 + 2 * strlen(name) : 0) + (ver ? 6 + 2 * strlen(ver) : 0);
+ buff = (uint8_t*)malloc(len);
+ if(!buff) { fprintf(stderr, "efiffs: unable to allocate memory\r\n"); return 2; }
+ memset(buff, 0, len);
+ sec = buff + 24;
+ /* add the PE section */
+ sec[0] = size & 0xff;
+ sec[1] = (size >> 8) & 0xff;
+ sec[2] = (size >> 16) & 0xff;
+ sec[3] = sectype;
+ fread(sec + 4, 1, size, f);
+ fclose(f);
+ sec += 4 + ((size + 3) & ~3);
+ /* add the name section */
+ if(name) {
+ size = 6 + 2 * strlen(name);
+ sec[0] = size & 0xff;
+ sec[1] = (size >> 8) & 0xff;
+ sec[2] = (size >> 16) & 0xff;
+ sec[3] = 0x15; /* EFI_SECTION_USER_INTERFACE */
+ for(i = 0; name[i]; i++)
+ sec[4 + 2 * i] = name[i];
+ sec += ((size + 3) & ~3);
+ }
+ /* add the version section */
+ if(ver) {
+ size = 6 + 2 * strlen(ver);
+ sec[0] = size & 0xff;
+ sec[1] = (size >> 8) & 0xff;
+ sec[2] = (size >> 16) & 0xff;
+ sec[3] = 0x14; /* EFI_SECTION_VERSION */
+ for(i = 0; ver[i]; i++)
+ sec[4 + 2 * i] = ver[i];
+ sec += ((size + 3) & ~3);
+ }
+
+ /* calculate ffs header fields */
+ len = (int)((uintptr_t)sec - (uintptr_t)buff);
+ memcpy(buff, &guid, 16);
+ buff[0x12] = filetype;
+ buff[0x14] = len & 0xff;
+ buff[0x15] = (len >> 8) & 0xff;
+ buff[0x16] = (len >> 16) & 0xff;
+ buff[0x11] = 0xAA;
+ buff[0x10] = checksum8(buff, 24);
+
+ /* write out image */
+ if(!out) {
+ i = strlen(in);
+ out = (char*)malloc(i + 5);
+ if(!out) { fprintf(stderr, "efiffs: unable to allocate memory\r\n"); return 2; }
+ strcpy(out, in);
+ strcpy(!strcmp(out + i - 4, ".efi") ? out + i - 4 : out + i, ".ffs");
+ }
+ f = fopen(out, "wb");
+ if(!f) {
+ fprintf(stderr, "efiffs: unable to write '%s'\r\n", out);
+ return 2;
+ }
+ fwrite(buff, 1, len, f);
+ fclose(f);
+
+ free(buff);
+ return 0;
+}
diff --git a/libs/posix-uefi/utils/efirom.c b/libs/posix-uefi/utils/efirom.c
new file mode 100644
index 0000000..cef1e5f
--- /dev/null
+++ b/libs/posix-uefi/utils/efirom.c
@@ -0,0 +1,1258 @@
+/*
+ * utils/efirom.c
+ *
+ * Copyright (C) 2009 Michael Brown .
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * modifications for gnuefi by bzt (bztsrc@gitlab)
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief small tool to convert an .efi file to a .rom file
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
+/**
+ * Print help
+ *
+ * @v program_name Program name
+ */
+static void print_help ( const char *program_name ) {
+ eprintf ( "POSIX-UEFI utils - efirom by Michael Brown GPL\r\n\r\n" );
+ eprintf ( "%s [--vendor=VVVV] [--device=DDDD] "
+ "infile outfile\n", program_name );
+}
+
+#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+typedef uint64_t UINTN;
+typedef UINTN EFI_TPL;
+
+typedef struct _EFI_DEVICE_PATH_PROTOCOL {
+ uint8_t Type;
+ uint8_t SubType;
+ uint8_t Length[2];
+} EFI_DEVICE_PATH_PROTOCOL;
+
+typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH;
+typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH;
+
+#ifndef _EFI_LINK_H
+#define _EFI_LINK_H
+
+/*++
+
+Copyright (c) 1998 Intel Corporation
+
+Module Name:
+
+ link.h (renamed efilink.h to avoid conflicts)
+
+Abstract:
+
+ EFI link list macro's
+
+
+
+Revision History
+
+--*/
+
+#ifndef EFI_NT_EMUL
+
+//
+// List entry - doubly linked list
+//
+
+typedef struct _LIST_ENTRY {
+ struct _LIST_ENTRY *Flink;
+ struct _LIST_ENTRY *Blink;
+} LIST_ENTRY;
+
+#endif
+
+
+//
+// VOID
+// InitializeListHead(
+// LIST_ENTRY *ListHead
+// );
+//
+
+#define InitializeListHead(ListHead) \
+ (ListHead)->Flink = ListHead; \
+ (ListHead)->Blink = ListHead;
+
+//
+// BOOLEAN
+// IsListEmpty(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define IsListEmpty(ListHead) \
+ ((ListHead)->Flink == (ListHead))
+
+//
+// VOID
+// RemoveEntryList(
+// PLIST_ENTRY Entry
+// );
+//
+
+#define _RemoveEntryList(Entry) { \
+ LIST_ENTRY *_Blink, *_Flink; \
+ _Flink = (Entry)->Flink; \
+ _Blink = (Entry)->Blink; \
+ _Blink->Flink = _Flink; \
+ _Flink->Blink = _Blink; \
+ }
+
+#if EFI_DEBUG
+ #define RemoveEntryList(Entry) \
+ _RemoveEntryList(Entry); \
+ (Entry)->Flink = (LIST_ENTRY *) BAD_POINTER; \
+ (Entry)->Blink = (LIST_ENTRY *) BAD_POINTER;
+#else
+ #define RemoveEntryList(Entry) \
+ _RemoveEntryList(Entry);
+#endif
+
+//
+// VOID
+// InsertTailList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertTailList(ListHead,Entry) {\
+ LIST_ENTRY *_ListHead, *_Blink; \
+ _ListHead = (ListHead); \
+ _Blink = _ListHead->Blink; \
+ (Entry)->Flink = _ListHead; \
+ (Entry)->Blink = _Blink; \
+ _Blink->Flink = (Entry); \
+ _ListHead->Blink = (Entry); \
+ }
+
+//
+// VOID
+// InsertHeadList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertHeadList(ListHead,Entry) {\
+ LIST_ENTRY *_ListHead, *_Flink; \
+ _ListHead = (ListHead); \
+ _Flink = _ListHead->Flink; \
+ (Entry)->Flink = _Flink; \
+ (Entry)->Blink = _ListHead; \
+ _Flink->Blink = (Entry); \
+ _ListHead->Flink = (Entry); \
+ }
+
+// VOID
+// SwapListEntries(
+// PLIST_ENTRY Entry1,
+// PLIST_ENTRY Entry2
+// );
+//
+// Put Entry2 before Entry1
+//
+#define SwapListEntries(Entry1,Entry2) {\
+ LIST_ENTRY *Entry1Flink, *Entry1Blink; \
+ LIST_ENTRY *Entry2Flink, *Entry2Blink; \
+ Entry2Flink = (Entry2)->Flink; \
+ Entry2Blink = (Entry2)->Blink; \
+ Entry1Flink = (Entry1)->Flink; \
+ Entry1Blink = (Entry1)->Blink; \
+ Entry2Blink->Flink = Entry2Flink; \
+ Entry2Flink->Blink = Entry2Blink; \
+ (Entry2)->Flink = Entry1; \
+ (Entry2)->Blink = Entry1Blink; \
+ Entry1Blink->Flink = (Entry2); \
+ (Entry1)->Blink = (Entry2); \
+ }
+
+//
+// EFI_FIELD_OFFSET - returns the byte offset to a field within a structure
+//
+
+#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field)))
+
+//
+// CONTAINING_RECORD - returns a pointer to the structure
+// from one of it's elements.
+//
+
+#define _CR(Record, TYPE, Field) \
+ ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
+
+#if EFI_DEBUG
+ #define CR(Record, TYPE, Field, Sig) \
+ _CR(Record, TYPE, Field)->Signature != Sig ? \
+ (TYPE *) ASSERT_STRUCT(_CR(Record, TYPE, Field), Record) : \
+ _CR(Record, TYPE, Field)
+#else
+ #define CR(Record, TYPE, Field, Signature) \
+ _CR(Record, TYPE, Field)
+#endif
+
+
+//
+// A lock structure
+//
+
+typedef struct _FLOCK {
+ EFI_TPL Tpl;
+ EFI_TPL OwnerTpl;
+ UINTN Lock;
+} FLOCK;
+
+#endif
+
+/*
+ PE32+ header file
+ */
+#ifndef _PE_H
+#define _PE_H
+
+#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define IMAGE_OS2_SIGNATURE 0x454E // NE
+#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+
+
+typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
+ uint16_t e_magic; // Magic number
+ uint16_t e_cblp; // Bytes on last page of file
+ uint16_t e_cp; // Pages in file
+ uint16_t e_crlc; // Relocations
+ uint16_t e_cparhdr; // Size of header in paragraphs
+ uint16_t e_minalloc; // Minimum extra paragraphs needed
+ uint16_t e_maxalloc; // Maximum extra paragraphs needed
+ uint16_t e_ss; // Initial (relative) SS value
+ uint16_t e_sp; // Initial SP value
+ uint16_t e_csum; // Checksum
+ uint16_t e_ip; // Initial IP value
+ uint16_t e_cs; // Initial (relative) CS value
+ uint16_t e_lfarlc; // File address of relocation table
+ uint16_t e_ovno; // Overlay number
+ uint16_t e_res[4]; // Reserved words
+ uint16_t e_oemid; // OEM identifier (for e_oeminfo)
+ uint16_t e_oeminfo; // OEM information; e_oemid specific
+ uint16_t e_res2[10]; // Reserved words
+ uint32_t e_lfanew; // File address of new exe header
+ } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header
+ uint16_t ne_magic; // Magic number
+ uint8_t ne_ver; // Version number
+ uint8_t ne_rev; // Revision number
+ uint16_t ne_enttab; // Offset of Entry Table
+ uint16_t ne_cbenttab; // Number of bytes in Entry Table
+ uint32_t ne_crc; // Checksum of whole file
+ uint16_t ne_flags; // Flag uint16_t
+ uint16_t ne_autodata; // Automatic data segment number
+ uint16_t ne_heap; // Initial heap allocation
+ uint16_t ne_stack; // Initial stack allocation
+ uint32_t ne_csip; // Initial CS:IP setting
+ uint32_t ne_sssp; // Initial SS:SP setting
+ uint16_t ne_cseg; // Count of file segments
+ uint16_t ne_cmod; // Entries in Module Reference Table
+ uint16_t ne_cbnrestab; // Size of non-resident name table
+ uint16_t ne_segtab; // Offset of Segment Table
+ uint16_t ne_rsrctab; // Offset of Resource Table
+ uint16_t ne_restab; // Offset of resident name table
+ uint16_t ne_modtab; // Offset of Module Reference Table
+ uint16_t ne_imptab; // Offset of Imported Names Table
+ uint32_t ne_nrestab; // Offset of Non-resident Names Table
+ uint16_t ne_cmovent; // Count of movable entries
+ uint16_t ne_align; // Segment alignment shift count
+ uint16_t ne_cres; // Count of resource segments
+ uint8_t ne_exetyp; // Target Operating system
+ uint8_t ne_flagsothers; // Other .EXE flags
+ uint16_t ne_pretthunks; // offset to return thunks
+ uint16_t ne_psegrefbytes; // offset to segment ref. bytes
+ uint16_t ne_swaparea; // Minimum code swap area size
+ uint16_t ne_expver; // Expected Windows version number
+ } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
+
+//
+// File header format.
+//
+
+typedef struct _IMAGE_FILE_HEADER {
+ uint16_t Machine;
+ uint16_t NumberOfSections;
+ uint32_t TimeDateStamp;
+ uint32_t PointerToSymbolTable;
+ uint32_t NumberOfSymbols;
+ uint16_t SizeOfOptionalHeader;
+ uint16_t Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+#define IMAGE_SIZEOF_FILE_HEADER 20
+
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0
+#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian
+#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian
+#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP
+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb
+#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian
+#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64
+#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code
+#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64
+//
+// Directory format.
+//
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+ uint32_t VirtualAddress;
+ uint32_t Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+//
+// Optional header format.
+//
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+ //
+ // Standard fields.
+ //
+
+ uint16_t Magic;
+ uint8_t MajorLinkerVersion;
+ uint8_t MinorLinkerVersion;
+ uint32_t SizeOfCode;
+ uint32_t SizeOfInitializedData;
+ uint32_t SizeOfUninitializedData;
+ uint32_t AddressOfEntryPoint;
+ uint32_t BaseOfCode;
+ uint32_t BaseOfData;
+
+ //
+ // NT additional fields.
+ //
+
+ uint32_t ImageBase;
+ uint32_t SectionAlignment;
+ uint32_t FileAlignment;
+ uint16_t MajorOperatingSystemVersion;
+ uint16_t MinorOperatingSystemVersion;
+ uint16_t MajorImageVersion;
+ uint16_t MinorImageVersion;
+ uint16_t MajorSubsystemVersion;
+ uint16_t MinorSubsystemVersion;
+ uint32_t Reserved1;
+ uint32_t SizeOfImage;
+ uint32_t SizeOfHeaders;
+ uint32_t CheckSum;
+ uint16_t Subsystem;
+ uint16_t DllCharacteristics;
+ uint32_t SizeOfStackReserve;
+ uint32_t SizeOfStackCommit;
+ uint32_t SizeOfHeapReserve;
+ uint32_t SizeOfHeapCommit;
+ uint32_t LoaderFlags;
+ uint32_t NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
+
+typedef struct _IMAGE_ROM_OPTIONAL_HEADER {
+ uint16_t Magic;
+ uint8_t MajorLinkerVersion;
+ uint8_t MinorLinkerVersion;
+ uint32_t SizeOfCode;
+ uint32_t SizeOfInitializedData;
+ uint32_t SizeOfUninitializedData;
+ uint32_t AddressOfEntryPoint;
+ uint32_t BaseOfCode;
+ uint32_t BaseOfData;
+ uint32_t BaseOfBss;
+ uint32_t GprMask;
+ uint32_t CprMask[4];
+ uint32_t GpValue;
+} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER;
+
+#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56
+#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224
+
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
+#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+
+typedef struct _IMAGE_NT_HEADERS {
+ uint32_t Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
+
+typedef struct _IMAGE_ROM_HEADERS {
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS;
+
+#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
+ ((uint32_t)ntheader + \
+ FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
+ ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \
+ ))
+
+
+// Subsystem Values
+
+#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
+#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
+#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
+#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem.
+
+
+// Directory Entries
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
+#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
+#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP)
+#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
+
+//
+// Section header format.
+//
+
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct _IMAGE_SECTION_HEADER {
+ uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ uint32_t PhysicalAddress;
+ uint32_t VirtualSize;
+ } Misc;
+ uint32_t VirtualAddress;
+ uint32_t SizeOfRawData;
+ uint32_t PointerToRawData;
+ uint32_t PointerToRelocations;
+ uint32_t PointerToLinenumbers;
+ uint16_t NumberOfRelocations;
+ uint16_t NumberOfLinenumbers;
+ uint32_t Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+
+#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.
+
+#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.
+
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //
+
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
+#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
+#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
+#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
+
+//
+// Symbol format.
+//
+
+
+#define IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+
+#define IMAGE_SYM_UNDEFINED (uint16_t)0 // Symbol is undefined or is common.
+#define IMAGE_SYM_ABSOLUTE (uint16_t)-1 // Symbol is an absolute value.
+#define IMAGE_SYM_DEBUG (uint16_t)-2 // Symbol is a special debug item.
+
+//
+// Type (fundamental) values.
+//
+
+#define IMAGE_SYM_TYPE_NULL 0 // no type.
+#define IMAGE_SYM_TYPE_VOID 1 //
+#define IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define IMAGE_SYM_TYPE_INT 4 //
+#define IMAGE_SYM_TYPE_LONG 5 //
+#define IMAGE_SYM_TYPE_FLOAT 6 //
+#define IMAGE_SYM_TYPE_DOUBLE 7 //
+#define IMAGE_SYM_TYPE_STRUCT 8 //
+#define IMAGE_SYM_TYPE_UNION 9 //
+#define IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define IMAGE_SYM_TYPE_BYTE 12 //
+#define IMAGE_SYM_TYPE_WORD 13 //
+#define IMAGE_SYM_TYPE_UINT 14 //
+#define IMAGE_SYM_TYPE_DWORD 15 //
+
+//
+// Type (derived) values.
+//
+
+#define IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define IMAGE_SYM_DTYPE_POINTER 1 // pointer.
+#define IMAGE_SYM_DTYPE_FUNCTION 2 // function.
+#define IMAGE_SYM_DTYPE_ARRAY 3 // array.
+
+//
+// Storage classes.
+//
+
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1
+#define IMAGE_SYM_CLASS_NULL 0
+#define IMAGE_SYM_CLASS_AUTOMATIC 1
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+#define IMAGE_SYM_CLASS_STATIC 3
+#define IMAGE_SYM_CLASS_REGISTER 4
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define IMAGE_SYM_CLASS_LABEL 6
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define IMAGE_SYM_CLASS_ARGUMENT 9
+#define IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define IMAGE_SYM_CLASS_UNION_TAG 12
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define IMAGE_SYM_CLASS_ENUM_TAG 15
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define IMAGE_SYM_CLASS_BIT_FIELD 18
+#define IMAGE_SYM_CLASS_BLOCK 100
+#define IMAGE_SYM_CLASS_FUNCTION 101
+#define IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define IMAGE_SYM_CLASS_FILE 103
+// new
+#define IMAGE_SYM_CLASS_SECTION 104
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+// type packing constants
+
+#define N_BTMASK 017
+#define N_TMASK 060
+#define N_TMASK1 0300
+#define N_TMASK2 0360
+#define N_BTSHFT 4
+#define N_TSHIFT 2
+
+// MACROS
+
+//
+// Communal selection types.
+//
+
+#define IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define IMAGE_COMDAT_SELECT_ANY 2
+#define IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+
+//
+// Relocation format.
+//
+
+typedef struct _IMAGE_RELOCATION {
+ uint32_t VirtualAddress;
+ uint32_t SymbolTableIndex;
+ uint16_t Type;
+} IMAGE_RELOCATION;
+
+#define IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+
+#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define IMAGE_REL_I386_SECTION 012
+#define IMAGE_REL_I386_SECREL 013
+#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+
+//
+// MIPS relocation types.
+//
+
+#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define IMAGE_REL_MIPS_REFHALF 01
+#define IMAGE_REL_MIPS_REFWORD 02
+#define IMAGE_REL_MIPS_JMPADDR 03
+#define IMAGE_REL_MIPS_REFHI 04
+#define IMAGE_REL_MIPS_REFLO 05
+#define IMAGE_REL_MIPS_GPREL 06
+#define IMAGE_REL_MIPS_LITERAL 07
+#define IMAGE_REL_MIPS_SECTION 012
+#define IMAGE_REL_MIPS_SECREL 013
+#define IMAGE_REL_MIPS_REFWORDNB 042
+#define IMAGE_REL_MIPS_PAIR 045
+
+//
+// Alpha Relocation types.
+//
+
+#define IMAGE_REL_ALPHA_ABSOLUTE 0x0
+#define IMAGE_REL_ALPHA_REFLONG 0x1
+#define IMAGE_REL_ALPHA_REFQUAD 0x2
+#define IMAGE_REL_ALPHA_GPREL32 0x3
+#define IMAGE_REL_ALPHA_LITERAL 0x4
+#define IMAGE_REL_ALPHA_LITUSE 0x5
+#define IMAGE_REL_ALPHA_GPDISP 0x6
+#define IMAGE_REL_ALPHA_BRADDR 0x7
+#define IMAGE_REL_ALPHA_HINT 0x8
+#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9
+#define IMAGE_REL_ALPHA_REFHI 0xA
+#define IMAGE_REL_ALPHA_REFLO 0xB
+#define IMAGE_REL_ALPHA_PAIR 0xC
+#define IMAGE_REL_ALPHA_MATCH 0xD
+#define IMAGE_REL_ALPHA_SECTION 0xE
+#define IMAGE_REL_ALPHA_SECREL 0xF
+#define IMAGE_REL_ALPHA_REFLONGNB 0x10
+
+//
+// IBM PowerPC relocation types.
+//
+
+#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP
+#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address
+#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address
+#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute)
+#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address
+#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword)
+#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative)
+#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative)
+#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base
+#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword)
+
+#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base
+#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr)
+#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number
+#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code
+#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction
+
+#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type
+
+// Flag bits in IMAGE_RELOCATION.TYPE
+
+#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it
+#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken
+#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken
+#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc)
+
+//
+// Based relocation format.
+//
+
+typedef struct _IMAGE_BASE_RELOCATION {
+ uint32_t VirtualAddress;
+ uint32_t SizeOfBlock;
+// uint16_t TypeOffset[1];
+} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;
+
+#define IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+
+#define IMAGE_REL_BASED_ABSOLUTE 0
+#define IMAGE_REL_BASED_HIGH 1
+#define IMAGE_REL_BASED_LOW 2
+#define IMAGE_REL_BASED_HIGHLOW 3
+#define IMAGE_REL_BASED_HIGHADJ 4
+#define IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define IMAGE_REL_BASED_IA64_IMM64 9
+#define IMAGE_REL_BASED_DIR64 10
+
+//
+// Line number format.
+//
+
+typedef struct _IMAGE_LINENUMBER {
+ union {
+ uint32_t SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ uint32_t VirtualAddress; // Virtual address of line number.
+ } Type;
+ uint16_t Linenumber; // Line number.
+} IMAGE_LINENUMBER;
+
+#define IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+
+#define IMAGE_ARCHIVE_START_SIZE 8
+#define IMAGE_ARCHIVE_START "!\n"
+#define IMAGE_ARCHIVE_END "`\n"
+#define IMAGE_ARCHIVE_PAD "\n"
+#define IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER {
+ uint8_t Name[16]; // File member name - `/' terminated.
+ uint8_t Date[12]; // File member date - decimal.
+ uint8_t UserID[6]; // File member user id - decimal.
+ uint8_t GroupID[6]; // File member group id - decimal.
+ uint8_t Mode[8]; // File member mode - octal.
+ uint8_t Size[10]; // File member size - decimal.
+ uint8_t EndHeader[2]; // String to end header.
+} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+
+//
+// Export Format
+//
+
+typedef struct _IMAGE_EXPORT_DIRECTORY {
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t Name;
+ uint32_t Base;
+ uint32_t NumberOfFunctions;
+ uint32_t NumberOfNames;
+ uint32_t *AddressOfFunctions;
+ uint32_t *AddressOfNames;
+ uint32_t *AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
+
+//
+// Import Format
+//
+
+typedef struct _IMAGE_IMPORT_BY_NAME {
+ uint16_t Hint;
+ uint8_t Name[1];
+} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
+
+typedef struct _IMAGE_THUNK_DATA {
+ union {
+ uint32_t Function;
+ uint32_t Ordinal;
+ PIMAGE_IMPORT_BY_NAME AddressOfData;
+ } u1;
+} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
+
+#define IMAGE_ORDINAL_FLAG 0x80000000
+#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0)
+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct _IMAGE_IMPORT_DESCRIPTOR {
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint32_t ForwarderChain;
+ uint32_t Name;
+ PIMAGE_THUNK_DATA FirstThunk;
+} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
+
+#endif
+
+#ifndef _PCI22_H
+#define _PCI22_H
+
+/*++
+
+Copyright (c) 1999 Intel Corporation
+
+Module Name:
+
+ pci22.h
+
+Abstract:
+ Support for PCI 2.2 standard.
+
+
+
+
+Revision History
+
+--*/
+
+#ifdef SOFT_SDV
+#define PCI_MAX_BUS 1
+#else
+#define PCI_MAX_BUS 255
+#endif
+
+#define PCI_MAX_DEVICE 31
+#define PCI_MAX_FUNC 7
+
+//
+// Command
+//
+#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20
+
+#pragma pack(1)
+typedef struct {
+ uint16_t VendorId;
+ uint16_t DeviceId;
+ uint16_t Command;
+ uint16_t Status;
+ uint8_t RevisionID;
+ uint8_t ClassCode[3];
+ uint8_t CacheLineSize;
+ uint8_t LaytencyTimer;
+ uint8_t HeaderType;
+ uint8_t BIST;
+} PCI_DEVICE_INDEPENDENT_REGION;
+
+typedef struct {
+ uint32_t Bar[6];
+ uint32_t CISPtr;
+ uint16_t SubsystemVendorID;
+ uint16_t SubsystemID;
+ uint32_t ExpansionRomBar;
+ uint32_t Reserved[2];
+ uint8_t InterruptLine;
+ uint8_t InterruptPin;
+ uint8_t MinGnt;
+ uint8_t MaxLat;
+} PCI_DEVICE_HEADER_TYPE_REGION;
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_DEVICE_HEADER_TYPE_REGION Device;
+} PCI_TYPE00;
+
+typedef struct {
+ uint32_t Bar[2];
+ uint8_t PrimaryBus;
+ uint8_t SecondaryBus;
+ uint8_t SubordinateBus;
+ uint8_t SecondaryLatencyTimer;
+ uint8_t IoBase;
+ uint8_t IoLimit;
+ uint16_t SecondaryStatus;
+ uint16_t MemoryBase;
+ uint16_t MemoryLimit;
+ uint16_t PrefetchableMemoryBase;
+ uint16_t PrefetchableMemoryLimit;
+ uint32_t PrefetchableBaseUpper32;
+ uint32_t PrefetchableLimitUpper32;
+ uint16_t IoBaseUpper16;
+ uint16_t IoLimitUpper16;
+ uint32_t Reserved;
+ uint32_t ExpansionRomBAR;
+ uint8_t InterruptLine;
+ uint8_t InterruptPin;
+ uint16_t BridgeControl;
+} PCI_BRIDGE_CONTROL_REGISTER;
+
+#define PCI_CLASS_DISPLAY_CTRL 0x03
+#define PCI_CLASS_VGA 0x00
+
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_ISA 0x01
+#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80
+
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_ETHERNET 0x00
+
+#define HEADER_TYPE_DEVICE 0x00
+#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01
+#define HEADER_TYPE_MULTI_FUNCTION 0x80
+#define HEADER_LAYOUT_CODE 0x7f
+
+#define IS_PCI_BRIDGE(_p) ((((_p)->Hdr.HeaderType) & HEADER_LAYOUT_CODE) == HEADER_TYPE_PCI_TO_PCI_BRIDGE)
+#define IS_PCI_MULTI_FUNC(_p) (((_p)->Hdr.HeaderType) & HEADER_TYPE_MULTI_FUNCTION)
+
+typedef struct {
+ PCI_DEVICE_INDEPENDENT_REGION Hdr;
+ PCI_BRIDGE_CONTROL_REGISTER Bridge;
+} PCI_TYPE01;
+
+typedef struct {
+ uint8_t Register;
+ uint8_t Function;
+ uint8_t Device;
+ uint8_t Bus;
+ uint8_t Reserved[4];
+} DEFIO_PCI_ADDR;
+
+typedef struct {
+ uint32_t Reg : 8;
+ uint32_t Func : 3;
+ uint32_t Dev : 5;
+ uint32_t Bus : 8;
+ uint32_t Reserved: 7;
+ uint32_t Enable : 1;
+} PCI_CONFIG_ACCESS_CF8;
+
+#pragma pack()
+
+#define EFI_ROOT_BRIDGE_LIST 'eprb'
+typedef struct {
+ UINTN Signature;
+
+ uint16_t BridgeNumber;
+ uint16_t PrimaryBus;
+ uint16_t SubordinateBus;
+
+ EFI_DEVICE_PATH *DevicePath;
+
+ LIST_ENTRY Link;
+} PCI_ROOT_BRIDGE_ENTRY;
+
+
+#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55
+#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1
+#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32('P','C','I','R')
+
+#pragma pack(1)
+typedef struct {
+ uint16_t Signature; // 0xaa55
+ uint8_t Reserved[0x16];
+ uint16_t PcirOffset;
+} PCI_EXPANSION_ROM_HEADER;
+
+
+typedef struct {
+ uint16_t Signature; // 0xaa55
+ uint16_t InitializationSize;
+ uint16_t EfiSignature; // 0x0EF1
+ uint16_t EfiSubsystem;
+ uint16_t EfiMachineType;
+ uint8_t Reserved[0x0A];
+ uint16_t EfiImageHeaderOffset;
+ uint16_t PcirOffset;
+} EFI_PCI_EXPANSION_ROM_HEADER;
+
+typedef struct {
+ uint32_t Signature; // "PCIR"
+ uint16_t VendorId;
+ uint16_t DeviceId;
+ uint16_t Reserved0;
+ uint16_t Length;
+ uint8_t Revision;
+ uint8_t ClassCode[3];
+ uint16_t ImageLength;
+ uint16_t CodeRevision;
+ uint8_t CodeType;
+ uint8_t Indicator;
+ uint16_t Reserved1;
+} PCI_DATA_STRUCTURE;
+#pragma pack()
+
+#endif
+
+
+/** Command-line options */
+struct options {
+ uint16_t vendor;
+ uint16_t device;
+};
+
+/**
+ * Allocate memory
+ *
+ * @v len Length of memory to allocate
+ * @ret ptr Pointer to allocated memory
+ */
+static void * xmalloc ( size_t len ) {
+ void *ptr;
+
+ ptr = malloc ( len );
+ if ( ! ptr ) {
+ eprintf ( "Could not allocate %zd bytes\n", len );
+ exit ( 1 );
+ }
+
+ return ptr;
+}
+
+/**
+ * Get file size
+ *
+ * @v file File
+ * @v len File size
+ */
+/*
+static size_t file_size ( FILE *file ) {
+ ssize_t len;
+
+ return len;
+}
+*/
+/**
+ * Read information from PE headers
+ *
+ * @v pe PE file
+ * @ret machine Machine type
+ * @ret subsystem EFI subsystem
+ */
+static void read_pe_info ( void *pe, uint16_t *machine,
+ uint16_t *subsystem ) {
+ IMAGE_DOS_HEADER *dos;
+ union {
+ IMAGE_NT_HEADERS nt64;
+ } *nt;
+
+ /* Locate NT header */
+ dos = pe;
+ nt = ( pe + dos->e_lfanew );
+
+ /* issue 4: TianoCore demands subsystem 10, so we must use EFI_APPLICATION
+ * in the PE header. Therefore we force EFI_ROM subsystem in this code here. */
+ if(nt->nt64.OptionalHeader.Subsystem == 10)
+ nt->nt64.OptionalHeader.Subsystem = 13;
+
+ /* Parse out PE information */
+ *machine = nt->nt64.FileHeader.Machine;
+ *subsystem = nt->nt64.OptionalHeader.Subsystem;
+}
+
+/**
+ * Convert EFI image to ROM image
+ *
+ * @v pe EFI file
+ * @v rom ROM file
+ */
+static void make_efi_rom ( FILE *pe, FILE *rom, struct options *opts ) {
+ struct {
+ EFI_PCI_EXPANSION_ROM_HEADER rom;
+ PCI_DATA_STRUCTURE pci __attribute__ (( aligned ( 4 ) ));
+ uint8_t checksum;
+ } *headers;
+ struct stat pe_stat;
+ size_t pe_size;
+ size_t rom_size;
+ void *buf;
+ void *payload;
+ unsigned int i;
+ uint8_t checksum;
+
+ /* Determine PE file size */
+ if ( fstat ( fileno ( pe ), &pe_stat ) != 0 ) {
+ eprintf ( "Could not stat PE file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+ pe_size = pe_stat.st_size;
+
+ /* Determine ROM file size */
+ rom_size = ( ( pe_size + sizeof ( *headers ) + 511 ) & ~511 );
+
+ /* Allocate ROM buffer and read in PE file */
+ buf = xmalloc ( rom_size );
+ memset ( buf, 0, rom_size );
+ headers = buf;
+ payload = ( buf + sizeof ( *headers ) );
+ if ( fread ( payload, pe_size, 1, pe ) != 1 ) {
+ eprintf ( "Could not read PE file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Construct ROM header */
+ headers->rom.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
+ headers->rom.InitializationSize = ( rom_size / 512 );
+ headers->rom.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
+ read_pe_info ( payload, &headers->rom.EfiMachineType,
+ &headers->rom.EfiSubsystem );
+ headers->rom.EfiImageHeaderOffset = sizeof ( *headers );
+ headers->rom.PcirOffset =
+ offsetof ( typeof ( *headers ), pci );
+ headers->pci.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ headers->pci.VendorId = opts->vendor ? opts->vendor : 0x8086;
+ headers->pci.DeviceId = opts->device ? opts->device : 0x100E;
+ headers->pci.Length = sizeof ( headers->pci );
+ headers->pci.ClassCode[0] = PCI_CLASS_NETWORK;
+ headers->pci.ImageLength = ( rom_size / 512 );
+ headers->pci.CodeType = 0x03; /* No constant in EFI headers? */
+ headers->pci.Indicator = 0x80; /* No constant in EFI headers? */
+
+ /* Fix image checksum */
+ for ( i = 0, checksum = 0 ; i < rom_size ; i++ )
+ checksum += *( ( uint8_t * ) buf + i );
+ headers->checksum -= checksum;
+
+ /* Write out ROM */
+ if ( fwrite ( buf, rom_size, 1, rom ) != 1 ) {
+ eprintf ( "Could not write ROM file: %s\n",
+ strerror ( errno ) );
+ exit ( 1 );
+ }
+}
+
+/**
+ * Parse command-line options
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @v opts Options structure to populate
+ */
+static int parse_options ( const int argc, char **argv,
+ struct options *opts ) {
+ char *end;
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "vendor", required_argument, NULL, 'v' },
+ { "device", required_argument, NULL, 'd' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ if ( ( c = getopt_long ( argc, argv, "v:d:h",
+ long_options,
+ &option_index ) ) == -1 ) {
+ break;
+ }
+
+ switch ( c ) {
+ case 'v':
+ opts->vendor = strtoul ( optarg, &end, 16 );
+ if ( *end ) {
+ eprintf ( "Invalid vendor \"%s\"\n", optarg );
+ exit ( 2 );
+ }
+ break;
+ case 'd':
+ opts->device = strtoul ( optarg, &end, 16 );
+ if ( *end ) {
+ eprintf ( "Invalid device \"%s\"\n", optarg );
+ exit ( 2 );
+ }
+ break;
+ case 'h':
+ print_help ( argv[0] );
+ exit ( 0 );
+ case '?':
+ default:
+ exit ( 2 );
+ }
+ }
+ return optind;
+}
+
+int main ( int argc, char **argv ) {
+ struct options opts = {
+ };
+ unsigned int infile_index;
+ const char *infile_name;
+ const char *outfile_name;
+ FILE *infile;
+ FILE *outfile;
+
+ /* Parse command-line arguments */
+ infile_index = parse_options ( argc, argv, &opts );
+ if ( argc != ( infile_index + 2 ) ) {
+ print_help ( argv[0] );
+ exit ( 2 );
+ }
+ infile_name = argv[infile_index];
+ outfile_name = argv[infile_index + 1];
+
+ /* Open input and output files */
+ infile = fopen ( infile_name, "r" );
+ if ( ! infile ) {
+ eprintf ( "Could not open %s for reading: %s\n",
+ infile_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+ outfile = fopen ( outfile_name, "w" );
+ if ( ! outfile ) {
+ eprintf ( "Could not open %s for writing: %s\n",
+ outfile_name, strerror ( errno ) );
+ exit ( 1 );
+ }
+
+ /* Convert file */
+ make_efi_rom ( infile, outfile, &opts );
+
+ fclose ( outfile );
+ fclose ( infile );
+
+ return 0;
+}