Browse Source

[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.
tags/v0.9.6
Michael Brown 15 years ago
parent
commit
81d92c6d34
40 changed files with 4781 additions and 1 deletions
  1. 2
    1
      src/Makefile
  2. 9
    0
      src/Makefile.housekeeping
  3. 1
    0
      src/arch/i386/Makefile
  4. 24
    0
      src/arch/i386/Makefile.efi
  5. 1
    0
      src/arch/i386/include/bits/nap.h
  6. 16
    0
      src/arch/i386/include/gpxe/efi/efix86_nap.h
  7. 46
    0
      src/arch/i386/interface/efi/efix86_nap.c
  8. 175
    0
      src/arch/i386/prefix/efiprefix.S
  9. 174
    0
      src/arch/i386/scripts/efi.lds
  10. 20
    0
      src/config/defaults/efi.h
  11. 1
    0
      src/config/general.h
  12. 6
    0
      src/core/config.c
  13. 106
    0
      src/image/efi_image.c
  14. 742
    0
      src/include/gpxe/efi/IndustryStandard/PeImage.h
  15. 326
    0
      src/include/gpxe/efi/Protocol/Cpu.h
  16. 128
    0
      src/include/gpxe/efi/Protocol/CpuIo.h
  17. 656
    0
      src/include/gpxe/efi/Protocol/DebugSupport.h
  18. 450
    0
      src/include/gpxe/efi/Protocol/PciRootBridgeIo.h
  19. 52
    0
      src/include/gpxe/efi/efi.h
  20. 178
    0
      src/include/gpxe/efi/efi_io.h
  21. 146
    0
      src/include/gpxe/efi/efi_pci.h
  22. 16
    0
      src/include/gpxe/efi/efi_timer.h
  23. 88
    0
      src/include/gpxe/efi/efi_uaccess.h
  24. 16
    0
      src/include/gpxe/efi/efi_umalloc.h
  25. 2
    0
      src/include/gpxe/errfile.h
  26. 1
    0
      src/include/gpxe/features.h
  27. 1
    0
      src/include/gpxe/io.h
  28. 1
    0
      src/include/gpxe/pci_io.h
  29. 1
    0
      src/include/gpxe/timer.h
  30. 1
    0
      src/include/gpxe/uaccess.h
  31. 1
    0
      src/include/gpxe/umalloc.h
  32. 273
    0
      src/interface/efi/efi_console.c
  33. 83
    0
      src/interface/efi/efi_entry.c
  34. 201
    0
      src/interface/efi/efi_io.c
  35. 81
    0
      src/interface/efi/efi_pci.c
  36. 115
    0
      src/interface/efi/efi_timer.c
  37. 37
    0
      src/interface/efi/efi_uaccess.c
  38. 96
    0
      src/interface/efi/efi_umalloc.c
  39. 1
    0
      src/util/.gitignore
  40. 507
    0
      src/util/efilink.c

+ 2
- 1
src/Makefile View File

@@ -37,6 +37,7 @@ SYMCHECK	:= $(PERL) ./util/symcheck.pl
37 37
 SORTOBJDUMP	:= $(PERL) ./util/sortobjdump.pl
38 38
 NRV2B		:= ./util/nrv2b
39 39
 ZBIN		:= ./util/zbin
40
+EFILINK		:= ./util/efilink
40 41
 DOXYGEN		:= doxygen
41 42
 
42 43
 ###############################################################################
@@ -57,7 +58,7 @@ SRCDIRS		+= drivers/block
57 58
 SRCDIRS		+= drivers/nvs
58 59
 SRCDIRS		+= drivers/bitbash
59 60
 SRCDIRS		+= drivers/infiniband
60
-SRCDIRS		+= interface/pxe
61
+SRCDIRS		+= interface/pxe interface/efi
61 62
 SRCDIRS		+= tests
62 63
 SRCDIRS		+= crypto crypto/axtls crypto/matrixssl
63 64
 SRCDIRS		+= hci hci/commands hci/tui

+ 9
- 0
src/Makefile.housekeeping View File

@@ -693,6 +693,15 @@ $(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
693 693
 	$(Q)$(HOST_CC) -O2 -o $@ $<
694 694
 CLEANUP += $(ZBIN)
695 695
 
696
+###############################################################################
697
+#
698
+# The EFI custom linker
699
+#
700
+$(EFILINK) : util/efilink.c $(MAKEDEPS)
701
+	$(QM)$(ECHO) "  [HOSTCC] $@"
702
+	$(Q)$(HOST_CC) -O2 -o $@ $< -lbfd
703
+CLEANUP += $(EFILINK)
704
+
696 705
 ###############################################################################
697 706
 #
698 707
 # Auto-incrementing build serial number.  Append "bs" to your list of

+ 1
- 0
src/arch/i386/Makefile View File

@@ -64,6 +64,7 @@ SRCDIRS		+= arch/i386/drivers/net
64 64
 SRCDIRS		+= arch/i386/interface/pcbios
65 65
 SRCDIRS		+= arch/i386/interface/pxe
66 66
 SRCDIRS 	+= arch/i386/interface/syslinux
67
+SRCDIRS 	+= arch/i386/interface/efi
67 68
 
68 69
 # The various xxx_loader.c files are #included into core/loader.c and
69 70
 # should not be compiled directly.

+ 24
- 0
src/arch/i386/Makefile.efi View File

@@ -0,0 +1,24 @@
1
+# -*- makefile -*- : Force emacs to use Makefile mode
2
+
3
+# The EFI linker script
4
+#
5
+LDSCRIPT	= arch/i386/scripts/efi.lds
6
+
7
+# Use a relocatable link; we perform final relocations in the efilink utility.
8
+#
9
+LDFLAGS		+= -r -d -S
10
+
11
+# Media types.
12
+#
13
+NON_AUTO_MEDIA	+= efi
14
+
15
+# Rule for building EFI files
16
+#
17
+$(BIN)/%.efi.tmp-reloc : $(BIN)/%.efi.tmp $(EFILINK)
18
+	$(QM)$(ECHO) "  [EFILINK] $@"
19
+	$(Q)$(LD) -e 0 -o /dev/null $< # Check for unresolved symbols
20
+	$(Q)$(EFILINK) $< $@
21
+
22
+$(BIN)/%.efi : $(BIN)/%.efi.tmp-reloc
23
+	$(QM)$(ECHO) "  [FINISH] $@"
24
+	$(Q)$(OBJCOPY) -Obinary $< $@

+ 1
- 0
src/arch/i386/include/bits/nap.h View File

@@ -8,5 +8,6 @@
8 8
  */
9 9
 
10 10
 #include <gpxe/bios_nap.h>
11
+#include <gpxe/efi/efix86_nap.h>
11 12
 
12 13
 #endif /* _BITS_MAP_H */

+ 16
- 0
src/arch/i386/include/gpxe/efi/efix86_nap.h View File

@@ -0,0 +1,16 @@
1
+#ifndef _GPXE_EFIX86_NAP_H
2
+#define _GPXE_EFIX86_NAP_H
3
+
4
+/** @file
5
+ *
6
+ * EFI CPU sleeping
7
+ *
8
+ */
9
+
10
+#ifdef NAP_EFIX86
11
+#define NAP_PREFIX_efix86
12
+#else
13
+#define NAP_PREFIX_efix86 __efix86_
14
+#endif
15
+
16
+#endif /* _GPXE_EFIX86_NAP_H */

+ 46
- 0
src/arch/i386/interface/efi/efix86_nap.c View File

@@ -0,0 +1,46 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <gpxe/nap.h>
20
+#include <gpxe/efi/efi.h>
21
+
22
+/** @file
23
+ *
24
+ * gPXE CPU sleeping API for EFI
25
+ *
26
+ */
27
+
28
+/**
29
+ * Sleep until next interrupt
30
+ *
31
+ */
32
+static void efix86_cpu_nap ( void ) {
33
+	/*
34
+	 * I can't find any EFI API that allows us to put the CPU to
35
+	 * sleep.  The CpuSleep() function is defined in CpuLib.h, but
36
+	 * isn't part of any exposed protocol so we have no way to
37
+	 * call it.
38
+	 *
39
+	 * The EFI shell doesn't seem to bother sleeping the CPU; it
40
+	 * just sits there idly burning power.
41
+	 *
42
+	 */
43
+	__asm__ __volatile__ ( "hlt" );
44
+}
45
+
46
+PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );

+ 175
- 0
src/arch/i386/prefix/efiprefix.S View File

@@ -0,0 +1,175 @@
1
+	.text
2
+	.code32
3
+	.arch i386
4
+	.section ".prefix", "a", @progbits
5
+	.org 0x00
6
+
7
+	/* DOS (.com) header
8
+	 *
9
+	 * EFI executables seem to leave most of this empty
10
+	 */
11
+mzhdr:
12
+	.ascii	"MZ"		/* Magic number */
13
+	.word	0		/* Bytes on last page of file */
14
+	.word	0		/* Pages in file */
15
+	.word	0		/* Relocations */
16
+	.word	0		/* Size of header in paragraphs */
17
+	.word	0		/* Minimum extra paragraphs needed */
18
+	.word	0		/* Maximum extra paragraphs needed */
19
+	.word	0		/* Initial (relative) SS value */
20
+	.word	0		/* Initial SP value */
21
+	.word	0		/* "Checksum" */
22
+	.word	0		/* Initial IP value */
23
+	.word	0		/* Initial (relative) CS value */
24
+	.word	0		/* File address of relocation table */
25
+	.word	0		/* Ovesrlay number */
26
+	.word	0, 0, 0, 0	/* Reserved words */
27
+	.word	0		/* OEM identifier (for e_oeminfo) */
28
+	.word	0		/* OEM information; e_oemid specific */
29
+	.word	0, 0, 0, 0, 0	/* Reserved words */
30
+	.word	0, 0, 0, 0, 0	/* Reserved words */
31
+	.long	pehdr_lma	/* File address of new exe header */
32
+	.size	mzhdr, . - mzhdr
33
+
34
+	/* PE header */
35
+	.org	0xc0 /* For compatibility with MS toolchain */
36
+pehdr:
37
+	.ascii	"PE\0\0"	/* Magic number */
38
+	.word	0x014c		/* CPU architecture: i386 */
39
+	.word	num_pe_sections	/* Number of sections */
40
+	.long	0x10d1a884	/* Timestamp */
41
+	.long	0		/* Symbol table */
42
+	.long	0		/* Number of symbols */
43
+	.word	opthdr_size	/* Size of optional header */
44
+	.word	0x2102		/* Characteristics */
45
+	.size	pehdr, . - pehdr
46
+	.equ	pehdr_lma, pehdr - mzhdr
47
+
48
+	/* "Optional" header */
49
+opthdr:
50
+	.word	0x010b		/* Magic number */
51
+	.byte	0		/* Linker major version number */
52
+	.byte	0		/* Linker minor version number */
53
+	.long	_text_filesz	/* Size of text section */
54
+	.long	_data_filesz	/* Size of data section */
55
+	.long	_bss_filesz	/* Size of bss section */
56
+	.long	efi_entry_lma	/* Entry point */
57
+	.long	_text_lma	/* Text section start RVA */
58
+	.long	_data_lma	/* Data section start RVA */
59
+	.long	0		/* Image base address */
60
+	.long	_max_align	/* Section alignment */
61
+	.long	_max_align	/* File alignment */
62
+	.word	0		/* Operating system major version number */
63
+	.word	0		/* Operating system minor version number */
64
+	.word	0		/* Image major version number */
65
+	.word	0		/* Image minor version number */
66
+	.word	0		/* Subsystem major version number */
67
+	.word	0		/* Subsystem minor version number */
68
+	.long	0		/* Reserved */
69
+	.long	_filesz		/* Total image size */
70
+	.long	_prefix_filesz	/* Total header size */
71
+	.long	0		/* "Checksum" */
72
+	.word	0x0a		/* Subsystem: EFI */
73
+	.word	0		/* DLL characteristics */
74
+	.long	0		/* Size of stack reserve */
75
+	.long	0		/* Size of stack commit */
76
+	.long	0		/* Size of heap reserve */
77
+	.long	0		/* Size of heap commit */
78
+	.long	0		/* Loader flags */
79
+	.long	16		/* Number of data directory entries */
80
+	.long	0, 0		/* Export directory */
81
+	.long	0, 0		/* Import directory */
82
+	.long	0, 0		/* Resource directory */
83
+	.long	0, 0		/* Exception directory */
84
+	.long	0, 0		/* Security directory */
85
+	.long	_reloc_lma, _reloc_filesz /* Base relocation directory */
86
+	.long	debugdir_lma, debugdir_size /* Debug directory */
87
+	.long	0, 0		/* Description directory */
88
+	.long	0, 0		/* Special directory */
89
+	.long	0, 0		/* Thread storage directory */
90
+	.long	0, 0		/* Load configuration directory */
91
+	.long	0, 0		/* Bound import directory */
92
+	.long	0, 0		/* Import address table directory */
93
+	.long	0, 0		/* Delay import directory */
94
+	.long	0, 0		/* Reserved */
95
+	.long	0, 0		/* Reserved */
96
+	.size	opthdr, . - opthdr
97
+	.equ	opthdr_size, . - opthdr
98
+
99
+	/* PE sections */
100
+pe_sections:
101
+text_section:
102
+	.asciz	".text"		/* Section name */
103
+	.align	8
104
+	.long	_text_filesz	/* Section size */
105
+	.long	_text_lma	/* Relative Virtual Address */
106
+	.long	_text_filesz	/* Section size (rounded up) */
107
+	.long	_text_lma	/* Pointer to raw data */
108
+	.long	0		/* Link-time relocations */
109
+	.long	0		/* Line numbers */
110
+	.word	0		/* Number of link-time relocations */
111
+	.word	0		/* Number of line numbers */
112
+	.long	0x68000020	/* Characteristics */
113
+rodata_section:
114
+	.asciz	".rodata"	/* Section name */
115
+	.align	8
116
+	.long	_rodata_filesz	/* Section size */
117
+	.long	_rodata_lma	/* Relative Virtual Address */
118
+	.long	_rodata_filesz	/* Section size (rounded up) */
119
+	.long	_rodata_lma	/* Pointer to raw data */
120
+	.long	0		/* Link-time relocations */
121
+	.long	0		/* Line numbers */
122
+	.word	0		/* Number of link-time relocations */
123
+	.word	0		/* Number of line numbers */
124
+	.long	0x48000040	/* Characteristics */
125
+data_section:
126
+	.asciz	".data"		/* Section name */
127
+	.align	8
128
+	.long	_data_filesz	/* Section size */
129
+	.long	_data_lma	/* Relative Virtual Address */
130
+	.long	_data_filesz	/* Section size (rounded up) */
131
+	.long	_data_lma	/* Pointer to raw data */
132
+	.long	0		/* Link-time relocations */
133
+	.long	0		/* Line numbers */
134
+	.word	0		/* Number of link-time relocations */
135
+	.word	0		/* Number of line numbers */
136
+	.long	0xc8000040	/* Characteristics */
137
+reloc_section:
138
+	.asciz	".reloc"	/* Section name */
139
+	.align	8
140
+	.long	_reloc_filesz	/* Section size */
141
+	.long	_reloc_lma	/* Relative Virtual Address */
142
+	.long	_reloc_filesz	/* Section size (rounded up) */
143
+	.long	_reloc_lma	/* Pointer to raw data */
144
+	.long	0		/* Link-time relocations */
145
+	.long	0		/* Line numbers */
146
+	.word	0		/* Number of link-time relocations */
147
+	.word	0		/* Number of line numbers */
148
+	.long	0x42000040	/* Characteristics */
149
+
150
+pe_sections_end:
151
+	.size	pe_sections, . - pe_sections
152
+	.equ	num_pe_sections, ( ( . - pe_sections ) / 0x28 )
153
+
154
+	/* Debug directory */
155
+	.section ".rodata"
156
+	.globl	debugdir
157
+debugdir:
158
+	.long	0		/* Characteristics */
159
+	.long	0x10d1a884	/* Timestamp */
160
+	.word	0		/* Major version */
161
+	.word	0		/* Minor version */
162
+	.long	0x02		/* RSDS? */
163
+	.long	codeview_rsds_size /* Size of data */
164
+	.long	codeview_rsds_lma /* RVA */
165
+	.long	codeview_rsds_lma /* File offset */
166
+	.size	debugdir, . - debugdir
167
+	.equ	debugdir_size, . - debugdir
168
+	/* Codeview structure */
169
+	.globl	codeview_rsds
170
+codeview_rsds:
171
+	.ascii	"RSDS"		/* Magic number */
172
+	.long	0, 0, 0, 0, 0	/* Unused by EFI */
173
+	.asciz	"efiprefix.pdb"
174
+	.size	codeview_rsds, . - codeview_rsds
175
+	.equ	codeview_rsds_size, . - codeview_rsds

+ 174
- 0
src/arch/i386/scripts/efi.lds View File

@@ -0,0 +1,174 @@
1
+/* -*- sh -*- */
2
+
3
+/*
4
+ * Linker script for EFI images
5
+ *
6
+ */
7
+
8
+EXTERN ( efi_entry )
9
+
10
+SECTIONS {
11
+
12
+    /* The file starts at a virtual address of zero, and sections are
13
+     * contiguous.  Each section is aligned to at least _max_align,
14
+     * which defaults to 32.  Load addresses are equal to virtual
15
+     * addresses.
16
+     */
17
+
18
+    . = 0;
19
+    PROVIDE ( _max_align = 32 );
20
+
21
+    /*
22
+     * The prefix
23
+     *
24
+     */
25
+
26
+    .prefix : AT ( _prefix_lma ) {
27
+	_prefix = .;
28
+	*(.prefix)
29
+	*(.prefix.*)
30
+	_mprefix = .;
31
+    } .prefix_bss (NOLOAD) : {
32
+	_eprefix = .;
33
+    }
34
+    _prefix_filesz	= ABSOLUTE ( _mprefix - _prefix );
35
+    _prefix_memsz	= ABSOLUTE ( _eprefix - _prefix );
36
+
37
+    /*
38
+     * The text section
39
+     *
40
+     */
41
+
42
+    . = ALIGN ( _max_align );
43
+    .text : AT ( _text_lma ) {
44
+	_text = .;
45
+	*(.text)
46
+	*(.text.*)
47
+	_mtext = .;
48
+    } .text_bss (NOLOAD) : {
49
+	_etext = .;
50
+    }
51
+    _text_filesz	= ABSOLUTE ( _mtext - _text );
52
+    _text_memsz		= ABSOLUTE ( _etext - _text );
53
+
54
+    /*
55
+     * The rodata section
56
+     *
57
+     */
58
+
59
+    . = ALIGN ( _max_align );
60
+    .rodata : AT ( _rodata_lma ) {
61
+	_rodata = .;
62
+	*(.rodata)
63
+	*(.rodata.*)
64
+	_mrodata = .;
65
+    } .rodata_bss (NOLOAD) : {
66
+	_erodata = .;
67
+    }
68
+    _rodata_filesz	= ABSOLUTE ( _mrodata - _rodata );
69
+    _rodata_memsz	= ABSOLUTE ( _erodata - _rodata );
70
+
71
+    /*
72
+     * The data section
73
+     *
74
+     */
75
+
76
+    . = ALIGN ( _max_align );
77
+    .data : AT ( _data_lma ) {
78
+	_data = .;
79
+	*(.data)
80
+	*(.data.*)
81
+	*(SORT(.tbl.*))		/* Various tables.  See include/tables.h */
82
+	/* EFI seems to not support proper bss sections */
83
+	*(.bss)
84
+	*(.bss.*)
85
+	*(COMMON)
86
+	*(.stack)
87
+	*(.stack.*)
88
+	_mdata = .;
89
+    } .data_bss (NOLOAD) : {
90
+	_edata = .;
91
+    }
92
+    _data_filesz	= ABSOLUTE ( _mdata - _data );
93
+    _data_memsz		= ABSOLUTE ( _edata - _data );
94
+
95
+    /*
96
+     * The bss section
97
+     *
98
+     */
99
+
100
+    . = ALIGN ( _max_align );
101
+    .bss : AT ( _bss_lma ) {
102
+	_bss = .;
103
+	/* EFI seems to not support proper bss sections */
104
+	_mbss = .;
105
+    } .bss_bss (NOLOAD) : {
106
+	_ebss = .;
107
+    }
108
+    _bss_filesz		= ABSOLUTE ( _mbss - _bss );
109
+    _bss_memsz		= ABSOLUTE ( _ebss - _bss );
110
+
111
+    /*
112
+     * The reloc section
113
+     *
114
+     */
115
+
116
+    . = ALIGN ( _max_align );
117
+    .reloc : AT ( _reloc_lma ) {
118
+	_reloc = .;
119
+	/* Provide some dummy contents to force ld to include this
120
+	 * section.  It will be created by the efilink utility.
121
+	 */
122
+	. += 1;
123
+	_mreloc = .;
124
+    } .reloc_bss (NOLOAD) : {
125
+	_ereloc = .;
126
+    }
127
+    _reloc_filesz	= ABSOLUTE ( _mreloc - _reloc );
128
+    _reloc_memsz	= ABSOLUTE ( _ereloc - _reloc );
129
+
130
+    _filesz		= ABSOLUTE ( . );
131
+
132
+    /*
133
+     * Weak symbols that need zero values if not otherwise defined
134
+     *
135
+     */
136
+
137
+    .weak 0x0 : {
138
+	_weak = .;
139
+	*(.weak)
140
+	_eweak = .;
141
+    }
142
+    _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
143
+
144
+    /*
145
+     * Dispose of the comment and note sections to make the link map
146
+     * easier to read
147
+     *
148
+     */
149
+
150
+    /DISCARD/ : {
151
+	*(.comment)
152
+	*(.note)
153
+    }
154
+
155
+    /*
156
+     * Load address calculations.
157
+     *
158
+     */
159
+
160
+    _prefix_lma		= ABSOLUTE ( _prefix );
161
+    _text_lma		= ABSOLUTE ( _text );
162
+    _rodata_lma		= ABSOLUTE ( _rodata );
163
+    _data_lma		= ABSOLUTE ( _data );
164
+    _bss_lma		= ABSOLUTE ( _bss );
165
+    _reloc_lma		= ABSOLUTE ( _reloc );
166
+
167
+    /*
168
+     * Load addresses required by the prefix
169
+     *
170
+     */
171
+    efi_entry_lma	= ABSOLUTE ( efi_entry );
172
+    debugdir_lma	= ABSOLUTE ( debugdir );
173
+    codeview_rsds_lma	= ABSOLUTE ( codeview_rsds );
174
+}

+ 20
- 0
src/config/defaults/efi.h View File

@@ -0,0 +1,20 @@
1
+#ifndef CONFIG_DEFAULTS_EFI_H
2
+#define CONFIG_DEFAULTS_EFI_H
3
+
4
+/** @file
5
+ *
6
+ * Configuration defaults for EFI
7
+ *
8
+ */
9
+
10
+#define UACCESS_EFI
11
+#define IOAPI_EFI
12
+#define PCIAPI_EFI
13
+#define CONSOLE_EFI
14
+#define TIMER_EFI
15
+#define NAP_EFIX86
16
+#define UMALLOC_EFI
17
+
18
+#define	IMAGE_EFI		/* EFI image support */
19
+
20
+#endif /* CONFIG_DEFAULTS_EFI_H */

+ 1
- 0
src/config/general.h View File

@@ -70,6 +70,7 @@
70 70
 //#define	IMAGE_SCRIPT		/* gPXE script image support */
71 71
 //#define	IMAGE_BZIMAGE		/* Linux bzImage image support */
72 72
 //#define	IMAGE_COMBOOT		/* SYSLINUX COMBOOT image support */
73
+//#define	IMAGE_EFI		/* EFI image support */
73 74
 
74 75
 /*
75 76
  * Command-line commands to include

+ 6
- 0
src/core/config.c View File

@@ -59,6 +59,9 @@ REQUIRE_OBJECT ( pc_kbd );
59 59
 #ifdef CONSOLE_SYSLOG
60 60
 REQUIRE_OBJECT ( syslog );
61 61
 #endif
62
+#ifdef CONSOLE_EFI
63
+REQUIRE_OBJECT ( efi_console );
64
+#endif
62 65
 
63 66
 /*
64 67
  * Drag in all requested network protocols
@@ -158,6 +161,9 @@ REQUIRE_OBJECT ( com32_call );
158 161
 REQUIRE_OBJECT ( com32_wrapper );
159 162
 REQUIRE_OBJECT ( comboot_resolv );
160 163
 #endif
164
+#ifdef IMAGE_EFI
165
+REQUIRE_OBJECT ( efi_image );
166
+#endif
161 167
 
162 168
 /*
163 169
  * Drag in all requested commands

+ 106
- 0
src/image/efi_image.c View File

@@ -0,0 +1,106 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <errno.h>
20
+#include <gpxe/efi/efi.h>
21
+#include <gpxe/image.h>
22
+#include <gpxe/features.h>
23
+
24
+FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
25
+
26
+struct image_type efi_image_type __image_type ( PROBE_NORMAL );
27
+
28
+/**
29
+ * Execute EFI image
30
+ *
31
+ * @v image		EFI image
32
+ * @ret rc		Return status code
33
+ */
34
+static int efi_image_exec ( struct image *image ) {
35
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
36
+	EFI_HANDLE handle;
37
+	UINTN exit_data_size;
38
+	CHAR16 *exit_data;
39
+	EFI_STATUS efirc;
40
+
41
+	/* Attempt loading image */
42
+	if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
43
+				       user_to_virt ( image->data, 0 ),
44
+				       image->len, &handle ) ) != 0 ) {
45
+		/* Not an EFI image */
46
+		DBGC ( image, "EFIIMAGE %p could not load: %lx\n",
47
+		       image, efirc );
48
+		return -ENOEXEC;
49
+	}
50
+
51
+	/* Start the image */
52
+	if ( ( efirc = bs->StartImage ( handle, &exit_data_size,
53
+					&exit_data ) ) != 0 ) {
54
+		DBGC ( image, "EFIIMAGE %p returned with status %lx\n",
55
+		       image, efirc );
56
+		goto done;
57
+	}
58
+
59
+ done:
60
+	/* Unload the image.  We can't leave it loaded, because we
61
+	 * have no "unload" operation.
62
+	 */
63
+	bs->UnloadImage ( handle );
64
+
65
+	return EFIRC_TO_RC ( efirc );
66
+}
67
+
68
+/**
69
+ * Load EFI image into memory
70
+ *
71
+ * @v image		EFI file
72
+ * @ret rc		Return status code
73
+ */
74
+static int efi_image_load ( struct image *image ) {
75
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
76
+	EFI_HANDLE handle;
77
+	EFI_STATUS efirc;
78
+
79
+	/* Attempt loading image */
80
+	if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
81
+				       user_to_virt ( image->data, 0 ),
82
+				       image->len, &handle ) ) != 0 ) {
83
+		/* Not an EFI image */
84
+		DBGC ( image, "EFIIMAGE %p could not load: %lx\n",
85
+		       image, efirc );
86
+		return -ENOEXEC;
87
+	}
88
+
89
+	/* This is an EFI image */
90
+	if ( ! image->type )
91
+		image->type = &efi_image_type;
92
+
93
+	/* Unload the image.  We can't leave it loaded, because we
94
+	 * have no "unload" operation.
95
+	 */
96
+	bs->UnloadImage ( handle );
97
+
98
+	return 0;
99
+}
100
+
101
+/** EFI image type */
102
+struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
103
+	.name = "EFI",
104
+	.load = efi_image_load,
105
+	.exec = efi_image_exec,
106
+};

+ 742
- 0
src/include/gpxe/efi/IndustryStandard/PeImage.h View File

@@ -0,0 +1,742 @@
1
+/** @file
2
+  EFI image format for PE32 and PE32+. Please note some data structures are
3
+  different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
4
+  EFI_IMAGE_NT_HEADERS64 is for PE32+.
5
+
6
+  This file is coded to the Visual Studio, Microsoft Portable Executable and
7
+  Common Object File Format Specification, Revision 8.0 - May 16, 2006.
8
+
9
+  Copyright (c) 2006 - 2007, Intel Corporation
10
+  All rights reserved. This program and the accompanying materials
11
+  are licensed and made available under the terms and conditions of the BSD License
12
+  which accompanies this distribution.  The full text of the license may be found at
13
+  http://opensource.org/licenses/bsd-license.php
14
+
15
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17
+
18
+**/
19
+
20
+#ifndef __EFI_IMAGE_H__
21
+#define __EFI_IMAGE_H__
22
+
23
+//
24
+// PE32+ Subsystem type for EFI images
25
+//
26
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION         10
27
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
28
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
29
+#define EFI_IMAGE_SUBSYSTEM_EFI_EFI_ROM             13
30
+
31
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13
32
+
33
+
34
+//
35
+// PE32+ Machine type for EFI images
36
+//
37
+#define IMAGE_FILE_MACHINE_I386     0x014c
38
+#define IMAGE_FILE_MACHINE_IA64     0x0200
39
+#define IMAGE_FILE_MACHINE_EBC      0x0EBC
40
+#define IMAGE_FILE_MACHINE_X64      0x8664
41
+//
42
+// Support old names for backward compatible
43
+//
44
+#define EFI_IMAGE_MACHINE_IA32      IMAGE_FILE_MACHINE_I386
45
+#define EFI_IMAGE_MACHINE_IA64      IMAGE_FILE_MACHINE_IA64
46
+#define EFI_IMAGE_MACHINE_IPF       IMAGE_FILE_MACHINE_IA64
47
+#define EFI_IMAGE_MACHINE_EBC       IMAGE_FILE_MACHINE_EBC
48
+#define EFI_IMAGE_MACHINE_X64       IMAGE_FILE_MACHINE_X64
49
+
50
+#define EFI_IMAGE_DOS_SIGNATURE     0x5A4D      // MZ
51
+#define EFI_IMAGE_OS2_SIGNATURE     0x454E      // NE
52
+#define EFI_IMAGE_OS2_SIGNATURE_LE  0x454C      // LE
53
+#define EFI_IMAGE_NT_SIGNATURE      0x00004550  // PE00
54
+
55
+///
56
+/// PE images can start with an optional DOS header, so if an image is run
57
+///  under DOS it can print an error message.
58
+///
59
+typedef struct {
60
+  UINT16  e_magic;    // Magic number
61
+  UINT16  e_cblp;     // Bytes on last page of file
62
+  UINT16  e_cp;       // Pages in file
63
+  UINT16  e_crlc;     // Relocations
64
+  UINT16  e_cparhdr;  // Size of header in paragraphs
65
+  UINT16  e_minalloc; // Minimum extra paragraphs needed
66
+  UINT16  e_maxalloc; // Maximum extra paragraphs needed
67
+  UINT16  e_ss;       // Initial (relative) SS value
68
+  UINT16  e_sp;       // Initial SP value
69
+  UINT16  e_csum;     // Checksum
70
+  UINT16  e_ip;       // Initial IP value
71
+  UINT16  e_cs;       // Initial (relative) CS value
72
+  UINT16  e_lfarlc;   // File address of relocation table
73
+  UINT16  e_ovno;     // Overlay number
74
+  UINT16  e_res[4];   // Reserved words
75
+  UINT16  e_oemid;    // OEM identifier (for e_oeminfo)
76
+  UINT16  e_oeminfo;  // OEM information; e_oemid specific
77
+  UINT16  e_res2[10]; // Reserved words
78
+  UINT32  e_lfanew;   // File address of new exe header
79
+} EFI_IMAGE_DOS_HEADER;
80
+
81
+///
82
+/// File header format.
83
+///
84
+typedef struct {
85
+  UINT16  Machine;
86
+  UINT16  NumberOfSections;
87
+  UINT32  TimeDateStamp;
88
+  UINT32  PointerToSymbolTable;
89
+  UINT32  NumberOfSymbols;
90
+  UINT16  SizeOfOptionalHeader;
91
+  UINT16  Characteristics;
92
+} EFI_IMAGE_FILE_HEADER;
93
+
94
+#define EFI_IMAGE_SIZEOF_FILE_HEADER        20
95
+
96
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED      0x0001  // Relocation info stripped from file.
97
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE     0x0002  // File is executable  (i.e. no unresolved externel references).
98
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004  // Line nunbers stripped from file.
99
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008  // Local symbols stripped from file.
100
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO    0x0080  // Bytes of machine word are reversed.
101
+#define EFI_IMAGE_FILE_32BIT_MACHINE        0x0100  // 32 bit word machine.
102
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED       0x0200  // Debugging info stripped from file in .DBG file
103
+#define EFI_IMAGE_FILE_SYSTEM               0x1000  // System File.
104
+#define EFI_IMAGE_FILE_DLL                  0x2000  // File is a DLL.
105
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI    0x8000  // Bytes of machine word are reversed.
106
+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN      0
107
+#define EFI_IMAGE_FILE_MACHINE_I386         0x14c   // Intel 386.
108
+#define EFI_IMAGE_FILE_MACHINE_R3000        0x162   // MIPS* little-endian, 0540 big-endian
109
+#define EFI_IMAGE_FILE_MACHINE_R4000        0x166   // MIPS* little-endian
110
+#define EFI_IMAGE_FILE_MACHINE_ALPHA        0x184   // Alpha_AXP*
111
+#define EFI_IMAGE_FILE_MACHINE_POWERPC      0x1F0   // IBM* PowerPC Little-Endian
112
+#define EFI_IMAGE_FILE_MACHINE_TAHOE        0x7cc   // Intel EM machine
113
+//
114
+// * Other names and brands may be claimed as the property of others.
115
+//
116
+
117
+///
118
+/// Directory format.
119
+///
120
+typedef struct {
121
+  UINT32  VirtualAddress;
122
+  UINT32  Size;
123
+} EFI_IMAGE_DATA_DIRECTORY;
124
+
125
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
126
+
127
+typedef struct {
128
+  UINT16  Magic;
129
+  UINT8   MajorLinkerVersion;
130
+  UINT8   MinorLinkerVersion;
131
+  UINT32  SizeOfCode;
132
+  UINT32  SizeOfInitializedData;
133
+  UINT32  SizeOfUninitializedData;
134
+  UINT32  AddressOfEntryPoint;
135
+  UINT32  BaseOfCode;
136
+  UINT32  BaseOfData;
137
+  UINT32  BaseOfBss;
138
+  UINT32  GprMask;
139
+  UINT32  CprMask[4];
140
+  UINT32  GpValue;
141
+} EFI_IMAGE_ROM_OPTIONAL_HEADER;
142
+
143
+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC      0x107
144
+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER  sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)
145
+
146
+typedef struct {
147
+  EFI_IMAGE_FILE_HEADER         FileHeader;
148
+  EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
149
+} EFI_IMAGE_ROM_HEADERS;
150
+
151
+///
152
+/// @attention
153
+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
154
+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
155
+/// after NT additional fields.
156
+///
157
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
158
+
159
+typedef struct {
160
+  ///
161
+  /// Standard fields.
162
+  ///
163
+  UINT16                    Magic;
164
+  UINT8                     MajorLinkerVersion;
165
+  UINT8                     MinorLinkerVersion;
166
+  UINT32                    SizeOfCode;
167
+  UINT32                    SizeOfInitializedData;
168
+  UINT32                    SizeOfUninitializedData;
169
+  UINT32                    AddressOfEntryPoint;
170
+  UINT32                    BaseOfCode;
171
+  UINT32                    BaseOfData;
172
+  ///
173
+  /// NT additional fields.
174
+  ///
175
+  UINT32                    ImageBase;
176
+  UINT32                    SectionAlignment;
177
+  UINT32                    FileAlignment;
178
+  UINT16                    MajorOperatingSystemVersion;
179
+  UINT16                    MinorOperatingSystemVersion;
180
+  UINT16                    MajorImageVersion;
181
+  UINT16                    MinorImageVersion;
182
+  UINT16                    MajorSubsystemVersion;
183
+  UINT16                    MinorSubsystemVersion;
184
+  UINT32                    Win32VersionValue;
185
+  UINT32                    SizeOfImage;
186
+  UINT32                    SizeOfHeaders;
187
+  UINT32                    CheckSum;
188
+  UINT16                    Subsystem;
189
+  UINT16                    DllCharacteristics;
190
+  UINT32                    SizeOfStackReserve;
191
+  UINT32                    SizeOfStackCommit;
192
+  UINT32                    SizeOfHeapReserve;
193
+  UINT32                    SizeOfHeapCommit;
194
+  UINT32                    LoaderFlags;
195
+  UINT32                    NumberOfRvaAndSizes;
196
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
197
+} EFI_IMAGE_OPTIONAL_HEADER32;
198
+
199
+///
200
+/// @attention
201
+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
202
+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
203
+/// after NT additional fields.
204
+///
205
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
206
+
207
+typedef struct {
208
+  //
209
+  // Standard fields.
210
+  //
211
+  UINT16                    Magic;
212
+  UINT8                     MajorLinkerVersion;
213
+  UINT8                     MinorLinkerVersion;
214
+  UINT32                    SizeOfCode;
215
+  UINT32                    SizeOfInitializedData;
216
+  UINT32                    SizeOfUninitializedData;
217
+  UINT32                    AddressOfEntryPoint;
218
+  UINT32                    BaseOfCode;
219
+  //
220
+  // NT additional fields.
221
+  //
222
+  UINT64                    ImageBase;
223
+  UINT32                    SectionAlignment;
224
+  UINT32                    FileAlignment;
225
+  UINT16                    MajorOperatingSystemVersion;
226
+  UINT16                    MinorOperatingSystemVersion;
227
+  UINT16                    MajorImageVersion;
228
+  UINT16                    MinorImageVersion;
229
+  UINT16                    MajorSubsystemVersion;
230
+  UINT16                    MinorSubsystemVersion;
231
+  UINT32                    Win32VersionValue;
232
+  UINT32                    SizeOfImage;
233
+  UINT32                    SizeOfHeaders;
234
+  UINT32                    CheckSum;
235
+  UINT16                    Subsystem;
236
+  UINT16                    DllCharacteristics;
237
+  UINT64                    SizeOfStackReserve;
238
+  UINT64                    SizeOfStackCommit;
239
+  UINT64                    SizeOfHeapReserve;
240
+  UINT64                    SizeOfHeapCommit;
241
+  UINT32                    LoaderFlags;
242
+  UINT32                    NumberOfRvaAndSizes;
243
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
244
+} EFI_IMAGE_OPTIONAL_HEADER64;
245
+
246
+
247
+///
248
+/// @attention
249
+/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY
250
+/// by tools.  All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!
251
+///
252
+typedef struct {
253
+  UINT32                      Signature;
254
+  EFI_IMAGE_FILE_HEADER       FileHeader;
255
+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
256
+} EFI_IMAGE_NT_HEADERS32;
257
+
258
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
259
+
260
+typedef struct {
261
+  UINT32                      Signature;
262
+  EFI_IMAGE_FILE_HEADER       FileHeader;
263
+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
264
+} EFI_IMAGE_NT_HEADERS64;
265
+
266
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
267
+
268
+
269
+//
270
+// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the
271
+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build.  Same for
272
+// EFI_IMAGE_NT_HEADERS.  These definitions MUST be used by ALL EFI code.
273
+//
274
+#if   defined (MDE_CPU_IA32)
275
+
276
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
277
+  (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
278
+
279
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
280
+
281
+//
282
+// @bug - Remove me when other package updated.
283
+//
284
+typedef EFI_IMAGE_NT_HEADERS32    EFI_IMAGE_NT_HEADERS;
285
+
286
+#elif defined (MDE_CPU_IPF)
287
+
288
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
289
+  (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
290
+
291
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
292
+
293
+//
294
+// @bug - Remove me when other package updated.
295
+//
296
+typedef EFI_IMAGE_NT_HEADERS64    EFI_IMAGE_NT_HEADERS;
297
+
298
+#elif defined (MDE_CPU_X64)
299
+
300
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
301
+  (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
302
+
303
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
304
+
305
+//
306
+// @bug - Remove me when other package updated.
307
+//
308
+typedef EFI_IMAGE_NT_HEADERS64    EFI_IMAGE_NT_HEADERS;
309
+
310
+#elif defined (MDE_CPU_EBC)
311
+
312
+///
313
+/// This is just to make sure you can cross compile with the EBC compiiler.
314
+/// It does not make sense to have a PE loader coded in EBC. You need to
315
+/// understand the basic
316
+///
317
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC)
318
+
319
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
320
+
321
+//
322
+// @bug - Remove me when other package updated.
323
+//
324
+typedef EFI_IMAGE_NT_HEADERS64    EFI_IMAGE_NT_HEADERS;
325
+
326
+#else
327
+#error Unknown Processor Type
328
+#endif
329
+
330
+
331
+#define EFI_IMAGE_FIRST_SECTION(ntheader) \
332
+    ( \
333
+      (EFI_IMAGE_SECTION_HEADER *) \
334
+        ( \
335
+          (UINT32) ntheader + \
336
+          FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \
337
+          ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \
338
+        ) \
339
+    )
340
+
341
+//
342
+// Subsystem Values
343
+//
344
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN     0
345
+#define EFI_IMAGE_SUBSYSTEM_NATIVE      1
346
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
347
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.
348
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI     5
349
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI   7
350
+
351
+//
352
+// Directory Entries
353
+//
354
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT      0
355
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT      1
356
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE    2
357
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION   3
358
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY    4
359
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC   5
360
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG       6
361
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT   7
362
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR   8
363
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS         9
364
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
365
+
366
+//
367
+// Section header format.
368
+//
369
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
370
+
371
+typedef struct {
372
+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
373
+  union {
374
+    UINT32  PhysicalAddress;
375
+    UINT32  VirtualSize;
376
+  } Misc;
377
+  UINT32  VirtualAddress;
378
+  UINT32  SizeOfRawData;
379
+  UINT32  PointerToRawData;
380
+  UINT32  PointerToRelocations;
381
+  UINT32  PointerToLinenumbers;
382
+  UINT16  NumberOfRelocations;
383
+  UINT16  NumberOfLinenumbers;
384
+  UINT32  Characteristics;
385
+} EFI_IMAGE_SECTION_HEADER;
386
+
387
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER       40
388
+
389
+#define EFI_IMAGE_SCN_TYPE_NO_PAD             0x00000008  // Reserved.
390
+#define EFI_IMAGE_SCN_CNT_CODE                0x00000020
391
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA    0x00000040
392
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA  0x00000080
393
+
394
+#define EFI_IMAGE_SCN_LNK_OTHER               0x00000100  // Reserved.
395
+#define EFI_IMAGE_SCN_LNK_INFO                0x00000200  // Section contains comments or some other type of information.
396
+#define EFI_IMAGE_SCN_LNK_REMOVE              0x00000800  // Section contents will not become part of image.
397
+#define EFI_IMAGE_SCN_LNK_COMDAT              0x00001000
398
+
399
+#define EFI_IMAGE_SCN_ALIGN_1BYTES            0x00100000
400
+#define EFI_IMAGE_SCN_ALIGN_2BYTES            0x00200000
401
+#define EFI_IMAGE_SCN_ALIGN_4BYTES            0x00300000
402
+#define EFI_IMAGE_SCN_ALIGN_8BYTES            0x00400000
403
+#define EFI_IMAGE_SCN_ALIGN_16BYTES           0x00500000
404
+#define EFI_IMAGE_SCN_ALIGN_32BYTES           0x00600000
405
+#define EFI_IMAGE_SCN_ALIGN_64BYTES           0x00700000
406
+
407
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE         0x02000000
408
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED          0x04000000
409
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED           0x08000000
410
+#define EFI_IMAGE_SCN_MEM_SHARED              0x10000000
411
+#define EFI_IMAGE_SCN_MEM_EXECUTE             0x20000000
412
+#define EFI_IMAGE_SCN_MEM_READ                0x40000000
413
+#define EFI_IMAGE_SCN_MEM_WRITE               0x80000000
414
+
415
+///
416
+/// Symbol format.
417
+///
418
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
419
+
420
+//
421
+// Section values.
422
+//
423
+// Symbols have a section number of the section in which they are
424
+// defined. Otherwise, section numbers have the following meanings:
425
+//
426
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0  // Symbol is undefined or is common.
427
+#define EFI_IMAGE_SYM_ABSOLUTE  (UINT16) -1 // Symbol is an absolute value.
428
+#define EFI_IMAGE_SYM_DEBUG     (UINT16) -2 // Symbol is a special debug item.
429
+//
430
+// Type (fundamental) values.
431
+//
432
+#define EFI_IMAGE_SYM_TYPE_NULL   0   // no type.
433
+#define EFI_IMAGE_SYM_TYPE_VOID   1   //
434
+#define EFI_IMAGE_SYM_TYPE_CHAR   2   // type character.
435
+#define EFI_IMAGE_SYM_TYPE_SHORT  3   // type short integer.
436
+#define EFI_IMAGE_SYM_TYPE_INT    4
437
+#define EFI_IMAGE_SYM_TYPE_LONG   5
438
+#define EFI_IMAGE_SYM_TYPE_FLOAT  6
439
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
440
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
441
+#define EFI_IMAGE_SYM_TYPE_UNION  9
442
+#define EFI_IMAGE_SYM_TYPE_ENUM   10  // enumeration.
443
+#define EFI_IMAGE_SYM_TYPE_MOE    11  // member of enumeration.
444
+#define EFI_IMAGE_SYM_TYPE_BYTE   12
445
+#define EFI_IMAGE_SYM_TYPE_WORD   13
446
+#define EFI_IMAGE_SYM_TYPE_UINT   14
447
+#define EFI_IMAGE_SYM_TYPE_DWORD  15
448
+
449
+//
450
+// Type (derived) values.
451
+//
452
+#define EFI_IMAGE_SYM_DTYPE_NULL      0 // no derived type.
453
+#define EFI_IMAGE_SYM_DTYPE_POINTER   1
454
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION  2
455
+#define EFI_IMAGE_SYM_DTYPE_ARRAY     3
456
+
457
+//
458
+// Storage classes.
459
+//
460
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION   (UINT8) -1
461
+#define EFI_IMAGE_SYM_CLASS_NULL              0
462
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC         1
463
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL          2
464
+#define EFI_IMAGE_SYM_CLASS_STATIC            3
465
+#define EFI_IMAGE_SYM_CLASS_REGISTER          4
466
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF      5
467
+#define EFI_IMAGE_SYM_CLASS_LABEL             6
468
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL   7
469
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT  8
470
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT          9
471
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG        10
472
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION   11
473
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG         12
474
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION   13
475
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC  14
476
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG          15
477
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM    16
478
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM    17
479
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD         18
480
+#define EFI_IMAGE_SYM_CLASS_BLOCK             100
481
+#define EFI_IMAGE_SYM_CLASS_FUNCTION          101
482
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT     102
483
+#define EFI_IMAGE_SYM_CLASS_FILE              103
484
+#define EFI_IMAGE_SYM_CLASS_SECTION           104
485
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL     105
486
+
487
+//
488
+// type packing constants
489
+//
490
+#define EFI_IMAGE_N_BTMASK  017
491
+#define EFI_IMAGE_N_TMASK   060
492
+#define EFI_IMAGE_N_TMASK1  0300
493
+#define EFI_IMAGE_N_TMASK2  0360
494
+#define EFI_IMAGE_N_BTSHFT  4
495
+#define EFI_IMAGE_N_TSHIFT  2
496
+
497
+//
498
+// Communal selection types.
499
+//
500
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES    1
501
+#define EFI_IMAGE_COMDAT_SELECT_ANY             2
502
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE       3
503
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH     4
504
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE     5
505
+
506
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1
507
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2
508
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3
509
+
510
+///
511
+/// Relocation format.
512
+///
513
+typedef struct {
514
+  UINT32  VirtualAddress;
515
+  UINT32  SymbolTableIndex;
516
+  UINT16  Type;
517
+} EFI_IMAGE_RELOCATION;
518
+
519
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
520
+
521
+//
522
+// I386 relocation types.
523
+//
524
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000   // Reference is absolute, no relocation is necessary
525
+#define EFI_IMAGE_REL_I386_DIR16    0x0001  // Direct 16-bit reference to the symbols virtual address
526
+#define EFI_IMAGE_REL_I386_REL16    0x0002  // PC-relative 16-bit reference to the symbols virtual address
527
+#define EFI_IMAGE_REL_I386_DIR32    0x0006  // Direct 32-bit reference to the symbols virtual address
528
+#define EFI_IMAGE_REL_I386_DIR32NB  0x0007  // Direct 32-bit reference to the symbols virtual address, base not included
529
+#define EFI_IMAGE_REL_I386_SEG12    0x0009 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
530
+#define EFI_IMAGE_REL_I386_SECTION  0x001a
531
+#define EFI_IMAGE_REL_I386_SECREL   0x000b
532
+#define EFI_IMAGE_REL_I386_REL32    0x0014 // PC-relative 32-bit reference to the symbols virtual address
533
+
534
+//
535
+// x64 processor relocation types.
536
+//
537
+#define IMAGE_REL_AMD64_ABSOLUTE	0x0000
538
+#define IMAGE_REL_AMD64_ADDR64	  0x0001
539
+#define IMAGE_REL_AMD64_ADDR32	  0x0002
540
+#define IMAGE_REL_AMD64_ADDR32NB	0x0003
541
+#define IMAGE_REL_AMD64_REL32	    0x0004
542
+#define IMAGE_REL_AMD64_REL32_1	  0x0005
543
+#define IMAGE_REL_AMD64_REL32_2	  0x0006
544
+#define IMAGE_REL_AMD64_REL32_3	  0x0007
545
+#define IMAGE_REL_AMD64_REL32_4	  0x0008
546
+#define IMAGE_REL_AMD64_REL32_5	  0x0009
547
+#define IMAGE_REL_AMD64_SECTION	  0x000A
548
+#define IMAGE_REL_AMD64_SECREL	  0x000B
549
+#define IMAGE_REL_AMD64_SECREL7	  0x000C
550
+#define IMAGE_REL_AMD64_TOKEN	    0x000D
551
+#define IMAGE_REL_AMD64_SREL32	  0x000E
552
+#define IMAGE_REL_AMD64_PAIR	    0x000F
553
+#define IMAGE_REL_AMD64_SSPAN32	  0x0010
554
+
555
+///
556
+/// Based relocation format.
557
+///
558
+typedef struct {
559
+  UINT32  VirtualAddress;
560
+  UINT32  SizeOfBlock;
561
+} EFI_IMAGE_BASE_RELOCATION;
562
+
563
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION  8
564
+
565
+//
566
+// Based relocation types.
567
+//
568
+#define EFI_IMAGE_REL_BASED_ABSOLUTE      0
569
+#define EFI_IMAGE_REL_BASED_HIGH          1
570
+#define EFI_IMAGE_REL_BASED_LOW           2
571
+#define EFI_IMAGE_REL_BASED_HIGHLOW       3
572
+#define EFI_IMAGE_REL_BASED_HIGHADJ       4
573
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR  5
574
+#define EFI_IMAGE_REL_BASED_IA64_IMM64    9
575
+#define EFI_IMAGE_REL_BASED_DIR64         10
576
+
577
+///
578
+/// Line number format.
579
+///
580
+typedef struct {
581
+  union {
582
+    UINT32  SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
583
+    UINT32  VirtualAddress;   // Virtual address of line number.
584
+  } Type;
585
+  UINT16  Linenumber;         // Line number.
586
+} EFI_IMAGE_LINENUMBER;
587
+
588
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
589
+
590
+//
591
+// Archive format.
592
+//
593
+#define EFI_IMAGE_ARCHIVE_START_SIZE        8
594
+#define EFI_IMAGE_ARCHIVE_START             "!<arch>\n"
595
+#define EFI_IMAGE_ARCHIVE_END               "`\n"
596
+#define EFI_IMAGE_ARCHIVE_PAD               "\n"
597
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER     "/               "
598
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER  "//              "
599
+
600
+typedef struct {
601
+  UINT8 Name[16];     // File member name - `/' terminated.
602
+  UINT8 Date[12];     // File member date - decimal.
603
+  UINT8 UserID[6];    // File member user id - decimal.
604
+  UINT8 GroupID[6];   // File member group id - decimal.
605
+  UINT8 Mode[8];      // File member mode - octal.
606
+  UINT8 Size[10];     // File member size - decimal.
607
+  UINT8 EndHeader[2]; // String to end header.
608
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
609
+
610
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
611
+
612
+//
613
+// DLL support.
614
+//
615
+
616
+///
617
+/// DLL Export Format
618
+///
619
+typedef struct {
620
+  UINT32  Characteristics;
621
+  UINT32  TimeDateStamp;
622
+  UINT16  MajorVersion;
623
+  UINT16  MinorVersion;
624
+  UINT32  Name;
625
+  UINT32  Base;
626
+  UINT32  NumberOfFunctions;
627
+  UINT32  NumberOfNames;
628
+  UINT32  AddressOfFunctions;
629
+  UINT32  AddressOfNames;
630
+  UINT32  AddressOfNameOrdinals;
631
+} EFI_IMAGE_EXPORT_DIRECTORY;
632
+
633
+///
634
+/// DLL support.
635
+/// Import Format
636
+///
637
+typedef struct {
638
+  UINT16  Hint;
639
+  UINT8   Name[1];
640
+} EFI_IMAGE_IMPORT_BY_NAME;
641
+
642
+typedef struct {
643
+  union {
644
+    UINT32                    Function;
645
+    UINT32                    Ordinal;
646
+    EFI_IMAGE_IMPORT_BY_NAME  *AddressOfData;
647
+  } u1;
648
+} EFI_IMAGE_THUNK_DATA;
649
+
650
+#define EFI_IMAGE_ORDINAL_FLAG              0x80000000
651
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal)  ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
652
+#define EFI_IMAGE_ORDINAL(Ordinal)          (Ordinal & 0xffff)
653
+
654
+typedef struct {
655
+  UINT32                Characteristics;
656
+  UINT32                TimeDateStamp;
657
+  UINT32                ForwarderChain;
658
+  UINT32                Name;
659
+  EFI_IMAGE_THUNK_DATA  *FirstThunk;
660
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
661
+
662
+///
663
+/// Debug Format
664
+///
665
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2
666
+
667
+typedef struct {
668
+  UINT32  Characteristics;
669
+  UINT32  TimeDateStamp;
670
+  UINT16  MajorVersion;
671
+  UINT16  MinorVersion;
672
+  UINT32  Type;
673
+  UINT32  SizeOfData;
674
+  UINT32  RVA;
675
+  UINT32  FileOffset;
676
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
677
+
678
+#define CODEVIEW_SIGNATURE_NB10 0x3031424E  // "NB10"
679
+typedef struct {
680
+  UINT32  Signature;                        // "NB10"
681
+  UINT32  Unknown;
682
+  UINT32  Unknown2;
683
+  UINT32  Unknown3;
684
+  //
685
+  // Filename of .PDB goes here
686
+  //
687
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
688
+
689
+#define CODEVIEW_SIGNATURE_RSDS 0x53445352  // "RSDS"
690
+typedef struct {
691
+  UINT32  Signature;                        // "RSDS"
692
+  UINT32  Unknown;
693
+  UINT32  Unknown2;
694
+  UINT32  Unknown3;
695
+  UINT32  Unknown4;
696
+  UINT32  Unknown5;
697
+  //
698
+  // Filename of .PDB goes here
699
+  //
700
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
701
+
702
+///
703
+/// Header format for TE images
704
+///
705
+typedef struct {
706
+  UINT16                    Signature;            // signature for TE format = "VZ"
707
+  UINT16                    Machine;              // from the original file header
708
+  UINT8                     NumberOfSections;     // from the original file header
709
+  UINT8                     Subsystem;            // from original optional header
710
+  UINT16                    StrippedSize;         // how many bytes we removed from the header
711
+  UINT32                    AddressOfEntryPoint;  // offset to entry point -- from original optional header
712
+  UINT32                    BaseOfCode;           // from original image -- required for ITP debug
713
+  UINT64                    ImageBase;            // from original file header
714
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[2];     // only base relocation and debug directory
715
+} EFI_TE_IMAGE_HEADER;
716
+
717
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56      // "VZ"
718
+
719
+//
720
+// Data directory indexes in our TE image header
721
+//
722
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0
723
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1
724
+
725
+
726
+///
727
+/// Union of PE32, PE32+, and TE headers
728
+///
729
+typedef union {
730
+  EFI_IMAGE_NT_HEADERS32   Pe32;
731
+  EFI_IMAGE_NT_HEADERS64   Pe32Plus;
732
+  EFI_TE_IMAGE_HEADER      Te;
733
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
734
+
735
+typedef union {
736
+  EFI_IMAGE_NT_HEADERS32            *Pe32;
737
+  EFI_IMAGE_NT_HEADERS64            *Pe32Plus;
738
+  EFI_TE_IMAGE_HEADER               *Te;
739
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   *Union;
740
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
741
+
742
+#endif

+ 326
- 0
src/include/gpxe/efi/Protocol/Cpu.h View File

@@ -0,0 +1,326 @@
1
+/** @file
2
+  CPU Architectural Protocol as defined in PI spec Volume 2 DXE
3
+
4
+  This code abstracts the DXE core from processor implementation details.
5
+
6
+  Copyright (c) 2006 - 2008, Intel Corporation
7
+  All rights reserved. This program and the accompanying materials
8
+  are licensed and made available under the terms and conditions of the BSD License
9
+  which accompanies this distribution.  The full text of the license may be found at
10
+  http://opensource.org/licenses/bsd-license.php
11
+
12
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
+
15
+**/
16
+
17
+#ifndef __ARCH_PROTOCOL_CPU_H__
18
+#define __ARCH_PROTOCOL_CPU_H__
19
+
20
+#include <gpxe/efi/Protocol/DebugSupport.h>
21
+
22
+#define EFI_CPU_ARCH_PROTOCOL_GUID \
23
+  { 0x26baccb1, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } }
24
+
25
+typedef struct _EFI_CPU_ARCH_PROTOCOL   EFI_CPU_ARCH_PROTOCOL;
26
+
27
+typedef enum {
28
+  EfiCpuFlushTypeWriteBackInvalidate,
29
+  EfiCpuFlushTypeWriteBack,
30
+  EfiCpuFlushTypeInvalidate,
31
+  EfiCpuMaxFlushType
32
+} EFI_CPU_FLUSH_TYPE;
33
+
34
+typedef enum {
35
+  EfiCpuInit,
36
+  EfiCpuMaxInitType
37
+} EFI_CPU_INIT_TYPE;
38
+
39
+/**
40
+  EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
41
+
42
+  @param  InterruptType    Defines the type of interrupt or exception that
43
+                           occurred on the processor.This parameter is processor architecture specific.
44
+  @param  SystemContext    A pointer to the processor context when
45
+                           the interrupt occurred on the processor.
46
+
47
+  @return None
48
+
49
+**/
50
+typedef
51
+VOID
52
+(EFIAPI *EFI_CPU_INTERRUPT_HANDLER)(
53
+  IN CONST  EFI_EXCEPTION_TYPE  InterruptType,
54
+  IN CONST  EFI_SYSTEM_CONTEXT  SystemContext
55
+  );
56
+
57
+/**
58
+  This function flushes the range of addresses from Start to Start+Length
59
+  from the processor's data cache. If Start is not aligned to a cache line
60
+  boundary, then the bytes before Start to the preceding cache line boundary
61
+  are also flushed. If Start+Length is not aligned to a cache line boundary,
62
+  then the bytes past Start+Length to the end of the next cache line boundary
63
+  are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
64
+  supported. If the data cache is fully coherent with all DMA operations, then
65
+  this function can just return EFI_SUCCESS. If the processor does not support
66
+  flushing a range of the data cache, then the entire data cache can be flushed.
67
+
68
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
69
+  @param  Start            The beginning physical address to flush from the processor's data
70
+                           cache.
71
+  @param  Length           The number of bytes to flush from the processor's data cache. This
72
+                           function may flush more bytes than Length specifies depending upon
73
+                           the granularity of the flush operation that the processor supports.
74
+  @param  FlushType        Specifies the type of flush operation to perform.
75
+
76
+  @retval EFI_SUCCESS           The address range from Start to Start+Length was flushed from
77
+                                the processor's data cache.
78
+  @retval EFI_UNSUPPORTEDT      The processor does not support the cache flush type specified
79
+                                by FlushType.
80
+  @retval EFI_DEVICE_ERROR      The address range from Start to Start+Length could not be flushed
81
+                                from the processor's data cache.
82
+
83
+**/
84
+typedef
85
+EFI_STATUS
86
+(EFIAPI *EFI_CPU_FLUSH_DATA_CACHE)(
87
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
88
+  IN EFI_PHYSICAL_ADDRESS               Start,
89
+  IN UINT64                             Length,
90
+  IN EFI_CPU_FLUSH_TYPE                 FlushType
91
+  );
92
+
93
+
94
+/**
95
+  This function enables interrupt processing by the processor.
96
+
97
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
98
+
99
+  @retval EFI_SUCCESS           Interrupts are enabled on the processor.
100
+  @retval EFI_DEVICE_ERROR      Interrupts could not be enabled on the processor.
101
+
102
+**/
103
+typedef
104
+EFI_STATUS
105
+(EFIAPI *EFI_CPU_ENABLE_INTERRUPT)(
106
+  IN EFI_CPU_ARCH_PROTOCOL              *This
107
+  );
108
+
109
+
110
+/**
111
+  This function disables interrupt processing by the processor.
112
+
113
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
114
+
115
+  @retval EFI_SUCCESS           Interrupts are disabled on the processor.
116
+  @retval EFI_DEVICE_ERROR      Interrupts could not be disabled on the processor.
117
+
118
+**/
119
+typedef
120
+EFI_STATUS
121
+(EFIAPI *EFI_CPU_DISABLE_INTERRUPT)(
122
+  IN EFI_CPU_ARCH_PROTOCOL              *This
123
+  );
124
+
125
+
126
+/**
127
+  This function retrieves the processor's current interrupt state a returns it in
128
+  State. If interrupts are currently enabled, then TRUE is returned. If interrupts
129
+  are currently disabled, then FALSE is returned.
130
+
131
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
132
+  @param  State            A pointer to the processor's current interrupt state. Set to TRUE if
133
+                           interrupts are enabled and FALSE if interrupts are disabled.
134
+
135
+  @retval EFI_SUCCESS           The processor's current interrupt state was returned in State.
136
+  @retval EFI_INVALID_PARAMETER State is NULL.
137
+
138
+**/
139
+typedef
140
+EFI_STATUS
141
+(EFIAPI *EFI_CPU_GET_INTERRUPT_STATE)(
142
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
143
+  OUT BOOLEAN                           *State
144
+  );
145
+
146
+
147
+/**
148
+  This function generates an INIT on the processor. If this function succeeds, then the
149
+  processor will be reset, and control will not be returned to the caller. If InitType is
150
+  not supported by this processor, or the processor cannot programmatically generate an
151
+  INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
152
+  occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
153
+
154
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
155
+  @param  InitType         The type of processor INIT to perform.
156
+
157
+  @retval EFI_SUCCESS           The processor INIT was performed. This return code should never be seen.
158
+  @retval EFI_UNSUPPORTED       The processor INIT operation specified by InitType is not supported
159
+                                by this processor.
160
+  @retval EFI_DEVICE_ERROR      The processor INIT failed.
161
+
162
+**/
163
+typedef
164
+EFI_STATUS
165
+(EFIAPI *EFI_CPU_INIT)(
166
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
167
+  IN EFI_CPU_INIT_TYPE                  InitType
168
+  );
169
+
170
+
171
+/**
172
+  This function registers and enables the handler specified by InterruptHandler for a processor
173
+  interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
174
+  handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
175
+  The installed handler is called once for each processor interrupt or exception.
176
+
177
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
178
+  @param  InterruptType    A pointer to the processor's current interrupt state. Set to TRUE if interrupts
179
+                           are enabled and FALSE if interrupts are disabled.
180
+  @param  InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
181
+                           when a processor interrupt occurs. If this parameter is NULL, then the handler
182
+                           will be uninstalled.
183
+
184
+  @retval EFI_SUCCESS           The handler for the processor interrupt was successfully installed or uninstalled.
185
+  @retval EFI_ALREADY_STARTED   InterruptHandler is not NULL, and a handler for InterruptType was
186
+                                previously installed.
187
+  @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
188
+                                previously installed.
189
+  @retval EFI_UNSUPPORTED       The interrupt specified by InterruptType is not supported.
190
+
191
+**/
192
+typedef
193
+EFI_STATUS
194
+(EFIAPI *EFI_CPU_REGISTER_INTERRUPT_HANDLER)(
195
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
196
+  IN EFI_EXCEPTION_TYPE                 InterruptType,
197
+  IN EFI_CPU_INTERRUPT_HANDLER          InterruptHandler
198
+  );
199
+
200
+
201
+/**
202
+  This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
203
+
204
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
205
+  @param  TimerIndex       Specifies which processor timer is to be returned in TimerValue. This parameter
206
+                           must be between 0 and NumberOfTimers-1.
207
+  @param  TimerValue       Pointer to the returned timer value.
208
+  @param  TimerPeriod      A pointer to the amount of time that passes in femtoseconds for each increment
209
+                           of TimerValue.
210
+
211
+  @retval EFI_SUCCESS           The processor timer value specified by TimerIndex was returned in TimerValue.
212
+  @retval EFI_DEVICE_ERROR      An error occurred attempting to read one of the processor's timers.
213
+  @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
214
+  @retval EFI_UNSUPPORTED       The processor does not have any readable timers.
215
+
216
+**/
217
+typedef
218
+EFI_STATUS
219
+(EFIAPI *EFI_CPU_GET_TIMER_VALUE)(
220
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
221
+  IN UINT32                             TimerIndex,
222
+  OUT UINT64                            *TimerValue,
223
+  OUT UINT64                            *TimerPeriod OPTIONAL
224
+  );
225
+
226
+
227
+/**
228
+  This function modifies the attributes for the memory region specified by BaseAddress and
229
+  Length from their current attributes to the attributes specified by Attributes.
230
+
231
+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
232
+  @param  BaseAddress      The physical address that is the start address of a memory region.
233
+  @param  Length           The size in bytes of the memory region.
234
+  @param  Attributes       The bit mask of attributes to set for the memory region.
235
+
236
+  @retval EFI_SUCCESS           The attributes were set for the memory region.
237
+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
238
+                                BaseAddress and Length cannot be modified.
239
+  @retval EFI_INVALID_PARAMETER Length is zero.
240
+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
241
+                                the memory resource range.
242
+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
243
+                                resource range specified by BaseAddress and Length.
244
+                                The bit mask of attributes is not support for the memory resource
245
+                                range specified by BaseAddress and Length.
246
+
247
+**/
248
+typedef
249
+EFI_STATUS
250
+(EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES)(
251
+  IN EFI_CPU_ARCH_PROTOCOL              *This,
252
+  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
253
+  IN  UINT64                            Length,
254
+  IN  UINT64                            Attributes
255
+  );
256
+
257
+
258
+/**
259
+  @par Protocol Description:
260
+  The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE
261
+  Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt
262
+  vectors and exception vectors, reading internal processor timers, resetting the processor, and
263
+  determining the processor frequency.
264
+
265
+  @param FlushDataCache
266
+  Flushes a range of the processor's data cache. If the processor does
267
+  not contain a data cache, or the data cache is fully coherent, then this
268
+  function can just return EFI_SUCCESS. If the processor does not support
269
+  flushing a range of addresses from the data cache, then the entire data
270
+  cache must be flushed.
271
+
272
+  @param EnableInterrupt
273
+  Enables interrupt processing by the processor.
274
+
275
+  @param DisableInterrupt
276
+  Disables interrupt processing by the processor.
277
+
278
+  @param GetInterruptState
279
+  Retrieves the processor's current interrupt state.
280
+
281
+  @param Init
282
+  Generates an INIT on the processor. If a processor cannot programmatically
283
+  generate an INIT without help from external hardware, then this function
284
+  returns EFI_UNSUPPORTED.
285
+
286
+  @param RegisterInterruptHandler
287
+  Associates an interrupt service routine with one of the processor's interrupt
288
+  vectors. This function is typically used by the EFI_TIMER_ARCH_PROTOCOL to
289
+  hook the timer interrupt in a system. It can also be used by the debugger to
290
+  hook exception vectors.
291
+
292
+  @param GetTimerValue
293
+  Returns the value of one of the processor's internal timers.
294
+
295
+  @param SetMemoryAttributes
296
+  Attempts to set the attributes of a memory region.
297
+
298
+  @param NumberOfTimers
299
+  The number of timers that are available in a processor. The value in this
300
+  field is a constant that must not be modified after the CPU Architectural
301
+  Protocol is installed. All consumers must treat this as a read-only field.
302
+
303
+  @param DmaBufferAlignment
304
+  The size, in bytes, of the alignment required for DMA buffer allocations.
305
+  This is typically the size of the largest data cache line in the platform.
306
+  The value in this field is a constant that must not be modified after the
307
+  CPU Architectural Protocol is installed. All consumers must treat this as
308
+  a read-only field.
309
+
310
+**/
311
+struct _EFI_CPU_ARCH_PROTOCOL {
312
+  EFI_CPU_FLUSH_DATA_CACHE            FlushDataCache;
313
+  EFI_CPU_ENABLE_INTERRUPT            EnableInterrupt;
314
+  EFI_CPU_DISABLE_INTERRUPT           DisableInterrupt;
315
+  EFI_CPU_GET_INTERRUPT_STATE         GetInterruptState;
316
+  EFI_CPU_INIT                        Init;
317
+  EFI_CPU_REGISTER_INTERRUPT_HANDLER  RegisterInterruptHandler;
318
+  EFI_CPU_GET_TIMER_VALUE             GetTimerValue;
319
+  EFI_CPU_SET_MEMORY_ATTRIBUTES       SetMemoryAttributes;
320
+  UINT32                              NumberOfTimers;
321
+  UINT32                              DmaBufferAlignment;
322
+};
323
+
324
+extern EFI_GUID gEfiCpuArchProtocolGuid;
325
+
326
+#endif

+ 128
- 0
src/include/gpxe/efi/Protocol/CpuIo.h View File

@@ -0,0 +1,128 @@
1
+/** @file
2
+  This code abstracts the CPU IO Protocol which installed by some platform or chipset-specific
3
+  PEIM that abstracts the processor-visible I/O operations.
4
+
5
+  Copyright (c) 2007, Intel Corporation
6
+  All rights reserved. This program and the accompanying materials
7
+  are licensed and made available under the terms and conditions of the BSD License
8
+  which accompanies this distribution.  The full text of the license may be found at
9
+  http://opensource.org/licenses/bsd-license.php
10
+
11
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
+
14
+  Module Name:  CpuIO.h
15
+
16
+  @par Revision Reference:
17
+  CPU IO Protocol is defined in Framework of EFI CPU IO Protocol Spec
18
+  Version 0.9
19
+
20
+**/
21
+
22
+#ifndef _CPUIO_H_
23
+#define _CPUIO_H_
24
+
25
+#include <gpxe/efi/PiDxe.h>
26
+
27
+#define EFI_CPU_IO_PROTOCOL_GUID \
28
+  { \
29
+    0xB0732526, 0x38C8, 0x4b40, {0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \
30
+  }
31
+
32
+typedef struct _EFI_CPU_IO_PROTOCOL EFI_CPU_IO_PROTOCOL;
33
+
34
+//
35
+// *******************************************************
36
+// EFI_CPU_IO_PROTOCOL_WIDTH
37
+// *******************************************************
38
+//
39
+typedef enum {
40
+  EfiCpuIoWidthUint8,
41
+  EfiCpuIoWidthUint16,
42
+  EfiCpuIoWidthUint32,
43
+  EfiCpuIoWidthUint64,
44
+  EfiCpuIoWidthFifoUint8,
45
+  EfiCpuIoWidthFifoUint16,
46
+  EfiCpuIoWidthFifoUint32,
47
+  EfiCpuIoWidthFifoUint64,
48
+  EfiCpuIoWidthFillUint8,
49
+  EfiCpuIoWidthFillUint16,
50
+  EfiCpuIoWidthFillUint32,
51
+  EfiCpuIoWidthFillUint64,
52
+  EfiCpuIoWidthMaximum
53
+} EFI_CPU_IO_PROTOCOL_WIDTH;
54
+
55
+//
56
+// *******************************************************
57
+// EFI_CPU_IO_PROTOCOL_IO_MEM
58
+// *******************************************************
59
+//
60
+/**
61
+  Enables a driver to access memory-mapped registers in the EFI system memory space.
62
+  Or, Enables a driver to access registers in the EFI CPU I/O space.
63
+
64
+  @param  This                  A pointer to the EFI_CPU_IO_PROTOCOL instance.
65
+  @param  Width                 Signifies the width of the I/O or Memory operation.
66
+  @param  Address               The base address of the I/O or Memoryoperation.
67
+  @param  Count                 The number of I/O or Memory operations to perform.
68
+                                The number of bytes moved is Width size * Count, starting at Address.
69
+  @param  Buffer                For read operations, the destination buffer to store the results.
70
+                                For write operations, the source buffer from which to write data.
71
+
72
+  @retval EFI_SUCCESS           The data was read from or written to the EFI system.
73
+  @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.Or Buffer is NULL.
74
+  @retval EFI_UNSUPPORTED       The Buffer is not aligned for the given Width.
75
+                                Or,The address range specified by Address, Width, and Count is not valid for this EFI system.
76
+
77
+**/
78
+typedef
79
+EFI_STATUS
80
+(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM)(
81
+  IN EFI_CPU_IO_PROTOCOL                *This,
82
+  IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
83
+  IN  UINT64                            Address,
84
+  IN  UINTN                             Count,
85
+  IN  OUT VOID                          *Buffer
86
+  );
87
+
88
+//
89
+// *******************************************************
90
+// EFI_CPU_IO_PROTOCOL_ACCESS
91
+// *******************************************************
92
+//
93
+typedef struct {
94
+  EFI_CPU_IO_PROTOCOL_IO_MEM  Read;
95
+  EFI_CPU_IO_PROTOCOL_IO_MEM  Write;
96
+} EFI_CPU_IO_PROTOCOL_ACCESS;
97
+
98
+//
99
+// *******************************************************
100
+// EFI_CPU_IO_PROTOCOL
101
+// *******************************************************
102
+//
103
+/**
104
+  @par Protocol Description:
105
+  Provides the basic memory and I/O interfaces that are used to abstract
106
+  accesses to devices in a system.
107
+
108
+  @param Mem.Read
109
+  Allows reads from memory-mapped I/O space.
110
+
111
+  @param Mem.Write
112
+  Allows writes to memory-mapped I/O space.
113
+
114
+  @param Io.Read
115
+  Allows reads from I/O space.
116
+
117
+  @param Io.Write
118
+  Allows writes to I/O space.
119
+
120
+**/
121
+struct _EFI_CPU_IO_PROTOCOL {
122
+  EFI_CPU_IO_PROTOCOL_ACCESS  Mem;
123
+  EFI_CPU_IO_PROTOCOL_ACCESS  Io;
124
+};
125
+
126
+extern EFI_GUID gEfiCpuIoProtocolGuid;
127
+
128
+#endif

+ 656
- 0
src/include/gpxe/efi/Protocol/DebugSupport.h View File

@@ -0,0 +1,656 @@
1
+/** @file
2
+  DebugSupport protocol and supporting definitions as defined in the UEFI2.0
3
+  specification.
4
+
5
+  The DebugSupport protocol is used by source level debuggers to abstract the
6
+  processor and handle context save and restore operations.
7
+
8
+  Copyright (c) 2006 - 2008, Intel Corporation
9
+  All rights reserved. This program and the accompanying materials
10
+  are licensed and made available under the terms and conditions of the BSD License
11
+  which accompanies this distribution.  The full text of the license may be found at
12
+  http://opensource.org/licenses/bsd-license.php
13
+
14
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
+
17
+**/
18
+
19
+#ifndef __DEBUG_SUPPORT_H__
20
+#define __DEBUG_SUPPORT_H__
21
+
22
+#include <gpxe/efi/ProcessorBind.h>
23
+#include <gpxe/efi/IndustryStandard/PeImage.h>
24
+
25
+typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL EFI_DEBUG_SUPPORT_PROTOCOL;
26
+
27
+///
28
+/// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25}
29
+///
30
+#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \
31
+  { \
32
+    0x2755590C, 0x6F3C, 0x42FA, {0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } \
33
+  }
34
+
35
+///
36
+/// Debug Support definitions
37
+///
38
+typedef INTN  EFI_EXCEPTION_TYPE;
39
+
40
+//
41
+//  IA-32 processor exception types
42
+//
43
+#define EXCEPT_IA32_DIVIDE_ERROR    0
44
+#define EXCEPT_IA32_DEBUG           1
45
+#define EXCEPT_IA32_NMI             2
46
+#define EXCEPT_IA32_BREAKPOINT      3
47
+#define EXCEPT_IA32_OVERFLOW        4
48
+#define EXCEPT_IA32_BOUND           5
49
+#define EXCEPT_IA32_INVALID_OPCODE  6
50
+#define EXCEPT_IA32_DOUBLE_FAULT    8
51
+#define EXCEPT_IA32_INVALID_TSS     10
52
+#define EXCEPT_IA32_SEG_NOT_PRESENT 11
53
+#define EXCEPT_IA32_STACK_FAULT     12
54
+#define EXCEPT_IA32_GP_FAULT        13
55
+#define EXCEPT_IA32_PAGE_FAULT      14
56
+#define EXCEPT_IA32_FP_ERROR        16
57
+#define EXCEPT_IA32_ALIGNMENT_CHECK 17
58
+#define EXCEPT_IA32_MACHINE_CHECK   18
59
+#define EXCEPT_IA32_SIMD            19
60
+
61
+//
62
+//  IA-32 processor context definition
63
+//
64
+//
65
+// FXSAVE_STATE
66
+// FP / MMX / XMM registers (see fxrstor instruction definition)
67
+//
68
+typedef struct {
69
+  UINT16  Fcw;
70
+  UINT16  Fsw;
71
+  UINT16  Ftw;
72
+  UINT16  Opcode;
73
+  UINT32  Eip;
74
+  UINT16  Cs;
75
+  UINT16  Reserved1;
76
+  UINT32  DataOffset;
77
+  UINT16  Ds;
78
+  UINT8   Reserved2[10];
79
+  UINT8   St0Mm0[10], Reserved3[6];
80
+  UINT8   St1Mm1[10], Reserved4[6];
81
+  UINT8   St2Mm2[10], Reserved5[6];
82
+  UINT8   St3Mm3[10], Reserved6[6];
83
+  UINT8   St4Mm4[10], Reserved7[6];
84
+  UINT8   St5Mm5[10], Reserved8[6];
85
+  UINT8   St6Mm6[10], Reserved9[6];
86
+  UINT8   St7Mm7[10], Reserved10[6];
87
+  UINT8   Xmm0[16];
88
+  UINT8   Xmm1[16];
89
+  UINT8   Xmm2[16];
90
+  UINT8   Xmm3[16];
91
+  UINT8   Xmm4[16];
92
+  UINT8   Xmm5[16];
93
+  UINT8   Xmm6[16];
94
+  UINT8   Xmm7[16];
95
+  UINT8   Reserved11[14 * 16];
96
+} EFI_FX_SAVE_STATE_IA32;
97
+
98
+typedef struct {
99
+  UINT32                 ExceptionData;
100
+  EFI_FX_SAVE_STATE_IA32 FxSaveState;
101
+  UINT32                 Dr0;
102
+  UINT32                 Dr1;
103
+  UINT32                 Dr2;
104
+  UINT32                 Dr3;
105
+  UINT32                 Dr6;
106
+  UINT32                 Dr7;
107
+  UINT32                 Cr0;
108
+  UINT32                 Cr1;  /* Reserved */
109
+  UINT32                 Cr2;
110
+  UINT32                 Cr3;
111
+  UINT32                 Cr4;
112
+  UINT32                 Eflags;
113
+  UINT32                 Ldtr;
114
+  UINT32                 Tr;
115
+  UINT32                 Gdtr[2];
116
+  UINT32                 Idtr[2];
117
+  UINT32                 Eip;
118
+  UINT32                 Gs;
119
+  UINT32                 Fs;
120
+  UINT32                 Es;
121
+  UINT32                 Ds;
122
+  UINT32                 Cs;
123
+  UINT32                 Ss;
124
+  UINT32                 Edi;
125
+  UINT32                 Esi;
126
+  UINT32                 Ebp;
127
+  UINT32                 Esp;
128
+  UINT32                 Ebx;
129
+  UINT32                 Edx;
130
+  UINT32                 Ecx;
131
+  UINT32                 Eax;
132
+} EFI_SYSTEM_CONTEXT_IA32;
133
+
134
+//
135
+//  X64 processor exception types
136
+//
137
+#define EXCEPT_X64_DIVIDE_ERROR    0
138
+#define EXCEPT_X64_DEBUG           1
139
+#define EXCEPT_X64_NMI             2
140
+#define EXCEPT_X64_BREAKPOINT      3
141
+#define EXCEPT_X64_OVERFLOW        4
142
+#define EXCEPT_X64_BOUND           5
143
+#define EXCEPT_X64_INVALID_OPCODE  6
144
+#define EXCEPT_X64_DOUBLE_FAULT    8
145
+#define EXCEPT_X64_INVALID_TSS     10
146
+#define EXCEPT_X64_SEG_NOT_PRESENT 11
147
+#define EXCEPT_X64_STACK_FAULT     12
148
+#define EXCEPT_X64_GP_FAULT        13
149
+#define EXCEPT_X64_PAGE_FAULT      14
150
+#define EXCEPT_X64_FP_ERROR        16
151
+#define EXCEPT_X64_ALIGNMENT_CHECK 17
152
+#define EXCEPT_X64_MACHINE_CHECK   18
153
+#define EXCEPT_X64_SIMD            19
154
+
155
+//
156
+//  X64 processor context definition
157
+//
158
+// FXSAVE_STATE
159
+// FP / MMX / XMM registers (see fxrstor instruction definition)
160
+//
161
+typedef struct {
162
+  UINT16  Fcw;
163
+  UINT16  Fsw;
164
+  UINT16  Ftw;
165
+  UINT16  Opcode;
166
+  UINT64  Rip;
167
+  UINT64  DataOffset;
168
+  UINT8   Reserved1[8];
169
+  UINT8   St0Mm0[10], Reserved2[6];
170
+  UINT8   St1Mm1[10], Reserved3[6];
171
+  UINT8   St2Mm2[10], Reserved4[6];
172
+  UINT8   St3Mm3[10], Reserved5[6];
173
+  UINT8   St4Mm4[10], Reserved6[6];
174
+  UINT8   St5Mm5[10], Reserved7[6];
175
+  UINT8   St6Mm6[10], Reserved8[6];
176
+  UINT8   St7Mm7[10], Reserved9[6];
177
+  UINT8   Xmm0[16];
178
+  UINT8   Xmm1[16];
179
+  UINT8   Xmm2[16];
180
+  UINT8   Xmm3[16];
181
+  UINT8   Xmm4[16];
182
+  UINT8   Xmm5[16];
183
+  UINT8   Xmm6[16];
184
+  UINT8   Xmm7[16];
185
+  //
186
+  // NOTE: UEFI 2.0 spec definition as follows.
187
+  //
188
+  UINT8   Reserved11[14 * 16];
189
+} EFI_FX_SAVE_STATE_X64;
190
+
191
+typedef struct {
192
+  UINT64                ExceptionData;
193
+  EFI_FX_SAVE_STATE_X64 FxSaveState;
194
+  UINT64                Dr0;
195
+  UINT64                Dr1;
196
+  UINT64                Dr2;
197
+  UINT64                Dr3;
198
+  UINT64                Dr6;
199
+  UINT64                Dr7;
200
+  UINT64                Cr0;
201
+  UINT64                Cr1;  /* Reserved */
202
+  UINT64                Cr2;
203
+  UINT64                Cr3;
204
+  UINT64                Cr4;
205
+  UINT64                Cr8;
206
+  UINT64                Rflags;
207
+  UINT64                Ldtr;
208
+  UINT64                Tr;
209
+  UINT64                Gdtr[2];
210
+  UINT64                Idtr[2];
211
+  UINT64                Rip;
212
+  UINT64                Gs;
213
+  UINT64                Fs;
214
+  UINT64                Es;
215
+  UINT64                Ds;
216
+  UINT64                Cs;
217
+  UINT64                Ss;
218
+  UINT64                Rdi;
219
+  UINT64                Rsi;
220
+  UINT64                Rbp;
221
+  UINT64                Rsp;
222
+  UINT64                Rbx;
223
+  UINT64                Rdx;
224
+  UINT64                Rcx;
225
+  UINT64                Rax;
226
+  UINT64                R8;
227
+  UINT64                R9;
228
+  UINT64                R10;
229
+  UINT64                R11;
230
+  UINT64                R12;
231
+  UINT64                R13;
232
+  UINT64                R14;
233
+  UINT64                R15;
234
+} EFI_SYSTEM_CONTEXT_X64;
235
+
236
+//
237
+//  IPF processor exception types
238
+//
239
+#define EXCEPT_IPF_VHTP_TRANSLATION       0
240
+#define EXCEPT_IPF_INSTRUCTION_TLB        1
241
+#define EXCEPT_IPF_DATA_TLB               2
242
+#define EXCEPT_IPF_ALT_INSTRUCTION_TLB    3
243
+#define EXCEPT_IPF_ALT_DATA_TLB           4
244
+#define EXCEPT_IPF_DATA_NESTED_TLB        5
245
+#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6
246
+#define EXCEPT_IPF_DATA_KEY_MISSED        7
247
+#define EXCEPT_IPF_DIRTY_BIT              8
248
+#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9
249
+#define EXCEPT_IPF_DATA_ACCESS_BIT        10
250
+#define EXCEPT_IPF_BREAKPOINT             11
251
+#define EXCEPT_IPF_EXTERNAL_INTERRUPT     12
252
+//
253
+// 13 - 19 reserved
254
+//
255
+#define EXCEPT_IPF_PAGE_NOT_PRESENT           20
256
+#define EXCEPT_IPF_KEY_PERMISSION             21
257
+#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS  22
258
+#define EXCEPT_IPF_DATA_ACCESS_RIGHTS         23
259
+#define EXCEPT_IPF_GENERAL_EXCEPTION          24
260
+#define EXCEPT_IPF_DISABLED_FP_REGISTER       25
261
+#define EXCEPT_IPF_NAT_CONSUMPTION            26
262
+#define EXCEPT_IPF_SPECULATION                27
263
+//
264
+// 28 reserved
265
+//
266
+#define EXCEPT_IPF_DEBUG                          29
267
+#define EXCEPT_IPF_UNALIGNED_REFERENCE            30
268
+#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE     31
269
+#define EXCEPT_IPF_FP_FAULT                       32
270
+#define EXCEPT_IPF_FP_TRAP                        33
271
+#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP  34
272
+#define EXCEPT_IPF_TAKEN_BRANCH                   35
273
+#define EXCEPT_IPF_SINGLE_STEP                    36
274
+//
275
+// 37 - 44 reserved
276
+//
277
+#define EXCEPT_IPF_IA32_EXCEPTION 45
278
+#define EXCEPT_IPF_IA32_INTERCEPT 46
279
+#define EXCEPT_IPF_IA32_INTERRUPT 47
280
+
281
+//
282
+//  IPF processor context definition
283
+//
284
+typedef struct {
285
+  //
286
+  // The first reserved field is necessary to preserve alignment for the correct
287
+  // bits in UNAT and to insure F2 is 16 byte aligned..
288
+  //
289
+  UINT64  Reserved;
290
+  UINT64  R1;
291
+  UINT64  R2;
292
+  UINT64  R3;
293
+  UINT64  R4;
294
+  UINT64  R5;
295
+  UINT64  R6;
296
+  UINT64  R7;
297
+  UINT64  R8;
298
+  UINT64  R9;
299
+  UINT64  R10;
300
+  UINT64  R11;
301
+  UINT64  R12;
302
+  UINT64  R13;
303
+  UINT64  R14;
304
+  UINT64  R15;
305
+  UINT64  R16;
306
+  UINT64  R17;
307
+  UINT64  R18;
308
+  UINT64  R19;
309
+  UINT64  R20;
310
+  UINT64  R21;
311
+  UINT64  R22;
312
+  UINT64  R23;
313
+  UINT64  R24;
314
+  UINT64  R25;
315
+  UINT64  R26;
316
+  UINT64  R27;
317
+  UINT64  R28;
318
+  UINT64  R29;
319
+  UINT64  R30;
320
+  UINT64  R31;
321
+
322
+  UINT64  F2[2];
323
+  UINT64  F3[2];
324
+  UINT64  F4[2];
325
+  UINT64  F5[2];
326
+  UINT64  F6[2];
327
+  UINT64  F7[2];
328
+  UINT64  F8[2];
329
+  UINT64  F9[2];
330
+  UINT64  F10[2];
331
+  UINT64  F11[2];
332
+  UINT64  F12[2];
333
+  UINT64  F13[2];
334
+  UINT64  F14[2];
335
+  UINT64  F15[2];
336
+  UINT64  F16[2];
337
+  UINT64  F17[2];
338
+  UINT64  F18[2];
339
+  UINT64  F19[2];
340
+  UINT64  F20[2];
341
+  UINT64  F21[2];
342
+  UINT64  F22[2];
343
+  UINT64  F23[2];
344
+  UINT64  F24[2];
345
+  UINT64  F25[2];
346
+  UINT64  F26[2];
347
+  UINT64  F27[2];
348
+  UINT64  F28[2];
349
+  UINT64  F29[2];
350
+  UINT64  F30[2];
351
+  UINT64  F31[2];
352
+
353
+  UINT64  Pr;
354
+
355
+  UINT64  B0;
356
+  UINT64  B1;
357
+  UINT64  B2;
358
+  UINT64  B3;
359
+  UINT64  B4;
360
+  UINT64  B5;
361
+  UINT64  B6;
362
+  UINT64  B7;
363
+
364
+  //
365
+  // application registers
366
+  //
367
+  UINT64  ArRsc;
368
+  UINT64  ArBsp;
369
+  UINT64  ArBspstore;
370
+  UINT64  ArRnat;
371
+
372
+  UINT64  ArFcr;
373
+
374
+  UINT64  ArEflag;
375
+  UINT64  ArCsd;
376
+  UINT64  ArSsd;
377
+  UINT64  ArCflg;
378
+  UINT64  ArFsr;
379
+  UINT64  ArFir;
380
+  UINT64  ArFdr;
381
+
382
+  UINT64  ArCcv;
383
+
384
+  UINT64  ArUnat;
385
+
386
+  UINT64  ArFpsr;
387
+
388
+  UINT64  ArPfs;
389
+  UINT64  ArLc;
390
+  UINT64  ArEc;
391
+
392
+  //
393
+  // control registers
394
+  //
395
+  UINT64  CrDcr;
396
+  UINT64  CrItm;
397
+  UINT64  CrIva;
398
+  UINT64  CrPta;
399
+  UINT64  CrIpsr;
400
+  UINT64  CrIsr;
401
+  UINT64  CrIip;
402
+  UINT64  CrIfa;
403
+  UINT64  CrItir;
404
+  UINT64  CrIipa;
405
+  UINT64  CrIfs;
406
+  UINT64  CrIim;
407
+  UINT64  CrIha;
408
+
409
+  //
410
+  // debug registers
411
+  //
412
+  UINT64  Dbr0;
413
+  UINT64  Dbr1;
414
+  UINT64  Dbr2;
415
+  UINT64  Dbr3;
416
+  UINT64  Dbr4;
417
+  UINT64  Dbr5;
418
+  UINT64  Dbr6;
419
+  UINT64  Dbr7;
420
+
421
+  UINT64  Ibr0;
422
+  UINT64  Ibr1;
423
+  UINT64  Ibr2;
424
+  UINT64  Ibr3;
425
+  UINT64  Ibr4;
426
+  UINT64  Ibr5;
427
+  UINT64  Ibr6;
428
+  UINT64  Ibr7;
429
+
430
+  //
431
+  // virtual registers - nat bits for R1-R31
432
+  //
433
+  UINT64  IntNat;
434
+
435
+} EFI_SYSTEM_CONTEXT_IPF;
436
+
437
+//
438
+//  EBC processor exception types
439
+//
440
+#define EXCEPT_EBC_UNDEFINED            0
441
+#define EXCEPT_EBC_DIVIDE_ERROR         1
442
+#define EXCEPT_EBC_DEBUG                2
443
+#define EXCEPT_EBC_BREAKPOINT           3
444
+#define EXCEPT_EBC_OVERFLOW             4
445
+#define EXCEPT_EBC_INVALID_OPCODE       5   // opcode out of range
446
+#define EXCEPT_EBC_STACK_FAULT          6
447
+#define EXCEPT_EBC_ALIGNMENT_CHECK      7
448
+#define EXCEPT_EBC_INSTRUCTION_ENCODING 8   // malformed instruction
449
+#define EXCEPT_EBC_BAD_BREAK            9   // BREAK 0 or undefined BREAK
450
+#define EXCEPT_EBC_STEP                 10  // to support debug stepping
451
+///
452
+/// For coding convenience, define the maximum valid EBC exception.
453
+///
454
+#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP
455
+
456
+///
457
+///  EBC processor context definition
458
+///
459
+typedef struct {
460
+  UINT64  R0;
461
+  UINT64  R1;
462
+  UINT64  R2;
463
+  UINT64  R3;
464
+  UINT64  R4;
465
+  UINT64  R5;
466
+  UINT64  R6;
467
+  UINT64  R7;
468
+  UINT64  Flags;
469
+  UINT64  ControlFlags;
470
+  UINT64  Ip;
471
+} EFI_SYSTEM_CONTEXT_EBC;
472
+
473
+///
474
+/// Universal EFI_SYSTEM_CONTEXT definition
475
+///
476
+typedef union {
477
+  EFI_SYSTEM_CONTEXT_EBC  *SystemContextEbc;
478
+  EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32;
479
+  EFI_SYSTEM_CONTEXT_X64  *SystemContextX64;
480
+  EFI_SYSTEM_CONTEXT_IPF  *SystemContextIpf;
481
+} EFI_SYSTEM_CONTEXT;
482
+
483
+//
484
+// DebugSupport callback function prototypes
485
+//
486
+
487
+/**
488
+  Registers and enables an exception callback function for the specified exception.
489
+
490
+  @param  ExceptionType         Exception types in EBC, IA-32, X64, or IPF
491
+  @param  SystemContext         Exception content.
492
+
493
+**/
494
+typedef
495
+VOID
496
+(*EFI_EXCEPTION_CALLBACK)(
497
+  IN     EFI_EXCEPTION_TYPE               ExceptionType,
498
+  IN OUT EFI_SYSTEM_CONTEXT               SystemContext
499
+  );
500
+
501
+/**
502
+  Registers and enables the on-target debug agent's periodic entry point.
503
+
504
+  @param  SystemContext         Exception content.
505
+
506
+**/
507
+typedef
508
+VOID
509
+(*EFI_PERIODIC_CALLBACK)(
510
+  IN OUT EFI_SYSTEM_CONTEXT               SystemContext
511
+  );
512
+
513
+//
514
+// Machine type definition
515
+//
516
+typedef enum {
517
+  IsaIa32 = IMAGE_FILE_MACHINE_I386, // 0x014C
518
+  IsaX64  = IMAGE_FILE_MACHINE_X64,   // 0x8664
519
+  IsaIpf  = IMAGE_FILE_MACHINE_IA64,  // 0x0200
520
+  IsaEbc  = IMAGE_FILE_MACHINE_EBC    // 0x0EBC
521
+} EFI_INSTRUCTION_SET_ARCHITECTURE;
522
+
523
+
524
+//
525
+// DebugSupport member function definitions
526
+//
527
+
528
+/**
529
+  Returns the maximum value that may be used for the ProcessorIndex parameter in
530
+  RegisterPeriodicCallback() and RegisterExceptionCallback().
531
+
532
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
533
+  @param  MaxProcessorIndex     Pointer to a caller-allocated UINTN in which the maximum supported
534
+                                processor index is returned.
535
+
536
+  @retval EFI_SUCCESS           The function completed successfully.
537
+
538
+**/
539
+typedef
540
+EFI_STATUS
541
+(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX)(
542
+  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,
543
+  OUT UINTN                              *MaxProcessorIndex
544
+  );
545
+
546
+/**
547
+  Registers a function to be called back periodically in interrupt context.
548
+
549
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
550
+  @param  ProcessorIndex        Specifies which processor the callback function applies to.
551
+  @param  PeriodicCallback      A pointer to a function of type PERIODIC_CALLBACK that is the main
552
+                                periodic entry point of the debug agent.
553
+
554
+  @retval EFI_SUCCESS           The function completed successfully.
555
+  @retval EFI_ALREADY_STARTED   Non-NULL PeriodicCallback parameter when a callback
556
+                                function was previously registered.
557
+  @retval EFI_OUT_OF_RESOURCES  System has insufficient memory resources to register new callback
558
+                                function.
559
+
560
+**/
561
+typedef
562
+EFI_STATUS
563
+(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK)(
564
+  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,
565
+  IN UINTN                               ProcessorIndex,
566
+  IN EFI_PERIODIC_CALLBACK               PeriodicCallback
567
+  );
568
+
569
+/**
570
+  Registers a function to be called when a given processor exception occurs.
571
+
572
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
573
+  @param  ProcessorIndex        Specifies which processor the callback function applies to.
574
+  @param  PeriodicCallback      A pointer to a function of type EXCEPTION_CALLBACK that is called
575
+                                when the processor exception specified by ExceptionType occurs.
576
+  @param  ExceptionType         Specifies which processor exception to hook.
577
+
578
+  @retval EFI_SUCCESS           The function completed successfully.
579
+  @retval EFI_ALREADY_STARTED   Non-NULL PeriodicCallback parameter when a callback
580
+                                function was previously registered.
581
+  @retval EFI_OUT_OF_RESOURCES  System has insufficient memory resources to register new callback
582
+                                function.
583
+
584
+**/
585
+typedef
586
+EFI_STATUS
587
+(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK)(
588
+  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,
589
+  IN UINTN                               ProcessorIndex,
590
+  IN EFI_EXCEPTION_CALLBACK              ExceptionCallback,
591
+  IN EFI_EXCEPTION_TYPE                  ExceptionType
592
+  );
593
+
594
+/**
595
+  Invalidates processor instruction cache for a memory range. Subsequent execution in this range
596
+  causes a fresh memory fetch to retrieve code to be executed.
597
+
598
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.
599
+  @param  ProcessorIndex        Specifies which processor's instruction cache is to be invalidated.
600
+  @param  Start                 Specifies the physical base of the memory range to be invalidated.
601
+  @param  Length                Specifies the minimum number of bytes in the processor's instruction
602
+                                cache to invalidate.
603
+
604
+  @retval EFI_SUCCESS           The function completed successfully.
605
+
606
+**/
607
+typedef
608
+EFI_STATUS
609
+(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE)(
610
+  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,
611
+  IN UINTN                               ProcessorIndex,
612
+  IN VOID                                *Start,
613
+  IN UINT64                              Length
614
+  );
615
+
616
+//
617
+// DebugSupport protocol definition
618
+//
619
+/**
620
+  @par Protocol Description:
621
+  This protocol provides the services to allow the debug agent to register
622
+  callback functions that are called either periodically or when specific
623
+  processor exceptions occur.
624
+
625
+  @param Isa
626
+  Declares the processor architecture for this instance of the EFI
627
+  Debug Support protocol.
628
+
629
+  @param GetMaximumProcessorIndex
630
+  Returns the maximum processor index value that may be used.
631
+
632
+  @param RegisterPeriodicCallback
633
+  Registers a callback function that will be invoked periodically
634
+  and asynchronously to the execution of EFI.
635
+
636
+  @param RegisterExceptionCallback
637
+  Registers a callback function that will be called each time the
638
+  specified processor exception occurs.
639
+
640
+  @param InvalidateInstructionCache
641
+  Invalidate the instruction cache of the processor. This is required
642
+  by processor architectures where instruction and data caches are
643
+  not coherent when instructions in the code under debug has been
644
+  modified by the debug agent.
645
+**/
646
+struct _EFI_DEBUG_SUPPORT_PROTOCOL {
647
+  EFI_INSTRUCTION_SET_ARCHITECTURE  Isa;
648
+  EFI_GET_MAXIMUM_PROCESSOR_INDEX   GetMaximumProcessorIndex;
649
+  EFI_REGISTER_PERIODIC_CALLBACK    RegisterPeriodicCallback;
650
+  EFI_REGISTER_EXCEPTION_CALLBACK   RegisterExceptionCallback;
651
+  EFI_INVALIDATE_INSTRUCTION_CACHE  InvalidateInstructionCache;
652
+};
653
+
654
+extern EFI_GUID gEfiDebugSupportProtocolGuid;
655
+
656
+#endif

+ 450
- 0
src/include/gpxe/efi/Protocol/PciRootBridgeIo.h View File

@@ -0,0 +1,450 @@
1
+/** @file
2
+  PCI Root Bridge I/O protocol as defined in the UEFI 2.0 specification.
3
+
4
+  PCI Root Bridge I/O protocol is used by PCI Bus Driver to perform PCI Memory, PCI I/O,
5
+  and PCI Configuration cycles on a PCI Root Bridge. It also provides services to perform
6
+  defferent types of bus mastering DMA
7
+
8
+  Copyright (c) 2006 - 2008, Intel Corporation
9
+  All rights reserved. This program and the accompanying materials
10
+  are licensed and made available under the terms and conditions of the BSD License
11
+  which accompanies this distribution.  The full text of the license may be found at
12
+  http://opensource.org/licenses/bsd-license.php
13
+
14
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
+
17
+**/
18
+
19
+#ifndef __PCI_ROOT_BRIDGE_IO_H__
20
+#define __PCI_ROOT_BRIDGE_IO_H__
21
+
22
+#include <gpxe/efi/PiDxe.h>
23
+
24
+#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \
25
+  { \
26
+    0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
27
+  }
28
+
29
+typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL;
30
+
31
+typedef enum {
32
+  EfiPciWidthUint8,
33
+  EfiPciWidthUint16,
34
+  EfiPciWidthUint32,
35
+  EfiPciWidthUint64,
36
+  EfiPciWidthFifoUint8,
37
+  EfiPciWidthFifoUint16,
38
+  EfiPciWidthFifoUint32,
39
+  EfiPciWidthFifoUint64,
40
+  EfiPciWidthFillUint8,
41
+  EfiPciWidthFillUint16,
42
+  EfiPciWidthFillUint32,
43
+  EfiPciWidthFillUint64,
44
+  EfiPciWidthMaximum
45
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH;
46
+
47
+typedef enum {
48
+  EfiPciOperationBusMasterRead,
49
+  EfiPciOperationBusMasterWrite,
50
+  EfiPciOperationBusMasterCommonBuffer,
51
+  EfiPciOperationBusMasterRead64,
52
+  EfiPciOperationBusMasterWrite64,
53
+  EfiPciOperationBusMasterCommonBuffer64,
54
+  EfiPciOperationMaximum
55
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION;
56
+
57
+#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO          0x0001
58
+#define EFI_PCI_ATTRIBUTE_ISA_IO                      0x0002
59
+#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO              0x0004
60
+#define EFI_PCI_ATTRIBUTE_VGA_MEMORY                  0x0008
61
+#define EFI_PCI_ATTRIBUTE_VGA_IO                      0x0010
62
+#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO              0x0020
63
+#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO            0x0040
64
+#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE        0x0080
65
+#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED               0x0800
66
+#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE              0x1000
67
+#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE          0x8000
68
+
69
+#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER   (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE)
70
+
71
+#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER)
72
+
73
+#define EFI_PCI_ADDRESS(bus, dev, func, reg) \
74
+    ((UINT64) ((((UINTN) bus) << 24) + (((UINTN) dev) << 16) + (((UINTN) func) << 8) + ((UINTN) reg)))
75
+
76
+typedef struct {
77
+  UINT8   Register;
78
+  UINT8   Function;
79
+  UINT8   Device;
80
+  UINT8   Bus;
81
+  UINT32  ExtendedRegister;
82
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS;
83
+
84
+/**
85
+  Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
86
+  satisfied or after a defined duration.
87
+
88
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
89
+  @param  Width                 Signifies the width of the memory or I/O operations.
90
+  @param  Address               The base address of the memory or I/O operations.
91
+  @param  Mask                  Mask used for the polling criteria.
92
+  @param  Value                 The comparison value used for the polling exit criteria.
93
+  @param  Delay                 The number of 100 ns units to poll.
94
+  @param  Result                Pointer to the last value read from the memory location.
95
+
96
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.
97
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
98
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
99
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
100
+
101
+**/
102
+typedef
103
+EFI_STATUS
104
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)(
105
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
106
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
107
+  IN  UINT64                                   Address,
108
+  IN  UINT64                                   Mask,
109
+  IN  UINT64                                   Value,
110
+  IN  UINT64                                   Delay,
111
+  OUT UINT64                                   *Result
112
+  );
113
+
114
+/**
115
+  Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
116
+
117
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
118
+  @param  Width                 Signifies the width of the memory operations.
119
+  @param  Address               The base address of the memory operations.
120
+  @param  Count                 The number of memory operations to perform.
121
+  @param  Buffer                For read operations, the destination buffer to store the results. For write
122
+                                operations, the source buffer to write data from.
123
+
124
+  @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
125
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
126
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
127
+
128
+**/
129
+typedef
130
+EFI_STATUS
131
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)(
132
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
133
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
134
+  IN     UINT64                                   Address,
135
+  IN     UINTN                                    Count,
136
+  IN OUT VOID                                     *Buffer
137
+  );
138
+
139
+typedef struct {
140
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM  Read;
141
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM  Write;
142
+} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS;
143
+
144
+/**
145
+  Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
146
+  root bridge memory space.
147
+
148
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
149
+  @param  Width                 Signifies the width of the memory operations.
150
+  @param  DestAddress           The destination address of the memory operation.
151
+  @param  SrcAddress            The source address of the memory operation.
152
+  @param  Count                 The number of memory operations to perform.
153
+
154
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.
155
+  @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
156
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
157
+
158
+**/
159
+typedef
160
+EFI_STATUS
161
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM)(
162
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
163
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH    Width,
164
+  IN     UINT64                                   DestAddress,
165
+  IN     UINT64                                   SrcAddress,
166
+  IN     UINTN                                    Count
167
+  );
168
+
169
+/**
170
+  Provides the PCI controller-Cspecific addresses required to access system memory from a
171
+  DMA bus master.
172
+
173
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
174
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
175
+  @param  HostAddress           The system memory address to map to the PCI controller.
176
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
177
+                                that were mapped.
178
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
179
+                                access the hosts HostAddress.
180
+  @param  Mapping               A resulting value to pass to Unmap().
181
+
182
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
183
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
184
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
185
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
186
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
187
+
188
+**/
189
+typedef
190
+EFI_STATUS
191
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP)(
192
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                *This,
193
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
194
+  IN     VOID                                       *HostAddress,
195
+  IN OUT UINTN                                      *NumberOfBytes,
196
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
197
+  OUT    VOID                                       **Mapping
198
+  );
199
+
200
+/**
201
+  Completes the Map() operation and releases any corresponding resources.
202
+
203
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
204
+  @param  Mapping               The mapping value returned from Map().
205
+
206
+  @retval EFI_SUCCESS           The range was unmapped.
207
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
208
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
209
+
210
+**/
211
+typedef
212
+EFI_STATUS
213
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP)(
214
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
215
+  IN  VOID                                     *Mapping
216
+  );
217
+
218
+/**
219
+  Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
220
+  EfiPciOperationBusMasterCommonBuffer64 mapping.
221
+
222
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
223
+  @param  Type                  This parameter is not used and must be ignored.
224
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
225
+                                EfiRuntimeServicesData.
226
+  @param  Pages                 The number of pages to allocate.
227
+  @param  HostAddress           A pointer to store the base system memory address of the
228
+                                allocated range.
229
+  @param  Attributes            The requested bit mask of attributes for the allocated range.
230
+
231
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
232
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
233
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
234
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
235
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
236
+
237
+**/
238
+typedef
239
+EFI_STATUS
240
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER)(
241
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
242
+  IN     EFI_ALLOCATE_TYPE                        Type,
243
+  IN     EFI_MEMORY_TYPE                          MemoryType,
244
+  IN     UINTN                                    Pages,
245
+  IN OUT VOID                                     **HostAddress,
246
+  IN     UINT64                                   Attributes
247
+  );
248
+
249
+/**
250
+  Frees memory that was allocated with AllocateBuffer().
251
+
252
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
253
+  @param  Pages                 The number of pages to free.
254
+  @param  HostAddress           The base system memory address of the allocated range.
255
+
256
+  @retval EFI_SUCCESS           The requested memory pages were freed.
257
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
258
+                                was not allocated with AllocateBuffer().
259
+
260
+**/
261
+typedef
262
+EFI_STATUS
263
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER)(
264
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
265
+  IN  UINTN                                    Pages,
266
+  IN  VOID                                     *HostAddress
267
+  );
268
+
269
+/**
270
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.
271
+
272
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
273
+
274
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host
275
+                                bridge to system memory.
276
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI
277
+                                host bridge due to a hardware error.
278
+
279
+**/
280
+typedef
281
+EFI_STATUS
282
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH)(
283
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
284
+  );
285
+
286
+/**
287
+  Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
288
+  attributes that a PCI root bridge is currently using.
289
+
290
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
291
+  @param  Supports              A pointer to the mask of attributes that this PCI root bridge supports
292
+                                setting with SetAttributes().
293
+  @param  Attributes            A pointer to the mask of attributes that this PCI root bridge is currently
294
+                                using.
295
+
296
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
297
+                                bridge supports is returned in Supports. If Attributes is
298
+                                not NULL, then the attributes that the PCI root bridge is currently
299
+                                using is returned in Attributes.
300
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
301
+
302
+
303
+**/
304
+typedef
305
+EFI_STATUS
306
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES)(
307
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This,
308
+  OUT UINT64                                   *Supports,
309
+  OUT UINT64                                   *Attributes
310
+  );
311
+
312
+/**
313
+  Sets attributes for a resource range on a PCI root bridge.
314
+
315
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
316
+  @param  Attributes            The mask of attributes to set.
317
+  @param  ResourceBase          A pointer to the base address of the resource range to be modified by the
318
+                                attributes specified by Attributes.
319
+  @param  ResourceLength        A pointer to the length of the resource range to be modified by the
320
+                                attributes specified by Attributes.
321
+
322
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource
323
+                                range specified by ResourceBase and ResourceLength
324
+                                were set on the PCI root bridge, and the actual resource range is
325
+                                returned in ResuourceBase and ResourceLength.
326
+  @retval EFI_UNSUPPORTED       A bit is set in Attributes that is not supported by the PCI Root
327
+                                Bridge.
328
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the
329
+                                resource range specified by BaseAddress and Length.
330
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
331
+
332
+**/
333
+typedef
334
+EFI_STATUS
335
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES)(
336
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
337
+  IN     UINT64                                   Attributes,
338
+  IN OUT UINT64                                   *ResourceBase,
339
+  IN OUT UINT64                                   *ResourceLength
340
+  );
341
+
342
+/**
343
+  Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
344
+  resource descriptors.
345
+
346
+  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
347
+  @param  Resources             A pointer to the ACPI 2.0 resource descriptors that describe the current
348
+                                configuration of this PCI root bridge.
349
+
350
+  @retval EFI_SUCCESS           The current configuration of this PCI root bridge was returned in
351
+                                Resources.
352
+  @retval EFI_UNSUPPORTED       The current configuration of this PCI root bridge could not be
353
+                                retrieved.
354
+
355
+**/
356
+typedef
357
+EFI_STATUS
358
+(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION)(
359
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL          *This,
360
+  OUT VOID                                     **Resources
361
+  );
362
+
363
+/**
364
+  @par Protocol Description:
365
+  Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are
366
+  used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller.
367
+
368
+  @param ParentHandle
369
+  The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member.
370
+
371
+  @param PollMem
372
+  Polls an address in memory mapped I/O space until an exit condition is met,
373
+  or a timeout occurs.
374
+
375
+  @param PollIo
376
+  Polls an address in I/O space until an exit condition is met, or a timeout occurs.
377
+
378
+  @param Mem.Read
379
+  Allows reads from memory mapped I/O space.
380
+
381
+  @param Mem.Write
382
+  Allows writes to memory mapped I/O space.
383
+
384
+  @param Io.Read
385
+  Allows reads from I/O space.
386
+
387
+  @param Io.Write
388
+  Allows writes to I/O space.
389
+
390
+  @param Pci.Read
391
+  Allows reads from PCI configuration space.
392
+
393
+  @param Pci.Write
394
+  Allows writes to PCI configuration space.
395
+
396
+  @param CopyMem
397
+  Allows one region of PCI root bridge memory space to be copied to another
398
+  region of PCI root bridge memory space.
399
+
400
+  @param Map
401
+  Provides the PCI controller's specific addresses needed to access system memory for DMA.
402
+
403
+  @param Unmap
404
+  Releases any resources allocated by Map().
405
+
406
+  @param AllocateBuffer
407
+  Allocates pages that are suitable for a common buffer mapping.
408
+
409
+  @param FreeBuffer
410
+  Free pages that were allocated with AllocateBuffer().
411
+
412
+  @param Flush
413
+  Flushes all PCI posted write transactions to system memory.
414
+
415
+  @param GetAttributes
416
+  Gets the attributes that a PCI root bridge supports setting with SetAttributes(),
417
+  and the attributes that a PCI root bridge is currently using.
418
+
419
+  @param SetAttributes
420
+  Sets attributes for a resource range on a PCI root bridge.
421
+
422
+  @param Configuration
423
+  Gets the current resource settings for this PCI root bridge.
424
+
425
+  @param SegmentNumber
426
+  The segment number that this PCI root bridge resides.
427
+
428
+**/
429
+struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL {
430
+  EFI_HANDLE                                      ParentHandle;
431
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM     PollMem;
432
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM     PollIo;
433
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Mem;
434
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Io;
435
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS          Pci;
436
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM        CopyMem;
437
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP             Map;
438
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP           Unmap;
439
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer;
440
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER     FreeBuffer;
441
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH           Flush;
442
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES  GetAttributes;
443
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES  SetAttributes;
444
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION   Configuration;
445
+  UINT32                                          SegmentNumber;
446
+};
447
+
448
+extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid;
449
+
450
+#endif

+ 52
- 0
src/include/gpxe/efi/efi.h View File

@@ -34,4 +34,56 @@
34 34
 /* Reset any trailing #pragma pack directives */
35 35
 #pragma pack()
36 36
 
37
+#include <gpxe/tables.h>
38
+#include <gpxe/uuid.h>
39
+
40
+/** An EFI protocol used by gPXE */
41
+struct efi_protocol {
42
+	union {
43
+		/** EFI protocol GUID */
44
+		EFI_GUID guid;
45
+		/** UUID structure understood by gPXE */
46
+		union uuid uuid;
47
+	} u;
48
+	/** Variable containing pointer to protocol structure */
49
+	void **protocol;
50
+};
51
+
52
+/** Declare an EFI protocol used by gPXE */
53
+#define __efi_protocol \
54
+	__table ( struct efi_protocol, efi_protocols, 01 )
55
+
56
+/** Declare an EFI protocol to be required by gPXE
57
+ *
58
+ * @v _protocol		EFI protocol name
59
+ * @v _ptr		Pointer to protocol instance
60
+ */
61
+#define EFI_REQUIRE_PROTOCOL( _protocol, _ptr )				     \
62
+	struct efi_protocol __ ## _protocol __efi_protocol = {		     \
63
+		.u.guid = _protocol ## _GUID,				     \
64
+		.protocol = ( ( void ** ) ( void * )			     \
65
+			      ( ( (_ptr) == ( ( _protocol ** ) NULL ) ) ?    \
66
+				(_ptr) : (_ptr) ) ),			     \
67
+	}
68
+
69
+/** Convert a gPXE status code to an EFI status code
70
+ *
71
+ * FIXME: actually perform some kind of conversion.  gPXE error codes
72
+ * will be detected as EFI error codes; both have the top bit set, and
73
+ * the success return code is zero for both.  Anything that just
74
+ * reports a numerical error will be OK, anything attempting to
75
+ * interpret the value or to display a text equivalent will be
76
+ * screwed.
77
+ */
78
+#define RC_TO_EFIRC( rc ) (rc)
79
+
80
+/** Convert an EFI status code to a gPXE status code
81
+ *
82
+ * FIXME: as above
83
+ */
84
+#define EFIRC_TO_RC( efirc ) (efirc)
85
+
86
+extern EFI_HANDLE efi_image_handle;
87
+extern EFI_SYSTEM_TABLE *efi_systab;
88
+
37 89
 #endif /* _EFI_H */

