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