iPXE
efi_autoexec.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2021 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  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <errno.h>
28 #include <ipxe/timer.h>
29 #include <ipxe/image.h>
30 #include <ipxe/netdevice.h>
31 #include <ipxe/uri.h>
32 #include <ipxe/efi/efi.h>
33 #include <ipxe/efi/efi_utils.h>
34 #include <ipxe/efi/efi_autoexec.h>
35 #include <ipxe/efi/mnpnet.h>
36 #include <usr/imgmgmt.h>
37 #include <usr/sync.h>
38 
39 /** @file
40  *
41  * EFI autoexec script
42  *
43  */
44 
45 /** Timeout for autoexec script downloads */
46 #define EFI_AUTOEXEC_TIMEOUT ( 30 * TICKS_PER_SEC )
47 
48 /** Timeout for autoexec pending operation completion */
49 #define EFI_AUTOEXEC_SYNC_TIMEOUT ( 1 * TICKS_PER_SEC )
50 
51 /** Autoexec script image name */
52 #define EFI_AUTOEXEC_NAME "autoexec.ipxe"
53 
54 /** An EFI autoexec script loader */
56  /** Required protocol GUID */
58  /**
59  * Load autoexec script
60  *
61  * @v handle Handle on which protocol was found
62  * @v image Image to fill in
63  * @ret rc Return status code
64  */
65  int ( * load ) ( EFI_HANDLE handle, struct image **image );
66 };
67 
68 /**
69  * Load autoexec script from filesystem
70  *
71  * @v handle Simple filesystem protocol handle
72  * @v image Image to fill in
73  * @ret rc Return status code
74  */
77  int rc;
78 
79  /* Check that we were loaded from a filesystem */
80  if ( handle != device ) {
81  DBGC ( device, "EFI %s is not the file system handle\n",
82  efi_handle_name ( device ) );
83  return -ENOTTY;
84  }
85 
86  /* Try loading from loaded image directory, if supported */
87  if ( ( rc = imgacquire ( "file:" EFI_AUTOEXEC_NAME,
88  EFI_AUTOEXEC_TIMEOUT, image ) ) == 0 )
89  return 0;
90 
91  /* Try loading from root directory, if supported */
92  if ( ( rc = imgacquire ( "file:/" EFI_AUTOEXEC_NAME,
93  EFI_AUTOEXEC_TIMEOUT, image ) ) == 0 )
94  return 0;
95 
96  return rc;
97 }
98 
99 /**
100  * Load autoexec script via temporary network device
101  *
102  * @v handle Managed network protocol service binding handle
103  * @v image Image to fill in
104  * @ret rc Return status code
105  */
108  struct net_device *netdev;
109  int rc;
110 
111  /* Create temporary network device */
112  if ( ( rc = mnptemp_create ( handle, &netdev ) ) != 0 ) {
113  DBGC ( device, "EFI %s could not create net device: %s\n",
114  efi_handle_name ( device ), strerror ( rc ) );
115  goto err_create;
116  }
117 
118  /* Do nothing unless we have a usable current working URI */
119  if ( ! cwuri ) {
120  DBGC ( device, "EFI %s has no current working URI\n",
121  efi_handle_name ( device ) );
122  rc = -ENOTTY;
123  goto err_cwuri;
124  }
125 
126  /* Open network device */
127  if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
128  DBGC ( device, "EFI %s could not open net device: %s\n",
129  efi_handle_name ( device ), strerror ( rc ) );
130  goto err_open;
131  }
132 
133  /* Attempt download */
135  if ( rc != 0 ) {
136  DBGC ( device, "EFI %s could not download %s: %s\n",
138  strerror ( rc ) );
139  }
140 
141  /* Ensure network exchanges have completed */
143 
144  err_open:
145  err_cwuri:
147  err_create:
148  return rc;
149 }
150 
151 /** Autoexec script loaders */
153  {
155  .load = efi_autoexec_filesystem,
156  },
157  {
159  .load = efi_autoexec_network,
160  },
161 };
162 
163 /**
164  * Load autoexec script
165  *
166  * @ret rc Return status code
167  */
168 int efi_autoexec_load ( void ) {
171  struct efi_autoexec_loader *loader;
172  struct image *image;
173  unsigned int i;
174  int rc;
175 
176  /* Use first applicable loader */
177  for ( i = 0 ; i < ( sizeof ( efi_autoexec_loaders ) /
178  sizeof ( efi_autoexec_loaders[0] ) ) ; i ++ ) {
179 
180  /* Locate required protocol for this loader */
181  loader = &efi_autoexec_loaders[i];
182  if ( ( rc = efi_locate_device ( device, loader->protocol,
183  &handle, 0 ) ) != 0 ) {
184  DBGC ( device, "EFI %s found no %s: %s\n",
186  efi_guid_ntoa ( loader->protocol ),
187  strerror ( rc ) );
188  continue;
189  }
190  DBGC ( device, "EFI %s found %s on ",
192  efi_guid_ntoa ( loader->protocol ) );
193  DBGC ( device, "%s\n", efi_handle_name ( handle ) );
194 
195  /* Try loading */
196  if ( ( rc = loader->load ( handle, &image ) ) != 0 )
197  return rc;
198 
199  /* Discard zero-length images */
200  if ( ! image->len ) {
201  DBGC ( device, "EFI %s discarding zero-length %s\n",
204  return -ENOENT;
205  }
206 
207  DBGC ( device, "EFI %s loaded %s (%zd bytes)\n",
209  return 0;
210  }
211 
212  return -ENOENT;
213 }
EFI_LOADED_IMAGE_PROTOCOL * efi_loaded_image
Loaded image protocol for this image.
Definition: efi_init.c:37
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
128 bit buffer containing a unique identifier value.
Definition: Base.h:215
Error codes.
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
iPXE timers
An executable image.
Definition: image.h:24
EFI_GUID efi_managed_network_service_binding_protocol_guid
Managed network service binding protocol GUID.
Definition: efi_guid.c:256
Uniform Resource Identifiers.
#define EFI_AUTOEXEC_TIMEOUT
Timeout for autoexec script downloads.
Definition: efi_autoexec.c:46
static int efi_autoexec_filesystem(EFI_HANDLE handle, struct image **image)
Load autoexec script from filesystem.
Definition: efi_autoexec.c:75
int efi_autoexec_load(void)
Load autoexec script.
Definition: efi_autoexec.c:168
EFI utilities.
EFI_GUID * protocol
Required protocol GUID.
Definition: efi_autoexec.c:57
A hardware device.
Definition: device.h:73
#define EFI_AUTOEXEC_NAME
Autoexec script image name.
Definition: efi_autoexec.c:52
void mnptemp_destroy(struct net_device *netdev)
Destroy temporary MNP network device.
Definition: mnpnet.c:551
int sync(unsigned long timeout)
Wait for pending operations to complete.
Definition: sync.c:73
Executable images.
EFI_GUID efi_simple_file_system_protocol_guid
Simple file system protocol GUID.
Definition: efi_guid.c:304
static struct net_device * netdev
Definition: gdbudp.c:52
static int efi_autoexec_network(EFI_HANDLE handle, struct image **image)
Load autoexec script via temporary network device.
Definition: efi_autoexec.c:106
const char * efi_handle_name(EFI_HANDLE handle)
Get name of an EFI handle.
Definition: efi_debug.c:810
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_debug.c:256
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
size_t len
Length of raw file image.
Definition: image.h:43
A network device.
Definition: netdevice.h:352
static struct efi_autoexec_loader efi_autoexec_loaders[]
Autoexec script loaders.
Definition: efi_autoexec.c:152
MNP NIC driver.
int efi_locate_device(EFI_HANDLE device, EFI_GUID *protocol, EFI_HANDLE *parent, unsigned int skip)
Locate parent device supporting a given protocol.
Definition: efi_utils.c:45
EFI API.
int mnptemp_create(EFI_HANDLE handle, struct net_device **netdev)
Create temporary MNP network device.
Definition: mnpnet.c:514
Network device management.
void unregister_image(struct image *image)
Unregister executable image.
Definition: image.c:322
int(* load)(EFI_HANDLE handle, struct image **image)
Load autoexec script.
Definition: efi_autoexec.c:65
Image management.
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
Wait for pending operations to complete.
EFI autoexec script.
#define EFI_AUTOEXEC_SYNC_TIMEOUT
Timeout for autoexec pending operation completion.
Definition: efi_autoexec.c:49
struct uri * cwuri
Current working URI.
Definition: cwuri.c:38
uint16_t handle
Handle.
Definition: smbios.h:16
char * name
Name.
Definition: image.h:34
An EFI autoexec script loader.
Definition: efi_autoexec.c:55
String functions.
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
int imgacquire(const char *name_uri, unsigned long timeout, struct image **image)
Acquire an image.
Definition: imgmgmt.c:141
Definition: efi.h:59
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:55