mirror of
https://gitlab.com/bztsrc/posix-uefi.git
synced 2024-12-29 05:55:31 +01:00
Initial commit
This commit is contained in:
commit
f46ef12c65
22 changed files with 4229 additions and 0 deletions
232
README.md
Normal file
232
README.md
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
POSIX-UEFI
|
||||||
|
==========
|
||||||
|
|
||||||
|
```
|
||||||
|
We hate that horrible and ugly UEFI API, we want POSIX!
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a very small library (32k) 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 Clang and GNU gcc both) and easier to use because it provides a POSIX like API.
|
||||||
|
|
||||||
|
To use it, you have to options:
|
||||||
|
|
||||||
|
Distributing as Static Library
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
In the `uefi` library, run
|
||||||
|
```sh
|
||||||
|
$ 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**.
|
||||||
|
|
||||||
|
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). Twelfe files, about 140K in total.
|
||||||
|
2. create an extremely simple **Makefile** like 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 <uefi.h>
|
||||||
|
|
||||||
|
int main(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
printf(L"Hello World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Makefile Options
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|------------|------------------------------------------------------------------------------------------------------|
|
||||||
|
| `TARGET` | the target application (required) |
|
||||||
|
| `SRCS` | list of source files you want to compile (defaults to \*.c \*.S) |
|
||||||
|
| `CFALGS` | 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) |
|
||||||
|
| `USE_LLVM` | set this if you want LLVM Clang / Lld instead of GNU gcc / ld |
|
||||||
|
| `ARCH` | the target architecture (only x86_64 supported for now, but the toolchain can handle multiple archs) |
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
USE_LLVM = 1
|
||||||
|
include uefi/Makefile
|
||||||
|
```
|
||||||
|
|
||||||
|
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` | *efi_boot_services_t*, pointer to the Boot Time Services |
|
||||||
|
| `*RT` | *efi_runtime_t*, pointer to the Runtime Services |
|
||||||
|
| `*ST` | *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.
|
||||||
|
|
||||||
|
That header also provides an UEFI ABI wrapper, exactly the same as in gnu-efi, and functions to exit Boot Services
|
||||||
|
and to dump memory for your convenience.
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|-----------------------|----------------------------------------------------|
|
||||||
|
| `uefi_call_wrapper()` | call a function with UEFI ABI (provided by crt0) |
|
||||||
|
| `uefi_exit_bs()` | leave this UEFI bullshit behind (provided by crt0) |
|
||||||
|
| `uefi_dumpmem()` | dump memory (provided by libuefi.a) |
|
||||||
|
|
||||||
|
Unlike gnu-efi, POSIX-UEFI does not pollute your application 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 = uefi_call_wrapper(BS->LocateProtocol, 3, &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 with your distro's package management solution, and POSIX-UEFI makes it possible
|
||||||
|
for you to use those system wide headers. POSIX-UEFI itself ships the very minimum set of typedefs and structs.
|
||||||
|
```c
|
||||||
|
#include <efi.h>
|
||||||
|
#include <uefi.h> /* this will work as expected! Both POSIX-UEFI and EDK II / gnu-efi typedefs accessible */
|
||||||
|
```
|
||||||
|
|
||||||
|
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,
|
||||||
|
so for example your main() is NOT 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) use this wide character type too. Functions that supposed
|
||||||
|
to handle characters in int type (like `getchar`, `putchar`), do not truncate to unsigned char, rather to wchar_t. For this
|
||||||
|
reason, you must specify your string literals with `L""` and characters with `L''`. There's an additional `getchar_ifany`
|
||||||
|
function, which does not block, but returns 0 when there's no key pressed.
|
||||||
|
|
||||||
|
That's about it, everything else is the same.
|
||||||
|
|
||||||
|
List of Provided POSIX Functions
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
### stdlib.h
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|---------------|----------------------------------------------------------------------------|
|
||||||
|
| atoi | as usual, but accepts wide char strings and understands "0x" prefix |
|
||||||
|
| atol | as usual, but accepts wide char strings and understands "0x" prefix |
|
||||||
|
| strtol | as usual, but accepts wide char strings |
|
||||||
|
| malloc | as usual |
|
||||||
|
| calloc | as usual |
|
||||||
|
| realloc | as usual (needs testing) |
|
||||||
|
| free | as usual |
|
||||||
|
| abort | as usual |
|
||||||
|
| exit | as usual |
|
||||||
|
| 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) |
|
||||||
|
|
||||||
|
### stdio.h
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|---------------|----------------------------------------------------------------------------|
|
||||||
|
| fopen | as usual, but accepts wide char strings, for mode L"r", L"w" and L"a" only |
|
||||||
|
| fclose | as usual |
|
||||||
|
| fflush | as usual |
|
||||||
|
| fread | as usual, only real files accepted (no stdin) |
|
||||||
|
| fwrite | as usual, only real files accepted (no stdout nor stderr) |
|
||||||
|
| fseek | as usual, only real files accepted (no stdin, stdout, stderr) |
|
||||||
|
| ftell | as usual, only real files accepted (no stdin, stdout, stderr) |
|
||||||
|
| fprintf | as usual, but accepts wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||||
|
| printf | as usual, but accepts wide char strings, max BUFSIZ, stdout only |
|
||||||
|
| sprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||||
|
| vfprintf | as usual, but accepts wide char strings, max BUFSIZ, files, stdout, stderr |
|
||||||
|
| vprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||||
|
| vsprintf | as usual, but accepts wide char strings, max BUFSIZ |
|
||||||
|
| snprintf | as usual, but accepts wide char strings |
|
||||||
|
| vsnprintf | as usual, but accepts wide char strings |
|
||||||
|
| getchar | as usual, waits for a key, blocking, stdin only (no redirects) |
|
||||||
|
| getchar_ifany | non-blocking, returns 0 if there was no key press, UNICODE otherwise |
|
||||||
|
| putchar | as usual, stdout only (no redirects) |
|
||||||
|
|
||||||
|
String formating is limited; only supports padding via number prefixes, `%d`, `%x`, `%X`, `%c`, `%s`, `%q` and
|
||||||
|
`%p`. Because it operates on wchar_t, it also supports the non-standard `%C` (printing an UTF-8 character, needs
|
||||||
|
char\*), `%S` (printing an UTF-8 string), `%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), except for the
|
||||||
|
variants which have a maxlen argument.
|
||||||
|
|
||||||
|
### 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 | works on wide char strings |
|
||||||
|
| strncpy | works on wide char strings |
|
||||||
|
| strcat | works on wide char strings |
|
||||||
|
| strncat | works on wide char strings |
|
||||||
|
| strcmp | works on wide char strings |
|
||||||
|
| strncmp | works on wide char strings |
|
||||||
|
| strdup | works on wide char strings |
|
||||||
|
| strchr | works on wide char strings |
|
||||||
|
| strrchr | works on wide char strings |
|
||||||
|
| strstr | works on wide char strings |
|
||||||
|
| strtok | works on wide char strings |
|
||||||
|
| strtok_r | works on wide char strings |
|
||||||
|
| strlen | works on wide char strings |
|
||||||
|
|
||||||
|
### time.h
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|---------------|----------------------------------------------------------------------------|
|
||||||
|
| localtime | no arguments, always returns current time in struct tm |
|
||||||
|
|
||||||
|
### unistd.h
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|---------------|----------------------------------------------------------------------------|
|
||||||
|
| usleep | the usual |
|
||||||
|
| sleep | the usual |
|
18
examples/01_helloworld/Makefile
Normal file
18
examples/01_helloworld/Makefile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# define which architecture you're targeting
|
||||||
|
ARCH = x86_64
|
||||||
|
# define your target file here
|
||||||
|
TARGET = helloworld.efi
|
||||||
|
#define your sources here
|
||||||
|
SRCS = $(wildcard *.c)
|
||||||
|
# define your default compiler flags
|
||||||
|
CFLAGS = -Wall -Wextra -Werror --std=c11 -O2
|
||||||
|
# define your default linker flags
|
||||||
|
#LDFLAGS =
|
||||||
|
# define your additional libraries here
|
||||||
|
#LIBS = -lm
|
||||||
|
|
||||||
|
# leave the hard work and all the rest to posix-uefi
|
||||||
|
|
||||||
|
# set this if you want LLVM Clang / Lld instead of GNU gcc / ld
|
||||||
|
#USE_LLVM = 1
|
||||||
|
include uefi/Makefile
|
9
examples/01_helloworld/helloworld.c
Normal file
9
examples/01_helloworld/helloworld.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <uefi.h>
|
||||||
|
|
||||||
|
int main(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
printf(L"Hello World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
1
examples/01_helloworld/uefi
Symbolic link
1
examples/01_helloworld/uefi
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../uefi
|
3
examples/02_args/Makefile
Normal file
3
examples/02_args/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
TARGET = args.efi
|
||||||
|
|
||||||
|
include uefi/Makefile
|
10
examples/02_args/args.c
Normal file
10
examples/02_args/args.c
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include <uefi.h>
|
||||||
|
|
||||||
|
int main(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
printf(L"I got %d arguments:\n", argc);
|
||||||
|
for(i = 0; i < argc + 1; i++)
|
||||||
|
printf(L" argv[%d] = '%s'\n", argv[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
1
examples/02_args/uefi
Symbolic link
1
examples/02_args/uefi
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../uefi
|
3
examples/03_dumpmem/Makefile
Normal file
3
examples/03_dumpmem/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
TARGET = dumpmem.efi
|
||||||
|
|
||||||
|
include uefi/Makefile
|
9
examples/03_dumpmem/dumpmem.c
Normal file
9
examples/03_dumpmem/dumpmem.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <uefi.h>
|
||||||
|
|
||||||
|
/* this should accept 0x prefixes from the command line */
|
||||||
|
int main(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
efi_physical_address_t address = (argc < 2 ? (efi_physical_address_t)IM : (efi_physical_address_t)atol(argv[1]));
|
||||||
|
uefi_dumpmem(address);
|
||||||
|
return 0;
|
||||||
|
}
|
1
examples/03_dumpmem/uefi
Symbolic link
1
examples/03_dumpmem/uefi
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../uefi
|
78
uefi/Makefile
Normal file
78
uefi/Makefile
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
MYARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
||||||
|
ifeq ($(ARCH),)
|
||||||
|
ARCH = $(MYARCH)
|
||||||
|
endif
|
||||||
|
SRCS ?= $(wildcard *.c) $(wildcard *.S)
|
||||||
|
TMP = $(SRCS:.c=.o)
|
||||||
|
OBJS = $(TMP:.S=.o)
|
||||||
|
CFLAGS += -mno-red-zone -fpic -fshort-wchar -fno-strict-aliasing -ffreestanding -fno-stack-protector -fno-stack-check \
|
||||||
|
-D__$(ARCH)__ -I/usr/include -I. -I./uefi -I/usr/include/efi -I/usr/include/efi/$(ARCH) -I/usr/include/efi/protocol
|
||||||
|
LDFLAGS += -nostdlib -shared -Bsymbolic
|
||||||
|
|
||||||
|
LIBSRCS = $(filter-out crt_$(ARCH).c,$(wildcard *.c)) $(wildcard *.S)
|
||||||
|
TMP = $(LIBSRCS:.c=.o)
|
||||||
|
LIBOBJS = $(TMP:.S=.o)
|
||||||
|
|
||||||
|
ifeq ($(USE_LLVM),)
|
||||||
|
CFLAGS += -Wno-builtin-declaration-mismatch
|
||||||
|
# see if we're cross-compiling
|
||||||
|
ifeq ($(ARCH),$(MYARCH))
|
||||||
|
CC = $(ARCH)-elf-gcc
|
||||||
|
LD = $(ARCH)-elf-ld
|
||||||
|
else
|
||||||
|
CC = gcc
|
||||||
|
LD = ld
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
CFLAGS += --target=$(ARCH)-elf -Wno-builtin-requires-header -Wno-incompatible-library-redeclaration
|
||||||
|
LDFLAGS += -m elf_$(ARCH)
|
||||||
|
CC = clang
|
||||||
|
LD = ld.lld
|
||||||
|
endif
|
||||||
|
# you will need this from GNU binutils, llvm-objcopy won't cut it
|
||||||
|
OBJCOPY ?= objcopy
|
||||||
|
AR ?= ar
|
||||||
|
|
||||||
|
ifeq ($(wildcard uefi/Makefile),)
|
||||||
|
ALLTARGETS = crt_$(ARCH).o libuefi.a build
|
||||||
|
else
|
||||||
|
ALLTARGETS = uefi/crt_$(ARCH).o uefi/libuefi.a $(OBJS) $(TARGET)
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(ALLTARGETS)
|
||||||
|
|
||||||
|
uefi/libuefi.a:
|
||||||
|
@make --no-print-directory -C uefi libuefi.a
|
||||||
|
|
||||||
|
libuefi.a: $(LIBOBJS)
|
||||||
|
@rm $@ 2>/dev/null || true
|
||||||
|
$(AR) -frsv $@ $(LIBOBJS) >/dev/null
|
||||||
|
|
||||||
|
$(TARGET): $(TARGET).so
|
||||||
|
@$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-$(ARCH) --subsystem=10 $^ $@
|
||||||
|
@rm $(TARGET).so
|
||||||
|
|
||||||
|
$(TARGET).so: uefi/crt_$(ARCH).o $(OBJS)
|
||||||
|
$(LD) $(LDFLAGS) -Luefi $^ -o $@ $(LIBS) -luefi -T uefi/elf_$(ARCH)_efi.lds
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
build:
|
||||||
|
@mkdir ../build ../build/uefi 2>/dev/null || true
|
||||||
|
@cp crt_$(ARCH).o ../build/uefi/crt0.o
|
||||||
|
@cp elf_$(ARCH)_efi.lds ../build/uefi/link.ld
|
||||||
|
@cp libuefi.a uefi.h ../build/uefi
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm $(TARGET) *.o *.a $(LIBOBJS) 2>/dev/null || true
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
ifeq ($(wildcard uefi/Makefile),)
|
||||||
|
@rm -rf ../build 2>/dev/null || true
|
||||||
|
else
|
||||||
|
@rm uefi/*.o uefi/libuefi.a 2>/dev/null || true
|
||||||
|
endif
|
286
uefi/crt_x86_64.c
Normal file
286
uefi/crt_x86_64.c
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
* 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 <uefi.h>
|
||||||
|
#include <uefielf.h>
|
||||||
|
|
||||||
|
/* this is implemented by the application */
|
||||||
|
extern int main(int argc, wchar_t **argv);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* we only need one .o file, so use inline Assembly here */
|
||||||
|
void bootstrap()
|
||||||
|
{
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
/* call init in C */
|
||||||
|
" .align 4;"
|
||||||
|
" .globl _start;"
|
||||||
|
"_start:"
|
||||||
|
" lea ImageBase(%rip), %rdi;"
|
||||||
|
" lea _DYNAMIC(%rip), %rsi;"
|
||||||
|
" call uefi_init;"
|
||||||
|
" ret;"
|
||||||
|
|
||||||
|
/*** the following code snipplets are borrowed from gnu-efi ***/
|
||||||
|
/* setjmp and longjmp */
|
||||||
|
" .globl setjmp;"
|
||||||
|
"setjmp:"
|
||||||
|
" pop %rsi;"
|
||||||
|
" movq %rbx,0x00(%rdi);"
|
||||||
|
" movq %rsp,0x08(%rdi);"
|
||||||
|
" push %rsi;"
|
||||||
|
" movq %rbp,0x10(%rdi);"
|
||||||
|
" movq %r12,0x18(%rdi);"
|
||||||
|
" movq %r13,0x20(%rdi);"
|
||||||
|
" movq %r14,0x28(%rdi);"
|
||||||
|
" movq %r15,0x30(%rdi);"
|
||||||
|
" movq %rsi,0x38(%rdi);"
|
||||||
|
" xor %rax,%rax;"
|
||||||
|
" ret;"
|
||||||
|
" .globl longjmp;"
|
||||||
|
"longjmp:"
|
||||||
|
" movl %esi, %eax;"
|
||||||
|
" movq 0x00(%rdi), %rbx;"
|
||||||
|
" movq 0x08(%rdi), %rsp;"
|
||||||
|
" movq 0x10(%rdi), %rbp;"
|
||||||
|
" movq 0x18(%rdi), %r12;"
|
||||||
|
" movq 0x20(%rdi), %r13;"
|
||||||
|
" movq 0x28(%rdi), %r14;"
|
||||||
|
" movq 0x30(%rdi), %r15;"
|
||||||
|
" xor %rdx,%rdx;"
|
||||||
|
" mov $1,%rcx;"
|
||||||
|
" cmp %rax,%rdx;"
|
||||||
|
" cmove %rcx,%rax;"
|
||||||
|
" jmp *0x38(%rdi);"
|
||||||
|
/* for uefi_call_wrapper */
|
||||||
|
" .globl uefi_call0;"
|
||||||
|
"uefi_call0:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call1;"
|
||||||
|
"uefi_call1:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call2;"
|
||||||
|
"uefi_call2:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call3;"
|
||||||
|
"uefi_call3:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call4;"
|
||||||
|
"uefi_call4:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call5;"
|
||||||
|
"uefi_call5:"
|
||||||
|
" subq $40, %rsp;"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $40, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call6;"
|
||||||
|
"uefi_call6:"
|
||||||
|
" subq $56, %rsp;"
|
||||||
|
" mov 56+8(%rsp), %rax;"
|
||||||
|
" mov %rax, 40(%rsp);"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $56, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call7;"
|
||||||
|
"uefi_call7:"
|
||||||
|
" subq $56, %rsp;"
|
||||||
|
" mov 56+16(%rsp), %rax;"
|
||||||
|
" mov %rax, 48(%rsp);"
|
||||||
|
" mov 56+8(%rsp), %rax;"
|
||||||
|
" mov %rax, 40(%rsp);"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $56, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call8;"
|
||||||
|
"uefi_call8:"
|
||||||
|
" subq $72, %rsp;"
|
||||||
|
" mov 72+24(%rsp), %rax;"
|
||||||
|
" mov %rax, 56(%rsp);"
|
||||||
|
" mov 72+16(%rsp), %rax;"
|
||||||
|
" mov %rax, 48(%rsp);"
|
||||||
|
" mov 72+8(%rsp), %rax;"
|
||||||
|
" mov %rax, 40(%rsp);"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $72, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call9;"
|
||||||
|
"uefi_call9:"
|
||||||
|
" subq $72, %rsp;"
|
||||||
|
" mov 72+32(%rsp), %rax;"
|
||||||
|
" mov %rax, 64(%rsp);"
|
||||||
|
" mov 72+24(%rsp), %rax;"
|
||||||
|
" mov %rax, 56(%rsp);"
|
||||||
|
" mov 72+16(%rsp), %rax;"
|
||||||
|
" mov %rax, 48(%rsp);"
|
||||||
|
" mov 72+8(%rsp), %rax;"
|
||||||
|
" mov %rax, 40(%rsp);"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $72, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
" .globl uefi_call10;"
|
||||||
|
"uefi_call10:"
|
||||||
|
" subq $88, %rsp;"
|
||||||
|
" mov 88+40(%rsp), %rax;"
|
||||||
|
" mov %rax, 72(%rsp);"
|
||||||
|
" mov 88+32(%rsp), %rax;"
|
||||||
|
" mov %rax, 64(%rsp);"
|
||||||
|
" mov 88+24(%rsp), %rax;"
|
||||||
|
" mov %rax, 56(%rsp);"
|
||||||
|
" mov 88+16(%rsp), %rax;"
|
||||||
|
" mov %rax, 48(%rsp);"
|
||||||
|
" mov 88+8(%rsp), %rax;"
|
||||||
|
" mov %rax, 40(%rsp);"
|
||||||
|
" mov %r9, 32(%rsp);"
|
||||||
|
" mov %r8, %r9;"
|
||||||
|
" mov %rcx, %r8;"
|
||||||
|
" mov %rsi, %rcx;"
|
||||||
|
" call *%rdi;"
|
||||||
|
" addq $88, %rsp;"
|
||||||
|
" ret;"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize POSIX-UEFI and call teh application's main() function
|
||||||
|
*/
|
||||||
|
int uefi_init (efi_handle_t image, efi_system_table_t *systab, uintptr_t ldbase, Elf64_Dyn *dyn) {
|
||||||
|
long relsz = 0, relent = 0;
|
||||||
|
Elf64_Rel *rel = 0;
|
||||||
|
uintptr_t *addr;
|
||||||
|
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 i, argc = 0;
|
||||||
|
wchar_t **argv = NULL;
|
||||||
|
/* 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; break; }
|
||||||
|
rel = (Elf64_Rel*) ((char *) rel + relent);
|
||||||
|
relsz -= relent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* save EFI pointers and loaded image into globals */
|
||||||
|
IM = image;
|
||||||
|
ST = systab;
|
||||||
|
BS = systab->BootServices;
|
||||||
|
RT = systab->RuntimeServices;
|
||||||
|
uefi_call_wrapper(BS->HandleProtocol, 3, image, &lipGuid, (void **) &LIP);
|
||||||
|
/* get command line arguments */
|
||||||
|
status = uefi_call_wrapper(BS->OpenProtocol, 6, image, &shpGuid, &shp, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
|
if(!EFI_ERROR(status) && shp) { argc = shp->Argc; argv = shp->Argv; }
|
||||||
|
else {
|
||||||
|
/* if shell 2.0 failed, fallback to shell 1.0 interface */
|
||||||
|
status = uefi_call_wrapper(BS->OpenProtocol, 6, image, &shiGuid, &shi, image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
|
if(!EFI_ERROR(status) && shi) { argc = shi->Argc; argv = shi->Argv; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call main */
|
||||||
|
return main(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit Boot Services
|
||||||
|
*/
|
||||||
|
boolean_t uefi_exit_bs()
|
||||||
|
{
|
||||||
|
efi_status_t status;
|
||||||
|
efi_memory_descriptor_t *memory_map = NULL;
|
||||||
|
uintn_t cnt = 3, memory_map_size=0, map_key=0, desc_size=0;
|
||||||
|
|
||||||
|
while(cnt--) {
|
||||||
|
status = uefi_call_wrapper(BS->GetMemoryMap, 5, &memory_map_size, memory_map, &map_key, &desc_size, NULL);
|
||||||
|
if (status!=EFI_BUFFER_TOO_SMALL) break;
|
||||||
|
status = uefi_call_wrapper(BS->ExitBootServices, 2, IM, map_key);
|
||||||
|
if(!EFI_ERROR(status)) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
76
uefi/elf_x86_64_efi.lds
Normal file
76
uefi/elf_x86_64_efi.lds
Normal file
|
@ -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) }
|
||||||
|
}
|
154
uefi/qsort.c
Normal file
154
uefi/qsort.c
Normal file
|
@ -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 <uefi.h>
|
||||||
|
|
||||||
|
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);*/
|
||||||
|
}
|
406
uefi/stdio.c
Normal file
406
uefi/stdio.c
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
/**
|
||||||
|
* 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 <uefi.h>
|
||||||
|
|
||||||
|
static efi_file_handle_t *__root_dir = NULL;
|
||||||
|
|
||||||
|
void __stdio_init()
|
||||||
|
{
|
||||||
|
efi_status_t status;
|
||||||
|
efi_guid_t sfsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
||||||
|
efi_simple_file_system_protocol_t *sfs = NULL;
|
||||||
|
if(!__root_dir && LIP) {
|
||||||
|
status = uefi_call_wrapper(BS->HandleProtocol, 3, LIP->DeviceHandle, &sfsGuid, &sfs);
|
||||||
|
if(!EFI_ERROR(status))
|
||||||
|
status = uefi_call_wrapper(sfs->OpenVolume, 2, sfs, &__root_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fclose (FILE *__stream)
|
||||||
|
{
|
||||||
|
efi_status_t status = uefi_call_wrapper(__stream->Close, 1, __stream);
|
||||||
|
free(__stream);
|
||||||
|
return !EFI_ERROR(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fflush (FILE *__stream)
|
||||||
|
{
|
||||||
|
efi_status_t status = uefi_call_wrapper(__stream->Flush, 1, __stream);
|
||||||
|
return !EFI_ERROR(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fopen (const wchar_t *__filename, const char *__modes)
|
||||||
|
{
|
||||||
|
FILE *ret;
|
||||||
|
efi_status_t status;
|
||||||
|
__stdio_init();
|
||||||
|
errno = 0;
|
||||||
|
if(!__root_dir) {
|
||||||
|
errno = ENODEV;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = (FILE*)malloc(sizeof(FILE));
|
||||||
|
if(!ret) return NULL;
|
||||||
|
status = uefi_call_wrapper(__root_dir->Open, 5, __root_dir, ret, __filename,
|
||||||
|
__modes[0] == L'r' ? EFI_FILE_MODE_READ : (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), 0);
|
||||||
|
if(EFI_ERROR(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;
|
||||||
|
default: errno = EIO; break;
|
||||||
|
}
|
||||||
|
free(ret); ret = NULL;
|
||||||
|
}
|
||||||
|
if(__modes[0] == L'a') fseek(ret, 0, SEEK_END);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fread (void *__ptr, size_t __size, size_t __n, FILE *__stream)
|
||||||
|
{
|
||||||
|
uintn_t bs = __size * __n;
|
||||||
|
efi_status_t status = uefi_call_wrapper(__stream->Read, 3, __stream, &bs, __ptr);
|
||||||
|
if(status == EFI_END_OF_FILE) bs = 0;
|
||||||
|
return bs / __size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fwrite (const void *__ptr, size_t __size, size_t __n, FILE *__stream)
|
||||||
|
{
|
||||||
|
uintn_t bs = __size * __n;
|
||||||
|
efi_status_t status = uefi_call_wrapper(__stream->Write, 3, __stream, &bs, __ptr);
|
||||||
|
return bs / __size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fseek (FILE *__stream, long int __off, int __whence)
|
||||||
|
{
|
||||||
|
uint64_t off = 0;
|
||||||
|
efi_status_t status;
|
||||||
|
efi_guid_t infoGuid = EFI_FILE_INFO_GUID;
|
||||||
|
efi_file_info_t *info;
|
||||||
|
uintn_t infosiz = sizeof(efi_file_info_t) + 16;
|
||||||
|
switch(__whence) {
|
||||||
|
case SEEK_END:
|
||||||
|
status = uefi_call_wrapper(__stream->GetInfo, 4, __stream, &infoGuid, &infosiz, info);
|
||||||
|
if(!EFI_ERROR(status)) {
|
||||||
|
off = info->FileSize + __off;
|
||||||
|
status = uefi_call_wrapper(__stream->SetPosition, 2, __stream, &off);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
status = uefi_call_wrapper(__stream->GetPosition, 2, __stream, &off);
|
||||||
|
if(!EFI_ERROR(status)) {
|
||||||
|
off += __off;
|
||||||
|
status = uefi_call_wrapper(__stream->SetPosition, 2, __stream, &off);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = uefi_call_wrapper(__stream->SetPosition, 2, __stream, &off);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return EFI_ERROR(status) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long int ftell (FILE *__stream)
|
||||||
|
{
|
||||||
|
uint64_t off = 0;
|
||||||
|
efi_status_t status = uefi_call_wrapper(__stream->GetPosition, 2, __stream, &off);
|
||||||
|
return EFI_ERROR(status) ? -1 : (long int)off;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsnprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
#define needsescape(a) (a==L'\"' || a==L'\\' || a==L'\a' || a==L'\b' || a==L'\033' || a=='\f' || \
|
||||||
|
a==L'\r' || a==L'\n' || a==L'\t' || a=='\v')
|
||||||
|
long int arg;
|
||||||
|
int len, sign, i;
|
||||||
|
wchar_t *p, *orig=dst, tmpstr[19], pad=' ';
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
if(dst==NULL || fmt==NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arg = 0;
|
||||||
|
while(*fmt && (dst - orig) + 1 < maxlen) {
|
||||||
|
if(*fmt==L'%') {
|
||||||
|
fmt++;
|
||||||
|
if(*fmt==L'%') goto put;
|
||||||
|
len=0;
|
||||||
|
if(*fmt==L'0') pad=L'0';
|
||||||
|
while(*fmt>=L'0' && *fmt<=L'9') {
|
||||||
|
len *= 10;
|
||||||
|
len += *fmt-L'0';
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
if(*fmt==L'l') fmt++;
|
||||||
|
if(*fmt==L'c') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
*dst++ = (wchar_t)(arg & 0xffff);
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
if(*fmt==L'C') {
|
||||||
|
c = __builtin_va_arg(args, char*);
|
||||||
|
arg = *c;
|
||||||
|
if((*c & 128) != 0) {
|
||||||
|
if((*c & 32) == 0 ) { arg = ((*c & 0x1F)<<6)|(*(c+1) & 0x3F); } else
|
||||||
|
if((*c & 16) == 0 ) { arg = ((*c & 0xF)<<12)|((*(c+1) & 0x3F)<<6)|(*(c+2) & 0x3F); } else
|
||||||
|
if((*c & 8) == 0 ) { arg = ((*c & 0x7)<<18)|((*(c+1) & 0x3F)<<12)|((*(c+2) & 0x3F)<<6)|(*(c+3) & 0x3F); }
|
||||||
|
else arg = L'?';
|
||||||
|
}
|
||||||
|
*dst++ = (wchar_t)(arg & 0xffff);
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
if(*fmt==L'd') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
sign=0;
|
||||||
|
if((int)arg<0) {
|
||||||
|
arg*=-1;
|
||||||
|
sign++;
|
||||||
|
}
|
||||||
|
if(arg>99999999999999999L) {
|
||||||
|
arg=99999999999999999L;
|
||||||
|
}
|
||||||
|
i=18;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
tmpstr[--i]=L'0'+(arg%10);
|
||||||
|
arg/=10;
|
||||||
|
} while(arg!=0 && i>0);
|
||||||
|
if(sign) {
|
||||||
|
tmpstr[--i]=L'-';
|
||||||
|
}
|
||||||
|
if(len>0 && len<18) {
|
||||||
|
while(i>18-len) {
|
||||||
|
tmpstr[--i]=pad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
if(*fmt==L'p' || *fmt==L'P') {
|
||||||
|
arg = __builtin_va_arg(args, uint64_t);
|
||||||
|
len = 16; pad = L'0'; goto hex;
|
||||||
|
} else
|
||||||
|
if(*fmt==L'x' || *fmt==L'X' || *fmt==L'p') {
|
||||||
|
arg = __builtin_va_arg(args, long int);
|
||||||
|
if(*fmt==L'p') { len = 16; pad = L'0'; }
|
||||||
|
hex: i=16;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
wchar_t n=arg & 0xf;
|
||||||
|
/* 0-9 => '0'-'9', 10-15 => 'A'-'F' */
|
||||||
|
tmpstr[--i]=n+(n>9?(*fmt==L'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]=L'0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
if(*fmt==L's' || *fmt==L'q') {
|
||||||
|
p = __builtin_va_arg(args, wchar_t*);
|
||||||
|
copystring: if(p==NULL) {
|
||||||
|
p=L"(null)";
|
||||||
|
}
|
||||||
|
while(*p && (dst - orig) + 2 < maxlen) {
|
||||||
|
if(*fmt==L'q' && needsescape(*p)) {
|
||||||
|
*dst++ = L'\\';
|
||||||
|
switch(*p) {
|
||||||
|
case L'\a': *dst++ = L'a'; break;
|
||||||
|
case L'\b': *dst++ = L'b'; break;
|
||||||
|
case L'\e': *dst++ = L'e'; break;
|
||||||
|
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++ = *p++; break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
*dst++ = *p++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if(*fmt==L'S' || *fmt==L'Q') {
|
||||||
|
c = __builtin_va_arg(args, char*);
|
||||||
|
if(c==NULL) goto copystring;
|
||||||
|
while(*p && (dst - orig) + 2 < maxlen) {
|
||||||
|
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 L'\e': *dst++ = L'e'; break;
|
||||||
|
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
|
||||||
|
*dst++ = (wchar_t)(arg & 0xffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
put: *dst++ = *fmt;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
*dst=0;
|
||||||
|
return dst-orig;
|
||||||
|
#undef needsescape
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsprintf(wchar_t *dst, const wchar_t *fmt, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
return vsnprintf(dst, BUFSIZ, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprintf(wchar_t *dst, const wchar_t* fmt, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
return vsnprintf(dst, BUFSIZ, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int snprintf(wchar_t *dst, size_t maxlen, const wchar_t* fmt, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
return vsnprintf(dst, maxlen, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vprintf(const wchar_t* fmt, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
wchar_t dst[BUFSIZ];
|
||||||
|
int ret;
|
||||||
|
ret = vsnprintf(dst, sizeof(dst), fmt, args);
|
||||||
|
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, &dst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printf(const wchar_t* fmt, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
return vprintf(fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfprintf (FILE *__stream, const wchar_t *__format, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
wchar_t dst[BUFSIZ];
|
||||||
|
int ret;
|
||||||
|
if(__stream == stdin) return 0;
|
||||||
|
ret = vsnprintf(dst, sizeof(dst), __format, args);
|
||||||
|
if(ret < 1) return 0;
|
||||||
|
if(__stream == stdout)
|
||||||
|
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, &dst);
|
||||||
|
else if(__stream == stderr)
|
||||||
|
uefi_call_wrapper(ST->StdErr->OutputString, 2, ST->StdErr, &dst);
|
||||||
|
else
|
||||||
|
uefi_call_wrapper(__stream->Write, 3, __stream, &ret, &dst);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fprintf (FILE *__stream, const wchar_t *__format, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, __format);
|
||||||
|
return vfprintf(__stream, __format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getchar (void)
|
||||||
|
{
|
||||||
|
efi_input_key_t key;
|
||||||
|
efi_status_t status = uefi_call_wrapper(ST->ConIn, 2, ST->ConIn, &key);
|
||||||
|
return EFI_ERROR(status) ? -1 : key.UnicodeChar;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int getchar_ifany (void)
|
||||||
|
{
|
||||||
|
efi_input_key_t key;
|
||||||
|
efi_status_t status = uefi_call_wrapper(BS->CheckEvent, 1, ST->ConIn->WaitForKey);
|
||||||
|
if(!status) {
|
||||||
|
status = uefi_call_wrapper(ST->ConIn, 2, ST->ConIn, &key);
|
||||||
|
return EFI_ERROR(status) ? -1 : key.UnicodeChar;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int putchar (int __c)
|
||||||
|
{
|
||||||
|
wchar_t tmp[2];
|
||||||
|
tmp[0] = (wchar_t)__c;
|
||||||
|
tmp[1] = 0;
|
||||||
|
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, &tmp);
|
||||||
|
return (int)tmp[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this isn't POSIX, but also uses sprintf */
|
||||||
|
void uefi_dumpmem(efi_physical_address_t address)
|
||||||
|
{
|
||||||
|
uint8_t *mem = (uint8_t*)(address & ~0xF);
|
||||||
|
int i, j;
|
||||||
|
wchar_t tmp[128], *t;
|
||||||
|
for(j = 0; j < 8; j++) {
|
||||||
|
t = tmp + sprintf(tmp, L"%p: ");
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
t += sprintf(t, L"%02x %s", mem[i], i % 4 == 3 ? L" " : L"");
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
t += sprintf(t, L" %c", mem[i] < 32 || mem[i] >= 127 ? L'.' : mem[i]);
|
||||||
|
uefi_call_wrapper(ST->StdErr->OutputString, 2, ST->StdErr, &tmp);
|
||||||
|
mem += 16;
|
||||||
|
}
|
||||||
|
}
|
214
uefi/stdlib.c
Normal file
214
uefi/stdlib.c
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* 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 <uefi.h>
|
||||||
|
|
||||||
|
int atoi(const wchar_t *s)
|
||||||
|
{
|
||||||
|
return (int)atol(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
long int atol(const wchar_t *s)
|
||||||
|
{
|
||||||
|
long int sign = 1;
|
||||||
|
if(!s || !*s) return 0;
|
||||||
|
if(*s == '-') { sign = -1; s++; }
|
||||||
|
if(s[0] == '0') {
|
||||||
|
if(s[1] == 'x')
|
||||||
|
return strtol(s + 2, NULL, 16);
|
||||||
|
if(s[1] >= '0' && s[1] <= '7')
|
||||||
|
return strtol(s, NULL, 8);
|
||||||
|
}
|
||||||
|
return strtol(s, NULL, 10) * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
long int strtol (const wchar_t *s, wchar_t **__endptr, int __base)
|
||||||
|
{
|
||||||
|
long int v=0, sign = 1;
|
||||||
|
if(!s || !*s) return 0;
|
||||||
|
if(*s == '-') { sign = -1; s++; }
|
||||||
|
while(*s < L'0' || (__base < 10 && *s >= __base + L'0') || (__base > 10 && ((*s > L'9' && *s < L'A') ||
|
||||||
|
(*s > L'F' && *s < L'a') || *s > L'f'))) {
|
||||||
|
v *= __base;
|
||||||
|
if(*s >= L'0' && *s < (__base < 10 ? __base + L'0' : L'9'))
|
||||||
|
v += (*s)-L'0';
|
||||||
|
else if(__base == 16 && *s >= L'a' && *s <= L'f')
|
||||||
|
v += (*s)-L'a'+10;
|
||||||
|
else if(__base == 16 && *s >= L'A' && *s <= L'F')
|
||||||
|
v += (*s)-L'A'+10;
|
||||||
|
s++;
|
||||||
|
};
|
||||||
|
if(__endptr) *__endptr = (wchar_t*)s;
|
||||||
|
return v * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *malloc (size_t __size)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
efi_status_t status = uefi_call_wrapper(BS->AllocatePool, 3, LIP ? LIP->ImageDataType : EfiLoaderData, __size, &ret);
|
||||||
|
if(!EFI_ERROR(status) || !ret) errno = ENOMEM;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *calloc (size_t __nmemb, size_t __size)
|
||||||
|
{
|
||||||
|
void *ret = malloc(__nmemb * __size);
|
||||||
|
if(ret) __builtin_memset(ret, 0, __nmemb * __size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *realloc (void *__ptr, size_t __size)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
void *ret = __ptr;
|
||||||
|
/* not sure if this works */
|
||||||
|
efi_status_t status = uefi_call_wrapper(BS->AllocatePool, 3, LIP ? LIP->ImageDataType : EfiLoaderData, __size, &ret);
|
||||||
|
if(!EFI_ERROR(status) || !ret) errno = ENOMEM;
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
void *ret = malloc(__size);
|
||||||
|
/* this isn't perfect, because we don't know the original size... */
|
||||||
|
if(ret && __ptr) __builtin_memcpy(ret, __ptr, __size);
|
||||||
|
if(__ptr) free(__ptr);
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void free (void *__ptr)
|
||||||
|
{
|
||||||
|
efi_status_t status = uefi_call_wrapper(BS->FreePool, 1, __ptr);
|
||||||
|
if(!EFI_ERROR(status)) errno = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void abort ()
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(BS->Exit, 4, IM, EFI_ABORTED, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit (int __status)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(BS->Exit, 4, IM, !__status ? 0 : (__status < 0 ? EFIERR(-__status) : EFIERR(__status)), 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
const char *orig = s;
|
||||||
|
arg = (wchar_t)*s;
|
||||||
|
if((*s & 128) != 0) {
|
||||||
|
if((*s & 32) == 0 && n > 0) { arg = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); } else
|
||||||
|
if((*s & 16) == 0 && n > 1) { arg = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); } else
|
||||||
|
if((*s & 8) == 0 && n > 2) { arg = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); }
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
if(__pwc) *__pwc = arg;
|
||||||
|
return s - orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 if(u<0x10000) {
|
||||||
|
*(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;
|
||||||
|
size_t ret = 0;
|
||||||
|
if(!__s || !*__s) return 0;
|
||||||
|
while(*__s) {
|
||||||
|
r = mbtowc(__pwcs, __s, __n - ret);
|
||||||
|
if(r < 0) return (size_t)-1;
|
||||||
|
__pwcs++;
|
||||||
|
__s += r;
|
||||||
|
};
|
||||||
|
return __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 && (__s - orig + 3 < __n)) {
|
||||||
|
r = wctomb(__s, *__pwcs);
|
||||||
|
if(r < 0) return (size_t)-1;
|
||||||
|
__pwcs++;
|
||||||
|
__s += r;
|
||||||
|
};
|
||||||
|
return __s - orig;
|
||||||
|
}
|
||||||
|
|
197
uefi/string.c
Normal file
197
uefi/string.c
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* 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 <uefi.h>
|
||||||
|
|
||||||
|
void *memmem(const void *haystack, size_t hl, const void *needle, size_t nl)
|
||||||
|
{
|
||||||
|
char *c = (char*)haystack;
|
||||||
|
if(!haystack || !needle || !hl || !nl || nl > hl) return NULL;
|
||||||
|
hl -= nl;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
char *c = (char*)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;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strcpy(wchar_t *dst, const wchar_t *src)
|
||||||
|
{
|
||||||
|
if(src && dst) {
|
||||||
|
while(*src) {*dst++=*src++;} *dst=0;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strncpy(wchar_t *dst, const wchar_t *src, size_t n)
|
||||||
|
{
|
||||||
|
const wchar_t *e = src+n;
|
||||||
|
if(src && dst && n>0) {
|
||||||
|
while(*src && src<e) {*dst++=*src++;} *dst=0;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strcat(wchar_t *dst, const wchar_t *src)
|
||||||
|
{
|
||||||
|
if(src && dst) {
|
||||||
|
dst += strlen(dst);
|
||||||
|
while(*src) {*dst++=*src++;} *dst=0;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const wchar_t *s1, const wchar_t *s2)
|
||||||
|
{
|
||||||
|
if(s1 && s2 && s1!=s2) {
|
||||||
|
do{if(*s1!=*s2){return *s1-*s2;}s1++;s2++;}while(*s1!=0);
|
||||||
|
return *s1-*s2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strncat(wchar_t *dst, const wchar_t *src, size_t n)
|
||||||
|
{
|
||||||
|
const wchar_t *e = src+n;
|
||||||
|
if(src && dst && n>0) {
|
||||||
|
dst += strlen(dst);
|
||||||
|
while(*src && src<e) {*dst++=*src++;} *dst=0;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
|
||||||
|
{
|
||||||
|
const wchar_t *e = s1+n;
|
||||||
|
if(s1 && s2 && s1!=s2 && n>0) {
|
||||||
|
do{if(*s1!=*s2){return *s1-*s2;}s1++;s2++;}while(*s1!=0 && s1<e);
|
||||||
|
return *s1-*s2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strdup(const wchar_t *s)
|
||||||
|
{
|
||||||
|
int i = (strlen(s)+1) * sizeof(wchar_t);
|
||||||
|
wchar_t *s2 = (wchar_t *)malloc(i);
|
||||||
|
if(s2 != NULL) memcpy(s2, (void*)s, i);
|
||||||
|
return s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strchr(const wchar_t *s, int c)
|
||||||
|
{
|
||||||
|
if(s) {
|
||||||
|
while(*s) {
|
||||||
|
if(*s == (wchar_t)c) return (wchar_t*)s;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strrchr(const wchar_t *s, int c)
|
||||||
|
{
|
||||||
|
wchar_t *e;
|
||||||
|
if(s) {
|
||||||
|
e = (wchar_t*)s + strlen(s) - 1;
|
||||||
|
while(s < e) {
|
||||||
|
if(*e == (wchar_t)c) return e;
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strstr(const wchar_t *haystack, const wchar_t *needle)
|
||||||
|
{
|
||||||
|
return memmem(haystack, strlen(haystack) * sizeof(wchar_t), needle, strlen(needle) * sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *_strtok_r(wchar_t *s, const wchar_t *d, wchar_t **p)
|
||||||
|
{
|
||||||
|
int c, sc;
|
||||||
|
wchar_t *tok, *sp;
|
||||||
|
|
||||||
|
if(d == NULL || (s == NULL && (s=*p) == NULL)) return NULL;
|
||||||
|
again:
|
||||||
|
c = *s++;
|
||||||
|
for(sp = (wchar_t *)d; (sc=*sp++)!=0;) {
|
||||||
|
if(c == sc) { *p=s; *(s-1)=0; return s-1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 0) { *p=NULL; return NULL; }
|
||||||
|
tok = s-1;
|
||||||
|
while(1) {
|
||||||
|
c = *s++;
|
||||||
|
sp = (wchar_t *)d;
|
||||||
|
do {
|
||||||
|
if((sc=*sp++) == c) {
|
||||||
|
if(c == 0) s = NULL;
|
||||||
|
else *(s-1) = 0;
|
||||||
|
*p = s;
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
} while(sc != 0);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strtok(wchar_t *s, const wchar_t *delim)
|
||||||
|
{
|
||||||
|
wchar_t *p = s;
|
||||||
|
return _strtok_r (s, delim, &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t *strtok_r(wchar_t *s, const wchar_t *delim, wchar_t **ptr)
|
||||||
|
{
|
||||||
|
return _strtok_r (s, delim, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strlen (const wchar_t *__s)
|
||||||
|
{
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if(!__s) return 0;
|
||||||
|
for(ret = 0; __s[ret]; ret++);
|
||||||
|
return ret;
|
||||||
|
}
|
50
uefi/time.c
Normal file
50
uefi/time.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* time.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 time.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <uefi.h>
|
||||||
|
|
||||||
|
static struct tm __tm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This isn't POSIX, no arguments. Just returns the current time in struct tm
|
||||||
|
*/
|
||||||
|
struct tm *localtime ()
|
||||||
|
{
|
||||||
|
efi_time_t t;
|
||||||
|
uefi_call_wrapper(ST->RuntimeServices->GetTime, 2, &t, NULL);
|
||||||
|
__tm.tm_year = t.Year + 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 &__tm;
|
||||||
|
}
|
1339
uefi/uefi.h
Normal file
1339
uefi/uefi.h
Normal file
File diff suppressed because it is too large
Load diff
469
uefi/uefielf.h
Normal file
469
uefi/uefielf.h
Normal file
|
@ -0,0 +1,469 @@
|
||||||
|
/*
|
||||||
|
* uefielf.h
|
||||||
|
*
|
||||||
|
* 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 Definitions for the Executable and Linkable Format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UEFIELF_H
|
||||||
|
#define _UEFIELF_H 1
|
||||||
|
|
||||||
|
#ifndef _UEFI_H_
|
||||||
|
#error "include uefi.h instead"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Standard ELF types. */
|
||||||
|
|
||||||
|
/* Type for a 16-bit quantity. */
|
||||||
|
typedef uint16_t Elf64_Half;
|
||||||
|
|
||||||
|
/* Types for signed and unsigned 32-bit quantities. */
|
||||||
|
typedef uint32_t Elf64_Word;
|
||||||
|
typedef int32_t Elf64_Sword;
|
||||||
|
|
||||||
|
/* Types for signed and unsigned 64-bit quantities. */
|
||||||
|
typedef uint64_t Elf64_Xword;
|
||||||
|
typedef int64_t Elf64_Sxword;
|
||||||
|
|
||||||
|
/* Type of addresses. */
|
||||||
|
typedef uint64_t Elf64_Addr;
|
||||||
|
|
||||||
|
/* Type of file offsets. */
|
||||||
|
typedef uint64_t Elf64_Off;
|
||||||
|
|
||||||
|
/* Type for section indices, which are 16-bit quantities. */
|
||||||
|
typedef uint16_t Elf64_Section;
|
||||||
|
|
||||||
|
/* Type for version symbol information. */
|
||||||
|
typedef Elf64_Half Elf64_Versym;
|
||||||
|
|
||||||
|
|
||||||
|
/* The ELF file header. This appears at the start of every ELF file. */
|
||||||
|
|
||||||
|
#define EI_NIDENT (16)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||||
|
Elf64_Half e_type; /* Object file type */
|
||||||
|
Elf64_Half e_machine; /* Architecture */
|
||||||
|
Elf64_Word e_version; /* Object file version */
|
||||||
|
Elf64_Addr e_entry; /* Entry point virtual address */
|
||||||
|
Elf64_Off e_phoff; /* Program header table file offset */
|
||||||
|
Elf64_Off e_shoff; /* Section header table file offset */
|
||||||
|
Elf64_Word e_flags; /* Processor-specific flags */
|
||||||
|
Elf64_Half e_ehsize; /* ELF header size in bytes */
|
||||||
|
Elf64_Half e_phentsize; /* Program header table entry size */
|
||||||
|
Elf64_Half e_phnum; /* Program header table entry count */
|
||||||
|
Elf64_Half e_shentsize; /* Section header table entry size */
|
||||||
|
Elf64_Half e_shnum; /* Section header table entry count */
|
||||||
|
Elf64_Half e_shstrndx; /* Section header string table index */
|
||||||
|
} Elf64_Ehdr;
|
||||||
|
|
||||||
|
/* Fields in the e_ident array. The EI_* macros are indices into the
|
||||||
|
array. The macros under each EI_* macro are the values the byte
|
||||||
|
may have. */
|
||||||
|
|
||||||
|
#define EI_MAG0 0 /* File identification byte 0 index */
|
||||||
|
#define ELFMAG0 0x7f /* Magic number byte 0 */
|
||||||
|
|
||||||
|
#define EI_MAG1 1 /* File identification byte 1 index */
|
||||||
|
#define ELFMAG1 'E' /* Magic number byte 1 */
|
||||||
|
|
||||||
|
#define EI_MAG2 2 /* File identification byte 2 index */
|
||||||
|
#define ELFMAG2 'L' /* Magic number byte 2 */
|
||||||
|
|
||||||
|
#define EI_MAG3 3 /* File identification byte 3 index */
|
||||||
|
#define ELFMAG3 'F' /* Magic number byte 3 */
|
||||||
|
|
||||||
|
/* Conglomeration of the identification bytes, for easy testing as a word. */
|
||||||
|
#define ELFMAG "\177ELF"
|
||||||
|
#define SELFMAG 4
|
||||||
|
|
||||||
|
#define EI_CLASS 4 /* File class byte index */
|
||||||
|
#define ELFCLASSNONE 0 /* Invalid class */
|
||||||
|
#define ELFCLASS32 1 /* 32-bit objects */
|
||||||
|
#define ELFCLASS64 2 /* 64-bit objects */
|
||||||
|
#define ELFCLASSNUM 3
|
||||||
|
|
||||||
|
#define EI_DATA 5 /* Data encoding byte index */
|
||||||
|
#define ELFDATANONE 0 /* Invalid data encoding */
|
||||||
|
#define ELFDATA2LSB 1 /* 2's complement, little endian */
|
||||||
|
#define ELFDATA2MSB 2 /* 2's complement, big endian */
|
||||||
|
#define ELFDATANUM 3
|
||||||
|
|
||||||
|
#define EI_VERSION 6 /* File version byte index */
|
||||||
|
/* Value must be EV_CURRENT */
|
||||||
|
|
||||||
|
#define EI_OSABI 7 /* OS ABI identification */
|
||||||
|
#define ELFOSABI_NONE 0 /* UNIX System V ABI */
|
||||||
|
#define ELFOSABI_SYSV 0 /* Alias. */
|
||||||
|
#define ELFOSABI_HPUX 1 /* HP-UX */
|
||||||
|
#define ELFOSABI_NETBSD 2 /* NetBSD. */
|
||||||
|
#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */
|
||||||
|
#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */
|
||||||
|
#define ELFOSABI_OSZ 5 /* OS/Z. (86Open was dissolved in 1999) */
|
||||||
|
#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
|
||||||
|
#define ELFOSABI_AIX 7 /* IBM AIX. */
|
||||||
|
#define ELFOSABI_IRIX 8 /* SGI Irix. */
|
||||||
|
#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
|
||||||
|
#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
|
||||||
|
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
|
||||||
|
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
|
||||||
|
#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
|
||||||
|
#define ELFOSABI_ARM 97 /* ARM */
|
||||||
|
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
||||||
|
|
||||||
|
#define EI_ABIVERSION 8 /* ABI version */
|
||||||
|
|
||||||
|
#define EI_PAD 9 /* Byte index of padding bytes */
|
||||||
|
|
||||||
|
/* Legal values for e_type (object file type). */
|
||||||
|
|
||||||
|
#define ET_NONE 0 /* No file type */
|
||||||
|
#define ET_REL 1 /* Relocatable file */
|
||||||
|
#define ET_EXEC 2 /* Executable file */
|
||||||
|
#define ET_DYN 3 /* Shared object file */
|
||||||
|
#define ET_CORE 4 /* Core file */
|
||||||
|
#define ET_NUM 5 /* Number of defined types */
|
||||||
|
#define ET_LOOS 0xfe00 /* OS-specific range start */
|
||||||
|
#define ET_HIOS 0xfeff /* OS-specific range end */
|
||||||
|
#define ET_LOPROC 0xff00 /* Processor-specific range start */
|
||||||
|
#define ET_HIPROC 0xffff /* Processor-specific range end */
|
||||||
|
|
||||||
|
/* Legal values for e_machine (architecture). */
|
||||||
|
|
||||||
|
#define EM_NONE 0 /* No machine */
|
||||||
|
#define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||||
|
#define EM_AARCH64 183 /* ARM aarch64 architecture */
|
||||||
|
|
||||||
|
/* Legal values for e_version (version). */
|
||||||
|
|
||||||
|
#define EV_NONE 0 /* Invalid ELF version */
|
||||||
|
#define EV_CURRENT 1 /* Current version */
|
||||||
|
#define EV_NUM 2
|
||||||
|
|
||||||
|
/* Section header. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word sh_name; /* Section name (string tbl index) */
|
||||||
|
Elf64_Word sh_type; /* Section type */
|
||||||
|
Elf64_Xword sh_flags; /* Section flags */
|
||||||
|
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||||
|
Elf64_Off sh_offset; /* Section file offset */
|
||||||
|
Elf64_Xword sh_size; /* Section size in bytes */
|
||||||
|
Elf64_Word sh_link; /* Link to another section */
|
||||||
|
Elf64_Word sh_info; /* Additional section information */
|
||||||
|
Elf64_Xword sh_addralign; /* Section alignment */
|
||||||
|
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||||
|
} Elf64_Shdr;
|
||||||
|
|
||||||
|
/* Special section indices. */
|
||||||
|
|
||||||
|
#define SHN_UNDEF 0 /* Undefined section */
|
||||||
|
#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
|
||||||
|
#define SHN_LOPROC 0xff00 /* Start of processor-specific */
|
||||||
|
#define SHN_BEFORE 0xff00 /* Order section before all others
|
||||||
|
(Solaris). */
|
||||||
|
#define SHN_AFTER 0xff01 /* Order section after all others
|
||||||
|
(Solaris). */
|
||||||
|
#define SHN_HIPROC 0xff1f /* End of processor-specific */
|
||||||
|
#define SHN_LOOS 0xff20 /* Start of OS-specific */
|
||||||
|
#define SHN_HIOS 0xff3f /* End of OS-specific */
|
||||||
|
#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
|
||||||
|
#define SHN_COMMON 0xfff2 /* Associated symbol is common */
|
||||||
|
#define SHN_XINDEX 0xffff /* Index is in extra table. */
|
||||||
|
#define SHN_HIRESERVE 0xffff /* End of reserved indices */
|
||||||
|
|
||||||
|
/* Legal values for sh_type (section type). */
|
||||||
|
|
||||||
|
#define SHT_NULL 0 /* Section header table entry unused */
|
||||||
|
#define SHT_PROGBITS 1 /* Program data */
|
||||||
|
#define SHT_SYMTAB 2 /* Symbol table */
|
||||||
|
#define SHT_STRTAB 3 /* String table */
|
||||||
|
#define SHT_RELA 4 /* Relocation entries with addends */
|
||||||
|
#define SHT_HASH 5 /* Symbol hash table */
|
||||||
|
#define SHT_DYNAMIC 6 /* Dynamic linking information */
|
||||||
|
#define SHT_NOTE 7 /* Notes */
|
||||||
|
#define SHT_NOBITS 8 /* Program space with no data (bss) */
|
||||||
|
#define SHT_REL 9 /* Relocation entries, no addends */
|
||||||
|
#define SHT_SHLIB 10 /* Reserved */
|
||||||
|
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
||||||
|
#define SHT_INIT_ARRAY 14 /* Array of constructors */
|
||||||
|
#define SHT_FINI_ARRAY 15 /* Array of destructors */
|
||||||
|
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
||||||
|
#define SHT_GROUP 17 /* Section group */
|
||||||
|
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
||||||
|
#define SHT_NUM 19 /* Number of defined types. */
|
||||||
|
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
|
||||||
|
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
|
||||||
|
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
|
||||||
|
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
|
||||||
|
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
|
||||||
|
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
|
||||||
|
#define SHT_SUNW_move 0x6ffffffa
|
||||||
|
#define SHT_SUNW_COMDAT 0x6ffffffb
|
||||||
|
#define SHT_SUNW_syminfo 0x6ffffffc
|
||||||
|
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
|
||||||
|
#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
|
||||||
|
#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
|
||||||
|
#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
|
||||||
|
#define SHT_HIOS 0x6fffffff /* End OS-specific type */
|
||||||
|
#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||||
|
#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||||
|
#define SHT_LOUSER 0x80000000 /* Start of application-specific */
|
||||||
|
#define SHT_HIUSER 0x8fffffff /* End of application-specific */
|
||||||
|
|
||||||
|
/* Legal values for sh_flags (section flags). */
|
||||||
|
|
||||||
|
#define SHF_WRITE (1 << 0) /* Writable */
|
||||||
|
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
|
||||||
|
#define SHF_EXECINSTR (1 << 2) /* Executable */
|
||||||
|
#define SHF_MERGE (1 << 4) /* Might be merged */
|
||||||
|
#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
|
||||||
|
#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
|
||||||
|
#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
|
||||||
|
#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
|
||||||
|
required */
|
||||||
|
#define SHF_GROUP (1 << 9) /* Section is member of a group. */
|
||||||
|
#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
|
||||||
|
#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
|
||||||
|
#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
|
||||||
|
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||||
|
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
|
||||||
|
(Solaris). */
|
||||||
|
#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
|
||||||
|
referenced or allocated (Solaris).*/
|
||||||
|
|
||||||
|
/* Section compression header. Used when SHF_COMPRESSED is set. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word ch_type; /* Compression format. */
|
||||||
|
Elf64_Word ch_reserved;
|
||||||
|
Elf64_Xword ch_size; /* Uncompressed data size. */
|
||||||
|
Elf64_Xword ch_addralign; /* Uncompressed data alignment. */
|
||||||
|
} Elf64_Chdr;
|
||||||
|
|
||||||
|
/* Legal values for ch_type (compression algorithm). */
|
||||||
|
#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */
|
||||||
|
#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */
|
||||||
|
#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */
|
||||||
|
#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */
|
||||||
|
#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */
|
||||||
|
|
||||||
|
/* Section group handling. */
|
||||||
|
#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
|
||||||
|
|
||||||
|
/* Symbol table entry. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word st_name; /* Symbol name (string tbl index) */
|
||||||
|
unsigned char st_info; /* Symbol type and binding */
|
||||||
|
unsigned char st_other; /* Symbol visibility */
|
||||||
|
Elf64_Section st_shndx; /* Section index */
|
||||||
|
Elf64_Addr st_value; /* Symbol value */
|
||||||
|
Elf64_Xword st_size; /* Symbol size */
|
||||||
|
} Elf64_Sym;
|
||||||
|
|
||||||
|
/* How to extract and insert information held in the st_info field. */
|
||||||
|
|
||||||
|
#define ELF64_ST_BIND(val) (((unsigned char) (val)) >> 4)
|
||||||
|
#define ELF64_ST_TYPE(val) ((val) & 0xf)
|
||||||
|
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||||
|
|
||||||
|
/* Legal values for ST_BIND subfield of st_info (symbol binding). */
|
||||||
|
|
||||||
|
#define STB_LOCAL 0 /* Local symbol */
|
||||||
|
#define STB_GLOBAL 1 /* Global symbol */
|
||||||
|
#define STB_WEAK 2 /* Weak symbol */
|
||||||
|
#define STB_NUM 3 /* Number of defined types. */
|
||||||
|
|
||||||
|
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
|
||||||
|
|
||||||
|
#define STT_NOTYPE 0 /* Symbol type is unspecified */
|
||||||
|
#define STT_OBJECT 1 /* Symbol is a data object */
|
||||||
|
#define STT_FUNC 2 /* Symbol is a code object */
|
||||||
|
#define STT_SECTION 3 /* Symbol associated with a section */
|
||||||
|
#define STT_FILE 4 /* Symbol's name is file name */
|
||||||
|
#define STT_COMMON 5 /* Symbol is a common data object */
|
||||||
|
#define STT_TLS 6 /* Symbol is thread-local data object*/
|
||||||
|
#define STT_NUM 7 /* Number of defined types. */
|
||||||
|
#define STT_LOOS 10 /* Start of OS-specific */
|
||||||
|
#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */
|
||||||
|
#define STT_HIOS 12 /* End of OS-specific */
|
||||||
|
#define STT_LOPROC 13 /* Start of processor-specific */
|
||||||
|
#define STT_HIPROC 15 /* End of processor-specific */
|
||||||
|
|
||||||
|
/* How to extract and insert information held in the st_other field. */
|
||||||
|
|
||||||
|
#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
|
||||||
|
|
||||||
|
/* Symbol visibility specification encoded in the st_other field. */
|
||||||
|
#define STV_DEFAULT 0 /* Default symbol visibility rules */
|
||||||
|
#define STV_INTERNAL 1 /* Processor specific hidden class */
|
||||||
|
#define STV_HIDDEN 2 /* Sym unavailable in other modules */
|
||||||
|
#define STV_PROTECTED 3 /* Not preemptible, not exported */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Addr r_offset; /* Address */
|
||||||
|
Elf64_Xword r_info; /* Relocation type and symbol index */
|
||||||
|
} Elf64_Rel;
|
||||||
|
|
||||||
|
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Addr r_offset; /* Address */
|
||||||
|
Elf64_Xword r_info; /* Relocation type and symbol index */
|
||||||
|
Elf64_Sxword r_addend; /* Addend */
|
||||||
|
} Elf64_Rela;
|
||||||
|
|
||||||
|
/* How to extract and insert information held in the r_info field. */
|
||||||
|
|
||||||
|
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||||
|
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
|
||||||
|
#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
|
||||||
|
|
||||||
|
/* Values for ELF64_R_TYPE */
|
||||||
|
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
|
||||||
|
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
|
||||||
|
#define R_X86_64_RELATIVE 8 /* Adjust by program base */
|
||||||
|
|
||||||
|
#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
|
||||||
|
#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
|
||||||
|
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
|
||||||
|
|
||||||
|
/* Program segment header. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Elf64_Word p_type; /* Segment type */
|
||||||
|
Elf64_Word p_flags; /* Segment flags */
|
||||||
|
Elf64_Off p_offset; /* Segment file offset */
|
||||||
|
Elf64_Addr p_vaddr; /* Segment virtual address */
|
||||||
|
Elf64_Addr p_paddr; /* Segment physical address */
|
||||||
|
Elf64_Xword p_filesz; /* Segment size in file */
|
||||||
|
Elf64_Xword p_memsz; /* Segment size in memory */
|
||||||
|
Elf64_Xword p_align; /* Segment alignment */
|
||||||
|
} Elf64_Phdr;
|
||||||
|
|
||||||
|
/* Special value for e_phnum. This indicates that the real number of
|
||||||
|
program headers is too large to fit into e_phnum. Instead the real
|
||||||
|
value is in the field sh_info of section 0. */
|
||||||
|
|
||||||
|
#define PN_XNUM 0xffff
|
||||||
|
|
||||||
|
/* Legal values for p_type (segment type). */
|
||||||
|
|
||||||
|
#define PT_NULL 0 /* Program header table entry unused */
|
||||||
|
#define PT_LOAD 1 /* Loadable program segment */
|
||||||
|
#define PT_DYNAMIC 2 /* Dynamic linking information */
|
||||||
|
#define PT_INTERP 3 /* Program interpreter */
|
||||||
|
#define PT_NOTE 4 /* Auxiliary information */
|
||||||
|
#define PT_SHLIB 5 /* Reserved */
|
||||||
|
#define PT_PHDR 6 /* Entry for header table itself */
|
||||||
|
#define PT_TLS 7 /* Thread-local storage segment */
|
||||||
|
#define PT_NUM 8 /* Number of defined types */
|
||||||
|
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||||
|
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||||
|
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||||
|
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||||
|
#define PT_LOSUNW 0x6ffffffa
|
||||||
|
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||||
|
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||||
|
#define PT_HISUNW 0x6fffffff
|
||||||
|
#define PT_HIOS 0x6fffffff /* End of OS-specific */
|
||||||
|
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||||
|
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||||
|
|
||||||
|
/* Legal values for p_flags (segment flags). */
|
||||||
|
|
||||||
|
#define PF_X (1 << 0) /* Segment is executable */
|
||||||
|
#define PF_W (1 << 1) /* Segment is writable */
|
||||||
|
#define PF_R (1 << 2) /* Segment is readable */
|
||||||
|
#define PF_MASKOS 0x0ff00000 /* OS-specific */
|
||||||
|
#define PF_MASKPROC 0xf0000000 /* Processor-specific */
|
||||||
|
|
||||||
|
|
||||||
|
/* Dynamic section entry. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Legal values for d_tag (dynamic entry type). */
|
||||||
|
|
||||||
|
#define DT_NULL 0 /* Marks end of dynamic section */
|
||||||
|
#define DT_NEEDED 1 /* Name of needed library */
|
||||||
|
#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
|
||||||
|
#define DT_PLTGOT 3 /* Processor defined value */
|
||||||
|
#define DT_HASH 4 /* Address of symbol hash table */
|
||||||
|
#define DT_STRTAB 5 /* Address of string table */
|
||||||
|
#define DT_SYMTAB 6 /* Address of symbol table */
|
||||||
|
#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 */
|
||||||
|
#define DT_STRSZ 10 /* Size of string table */
|
||||||
|
#define DT_SYMENT 11 /* Size of one symbol table entry */
|
||||||
|
#define DT_INIT 12 /* Address of init function */
|
||||||
|
#define DT_FINI 13 /* Address of termination function */
|
||||||
|
#define DT_SONAME 14 /* Name of shared object */
|
||||||
|
#define DT_RPATH 15 /* Library search path (deprecated) */
|
||||||
|
#define DT_SYMBOLIC 16 /* Start symbol search here */
|
||||||
|
#define DT_REL 17 /* Address of Rel relocs */
|
||||||
|
#define DT_RELSZ 18 /* Total size of Rel relocs */
|
||||||
|
#define DT_RELENT 19 /* Size of one Rel reloc */
|
||||||
|
#define DT_PLTREL 20 /* Type of reloc in PLT */
|
||||||
|
#define DT_DEBUG 21 /* For debugging; unspecified */
|
||||||
|
#define DT_TEXTREL 22 /* Reloc might modify .text */
|
||||||
|
#define DT_JMPREL 23 /* Address of PLT relocs */
|
||||||
|
#define DT_BIND_NOW 24 /* Process relocations of object */
|
||||||
|
#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
|
||||||
|
#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
|
||||||
|
#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
|
||||||
|
#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
|
||||||
|
#define DT_RUNPATH 29 /* Library search path */
|
||||||
|
#define DT_FLAGS 30 /* Flags for the object being loaded */
|
||||||
|
#define DT_ENCODING 32 /* Start of encoded range */
|
||||||
|
#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
|
||||||
|
#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
|
||||||
|
#define DT_NUM 34 /* Number used */
|
||||||
|
#define DT_LOOS 0x6000000d /* Start of OS-specific */
|
||||||
|
#define DT_HIOS 0x6ffff000 /* End of OS-specific */
|
||||||
|
#define DT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||||
|
#define DT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||||
|
|
||||||
|
#endif /* uefielf.h */
|
630
uefi/uefipe.h
Normal file
630
uefi/uefipe.h
Normal file
|
@ -0,0 +1,630 @@
|
||||||
|
/**
|
||||||
|
* uefipe.h
|
||||||
|
*
|
||||||
|
* 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 Definitions for the Portable Executable 32+ format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UEFIPE_H
|
||||||
|
#define _UEFIPE_H
|
||||||
|
|
||||||
|
#ifndef _UEFI_H_
|
||||||
|
#error "include uefi.h instead"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IMAGE_DOS_SIGNATURE
|
||||||
|
|
||||||
|
#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 "!<arch>\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
|
||||||
|
|
||||||
|
#endif /* uefipe.h */
|
43
uefi/unistd.c
Normal file
43
uefi/unistd.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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 <uefi.h>
|
||||||
|
|
||||||
|
int usleep (unsigned long int __useconds)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(BS->Stall, 1, __useconds);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int sleep (unsigned int __seconds)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(BS->Stall, 1, __seconds * 1000000);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue