Major overhaul of this branch.

This branch has been dedicated to purely the UEFI bootloader.
As such, all other code has been removed.

This code can be compiled with Visual Studio, gcc or llvm.
This commit is contained in:
Curle 2019-07-17 21:10:29 +01:00
parent 352db828e7
commit d588e232c4
257 changed files with 16057 additions and 3293 deletions

View File

@ -1,10 +0,0 @@
---
DerivePointerAlignment: 'true'
SpaceBeforeParens: ControlStatements
UseTab: ForIndentation
IndentWidth: 2
TabWidth: 2
ColumnLimit: 120
BreakBeforeBraces: Attach
...

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.sh eol=lf
Makefile eol=lf

71
.gitignore vendored
View File

@ -1,59 +1,14 @@
# Created by https://www.gitignore.io/api/c
# Edit at https://www.gitignore.io/?templates=c
### C ###
# Prerequisites
*.d
# Object files
*.o *.o
*.ko *.efi
*.obj *.vhd
*.elf *.sdf
*.suo
# Linker output *.opensdf
*.ilk *.opendb
*.map *.fd
*.exp *.db*
arm
# Precompiled Headers aa64
*.gch x86_64
*.pch x86_32
image
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# End of https://www.gitignore.io/api/c

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "gnu-efi"]
path = gnu-efi
url = git://git.code.sf.net/p/gnu-efi/code
ignore = dirty

3
.vs/ProjectSettings.json Normal file
View File

@ -0,0 +1,3 @@
{
"CurrentProjectSetting": "No Configurations"
}

View File

@ -0,0 +1,9 @@
{
"ExpandedNodes": [
"",
"\\arch",
"\\arch\\uefi"
],
"SelectedNode": "\\.gitignore",
"PreviewInSolutionExplorer": false
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@ -1,9 +1,6 @@
# Sync ##Sync UEFI Bootloader
Sync, an experimental synchronising OS. This branch represents the UEFI bootloader used by Sync.
It tries to set a nice video mode, then gets the date and time, then finds, packs and loads the kernel, giving the information gathered to it.
Currently features: A .sln project is provided for convenience. The Windows SDK is required to compile using it, but it also works with gcc and llvm.
* Text mode printing with CSI support
* literally nothing else
Keep posted. Development is relatively active.

View File

@ -1,28 +0,0 @@
[BITS 32] ;... somehow.
[GLOBAL load_gdt]
[EXTERN gp]
load_gdt:
lgdt [gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush ; Far jump and load the new CSD into the processor
flush:
ret
[GLOBAL load_idt]
[EXTERN idtp]
load_idt:
lidt [idtp]
ret
SECTION .bss
resb 8192
_sys_stack:

View File

@ -1,52 +0,0 @@
/************************
*** Team Kitty, 2019 ***
*** Sync ***
***********************/
/* The entry point of the UEFI app.
* When the firmware loads the app,
* it calls the efi_main function.
*
* When it is called, the processor
* is running in 32-bit Protected mode.
* It is given a map of memory, and there
* are a bunch of Boot Services provided
* by the UEFI firmware.
*
* See uefi/docs for more information.
*/
//Example stolen from osdev.org/uefi_bare_bones
#include <efi.h>
#include <efilib.h>
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
/* Store the system table for future use in other functions */
ST = SystemTable;
/* Say hi */
Status = ST->ConOut->OutputString(ST->ConOut, L"Hello World\n\r");
if (EFI_ERROR(Status))
return Status;
/* Now wait for a keystroke before continuing, otherwise your
message will flash off the screen before you see it.
First, we need to empty the console input buffer to flush
out any keystrokes entered before this point */
Status = ST->ConIn->Reset(ST->ConIn, FALSE);
if (EFI_ERROR(Status))
return Status;
/* Now wait until a key becomes available. This is a simple
polling implementation. You could try and use the WaitForKey
event instead if you like */
while ((Status = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key)) == EFI_NOT_READY) ;
return Status;
}

View File

@ -1,25 +0,0 @@
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}

View File

@ -1,9 +0,0 @@
KERNEL_ARCH_CFLAGS=
KERNEL_ARCH_CPPFLAGS=
KERNEL_ARCH_LDFLAGS=
KERNEL_ARCH_LIBS=
KERNEL_ARCH_OBJS= \
$(ARCHDIR)/boot.o \
$(ARCHDIR)/sys_clock.o \
$(ARCHDIR)/tty.o

View File

@ -1,35 +0,0 @@
/************************
*** Team Kitty, 2019 ***
*** Sync ***
***********************/
/* This file provides an interface to
* the hardware timer / RTC. Not much
* more to be said about it. */
#include <kernel/utils.h>
#include <kernel.h>
#include <kernel/serial.h>
#include <kernel/descriptor_tables.h>
size_t timer_ticks = 0;
size_t flag = 0;
void timer_handler(struct int_frame* r) {
gdb_end();
timer_ticks++;
if(timer_ticks % 18 == 0) {
if(++flag % 2 == 0) {
serial_print(0x3F8, "Tick.");
} else {
serial_print(0x3F8, "Tock.");
}
}
if(timer_ticks > 18)
timer_ticks = 0;
}
void timer_install() {
irq_install_handler(0, &timer_handler);
}

View File

@ -1,348 +0,0 @@
/************************
*** Team Kitty, 2019 ***
*** Sync ***
***********************/
/* This file provides all of the functionality
* needed to interact with the Text-Mode VGA
* buffer, which will soon be defunct due to
* EFI and graphics.
*
* This file will be left for the forseeable
* future, because it allows for easy debugging.
* 17/07/19 Curle
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
//#include <string.h>
#include "kernel/tty.h"
#include "kernel/utils.h"
static const size_t TERM_WIDTH = 80;
static const size_t TERM_HEIGHT = 25;
static size_t terminal_row;
static size_t terminal_column;
static uint8_t current_color;
static uint16_t* term_buffer;
volatile uint16_t* vga_buffer = (uint16_t*)0xB8000;
void screen_initialize(void) {
terminal_row = 0;
terminal_column = 0;
current_color = vga_color_set(LIGHT_GREY, BLACK);
term_buffer = vga_buffer;
for (size_t y = 0; y < TERM_HEIGHT; y++) {
for (size_t x = 0; x < TERM_WIDTH; x++) {
const size_t offset = y * TERM_WIDTH + x;
term_buffer[offset] = vga_entry(' ', current_color);
}
}
}
void term_setcolor(enum vga_colors color) { current_color = color; }
void term_putentryat(char c, uint8_t color, size_t x, size_t y) {
const size_t offset = y * TERM_WIDTH + x;
term_buffer[offset] = vga_entry(c, color);
}
void term_putchar(char c) {
unsigned char uc = c;
// Handle escaped characters, such as newline, and crtn.
switch (uc) {
case '\n':
terminal_column = 0;
terminal_row += 1;
break;
default:
term_putentryat(uc, current_color, terminal_column, terminal_row);
if (++terminal_column == TERM_WIDTH) {
terminal_column = 0;
if (++terminal_row == TERM_HEIGHT) {
term_scroll(false);
terminal_row = 0;
}
}
break;
}
}
struct csi_sequence parse_csi(const char* data, size_t size) {
enum State { PARAMETER, INTERMEDIATE, FINAL, INVALID };
enum State state = PARAMETER;
struct csi_sequence sequence = {.parameter = NULL,
.parameter_len = 0,
.intermediate = NULL,
.intermediate_len = 0,
.final = NULL,
.valid = false};
for (size_t j = 0; j < size; j++) {
uint8_t c = data[j];
if (state == PARAMETER && (c >= 0x30 && c <= 0x3F)) {
if (!sequence.parameter)
sequence.parameter = data + j;
sequence.parameter_len++;
} else if (c >= 0x20 && c <= 0x2F) {
if (!sequence.intermediate)
sequence.intermediate = data + j;
sequence.intermediate_len++;
state = INTERMEDIATE;
} else if (c >= 0x40 && c <= 0x7F) {
sequence.final = data + j;
sequence.valid = true;
state = FINAL;
break;
} else {
// Parameter found in intermediate byte location, or byte out of
// range
state = INVALID;
break;
}
}
return sequence;
}
void term_write(const char* data, size_t size) {
for (size_t i = 0; i < size; i++) {
// Begin handling ANSI escape codes.
if (data[i] == 0x1b) { // The current character is ESC - the start of ANSI codes.
// term_writes("ANSI Code encountered: ");
bool string_terminated = false; // Flag used in some of the escape codes
// TODO: Should only progress if we have at least 2 more bytes
switch ((uint8_t)data[i + 1]) {
case '[': // CSI - Control Sequence Introducer (The most common one, hence it comes first)
{
struct csi_sequence sequence = parse_csi(data + i + 2, size - (i + 2));
if (sequence.valid) {
// Send it off to our handler function to keep this part clean
handleControlSequence(sequence);
i += sequence.parameter_len + sequence.intermediate_len + 2; // Move past sequence
}
} break;
// Single shifts are not handled, so just print them and exit
case 'N': // SS2 - Single Shift Two
term_writes("Single Shift Two\n");
break;
case 'O': // SS3 - Single Shift Three
term_writes("Single Shift Three\n");
break;
// Control Strings
case 'P': // DCS - Device Control String
term_writes("Device Control String");
string_terminated = false;
break;
case '\\': // ST - String Terminator
term_writes("String Terminator\n");
string_terminated = true;
break;
case ']': // OSC - Operating System Command
term_writes("Operating System Command\n");
string_terminated = false;
break;
case 'X': // SOS - Start Of String
term_writes("Start of String");
string_terminated = false;
break;
case '^': // PM - Privacy Message
term_writes("Privacy Message\n");
break;
case '_': // APC - Application Program Command
term_writes("Application Program Command\n");
break;
}
} else {
term_putchar(data[i]);
}
}
}
void term_writes(const char* data) { term_write(data, strlen(data)); }
void puts(const char* string) {
term_write(string, strlen(string));
term_putchar('\n');
}
void handleControlSequence(struct csi_sequence sequence) {
// Check for our failsafes
if (sequence.valid) {
int n = 0; // Default of the flag used for a few items
// Parse parameters, we only care about a max 2 of number only parameters
// for now
int params[2] = {0};
int param_count = 0;
if (sequence.parameter_len) {
for (size_t i = 0; i < sequence.parameter_len && param_count < 1; i++) {
char c = sequence.parameter[i];
if (isDigit(c)) {
n = (n * 10) + (sequence.parameter[i] - '0');
} else if (c == ';') {
params[param_count++] = n;
}
}
params[param_count++] = n;
}
switch (*(sequence.final)) {
case 'H':
case 'f': // CUP - Cursor Position
// TODO: Check to see if we have 2 paramaters
if (params[0])
params[0]--;
if (params[1])
params[1]--;
set_cursor(params[0], params[1]);
break;
case 'A': // CUU - Cursor Up
if (!params[0])
params[0] = 1;
set_cursor(terminal_column, terminal_row - params[0]);
break;
case 'B': // CUD - Cursor Down
if (!params[0])
params[0] = 1;
set_cursor(terminal_column, terminal_row + params[0]);
break;
case 'C': // CUF - Cursor Forward
if (!params[0])
params[0] = 1;
set_cursor(terminal_column + params[0], terminal_row);
break;
case 'D': // CUB - Cursor Back
if (!params[0])
params[0] = 1;
set_cursor(terminal_column - params[0], terminal_row);
break;
case 'E': // CNL - Cursor Next Line
if (!params[0])
params[0] = 1;
set_cursor(0, terminal_row + params[0]);
break;
case 'F': // CPL - Cursor Previous Line
if (!params[0])
params[0] = 1;
set_cursor(0, terminal_row - params[0]);
break;
case 'G': // CHA - Cursor Horizontal Absolute
if (params[0])
params[0]--;
set_cursor(params[0], terminal_row);
break;
case 'J': // ED - Erase in Display
{
// current cursor pos = y * width + x
int pos = terminal_row * 80 + terminal_column;
if (params[0] == 0) { // Clear from cursor to end of screen
for (; pos < (25 * 80); pos++) {
vga_buffer[pos] = '\0';
}
} else if (params[0] == 1) { // Clear from cursor to beginning
for (; pos > 0; pos--) {
vga_buffer[pos] = '\0';
}
} else if (params[0] == 2 || params[0] == 3) { // Clear entire screen
// TODO: Support scrollback buffer? (n = 3)
for (int i = 0; i < (25 * 80); i++) {
vga_buffer[0] = '\0';
}
}
break;
}
case 'K': // EL - Erase in Line
{
int pos = terminal_row * 80 + terminal_column;
if (params[0] == 0) { // From cursor to end of line
int endPos = (terminal_row + 1) * 80 - 1; // End of line = current row + 25 columns = current row + 1
for (; pos < endPos; pos++) {
vga_buffer[pos] = '\0';
}
} else if (params[0] == 1) { // From cursor to start of line
int endPos = terminal_row * 80; // Start of line = end of previous line + 1 == current line
for (; pos > endPos; pos--) {
vga_buffer[pos] = '\0';
}
} else if (params[0] == 2) { // Entire current line
pos = terminal_row * 80;
int endPos = (terminal_row + 1) * 80 - 1;
for (; pos < endPos; pos++) {
vga_buffer[pos] = '\0';
}
}
break;
}
case 'S': // SU - Scroll Up
term_scroll(true);
break;
case 'T': // SD - Scroll Down
term_scroll(false);
break;
}
}
}
bool isDigit(char c) { return c >= '0' && c <= '9'; }
void set_cursor(int n, int m) {
terminal_column = n;
terminal_row = m;
}
void term_scroll(bool down) {
int current_pos;
if (down) {
current_pos = 25 * 80; // Start of the last line.
} else {
current_pos = 160; // Start of the second line.
}
unsigned char* term_buffer = (unsigned char*)vga_buffer;
if (down) { // To scroll down, move every character into the one below it, or "pull" every character down
while (current_pos > 80) {
term_buffer[current_pos + 160] = vga_buffer[current_pos];
term_buffer[current_pos + 159] = vga_buffer[current_pos - 1];
current_pos -= 2;
}
} else {
while (current_pos <= 4000) {
term_buffer[current_pos - 160 /*The character immediately below it*/] =
vga_buffer[current_pos]; // Move each character up a line
term_buffer[current_pos - 159 /*The color of the character below*/] =
vga_buffer[current_pos + 1]; // As well as its color
current_pos += 2; // Move to next char
}
}
if (down) {
current_pos = 0; // Start of first line
for (; current_pos < 80; current_pos++) {
term_buffer[current_pos] = '\0';
current_pos += 2;
}
} else {
; // Start of the last line
// Wipe out the bottom line
for (current_pos = 3840; current_pos <= 3920; current_pos += 2) {
term_buffer[current_pos] = 0;
}
}
terminal_row = 24; // Start writing on the last line
terminal_column = 0;
}

View File

@ -1,53 +0,0 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, iodebug=1
config_interface: textconfig
display_library: x
memory: host=32, guest=32
romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x0, options=none
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: a
floppy_bootsig_check: disabled=1
floppya: 1_44=/dev/loop0, status=inserted
# no floppyb
ata0: enabled=0
ata1: enabled=0
ata2: enabled=0
ata3: enabled=0
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5, realtime=1
cpu: count=1:1:1, ips=1000000, quantum=16, model=bx_generic, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor"
cpuid: mmx=1, apic=xapic, simd=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0
cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, fma4=0
cpuid: tbm=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, smep=0, smap=0, mwait=1
print_timestamps: enabled=0
debugger_log: ../red.debug
magic_break: enabled=1
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
# no loader
log: ../red.log
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=0, toggle=ctrl+mbutton
speaker: enabled=1, mode=system
parport1: enabled=1, file=none
parport2: enabled=0
com1: enabled=1, mode=null
com2: enabled=0
com3: enabled=0
com4: enabled=0

141
debug.vbs Normal file
View File