+ 178
- 0
src/include/gpxe/efi/efi_io.h View File

@@ -0,0 +1,178 @@
1
+#ifndef _GPXE_EFI_IO_H
2
+#define _GPXE_EFI_IO_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE I/O API for EFI
7
+ *
8
+ * EFI runs with flat physical addressing, so the various mappings
9
+ * between virtual addresses, I/O addresses and bus addresses are all
10
+ * no-ops.  I/O is handled using the EFI_CPU_IO_PROTOCOL.
11
+ */
12
+
13
+#ifdef IOAPI_EFI
14
+#define IOAPI_PREFIX_efi
15
+#else
16
+#define IOAPI_PREFIX_efi __efi_
17
+#endif
18
+
19
+extern unsigned long long efi_ioread ( volatile void *io_addr,
20
+				       size_t size );
21
+extern void efi_iowrite ( unsigned long long data, volatile void *io_addr,
22
+			  size_t size );
23
+extern void efi_ioreads ( volatile void *io_addr, void *data,
24
+			  size_t size, unsigned int count );
25
+extern void efi_iowrites ( volatile void *io_addr, const void *data,
26
+			  size_t size, unsigned int count );
27
+
28
+/*
29
+ * Physical<->Bus and Bus<->I/O address mappings
30
+ *
31
+ * EFI runs with flat physical addressing, so these are all no-ops.
32
+ *
33
+ */
34
+
35
+static inline __always_inline unsigned long
36
+IOAPI_INLINE ( efi, phys_to_bus ) ( unsigned long phys_addr ) {
37
+	return phys_addr;
38
+}
39
+
40
+static inline __always_inline unsigned long
41
+IOAPI_INLINE ( efi, bus_to_phys ) ( unsigned long bus_addr ) {
42
+	return bus_addr;
43
+}
44
+
45
+static inline __always_inline void *
46
+IOAPI_INLINE ( efi, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
47
+	return ( ( void * ) bus_addr );
48
+}
49
+
50
+static inline __always_inline void
51
+IOAPI_INLINE ( efi, iounmap ) ( volatile const void *io_addr __unused ) {
52
+	/* Nothing to do */
53
+}
54
+
55
+static inline __always_inline unsigned long
56
+IOAPI_INLINE ( efi, io_to_bus ) ( volatile const void *io_addr ) {
57
+	return ( ( unsigned long ) io_addr );
58
+}
59
+
60
+/*
61
+ * I/O functions
62
+ *
63
+ */
64
+
65
+static inline __always_inline uint8_t
66
+IOAPI_INLINE ( efi, readb ) ( volatile uint8_t *io_addr ) {
67
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
68
+}
69
+
70
+static inline __always_inline uint16_t
71
+IOAPI_INLINE ( efi, readw ) ( volatile uint16_t *io_addr ) {
72
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
73
+}
74
+
75
+static inline __always_inline uint32_t
76
+IOAPI_INLINE ( efi, readl ) ( volatile uint32_t *io_addr ) {
77
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
78
+}
79
+
80
+static inline __always_inline uint64_t
81
+IOAPI_INLINE ( efi, readq ) ( volatile uint64_t *io_addr ) {
82
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
83
+}
84
+
85
+static inline __always_inline void
86
+IOAPI_INLINE ( efi, writeb ) ( uint8_t data, volatile uint8_t *io_addr ) {
87
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
88
+}
89
+
90
+static inline __always_inline void
91
+IOAPI_INLINE ( efi, writew ) ( uint16_t data, volatile uint16_t *io_addr ) {
92
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
93
+}
94
+
95
+static inline __always_inline void
96
+IOAPI_INLINE ( efi, writel ) ( uint32_t data, volatile uint32_t *io_addr ) {
97
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
98
+}
99
+
100
+static inline __always_inline void
101
+IOAPI_INLINE ( efi, writeq ) ( uint64_t data, volatile uint64_t *io_addr ) {
102
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
103
+}
104
+
105
+static inline __always_inline uint8_t
106
+IOAPI_INLINE ( efi, inb ) ( volatile uint8_t *io_addr ) {
107
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
108
+}
109
+
110
+static inline __always_inline uint16_t
111
+IOAPI_INLINE ( efi, inw ) ( volatile uint16_t *io_addr ) {
112
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
113
+}
114
+
115
+static inline __always_inline uint32_t
116
+IOAPI_INLINE ( efi, inl ) ( volatile uint32_t *io_addr ) {
117
+	return efi_ioread ( io_addr, sizeof ( *io_addr ) );
118
+}
119
+
120
+static inline __always_inline void
121
+IOAPI_INLINE ( efi, outb ) ( uint8_t data, volatile uint8_t *io_addr ) {
122
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
123
+}
124
+
125
+static inline __always_inline void
126
+IOAPI_INLINE ( efi, outw ) ( uint16_t data, volatile uint16_t *io_addr ) {
127
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
128
+}
129
+
130
+static inline __always_inline void
131
+IOAPI_INLINE ( efi, outl ) ( uint32_t data, volatile uint32_t *io_addr ) {
132
+	efi_iowrite ( data, io_addr, sizeof ( *io_addr ) );
133
+}
134
+
135
+static inline __always_inline void
136
+IOAPI_INLINE ( efi, insb ) ( volatile uint8_t *io_addr, uint8_t *data,
137
+			     unsigned int count ) {
138
+	efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
139
+}
140
+
141
+static inline __always_inline void
142
+IOAPI_INLINE ( efi, insw ) ( volatile uint16_t *io_addr, uint16_t *data,
143
+			     unsigned int count ) {
144
+	efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
145
+}
146
+
147
+static inline __always_inline void
148
+IOAPI_INLINE ( efi, insl ) ( volatile uint32_t *io_addr, uint32_t *data,
149
+			     unsigned int count ) {
150
+	efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count );
151
+}
152
+
153
+static inline __always_inline void
154
+IOAPI_INLINE ( efi, outsb ) ( volatile uint8_t *io_addr, const uint8_t *data,
155
+			      unsigned int count ) {
156
+	efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
157
+}
158
+
159
+static inline __always_inline void
160
+IOAPI_INLINE ( efi, outsw ) ( volatile uint16_t *io_addr, const uint16_t *data,
161
+			      unsigned int count ) {
162
+	efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
163
+}
164
+
165
+static inline __always_inline void
166
+IOAPI_INLINE ( efi, outsl ) ( volatile uint32_t *io_addr, const uint32_t *data,
167
+			      unsigned int count ) {
168
+	efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count );
169
+}
170
+
171
+static inline __always_inline void
172
+IOAPI_INLINE ( efi, mb ) ( void ) {
173
+	/* Do nothing; EFI readl()/writel() calls already act as
174
+	 * memory barriers.
175
+	 */
176
+}
177
+
178
+#endif /* _GPXE_EFI_IO_H */

