mirror of
https://github.com/ipxe/ipxe
synced 2025-12-21 12:30:20 +03:00
[efi] Add EFI image format and basic runtime environment
We have EFI APIs for CPU I/O, PCI I/O, timers, console I/O, user access and user memory allocation. EFI executables are created using the vanilla GNU toolchain, with the EXE header handcrafted in assembly and relocations generated by a custom efilink utility.
This commit is contained in:
@@ -64,6 +64,7 @@ SRCDIRS += arch/i386/drivers/net
|
||||
SRCDIRS += arch/i386/interface/pcbios
|
||||
SRCDIRS += arch/i386/interface/pxe
|
||||
SRCDIRS += arch/i386/interface/syslinux
|
||||
SRCDIRS += arch/i386/interface/efi
|
||||
|
||||
# The various xxx_loader.c files are #included into core/loader.c and
|
||||
# should not be compiled directly.
|
||||
|
||||
24
src/arch/i386/Makefile.efi
Normal file
24
src/arch/i386/Makefile.efi
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- makefile -*- : Force emacs to use Makefile mode
|
||||
|
||||
# The EFI linker script
|
||||
#
|
||||
LDSCRIPT = arch/i386/scripts/efi.lds
|
||||
|
||||
# Use a relocatable link; we perform final relocations in the efilink utility.
|
||||
#
|
||||
LDFLAGS += -r -d -S
|
||||
|
||||
# Media types.
|
||||
#
|
||||
NON_AUTO_MEDIA += efi
|
||||
|
||||
# Rule for building EFI files
|
||||
#
|
||||
$(BIN)/%.efi.tmp-reloc : $(BIN)/%.efi.tmp $(EFILINK)
|
||||
$(QM)$(ECHO) " [EFILINK] $@"
|
||||
$(Q)$(LD) -e 0 -o /dev/null $< # Check for unresolved symbols
|
||||
$(Q)$(EFILINK) $< $@
|
||||
|
||||
$(BIN)/%.efi : $(BIN)/%.efi.tmp-reloc
|
||||
$(QM)$(ECHO) " [FINISH] $@"
|
||||
$(Q)$(OBJCOPY) -Obinary $< $@
|
||||
@@ -8,5 +8,6 @@
|
||||
*/
|
||||
|
||||
#include <gpxe/bios_nap.h>
|
||||
#include <gpxe/efi/efix86_nap.h>
|
||||
|
||||
#endif /* _BITS_MAP_H */
|
||||
|
||||
16
src/arch/i386/include/gpxe/efi/efix86_nap.h
Normal file
16
src/arch/i386/include/gpxe/efi/efix86_nap.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _GPXE_EFIX86_NAP_H
|
||||
#define _GPXE_EFIX86_NAP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* EFI CPU sleeping
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef NAP_EFIX86
|
||||
#define NAP_PREFIX_efix86
|
||||
#else
|
||||
#define NAP_PREFIX_efix86 __efix86_
|
||||
#endif
|
||||
|
||||
#endif /* _GPXE_EFIX86_NAP_H */
|
||||
46
src/arch/i386/interface/efi/efix86_nap.c
Normal file
46
src/arch/i386/interface/efi/efix86_nap.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <gpxe/nap.h>
|
||||
#include <gpxe/efi/efi.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* gPXE CPU sleeping API for EFI
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sleep until next interrupt
|
||||
*
|
||||
*/
|
||||
static void efix86_cpu_nap ( void ) {
|
||||
/*
|
||||
* I can't find any EFI API that allows us to put the CPU to
|
||||
* sleep. The CpuSleep() function is defined in CpuLib.h, but
|
||||
* isn't part of any exposed protocol so we have no way to
|
||||
* call it.
|
||||
*
|
||||
* The EFI shell doesn't seem to bother sleeping the CPU; it
|
||||
* just sits there idly burning power.
|
||||
*
|
||||
*/
|
||||
__asm__ __volatile__ ( "hlt" );
|
||||
}
|
||||
|
||||
PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );
|
||||
175
src/arch/i386/prefix/efiprefix.S
Normal file
175
src/arch/i386/prefix/efiprefix.S
Normal file
@@ -0,0 +1,175 @@
|
||||
.text
|
||||
.code32
|
||||
.arch i386
|
||||
.section ".prefix", "a", @progbits
|
||||
.org 0x00
|
||||
|
||||
/* DOS (.com) header
|
||||
*
|
||||
* EFI executables seem to leave most of this empty
|
||||
*/
|
||||
mzhdr:
|
||||
.ascii "MZ" /* Magic number */
|
||||
.word 0 /* Bytes on last page of file */
|
||||
.word 0 /* Pages in file */
|
||||
.word 0 /* Relocations */
|
||||
.word 0 /* Size of header in paragraphs */
|
||||
.word 0 /* Minimum extra paragraphs needed */
|
||||
.word 0 /* Maximum extra paragraphs needed */
|
||||
.word 0 /* Initial (relative) SS value */
|
||||
.word 0 /* Initial SP value */
|
||||
.word 0 /* "Checksum" */
|
||||
.word 0 /* Initial IP value */
|
||||
.word 0 /* Initial (relative) CS value */
|
||||
.word 0 /* File address of relocation table */
|
||||
.word 0 /* Ovesrlay number */
|
||||
.word 0, 0, 0, 0 /* Reserved words */
|
||||
.word 0 /* OEM identifier (for e_oeminfo) */
|
||||
.word 0 /* OEM information; e_oemid specific */
|
||||
.word 0, 0, 0, 0, 0 /* Reserved words */
|
||||
.word 0, 0, 0, 0, 0 /* Reserved words */
|
||||
.long pehdr_lma /* File address of new exe header */
|
||||
.size mzhdr, . - mzhdr
|
||||
|
||||
/* PE header */
|
||||
.org 0xc0 /* For compatibility with MS toolchain */
|
||||
pehdr:
|
||||
.ascii "PE\0\0" /* Magic number */
|
||||
.word 0x014c /* CPU architecture: i386 */
|
||||
.word num_pe_sections /* Number of sections */
|
||||
.long 0x10d1a884 /* Timestamp */
|
||||
.long 0 /* Symbol table */
|
||||
.long 0 /* Number of symbols */
|
||||
.word opthdr_size /* Size of optional header */
|
||||
.word 0x2102 /* Characteristics */
|
||||
.size pehdr, . - pehdr
|
||||
.equ pehdr_lma, pehdr - mzhdr
|
||||
|
||||
/* "Optional" header */
|
||||
opthdr:
|
||||
.word 0x010b /* Magic number */
|
||||
.byte 0 /* Linker major version number */
|
||||
.byte 0 /* Linker minor version number */
|
||||
.long _text_filesz /* Size of text section */
|
||||
.long _data_filesz /* Size of data section */
|
||||
.long _bss_filesz /* Size of bss section */
|
||||
.long efi_entry_lma /* Entry point */
|
||||
.long _text_lma /* Text section start RVA */
|
||||
.long _data_lma /* Data section start RVA */
|
||||
.long 0 /* Image base address */
|
||||
.long _max_align /* Section alignment */
|
||||
.long _max_align /* File alignment */
|
||||
.word 0 /* Operating system major version number */
|
||||
.word 0 /* Operating system minor version number */
|
||||
.word 0 /* Image major version number */
|
||||
.word 0 /* Image minor version number */
|
||||
.word 0 /* Subsystem major version number */
|
||||
.word 0 /* Subsystem minor version number */
|
||||
.long 0 /* Reserved */
|
||||
.long _filesz /* Total image size */
|
||||
.long _prefix_filesz /* Total header size */
|
||||
.long 0 /* "Checksum" */
|
||||
.word 0x0a /* Subsystem: EFI */
|
||||
.word 0 /* DLL characteristics */
|
||||
.long 0 /* Size of stack reserve */
|
||||
.long 0 /* Size of stack commit */
|
||||
.long 0 /* Size of heap reserve */
|
||||
.long 0 /* Size of heap commit */
|
||||
.long 0 /* Loader flags */
|
||||
.long 16 /* Number of data directory entries */
|
||||
.long 0, 0 /* Export directory */
|
||||
.long 0, 0 /* Import directory */
|
||||
.long 0, 0 /* Resource directory */
|
||||
.long 0, 0 /* Exception directory */
|
||||
.long 0, 0 /* Security directory */
|
||||
.long _reloc_lma, _reloc_filesz /* Base relocation directory */
|
||||
.long debugdir_lma, debugdir_size /* Debug directory */
|
||||
.long 0, 0 /* Description directory */
|
||||
.long 0, 0 /* Special directory */
|
||||
.long 0, 0 /* Thread storage directory */
|
||||
.long 0, 0 /* Load configuration directory */
|
||||
.long 0, 0 /* Bound import directory */
|
||||
.long 0, 0 /* Import address table directory */
|
||||
.long 0, 0 /* Delay import directory */
|
||||
.long 0, 0 /* Reserved */
|
||||
.long 0, 0 /* Reserved */
|
||||
.size opthdr, . - opthdr
|
||||
.equ opthdr_size, . - opthdr
|
||||
|
||||
/* PE sections */
|
||||
pe_sections:
|
||||
text_section:
|
||||
.asciz ".text" /* Section name */
|
||||
.align 8
|
||||
.long _text_filesz /* Section size */
|
||||
.long _text_lma /* Relative Virtual Address */
|
||||
.long _text_filesz /* Section size (rounded up) */
|
||||
.long _text_lma /* Pointer to raw data */
|
||||
.long 0 /* Link-time relocations */
|
||||
.long 0 /* Line numbers */
|
||||
.word 0 /* Number of link-time relocations */
|
||||
.word 0 /* Number of line numbers */
|
||||
.long 0x68000020 /* Characteristics */
|
||||
rodata_section:
|
||||
.asciz ".rodata" /* Section name */
|
||||
.align 8
|
||||
.long _rodata_filesz /* Section size */
|
||||
.long _rodata_lma /* Relative Virtual Address */
|
||||
.long _rodata_filesz /* Section size (rounded up) */
|
||||
.long _rodata_lma /* Pointer to raw data */
|
||||
.long 0 /* Link-time relocations */
|
||||
.long 0 /* Line numbers */
|
||||
.word 0 /* Number of link-time relocations */
|
||||
.word 0 /* Number of line numbers */
|
||||
.long 0x48000040 /* Characteristics */
|
||||
data_section:
|
||||
.asciz ".data" /* Section name */
|
||||
.align 8
|
||||
.long _data_filesz /* Section size */
|
||||
.long _data_lma /* Relative Virtual Address */
|
||||
.long _data_filesz /* Section size (rounded up) */
|
||||
.long _data_lma /* Pointer to raw data */
|
||||
.long 0 /* Link-time relocations */
|
||||
.long 0 /* Line numbers */
|
||||
.word 0 /* Number of link-time relocations */
|
||||
.word 0 /* Number of line numbers */
|
||||
.long 0xc8000040 /* Characteristics */
|
||||
reloc_section:
|
||||
.asciz ".reloc" /* Section name */
|
||||
.align 8
|
||||
.long _reloc_filesz /* Section size */
|
||||
.long _reloc_lma /* Relative Virtual Address */
|
||||
.long _reloc_filesz /* Section size (rounded up) */
|
||||
.long _reloc_lma /* Pointer to raw data */
|
||||
.long 0 /* Link-time relocations */
|
||||
.long 0 /* Line numbers */
|
||||
.word 0 /* Number of link-time relocations */
|
||||
.word 0 /* Number of line numbers */
|
||||
.long 0x42000040 /* Characteristics */
|
||||
|
||||
pe_sections_end:
|
||||
.size pe_sections, . - pe_sections
|
||||
.equ num_pe_sections, ( ( . - pe_sections ) / 0x28 )
|
||||
|
||||
/* Debug directory */
|
||||
.section ".rodata"
|
||||
.globl debugdir
|
||||
debugdir:
|
||||
.long 0 /* Characteristics */
|
||||
.long 0x10d1a884 /* Timestamp */
|
||||
.word 0 /* Major version */
|
||||
.word 0 /* Minor version */
|
||||
.long 0x02 /* RSDS? */
|
||||
.long codeview_rsds_size /* Size of data */
|
||||
.long codeview_rsds_lma /* RVA */
|
||||
.long codeview_rsds_lma /* File offset */
|
||||
.size debugdir, . - debugdir
|
||||
.equ debugdir_size, . - debugdir
|
||||
/* Codeview structure */
|
||||
.globl codeview_rsds
|
||||
codeview_rsds:
|
||||
.ascii "RSDS" /* Magic number */
|
||||
.long 0, 0, 0, 0, 0 /* Unused by EFI */
|
||||
.asciz "efiprefix.pdb"
|
||||
.size codeview_rsds, . - codeview_rsds
|
||||
.equ codeview_rsds_size, . - codeview_rsds
|
||||
174
src/arch/i386/scripts/efi.lds
Normal file
174
src/arch/i386/scripts/efi.lds
Normal file
@@ -0,0 +1,174 @@
|
||||
/* -*- sh -*- */
|
||||
|
||||
/*
|
||||
* Linker script for EFI images
|
||||
*
|
||||
*/
|
||||
|
||||
EXTERN ( efi_entry )
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* The file starts at a virtual address of zero, and sections are
|
||||
* contiguous. Each section is aligned to at least _max_align,
|
||||
* which defaults to 32. Load addresses are equal to virtual
|
||||
* addresses.
|
||||
*/
|
||||
|
||||
. = 0;
|
||||
PROVIDE ( _max_align = 32 );
|
||||
|
||||
/*
|
||||
* The prefix
|
||||
*
|
||||
*/
|
||||
|
||||
.prefix : AT ( _prefix_lma ) {
|
||||
_prefix = .;
|
||||
*(.prefix)
|
||||
*(.prefix.*)
|
||||
_mprefix = .;
|
||||
} .prefix_bss (NOLOAD) : {
|
||||
_eprefix = .;
|
||||
}
|
||||
_prefix_filesz = ABSOLUTE ( _mprefix - _prefix );
|
||||
_prefix_memsz = ABSOLUTE ( _eprefix - _prefix );
|
||||
|
||||
/*
|
||||
* The text section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.text : AT ( _text_lma ) {
|
||||
_text = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
_mtext = .;
|
||||
} .text_bss (NOLOAD) : {
|
||||
_etext = .;
|
||||
}
|
||||
_text_filesz = ABSOLUTE ( _mtext - _text );
|
||||
_text_memsz = ABSOLUTE ( _etext - _text );
|
||||
|
||||
/*
|
||||
* The rodata section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.rodata : AT ( _rodata_lma ) {
|
||||
_rodata = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
_mrodata = .;
|
||||
} .rodata_bss (NOLOAD) : {
|
||||
_erodata = .;
|
||||
}
|
||||
_rodata_filesz = ABSOLUTE ( _mrodata - _rodata );
|
||||
_rodata_memsz = ABSOLUTE ( _erodata - _rodata );
|
||||
|
||||
/*
|
||||
* The data section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.data : AT ( _data_lma ) {
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(SORT(.tbl.*)) /* Various tables. See include/tables.h */
|
||||
/* EFI seems to not support proper bss sections */
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
*(.stack)
|
||||
*(.stack.*)
|
||||
_mdata = .;
|
||||
} .data_bss (NOLOAD) : {
|
||||
_edata = .;
|
||||
}
|
||||
_data_filesz = ABSOLUTE ( _mdata - _data );
|
||||
_data_memsz = ABSOLUTE ( _edata - _data );
|
||||
|
||||
/*
|
||||
* The bss section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.bss : AT ( _bss_lma ) {
|
||||
_bss = .;
|
||||
/* EFI seems to not support proper bss sections */
|
||||
_mbss = .;
|
||||
} .bss_bss (NOLOAD) : {
|
||||
_ebss = .;
|
||||
}
|
||||
_bss_filesz = ABSOLUTE ( _mbss - _bss );
|
||||
_bss_memsz = ABSOLUTE ( _ebss - _bss );
|
||||
|
||||
/*
|
||||
* The reloc section
|
||||
*
|
||||
*/
|
||||
|
||||
. = ALIGN ( _max_align );
|
||||
.reloc : AT ( _reloc_lma ) {
|
||||
_reloc = .;
|
||||
/* Provide some dummy contents to force ld to include this
|
||||
* section. It will be created by the efilink utility.
|
||||
*/
|
||||
. += 1;
|
||||
_mreloc = .;
|
||||
} .reloc_bss (NOLOAD) : {
|
||||
_ereloc = .;
|
||||
}
|
||||
_reloc_filesz = ABSOLUTE ( _mreloc - _reloc );
|
||||
_reloc_memsz = ABSOLUTE ( _ereloc - _reloc );
|
||||
|
||||
_filesz = ABSOLUTE ( . );
|
||||
|
||||
/*
|
||||
* Weak symbols that need zero values if not otherwise defined
|
||||
*
|
||||
*/
|
||||
|
||||
.weak 0x0 : {
|
||||
_weak = .;
|
||||
*(.weak)
|
||||
_eweak = .;
|
||||
}
|
||||
_assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
|
||||
|
||||
/*
|
||||
* Dispose of the comment and note sections to make the link map
|
||||
* easier to read
|
||||
*
|
||||
*/
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.comment)
|
||||
*(.note)
|
||||
}
|
||||
|
||||
/*
|
||||
* Load address calculations.
|
||||
*
|
||||
*/
|
||||
|
||||
_prefix_lma = ABSOLUTE ( _prefix );
|
||||
_text_lma = ABSOLUTE ( _text );
|
||||
_rodata_lma = ABSOLUTE ( _rodata );
|
||||
_data_lma = ABSOLUTE ( _data );
|
||||
_bss_lma = ABSOLUTE ( _bss );
|
||||
_reloc_lma = ABSOLUTE ( _reloc );
|
||||
|
||||
/*
|
||||
* Load addresses required by the prefix
|
||||
*
|
||||
*/
|
||||
efi_entry_lma = ABSOLUTE ( efi_entry );
|
||||
debugdir_lma = ABSOLUTE ( debugdir );
|
||||
codeview_rsds_lma = ABSOLUTE ( codeview_rsds );
|
||||
}
|
||||
Reference in New Issue
Block a user