@ -0,0 +1,141 @@
' Visual Studio QEMU debugging script.
'
' I like invoking vbs as much as anyone else, but we need to download and unzip our
' firmware file, as well as launch QEMU, and neither Powershell or a standard batch
' can do that without having an extra console appearing.
'
' Note: You may get a prompt from the firewall when trying to download the BIOS file
' Modify these variables as needed
QEMU_PATH = "C:\Program Files\qemu\"
' You can add something like "-S -gdb tcp:127.0.0.1:1234" if you plan to use gdb to debug
QEMU_OPTS = "-net none -monitor none -parallel none"
' Set to True if you need to download a file that might be cached locally
NO_CACHE = False
' You shouldn't have to modify anything below this
TARGET = WScript.Arguments(1)
If (TARGET = "x86") Then
UEFI_EXT = "ia32"
QEMU_ARCH = "i386"
FW_BASE = "OVMF"
ElseIf (TARGET = "x64") Then
UEFI_EXT = "x64"
QEMU_ARCH = "x86_64"
FW_BASE = "OVMF"
ElseIf (TARGET = "ARM") Then
UEFI_EXT = "arm"
QEMU_ARCH = "arm"
FW_BASE = "QEMU_EFI"
' You can also add '-device VGA' to the options below, to get graphics output.
' But if you do, be mindful that the keyboard input may not work... :(
QEMU_OPTS = "-M virt -cpu cortex-a15 " & QEMU_OPTS
ElseIf (TARGET = "ARM64") Then
UEFI_EXT = "aa64"
QEMU_ARCH = "aarch64"
FW_BASE = "QEMU_EFI"
QEMU_OPTS = "-M virt -cpu cortex-a57 " & QEMU_OPTS
Else
MsgBox("Unsupported debug target: " & TARGET)
Call WScript.Quit(1)
End If
BOOT_NAME = "boot" & UEFI_EXT & ".efi"
QEMU_EXE = "qemu-system-" & QEMU_ARCH & "w.exe"
FW_ARCH = UCase(UEFI_EXT)
FW_DIR = "https://efi.akeo.ie/" & FW_BASE & "/"
FW_ZIP = FW_BASE & "-" & FW_ARCH & ".zip"
FW_FILE = FW_BASE & "_" & FW_ARCH & ".fd"
FW_URL = FW_DIR & FW_ZIP
' Globals
Set fso = CreateObject("Scripting.FileSystemObject")
Set shell = CreateObject("WScript.Shell")
' Download a file from FTP
Sub DownloadFtp(Server, Path)
Set file = fso.CreateTextFile("ftp.txt", True)
Call file.Write("open " & Server & vbCrLf &_
"anonymous" & vbCrLf & "user" & vbCrLf & "bin" & vbCrLf &_
"get " & Path & vbCrLf & "bye" & vbCrLf)
Call file.Close()
Call shell.Run("%comspec% /c ftp -s:ftp.txt > NUL", 0, True)
Call fso.DeleteFile("ftp.txt")
End Sub
' Download a file from HTTP
Sub DownloadHttp(Url, File)
Const BINARY = 1
Const OVERWRITE = 2
Set xHttp = createobject("Microsoft.XMLHTTP")
Set bStrm = createobject("Adodb.Stream")
Call xHttp.Open("GET", Url, False)
If NO_CACHE = True Then
Call xHttp.SetRequestHeader("If-None-Match", "some-random-string")
Call xHttp.SetRequestHeader("Cache-Control", "no-cache,max-age=0")
Call xHttp.SetRequestHeader("Pragma", "no-cache")
End If
Call xHttp.Send()
If Not xHttp.Status = 200 Then
Call WScript.Echo("Unable to access file - Error " & xHttp.Status)
Call WScript.Quit(1)
End If
With bStrm
.type = BINARY
.open
.write xHttp.responseBody
.savetofile File, OVERWRITE
End With
End Sub
' Unzip a specific file from an archive
Sub Unzip(Archive, File)
Const NOCONFIRMATION = &H10&
Const NOERRORUI = &H400&
Const SIMPLEPROGRESS = &H100&
unzipFlags = NOCONFIRMATION + NOERRORUI + SIMPLEPROGRESS
Set objShell = CreateObject("Shell.Application")
Set objSource = objShell.NameSpace(fso.GetAbsolutePathName(Archive)).Items()
Set objTarget = objShell.NameSpace(fso.GetAbsolutePathName("."))
' Only extract the file we are interested in
For i = 0 To objSource.Count - 1
If objSource.Item(i).Name = File Then
Call objTarget.CopyHere(objSource.Item(i), unzipFlags)
End If
Next
End Sub
' Check that QEMU is available
If Not fso.FileExists(QEMU_PATH & QEMU_EXE) Then
Call WScript.Echo("'" & QEMU_PATH & QEMU_EXE & "' was not found." & vbCrLf &_
"Please make sure QEMU is installed or edit the path in '.msvc\debug.vbs'.")
Call WScript.Quit(1)
End If
' Fetch the UEFI firmware and unzip it
If Not fso.FileExists(FW_FILE) Then
Call WScript.Echo("The UEFI firmware file, needed for QEMU, " &_
"will be downloaded from: " & FW_URL & vbCrLf & vbCrLf &_
"Note: Unless you delete the file, this should only happen once.")
Call DownloadHttp(FW_URL, FW_ZIP)
End If
If Not fso.FileExists(FW_ZIP) And Not fso.FileExists(FW_FILE) Then
Call WScript.Echo("There was a problem downloading the QEMU UEFI firmware.")
Call WScript.Quit(1)
End If
If fso.FileExists(FW_ZIP) Then
Call Unzip(FW_ZIP, FW_BASE & ".fd")
Call fso.MoveFile(FW_BASE & ".fd", FW_FILE)
Call fso.DeleteFile(FW_ZIP)
End If
If Not fso.FileExists(FW_FILE) Then
Call WScript.Echo("There was a problem unzipping the QEMU UEFI firmware.")
Call WScript.Quit(1)
End If
' Copy the app file as boot application and run it in QEMU
Call shell.Run("%COMSPEC% /c mkdir ""image\efi\boot""", 0, True)
Call fso.CopyFile(WScript.Arguments(0), "image\efi\boot\" & BOOT_NAME, True)
Call shell.Run("""" & QEMU_PATH & QEMU_EXE & """ " & QEMU_OPTS & " -L . -bios " & FW_FILE & " -hda fat:rw:image", 1, True)

6
gnu-efi/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.efi
*.efi.debug
*.o
*.a
*.tar.*
*.tar

1324
gnu-efi/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

183
gnu-efi/Make.defaults Normal file
View File

@ -0,0 +1,183 @@
# -*- makefile -*-
# Copyright (c) 1999-2007 Hewlett-Packard Development Company, L.P.
# Contributed by David Mosberger <davidm@hpl.hp.com>
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANYDIRECT, 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.
#
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
#
# Variables below overridable from command-line:
# make VARNAME=value ...
#
#
# Where to install the package. GNU-EFI will create and access
# lib and include under the root
#
INSTALLROOT := /
PREFIX := /usr/local
LIBDIR := $(PREFIX)/lib
INSTALL := install
# Compilation tools
HOSTCC := $(prefix)gcc
CC := $(prefix)$(CROSS_COMPILE)gcc
AS := $(prefix)$(CROSS_COMPILE)as
LD := $(prefix)$(CROSS_COMPILE)ld
AR := $(prefix)$(CROSS_COMPILE)ar
RANLIB := $(prefix)$(CROSS_COMPILE)ranlib
OBJCOPY := $(prefix)$(CROSS_COMPILE)objcopy
# Host/target identification
OS := $(shell uname -s)
HOSTARCH ?= $(shell $(HOSTCC) -dumpmachine | cut -f1 -d- | sed -e s,i[3456789]86,ia32, -e 's,armv7.*,arm,' )
ARCH ?= $(shell $(HOSTCC) -dumpmachine | cut -f1 -d- | sed -e s,i[3456789]86,ia32, -e 's,armv7.*,arm,' )
# Get ARCH from the compiler if cross compiling
ifneq ($(CROSS_COMPILE),)
override ARCH := $(shell $(CC) -dumpmachine | cut -f1 -d-| sed -e s,i[3456789]86,ia32, -e 's,armv7.*,arm,' )
endif
# FreeBSD (and possibly others) reports amd64 instead of x86_64
ifeq ($(ARCH),amd64)
override ARCH := x86_64
endif
#
# Where to build the package
#
OBJDIR := $(TOPDIR)/$(ARCH)
#
# Variables below derived from variables above
#
# Arch-specific compilation flags
CPPFLAGS += -DCONFIG_$(ARCH)
CFLAGS += -Wno-error=pragmas
ifeq ($(ARCH),ia64)
CFLAGS += -mfixed-range=f32-f127
endif
ifeq ($(ARCH),ia32)
CFLAGS += -mno-mmx -mno-sse
ifeq ($(HOSTARCH),x86_64)
ARCH3264 = -m32
endif
endif
ifeq ($(ARCH),x86_64)
GCCVERSION := $(shell $(CC) -dumpversion | cut -f1 -d.)
GCCMINOR := $(shell $(CC) -dumpversion | cut -f2 -d.)
USING_CLANG := $(shell $(CC) -v 2>&1 | grep -q 'clang version' && echo clang)
# Rely on GCC MS ABI support?
GCCNEWENOUGH := $(shell ( [ $(GCCVERSION) -gt "4" ] \
|| ( [ $(GCCVERSION) -eq "4" ] \
&& [ $(GCCMINOR) -ge "7" ] ) ) \
&& echo 1)
ifeq ($(GCCNEWENOUGH),1)
CPPFLAGS += -DGNU_EFI_USE_MS_ABI -maccumulate-outgoing-args --std=c11
else ifeq ($(USING_CLANG),clang)
CPPFLAGS += -DGNU_EFI_USE_MS_ABI --std=c11
endif
CFLAGS += -mno-red-zone
ifeq ($(HOSTARCH),ia32)
ARCH3264 = -m64
endif
endif
ifneq (,$(filter $(ARCH),ia32 x86_64))
# Disable AVX, if the compiler supports that.
CC_CAN_DISABLE_AVX=$(shell $(CC) -Werror -c -o /dev/null -xc -mno-avx - </dev/null >/dev/null 2>&1 && echo 1)
ifeq ($(CC_CAN_DISABLE_AVX), 1)
CFLAGS += -mno-avx
endif
endif
ifeq ($(ARCH),mips64el)
CFLAGS += -march=mips64r2
ARCH3264 = -mabi=64
endif
#
# Set HAVE_EFI_OBJCOPY if objcopy understands --target efi-[app|bsdrv|rtdrv],
# otherwise we need to compose the PE/COFF header using the assembler
#
ifneq ($(ARCH),aarch64)
ifneq ($(ARCH),arm)
ifneq ($(ARCH),mips64el)
export HAVE_EFI_OBJCOPY=y
endif
endif
endif
ifneq ($(ARCH),arm)
export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
endif
ifeq ($(ARCH),arm)
CFLAGS += -marm
endif
# Generic compilation flags
INCDIR += -I$(SRCDIR) -I$(TOPDIR)/inc -I$(TOPDIR)/inc/$(ARCH) \
-I$(TOPDIR)/inc/protocol
# Only enable -fpic for non MinGW compilers (unneeded on MinGW)
GCCMACHINE := $(shell $(CC) -dumpmachine)
ifneq (mingw32,$(findstring mingw32, $(GCCMACHINE)))
CFLAGS += -fpic
endif
ifeq (FreeBSD, $(findstring FreeBSD, $(OS)))
CFLAGS += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \
-fshort-wchar -fno-strict-aliasing \
-ffreestanding -fno-stack-protector
else
CFLAGS += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \
-fshort-wchar -fno-strict-aliasing \
-ffreestanding -fno-stack-protector -fno-stack-check \
-fno-stack-check \
$(if $(findstring gcc,$(CC)),-fno-merge-all-constants,)
endif
ARFLAGS := rDv
ASFLAGS += $(ARCH3264)
LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings \
--build-id=sha1

58
gnu-efi/Make.rules Normal file
View File

@ -0,0 +1,58 @@
#
# Copyright (C) 1999-2007 Hewlett-Packard Co.
# Contributed by David Mosberger <davidm@hpl.hp.com>
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANYDIRECT, 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.
#
%.efi: %.so
$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
-j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \
-j .reloc $(FORMAT) $*.so $@
%.efi.debug: %.so
$(OBJCOPY) -j .debug_info -j .debug_abbrev -j .debug_aranges \
-j .debug_line -j .debug_str -j .debug_ranges \
-j .note.gnu.build-id \
$(FORMAT) $*.so $@
%.so: %.o
$(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES)
%.o: %.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
%.S: %.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -S $< -o $@
%.E: %.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -E $< -o $@

129
gnu-efi/Makefile Normal file
View File

@ -0,0 +1,129 @@
#
# Copyright (C) 1999-2007 Hewlett-Packard Co.
# Contributed by David Mosberger <davidm@hpl.hp.com>
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANYDIRECT, 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.
#
VERSION = 3.0.9
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
SRCDIR = $(dir $(MKFILE_PATH))
VPATH = $(SRCDIR)
include $(SRCDIR)/Make.defaults
SUBDIRS = lib gnuefi inc apps
gnuefi: lib
all: check_gcc $(SUBDIRS)
mkvars:
@echo AR=$(AR)
@echo ARCH=$(ARCH)
@echo ARCH3264=$(ARCH3264)
@echo AS=$(AS)
@echo ASFLAGS=$(ASFLAGS)
@echo CC=$(CC)
@echo CFLAGS=$(CFLAGS)
@echo CPPFLAGS=$(CPPFLAGS)
@echo GCCMINOR=$(GCCMINOR)
@echo GCCNEWENOUGH=$(GCCNEWENOUGH)
@echo GCCVERSION=$(GCCVERSION)
@echo HOSTARCH=$(HOSTARCH)
@echo INCDIR=$(INCDIR)
@echo INSTALL=$(INSTALL)
@echo INSTALLROOT=$(INSTALLROOT)
@echo LD=$(LD)
@echo LDFLAGS=$(LDFLAGS)
@echo LIBDIR=$(LIBDIR)
@echo OBJCOPY=$(OBJCOPY)
@echo OS=$(OS)
@echo prefix=$(prefix)
@echo PREFIX=$(PREFIX)
@echo RANLIB=$(RANLIB)
@echo SRCDIR=$(SRCDIR)
@echo TOPDIR=$(TOPDIR)
$(SUBDIRS):
mkdir -p $(OBJDIR)/$@
$(MAKE) -C $(OBJDIR)/$@ -f $(SRCDIR)/$@/Makefile SRCDIR=$(SRCDIR)/$@ ARCH=$(ARCH)
clean:
rm -f *~
@for d in $(SUBDIRS); do \
if [ -d $(OBJDIR)/$$d ]; then \
$(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d clean; \
fi; \
done
install:
@for d in $(SUBDIRS); do \
mkdir -p $(OBJDIR)/$$d; \
$(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d install; done
.PHONY: $(SUBDIRS) clean depend
#
# on both platforms you must use gcc 3.0 or higher
#
check_gcc:
ifeq ($(GCC_VERSION),2)
@echo "you need to use a version of gcc >= 3.0, you are using `$(CC) --version`"
@exit 1
endif
include $(SRCDIR)/Make.rules
test-archive:
@rm -rf /tmp/gnu-efi-$(VERSION) /tmp/gnu-efi-$(VERSION)-tmp
@mkdir -p /tmp/gnu-efi-$(VERSION)-tmp
@git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; tar x )
@git diff | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; patch -s -p1 -b -z .gitdiff )
@mv /tmp/gnu-efi-$(VERSION)-tmp/ /tmp/gnu-efi-$(VERSION)/
@dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/gnu-efi-$(VERSION).tar.bz2 gnu-efi-$(VERSION)
@rm -rf /tmp/gnu-efi-$(VERSION)
@echo "The archive is in gnu-efi-$(VERSION).tar.bz2"
tag:
git tag $(VERSION) refs/heads/master
archive: tag
@rm -rf /tmp/gnu-efi-$(VERSION) /tmp/gnu-efi-$(VERSION)-tmp
@mkdir -p /tmp/gnu-efi-$(VERSION)-tmp
@git archive --format=tar $(VERSION) | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; tar x )
@mv /tmp/gnu-efi-$(VERSION)-tmp/ /tmp/gnu-efi-$(VERSION)/
@dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/gnu-efi-$(VERSION).tar.bz2 gnu-efi-$(VERSION)
@rm -rf /tmp/gnu-efi-$(VERSION)
@echo "The archive is in gnu-efi-$(VERSION).tar.bz2"

30
gnu-efi/README.efilib Normal file
View File

@ -0,0 +1,30 @@
The files in the "lib" and "inc" subdirectories are using the EFI Application
Toolkit distributed by Intel at http://developer.intel.com/technology/efi
This code is covered by the following agreement:
Copyright (c) 1998-2000 Intel Corporation
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
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.
THIS SOFTWARE IS PROVIDED ``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 INTEL 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. THE EFI SPECIFICATION AND ALL OTHER INFORMATION
ON THIS WEB SITE ARE PROVIDED "AS IS" WITH NO WARRANTIES, AND ARE SUBJECT
TO CHANGE WITHOUT NOTICE.

19
gnu-efi/README.elilo Normal file
View File

@ -0,0 +1,19 @@
IMPORTANT information related to the gnu-efi package
----------------------------------------------------
June 2001
As of version 3.0, the gnu-efi package is now split in two different packages:
-> gnu-efi-X.y: contains the EFI library, include files and crt0.
-> elilo-X.y : contains the ELILO bootloader.
Note that X.y don't need to match for both packages. However elilo-3.x
requires at least gnu-efi-3.0. EFI support for x86_64 is provided in
gnu-efi-3.0d.
Both packages can be downloaded from:
http://www.sf.net/projects/gnu-efi
http://www.sf.net/projects/elilo

21
gnu-efi/README.git Normal file
View File

@ -0,0 +1,21 @@
README.git
Generating releases from git a very simple process;
1) Edit the file "Makefile". Changing the "VERSION" line to the new version.
2) Do a "git commit" just for the version number change.
3) Then do a "make test-archive".
That will make a file in the current directory gnu-efi-$VERSION.tar.bz2 ,
with its top level directory gnu-efi-$VERSION/ and the source tree under that.
Once you've tested that and you're sure it's what you want to release,
4) Do "make archive", which will tag a release in git and generate a
final tarball from it.
You then push to the archive, being sure to include the tag:
5) "git push origin master:master --tags"
And upload the archive wherever it's supposed to go.

405
gnu-efi/README.gnuefi Normal file
View File

