Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / interface / efi / efi_init.c
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>
27 #include <ipxe/efi/Protocol/LoadedImage.h>
28
29 /** Image handle passed to entry point */
30 EFI_HANDLE efi_image_handle;
31
32 /** Loaded image protocol for this image */
33 EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image;
34
35 /** System table passed to entry point */
36 EFI_SYSTEM_TABLE *efi_systab;
37
38 /** Event used to signal shutdown */
39 static EFI_EVENT efi_shutdown_event;
40
41 /* Forward declarations */
42 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
43
44 /**
45  * Shut down in preparation for booting an OS.
46  *
47  * This hook gets called at ExitBootServices time in order to make
48  * sure that everything is properly shut down before the OS takes
49  * over.
50  */
51 static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
52                                        void *context __unused ) {
53         shutdown_boot();
54 }
55
56 /**
57  * Look up EFI configuration table
58  *
59  * @v guid              Configuration table GUID
60  * @ret table           Configuration table, or NULL
61  */
62 static void * efi_find_table ( EFI_GUID *guid ) {
63         unsigned int i;
64
65         for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
66                 if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid,
67                               guid, sizeof ( *guid ) ) == 0 )
68                         return efi_systab->ConfigurationTable[i].VendorTable;
69         }
70
71         return NULL;
72 }
73
74 /**
75  * Initialise EFI environment
76  *
77  * @v image_handle      Image handle
78  * @v systab            System table
79  * @ret efirc           EFI return status code
80  */
81 EFI_STATUS efi_init ( EFI_HANDLE image_handle,
82                       EFI_SYSTEM_TABLE *systab ) {
83         EFI_BOOT_SERVICES *bs;
84         struct efi_protocol *prot;
85         struct efi_config_table *tab;
86         void *loaded_image;
87         EFI_STATUS efirc;
88         int rc;
89
90         /* Store image handle and system table pointer for future use */
91         efi_image_handle = image_handle;
92         efi_systab = systab;
93
94         /* Sanity checks */
95         if ( ! systab ) {
96                 efirc = EFI_NOT_AVAILABLE_YET;
97                 goto err_sanity;
98         }
99         if ( ! systab->ConOut ) {
100                 efirc = EFI_NOT_AVAILABLE_YET;
101                 goto err_sanity;
102         }
103         if ( ! systab->BootServices ) {
104                 DBGC ( systab, "EFI provided no BootServices entry point\n" );
105                 efirc = EFI_NOT_AVAILABLE_YET;
106                 goto err_sanity;
107         }
108         if ( ! systab->RuntimeServices ) {
109                 DBGC ( systab, "EFI provided no RuntimeServices entry "
110                        "point\n" );
111                 efirc = EFI_NOT_AVAILABLE_YET;
112                 goto err_sanity;
113         }
114         DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
115         bs = systab->BootServices;
116
117         /* Look up used protocols */
118         for_each_table_entry ( prot, EFI_PROTOCOLS ) {
119                 if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
120                                                     prot->protocol ) ) == 0 ) {
121                         DBGC ( systab, "EFI protocol %s is at %p\n",
122                                efi_guid_ntoa ( &prot->guid ),
123                                *(prot->protocol) );
124                 } else {
125                         DBGC ( systab, "EFI does not provide protocol %s\n",
126                                efi_guid_ntoa ( &prot->guid ) );
127                         /* Fail if protocol is required */
128                         if ( prot->required )
129                                 goto err_missing_protocol;
130                 }
131         }
132
133         /* Look up used configuration tables */
134         for_each_table_entry ( tab, EFI_CONFIG_TABLES ) {
135                 if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) {
136                         DBGC ( systab, "EFI configuration table %s is at %p\n",
137                                efi_guid_ntoa ( &tab->guid ), *(tab->table) );
138                 } else {
139                         DBGC ( systab, "EFI does not provide configuration "
140                                "table %s\n", efi_guid_ntoa ( &tab->guid ) );
141                         if ( tab->required ) {
142                                 efirc = EFI_NOT_AVAILABLE_YET;
143                                 goto err_missing_table;
144                         }
145                 }
146         }
147
148         /* Get loaded image protocol */
149         if ( ( efirc = bs->OpenProtocol ( image_handle,
150                                 &efi_loaded_image_protocol_guid,
151                                 &loaded_image, image_handle, NULL,
152                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
153                 rc = -EEFI ( efirc );
154                 DBGC ( systab, "EFI could not get loaded image protocol: %s",
155                        strerror ( rc ) );
156                 goto err_no_loaded_image;
157         }
158         efi_loaded_image = loaded_image;
159         DBGC ( systab, "EFI image base address %p\n",
160                efi_loaded_image->ImageBase );
161
162         /* EFI is perfectly capable of gracefully shutting down any
163          * loaded devices if it decides to fall back to a legacy boot.
164          * For no particularly comprehensible reason, it doesn't
165          * bother doing so when ExitBootServices() is called.
166          */
167         if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
168                                          TPL_CALLBACK, efi_shutdown_hook,
169                                          NULL, &efi_shutdown_event ) ) != 0 ) {
170                 rc = -EEFI ( efirc );
171                 DBGC ( systab, "EFI could not create ExitBootServices event: "
172                        "%s\n", strerror ( rc ) );
173                 goto err_create_event;
174         }
175
176         /* Install driver binding protocol */
177         if ( ( rc = efi_driver_install() ) != 0 ) {
178                 DBGC ( systab, "EFI could not install driver: %s\n",
179                        strerror ( rc ) );
180                 efirc = EFIRC ( rc );
181                 goto err_driver_install;
182         }
183
184         /* Install image unload method */
185         efi_loaded_image->Unload = efi_unload;
186
187         return 0;
188
189         efi_driver_uninstall();
190  err_driver_install:
191         bs->CloseEvent ( efi_shutdown_event );
192  err_create_event:
193  err_no_loaded_image:
194  err_missing_table:
195  err_missing_protocol:
196  err_sanity:
197         return efirc;
198 }
199
200 /**
201  * Shut down EFI environment
202  *
203  * @v image_handle      Image handle
204  */
205 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
206         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
207         EFI_SYSTEM_TABLE *systab = efi_systab;
208
209         DBGC ( systab, "EFI image unloading\n" );
210
211         /* Shut down */
212         shutdown_exit();
213
214         /* Disconnect any remaining devices */
215         efi_driver_disconnect_all();
216
217         /* Uninstall driver binding protocol */
218         efi_driver_uninstall();
219
220         /* Uninstall exit boot services event */
221         bs->CloseEvent ( efi_shutdown_event );
222
223         DBGC ( systab, "EFI image unloaded\n" );
224
225         return 0;
226 }