+ 146
- 0
src/include/gpxe/efi/efi_pci.h View File

@@ -0,0 +1,146 @@
1
+#ifndef _GPXE_EFI_PCI_H
2
+#define _GPXE_EFI_PCI_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE PCI I/O API for EFI
7
+ *
8
+ */
9
+
10
+#ifdef PCIAPI_EFI
11
+#define PCIAPI_PREFIX_efi
12
+#else
13
+#define PCIAPI_PREFIX_efi __efi_
14
+#endif
15
+
16
+/* EFI PCI width codes defined by EFI spec */
17
+#define EFIPCI_WIDTH_BYTE 0
18
+#define EFIPCI_WIDTH_WORD 1
19
+#define EFIPCI_WIDTH_DWORD 2
20
+
21
+#define EFIPCI_LOCATION( _offset, _width ) \
22
+	( (_offset) | ( (_width) << 16 ) )
23
+#define EFIPCI_OFFSET( _location ) ( (_location) & 0xffff )
24
+#define EFIPCI_WIDTH( _location ) ( (_location) >> 16 )
25
+
26
+struct pci_device;
27
+
28
+extern int efipci_read ( struct pci_device *pci, unsigned long location,
29
+			 void *value );
30
+extern int efipci_write ( struct pci_device *pci, unsigned long location,
31
+			  unsigned long value );
32
+
33
+/**
34
+ * Determine maximum PCI bus number within system
35
+ *
36
+ * @ret max_bus		Maximum bus number
37
+ */
38
+static inline __always_inline int
39
+PCIAPI_INLINE ( efi, pci_max_bus ) ( void ) {
40
+	/* No way to work this out via EFI */
41
+	return 0xff;
42
+}
43
+
44
+/**
45
+ * Read byte from PCI configuration space via EFI
46
+ *
47
+ * @v pci	PCI device
48
+ * @v where	Location within PCI configuration space
49
+ * @v value	Value read
50
+ * @ret rc	Return status code
51
+ */
52
+static inline __always_inline int
53
+PCIAPI_INLINE ( efi, pci_read_config_byte ) ( struct pci_device *pci,
54
+					      unsigned int where,
55
+					      uint8_t *value ) {
56
+	return efipci_read ( pci,
57
+			     EFIPCI_LOCATION ( where, EFIPCI_WIDTH_BYTE ),
58
+			     value );
59
+}
60
+
61
+/**
62
+ * Read word from PCI configuration space via EFI
63
+ *
64
+ * @v pci	PCI device
65
+ * @v where	Location within PCI configuration space
66
+ * @v value	Value read
67
+ * @ret rc	Return status code
68
+ */
69
+static inline __always_inline int
70
+PCIAPI_INLINE ( efi, pci_read_config_word ) ( struct pci_device *pci,
71
+					      unsigned int where,
72
+					      uint16_t *value ) {
73
+	return efipci_read ( pci,
74
+			     EFIPCI_LOCATION ( where, EFIPCI_WIDTH_WORD ),
75
+			     value );
76
+}
77
+
78
+/**
79
+ * Read dword from PCI configuration space via EFI
80
+ *
81
+ * @v pci	PCI device
82
+ * @v where	Location within PCI configuration space
83
+ * @v value	Value read
84
+ * @ret rc	Return status code
85
+ */
86
+static inline __always_inline int
87
+PCIAPI_INLINE ( efi, pci_read_config_dword ) ( struct pci_device *pci,
88
+					       unsigned int where,
89
+					       uint32_t *value ) {
90
+	return efipci_read ( pci,
91
+			     EFIPCI_LOCATION ( where, EFIPCI_WIDTH_DWORD ),
92
+			     value );
93
+}
94
+
95
+/**
96
+ * Write byte to PCI configuration space via EFI
97
+ *
98
+ * @v pci	PCI device
99
+ * @v where	Location within PCI configuration space
100
+ * @v value	Value to be written
101
+ * @ret rc	Return status code
102
+ */
103
+static inline __always_inline int
104
+PCIAPI_INLINE ( efi, pci_write_config_byte ) ( struct pci_device *pci,
105
+					       unsigned int where,
106
+					       uint8_t value ) {
107
+	return efipci_write ( pci,
108
+			      EFIPCI_LOCATION ( where, EFIPCI_WIDTH_BYTE ),
109
+			      value );
110
+}
111
+
112
+/**
113
+ * Write word to PCI configuration space via EFI
114
+ *
115
+ * @v pci	PCI device
116
+ * @v where	Location within PCI configuration space
117
+ * @v value	Value to be written
118
+ * @ret rc	Return status code
119
+ */
120
+static inline __always_inline int
121
+PCIAPI_INLINE ( efi, pci_write_config_word ) ( struct pci_device *pci,
122
+					       unsigned int where,
123
+					       uint16_t value ) {
124
+	return efipci_write ( pci,
125
+			      EFIPCI_LOCATION ( where, EFIPCI_WIDTH_WORD ),
126
+			      value );
127
+}
128
+
129
+/**
130
+ * Write dword to PCI configuration space via EFI
131
+ *
132
+ * @v pci	PCI device
133
+ * @v where	Location within PCI configuration space
134
+ * @v value	Value to be written
135
+ * @ret rc	Return status code
136
+ */
137
+static inline __always_inline int
138
+PCIAPI_INLINE ( efi, pci_write_config_dword ) ( struct pci_device *pci,
139
+						unsigned int where,
140
+						uint32_t value ) {
141
+	return efipci_write ( pci,
142
+			      EFIPCI_LOCATION ( where, EFIPCI_WIDTH_DWORD ),
143
+			      value );
144
+}
145
+
146
+#endif /* _GPXE_EFI_PCI_H */