@ -0,0 +1,405 @@
-------------------------------------------------
Building EFI Applications Using the GNU Toolchain
-------------------------------------------------
David Mosberger <davidm@hpl.hp.com>
23 September 1999
Copyright (c) 1999-2007 Hewlett-Packard Co.
Copyright (c) 2006-2010 Intel Co.
Last update: 04/09/2007
* Introduction
This document has two parts: the first part describes how to develop
EFI applications for IA-64,x86 and x86_64 using the GNU toolchain and the EFI
development environment contained in this directory. The second part
describes some of the more subtle aspects of how this development
environment works.
* Part 1: Developing EFI Applications
** Prerequisites:
To develop x86 and x86_64 EFI applications, the following tools are needed:
- gcc-3.0 or newer (gcc 2.7.2 is NOT sufficient!)
As of gnu-efi-3.0b, the Redhat 8.0 toolchain is known to work,
but the Redhat 9.0 toolchain is not currently supported.
- A version of "objcopy" that supports EFI applications. To
check if your version includes EFI support, issue the
command:
objcopy --help
Verify that the line "supported targets" contains the string
"efi-app-ia32" and "efi-app-x86_64" and that the "-j" option
accepts wildcards. The binutils release binutils-2.24
supports Intel64 EFI and accepts wildcard section names.
- For debugging purposes, it's useful to have a version of
"objdump" that supports EFI applications as well. This
allows inspect and disassemble EFI binaries.
To develop IA-64 EFI applications, the following tools are needed:
- A version of gcc newer than July 30th 1999 (older versions
had problems with generating position independent code).
As of gnu-efi-3.0b, gcc-3.1 is known to work well.
- A version of "objcopy" that supports EFI applications. To
check if your version includes EFI support, issue the
command:
objcopy --help
Verify that the line "supported targets" contains the string
"efi-app-ia64" and that the "-j" option accepts wildcards.
- For debugging purposes, it's useful to have a version of
"objdump" that supports EFI applications as well. This
allows inspect and disassemble EFI binaries.
** Directory Structure
This EFI development environment contains the following
subdirectories:
inc: This directory contains the EFI-related include files. The
files are taken from Intel's EFI source distribution, except
that various fixes were applied to make it compile with the
GNU toolchain.
lib: This directory contains the source code for Intel's EFI library.
Again, the files are taken from Intel's EFI source
distribution, with changes to make them compile with the GNU
toolchain.
gnuefi: This directory contains the glue necessary to convert ELF64
binaries to EFI binaries. Various runtime code bits, such as
a self-relocator are included as well. This code has been
contributed by the Hewlett-Packard Company and is distributed
under the GNU GPL.
apps: This directory contains a few simple EFI test apps.
** Setup
It is necessary to edit the Makefile in the directory containing this
README file before EFI applications can be built. Specifically, you
should verify that macros CC, AS, LD, AR, RANLIB, and OBJCOPY point to
the appropriate compiler, assembler, linker, ar, and ranlib binaries,
respectively.
If you're working in a cross-development environment, be sure to set
macro ARCH to the desired target architecture ("ia32" for x86, "x86_64" for
x86_64 and "ia64" for IA-64). For convenience, this can also be done from
the make command line (e.g., "make ARCH=ia64").
** Building
To build the sample EFI applications provided in subdirectory "apps",
simply invoke "make" in the toplevel directory (the directory
containing this README file). This should build lib/libefi.a and
gnuefi/libgnuefi.a first and then all the EFI applications such as a
apps/t6.efi.
** Running
Just copy the EFI application (e.g., apps/t6.efi) to the EFI
filesystem, boot EFI, and then select "Invoke EFI application" to run
the application you want to test. Alternatively, you can invoke the
Intel-provided "nshell" application and then invoke your test binary
via the command line interface that "nshell" provides.
** Writing Your Own EFI Application
Suppose you have your own EFI application in a file called
"apps/myefiapp.c". To get this application built by the GNU EFI build
environment, simply add "myefiapp.efi" to macro TARGETS in
apps/Makefile. Once this is done, invoke "make" in the top level
directory. This should result in EFI application apps/myefiapp.efi,
ready for execution.
The GNU EFI build environment allows to write EFI applications as
described in Intel's EFI documentation, except for two differences:
- The EFI application's entry point is always called "efi_main". The
declaration of this routine is:
EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab);
- UNICODE string literals must be written as W2U(L"Sample String")
instead of just L"Sample String". The W2U() macro is defined in
<efilib.h>. This header file also declares the function W2UCpy()
which allows to convert a wide string into a UNICODE string and
store the result in a programmer-supplied buffer.
- Calls to EFI services should be made via uefi_call_wrapper(). This
ensures appropriate parameter passing for the architecture.
* Part 2: Inner Workings
WARNING: This part contains all the gory detail of how the GNU EFI
toolchain works. Normal users do not have to worry about such
details. Reading this part incurs a definite risk of inducing severe
headaches or other maladies.
The basic idea behind the GNU EFI build environment is to use the GNU
toolchain to build a normal ELF binary that, at the end, is converted
to an EFI binary. EFI binaries are really just PE32+ binaries. PE
stands for "Portable Executable" and is the object file format
Microsoft is using on its Windows platforms. PE is basically the COFF
object file format with an MS-DOS2.0 compatible header slapped on in
front of it. The "32" in PE32+ stands for 32 bits, meaning that PE32
is a 32-bit object file format. The plus in "PE32+" indicates that
this format has been hacked to allow loading a 4GB binary anywhere in
a 64-bit address space (unlike ELF64, however, this is not a full
64-bit object file format because the entire binary cannot span more
than 4GB of address space). EFI binaries are plain PE32+ binaries
except that the "subsystem id" differs from normal Windows binaries.
There are two flavors of EFI binaries: "applications" and "drivers"
and each has there own subsystem id and are identical otherwise. At
present, the GNU EFI build environment supports the building of EFI
applications only, though it would be trivial to generate drivers, as
the only difference is the subsystem id. For more details on PE32+,
see the spec at
http://msdn.microsoft.com/library/specs/msdn_pecoff.htm.
In theory, converting a suitable ELF64 binary to PE32+ is easy and
could be accomplished with the "objcopy" utility by specifying option
--target=efi-app-ia32 (x86) or --target=efi-app-ia64 (IA-64). But
life never is that easy, so here some complicating factors:
(1) COFF sections are very different from ELF sections.
ELF binaries distinguish between program headers and sections.
The program headers describe the memory segments that need to
be loaded/initialized, whereas the sections describe what
constitutes those segments. In COFF (and therefore PE32+) no
such distinction is made. Thus, COFF sections need to be page
aligned and have a size that is a multiple of the page size
(4KB for EFI), whereas ELF allows sections at arbitrary
addresses and with arbitrary sizes.
(2) EFI binaries should be relocatable.
Since EFI binaries are executed in physical mode, EFI cannot
guarantee that a given binary can be loaded at its preferred
address. EFI does _try_ to load a binary at it's preferred
address, but if it can't do so, it will load it at another
address and then relocate the binary using the contents of the
.reloc section.
(3) On IA-64, the EFI entry point needs to point to a function
descriptor, not to the code address of the entry point.
(4) The EFI specification assumes that wide characters use UNICODE
encoding.
ANSI C does not specify the size or encoding that a wide
character uses. These choices are "implementation defined".
On most UNIX systems, the GNU toolchain uses a wchar_t that is
4 bytes in size. The encoding used for such characters is
(mostly) UCS4.
In the following sections, we address how the GNU EFI build
environment addresses each of these issues.
** (1) Accommodating COFF Sections
In order to satisfy the COFF constraint of page-sized and page-aligned
sections, the GNU EFI build environment uses the special linker script
in gnuefi/elf_$(ARCH)_efi.lds where $(ARCH) is the target architecture
("ia32" for x86, "x86_64" for x86_64 and "ia64" for IA-64).
This script is set up to create only eight COFF section, each page aligned
and page sized.These eight sections are used to group together the much
greater number of sections that are typically present in ELF object files.
Specifically:
.hash (and/or .gnu.hash)
Collects the ELF .hash info (this section _must_ be the first
section in order to build a shared object file; the section is
not actually loaded or used at runtime).
GNU binutils provides a mechanism to generate different hash info
via --hash-style=<sysv|gnu|both> option. In this case output
shared object will contain .hash section, .gnu.hash section or
both. In order to generate correct output linker script preserves
both types of hash sections.
.text
Collects all sections containing executable code.
.data
Collects read-only and read-write data, literal string data,
global offset tables, the uninitialized data segment (bss) and
various other sections containing data.
The reason read-only data is placed here instead of the in
.text is to make it possible to disassemble the .text section
without getting garbage due to read-only data. Besides, since
EFI binaries execute in physical mode, differences in page
protection do not matter.
The reason the uninitialized data is placed in this section is
that the EFI loader appears to be unable to handle sections
that are allocated but not loaded from the binary.
.dynamic, .dynsym, .rela, .rel, .reloc
These sections contains the dynamic information necessary to
self-relocate the binary (see below).
A couple of more points worth noting about the linker script:
o On IA-64, the global pointer symbol (__gp) needs to be placed such
that the _entire_ EFI binary can be addressed using the signed
22-bit offset that the "addl" instruction affords. Specifically,
this means that __gp should be placed at ImageBase + 0x200000.
Strictly speaking, only a couple of symbols need to be addressable
in this fashion, so with some care it should be possible to build
binaries much larger than 4MB. To get a list of symbols that need
to be addressable in this fashion, grep the assembly files in
directory gnuefi for the string "@gprel".
o The link address (ImageBase) of the binary is (arbitrarily) set to
zero. This could be set to something larger to increase the chance
of EFI being able to load the binary without requiring relocation.
However, a start address of 0 makes debugging a wee bit easier
(great for those of us who can add, but not subtract... ;-).
o The relocation related sections (.dynamic, .rel, .rela, .reloc)
cannot be placed inside .data because some tools in the GNU
toolchain rely on the existence of these sections.
o Some sections in the ELF binary intentionally get dropped when
building the EFI binary. Particularly noteworthy are the dynamic
relocation sections for the .plabel and .reloc sections. It would
be _wrong_ to include these sections in the EFI binary because it
would result in .reloc and .plabel being relocated twice (once by
the EFI loader and once by the self-relocator; see below for a
description of the latter). Specifically, only the sections
mentioned with the -j option in the final "objcopy" command are
retained in the EFI binary (see Make.rules).
** (2) Building Relocatable Binaries
ELF binaries are normally linked for a fixed load address and are thus
not relocatable. The only kind of ELF object that is relocatable are
shared objects ("shared libraries"). However, even those objects are
usually not completely position independent and therefore require
runtime relocation by the dynamic loader. For example, IA-64 binaries
normally require relocation of the global offset table.
The approach to building relocatable binaries in the GNU EFI build
environment is to:
(a) build an ELF shared object
(b) link it together with a self-relocator that takes care of
applying the dynamic relocations that may be present in the
ELF shared object
(c) convert the resulting image to an EFI binary
The self-relocator is of course architecture dependent. The x86
version can be found in gnuefi/reloc_ia32.c, the x86_64 version
can be found in gnuefi/reloc_x86_64.c and the IA-64 version can be
found in gnuefi/reloc_ia64.S.
The self-relocator operates as follows: the startup code invokes it
right after EFI has handed off control to the EFI binary at symbol
"_start". Upon activation, the self-relocator searches the .dynamic
section (whose starting address is given by symbol _DYNAMIC) for the
dynamic relocation information, which can be found in the DT_REL,
DT_RELSZ, and DT_RELENT entries of the dynamic table (DT_RELA,
DT_RELASZ, and DT_RELAENT in the case of rela relocations, as is the
case for IA-64). The dynamic relocation information points to the ELF
relocation table. Once this table is found, the self-relocator walks
through it, applying each relocation one by one. Since the EFI
binaries are fully resolved shared objects, only a subset of all
possible relocations need to be supported. Specifically, on x86 only
the R_386_RELATIVE relocation is needed. On IA-64, the relocations
R_IA64_DIR64LSB, R_IA64_REL64LSB, and R_IA64_FPTR64LSB are needed.
Note that the R_IA64_FPTR64LSB relocation requires access to the
dynamic symbol table. This is why the .dynsym section is included in
the EFI binary. Another complication is that this relocation requires
memory to hold the function descriptors (aka "procedure labels" or
"plabels"). Each function descriptor uses 16 bytes of memory. The
IA-64 self-relocator currently reserves a static memory area that can
hold 100 of these descriptors. If the self-relocator runs out of
space, it causes the EFI binary to fail with error code 5
(EFI_BUFFER_TOO_SMALL). When this happens, the manifest constant
MAX_FUNCTION_DESCRIPTORS in gnuefi/reloc_ia64.S should be increased
and the application recompiled. An easy way to count the number of
function descriptors required by an EFI application is to run the
command:
objdump --dynamic-reloc example.so | fgrep FPTR64 | wc -l
assuming "example" is the name of the desired EFI application.
** (3) Creating the Function Descriptor for the IA-64 EFI Binaries
As mentioned above, the IA-64 PE32+ format assumes that the entry
point of the binary is a function descriptor. A function descriptors
consists of two double words: the first one is the code entry point
and the second is the global pointer that should be loaded before
calling the entry point. Since the ELF toolchain doesn't know how to
generate a function descriptor for the entry point, the startup code
in gnuefi/crt0-efi-ia64.S crafts one manually by with the code:
.section .plabel, "a"
_start_plabel:
data8 _start
data8 __gp
this places the procedure label for entry point _start in a section
called ".plabel". Now, the only problem is that _start and __gp need
to be relocated _before_ EFI hands control over to the EFI binary.
Fortunately, PE32+ defines a section called ".reloc" that can achieve
this. Thus, in addition to manually crafting the function descriptor,
the startup code also crafts a ".reloc" section that has will cause
the EFI loader to relocate the function descriptor before handing over
control to the EFI binary (again, see the PECOFF spec mentioned above
for details).
A final question may be why .plabel and .reloc need to go in their own
COFF sections. The answer is simply: we need to be able to discard
the relocation entries that are generated for these sections. By
placing them in these sections, the relocations end up in sections
".rela.plabel" and ".rela.reloc" which makes it easy to filter them
out in the filter script. Also, the ".reloc" section needs to be in
its own section so that the objcopy program can recognize it and can
create the correct directory entries in the PE32+ binary.
** (4) Convenient and Portable Generation of UNICODE String Literals
As of gnu-efi-3.0, we make use (and somewhat abuse) the gcc option
that forces wide characters (WCHAR_T) to use short integers (2 bytes)
instead of integers (4 bytes). This way we match the Unicode character
size. By abuse, we mean that we rely on the fact that the regular ASCII
characters are encoded the same way between (short) wide characters
and Unicode and basically only use the first byte. This allows us
to just use them interchangeably.
The gcc option to force short wide characters is : -fshort-wchar
* * * The End * * *

