iPXE
efi_init.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include <string.h>
23 #include <errno.h>
24 #include <ipxe/init.h>
25 #include <ipxe/efi/efi.h>
26 #include <ipxe/efi/efi_driver.h>
28 
29 /** Image handle passed to entry point */
31 
32 /** Loaded image protocol for this image */
34 
35 /** System table passed to entry point
36  *
37  * We construct the symbol name efi_systab via the PLATFORM macro.
38  * This ensures that the symbol is defined only in EFI builds, and so
39  * prevents EFI code from being incorrectly linked in to a non-EFI
40  * build.
41  */
42 EFI_SYSTEM_TABLE * _C2 ( PLATFORM, _systab );
43 
44 /** EFI shutdown is in progress */
46 
47 /** Event used to signal shutdown */
49 
50 /* Forward declarations */
51 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
52 
53 /**
54  * Shut down in preparation for booting an OS.
55  *
56  * This hook gets called at ExitBootServices time in order to make
57  * sure that everything is properly shut down before the OS takes
58  * over.
59  */
61  void *context __unused ) {
62 
63  /* Mark shutdown as being in progress, to indicate that large
64  * parts of the system (e.g. timers) are no longer functional.
65  */
67 
68  /* Shut down iPXE */
69  shutdown_boot();
70 }
71 
72 /**
73  * Look up EFI configuration table
74  *
75  * @v guid Configuration table GUID
76  * @ret table Configuration table, or NULL
77  */
78 static void * efi_find_table ( EFI_GUID *guid ) {
79  unsigned int i;
80 
81  for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
83  guid, sizeof ( *guid ) ) == 0 )
85  }
86 
87  return NULL;
88 }
89 
90 /**
91  * Initialise EFI environment
92  *
93  * @v image_handle Image handle
94  * @v systab System table
95  * @ret efirc EFI return status code
96  */
98  EFI_SYSTEM_TABLE *systab ) {
100  struct efi_protocol *prot;
101  struct efi_config_table *tab;
102  void *loaded_image;
103  EFI_STATUS efirc;
104  int rc;
105 
106  /* Store image handle and system table pointer for future use */
107  efi_image_handle = image_handle;
108  efi_systab = systab;
109 
110  /* Sanity checks */
111  if ( ! systab ) {
112  efirc = EFI_NOT_AVAILABLE_YET;
113  goto err_sanity;
114  }
115  if ( ! systab->ConOut ) {
116  efirc = EFI_NOT_AVAILABLE_YET;
117  goto err_sanity;
118  }
119  if ( ! systab->BootServices ) {
120  DBGC ( systab, "EFI provided no BootServices entry point\n" );
121  efirc = EFI_NOT_AVAILABLE_YET;
122  goto err_sanity;
123  }
124  if ( ! systab->RuntimeServices ) {
125  DBGC ( systab, "EFI provided no RuntimeServices entry "
126  "point\n" );
127  efirc = EFI_NOT_AVAILABLE_YET;
128  goto err_sanity;
129  }
130  DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
131  bs = systab->BootServices;
132 
133  /* Look up used protocols */
135  if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
136  prot->protocol ) ) == 0 ) {
137  DBGC ( systab, "EFI protocol %s is at %p\n",
138  efi_guid_ntoa ( &prot->guid ),
139  *(prot->protocol) );
140  } else {
141  DBGC ( systab, "EFI does not provide protocol %s\n",
142  efi_guid_ntoa ( &prot->guid ) );
143  /* Fail if protocol is required */
144  if ( prot->required )
145  goto err_missing_protocol;
146  }
147  }
148 
149  /* Look up used configuration tables */
151  if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) {
152  DBGC ( systab, "EFI configuration table %s is at %p\n",
153  efi_guid_ntoa ( &tab->guid ), *(tab->table) );
154  } else {
155  DBGC ( systab, "EFI does not provide configuration "
156  "table %s\n", efi_guid_ntoa ( &tab->guid ) );
157  if ( tab->required ) {
158  efirc = EFI_NOT_AVAILABLE_YET;
159  goto err_missing_table;
160  }
161  }
162  }
163 
164  /* Get loaded image protocol */
165  if ( ( efirc = bs->OpenProtocol ( image_handle,
167  &loaded_image, image_handle, NULL,
168  EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
169  rc = -EEFI ( efirc );
170  DBGC ( systab, "EFI could not get loaded image protocol: %s",
171  strerror ( rc ) );
172  goto err_no_loaded_image;
173  }
174  efi_loaded_image = loaded_image;
175  DBGC ( systab, "EFI image base address %p\n",
177 
178  /* EFI is perfectly capable of gracefully shutting down any
179  * loaded devices if it decides to fall back to a legacy boot.
180  * For no particularly comprehensible reason, it doesn't
181  * bother doing so when ExitBootServices() is called.
182  */
183  if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
185  NULL, &efi_shutdown_event ) ) != 0 ) {
186  rc = -EEFI ( efirc );
187  DBGC ( systab, "EFI could not create ExitBootServices event: "
188  "%s\n", strerror ( rc ) );
189  goto err_create_event;
190  }
191 
192  /* Install driver binding protocol */
193  if ( ( rc = efi_driver_install() ) != 0 ) {
194  DBGC ( systab, "EFI could not install driver: %s\n",
195  strerror ( rc ) );
196  efirc = EFIRC ( rc );
197  goto err_driver_install;
198  }
199 
200  /* Install image unload method */
202 
203  return 0;
204 
206  err_driver_install:
208  err_create_event:
209  err_no_loaded_image:
210  err_missing_table:
211  err_missing_protocol:
212  err_sanity:
213  return efirc;
214 }
215 
216 /**
217  * Shut down EFI environment
218  *
219  * @v image_handle Image handle
220  */
221 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
223  EFI_SYSTEM_TABLE *systab = efi_systab;
224 
225  DBGC ( systab, "EFI image unloading\n" );
226 
227  /* Shut down */
228  shutdown_exit();
229 
230  /* Disconnect any remaining devices */
232 
233  /* Uninstall driver binding protocol */
235 
236  /* Uninstall exit boot services event */
238 
239  DBGC ( systab, "EFI image unloaded\n" );
240 
241  return 0;
242 }
void efi_driver_uninstall(void)
Uninstall EFI driver.
Definition: efi_driver.c:419
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
void ** protocol
Variable containing pointer to protocol structure.
Definition: efi.h:74
EFI_LOADED_IMAGE_PROTOCOL * efi_loaded_image
Loaded image protocol for this image.
Definition: efi_init.c:33
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
EFI driver interface.
EFI_LOCATE_PROTOCOL LocateProtocol
Definition: UefiSpec.h:1914
128 bit buffer containing a unique identifier value.
Definition: Base.h:263
Error codes.
VOID * EFI_EVENT
Handle to an event structure.
Definition: UefiBaseType.h:43
EFI_GUID VendorGuid
The 128-bit GUID value that uniquely identifies the system configuration table.
Definition: UefiSpec.h:1939
EFI_GUID guid
GUID.
Definition: efi.h:72
#define DBGC(...)
Definition: compiler.h:505
EFI_GUID efi_loaded_image_protocol_guid
Loaded image protocol GUID.
Definition: efi_guid.c:184
EFI_CLOSE_EVENT CloseEvent
Definition: UefiSpec.h:1864
VOID * ImageBase
The base address at which the image was loaded.
Definition: LoadedImage.h:75
#define EFI_PROTOCOLS
EFI protocol table.
Definition: efi.h:80
FILE_LICENCE(GPL2_OR_LATER)
#define EVT_SIGNAL_EXIT_BOOT_SERVICES
Definition: UefiSpec.h:396
UEFI 2.0 Loaded image protocol definition.
#define EFI_CONFIG_TABLES
EFI configuration table table.
Definition: efi.h:124
An EFI configuration table used by iPXE.
Definition: efi.h:114
#define EFI_NOT_AVAILABLE_YET
If this value is returned by an API, it means the capability is not yet installed/available/ready to ...
Definition: PiMultiPhase.h:55
Can be used on any image handle to obtain information about the loaded image.
Definition: LoadedImage.h:51
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface that is associated with ConsoleOutHandle.
Definition: UefiSpec.h:1982
static EFI_EVENT efi_shutdown_event
Event used to signal shutdown.
Definition: efi_init.c:48
static EFIAPI void efi_shutdown_hook(EFI_EVENT event __unused, void *context __unused)
Shut down in preparation for booting an OS.
Definition: efi_init.c:60
EFI_CREATE_EVENT CreateEvent
Definition: UefiSpec.h:1860
static void * efi_find_table(EFI_GUID *guid)
Look up EFI configuration table.
Definition: efi_init.c:78
static void shutdown_exit(void)
Shut down system for exit back to firmware.
Definition: init.h:84
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL
Definition: UefiSpec.h:1271
An EFI protocol used by iPXE.
Definition: efi.h:70
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define EFIAPI
EFI Boot Services Table.
Definition: UefiSpec.h:1836
EFI_HANDLE efi_image_handle
Image handle passed to entry point.
Definition: efi_init.c:30
EFI_IMAGE_UNLOAD Unload
Definition: LoadedImage.h:79
void efi_driver_disconnect_all(void)
Disconnect EFI driver from all possible devices.
Definition: efi_driver.c:576
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
#define TPL_CALLBACK
Definition: UefiSpec.h:591
EFI System Table.
Definition: UefiSpec.h:1949
EFI API.
void ** table
Variable containing pointer to configuration table.
Definition: efi.h:118
uint64_t guid
GUID.
Definition: edd.h:30
int required
Protocol is required.
Definition: efi.h:76
const char * efi_guid_ntoa(EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_debug.c:192
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
EFI_RUNTIME_SERVICES * RuntimeServices
A pointer to the EFI Runtime Services Table.
Definition: UefiSpec.h:1996
EFI_GUID guid
GUID.
Definition: efi.h:116
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
UINTN NumberOfTableEntries
The number of system configuration tables in the buffer ConfigurationTable.
Definition: UefiSpec.h:2004
EFI_STATUS efi_init(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
Initialise EFI environment.
Definition: efi_init.c:97
EFI_SYSTEM_TABLE * efi_systab
EFI_OPEN_PROTOCOL OpenProtocol
Definition: UefiSpec.h:1905
EFI_SYSTEM_TABLE * _C2(PLATFORM, _systab)
System table passed to entry point.
int required
Table is required for operation.
Definition: efi.h:120
static EFI_STATUS EFIAPI efi_unload(EFI_HANDLE image_handle)
Shut down EFI environment.
Definition: efi_init.c:221
static void shutdown_boot(void)
Shut down system for OS boot.
Definition: init.h:76
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
String functions.
int efi_driver_install(void)
Install EFI driver.
Definition: efi_driver.c:386
#define EFIRC(rc)
Convert an iPXE status code to an EFI status code.
Definition: efi.h:149
Definition: efi.h:55
EFI_CONFIGURATION_TABLE * ConfigurationTable
A pointer to the system configuration tables.
Definition: UefiSpec.h:2009
int efi_shutdown_in_progress
EFI shutdown is in progress.
Definition: efi_init.c:45
VOID * VendorTable
A pointer to the table associated with VendorGuid.
Definition: UefiSpec.h:1943