+ 16
- 0
src/include/gpxe/efi/efi_timer.h View File

@@ -0,0 +1,16 @@
1
+#ifndef _GPXE_EFI_TIMER_H
2
+#define _GPXE_EFI_TIMER_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE timer API for EFI
7
+ *
8
+ */
9
+
10
+#ifdef TIMER_EFI
11
+#define TIMER_PREFIX_efi
12
+#else
13
+#define TIMER_PREFIX_efi __efi_
14
+#endif
15
+
16
+#endif /* _GPXE_EFI_TIMER_H */

+ 88
- 0
src/include/gpxe/efi/efi_uaccess.h View File

@@ -0,0 +1,88 @@
1
+#ifndef _GPXE_EFI_UACCESS_H
2
+#define _GPXE_EFI_UACCESS_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE user access API for EFI
7
+ *
8
+ * EFI runs with flat physical addressing, so the various mappings
9
+ * between virtual addresses, I/O addresses and bus addresses are all
10
+ * no-ops.
11
+ */
12
+
13
+#ifdef UACCESS_EFI
14
+#define UACCESS_PREFIX_efi
15
+#else
16
+#define UACCESS_PREFIX_efi __efi_
17
+#endif
18
+
19
+/**
20
+ * Convert physical address to user pointer
21
+ *
22
+ * @v phys_addr		Physical address
23
+ * @ret userptr		User pointer
24
+ */
25
+static inline __always_inline userptr_t
26
+UACCESS_INLINE ( efi, phys_to_user ) ( unsigned long phys_addr ) {
27
+	return phys_addr;
28
+}
29
+
30
+/**
31
+ * Convert user buffer to physical address
32
+ *
33
+ * @v userptr		User pointer
34
+ * @v offset		Offset from user pointer
35
+ * @ret phys_addr	Physical address
36
+ */
37
+static inline __always_inline unsigned long
38
+UACCESS_INLINE ( efi, user_to_phys ) ( userptr_t userptr, off_t offset ) {
39
+	return ( userptr + offset );
40
+}
41
+
42
+static inline __always_inline userptr_t
43
+UACCESS_INLINE ( efi, virt_to_user ) ( volatile const void *addr ) {
44
+	return trivial_virt_to_user ( addr );
45
+}
46
+
47
+static inline __always_inline void *
48
+UACCESS_INLINE ( efi, user_to_virt ) ( userptr_t userptr, off_t offset ) {
49
+	return trivial_user_to_virt ( userptr, offset );
50
+}
51
+
52
+static inline __always_inline userptr_t
53
+UACCESS_INLINE ( efi, userptr_add ) ( userptr_t userptr, off_t offset ) {
54
+	return trivial_userptr_add ( userptr, offset );
55
+}
56
+
57
+static inline __always_inline void
58
+UACCESS_INLINE ( efi, memcpy_user ) ( userptr_t dest, off_t dest_off,
59
+					userptr_t src, off_t src_off,
60
+					size_t len ) {
61
+	trivial_memcpy_user ( dest, dest_off, src, src_off, len );
62
+}
63
+
64
+static inline __always_inline void
65
+UACCESS_INLINE ( efi, memmove_user ) ( userptr_t dest, off_t dest_off,
66
+					 userptr_t src, off_t src_off,
67
+					 size_t len ) {
68
+	trivial_memmove_user ( dest, dest_off, src, src_off, len );
69
+}
70
+
71
+static inline __always_inline void
72
+UACCESS_INLINE ( efi, memset_user ) ( userptr_t buffer, off_t offset,
73
+					int c, size_t len ) {
74
+	trivial_memset_user ( buffer, offset, c, len );
75
+}
76
+
77
+static inline __always_inline size_t
78
+UACCESS_INLINE ( efi, strlen_user ) ( userptr_t buffer, off_t offset ) {
79
+	return trivial_strlen_user ( buffer, offset );
80
+}
81
+
82
+static inline __always_inline off_t
83
+UACCESS_INLINE ( efi, memchr_user ) ( userptr_t buffer, off_t offset,
84
+					int c, size_t len ) {
85
+	return trivial_memchr_user ( buffer, offset, c, len );
86
+}
87
+
88
+#endif /* _GPXE_EFI_UACCESS_H */