184
gnu-efi/apps/AllocPages.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright (C) 2013 Jerry Hoemann <jerry.hoemann@hp.com>
*
*
* Application to allocate memory at EFI. Syntax of command
* mimics the EFI Boot Service "AllocatePages."
*
* See UEFI spec 2.3, Section 6.2.
*
*
FS1:\> memmap
Type Start End #pages Attributes
BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
Available 0000000010062000-000000005CDFFFFF 000000000004CD9E 000000000000000F
ACPI_NVS 000000005CE00000-000000005DDFFFFF 0000000000001000 000000000000000F
BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
Available 000000005E000000-000000005EF1CFFF 0000000000000F1D 000000000000000F
BS_Data 000000005EF1D000-00000000709FBFFF 0000000000011ADF 000000000000000F
Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
LoaderCode 00000000710E4000-00000000711FEFFF 000000000000011B 000000000000000F
Available 00000000711FF000-0000000071901FFF 0000000000000703 000000000000000F
BS_Code 0000000071902000-00000000721FEFFF 00000000000008FD 000000000000000F
Example to allocat 5 pages type BootCode at address 20000000 (hex)
FS1:\> AllocPages.efi 2 3 5 20000000
AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__]
__AllocType__ {0,1,2} -- Any, MaxAddr, Addr
__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ...
__NumPages__ {0..F000000}
[__Addr__] 0... 3FFFFFFFFFFF
All numbers in hex no leading 0x
AllocatPage(2,3,5,20000000)
Example to allocat 5 pages type BootCode at address 30000000 (hex)
FS1:\> AllocPages.efi 2 3 5 30000000
AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__]
__AllocType__ {0,1,2} -- Any, MaxAddr, Addr
__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ...
__NumPages__ {0..F000000}
[__Addr__] 0... 3FFFFFFFFFFF
All numbers in hex no leading 0x
FS1:\> memmap
Type Start End #pages Attributes
BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
Available 0000000010062000-000000001FFFFFFF 000000000000FF9E 000000000000000F
BS_Code 0000000020000000-0000000020004FFF 0000000000000005 000000000000000F
Available 0000000020005000-000000002FFFFFFF 000000000000FFFB 000000000000000F
BS_Code 0000000030000000-0000000030004FFF 0000000000000005 000000000000000F
Available 0000000030005000-000000005CDFFFFF 000000000002CDFB 000000000000000F
ACPI_NVS 000000005CE00000-000000005DDFFFFF 0000000000001000 000000000000000F
BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
Available 000000005E000000-000000005EF1CFFF 0000000000000F1D 000000000000000F
BS_Data 000000005EF1D000-00000000709FBFFF 0000000000011ADF 000000000000000F
Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
LoaderCode 00000000710E4000-00000000711FEFFF 000000000000011B 000000000000000F
Available 00000000711FF000-0000000071901FFF 0000000000000703 000000000000000F
BS_Code 0000000071902000-00000000721FEFFF 00000000000008FD 000000000000000F
*/
#include <efi.h>
#include <efilib.h>
#define MAX_NUM_PAGES 0x000000000F000000
#define MAX_ADDR ((1ULL << 46) - 1)
#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG 0
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS efi_status;
CHAR16 **argv;
INTN argc;
INTN err = 0;
#if DEBUG
INTN c = 0;
#endif
INTN AllocType = -1;
INTN MemType = -1;
INTN NumPages = -1;
EFI_PHYSICAL_ADDRESS Addr = 0;
InitializeLib(image, systab);
Print(L"AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__]\n");
Print(L"__AllocType__ {0,1,2} -- Any, MaxAddr, Addr\n");
Print(L"__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ...\n");
Print(L"__NumPages__ {0..%x}\n", MAX_NUM_PAGES);
Print(L"[__Addr__] 0... %llx\n", MAX_ADDR);
Print(L"All numbers in hex no leading 0x\n");
Print(L"\n");
#if DEBUG
Print(L"Now get argc/argv\n");
#endif
argc = GetShellArgcArgv(image, &argv);
#if DEBUG
Print(L"argc = %d\n", argc);
#endif
#if DEBUG
for (c = 0; c < argc; c++ ) {
Print(L"argv[%d] = <%s>\n", c, argv[c]);
}
#endif
if ( (argc < 4) || (argc > 5) ) {
Print(L"Wrong argument count\n");
return EFI_SUCCESS;
}
AllocType = xtoi(argv[1]);
MemType = xtoi(argv[2]);
NumPages = xtoi(argv[3]);
if ( argc == 5 ) Addr = xtoi(argv[4]);
if ( (AllocType < 0) || (AllocType > 2)) {
Print(L"Invalid AllocType\n");
err++;
}
if ( (MemType < 0) || (MemType > 13) ) {
Print(L"Invalid MemType\n");
err++;
}
if ( (NumPages < 0) || (NumPages > MAX_NUM_PAGES) ) {
Print(L"Inavlid NumPages\n");
err++;
}
if ( Addr > MAX_ADDR ) {
Print(L"Inavlid Address\n");
err++;
}
if ( err ) {
return EFI_INVALID_PARAMETER;
}
Print(L"AllocatPage(%d,%d,%d,%lx)\n", AllocType, MemType, NumPages, Addr);
efi_status = uefi_call_wrapper(BS->AllocatePages, 4, AllocType, MemType, NumPages, &Addr);
if ( EFI_ERROR(efi_status) ) {
Print(L"Allocate Pages Failed: %d\n", efi_status);
return efi_status;
}
return EFI_SUCCESS;
}

145
gnu-efi/apps/FreePages.c Normal file
View File

@ -0,0 +1,145 @@
/*
* Copyright (C) 2013 Jerry Hoemann <jerry.hoemann@hp.com>
*
* Application to allocate memory at EFI. Syntax of command
* mimics the EFI Boot Service "FreePages."
*
* See UEFI spec 2.3, Section 6.2.
*
Example freeing a 5 page BS_Code setment at address: 0000000020000000 (hex)
FS1:\> memmap
Type Start End #pages Attributes
BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
Available 0000000010062000-000000001FFFFFFF 000000000000FF9E 000000000000000F
BS_Code 0000000020000000-0000000020004FFF 0000000000000005 000000000000000F
Available 0000000020005000-000000005DDFFFFF 000000000003DDFB 000000000000000F
BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F
ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F
BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F
Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
FS1:\> FreePages 0000000020000000 5
FreePages: __PhysAddr__ __PgCnt__
__PhysAddr__ 0... 3FFFFFFFFFFF
__PgCnt__ [0..F000000]
All numbers hex w/ no leading 0x
FreePages(20000000,5)
FS1:\> memmap
Type Start End #pages Attributes
BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F
Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F
Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F
Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F
BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F
Available 0000000010062000-000000005DDFFFFF 000000000004DD9E 000000000000000F
BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F
Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F
ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F
BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F
Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F
*/
#include <efi.h>
#include <efilib.h>
/*
* FreePages: __PhysAddr__ __PgCnt__
*
*/
#define MAX_NUM_PAGES 0x000000000F000000
#define MAX_ADDR ((1ULL << 46) - 1)
#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG 0
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS efi_status;
CHAR16 **argv;
INTN argc = 0;
#if DEBUG
INTN c = 0;
#endif
INTN err = 0;
INTN PgCnt = -1;
EFI_PHYSICAL_ADDRESS PhysAddr = 0;
InitializeLib(image, systab);
Print(L"FreePages: __PhysAddr__ __PgCnt__\n");
Print(L"__PhysAddr__ 0... %llx\n", MAX_ADDR);
Print(L"__PgCnt__ [0..%lx]\n", MAX_NUM_PAGES);
Print(L"All numbers hex w/ no leading 0x\n");
Print(L"\n");
#if DEBUG
Print(L"Now parse argc/argv\n");
#endif
argc = GetShellArgcArgv(image, &argv);
#if DEBUG
Print(L"argc = %d\n", argc);
#endif
#if DEBUG
for (c = 0; c < argc; c++ ) {
Print(L"argv[%d] = <%s>\n", c, argv[c]);
}
#endif
if (argc != 3) {
Print(L"Invalid argument count\n");
return EFI_SUCCESS;
}
PhysAddr = xtoi(argv[1]);
PgCnt = xtoi(argv[2]);
if ( (PgCnt < 0) || (PgCnt > MAX_NUM_PAGES) ) {
Print(L"Inavlid PgCnt\n");
err++;
}
if ( PhysAddr > MAX_ADDR ) {
Print(L"Inavlid Address\n");
err++;
}
if ( err ) {
return EFI_SUCCESS;
}
Print(L"FreePages(%lx,%d)\n", PhysAddr, PgCnt);
efi_status = uefi_call_wrapper(BS->FreePages, 2, PhysAddr, PgCnt);
if ( EFI_ERROR(efi_status) ) {
Print(L"Free Pages Failed: %d\n", efi_status);
return efi_status;
}
return EFI_SUCCESS;
}

95
gnu-efi/apps/Makefile Normal file
View File

@ -0,0 +1,95 @@
#
# Copyright (C) 1999-2001 Hewlett-Packard Co.
# Contributed by David Mosberger <davidm@hpl.hp.com>
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANYDIRECT, 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.
#
SRCDIR = .
VPATH = $(SRCDIR)
include $(SRCDIR)/../Make.defaults
TOPDIR = $(SRCDIR)/..
CDIR=$(TOPDIR)/..
LINUX_HEADERS = /usr/src/sys/build
CPPFLAGS += -D__KERNEL__ -I$(LINUX_HEADERS)/include
CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o
LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_efi.lds
ifneq (,$(findstring FreeBSD,$(OS)))
LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_fbsd_efi.lds
endif
LDFLAGS += -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS)
LOADLIBES += -lefi -lgnuefi
LOADLIBES += $(LIBGCC)
LOADLIBES += -T $(LDSCRIPT)
TARGET_APPS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi \
printenv.efi t7.efi t8.efi tcc.efi modelist.efi \
route80h.efi drv0_use.efi AllocPages.efi exit.efi \
FreePages.efi setjmp.efi debughook.efi debughook.efi.debug \
bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi
TARGET_BSDRIVERS = drv0.efi
TARGET_RTDRIVERS =
ifneq ($(HAVE_EFI_OBJCOPY),)
FORMAT := --target efi-app-$(ARCH)
$(TARGET_BSDRIVERS): FORMAT=--target efi-bsdrv-$(ARCH)
$(TARGET_RTDRIVERS): FORMAT=--target efi-rtdrv-$(ARCH)
else
SUBSYSTEM := 0xa
$(TARGET_BSDRIVERS): SUBSYSTEM = 0xb
$(TARGET_RTDRIVERS): SUBSYSTEM = 0xc
FORMAT := -O binary
LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
endif
TARGETS = $(TARGET_APPS) $(TARGET_BSDRIVERS) $(TARGET_RTDRIVERS)
all: $(TARGETS)
clean:
rm -f $(TARGETS) *~ *.o *.so
.PHONY: install
include $(SRCDIR)/../Make.rules

131
gnu-efi/apps/bltgrid.c Normal file
View File

@ -0,0 +1,131 @@
#include <efi.h>
#include <efilib.h>
extern EFI_GUID GraphicsOutputProtocol;
static void
fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height)
{
UINT32 y, x = 0;
/*
* This assums BGRR, but it doesn't really matter; we pick red and
* green so it'll just be blue/green if the pixel format is backwards.
*/
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Red = {0, 0, 0xff, 0},
Green = {0, 0xff, 0, 0},
*Color;
for (y = 0; y < Height; y++) {
Color = ((y / 32) % 2 == 0) ? &Red : &Green;
for (x = 0; x < Width; x++) {
if (x % 32 == 0 && x != 0)
Color = (Color == &Red) ? &Green : &Red;
PixelBuffer[y * Width + x] = *(UINT32 *)Color;
}
}
}
static void
draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
{
int i, imax;
EFI_STATUS rc;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN NumPixels;
UINT32 *PixelBuffer;
UINT32 BufferSize;
if (gop->Mode) {
imax = gop->Mode->MaxMode;
} else {
Print(L"gop->Mode is NULL\n");
return;
}
for (i = 0; i < imax; i++) {
UINTN SizeOfInfo;
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
&info);
if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) {
Print(L"gop->QueryMode() returned %r\n", rc);
Print(L"Trying to start GOP with SetMode().\n");
rc = uefi_call_wrapper(gop->SetMode, 2, gop,
gop->Mode ? gop->Mode->Mode : 0);
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
&SizeOfInfo, &info);
}
if (EFI_ERROR(rc)) {
Print(L"%d: Bad response from QueryMode: %r (%d)\n",
i, rc, rc);
continue;
}
if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
continue;
NumPixels = info->VerticalResolution * info->HorizontalResolution;
BufferSize = NumPixels * sizeof(UINT32);
PixelBuffer = AllocatePool(BufferSize);
if (!PixelBuffer) {
Print(L"Allocation of 0x%08lx bytes failed.\n",
sizeof(UINT32) * NumPixels);
return;
}
fill_boxes(PixelBuffer,
info->HorizontalResolution, info->VerticalResolution);
uefi_call_wrapper(gop->Blt, 10, gop,
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)PixelBuffer,
EfiBltBufferToVideo,
0, 0, 0, 0,
info->HorizontalResolution,
info->VerticalResolution,
0);
return;
}
Print(L"Never found the active video mode?\n");
}
static EFI_STATUS
SetWatchdog(UINTN seconds)
{
EFI_STATUS rc;
rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
0, NULL);
if (EFI_ERROR(rc)) {
CHAR16 Buffer[64];
StatusToString(Buffer, rc);
Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
}
return rc;
}
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS rc;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
InitializeLib(image_handle, systab);
SetWatchdog(10);
rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
if (EFI_ERROR(rc)) {
Print(L"Could not locate GOP: %r\n", rc);
return rc;
}
if (!gop) {
Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc);
return EFI_UNSUPPORTED;
}
draw_boxes(gop);
SetWatchdog(0);
return EFI_SUCCESS;
}

97
gnu-efi/apps/debughook.c Normal file
View File

@ -0,0 +1,97 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
GetVariableAttr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
UINT32 *attributes)
{
EFI_STATUS efi_status;
*len = 0;
efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
NULL, len, NULL);
if (efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
*data = AllocateZeroPool(*len);
if (!*data)
return EFI_OUT_OF_RESOURCES;
efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
attributes, len, *data);
if (efi_status != EFI_SUCCESS) {
FreePool(*data);
*data = NULL;
}
return efi_status;
}
EFI_STATUS
GetVariable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner)
{
return GetVariableAttr(var, data, len, owner, NULL);
}
EFI_GUID DUMMY_GUID =
{0x55aad538, 0x8f82, 0x4e2a, {0xa4,0xf0,0xbe, 0x59, 0x13, 0xb6, 0x5f, 0x1e}};
#if defined(__clang__)
# define _OPTNONE __attribute__((optnone))
#else
# define _OPTNONE __attribute__((__optimize__("0")))
#endif
static _OPTNONE void
DebugHook(void)
{
EFI_GUID guid = DUMMY_GUID;
UINT8 *data = NULL;
UINTN dataSize = 0;
EFI_STATUS efi_status;
register volatile unsigned long long x = 0;
extern char _text, _data;
if (x)
return;
efi_status = GetVariable(L"DUMMY_DEBUG", &data, &dataSize, guid);
if (EFI_ERROR(efi_status)) {
return;
}
Print(L"add-symbol-file /usr/lib/debug/boot/efi/debughook.debug "
L"0x%08x -s .data 0x%08x\n", &_text, &_data);
Print(L"Pausing for debugger attachment.\n");
Print(L"To disable this, remove the EFI variable DUMMY_DEBUG-%g .\n",
&guid);
x = 1;
while (x++) {
/* Make this so it can't /totally/ DoS us. */
#if defined(__x86_64__) || defined(__i386__) || defined(__i686__)
if (x > 4294967294ULL)
break;
__asm__ __volatile__("pause");
#elif defined(__aarch64__)
if (x > 1000)
break;
__asm__ __volatile__("wfi");
#else
if (x > 12000)
break;
uefi_call_wrapper(BS->Stall, 1, 5000);
#endif
}
x = 1;
}
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
InitializeLib(image, systab);
DebugHook();
return EFI_SUCCESS;
}

191
gnu-efi/apps/drv0.c Normal file
View File

@ -0,0 +1,191 @@
/*
* Copyright (C) 2013 David Decotigny <decot@googlers.com>
*
* Sample EFI shell session, together with drv0_use.efi:
*
* # Loading first instance:
*
* fs0:\> load drv0.efi
* Driver instance loaded successfully.
* load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success
*
* # Testing 1st instance:
*
* fs0:\> drv0_use.efi
* Playing with driver instance 0...
* Hello Sample UEFI Driver!
* Hello was called 1 time(s).
*
* fs0:\> drv0_use.efi
* Playing with driver instance 0...
* Hello Sample UEFI Driver!
* Hello was called 2 time(s).
*
* # Loading another instance:
*
* fs0:\> load drv0.efi
* Driver instance loaded successfully.
* load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success
*
* # Using both instances:
*
* fs0:\> drv0_use.efi
* Playing with driver instance 0...
* Hello Sample UEFI Driver!
* Hello was called 3 time(s).
* Playing with driver instance 1...
* Hello Sample UEFI Driver!
* Hello was called 1 time(s).
*
* fs0:\> drv0_use.efi
* Playing with driver instance 0...
* Hello Sample UEFI Driver!
* Hello was called 4 time(s).
* Playing with driver instance 1...
* Hello Sample UEFI Driver!
* Hello was called 2 time(s).
*
* # Removing 1st instance:
*
* fs0:\> dh
* Handle dump
* 1: Image(DxeCore)
* [...]
* 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
* 7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
*
* fs0:\> unload 79
* 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
* Unload driver image (y/n)? y
* Driver instance unloaded.
* unload: Success
*
* # Only 2nd instance remaining:
*
* fs0:\> drv0_use.efi
* Playing with driver instance 0...
* Hello Sample UEFI Driver!
* Hello was called 3 time(s).
*
* # Removing 2nd/last instance:
*
* fs0:\> dh
* Handle dump
* 1: Image(DxeCore)
* [...]
* 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
*
* fs0:\> unload 79
* 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
* Unload driver image (y/n)? y
* Driver instance unloaded.
* unload: Success
*
* # Expect error: no other drv0 instance left
*
* fs0:\> drv0_use.efi
* Error looking up handles for proto: 14
*/
#include <efi.h>
#include <efilib.h>
#include "drv0.h"
static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid
= GNU_EFI_APPS_DRV0_PROTOCOL_GUID;
static struct {
GNU_EFI_APPS_DRV0_PROTOCOL Proto;
UINTN Counter;
} InternalGnuEfiAppsDrv0ProtocolData;
static
EFI_STATUS
EFI_FUNCTION
Drv0SayHello(
IN const CHAR16 *HelloWho
)
{
if (! HelloWho)
return EFI_INVALID_PARAMETER;
Print(L"Hello %s!\n", HelloWho);
InternalGnuEfiAppsDrv0ProtocolData.Counter ++;
return EFI_SUCCESS;
}
static
EFI_STATUS
EFI_FUNCTION
Drv0GetNumberOfHello(
OUT UINTN *NumberOfHello
)
{
if (! NumberOfHello)
return EFI_INVALID_PARAMETER;
*NumberOfHello = InternalGnuEfiAppsDrv0ProtocolData.Counter;
return EFI_SUCCESS;
}
static
EFI_STATUS
EFI_FUNCTION
Drv0Unload(IN EFI_HANDLE ImageHandle)
{
LibUninstallProtocolInterfaces(ImageHandle,
&GnuEfiAppsDrv0ProtocolGuid,
&InternalGnuEfiAppsDrv0ProtocolData.Proto,
NULL);
Print(L"Driver instance unloaded.\n", ImageHandle);
return EFI_SUCCESS;
}
EFI_STATUS
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SysTab)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE *LoadedImage = NULL;
InitializeLib(ImageHandle, SysTab);
/* Initialize global protocol definition + data */
InternalGnuEfiAppsDrv0ProtocolData.Proto.SayHello
= (GNU_EFI_APPS_DRV0_SAY_HELLO) Drv0SayHello;
InternalGnuEfiAppsDrv0ProtocolData.Proto.GetNumberOfHello
= (GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) Drv0GetNumberOfHello;
InternalGnuEfiAppsDrv0ProtocolData.Counter = 0;
/* Grab handle to this image: we'll attach our proto instance to it */
Status = uefi_call_wrapper(BS->OpenProtocol, 6,
ImageHandle, &LoadedImageProtocol,
(void**)&LoadedImage, ImageHandle,
NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
Print(L"Could not open loaded image protocol: %d\n", Status);
return Status;
}
/* Attach our proto to the current driver image */
Status = LibInstallProtocolInterfaces(
&ImageHandle, &GnuEfiAppsDrv0ProtocolGuid,
&InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL);
if (EFI_ERROR(Status)) {
Print(L"Error registering driver instance: %d\n", Status);
return Status;
}
/* Register Unload callback, used to unregister current protocol
* instance from system */
LoadedImage->Unload = (EFI_IMAGE_UNLOAD)Drv0Unload;
Print(L"Driver instance loaded successfully.\n");
return EFI_SUCCESS; /* at this point, this instance stays resident
* until image is unloaded, eg. with shell's unload,
* ExitBootServices() */
}

