[contrib] Allow Network Protocol header to display in rom-o-matic
[gpxe.git] / src / image / efi_image.c
blob3b94c02a8b2d16dfd51a5a02721932940769fab5
1 /*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER );
21 #include <errno.h>
22 #include <gpxe/efi/efi.h>
23 #include <gpxe/image.h>
24 #include <gpxe/init.h>
25 #include <gpxe/features.h>
27 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
29 struct image_type efi_image_type __image_type ( PROBE_NORMAL );
31 /** Event used to signal shutdown */
32 static EFI_EVENT efi_shutdown_event;
34 /**
35 * Shut down in preparation for booting an OS.
37 * This hook gets called at ExitBootServices time in order to make sure that
38 * the network cards are properly shut down before the OS takes over.
40 static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
41 void *context __unused ) {
42 shutdown ( SHUTDOWN_BOOT );
45 /**
46 * Execute EFI image
48 * @v image EFI image
49 * @ret rc Return status code
51 static int efi_image_exec ( struct image *image ) {
52 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
53 EFI_HANDLE handle;
54 UINTN exit_data_size;
55 CHAR16 *exit_data;
56 EFI_STATUS efirc;
57 int rc;
59 /* Attempt loading image */
60 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
61 user_to_virt ( image->data, 0 ),
62 image->len, &handle ) ) != 0 ) {
63 /* Not an EFI image */
64 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
65 image, efi_strerror ( efirc ) );
66 return -ENOEXEC;
69 /* Be sure to shut down the NIC at ExitBootServices time, or else
70 * DMA from the card can corrupt the OS.
72 efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
73 TPL_CALLBACK, efi_shutdown_hook,
74 NULL, &efi_shutdown_event );
75 if ( efirc ) {
76 rc = EFIRC_TO_RC ( efirc );
77 goto done;
80 /* Start the image */
81 if ( ( efirc = bs->StartImage ( handle, &exit_data_size,
82 &exit_data ) ) != 0 ) {
83 DBGC ( image, "EFIIMAGE %p returned with status %s\n",
84 image, efi_strerror ( efirc ) );
87 rc = EFIRC_TO_RC ( efirc );
89 /* Remove the shutdown hook */
90 bs->CloseEvent ( efi_shutdown_event );
92 done:
93 /* Unload the image. We can't leave it loaded, because we
94 * have no "unload" operation.
96 bs->UnloadImage ( handle );
98 return rc;
102 * Load EFI image into memory
104 * @v image EFI file
105 * @ret rc Return status code
107 static int efi_image_load ( struct image *image ) {
108 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
109 EFI_HANDLE handle;
110 EFI_STATUS efirc;
112 /* Attempt loading image */
113 if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
114 user_to_virt ( image->data, 0 ),
115 image->len, &handle ) ) != 0 ) {
116 /* Not an EFI image */
117 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
118 image, efi_strerror ( efirc ) );
119 return -ENOEXEC;
122 /* This is an EFI image */
123 if ( ! image->type )
124 image->type = &efi_image_type;
126 /* Unload the image. We can't leave it loaded, because we
127 * have no "unload" operation.
129 bs->UnloadImage ( handle );
131 return 0;
134 /** EFI image type */
135 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
136 .name = "EFI",
137 .load = efi_image_load,
138 .exec = efi_image_exec,