+ 16
- 0
src/include/gpxe/efi/efi_umalloc.h View File

@@ -0,0 +1,16 @@
1
+#ifndef _GPXE_EFI_UMALLOC_H
2
+#define _GPXE_EFI_UMALLOC_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE user memory allocation API for EFI
7
+ *
8
+ */
9
+
10
+#ifdef UMALLOC_EFI
11
+#define UMALLOC_PREFIX_efi
12
+#else
13
+#define UMALLOC_PREFIX_efi __efi_
14
+#endif
15
+
16
+#endif /* _GPXE_EFI_UMALLOC_H */

+ 2
- 0
src/include/gpxe/errfile.h View File

@@ -139,6 +139,7 @@
139 139
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )
140 140
 #define ERRFILE_script		      ( ERRFILE_IMAGE | 0x00020000 )
141 141
 #define ERRFILE_segment		      ( ERRFILE_IMAGE | 0x00030000 )
142
+#define ERRFILE_efi_image	      ( ERRFILE_IMAGE | 0x00040000 )
142 143
 
143 144
 #define ERRFILE_asn1		      ( ERRFILE_OTHER | 0x00000000 )
144 145
 #define ERRFILE_chap		      ( ERRFILE_OTHER | 0x00010000 )
@@ -156,6 +157,7 @@
156 157
 #define ERRFILE_tls		      ( ERRFILE_OTHER | 0x000d0000 )
157 158
 #define ERRFILE_ifmgmt		      ( ERRFILE_OTHER | 0x000e0000 )
158 159
 #define ERRFILE_iscsiboot	      ( ERRFILE_OTHER | 0x000f0000 )
160
+#define ERRFILE_efi_pci		      ( ERRFILE_OTHER | 0x00100000 )
159 161
 
160 162
 /** @} */
161 163
 

+ 1
- 0
src/include/gpxe/features.h View File

@@ -46,6 +46,7 @@
46 46
 #define DHCP_EB_FEATURE_PXE		0x21 /**< PXE format */
47 47
 #define DHCP_EB_FEATURE_ELF		0x22 /**< ELF format */
48 48
 #define DHCP_EB_FEATURE_COMBOOT		0x23 /**< COMBOOT format */
49
+#define DHCP_EB_FEATURE_EFI		0x24 /**< EFI format */
49 50
 
50 51
 /** @} */
51 52
 

+ 1
- 0
src/include/gpxe/io.h View File

@@ -51,6 +51,7 @@
51 51
 	PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
52 52
 
53 53
 /* Include all architecture-independent I/O API headers */
54
+#include <gpxe/efi/efi_io.h>
54 55
 
55 56
 /* Include all architecture-dependent I/O API headers */
56 57
 #include <bits/io.h>

+ 1
- 0
src/include/gpxe/pci_io.h View File

@@ -41,6 +41,7 @@
41 41
 	PROVIDE_SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func )
42 42
 
43 43
 /* Include all architecture-independent I/O API headers */
44
+#include <gpxe/efi/efi_pci.h>
44 45
 
45 46
 /* Include all architecture-dependent I/O API headers */
46 47
 #include <bits/pci_io.h>

+ 1
- 0
src/include/gpxe/timer.h View File

