Initial commit

This commit is contained in:
bzt 2021-02-01 01:09:23 +01:00
commit f46ef12c65
22 changed files with 4229 additions and 0 deletions

232
README.md Normal file
View 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 |

View 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

View 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
View file

@ -0,0 +1 @@
../../uefi

View file

@ -0,0 +1,3 @@
TARGET = args.efi
include uefi/Makefile

10
examples/02_args/args.c Normal file
View 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
View file

@ -0,0 +1 @@
../../uefi

View file

@ -0,0 +1,3 @@
TARGET = dumpmem.efi
include uefi/Makefile

View 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
View file

@ -0,0 +1 @@
../../uefi

78
uefi/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

469
uefi/uefielf.h Normal file
View 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
View 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
View 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;
}