[hermon] Randomise the high-order bits of queue pair numbers
[people/peper/gpxe.git] / src / image / efi_image.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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <errno.h>
22 #include <gpxe/efi/efi.h>
23 #include <gpxe/image.h>
24 #include <gpxe/features.h>
25
26 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
27
28 struct image_type efi_image_type __image_type ( PROBE_NORMAL );
29
30 /**
31  * Execute EFI image
32  *
33  * @v image             EFI image
34  * @ret rc              Return status code
35  */
36 static int efi_image_exec ( struct image *image ) {
37         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
38         EFI_HANDLE handle;
39         UINTN exit_data_size;
40         CHAR16 *exit_data;
41         EFI_STATUS efirc;
42
43         /* Attempt loading image */
44         if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
45                                        user_to_virt ( image->data, 0 ),
46                                        image->len, &handle ) ) != 0 ) {
47                 /* Not an EFI image */
48                 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
49                        image, efi_strerror ( efirc ) );
50                 return -ENOEXEC;
51         }
52
53         /* Start the image */
54         if ( ( efirc = bs->StartImage ( handle, &exit_data_size,
55                                         &exit_data ) ) != 0 ) {
56                 DBGC ( image, "EFIIMAGE %p returned with status %s\n",
57                        image, efi_strerror ( efirc ) );
58                 goto done;
59         }
60
61  done:
62         /* Unload the image.  We can't leave it loaded, because we
63          * have no "unload" operation.
64          */
65         bs->UnloadImage ( handle );
66
67         return EFIRC_TO_RC ( efirc );
68 }
69
70 /**
71  * Load EFI image into memory
72  *
73  * @v image             EFI file
74  * @ret rc              Return status code
75  */
76 static int efi_image_load ( struct image *image ) {
77         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
78         EFI_HANDLE handle;
79         EFI_STATUS efirc;
80
81         /* Attempt loading image */
82         if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL,
83                                        user_to_virt ( image->data, 0 ),
84                                        image->len, &handle ) ) != 0 ) {
85                 /* Not an EFI image */
86                 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
87                        image, efi_strerror ( efirc ) );
88                 return -ENOEXEC;
89         }
90
91         /* This is an EFI image */
92         if ( ! image->type )
93                 image->type = &efi_image_type;
94
95         /* Unload the image.  We can't leave it loaded, because we
96          * have no "unload" operation.
97          */
98         bs->UnloadImage ( handle );
99
100         return 0;
101 }
102
103 /** EFI image type */
104 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
105         .name = "EFI",
106         .load = efi_image_load,
107         .exec = efi_image_exec,
108 };