35
gnu-efi/apps/drv0.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef _GNU_EFI_APPS_DRV0_H_
#define _GNU_EFI_APPS_DRV0_H_
#ifdef __cplusplus
extern "C" {
#endif
/* UEFI naming conventions */
#define GNU_EFI_APPS_DRV0_PROTOCOL_GUID \
{ 0xe4dcafd0, 0x586c, 0x4b3d, {0x86, 0xe7, 0x28, 0xde, 0x7f, 0xcc, 0x04, 0xb9} }
INTERFACE_DECL(_GNU_EFI_APPS_DRV0_PROTOCOL);
typedef
EFI_STATUS
(EFIAPI *GNU_EFI_APPS_DRV0_SAY_HELLO) (
IN const CHAR16 *HelloWho
);
typedef
EFI_STATUS
(EFIAPI *GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) (
OUT UINTN *NumberOfHello
);
typedef struct _GNU_EFI_APPS_DRV0_PROTOCOL {
GNU_EFI_APPS_DRV0_SAY_HELLO SayHello;
GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO GetNumberOfHello;
} GNU_EFI_APPS_DRV0_PROTOCOL;
#ifdef __cplusplus
}
#endif
#endif

79
gnu-efi/apps/drv0_use.c Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2013 David Decotigny <decot@googlers.com>
*
* See drv0.c for an example session.
*/
#include <efi.h>
#include <efilib.h>
#include "drv0.h"
static EFI_GUID GnuEfiAppsDrv0ProtocolGuid
= GNU_EFI_APPS_DRV0_PROTOCOL_GUID;
static
EFI_STATUS
PlayWithGnuEfiAppsDrv0Protocol(IN EFI_HANDLE DrvHandle) {
EFI_STATUS Status;
GNU_EFI_APPS_DRV0_PROTOCOL *drv = NULL;
UINTN NumberOfHello = 0;
Status = uefi_call_wrapper(BS->OpenProtocol, 6,
DrvHandle,
&GnuEfiAppsDrv0ProtocolGuid,
(void**)&drv,
DrvHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
Print(L"Cannot open proto: %d\n", Status);
return Status;
}
Status = uefi_call_wrapper(drv->SayHello, 2, L"Sample UEFI Driver");
if (EFI_ERROR(Status)) {
Print(L"Cannot call SayHello: %d\n", Status);
}
Status = uefi_call_wrapper(drv->GetNumberOfHello, 2, &NumberOfHello);
if (EFI_ERROR(Status)) {
Print(L"Cannot call GetNumberOfHello: %d\n", Status);
} else {
Print(L"Hello was called %d time(s).\n", NumberOfHello);
}
return EFI_SUCCESS;
}
EFI_STATUS
efi_main (EFI_HANDLE Image, EFI_SYSTEM_TABLE *SysTab)
{
EFI_STATUS Status;
EFI_HANDLE *Handles = NULL;
UINTN i, NoHandles = 0;
InitializeLib(Image, SysTab);
Status = LibLocateHandle(ByProtocol, &GnuEfiAppsDrv0ProtocolGuid,
NULL, &NoHandles, &Handles);
if (EFI_ERROR(Status)) {
Print(L"Error looking up handles for proto: %d\n", Status);
return Status;
}
for (i = 0 ; i < NoHandles ; ++i)
{
Print(L"Playing with driver instance %d...\n", i);
Status = PlayWithGnuEfiAppsDrv0Protocol(Handles[i]);
if (EFI_ERROR(Status))
Print(L"Error playing with instance %d, skipping\n", i);
}
if (Handles)
FreePool(Handles);
return EFI_SUCCESS;
}

12
gnu-efi/apps/exit.c Normal file
View File

@ -0,0 +1,12 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
InitializeLib(image_handle, systab);
Exit(EFI_SUCCESS, 0, NULL);
return EFI_UNSUPPORTED;
}

170
gnu-efi/apps/lfbgrid.c Normal file
View File

@ -0,0 +1,170 @@
#include <efi.h>
#include <efilib.h>
extern EFI_GUID GraphicsOutputProtocol;
#define be32_to_cpu(x) __builtin_bswap32(x)
static void
fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height, UINT32 Pitch,
EFI_GRAPHICS_PIXEL_FORMAT Format, EFI_PIXEL_BITMASK Info )
{
UINT32 Red, Green;
UINT32 y, x, color;
switch(Format) {
case PixelRedGreenBlueReserved8BitPerColor:
Red = be32_to_cpu(0xff000000);
Green = be32_to_cpu(0x00ff0000);
break;
case PixelBlueGreenRedReserved8BitPerColor:
Red = be32_to_cpu(0x0000ff00);
Green = be32_to_cpu(0x00ff0000);
break;
case PixelBitMask:
Red = Info.RedMask;
Green = Info.GreenMask;
break;
case PixelBltOnly:
return;
default:
Print(L"Invalid pixel format\n");
return;
}
for (y = 0; y < Height; y++) {
color = ((y / 32) % 2 == 0) ? Red : Green;
for (x = 0; x < Width; x++) {
if (x % 32 == 0 && x != 0)
color = (color == Red) ? Green : Red;
PixelBuffer[y * Pitch + x] = color;
}
}
}
static void
draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
{
int i, imax;
EFI_STATUS rc;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN NumPixels;
UINT32 *PixelBuffer;
UINT32 CopySize, BufferSize;
#if defined(__x86_64__) || defined(__aarch64__)
UINT64 FrameBufferAddr;
#elif defined(__i386__) || defined(__arm__)
UINT32 FrameBufferAddr;
#else
#error YOUR ARCH HERE
#endif
if (gop->Mode) {
imax = gop->Mode->MaxMode;
} else {
Print(L"gop->Mode is NULL\n");
return;
}
for (i = 0; i < imax; i++) {
UINTN SizeOfInfo;
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
&info);
if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) {
Print(L"gop->QueryMode() returned %r\n", rc);
Print(L"Trying to start GOP with SetMode().\n");
rc = uefi_call_wrapper(gop->SetMode, 2, gop,
gop->Mode ? gop->Mode->Mode : 0);
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
&SizeOfInfo, &info);
}
if (EFI_ERROR(rc)) {
Print(L"%d: Bad response from QueryMode: %r (%d)\n",
i, rc, rc);
continue;
}
if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
continue;
NumPixels = info->VerticalResolution * info->PixelsPerScanLine;
BufferSize = NumPixels * sizeof(UINT32);
if (BufferSize == gop->Mode->FrameBufferSize) {
CopySize = BufferSize;
} else {
CopySize = BufferSize < gop->Mode->FrameBufferSize ?
BufferSize : gop->Mode->FrameBufferSize;
Print(L"height * pitch * pixelsize = %lu buf fb size is %lu; using %lu\n",
BufferSize, gop->Mode->FrameBufferSize, CopySize);
}
PixelBuffer = AllocatePool(BufferSize);
if (!PixelBuffer) {
Print(L"Allocation of 0x%08lx bytes failed.\n",
sizeof(UINT32) * NumPixels);
return;
}
fill_boxes(PixelBuffer, info->HorizontalResolution,
info->VerticalResolution, info->PixelsPerScanLine,
info->PixelFormat, info->PixelInformation);
if (info->PixelFormat == PixelBltOnly) {
Print(L"No linear framebuffer on this device.\n");
return;
}
#if defined(__x86_64__) || defined(__aarch64__)
FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase;
#elif defined(__i386__) || defined(__arm__)
FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase;
#else
#error YOUR ARCH HERE
#endif
CopyMem((VOID *)FrameBufferAddr, PixelBuffer, CopySize);
return;
}
Print(L"Never found the active video mode?\n");
}
static EFI_STATUS
SetWatchdog(UINTN seconds)
{
EFI_STATUS rc;
rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
0, NULL);
if (EFI_ERROR(rc)) {
CHAR16 Buffer[64];
StatusToString(Buffer, rc);
Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
}
return rc;
}
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS rc;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
InitializeLib(image_handle, systab);
SetWatchdog(10);
rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
if (EFI_ERROR(rc)) {
Print(L"Could not locate GOP: %r\n", rc);
return rc;
}
if (!gop) {
Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc);
return EFI_UNSUPPORTED;
}
draw_boxes(gop);
SetWatchdog(0);
return EFI_SUCCESS;
}

108
gnu-efi/apps/modelist.c Normal file
View File

@ -0,0 +1,108 @@
#include <efi.h>
#include <efilib.h>
extern EFI_GUID GraphicsOutputProtocol;
static void
print_modes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
{
int i, imax;
EFI_STATUS rc;
if (gop->Mode) {
imax = gop->Mode->MaxMode;
Print(L"GOP reports MaxMode %d\n", imax);
} else {
Print(L"gop->Mode is NULL\n");
imax = 1;
}
for (i = 0; i < imax; i++) {
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN SizeOfInfo;
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
&info);
if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) {
Print(L"gop->QueryMode() returned %r\n", rc);
Print(L"Trying to start GOP with SetMode().\n");
rc = uefi_call_wrapper(gop->SetMode, 2, gop,
gop->Mode ? gop->Mode->Mode : 0);
rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
&SizeOfInfo, &info);
}
if (EFI_ERROR(rc)) {
Print(L"%d: Bad response from QueryMode: %r (%d)\n",
i, rc, rc);
continue;
}
Print(L"%c%d: %dx%d ",
(gop->Mode &&
CompareMem(info,gop->Mode->Info,sizeof(*info)) == 0
) ? '*' : ' ',
i, info->HorizontalResolution, info->VerticalResolution);
switch(info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
Print(L"RGBR");
break;
case PixelBlueGreenRedReserved8BitPerColor:
Print(L"BGRR");
break;
case PixelBitMask:
Print(L"R:%08x G:%08x B:%08x X:%08x",
info->PixelInformation.RedMask,
info->PixelInformation.GreenMask,
info->PixelInformation.BlueMask,
info->PixelInformation.ReservedMask);
break;
case PixelBltOnly:
Print(L"(blt only)");
break;
default:
Print(L"(Invalid pixel format)");
break;
}
Print(L" pitch %d\n", info->PixelsPerScanLine);
}
}
static EFI_STATUS
SetWatchdog(UINTN seconds)
{
EFI_STATUS rc;
rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
0, NULL);
if (EFI_ERROR(rc)) {
CHAR16 Buffer[64];
StatusToString(Buffer, rc);
Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
}
return rc;
}
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS rc;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
InitializeLib(image_handle, systab);
SetWatchdog(10);
rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
if (EFI_ERROR(rc)) {
Print(L"Could not locate GOP: %r\n", rc);
return rc;
}
if (!gop) {
Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc);
return EFI_UNSUPPORTED;
}
print_modes(gop);
SetWatchdog(0);
return EFI_SUCCESS;
}

32
gnu-efi/apps/printenv.c Normal file
View File

@ -0,0 +1,32 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS status;
CHAR16 name[256], *val, fmt[20];
EFI_GUID vendor;
UINTN size;
InitializeLib(image, systab);
name[0] = 0;
vendor = NullGuid;
Print(L"GUID Variable Name Value\n");
Print(L"=================================== ==================== ========\n");
StrCpy(fmt, L"%.-35g %.-20s %s\n");
while (1) {
size = sizeof(name);
status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, name, &vendor);
if (status != EFI_SUCCESS)
break;
val = LibGetVariable(name, &vendor);
Print(fmt, &vendor, name, val);
FreePool(val);
}
return EFI_SUCCESS;
}

136
gnu-efi/apps/route80h.c Normal file
View File

@ -0,0 +1,136 @@
#include <efi.h>
#include <efilib.h>
/* this example program changes the Reserved Page Route (RPR) bit on ICH10's General
* Control And Status Register (GCS) from LPC to PCI. In practical terms, it routes
* outb to port 80h to the PCI bus. */
#define GCS_OFFSET_ADDR 0x3410
#define GCS_RPR_SHIFT 2
#define GCS_RPR_PCI 1
#define GCS_RPR_LPC 0
#define VENDOR_ID_INTEL 0x8086
#define DEVICE_ID_LPCIF 0x3a16
#define DEVICE_ID_COUGARPOINT_LPCIF 0x1c56
static EFI_HANDLE ImageHandle;
typedef struct {
uint16_t vendor_id; /* 00-01 */
uint16_t device_id; /* 02-03 */
char pad[0xEB]; /* 04-EF */
uint32_t rcba; /* F0-F3 */
uint32_t reserved[3]; /* F4-FF */
} lpcif_t;
static inline void set_bit(volatile uint32_t *flag, int bit, int value)
{
uint32_t val = *flag;
Print(L"current value is 0x%2x\n", val);
if (value) {
val |= (1 << bit);
} else {
val &= ~(1 << bit);
}
Print(L"setting value to 0x%2x\n", val);
*flag = val;
val = *flag;
Print(L"new value is 0x%2x\n", val);
}
static int is_device(EFI_PCI_IO *pciio, uint16_t vendor_id, uint16_t device_id)
{
lpcif_t lpcif;
EFI_STATUS rc;
rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint16, 0, 2, &lpcif);
if (EFI_ERROR(rc))
return 0;
if (vendor_id == lpcif.vendor_id && device_id == lpcif.device_id)
return 1;
return 0;
}
static EFI_STATUS find_pci_device(uint16_t vendor_id, uint16_t device_id,
EFI_PCI_IO **pciio)
{
EFI_STATUS rc;
EFI_HANDLE *Handles;
UINTN NoHandles, i;
if (!pciio)
return EFI_INVALID_PARAMETER;
rc = LibLocateHandle(ByProtocol, &PciIoProtocol, NULL, &NoHandles,
&Handles);
if (EFI_ERROR(rc))
return rc;
for (i = 0; i < NoHandles; i++) {
void *pciio_tmp = NULL;
rc = uefi_call_wrapper(BS->OpenProtocol, 6, Handles[i],
&PciIoProtocol, &pciio_tmp, ImageHandle,
NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(rc))
continue;
*pciio = pciio_tmp;
if (!is_device(*pciio, vendor_id, device_id)) {
*pciio = NULL;
continue;
}
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
InitializeLib(image_handle, systab);
EFI_PCI_IO *pciio = NULL;
lpcif_t lpcif;
EFI_STATUS rc = EFI_SUCCESS;
struct {
uint16_t vendor;
uint16_t device;
} devices[] = {
{ VENDOR_ID_INTEL, DEVICE_ID_LPCIF },
{ VENDOR_ID_INTEL, DEVICE_ID_COUGARPOINT_LPCIF },
{ 0, 0 }
};
int i;
ImageHandle = image_handle;
for (i = 0; devices[i].vendor != 0; i++) {
rc = find_pci_device(devices[i].vendor, devices[i].device, &pciio);
if (EFI_ERROR(rc))
continue;
}
if (rc == EFI_NOT_FOUND) {
Print(L"Device not found.\n");
return rc;
} else if (EFI_ERROR(rc)) {
return rc;
}
rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint32,
EFI_FIELD_OFFSET(lpcif_t, rcba), 1, &lpcif.rcba);
if (EFI_ERROR(rc))
return rc;
if (!(lpcif.rcba & 1)) {
Print(L"rcrb is not mapped, cannot route port 80h\n");
return EFI_UNSUPPORTED;
}
lpcif.rcba &= ~1UL;
Print(L"rcba: 0x%8x\n", lpcif.rcba, lpcif.rcba);
set_bit((uint32_t *)(intptr_t)(lpcif.rcba + GCS_OFFSET_ADDR),
GCS_RPR_SHIFT, GCS_RPR_PCI);
return EFI_SUCCESS;
}

37
gnu-efi/apps/setdbg.c Normal file
View File