@@ -42,6 +42,7 @@
42 42
 	PROVIDE_SINGLE_API_INLINE ( TIMER_PREFIX_ ## _subsys, _api_func )
43 43
 
44 44
 /* Include all architecture-independent I/O API headers */
45
+#include <gpxe/efi/efi_timer.h>
45 46
 
46 47
 /* Include all architecture-dependent I/O API headers */
47 48
 #include <bits/timer.h>

+ 1
- 0
src/include/gpxe/uaccess.h View File

@@ -186,6 +186,7 @@ trivial_memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
186 186
 	PROVIDE_SINGLE_API_INLINE ( UACCESS_PREFIX_ ## _subsys, _api_func )
187 187
 
188 188
 /* Include all architecture-independent user access API headers */
189
+#include <gpxe/efi/efi_uaccess.h>
189 190
 
190 191
 /* Include all architecture-dependent user access API headers */
191 192
 #include <bits/uaccess.h>

+ 1
- 0
src/include/gpxe/umalloc.h View File

@@ -23,6 +23,7 @@
23 23
 	PROVIDE_SINGLE_API ( UMALLOC_PREFIX_ ## _subsys, _api_func, _func )
24 24
 
25 25
 /* Include all architecture-independent I/O API headers */
26
+#include <gpxe/efi/efi_umalloc.h>
26 27
 
27 28
 /* Include all architecture-dependent I/O API headers */
28 29
 #include <bits/umalloc.h>

+ 273
- 0
src/interface/efi/efi_console.c View File

@@ -0,0 +1,273 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stddef.h>
20
+#include <assert.h>
21
+#include <gpxe/efi/efi.h>
22
+#include <gpxe/ansiesc.h>
23
+#include <console.h>
24
+
25
+#define ATTR_BOLD		0x08
26
+
27
+#define ATTR_FCOL_MASK		0x07
28
+#define ATTR_FCOL_BLACK		0x00
29
+#define ATTR_FCOL_BLUE		0x01
30
+#define ATTR_FCOL_GREEN		0x02
31
+#define ATTR_FCOL_CYAN		0x03
32
+#define ATTR_FCOL_RED		0x04
33
+#define ATTR_FCOL_MAGENTA	0x05
34
+#define ATTR_FCOL_YELLOW	0x06
35
+#define ATTR_FCOL_WHITE		0x07
36
+
37
+#define ATTR_BCOL_MASK		0x70
38
+#define ATTR_BCOL_BLACK		0x00
39
+#define ATTR_BCOL_BLUE		0x10
40
+#define ATTR_BCOL_GREEN		0x20
41
+#define ATTR_BCOL_CYAN		0x30
42
+#define ATTR_BCOL_RED		0x40
43
+#define ATTR_BCOL_MAGENTA	0x50
44
+#define ATTR_BCOL_YELLOW	0x60
45
+#define ATTR_BCOL_WHITE		0x70
46
+
47
+#define ATTR_DEFAULT		ATTR_FCOL_WHITE
48
+
49
+/** Current character attribute */
50
+static unsigned int efi_attr = ATTR_DEFAULT;
51
+
52
+/**
53
+ * Handle ANSI CUP (cursor position)
54
+ *
55
+ * @v count		Parameter count
56
+ * @v params[0]		Row (1 is top)
57
+ * @v params[1]		Column (1 is left)
58
+ */
59
+static void efi_handle_cup ( unsigned int count __unused, int params[] ) {
60
+	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
61
+	int cx = ( params[1] - 1 );
62
+	int cy = ( params[0] - 1 );
63
+
64
+	if ( cx < 0 )
65
+		cx = 0;
66
+	if ( cy < 0 )
67
+		cy = 0;
68
+
69
+	conout->SetCursorPosition ( conout, cx, cy );
70
+}
71
+
72
+/**
73
+ * Handle ANSI ED (erase in page)
74
+ *
75
+ * @v count		Parameter count
76
+ * @v params[0]		Region to erase
77
+ */
78
+static void efi_handle_ed ( unsigned int count __unused,
79
+			     int params[] __unused ) {
80
+	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
81
+
82
+	/* We assume that we always clear the whole screen */
83
+	assert ( params[0] == ANSIESC_ED_ALL );
84
+
85
+	conout->ClearScreen ( conout );
86
+}
87
+
88
+/**
89
+ * Handle ANSI SGR (set graphics rendition)
90
+ *
91
+ * @v count		Parameter count
92
+ * @v params		List of graphic rendition aspects
93
+ */
94
+static void efi_handle_sgr ( unsigned int count, int params[] ) {
95
+	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
96
+	static const uint8_t efi_attr_fcols[10] = {
97
+		ATTR_FCOL_BLACK, ATTR_FCOL_RED, ATTR_FCOL_GREEN,
98
+		ATTR_FCOL_YELLOW, ATTR_FCOL_BLUE, ATTR_FCOL_MAGENTA,
99
+		ATTR_FCOL_CYAN, ATTR_FCOL_WHITE,
100
+		ATTR_FCOL_WHITE, ATTR_FCOL_WHITE /* defaults */
101
+	};
102
+	static const uint8_t efi_attr_bcols[10] = {
103
+		ATTR_BCOL_BLACK, ATTR_BCOL_RED, ATTR_BCOL_GREEN,
104
+		ATTR_BCOL_YELLOW, ATTR_BCOL_BLUE, ATTR_BCOL_MAGENTA,
105
+		ATTR_BCOL_CYAN, ATTR_BCOL_WHITE,
106
+		ATTR_BCOL_BLACK, ATTR_BCOL_BLACK /* defaults */
107
+	};
108
+	unsigned int i;
109
+	int aspect;
110
+
111
+	for ( i = 0 ; i < count ; i++ ) {
112
+		aspect = params[i];
113
+		if ( aspect == 0 ) {
114
+			efi_attr = ATTR_DEFAULT;
115
+		} else if ( aspect == 1 ) {
116
+			efi_attr |= ATTR_BOLD;
117
+		} else if ( aspect == 22 ) {
118
+			efi_attr &= ~ATTR_BOLD;
119
+		} else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
120
+			efi_attr &= ~ATTR_FCOL_MASK;
121
+			efi_attr |= efi_attr_fcols[ aspect - 30 ];
122
+		} else if ( ( aspect >= 40 ) && ( aspect <= 49 ) ) {
123
+			efi_attr &= ~ATTR_BCOL_MASK;
124
+			efi_attr |= efi_attr_bcols[ aspect - 40 ];
125
+		}
126
+	}
127
+
128
+	conout->SetAttribute ( conout, efi_attr );
129
+}
130
+
131
+/** EFI console ANSI escape sequence handlers */
132
+static struct ansiesc_handler efi_ansiesc_handlers[] = {
133
+	{ ANSIESC_CUP, efi_handle_cup },
134
+	{ ANSIESC_ED, efi_handle_ed },
135
+	{ ANSIESC_SGR, efi_handle_sgr },
136
+	{ 0, NULL }
137
+};
138
+
139
+/** EFI console ANSI escape sequence context */
140
+static struct ansiesc_context efi_ansiesc_ctx = {
141
+	.handlers = efi_ansiesc_handlers,
142
+};
143
+
144
+/**
145
+ * Print a character to EFI console
146
+ *
147
+ * @v character		Character to be printed
148
+ */
149
+static void efi_putchar ( int character ) {
150
+	EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout = efi_systab->ConOut;
151
+	wchar_t wstr[] = { character, 0 };
152
+
153
+	/* Intercept ANSI escape sequences */
154
+	character = ansiesc_process ( &efi_ansiesc_ctx, character );
155
+	if ( character < 0 )
156
+		return;
157
+
158
+	conout->OutputString ( conout, wstr );
159
+}
160
+
161
+/**
162
+ * Pointer to current ANSI output sequence
163
+ *
164
+ * While we are in the middle of returning an ANSI sequence for a
165
+ * special key, this will point to the next character to return.  When
166
+ * not in the middle of such a sequence, this will point to a NUL
167
+ * (note: not "will be NULL").
168
+ */
169
+static const char *ansi_input = "";
170
+
171
+/** Mapping from EFI scan codes to ANSI escape sequences */
172
+static const char *ansi_sequences[] = {
173
+	[SCAN_UP] = "[A",
174
+	[SCAN_DOWN] = "[B",
175
+	[SCAN_RIGHT] = "[C",
176
+	[SCAN_LEFT] = "[D",
177
+	[SCAN_HOME] = "[H",
178
+	[SCAN_END] = "[F",
179
+	[SCAN_INSERT] = "[2~",
180
+	/* EFI translates an incoming backspace via the serial console
181
+	 * into a SCAN_DELETE.  There's not much we can do about this.
182
+	 */
183
+	[SCAN_DELETE] = "[3~",
184
+	[SCAN_PAGE_UP] = "[5~",
185
+	[SCAN_PAGE_DOWN] = "[6~",
186
+	/* EFI translates some (but not all) incoming escape sequences
187
+	 * via the serial console into equivalent scancodes.  When it
188
+	 * doesn't recognise a sequence, it helpfully(!) translates
189
+	 * the initial ESC and passes the remainder through verbatim.
190
+	 * Treating SCAN_ESC as equivalent to an empty escape sequence
191
+	 * works around this bug.
192
+	 */
193
+	[SCAN_ESC] = "",
194
+};
195
+
196
+/**
197
+ * Get ANSI escape sequence corresponding to EFI scancode
198
+ *
199
+ * @v scancode		EFI scancode
200
+ * @ret ansi_seq	ANSI escape sequence, if any, otherwise NULL
201
+ */
202
+static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
203
+	if ( scancode < ( sizeof ( ansi_sequences ) /
204
+			  sizeof ( ansi_sequences[0] ) ) ) {
205
+		return ansi_sequences[scancode];
206
+	}
207
+	return NULL;
208
+}
209
+
210
+/**
211
+ * Get character from EFI console
212
+ *
213
+ * @ret character	Character read from console
214
+ */
215
+static int efi_getchar ( void ) {
216
+	EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
217
+	const char *ansi_seq;
218
+	EFI_INPUT_KEY key;
219
+	EFI_STATUS efirc;
220
+
221
+	/* If we are mid-sequence, pass out the next byte */
222
+	if ( *ansi_input )
223
+		return *(ansi_input++);
224
+
225
+	/* Read key from real EFI console */
226
+	if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) {
227
+		DBG ( "EFI could not read keystroke: %lx\n", efirc );
228
+		return 0;
229
+	}
230
+	DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n",
231
+	       key.UnicodeChar, key.ScanCode );
232
+
233
+	/* If key has a Unicode representation, return it */
234
+	if ( key.UnicodeChar )
235
+		return key.UnicodeChar;
236
+
237
+	/* Otherwise, check for a special key that we know about */
238
+	if ( ( ansi_seq = scancode_to_ansi_seq ( key.ScanCode ) ) ) {
239
+		/* Start of escape sequence: return ESC (0x1b) */
240
+		ansi_input = ansi_seq;
241
+		return 0x1b;
242
+	}
243
+
244
+	return 0;
245
+}
246
+
247
+/**
248
+ * Check for character ready to read from EFI console
249
+ *
250
+ * @ret True		Character available to read
251
+ * @ret False		No character available to read
252
+ */
253
+static int efi_iskey ( void ) {
254
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
255
+	EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin = efi_systab->ConIn;
256
+	EFI_STATUS efirc;
257
+
258
+	/* If we are mid-sequence, we are always ready */
259
+	if ( *ansi_input )
260
+		return 1;
261
+
262
+	/* Check to see if the WaitForKey event has fired */
263
+	if ( ( efirc = bs->CheckEvent ( conin->WaitForKey ) ) == 0 )
264
+		return 1;
265
+
266
+	return 0;
267
+}
268
+
269
+struct console_driver efi_console __console_driver = {
270
+	.putchar = efi_putchar,
271
+	.getchar = efi_getchar,
272
+	.iskey = efi_iskey,
273
+};

+ 83
- 0
src/interface/efi/efi_entry.c View File

@@ -0,0 +1,83 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdlib.h>
20
+#include <gpxe/efi/efi.h>
21
+#include <gpxe/uuid.h>
22
+
23
+/** Image handle passed to entry point */
24
+EFI_HANDLE efi_image_handle;
25
+
26
+/** System table passed to entry point */
27
+EFI_SYSTEM_TABLE *efi_systab;
28
+
29
+/** Declared used EFI protocols */
30
+static struct efi_protocol efi_protocols[0] \
31
+	__table_start ( struct efi_protocol, efi_protocols );
32
+static struct efi_protocol efi_protocols_end[0] \
33
+	__table_end ( struct efi_protocol, efi_protocols );
34
+
35
+/**
36
+ * EFI entry point
37
+ *
38
+ * @v image_handle	Image handle
39
+ * @v systab		System table
40
+ * @ret efirc		EFI return status code
41
+ */
42
+EFI_STATUS EFIAPI efi_entry ( EFI_HANDLE image_handle,
43
+			      EFI_SYSTEM_TABLE *systab ) {
44
+	EFI_BOOT_SERVICES *bs;
45
+	struct efi_protocol *prot;
46
+	EFI_STATUS efirc;
47
+
48
+	/* Store image handle and system table pointer for future use */
49
+	efi_image_handle = image_handle;
50
+	efi_systab = systab;
51
+
52
+	/* Sanity checks */
53
+	if ( ! systab )
54
+		return EFI_NOT_AVAILABLE_YET;
55
+	if ( ! systab->ConOut )
56
+		return EFI_NOT_AVAILABLE_YET;
57
+	if ( ! systab->BootServices ) {
58
+		DBGC ( systab, "EFI provided no BootServices entry point\n" );
59
+		return EFI_NOT_AVAILABLE_YET;
60
+	}
61
+	if ( ! systab->RuntimeServices ) {
62
+		DBGC ( systab, "EFI provided no RuntimeServices entry "
63
+		       "point\n" );
64
+		return EFI_NOT_AVAILABLE_YET;
65
+	}
66
+	DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
67
+
68
+	/* Look up required protocols */
69
+	bs = systab->BootServices;
70
+	for ( prot = efi_protocols ; prot < efi_protocols_end ; prot++ ) {
71
+		if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL,
72
+						    prot->protocol ) ) != 0 ) {
73
+			DBGC ( systab, "EFI does not provide protocol %s\n",
74
+			       uuid_ntoa ( &prot->u.uuid ) );
75
+			return efirc;
76
+		}
77
+		DBGC ( systab, "EFI protocol %s is at %p\n",
78
+		       uuid_ntoa ( &prot->u.uuid ), *(prot->protocol) );
79
+	}
80
+
81
+	/* Call to main() */
82
+	return RC_TO_EFIRC ( main () );
83
+}

+ 201
- 0
src/interface/efi/efi_io.c View File

@@ -0,0 +1,201 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <assert.h>
20
+#include <gpxe/io.h>
21
+#include <gpxe/efi/efi.h>
22
+#include <gpxe/efi/Protocol/CpuIo.h>
23
+#include <gpxe/efi/efi_io.h>
24
+
25
+/** @file
26
+ *
27
+ * gPXE I/O API for EFI
28
+ *
29
+ */
30
+
31
+/** CPU I/O protocol */
32
+static EFI_CPU_IO_PROTOCOL *cpu_io;
33
+EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
34
+
35
+/** Maximum address that can be used for port I/O */
36
+#define MAX_PORT_ADDRESS 0xffff
37
+
38
+/**
39
+ * Determine whether or not address is a port I/O address
40
+ *
41
+ * @v io_addr		I/O address
42
+ * @v is_port		I/O address is a port I/O address
43
+ */
44
+#define IS_PORT_ADDRESS(io_addr) \
45
+	( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
46
+
47
+/**
48
+ * Determine EFI CPU I/O width code
49
+ *
50
+ * @v size		Size of value
51
+ * @ret width		EFI width code
52
+ *
53
+ * Someone at Intel clearly gets paid by the number of lines of code
54
+ * they write.  No-one should ever be able to make I/O this
55
+ * convoluted.  The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite
56
+ * idiocy.
57
+ */
58
+static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) {
59
+	switch ( size ) {
60
+	case 1 :	return EfiCpuIoWidthFifoUint8;
61
+	case 2 :	return EfiCpuIoWidthFifoUint16;
62
+	case 4 :	return EfiCpuIoWidthFifoUint32;
63
+	case 8 :	return EfiCpuIoWidthFifoUint64;
64
+	default :
65
+		assert ( 0 );
66
+		/* I wonder what this will actually do... */
67
+		return EfiCpuIoWidthMaximum;
68
+	}
69
+}
70
+
71
+/**
72
+ * Read from device
73
+ *
74
+ * @v io_addr		I/O address
75
+ * @v size		Size of value
76
+ * @ret data		Value read
77
+ */
78
+unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) {
79
+	EFI_CPU_IO_PROTOCOL_IO_MEM read;
80
+	unsigned long long data = 0;
81
+	EFI_STATUS efirc;
82
+
83
+	read = ( IS_PORT_ADDRESS ( io_addr ) ?
84
+		 cpu_io->Io.Read : cpu_io->Mem.Read );
85
+
86
+	if ( ( efirc = read ( cpu_io, efi_width ( size ),
87
+			      ( intptr_t ) io_addr, 1,
88
+			      ( void * ) &data ) ) != 0 ) {
89
+		DBG ( "EFI I/O read at %p failed: %lx\n", io_addr, efirc );
90
+		return -1ULL;
91
+	}
92
+
93
+	return data;
94
+}
95
+
96
+/**
97
+ * Write to device
98
+ *
99
+ * @v data		Value to write
100
+ * @v io_addr		I/O address
101
+ * @v size		Size of value
102
+ */
103
+void efi_iowrite ( unsigned long long data, volatile void *io_addr,
104
+		   size_t size ) {
105
+	EFI_CPU_IO_PROTOCOL_IO_MEM write;
106
+	EFI_STATUS efirc;
107
+
108
+	write = ( IS_PORT_ADDRESS ( io_addr ) ?
109
+		  cpu_io->Io.Write : cpu_io->Mem.Write );
110
+
111
+	if ( ( efirc = write ( cpu_io, efi_width ( size ),
112
+			       ( intptr_t ) io_addr, 1,
113
+			       ( void * ) &data ) ) != 0 ) {
114
+		DBG ( "EFI I/O write at %p failed: %lx\n", io_addr, efirc );
115
+	}
116
+}
117
+
118
+/**
119
+ * String read from device
120
+ *
121
+ * @v io_addr		I/O address
122
+ * @v data		Data buffer
123
+ * @v size		Size of values
124
+ * @v count		Number of values to read
125
+ */
126
+void efi_ioreads ( volatile void *io_addr, void *data,
127
+		   size_t size, unsigned int count ) {
128
+	EFI_CPU_IO_PROTOCOL_IO_MEM read;
129
+	EFI_STATUS efirc;
130
+
131
+	read = ( IS_PORT_ADDRESS ( io_addr ) ?
132
+		 cpu_io->Io.Read : cpu_io->Mem.Read );
133
+
134
+	if ( ( efirc = read ( cpu_io, efi_width ( size ),
135
+			      ( intptr_t ) io_addr, count,
136
+			      ( void * ) data ) ) != 0 ) {
137
+		DBG ( "EFI I/O string read at %p failed: %lx\n",
138
+		      io_addr, efirc );
139
+	}
140
+}
141
+
142
+/**
143
+ * String write to device
144
+ *
145
+ * @v io_addr		I/O address
146
+ * @v data		Data buffer
147
+ * @v size		Size of values
148
+ * @v count		Number of values to write
149
+ */
150
+void efi_iowrites ( volatile void *io_addr, const void *data,
151
+		    size_t size, unsigned int count ) {
152
+	EFI_CPU_IO_PROTOCOL_IO_MEM write;
153
+	EFI_STATUS efirc;
154
+
155
+	write = ( IS_PORT_ADDRESS ( io_addr ) ?
156
+		 cpu_io->Io.Write : cpu_io->Mem.Write );
157
+
158
+	if ( ( efirc = write ( cpu_io, efi_width ( size ),
159
+			       ( intptr_t ) io_addr, count,
160
+			       ( void * ) data ) ) != 0 ) {
161
+		DBG ( "EFI I/O write at %p failed: %lx\n",
162
+		      io_addr, efirc );
163
+	}
164
+}
165
+
166
+/**
167
+ * Wait for I/O-mapped operation to complete
168
+ *
169
+ */
170
+static void efi_iodelay ( void ) {
171
+	/* Write to non-existent port.  Probably x86-only. */
172
+	outb ( 0, 0x80 );
173
+}
174
+
175
+PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
176
+PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
177
+PROVIDE_IOAPI_INLINE ( efi, ioremap );
178
+PROVIDE_IOAPI_INLINE ( efi, iounmap );
179
+PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
180
+PROVIDE_IOAPI_INLINE ( efi, readb );
181
+PROVIDE_IOAPI_INLINE ( efi, readw );
182
+PROVIDE_IOAPI_INLINE ( efi, readl );
183
+PROVIDE_IOAPI_INLINE ( efi, readq );
184
+PROVIDE_IOAPI_INLINE ( efi, writeb );
185
+PROVIDE_IOAPI_INLINE ( efi, writew );
186
+PROVIDE_IOAPI_INLINE ( efi, writel );
187
+PROVIDE_IOAPI_INLINE ( efi, writeq );
188
+PROVIDE_IOAPI_INLINE ( efi, inb );
189
+PROVIDE_IOAPI_INLINE ( efi, inw );
190
+PROVIDE_IOAPI_INLINE ( efi, inl );
191
+PROVIDE_IOAPI_INLINE ( efi, outb );
192
+PROVIDE_IOAPI_INLINE ( efi, outw );
193
+PROVIDE_IOAPI_INLINE ( efi, outl );
194
+PROVIDE_IOAPI_INLINE ( efi, insb );
195
+PROVIDE_IOAPI_INLINE ( efi, insw );
196
+PROVIDE_IOAPI_INLINE ( efi, insl );
197
+PROVIDE_IOAPI_INLINE ( efi, outsb );
198
+PROVIDE_IOAPI_INLINE ( efi, outsw );
199
+PROVIDE_IOAPI_INLINE ( efi, outsl );
200
+PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
201
+PROVIDE_IOAPI_INLINE ( efi, mb );

+ 81
- 0
src/interface/efi/efi_pci.c View File

@@ -0,0 +1,81 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <errno.h>
20
+#include <gpxe/pci.h>
21
+#include <gpxe/efi/efi.h>
22
+#include <gpxe/efi/Protocol/PciRootBridgeIo.h>
23
+
24
+/** @file
25
+ *
26
+ * gPXE PCI I/O API for EFI
27
+ *
28
+ */
29
+
30
+/** PCI root bridge I/O protocol */
31
+static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
32
+EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
33
+
34
+static unsigned long efipci_address ( struct pci_device *pci,
35
+				      unsigned long location ) {
36
+	return EFI_PCI_ADDRESS ( pci->bus, PCI_SLOT ( pci->devfn ),
37
+				 PCI_FUNC ( pci->devfn ),
38
+				 EFIPCI_OFFSET ( location ) );
39
+}
40
+
41
+int efipci_read ( struct pci_device *pci, unsigned long location,
42
+		  void *value ) {
43
+	EFI_STATUS efirc;
44
+
45
+	if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ),
46
+					  efipci_address ( pci, location ), 1,
47
+					  value ) ) != 0 ) {
48
+		DBG ( "EFIPCI config read from %02x:%02x.%x offset %02lx "
49
+		      "failed: %lx\n", pci->bus, PCI_SLOT ( pci->devfn ),
50
+		      PCI_FUNC ( pci->devfn ), EFIPCI_OFFSET ( location ),
51
+		      efirc );
52
+		return -EIO;
53
+	}
54
+
55
+	return 0;
56
+}
57
+
58
+int efipci_write ( struct pci_device *pci, unsigned long location,
59
+		   unsigned long value ) {
60
+	EFI_STATUS efirc;
61
+
62
+	if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ),
63
+					   efipci_address ( pci, location ), 1,
64
+					   &value ) ) != 0 ) {
65
+		DBG ( "EFIPCI config write to %02x:%02x.%x offset %02lx "
66
+		      "failed: %lx\n", pci->bus, PCI_SLOT ( pci->devfn ),
67
+		      PCI_FUNC ( pci->devfn ), EFIPCI_OFFSET ( location ),
68
+		      efirc );
69
+		return -EIO;
70
+	}
71
+
72
+	return 0;
73
+}
74
+
75
+PROVIDE_PCIAPI_INLINE ( efi, pci_max_bus );
76
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte );
77
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word );
78
+PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword );
79
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
80
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
81
+PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword );

+ 115
- 0
src/interface/efi/efi_timer.c View File

@@ -0,0 +1,115 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <limits.h>
20
+#include <assert.h>
21
+#include <unistd.h>
22
+#include <gpxe/timer.h>
23
+#include <gpxe/efi/efi.h>
24
+#include <gpxe/efi/Protocol/Cpu.h>
25
+
26
+/** @file
27
+ *
28
+ * gPXE timer API for EFI
29
+ *
30
+ */
31
+
32
+/** Scale factor to apply to CPU timer 0
33
+ *
34
+ * The timer is scaled down in order to ensure that reasonable values
35
+ * for "number of ticks" don't exceed the size of an unsigned long.
36
+ */
37
+#define EFI_TIMER0_SHIFT 12
38
+
39
+/** Calibration time */
40
+#define EFI_CALIBRATE_DELAY_MS 1
41
+
42
+/** CPU protocol */
43
+static EFI_CPU_ARCH_PROTOCOL *cpu_arch;
44
+EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch );
45
+
46
+/**
47
+ * Delay for a fixed number of microseconds
48
+ *
49
+ * @v usecs		Number of microseconds for which to delay
50
+ */
51
+static void efi_udelay ( unsigned long usecs ) {
52
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
53
+	EFI_STATUS efirc;
54
+
55
+	if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) {
56
+		DBG ( "EFI could not delay for %ldus: %lx\n",
57
+		      usecs, efirc );
58
+		/* Probably screwed */
59
+	}
60
+}
61
+
62
+/**
63
+ * Get current system time in ticks
64
+ *
65
+ * @ret ticks		Current time, in ticks
66
+ */
67
+static unsigned long efi_currticks ( void ) {
68
+	UINT64 time;
69
+	EFI_STATUS efirc;
70
+
71
+	/* Read CPU timer 0 (TSC) */
72
+	if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time,
73
+						 NULL ) ) != 0 ) {
74
+		DBG ( "EFI could not read CPU timer: %lx\n", efirc );
75
+		/* Probably screwed */
76
+		return -1UL;
77
+	}
78
+
79
+	return ( time >> EFI_TIMER0_SHIFT );
80
+}
81
+
82
+/**
83
+ * Get number of ticks per second
84
+ *
85
+ * @ret ticks_per_sec	Number of ticks per second
86
+ */
87
+static unsigned long efi_ticks_per_sec ( void ) {
88
+	static unsigned long ticks_per_sec = 0;
89
+
90
+	/* Calibrate timer, if necessary.  EFI does nominally provide
91
+	 * the timer speed via the (optional) TimerPeriod parameter to
92
+	 * the GetTimerValue() call, but it gets the speed slightly
93
+	 * wrong.  By up to three orders of magnitude.  Not helpful.
94
+	 */
95
+	if ( ! ticks_per_sec ) {
96
+		unsigned long start;
97
+		unsigned long elapsed;
98
+
99
+		DBG ( "Calibrating EFI timer with a %d ms delay\n",
100
+		      EFI_CALIBRATE_DELAY_MS );
101
+		start = currticks();
102
+		mdelay ( EFI_CALIBRATE_DELAY_MS );
103
+		elapsed = ( currticks() - start );
104
+		ticks_per_sec = ( elapsed * ( 1000 / EFI_CALIBRATE_DELAY_MS ));
105
+		DBG ( "EFI CPU timer calibrated at %ld ticks in %d ms (%ld "
106
+		      "ticks/sec)\n", elapsed, EFI_CALIBRATE_DELAY_MS,
107
+		      ticks_per_sec );
108
+	}
109
+
110
+	return ticks_per_sec;
111
+}
112
+
113
+PROVIDE_TIMER ( efi, udelay, efi_udelay );
114
+PROVIDE_TIMER ( efi, currticks, efi_currticks );
115
+PROVIDE_TIMER ( efi, ticks_per_sec, efi_ticks_per_sec );

+ 37
- 0
src/interface/efi/efi_uaccess.c View File