@ -0,0 +1,37 @@
#include <efi.h>
#include <efilib.h>
EFI_GUID GRUB_EFI_GRUB_VARIABLE_GUID = {0x91376aff,0xcba6,0x42be,{0x94,0x9d,0x06,0xfd,0xe8,0x11,0x28,0xe8}};
EFI_GUID SHIM_GUID = {0x605dab50,0xe046,0x4300,{0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23}};
char grubenv[] = "# GRUB Environment Block\n\
debug=tcp,http,net\n\
####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################";
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS status;
InitializeLib(image, systab);
#if 0
UINT8 data = 1;
status = RT->SetVariable(L"SHIM_DEBUG", &SHIM_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(data), &data);
if (EFI_ERROR(status))
Print(L"SetVariable failed: %r\n", status);
#endif
status = RT->SetVariable(L"GRUB_ENV", &SHIM_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(grubenv)-1, grubenv);
if (EFI_ERROR(status))
Print(L"SetVariable(GRUB_ENV) failed: %r\n", status);
return EFI_SUCCESS;
}

31
gnu-efi/apps/setjmp.c Normal file
View File

@ -0,0 +1,31 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main(
EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *systab
)
{
jmp_buf env;
int rc;
InitializeLib(image_handle, systab);
rc = setjmp(&env);
Print(L"setjmp() = %d\n", rc);
if (rc == 3) {
Print(L"3 worked\n");
longjmp(&env, 0);
return 0;
}
if (rc == 1) {
Print(L"0 got to be one yay\n");
return 0;
}
longjmp(&env, 3);
return 0;
}

27
gnu-efi/apps/t.c Normal file
View File

@ -0,0 +1,27 @@
#include <efi.h>
#include <efilib.h>
static CHAR16 *
a2u (char *str)
{
static CHAR16 mem[2048];
int i;
for (i = 0; str[i]; ++i)
mem[i] = (CHAR16) str[i];
mem[i] = 0;
return mem;
}
EFI_STATUS
efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
{
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
InitializeLib(image_handle, systab);
conout = systab->ConOut;
uefi_call_wrapper(conout->OutputString, 2, conout, (CHAR16 *)L"Hello World!\n\r");
uefi_call_wrapper(conout->OutputString, 2, conout, a2u("Hello World!\n\r"));
return EFI_SUCCESS;
}

14
gnu-efi/apps/t2.c Normal file
View File

@ -0,0 +1,14 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
InitializeLib(image, systab);
conout = systab->ConOut;
uefi_call_wrapper(conout->OutputString, 2, conout, L"Hello World!\n\r");
return EFI_SUCCESS;
}

95
gnu-efi/apps/t3.c Normal file
View File

@ -0,0 +1,95 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main(
EFI_HANDLE image_handle,
EFI_SYSTEM_TABLE *systab
)
{
EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
EFI_STATUS efi_status;
EFI_LOADED_IMAGE *li;
UINTN pat = PoolAllocationType;
VOID *void_li_p;
InitializeLib(image_handle, systab);
PoolAllocationType = 2; /* klooj */
Print(L"Hello World! (0xd=0x%x, 13=%d)\n", 13, 13);
Print(L"before InitializeLib(): PoolAllocationType=%d\n",
pat);
Print(L" after InitializeLib(): PoolAllocationType=%d\n",
PoolAllocationType);
/*
* Locate loaded_image_handle instance.
*/
Print(L"BS->HandleProtocol() ");
efi_status = uefi_call_wrapper(
BS->HandleProtocol,
3,
image_handle,
&loaded_image_protocol,
&void_li_p);
li = void_li_p;
Print(L"%xh (%r)\n", efi_status, efi_status);
if (efi_status != EFI_SUCCESS) {
return efi_status;
}
Print(L" li: %xh\n", li);
if (!li) {
return EFI_UNSUPPORTED;
}
Print(L" li->Revision: %xh\n", li->Revision);
Print(L" li->ParentHandle: %xh\n", li->ParentHandle);
Print(L" li->SystemTable: %xh\n", li->SystemTable);
Print(L" li->DeviceHandle: %xh\n", li->DeviceHandle);
Print(L" li->FilePath: %xh\n", li->FilePath);
Print(L" li->Reserved: %xh\n", li->Reserved);
Print(L" li->LoadOptionsSize: %xh\n", li->LoadOptionsSize);
Print(L" li->LoadOptions: %xh\n", li->LoadOptions);
Print(L" li->ImageBase: %xh\n", li->ImageBase);
Print(L" li->ImageSize: %xh\n", li->ImageSize);
Print(L" li->ImageCodeType: %xh\n", li->ImageCodeType);
Print(L" li->ImageDataType: %xh\n", li->ImageDataType);
Print(L" li->Unload: %xh\n", li->Unload);
#if 0
typedef struct {
UINT32 Revision;
EFI_HANDLE ParentHandle;
struct _EFI_SYSTEM_TABLE *SystemTable;
// Source location of image
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH *FilePath;
VOID *Reserved;
// Images load options
UINT32 LoadOptionsSize;
VOID *LoadOptions;
// Location of where image was loaded
VOID *ImageBase;
UINT64 ImageSize;
EFI_MEMORY_TYPE ImageCodeType;
EFI_MEMORY_TYPE ImageDataType;
// If the driver image supports a dynamic unload request
EFI_IMAGE_UNLOAD Unload;
} EFI_LOADED_IMAGE;
#endif
return EFI_SUCCESS;
}

14
gnu-efi/apps/t4.c Normal file
View File

@ -0,0 +1,14 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE *image, EFI_SYSTEM_TABLE *systab)
{
UINTN index;
InitializeLib(image, systab);
uefi_call_wrapper(systab->ConOut->OutputString, 2, systab->ConOut, L"Hello application started\r\n");
uefi_call_wrapper(systab->ConOut->OutputString, 2, systab->ConOut, L"\r\n\r\n\r\nHit any key to exit\r\n");
uefi_call_wrapper(systab->BootServices->WaitForEvent, 3, 1, &systab->ConIn->WaitForKey, &index);
return EFI_SUCCESS;
}

13
gnu-efi/apps/t5.c Normal file
View File

@ -0,0 +1,13 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
InitializeLib(image, systab);
Print(L"HelloLib application started\n");
Print(L"\n\n\nHit any key to exit this image\n");
WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"\n\n");
return EFI_SUCCESS;
}

43
gnu-efi/apps/t6.c Normal file
View File

@ -0,0 +1,43 @@
#include <efi.h>
#include <efilib.h>
typedef EFI_STATUS (*foo_t)(EFI_HANDLE, EFI_GUID *, VOID **);
typedef struct {
unsigned long addr;
unsigned long gp;
} fdesc_t;
EFI_LOADED_IMAGE my_loaded;
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_LOADED_IMAGE *loaded_image = NULL;
#if 0
EFI_DEVICE_PATH *dev_path;
#endif
EFI_STATUS status;
InitializeLib(image, systab);
status = uefi_call_wrapper(systab->BootServices->HandleProtocol,
3,
image,
&LoadedImageProtocol,
(void **) &loaded_image);
if (EFI_ERROR(status)) {
Print(L"handleprotocol: %r\n", status);
}
#if 0
BS->HandleProtocol(loaded_image->DeviceHandle, &DevicePathProtocol, (void **) &dev_path);
Print(L"Image device : %s\n", DevicePathToStr(dev_path));
Print(L"Image file : %s\n", DevicePathToStr(loaded_image->FilePath));
#endif
Print(L"Image base : %lx\n", loaded_image->ImageBase);
Print(L"Image size : %lx\n", loaded_image->ImageSize);
Print(L"Load options size : %lx\n", loaded_image->LoadOptionsSize);
Print(L"Load options : %s\n", loaded_image->LoadOptions);
return EFI_SUCCESS;
}

25
gnu-efi/apps/t7.c Normal file
View File

@ -0,0 +1,25 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_INPUT_KEY efi_input_key;
EFI_STATUS efi_status;
InitializeLib(image, systab);
Print(L"HelloLib application started\n");
Print(L"\n\n\nHit any key to exit this image\n");
WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"\n\n");
efi_status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &efi_input_key);
Print(L"ScanCode: %xh UnicodeChar: %xh CallRtStatus: %x\n",
efi_input_key.ScanCode, efi_input_key.UnicodeChar, efi_status);
return EFI_SUCCESS;
}

19
gnu-efi/apps/t8.c Normal file
View File

@ -0,0 +1,19 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
INTN Argc, i;
CHAR16 **Argv;
InitializeLib(ImageHandle, SystemTable);
Argc = GetShellArgcArgv(ImageHandle, &Argv);
Print(L"Hello World, started with Argc=%d\n", Argc);
for (i = 0 ; i < Argc ; ++i)
Print(L" Argv[%d] = '%s'\n", i, Argv[i]);
Print(L"Bye.\n");
return EFI_SUCCESS;
}

431
gnu-efi/apps/tcc.c Normal file
View File