@@ -0,0 +1,37 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <gpxe/uaccess.h>
20
+#include <gpxe/efi/efi.h>
21
+
22
+/** @file
23
+ *
24
+ * gPXE user access API for EFI
25
+ *
26
+ */
27
+
28
+PROVIDE_UACCESS_INLINE ( efi, phys_to_user );
29
+PROVIDE_UACCESS_INLINE ( efi, user_to_phys );
30
+PROVIDE_UACCESS_INLINE ( efi, virt_to_user );
31
+PROVIDE_UACCESS_INLINE ( efi, user_to_virt );
32
+PROVIDE_UACCESS_INLINE ( efi, userptr_add );
33
+PROVIDE_UACCESS_INLINE ( efi, memcpy_user );
34
+PROVIDE_UACCESS_INLINE ( efi, memmove_user );
35
+PROVIDE_UACCESS_INLINE ( efi, memset_user );
36
+PROVIDE_UACCESS_INLINE ( efi, strlen_user );
37
+PROVIDE_UACCESS_INLINE ( efi, memchr_user );

+ 96
- 0
src/interface/efi/efi_umalloc.c View File

@@ -0,0 +1,96 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <assert.h>
20
+#include <gpxe/umalloc.h>
21
+#include <gpxe/efi/efi.h>
22
+
23
+/** @file
24
+ *
25
+ * gPXE user memory allocation API for EFI
26
+ *
27
+ */
28
+
29
+/** Equivalent of NOWHERE for user pointers */
30
+#define UNOWHERE ( ~UNULL )
31
+
32
+/**
33
+ * Reallocate external memory
34
+ *
35
+ * @v old_ptr		Memory previously allocated by umalloc(), or UNULL
36
+ * @v new_size		Requested size
37
+ * @ret new_ptr		Allocated memory, or UNULL
38
+ *
39
+ * Calling realloc() with a new size of zero is a valid way to free a
40
+ * memory block.
41
+ */
42
+static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) {
43
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
44
+	EFI_PHYSICAL_ADDRESS phys_addr;
45
+	unsigned int new_pages, old_pages;
46
+	userptr_t new_ptr = UNOWHERE;
47
+	size_t old_size;
48
+	EFI_STATUS efirc;
49
+
50
+	/* Allocate new memory if necessary.  If allocation fails,
51
+	 * return without touching the old block.
52
+	 */
53
+	if ( new_size ) {
54
+		new_pages = ( EFI_SIZE_TO_PAGES ( new_size ) + 1 );
55
+		if ( ( efirc = bs->AllocatePages ( AllocateAnyPages,
56
+						   EfiBootServicesData,
57
+						   new_pages,
58
+						   &phys_addr ) ) != 0 ) {
59
+			DBG ( "EFI could not allocate %d pages: %lx\n",
60
+			      new_pages, efirc );
61
+			return UNULL;
62
+		}
63
+		assert ( phys_addr != 0 );
64
+		new_ptr = phys_to_user ( phys_addr + EFI_PAGE_SIZE );
65
+		copy_to_user ( new_ptr, -EFI_PAGE_SIZE,
66
+			       &new_size, sizeof ( new_size ) );
67
+		DBG ( "EFI allocated %d pages at %llx\n",
68
+		      new_pages, phys_addr );
69
+	}
70
+
71
+	/* Copy across relevant part of the old data region (if any),
72
+	 * then free it.  Note that at this point either (a) new_ptr
73
+	 * is valid, or (b) new_size is 0; either way, the memcpy() is
74
+	 * valid.
75
+	 */
76
+	if ( old_ptr && ( old_ptr != UNOWHERE ) ) {
77
+		copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE,
78
+				 sizeof ( old_size ) );
79
+		memcpy_user ( new_ptr, 0, old_ptr, 0,
80
+			      ( (old_size < new_size) ? old_size : new_size ));
81
+		old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 );
82
+		phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE );
83
+		if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){
84
+			DBG ( "EFI could not free %d pages at %llx: %lx\n",
85
+			      old_pages, phys_addr, efirc );
86
+			/* Not fatal; we have leaked memory but successfully
87
+			 * allocated (if asked to do so).
88
+			 */
89
+		}
90
+		DBG ( "EFI freed %d pages at %llx\n", old_pages, phys_addr );
91
+	}
92
+
93
+	return new_ptr;
94
+}
95
+
96
+PROVIDE_UMALLOC ( efi, urealloc, efi_urealloc );

+ 1
- 0
src/util/.gitignore View File

@@ -2,3 +2,4 @@ nrv2b
2 2
 zbin
3 3
 hijack
4 4
 prototester
5
+efilink

+ 507
- 0
src/util/efilink.c View File

@@ -0,0 +1,507 @@
1
+#include <stdint.h>
2
+#include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+#include <unistd.h>
6
+#include <errno.h>
7
+#include <bfd.h>
8
+
9
+struct bfd_file {
10
+	bfd *bfd;
11
+	asymbol **symtab;
12
+	long symcount;
13
+};
14
+
15
+struct pe_relocs {
16
+	struct pe_relocs *next;
17
+	unsigned long start_rva;
18
+	unsigned int used_relocs;
19
+	unsigned int total_relocs;
20
+	uint16_t *relocs;
21
+};
22
+
23
+/**
24
+ * Allocate memory
25
+ *
26
+ * @v len		Length of memory to allocate
27
+ * @ret ptr		Pointer to allocated memory
28
+ */
29
+static void * xmalloc ( size_t len ) {
30
+	void *ptr;
31
+
32
+	ptr = malloc ( len );
33
+	if ( ! ptr ) {
34
+		fprintf ( stderr, "Could not allocate %zd bytes\n", len );
35
+		exit ( 1 );
36
+	}
37
+
38
+	return ptr;
39
+}
40
+
41
+/**
42
+ * Generate entry in PE relocation table
43
+ *
44
+ * @v pe_reltab		PE relocation table
45
+ * @v rva		RVA
46
+ * @v size		Size of relocation entry
47
+ */
48
+static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
49
+				unsigned long rva, size_t size ) {
50
+	unsigned long start_rva;
51
+	uint16_t reloc;
52
+	struct pe_relocs *pe_rel;
53
+	uint16_t *relocs;
54
+
55
+	/* Construct */
56
+	start_rva = ( rva & ~0xfff );
57
+	reloc = ( rva & 0xfff );
58
+	switch ( size ) {
59
+	case 4:
60
+		reloc |= 0x3000;
61
+		break;
62
+	case 2:
63
+		reloc |= 0x2000;
64
+		break;
65
+	default:
66
+		fprintf ( stderr, "Unsupported relocation size %zd\n", size );
67
+		exit ( 1 );
68
+	}
69
+
70
+	/* Locate or create PE relocation table */
71
+	for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
72
+		if ( pe_rel->start_rva == start_rva )
73
+			break;
74
+	}
75
+	if ( ! pe_rel ) {
76
+		pe_rel = xmalloc ( sizeof ( *pe_rel ) );
77
+		memset ( pe_rel, 0, sizeof ( *pe_rel ) );
78
+		pe_rel->next = *pe_reltab;
79
+		*pe_reltab = pe_rel;
80
+		pe_rel->start_rva = start_rva;
81
+	}
82
+
83
+	/* Expand relocation list if necessary */
84
+	if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
85
+		relocs = pe_rel->relocs;
86
+	} else {
87
+		pe_rel->total_relocs = ( pe_rel->total_relocs ?
88
+					 ( pe_rel->total_relocs * 2 ) : 256 );
89
+		relocs = xmalloc ( pe_rel->total_relocs *
90
+				   sizeof ( pe_rel->relocs[0] ) );
91
+		memset ( relocs, 0,
92
+			 pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
93
+		memcpy ( relocs, pe_rel->relocs,
94
+			 pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
95
+		free ( pe_rel->relocs );
96
+		pe_rel->relocs = relocs;
97
+	}
98
+
99
+	/* Store relocation */
100
+	pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
101
+}
102
+
103
+/**
104
+ * Calculate size of binary PE relocation table
105
+ *
106
+ * @v pe_reltab		PE relocation table
107
+ * @v buffer		Buffer to contain binary table, or NULL
108
+ * @ret size		Size of binary table
109
+ */
110
+static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
111
+				 void *buffer ) {
112
+	struct pe_relocs *pe_rel;
113
+	unsigned int num_relocs;
114
+	size_t size;
115
+	size_t total_size = 0;
116
+
117
+	for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
118
+		num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
119
+		size = ( sizeof ( uint32_t ) /* VirtualAddress */ +
120
+			 sizeof ( uint32_t ) /* SizeOfBlock */ +
121
+			 ( num_relocs * sizeof ( uint16_t ) ) );
122
+		if ( buffer ) {
123
+			*( (uint32_t *) ( buffer + total_size + 0 ) )
124
+				= pe_rel->start_rva;
125
+			*( (uint32_t *) ( buffer + total_size + 4 ) ) = size;
126
+			memcpy ( ( buffer + total_size + 8 ), pe_rel->relocs,
127
+				 ( num_relocs * sizeof ( uint16_t ) ) );
128
+		}
129
+		total_size += size;
130
+	}
131
+
132
+	return total_size;
133
+}
134
+
135
+/**
136
+ * Read symbol table
137
+ *
138
+ * @v bfd		BFD file
139
+ */
140
+static void read_symtab ( struct bfd_file *bfd ) {
141
+	long symtab_size;
142
+
143
+	/* Get symbol table size */
144
+	symtab_size = bfd_get_symtab_upper_bound ( bfd->bfd );
145
+	if ( symtab_size < 0 ) {
146
+		bfd_perror ( "Could not get symbol table upper bound" );
147
+		exit ( 1 );
148
+	}
149
+
150
+	/* Allocate and read symbol table */
151
+	bfd->symtab = xmalloc ( symtab_size );
152
+	bfd->symcount = bfd_canonicalize_symtab ( bfd->bfd, bfd->symtab );
153
+	if ( bfd->symcount < 0 ) {
154
+		bfd_perror ( "Cannot read symbol table" );
155
+		exit ( 1 );
156
+	}
157
+}
158
+
159
+/**
160
+ * Read relocation table
161
+ *
162
+ * @v bfd		BFD file
163
+ * @v section		Section
164
+ * @v symtab		Symbol table
165
+ * @ret reltab		Relocation table
166
+ */
167
+static arelent ** read_reltab ( struct bfd_file *bfd, asection *section ) {
168
+	long reltab_size;
169
+	arelent **reltab;
170
+	long numrels;
171
+
172
+	/* Get relocation table size */
173
+	reltab_size = bfd_get_reloc_upper_bound ( bfd->bfd, section );
174
+	if ( reltab_size < 0 ) {
175
+		bfd_perror ( "Could not get relocation table upper bound" );
176
+		exit ( 1 );
177
+	}
178
+
179
+	/* Allocate and read relocation table */
180
+	reltab = xmalloc ( reltab_size );
181
+	numrels = bfd_canonicalize_reloc ( bfd->bfd, section, reltab,
182
+					   bfd->symtab );
183
+	if ( numrels < 0 ) {
184
+		bfd_perror ( "Cannot read relocation table" );
185
+		exit ( 1 );
186
+	}
187
+
188
+	return reltab;
189
+}
190
+
191
+
192
+/**
193
+ * Open input BFD file
194
+ *
195
+ * @v filename		File name
196
+ * @ret ibfd		BFD file
197
+ */
198
+static struct bfd_file * open_input_bfd ( const char *filename ) {
199
+	struct bfd_file *ibfd;
200
+
201
+	/* Create BFD file */
202
+	ibfd = xmalloc ( sizeof ( *ibfd ) );
203
+	memset ( ibfd, 0, sizeof ( *ibfd ) );
204
+
205
+	/* Open the file */
206
+	ibfd->bfd = bfd_openr ( filename, NULL );
207
+	if ( ! ibfd->bfd ) {
208
+		fprintf ( stderr, "Cannot open %s: ", filename );
209
+		bfd_perror ( NULL );
210
+		exit ( 1 );
211
+	}
212
+
213
+	/* The call to bfd_check_format() must be present, otherwise
214
+	 * we get a segfault from later BFD calls.
215
+	 */
216
+	if ( bfd_check_format ( ibfd->bfd, bfd_object ) < 0 ) {
217
+		fprintf ( stderr, "%s is not an object file\n", filename );
218
+		exit ( 1 );
219
+	}
220
+
221
+	/* Read symbols and relocation entries */
222
+	read_symtab ( ibfd );
223
+
224
+	return ibfd;
225
+}
226
+
227
+/**
228
+ * Open output BFD file
229
+ *
230
+ * @v filename		File name
231
+ * @v ibfd		Input BFD file
232
+ * @ret obfd		BFD file
233
+ */
234
+static struct bfd_file * open_output_bfd ( const char *filename,
235
+					   struct bfd_file *ibfd ) {
236
+	struct bfd_file *obfd;
237
+	asection *isection;
238
+	asection *osection;
239
+
240
+	/*
241
+	 * Most of this code is based on what objcopy.c does.
242
+	 *
243
+	 */
244
+
245
+	/* Create BFD file */
246
+	obfd = xmalloc ( sizeof ( *obfd ) );
247
+	memset ( obfd, 0, sizeof ( *obfd ) );
248
+
249
+	/* Open the file */
250
+	obfd->bfd = bfd_openw ( filename, ibfd->bfd->xvec->name );
251
+	if ( ! obfd->bfd ) {
252
+		fprintf ( stderr, "Cannot open %s: ", filename );
253
+		bfd_perror ( NULL );
254
+		exit ( 1 );
255
+	}
256
+
257
+	/* Copy per-file data */
258
+	if ( ! bfd_set_arch_mach ( obfd->bfd, bfd_get_arch ( ibfd->bfd ),
259
+				   bfd_get_mach ( ibfd->bfd ) ) ) {
260
+		bfd_perror ( "Cannot copy architecture" );
261
+		exit ( 1 );
262
+	}
263
+	if ( ! bfd_set_format ( obfd->bfd, bfd_get_format ( ibfd->bfd ) ) ) {
264
+		bfd_perror ( "Cannot copy format" );
265
+		exit ( 1 );
266
+	}
267
+	if ( ! bfd_copy_private_header_data ( ibfd->bfd, obfd->bfd ) ) {
268
+		bfd_perror ( "Cannot copy private header data" );
269
+		exit ( 1 );
270
+	}
271
+
272
+	/* Create sections */
273
+	for ( isection = ibfd->bfd->sections ; isection ;
274
+	      isection = isection->next ) {
275
+		osection = bfd_make_section_anyway ( obfd->bfd,
276
+						     isection->name );
277
+		if ( ! osection ) {
278
+			bfd_perror ( "Cannot create section" );
279
+			exit ( 1 );
280
+		}
281
+		if ( ! bfd_set_section_flags ( obfd->bfd, osection,
282
+					       isection->flags ) ) {
283
+			bfd_perror ( "Cannot copy section flags" );
284
+			exit ( 1 );
285
+		}
286
+		if ( ! bfd_set_section_size ( obfd->bfd, osection,
287
+				 bfd_section_size ( ibfd->bfd, isection ) ) ) {
288
+			bfd_perror ( "Cannot copy section size" );
289
+			exit ( 1 );
290
+		}
291
+		if ( ! bfd_set_section_vma ( obfd->bfd, osection,
292
+				  bfd_section_vma ( ibfd->bfd, isection ) ) ) {
293
+			bfd_perror ( "Cannot copy section VMA" );
294
+			exit ( 1 );
295
+		}
296
+		osection->lma = bfd_section_lma ( ibfd->bfd, isection );
297
+		if ( ! bfd_set_section_alignment ( obfd->bfd, osection,
298
+			    bfd_section_alignment ( ibfd->bfd, isection ) ) ) {
299
+			bfd_perror ( "Cannot copy section alignment" );
300
+			exit ( 1 );
301
+		}
302
+		osection->entsize = isection->entsize;
303
+		isection->output_section = osection;
304
+		isection->output_offset = 0;
305
+		if ( ! bfd_copy_private_section_data ( ibfd->bfd, isection,
306
+						       obfd->bfd, osection ) ){
307
+			bfd_perror ( "Cannot copy section private data" );
308
+			exit ( 1 );
309
+		}
310
+	}
311
+
312
+	/* Copy symbol table */
313
+	bfd_set_symtab ( obfd->bfd, ibfd->symtab, ibfd->symcount );
314
+	obfd->symtab = ibfd->symtab;
315
+
316
+	return obfd;
317
+}
318
+
319
+/**
320
+ * Copy section from input BFD file to output BFD file
321
+ *
322
+ * @v obfd		Output BFD file
323
+ * @v ibfd		Input BFD file
324
+ * @v section		Section
325
+ */
326
+static void copy_bfd_section ( struct bfd_file *obfd, struct bfd_file *ibfd,
327
+			       asection *isection ) {
328
+	size_t size;
329
+	void *buf;
330
+	arelent **reltab;
331
+	arelent **rel;
332
+	char *errmsg;
333
+
334
+	/* Read in original section */
335
+	size = bfd_section_size ( ibfd->bfd, isection );
336
+	if ( ! size )
337
+		return;
338
+	buf = xmalloc ( size );
339
+	if ( ( ! bfd_get_section_contents ( ibfd->bfd, isection,
340
+					    buf, 0, size ) ) ) {
341
+		fprintf ( stderr, "Cannot read section %s: ", isection->name );
342
+		bfd_perror ( NULL );
343
+		exit ( 1 );
344
+	}
345
+
346
+	/* Perform relocations.  We do this here, rather than letting
347
+	 * ld do it for us when creating the input ELF file, so that
348
+	 * we can change symbol values as a result of having created
349
+	 * the .reloc section.
350
+	 */
351
+	reltab = read_reltab ( ibfd, isection );
352
+	for ( rel = reltab ; *rel ; rel++ ) {
353
+		bfd_perform_relocation ( ibfd->bfd, *rel, buf, isection,
354
+					 NULL, &errmsg );
355
+	}
356
+	free ( reltab );
357
+
358
+	/* Write out modified section */
359
+	if ( ( ! bfd_set_section_contents ( obfd->bfd,
360
+					    isection->output_section,
361
+					    buf, 0, size ) ) ) {
362
+		fprintf ( stderr, "Cannot write section %s: ",
363
+			  isection->output_section->name );
364
+		bfd_perror ( NULL );
365
+		exit ( 1 );
366
+	}
367
+
368
+	free ( buf );
369
+}
370
+
371
+/**
372
+ * Process relocation record
373
+ *
374
+ * @v section		Section
375
+ * @v rel		Relocation entry
376
+ * @v pe_reltab		PE relocation table to fill in
377
+ */
378
+static void process_reloc ( asection *section, arelent *rel,
379
+			    struct pe_relocs **pe_reltab ) {
380
+	reloc_howto_type *howto = rel->howto;
381
+	asymbol *sym = *(rel->sym_ptr_ptr);
382
+	unsigned long offset = ( section->lma + rel->address );
383
+
384
+	if ( bfd_is_abs_section ( sym->section ) ) {
385
+		/* Skip absolute symbols; the symbol value won't
386
+		 * change when the object is loaded.
387
+		 */
388
+	} else if ( strcmp ( howto->name, "R_386_32" ) == 0 ) {
389
+		/* Generate a 4-byte PE relocation */
390
+		generate_pe_reloc ( pe_reltab, offset, 4 );
391
+	} else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
392
+		/* Generate a 2-byte PE relocation */
393
+		generate_pe_reloc ( pe_reltab, offset, 2 );
394
+	} else if ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) {
395
+		/* Skip PC-relative relocations; all relative offsets
396
+		 * remain unaltered when the object is loaded.
397
+		 */
398
+	} else {
399
+		fprintf ( stderr, "Unrecognised relocation type %s\n",
400
+			  howto->name );
401
+		exit ( 1 );
402
+	}
403
+}
404
+
405
+/**
406
+ * Create .reloc section
407
+ *
408
+ * obfd			Output BFD file
409
+ * section		.reloc section in output file
410
+ * pe_reltab		PE relocation table
411
+ */
412
+static void create_reloc_section ( struct bfd_file *obfd, asection *section,
413
+				   struct pe_relocs *pe_reltab ) {
414
+	size_t raw_size;
415
+	size_t size;
416
+	size_t old_size;
417
+	void *buf;
418
+	asymbol **sym;
419
+
420
+	/* Build binary PE relocation table */
421
+	raw_size = output_pe_reltab ( pe_reltab, NULL );
422
+	size = ( ( raw_size + 31 ) & ~31 );
423
+	buf = xmalloc ( size );
424
+	memset ( buf, 0, size );
425
+	output_pe_reltab ( pe_reltab, buf );
426
+
427
+	/* Write .reloc section */
428
+	old_size = bfd_section_size ( obfd->bfd, section );
429
+	if ( ! bfd_set_section_size ( obfd->bfd, section, size ) ) {
430
+		bfd_perror ( "Cannot resize .reloc section" );
431
+		exit ( 1 );
432
+	}
433
+	if ( ! bfd_set_section_contents ( obfd->bfd, section,
434
+					  buf, 0, size ) ) {
435
+		bfd_perror ( "Cannot set .reloc section contents" );
436
+		exit ( 1 );
437
+	}
438
+
439
+	/* Update symbols pertaining to the relocation directory */
440
+	for ( sym = obfd->symtab ; *sym ; sym++ ) {
441
+		if ( strcmp ( (*sym)->name, "_reloc_memsz" ) == 0 ) {
442
+			(*sym)->value = size;
443
+		} else if ( strcmp ( (*sym)->name, "_reloc_filesz" ) == 0 ){
444
+			(*sym)->value = raw_size;
445
+		} else if ( strcmp ( (*sym)->name, "_filesz" ) == 0 ) {
446
+			(*sym)->value += ( size - old_size );
447
+		}
448
+	}
449
+}
450
+
451
+int main ( int argc, const char *argv[] ) {
452
+	const char *iname;
453
+	const char *oname;
454
+	struct bfd_file *ibfd;
455
+	struct bfd_file *obfd;
456
+	asection *section;
457
+	arelent **reltab;
458
+	arelent **rel;
459
+	struct pe_relocs *pe_reltab = NULL;
460
+	asection *reloc_section;
461
+
462
+	/* Initialise libbfd */
463
+	bfd_init();
464
+
465
+	/* Identify intput and output files */
466
+	if ( argc != 3 ) {
467
+		fprintf ( stderr, "Syntax: %s infile outfile\n", argv[0] );
468
+		exit ( 1 );
469
+	}
470
+	iname = argv[1];
471
+	oname = argv[2];
472
+
473
+	/* Open BFD files */
474
+	ibfd = open_input_bfd ( iname );
475
+	obfd = open_output_bfd ( oname, ibfd );
476
+
477
+	/* Process relocations in all sections */
478
+	for ( section = ibfd->bfd->sections ; section ;
479
+	      section = section->next ) {
480
+		reltab = read_reltab ( ibfd, section );
481
+		for ( rel = reltab ; *rel ; rel++ ) {
482
+			process_reloc ( section, *rel, &pe_reltab );
483
+		}
484
+		free ( reltab );
485
+	}
486
+
487
+	/* Create modified .reloc section */
488
+	reloc_section = bfd_get_section_by_name ( obfd->bfd, ".reloc" );
489
+	if ( ! reloc_section ) {
490
+		fprintf ( stderr, "Cannot find .reloc section\n" );
491
+		exit ( 1 );
492
+	}
493
+	create_reloc_section ( obfd, reloc_section, pe_reltab );
494
+
495
+	/* Copy other section contents */
496
+	for ( section = ibfd->bfd->sections ; section ;
497
+	      section = section->next ) {
498
+		if ( section->output_section != reloc_section )
499
+			copy_bfd_section ( obfd, ibfd, section );
500
+	}
501
+
502
+	/* Write out files and clean up */
503
+	bfd_close ( obfd->bfd );
504
+	bfd_close ( ibfd->bfd );
505
+
506
+	return 0;
507
+}

Loading…
Cancel
Save