@ -0,0 +1,431 @@
/*
* Test if our calling convention gymnastics actually work
*/
#include <efi.h>
#include <efilib.h>
#if 0
extern void dump_stack(void);
asm( ".globl dump_stack\n"
"dump_stack:\n"
" movq %rsp, %rdi\n"
" jmp *dump_stack_helper@GOTPCREL(%rip)\n"
".size dump_stack, .-dump_stack");
void dump_stack_helper(uint64_t rsp_val)
{
uint64_t *rsp = (uint64_t *)rsp_val;
int x;
Print(L"%%rsp: 0x%08x%08x stack:\r\n",
(rsp_val & 0xffffffff00000000) >>32,
rsp_val & 0xffffffff);
for (x = 0; x < 8; x++) {
Print(L"%08x: ", ((uint64_t)rsp) & 0xffffffff);
Print(L"%016x ", *rsp++);
Print(L"%016x ", *rsp++);
Print(L"%016x ", *rsp++);
Print(L"%016x\r\n", *rsp++);
}
}
#endif
EFI_STATUS EFI_FUNCTION test_failure_callback(void)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS test_failure(void)
{
return uefi_call_wrapper(test_failure_callback, 0);
}
EFI_STATUS EFI_FUNCTION test_call0_callback(void)
{
return EFI_SUCCESS;
}
EFI_STATUS test_call0(void)
{
return uefi_call_wrapper(test_call0_callback, 0);
}
EFI_STATUS EFI_FUNCTION test_call1_callback(UINT32 a)
{
if (a != 0x12345678) {
return EFI_LOAD_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS test_call1(void)
{
return uefi_call_wrapper(test_call1_callback, 1,0x12345678);
}
EFI_STATUS EFI_FUNCTION test_call2_callback(UINT32 a, UINT32 b)
{
if (a != 0x12345678) {
return EFI_LOAD_ERROR;
}
if (b != 0x23456789) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS test_call2(void)
{
return uefi_call_wrapper(test_call2_callback, 2,
0x12345678, 0x23456789);
}
EFI_STATUS EFI_FUNCTION test_call3_callback(UINT32 a, UINT32 b,
UINT32 c)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
return EFI_SUCCESS;
}
EFI_STATUS test_call3(void)
{
return uefi_call_wrapper(test_call3_callback, 3,
0x12345678, 0x23456789, 0x3456789a);
}
EFI_STATUS EFI_FUNCTION test_call4_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
return EFI_SUCCESS;
}
EFI_STATUS test_call4(void)
{
return uefi_call_wrapper(test_call4_callback, 4,
0x12345678, 0x23456789, 0x3456789a, 0x456789ab);
}
EFI_STATUS EFI_FUNCTION test_call5_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
return EFI_SUCCESS;
}
EFI_STATUS test_call5(void)
{
return uefi_call_wrapper(test_call5_callback, 5,
0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc);
}
EFI_STATUS EFI_FUNCTION test_call6_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e, UINT32 f)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
if (f != 0x6789abcd)
return EFI_NOT_READY;
return EFI_SUCCESS;
}
EFI_STATUS test_call6(void)
{
return uefi_call_wrapper(test_call6_callback, 6,
0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
0x6789abcd);
}
EFI_STATUS EFI_FUNCTION test_call7_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
if (f != 0x6789abcd)
return EFI_NOT_READY;
if (g != 0x789abcde)
return EFI_DEVICE_ERROR;
return EFI_SUCCESS;
}
EFI_STATUS test_call7(void)
{
return uefi_call_wrapper(test_call7_callback, 7,
0x12345678, 0x23456789, 0x3456789a, 0x456789ab,
0x56789abc, 0x6789abcd, 0x789abcde);
}
EFI_STATUS EFI_FUNCTION test_call8_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
if (f != 0x6789abcd)
return EFI_NOT_READY;
if (g != 0x789abcde)
return EFI_DEVICE_ERROR;
if (h != 0x89abcdef)
return EFI_WRITE_PROTECTED;
return EFI_SUCCESS;
}
EFI_STATUS test_call8(void)
{
return uefi_call_wrapper(test_call8_callback, 8,
0x12345678,
0x23456789,
0x3456789a,
0x456789ab,
0x56789abc,
0x6789abcd,
0x789abcde,
0x89abcdef);
}
EFI_STATUS EFI_FUNCTION test_call9_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
if (f != 0x6789abcd)
return EFI_NOT_READY;
if (g != 0x789abcde)
return EFI_DEVICE_ERROR;
if (h != 0x89abcdef)
return EFI_WRITE_PROTECTED;
if (i != 0x9abcdef0)
return EFI_OUT_OF_RESOURCES;
return EFI_SUCCESS;
}
EFI_STATUS test_call9(void)
{
return uefi_call_wrapper(test_call9_callback, 9,
0x12345678,
0x23456789,
0x3456789a,
0x456789ab,
0x56789abc,
0x6789abcd,
0x789abcde,
0x89abcdef,
0x9abcdef0);
}
extern EFI_STATUS test_call10(void);
EFI_STATUS EFI_FUNCTION test_call10_callback(UINT32 a, UINT32 b,
UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i,
UINT32 j)
{
if (a != 0x12345678)
return EFI_LOAD_ERROR;
if (b != 0x23456789)
return EFI_INVALID_PARAMETER;
if (c != 0x3456789a)
return EFI_UNSUPPORTED;
if (d != 0x456789ab)
return EFI_BAD_BUFFER_SIZE;
if (e != 0x56789abc)
return EFI_BUFFER_TOO_SMALL;
if (f != 0x6789abcd)
return EFI_NOT_READY;
if (g != 0x789abcde)
return EFI_DEVICE_ERROR;
if (h != 0x89abcdef)
return EFI_WRITE_PROTECTED;
if (i != 0x9abcdef0)
return EFI_OUT_OF_RESOURCES;
if (j != 0xabcdef01)
return EFI_VOLUME_CORRUPTED;
return EFI_SUCCESS;
}
EFI_STATUS test_call10(void)
{
return uefi_call_wrapper(test_call10_callback, 10,
0x12345678,
0x23456789,
0x3456789a,
0x456789ab,
0x56789abc,
0x6789abcd,
0x789abcde,
0x89abcdef,
0x9abcdef0,
0xabcdef01);
}
EFI_STATUS
efi_main (EFI_HANDLE *image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS rc = EFI_SUCCESS;
InitializeLib(image, systab);
PoolAllocationType = 2; /* klooj */
#ifdef __x86_64__
__asm__ volatile("out %0,%1" : : "a" ((uint8_t)0x14), "dN" (0x80));
#endif
Print(L"Hello\r\n");
rc = test_failure();
if (EFI_ERROR(rc)) {
Print(L"Returning Failure works\n");
} else {
Print(L"Returning failure doesn't work.\r\n");
Print(L"%%rax was 0x%016x, should have been 0x%016x\n",
rc, EFI_UNSUPPORTED);
return EFI_INVALID_PARAMETER;
}
rc = test_call0();
if (!EFI_ERROR(rc)) {
Print(L"0 args works just fine here.\r\n");
} else {
Print(L"0 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call1();
if (!EFI_ERROR(rc)) {
Print(L"1 arg works just fine here.\r\n");
} else {
Print(L"1 arg failed: 0x%016x\n", rc);
return rc;
}
rc = test_call2();
if (!EFI_ERROR(rc)) {
Print(L"2 args works just fine here.\r\n");
} else {
Print(L"2 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call3();
if (!EFI_ERROR(rc)) {
Print(L"3 args works just fine here.\r\n");
} else {
Print(L"3 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call4();
if (!EFI_ERROR(rc)) {
Print(L"4 args works just fine here.\r\n");
} else {
Print(L"4 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call5();
if (!EFI_ERROR(rc)) {
Print(L"5 args works just fine here.\r\n");
} else {
Print(L"5 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call6();
if (!EFI_ERROR(rc)) {
Print(L"6 args works just fine here.\r\n");
} else {
Print(L"6 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call7();
if (!EFI_ERROR(rc)) {
Print(L"7 args works just fine here.\r\n");
} else {
Print(L"7 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call8();
if (!EFI_ERROR(rc)) {
Print(L"8 args works just fine here.\r\n");
} else {
Print(L"8 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call9();
if (!EFI_ERROR(rc)) {
Print(L"9 args works just fine here.\r\n");
} else {
Print(L"9 args failed: 0x%016x\n", rc);
return rc;
}
rc = test_call10();
if (!EFI_ERROR(rc)) {
Print(L"10 args works just fine here.\r\n");
} else {
Print(L"10 args failed: 0x%016x\n", rc);
return rc;
}
return rc;
}

9
gnu-efi/apps/tpause.c Normal file
View File

@ -0,0 +1,9 @@
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
Print(L"Press `q' to quit, any other key to continue:\n");
}

43
gnu-efi/apps/trivial.S Normal file
View File

@ -0,0 +1,43 @@
.text
.align 4
.globl _start
_start:
#if 0
pushl %ebp
movl %esp,%ebp
pushl %ebx # save ebx
movl 12(%ebp),%eax # eax <- systab
movl 24(%eax),%ebx # ebx <- systab->FirmwareVendor
pushl %ebx
movl 44(%eax),%ebx # ebx <- systab->ConOut
pushl %ebx
movl 4(%ebx),%eax # eax <- conout->OutputString
call *%eax
movl -4(%ebp),%ebx # restore ebx
leave
ret
#else
pushl %ebp
movl %esp,%ebp
pushl %ebx
call 0f
0: popl %eax
addl $hello-0b,%eax
pushl %eax
movl 12(%ebp),%eax # eax <- systab
movl 44(%eax),%ebx # ebx <- systab->ConOut
pushl %ebx
movl 4(%ebx),%eax # eax <- conout->OutputString
call *%eax
movl -4(%ebp),%ebx
leave
ret
.section .rodata
.align 2
hello: .byte 'h',0,'e',0,'l',0,'l',0,'o',0,'\n',0,'\r',0,0,0
#endif

37
gnu-efi/apps/unsetdbg.c Normal file
View File

@ -0,0 +1,37 @@
#include <efi.h>
#include <efilib.h>
EFI_GUID GRUB_EFI_GRUB_VARIABLE_GUID = {0x91376aff,0xcba6,0x42be,{0x94,0x9d,0x06,0xfd,0xe8,0x11,0x28,0xe8}};
EFI_GUID SHIM_GUID = {0x605dab50,0xe046,0x4300,{0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23}};
char grubenv[] = "# GRUB Environment Block\n\
debug=all\n\
#############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################";
EFI_STATUS
efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS status;
UINT8 data = 1;
InitializeLib(image, systab);
status = RT->SetVariable(L"SHIM_DEBUG", &SHIM_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
0, &data);
if (EFI_ERROR(status))
Print(L"SetVariable failed: %r\n", status);
#if 0
status = RT->SetVariable(L"GRUB_ENV", &SHIM_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(grubenv)-1, grubenv);
if (EFI_ERROR(status))
Print(L"SetVariable(GRUB_ENV) failed: %r\n", status);
#endif
return EFI_SUCCESS;
}

75
gnu-efi/gnuefi/Makefile Normal file
View File

@ -0,0 +1,75 @@
#
# Copyright (C) 1999-2001 Hewlett-Packard Co.
# Contributed by David Mosberger <davidm@hpl.hp.com>
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANYDIRECT, 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.
#
SRCDIR = .
VPATH = $(SRCDIR)
include $(SRCDIR)/../Make.defaults
TOPDIR = $(SRCDIR)/..
CDIR=$(TOPDIR)/..
FILES = reloc_$(ARCH)
OBJS = $(FILES:%=%.o)
# on aarch64, avoid jump tables before all relocations have been processed
reloc_aarch64.o: CFLAGS += -fno-jump-tables
TARGETS = crt0-efi-$(ARCH).o libgnuefi.a
all: $(TARGETS)
libgnuefi.a: $(patsubst %,libgnuefi.a(%),$(OBJS))
clean:
rm -f $(TARGETS) *~ *.o $(OBJS)
install:
mkdir -p $(INSTALLROOT)$(LIBDIR)
$(INSTALL) -m 644 $(TARGETS) $(INSTALLROOT)$(LIBDIR)
ifneq (,$(findstring FreeBSD,$(OS)))
ifeq ($(ARCH),x86_64)
$(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_fbsd_efi.lds $(INSTALLROOT)$(LIBDIR)
else
$(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR)
endif
else
$(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR)
endif
include $(SRCDIR)/../Make.rules

View File

@ -0,0 +1,130 @@
/*
* crt0-efi-aarch64.S - PE/COFF header for AArch64 EFI applications
*
* Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
*
* 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 and this list of conditions, without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any later version.
*/
.section .text.head
/*
* Magic "MZ" signature for PE/COFF
*/
.globl ImageBase
ImageBase:
.ascii "MZ"
.skip 58 // 'MZ' + pad + offset == 64
.long pe_header - ImageBase // Offset to the PE header.
pe_header:
.ascii "PE"
.short 0
coff_header:
.short 0xaa64 // AArch64
.short 2 // nr_sections
.long 0 // TimeDateStamp
.long 0 // PointerToSymbolTable
.long 1 // NumberOfSymbols
.short section_table - optional_header // SizeOfOptionalHeader
.short 0x206 // Characteristics.
// IMAGE_FILE_DEBUG_STRIPPED |
// IMAGE_FILE_EXECUTABLE_IMAGE |
// IMAGE_FILE_LINE_NUMS_STRIPPED
optional_header:
.short 0x20b // PE32+ format
.byte 0x02 // MajorLinkerVersion
.byte 0x14 // MinorLinkerVersion
.long _data - _start // SizeOfCode
.long _data_size // SizeOfInitializedData
.long 0 // SizeOfUninitializedData
.long _start - ImageBase // AddressOfEntryPoint
.long _start - ImageBase // BaseOfCode
extra_header_fields:
.quad 0 // ImageBase
.long 0x1000 // SectionAlignment
.long 0x200 // FileAlignment
.short 0 // MajorOperatingSystemVersion
.short 0 // MinorOperatingSystemVersion
.short 0 // MajorImageVersion
.short 0 // MinorImageVersion
.short 0 // MajorSubsystemVersion
.short 0 // MinorSubsystemVersion
.long 0 // Win32VersionValue
.long _edata - ImageBase // SizeOfImage
// Everything before the kernel image is considered part of the header
.long _start - ImageBase // SizeOfHeaders
.long 0 // CheckSum
.short EFI_SUBSYSTEM // Subsystem
.short 0 // DllCharacteristics
.quad 0 // SizeOfStackReserve
.quad 0 // SizeOfStackCommit
.quad 0 // SizeOfHeapReserve
.quad 0 // SizeOfHeapCommit
.long 0 // LoaderFlags
.long 0x6 // NumberOfRvaAndSizes
.quad 0 // ExportTable
.quad 0 // ImportTable
.quad 0 // ResourceTable
.quad 0 // ExceptionTable
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
// Section table
section_table:
.ascii ".text\0\0\0"
.long _data - _start // VirtualSize
.long _start - ImageBase // VirtualAddress
.long _data - _start // SizeOfRawData
.long _start - ImageBase // PointerToRawData
.long 0 // PointerToRelocations (0 for executables)
.long 0 // PointerToLineNumbers (0 for executables)
.short 0 // NumberOfRelocations (0 for executables)
.short 0 // NumberOfLineNumbers (0 for executables)
.long 0x60000020 // Characteristics (section flags)
.ascii ".data\0\0\0"
.long _data_size // VirtualSize
.long _data - ImageBase // VirtualAddress
.long _data_size // SizeOfRawData
.long _data - ImageBase // PointerToRawData
.long 0 // PointerToRelocations (0 for executables)
.long 0 // PointerToLineNumbers (0 for executables)
.short 0 // NumberOfRelocations (0 for executables)
.short 0 // NumberOfLineNumbers (0 for executables)
.long 0xc0000040 // Characteristics (section flags)
.align 12
_start:
stp x29, x30, [sp, #-32]!
mov x29, sp
stp x0, x1, [sp, #16]
mov x2, x0
mov x3, x1
adr x0, ImageBase
adrp x1, _DYNAMIC
add x1, x1, #:lo12:_DYNAMIC
bl _relocate
cbnz x0, 0f
ldp x0, x1, [sp, #16]
bl efi_main
0: ldp x29, x30, [sp], #32
ret

View File

@ -0,0 +1,145 @@
/*
* crt0-efi-arm.S - PE/COFF header for ARM EFI applications
*
* Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
*
* 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 and this list of conditions, without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any later version.
*/
.section .text.head
/*
* Magic "MZ" signature for PE/COFF
*/
.globl ImageBase
ImageBase:
.ascii "MZ"
.skip 58 // 'MZ' + pad + offset == 64
.long pe_header - ImageBase // Offset to the PE header.
pe_header:
.ascii "PE"
.short 0
coff_header:
.short 0x1c2 // Mixed ARM/Thumb
.short 2 // nr_sections
.long 0 // TimeDateStamp
.long 0 // PointerToSymbolTable
.long 1 // NumberOfSymbols
.short section_table - optional_header // SizeOfOptionalHeader
.short 0x306 // Characteristics.
// IMAGE_FILE_32BIT_MACHINE |
// IMAGE_FILE_DEBUG_STRIPPED |
// IMAGE_FILE_EXECUTABLE_IMAGE |
// IMAGE_FILE_LINE_NUMS_STRIPPED
optional_header:
.short 0x10b // PE32+ format
.byte 0x02 // MajorLinkerVersion
.byte 0x14 // MinorLinkerVersion
.long _edata - _start // SizeOfCode
.long 0 // SizeOfInitializedData
.long 0 // SizeOfUninitializedData
.long _start - ImageBase // AddressOfEntryPoint
.long _start - ImageBase // BaseOfCode
.long 0 // BaseOfData
extra_header_fields:
.long 0 // ImageBase
.long 0x20 // SectionAlignment
.long 0x8 // FileAlignment
.short 0 // MajorOperatingSystemVersion
.short 0 // MinorOperatingSystemVersion
.short 0 // MajorImageVersion
.short 0 // MinorImageVersion
.short 0 // MajorSubsystemVersion
.short 0 // MinorSubsystemVersion
.long 0 // Win32VersionValue
.long _edata - ImageBase // SizeOfImage
// Everything before the kernel image is considered part of the header
.long _start - ImageBase // SizeOfHeaders
.long 0 // CheckSum
.short EFI_SUBSYSTEM // Subsystem
.short 0 // DllCharacteristics
.long 0 // SizeOfStackReserve
.long 0 // SizeOfStackCommit
.long 0 // SizeOfHeapReserve
.long 0 // SizeOfHeapCommit
.long 0 // LoaderFlags
.long 0x6 // NumberOfRvaAndSizes
.quad 0 // ExportTable
.quad 0 // ImportTable
.quad 0 // ResourceTable
.quad 0 // ExceptionTable
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
// Section table
section_table:
/*
* The EFI application loader requires a relocation section
* because EFI applications must be relocatable. This is a
* dummy section as far as we are concerned.
*/
.ascii ".reloc"
.byte 0
.byte 0 // end of 0 padding of section name
.long 0
.long 0
.long 0 // SizeOfRawData
.long 0 // PointerToRawData
.long 0 // PointerToRelocations
.long 0 // PointerToLineNumbers
.short 0 // NumberOfRelocations
.short 0 // NumberOfLineNumbers
.long 0x42100040 // Characteristics (section flags)
.ascii ".text"
.byte 0
.byte 0
.byte 0 // end of 0 padding of section name
.long _edata - _start // VirtualSize
.long _start - ImageBase // VirtualAddress
.long _edata - _start // SizeOfRawData
.long _start - ImageBase // PointerToRawData
.long 0 // PointerToRelocations (0 for executables)
.long 0 // PointerToLineNumbers (0 for executables)
.short 0 // NumberOfRelocations (0 for executables)
.short 0 // NumberOfLineNumbers (0 for executables)
.long 0xe0500020 // Characteristics (section flags)
_start:
stmfd sp!, {r0-r2, lr}
mov r2, r0
mov r3, r1
adr r1, .L_DYNAMIC
ldr r0, [r1]
add r1, r0, r1
adr r0, ImageBase
bl _relocate
teq r0, #0
bne 0f
ldmfd sp, {r0-r1}
bl efi_main
0: add sp, sp, #12
ldr pc, [sp], #4
.L_DYNAMIC:
.word _DYNAMIC - .

View File

@ -0,0 +1,76 @@
/* crt0-efi-ia32.S - x86 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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.
*/
.text
.align 4
.globl _start
_start:
pushl %ebp
movl %esp,%ebp
pushl 12(%ebp) # copy "image" argument
pushl 8(%ebp) # copy "systab" argument
call 0f
0: popl %eax
movl %eax,%ebx
addl $ImageBase-0b,%eax # %eax = ldbase
addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
pushl %ebx # pass _DYNAMIC as second argument
pushl %eax # pass ldbase as first argument
call _relocate
popl %ebx
popl %ebx
testl %eax,%eax
jne .exit
call efi_main # call app with "image" and "systab" argument
.exit: leave
ret
// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
.data
dummy: .long 0
#define IMAGE_REL_ABSOLUTE 0
.section .reloc
.long dummy // Page RVA
.long 10 // Block Size (2*4+2)
.word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy

View File

@ -0,0 +1,87 @@
/* crt0-efi-ia64.S - IA-64 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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.
*/
.text
.psr abi64
.psr lsb
.lsb
.proc _start
_start:
alloc loc0=ar.pfs,2,2,2,0
mov loc1=rp
movl out0=@gprel(ImageBase) // out0 <- ImageBase (ldbase)
;;
add out0=out0,gp
movl out1=@gprel(_DYNAMIC) // out1 <- _DYNAMIC
;; // avoid WAW on CFM
add out1=out1,gp
br.call.sptk.few rp=_relocate
.Lret0:
cmp.ne p6,p0=r0,r8 // r8 == EFI_SUCCESS?
(p6) br.cond.sptk.few .exit // no ->
.Lret1:
mov out0=in0 // image handle
mov out1=in1 // systab
br.call.sptk.few rp=efi_main
.Lret2:
.exit:
mov ar.pfs=loc0
mov rp=loc1
;;
br.ret.sptk.few rp
.endp _start
// PE32+ wants a PLABEL, not the code address of the entry point:
.align 16
.global _start_plabel
.section .plabel, "a"
_start_plabel:
data8 _start
data8 __gp
// hand-craft a .reloc section for the plabel:
#define IMAGE_REL_BASED_DIR64 10
.section .reloc, "a"
data4 _start_plabel // Page RVA
data4 12 // Block Size (2*4+2*2)
data2 (IMAGE_REL_BASED_DIR64<<12) + 0 // reloc for plabel's entry point
data2 (IMAGE_REL_BASED_DIR64<<12) + 8 // reloc for plabel's global pointer

View File

@ -0,0 +1,188 @@
/*
* crt0-efi-mips64el.S - PE/COFF header for MIPS64 EFI applications
*
* Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
* Copright (C) 2017 Heiher <r@hev.cc>
*
* 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 and this list of conditions, without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any later version.
*/
.section .text.head
/*
* Magic "MZ" signature for PE/COFF
*/
.globl ImageBase
ImageBase:
.ascii "MZ"
.skip 58 // 'MZ' + pad + offset == 64
.long pe_header - ImageBase // Offset to the PE header.
pe_header:
.ascii "PE"
.short 0
coff_header:
.short 0x166 // MIPS little endian
.short 2 // nr_sections
.long 0 // TimeDateStamp
.long 0 // PointerToSymbolTable
.long 1 // NumberOfSymbols
.short section_table - optional_header // SizeOfOptionalHeader
.short 0x206 // Characteristics.
// IMAGE_FILE_DEBUG_STRIPPED |
// IMAGE_FILE_EXECUTABLE_IMAGE |
// IMAGE_FILE_LINE_NUMS_STRIPPED
optional_header:
.short 0x20b // PE32+ format
.byte 0x02 // MajorLinkerVersion
.byte 0x14 // MinorLinkerVersion
.long _edata - _start // SizeOfCode
.long 0 // SizeOfInitializedData
.long 0 // SizeOfUninitializedData
.long _start - ImageBase // AddressOfEntryPoint
.long _start - ImageBase // BaseOfCode
extra_header_fields:
.quad 0 // ImageBase
.long 0x20 // SectionAlignment
.long 0x8 // FileAlignment
.short 0 // MajorOperatingSystemVersion
.short 0 // MinorOperatingSystemVersion
.short 0 // MajorImageVersion
.short 0 // MinorImageVersion
.short 0 // MajorSubsystemVersion
.short 0 // MinorSubsystemVersion
.long 0 // Win32VersionValue
.long _edata - ImageBase // SizeOfImage
// Everything before the kernel image is considered part of the header
.long _start - ImageBase // SizeOfHeaders
.long 0 // CheckSum
.short EFI_SUBSYSTEM // Subsystem
.short 0 // DllCharacteristics
.quad 0 // SizeOfStackReserve
.quad 0 // SizeOfStackCommit
.quad 0 // SizeOfHeapReserve
.quad 0 // SizeOfHeapCommit
.long 0 // LoaderFlags
.long 0x6 // NumberOfRvaAndSizes
.quad 0 // ExportTable
.quad 0 // ImportTable
.quad 0 // ResourceTable
.quad 0 // ExceptionTable
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
// Section table
section_table:
/*
* The EFI application loader requires a relocation section
* because EFI applications must be relocatable. This is a
* dummy section as far as we are concerned.
*/
.ascii ".reloc"
.byte 0
.byte 0 // end of 0 padding of section name
.long 0
.long 0
.long 0 // SizeOfRawData
.long 0 // PointerToRawData
.long 0 // PointerToRelocations
.long 0 // PointerToLineNumbers
.short 0 // NumberOfRelocations
.short 0 // NumberOfLineNumbers
.long 0x42100040 // Characteristics (section flags)
.ascii ".text"
.byte 0
.byte 0
.byte 0 // end of 0 padding of section name
.long _edata - _start // VirtualSize
.long _start - ImageBase // VirtualAddress
.long _edata - _start // SizeOfRawData
.long _start - ImageBase // PointerToRawData
.long 0 // PointerToRelocations (0 for executables)
.long 0 // PointerToLineNumbers (0 for executables)
.short 0 // NumberOfRelocations (0 for executables)
.short 0 // NumberOfLineNumbers (0 for executables)
.long 0xe0500020 // Characteristics (section flags)
.set push
.set noreorder
.align 4
.globl _start
.ent _start
.type _start, @function
_start:
daddiu $sp, -32
sd $ra, ($sp)
// Get pc & gp
.align 3
bal 1f
sd $gp, 8($sp)
_pc:
.dword _gp
.dword _DYNAMIC
.dword _relocate
1:
// pc in ra
ld $gp, ($ra)
dli $t0, _pc
dsubu $gp, $t0
daddu $gp, $ra
sd $a0, 16($sp)
sd $a1, 24($sp)
// a2: ImageHandle
move $a2, $a0
// a3: SystemTable
move $a3, $a1
// a0: ImageBase
dli $t1, ImageBase - _pc
daddu $a0, $ra, $t1
// a1: DynamicSection
ld $t1, 8($ra)
dsubu $t1, $t0
daddu $a1, $ra, $t1
// call _relocate
ld $t1, 16($ra)
dsubu $t1, $t0
daddu $t9, $ra, $t1
jalr $t9
nop
bnez $v0, 1b
nop
// a0: ImageHandle
ld $a0, 16($sp)
// call efi_main
dla $t9, efi_main
jalr $t9
// a1: SystemTable
ld $a1, 24($sp)
1:
ld $gp, 8($sp)
ld $ra, ($sp)
jr $ra
daddiu $sp, 32
.end _start
.set pop

View File

@ -0,0 +1,76 @@
/* crt0-efi-x86_64.S - x86_64 EFI startup code.
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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.
*/
.text
.align 4
.globl _start
_start:
subq $8, %rsp
pushq %rcx
pushq %rdx
0:
lea ImageBase(%rip), %rdi
lea _DYNAMIC(%rip), %rsi
popq %rcx
popq %rdx
pushq %rcx
pushq %rdx
call _relocate
popq %rdi
popq %rsi
call efi_main
addq $8, %rsp
.exit:
ret
// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
.data
dummy: .long 0
#define IMAGE_REL_ABSOLUTE 0
.section .reloc, "a"
label1:
.long dummy-label1 // Page RVA
.long 10 // Block Size (2*4+2)
.word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy

View File

@ -0,0 +1,63 @@
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(_start)
SECTIONS
{
.text 0x0 : {
_text = .;
*(.text.head)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.srodata)
*(.rodata*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
.dynamic : { *(.dynamic) }
.data : ALIGN(4096)
{
_data = .;
*(.sdata)
*(.data)
*(.data1)
*(.data.*)
*(.got.plt)
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
. = ALIGN(16);
_bss = .;
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
. = ALIGN(16);
_bss_end = .;
}
.rela.dyn : { *(.rela.dyn) }
.rela.plt : { *(.rela.plt) }
.rela.got : { *(.rela.got) }
.rela.data : { *(.rela.data) *(.rela.data*) }
. = ALIGN(512);
_edata = .;
_data_size = . - _data;
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.note.gnu.build-id : { *(.note.gnu.build-id) }
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@ -0,0 +1,63 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
.text 0x0 : {
_text = .;
*(.text.head)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.srodata)
*(.rodata*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
.dynamic : { *(.dynamic) }
.data :
{
_data = .;
*(.sdata)
*(.data)
*(.data1)
*(.data.*)
*(.got.plt)
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
. = ALIGN(16);
_bss = .;
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(16);
_bss_end = .;
}
.rel.dyn : { *(.rel.dyn) }
.rel.plt : { *(.rel.plt) }
.rel.got : { *(.rel.got) }
.rel.data : { *(.rel.data) *(.rel.data*) }
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.note.gnu.build-id : { *(.note.gnu.build-id) }
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@ -0,0 +1,86 @@
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0;
ImageBase = .;
/* .hash and/or .gnu.hash MUST come first! */
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
. = ALIGN(4096);
.text :
{
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
.sdata :
{
_data = .;
*(.got.plt)
*(.got)
*(.srodata)
*(.sdata)
*(.sbss)
*(.scommon)
}
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.data)
*(.data1)
*(.data.*)
*(.sdata)
*(.got.plt)
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
}
.note.gnu.build-id : { *(.note.gnu.build-id) }
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rel :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.got)
*(.rel.stab)
*(.data.rel.ro.local)
*(.data.rel.local)
*(.data.rel.ro)
*(.data.rel*)
}
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.reloc : /* This is the PECOFF .reloc section! */
{
*(.reloc)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@ -0,0 +1,86 @@
OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0;
ImageBase = .;
/* .hash and/or .gnu.hash MUST come first! */
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
. = ALIGN(4096);
.text :
{
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
.sdata :
{
_data = .;
*(.got.plt)
*(.got)
*(.srodata)
*(.sdata)
*(.sbss)
*(.scommon)
}
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.data)
*(.data1)
*(.data.*)
*(.sdata)
*(.got.plt)
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
}
.note.gnu.build-id : { *(.note.gnu.build-id) }
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rel :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.got)
*(.rel.stab)
*(.data.rel.ro.local)
*(.data.rel.local)
*(.data.rel.ro)
*(.data.rel*)
}
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.reloc : /* This is the PECOFF .reloc section! */
{
*(.reloc)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

View File

@ -0,0 +1,81 @@
OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64)
ENTRY(_start_plabel)
SECTIONS
{
. = 0;
ImageBase = .;
/* .hash and/or .gnu.hash MUST come first! */
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
. = ALIGN(4096);
.text :
{
_text = .;
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
__gp = ALIGN (8) + 0x200000;
.sdata :
{
_data = .;
*(.got.plt)
*(.got)
*(.srodata)
*(.sdata)
*(.sbss)
*(.scommon)
}
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.ctors)
*(.data*)
*(.gnu.linkonce.d*)
*(.plabel) /* data whose relocs we want to ignore */
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
*(.dynbss)
*(.bss)
*(COMMON)
}
.note.gnu.build-id : { *(.note.gnu.build-id) }
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela :
{
*(.rela.text)
*(.rela.data*)
*(.rela.sdata)
*(.rela.got)
*(.rela.gnu.linkonce.d*)
*(.rela.stab)
*(.rela.ctors)
}
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.reloc : /* This is the PECOFF .reloc section! */
{
*(.reloc)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
/DISCARD/ :
{
*(.rela.plabel)
*(.rela.reloc)
*(.IA_64.unwind*)
*(.IA64.unwind*)
}
}

View File

@ -0,0 +1,64 @@
OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
OUTPUT_ARCH(mips)
ENTRY(_start)
SECTIONS
{
.text 0x0 : {
_text = .;
*(.text.head)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.srodata)
*(.rodata*)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
.dynamic : { *(.dynamic) }
.data :
{
_data = .;
*(.sdata)
*(.data)
*(.data1)
*(.data.*)
*(.got.plt)
HIDDEN (_gp = ALIGN (16) + 0x7ff0);
*(.got)
/* the EFI loader doesn't seem to like a .bss section, so we stick
it all into .data: */
. = ALIGN(16);
_bss = .;
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
. = ALIGN(16);
_bss_end = .;
}
.rel.dyn : { *(.rel.dyn) }
.rel.plt : { *(.rel.plt) }
.rel.got : { *(.rel.got) }
.rel.data : { *(.rel.data) *(.rel.data*) }
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.note.gnu.build-id : { *(.note.gnu.build-id) }
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.MIPS.abiflags)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
}

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) }
}

View File

@ -0,0 +1,70 @@
/* Same as elf_x86_64_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd")
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)
. = ALIGN(16);
}
_etext = .;
_text_size = . - _text;
.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) }
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela :
{
*(.rela.data*)
*(.rela.got)
*(.rela.stab)
}
_edata = .;
_data_size = . - _etext;
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
.ignored.reloc :
{
*(.rela.reloc)
}
}

View File

@ -0,0 +1,97 @@
/* reloc_aarch64.c - position independent x86 ELF shared object relocator
Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <efilib.h>
#include <elf.h>
EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0;
Elf64_Rela *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_RELA:
rel = (Elf64_Rela*)
((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 == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (rel->r_info)) {
case R_AARCH64_NONE:
break;
case R_AARCH64_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr = ldbase + rel->r_addend;
break;
default:
break;
}
rel = (Elf64_Rela*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,97 @@
/* reloc_arm.c - position independent x86 ELF shared object relocator
Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <efilib.h>
#include <elf.h>
EFI_STATUS _relocate (long ldbase, Elf32_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0;
Elf32_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_REL:
rel = (Elf32_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELSZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELENT:
relent = dyn[i].d_un.d_val;
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF32_R_TYPE (rel->r_info)) {
case R_ARM_NONE:
break;
case R_ARM_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf32_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,99 @@
/* reloc_ia32.c - position independent x86 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <efilib.h>
#include <elf.h>
EFI_STATUS _relocate (long ldbase, Elf32_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0;
Elf32_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_REL:
rel = (Elf32_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELSZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELENT:
relent = dyn[i].d_un.d_val;
break;
case DT_RELA:
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF32_R_TYPE (rel->r_info)) {
case R_386_NONE:
break;
case R_386_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf32_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

227
gnu-efi/gnuefi/reloc_ia64.S Normal file
View File

@ -0,0 +1,227 @@
/* reloc_ia64.S - position independent IA-64 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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.
*/
/*
* This is written in assembly because the entire code needs to be position
* independent. Note that the compiler does not generate code that's position
* independent by itself because it relies on the global offset table being
* relocated.
*/
.text
.psr abi64
.psr lsb
.lsb
/*
* This constant determines how many R_IA64_FPTR64LSB relocations we
* can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may
* need to increase this number.
*/
#define MAX_FUNCTION_DESCRIPTORS 750
#define ST_VALUE_OFF 8 /* offset of st_value in elf sym */
#define EFI_SUCCESS 0
#define EFI_LOAD_ERROR 1
#define EFI_BUFFER_TOO_SMALL 5
#define DT_NULL 0 /* Marks end of dynamic section */
#define DT_RELA 7 /* Address of Rela relocs */
#define DT_RELASZ 8 /* Total size of Rela relocs */
#define DT_RELAENT 9 /* Size of one Rela reloc */
#define DT_SYMTAB 6 /* Address of symbol table */
#define DT_SYMENT 11 /* Size of one symbol table entry */
#define R_IA64_NONE 0
#define R_IA64_REL64MSB 0x6e
#define R_IA64_REL64LSB 0x6f
#define R_IA64_DIR64MSB 0x26
#define R_IA64_DIR64LSB 0x27
#define R_IA64_FPTR64MSB 0x46
#define R_IA64_FPTR64LSB 0x47
#define ldbase in0 /* load address (address of .text) */
#define dyn in1 /* address of _DYNAMIC */
#define d_tag r16
#define d_val r17
#define rela r18
#define relasz r19
#define relaent r20
#define addr r21
#define r_info r22
#define r_offset r23
#define r_addend r24
#define r_type r25
#define r_sym r25 /* alias of r_type ! */
#define fptr r26
#define fptr_limit r27
#define symtab f8
#define syment f9
#define ftmp f10
#define target r16
#define val r17
#define NLOC 0
#define Pnull p6
#define Prela p7
#define Prelasz p8
#define Prelaent p9
#define Psymtab p10
#define Psyment p11
#define Pnone p6
#define Prel p7
#define Pfptr p8
#define Pmore p6
#define Poom p6 /* out-of-memory */
.global _relocate
.proc _relocate
_relocate:
alloc r2=ar.pfs,2,0,0,0
movl fptr = @gprel(fptr_mem_base)
;;
add fptr = fptr, gp
movl fptr_limit = @gprel(fptr_mem_limit)
;;
add fptr_limit = fptr_limit, gp
search_dynamic:
ld8 d_tag = [dyn],8
;;
ld8 d_val = [dyn],8
cmp.eq Pnull,p0 = DT_NULL,d_tag
(Pnull) br.cond.sptk.few apply_relocs
cmp.eq Prela,p0 = DT_RELA,d_tag
cmp.eq Prelasz,p0 = DT_RELASZ,d_tag
cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag
cmp.eq Psyment,p0 = DT_SYMENT,d_tag
cmp.eq Prelaent,p0 = DT_RELAENT,d_tag
;;
(Prela) add rela = d_val, ldbase
(Prelasz) mov relasz = d_val
(Prelaent) mov relaent = d_val
(Psymtab) add val = d_val, ldbase
;;
(Psyment) setf.sig syment = d_val
;;
(Psymtab) setf.sig symtab = val
br.sptk.few search_dynamic
apply_loop:
ld8 r_offset = [rela]
add addr = 8,rela
sub relasz = relasz,relaent
;;
ld8 r_info = [addr],8
;;
ld8 r_addend = [addr]
add target = ldbase, r_offset
add rela = rela,relaent
extr.u r_type = r_info, 0, 32
;;
cmp.eq Pnone,p0 = R_IA64_NONE,r_type
cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type
cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type
(Prel) br.cond.sptk.few apply_REL64
;;
cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
(Pnone) br.cond.sptk.few apply_relocs
(Prel) br.cond.sptk.few apply_REL64
(Pfptr) br.cond.sptk.few apply_FPTR64
mov r8 = EFI_LOAD_ERROR
br.ret.sptk.few rp
apply_relocs:
cmp.ltu Pmore,p0=0,relasz
(Pmore) br.cond.sptk.few apply_loop
mov r8 = EFI_SUCCESS
br.ret.sptk.few rp
apply_REL64:
ld8 val = [target]
;;
add val = val,ldbase
;;
st8 [target] = val
br.cond.sptk.few apply_relocs
// FPTR relocs are a bit more interesting: we need to lookup
// the symbol's value in symtab, allocate 16 bytes of memory,
// store the value in [target] in the first and the gp in the
// second dword.
apply_FPTR64:
st8 [target] = fptr
extr.u r_sym = r_info,32,32
add target = 8,fptr
;;
setf.sig ftmp = r_sym
mov r8=EFI_BUFFER_TOO_SMALL
;;
cmp.geu Poom,p0 = fptr,fptr_limit
xma.lu ftmp = ftmp,syment,symtab
(Poom) br.ret.sptk.few rp
;;
getf.sig addr = ftmp
st8 [target] = gp
;;
add addr = ST_VALUE_OFF, addr
;;
ld8 val = [addr]
;;
add val = val,ldbase
;;
st8 [fptr] = val,16
br.cond.sptk.few apply_relocs
.endp _relocate
.data
.align 16
fptr_mem_base:
.space MAX_FUNCTION_DESCRIPTORS*16
fptr_mem_limit:

View File

@ -0,0 +1,115 @@
/* reloc_mips64el.c - position independent MIPS64 ELF shared object relocator
Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2017 Lemote Co.
Contributed by Heiher <r@hev.cc>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <efilib.h>
#include <elf.h>
EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0, gotsz = 0;
Elf64_Rel *rel = 0;
unsigned long *addr = 0;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_REL:
rel = (Elf64_Rel*)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_RELSZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELENT:
relent = dyn[i].d_un.d_val;
break;
case DT_PLTGOT:
addr = (unsigned long *)
((unsigned long)dyn[i].d_un.d_ptr
+ ldbase);
break;
case DT_MIPS_LOCAL_GOTNO:
gotsz = dyn[i].d_un.d_val;
break;
default:
break;
}
}
if ((!rel && relent == 0) && (!addr && gotsz == 0))
return EFI_SUCCESS;
if ((!rel && relent != 0) || (!addr && gotsz != 0))
return EFI_LOAD_ERROR;
while (gotsz > 0) {
*addr += ldbase;
addr += 1;
gotsz --;
}
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (swap_uint64 (rel->r_info))) {
case R_MIPS_NONE:
break;
case (R_MIPS_64 << 8) | R_MIPS_REL32:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,98 @@
/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
Copyright (C) 1999 Hewlett-Packard Co.
Contributed by David Mosberger <davidm@hpl.hp.com>.
Copyright (C) 2005 Intel Co.
Contributed by Fenghua Yu <fenghua.yu@intel.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Hewlett-Packard Co. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANYDIRECT, 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 <efi.h>
#include <efilib.h>
#include <elf.h>
EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
EFI_HANDLE image EFI_UNUSED,
EFI_SYSTEM_TABLE *systab EFI_UNUSED)
{
long relsz = 0, relent = 0;
Elf64_Rel *rel = 0;
unsigned long *addr;
int i;
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 == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF64_R_TYPE (rel->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_RELATIVE:
addr = (unsigned long *)
(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
}

27
gnu-efi/inc/Makefile Normal file
View File

@ -0,0 +1,27 @@
SRCDIR = .
VPATH = $(SRCDIR)
include $(SRCDIR)/../Make.defaults
TOPDIR = $(SRCDIR)/..
CDIR=$(TOPDIR)/..
all:
clean:
install:
mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi
mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol
mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH)
$(INSTALL) -m 644 $(SRCDIR)/*.h $(INSTALLROOT)$(PREFIX)/include/efi
$(INSTALL) -m 644 $(SRCDIR)/protocol/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol
$(INSTALL) -m 644 $(SRCDIR)/$(ARCH)/*.h $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH)
ifeq ($(ARCH),ia64)
mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64
$(INSTALL) -m 644 $(SRCDIR)/protocol/ia64/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64
endif
include $(SRCDIR)/../Make.rules

Some files were not shown because too many files have changed in this diff Show More