iPXE
efi_image.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  */
00019 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include <errno.h>
00023 #include <stdlib.h>
00024 #include <wchar.h>
00025 #include <ipxe/efi/efi.h>
00026 #include <ipxe/efi/efi_snp.h>
00027 #include <ipxe/efi/efi_download.h>
00028 #include <ipxe/efi/efi_file.h>
00029 #include <ipxe/efi/efi_utils.h>
00030 #include <ipxe/efi/efi_strings.h>
00031 #include <ipxe/efi/efi_wrap.h>
00032 #include <ipxe/efi/efi_pxe.h>
00033 #include <ipxe/image.h>
00034 #include <ipxe/init.h>
00035 #include <ipxe/features.h>
00036 #include <ipxe/uri.h>
00037 #include <ipxe/console.h>
00038 
00039 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
00040 
00041 /* Disambiguate the various error causes */
00042 #define EINFO_EEFI_LOAD                                                 \
00043         __einfo_uniqify ( EINFO_EPLATFORM, 0x01,                        \
00044                           "Could not load image" )
00045 #define EINFO_EEFI_LOAD_PROHIBITED                                      \
00046         __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION,  \
00047                               "Image prohibited by security policy" )
00048 #define EEFI_LOAD_PROHIBITED                                            \
00049         __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )
00050 #define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc,          \
00051                                        EEFI_LOAD_PROHIBITED )
00052 #define EINFO_EEFI_START                                                \
00053         __einfo_uniqify ( EINFO_EPLATFORM, 0x02,                        \
00054                           "Could not start image" )
00055 #define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
00056 
00057 /**
00058  * Create device path for image
00059  *
00060  * @v image             EFI image
00061  * @v parent            Parent device path
00062  * @ret path            Device path, or NULL on failure
00063  *
00064  * The caller must eventually free() the device path.
00065  */
00066 static EFI_DEVICE_PATH_PROTOCOL *
00067 efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) {
00068         EFI_DEVICE_PATH_PROTOCOL *path;
00069         FILEPATH_DEVICE_PATH *filepath;
00070         EFI_DEVICE_PATH_PROTOCOL *end;
00071         size_t name_len;
00072         size_t prefix_len;
00073         size_t filepath_len;
00074         size_t len;
00075 
00076         /* Calculate device path lengths */
00077         prefix_len = efi_devpath_len ( parent );
00078         name_len = strlen ( image->name );
00079         filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
00080                          ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
00081         len = ( prefix_len + filepath_len + sizeof ( *end ) );
00082 
00083         /* Allocate device path */
00084         path = zalloc ( len );
00085         if ( ! path )
00086                 return NULL;
00087 
00088         /* Construct device path */
00089         memcpy ( path, parent, prefix_len );
00090         filepath = ( ( ( void * ) path ) + prefix_len );
00091         filepath->Header.Type = MEDIA_DEVICE_PATH;
00092         filepath->Header.SubType = MEDIA_FILEPATH_DP;
00093         filepath->Header.Length[0] = ( filepath_len & 0xff );
00094         filepath->Header.Length[1] = ( filepath_len >> 8 );
00095         efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
00096                        "%s", image->name );
00097         end = ( ( ( void * ) filepath ) + filepath_len );
00098         end->Type = END_DEVICE_PATH_TYPE;
00099         end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
00100         end->Length[0] = sizeof ( *end );
00101 
00102         return path;
00103 }
00104 
00105 /**
00106  * Create command line for image
00107  *
00108  * @v image             EFI image
00109  * @ret cmdline         Command line, or NULL on failure
00110  */
00111 static wchar_t * efi_image_cmdline ( struct image *image ) {
00112         wchar_t *cmdline;
00113         size_t len;
00114 
00115         len = ( strlen ( image->name ) +
00116                 ( image->cmdline ?
00117                   ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
00118         cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
00119         if ( ! cmdline )
00120                 return NULL;
00121         efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
00122                        image->name,
00123                        ( image->cmdline ? " " : "" ),
00124                        ( image->cmdline ? image->cmdline : "" ) );
00125         return cmdline;
00126 }
00127 
00128 /**
00129  * Execute EFI image
00130  *
00131  * @v image             EFI image
00132  * @ret rc              Return status code
00133  */
00134 static int efi_image_exec ( struct image *image ) {
00135         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00136         struct efi_snp_device *snpdev;
00137         EFI_DEVICE_PATH_PROTOCOL *path;
00138         union {
00139                 EFI_LOADED_IMAGE_PROTOCOL *image;
00140                 void *interface;
00141         } loaded;
00142         EFI_HANDLE handle;
00143         wchar_t *cmdline;
00144         EFI_STATUS efirc;
00145         int rc;
00146 
00147         /* Find an appropriate device handle to use */
00148         snpdev = last_opened_snpdev();
00149         if ( ! snpdev ) {
00150                 DBGC ( image, "EFIIMAGE %p could not identify SNP device\n",
00151                        image );
00152                 rc = -ENODEV;
00153                 goto err_no_snpdev;
00154         }
00155 
00156         /* Install file I/O protocols */
00157         if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
00158                 DBGC ( image, "EFIIMAGE %p could not install file protocol: "
00159                        "%s\n", image, strerror ( rc ) );
00160                 goto err_file_install;
00161         }
00162 
00163         /* Install PXE base code protocol */
00164         if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
00165                 DBGC ( image, "EFIIMAGE %p could not install PXE protocol: "
00166                        "%s\n", image, strerror ( rc ) );
00167                 goto err_pxe_install;
00168         }
00169 
00170         /* Install iPXE download protocol */
00171         if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
00172                 DBGC ( image, "EFIIMAGE %p could not install iPXE download "
00173                        "protocol: %s\n", image, strerror ( rc ) );
00174                 goto err_download_install;
00175         }
00176 
00177         /* Create device path for image */
00178         path = efi_image_path ( image, snpdev->path );
00179         if ( ! path ) {
00180                 DBGC ( image, "EFIIMAGE %p could not create device path\n",
00181                        image );
00182                 rc = -ENOMEM;
00183                 goto err_image_path;
00184         }
00185 
00186         /* Create command line for image */
00187         cmdline = efi_image_cmdline ( image );
00188         if ( ! cmdline ) {
00189                 DBGC ( image, "EFIIMAGE %p could not create command line\n",
00190                        image );
00191                 rc = -ENOMEM;
00192                 goto err_cmdline;
00193         }
00194 
00195         /* Attempt loading image */
00196         if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
00197                                        user_to_virt ( image->data, 0 ),
00198                                        image->len, &handle ) ) != 0 ) {
00199                 /* Not an EFI image */
00200                 rc = -EEFI_LOAD ( efirc );
00201                 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
00202                        image, strerror ( rc ) );
00203                 goto err_load_image;
00204         }
00205 
00206         /* Get the loaded image protocol for the newly loaded image */
00207         efirc = bs->OpenProtocol ( handle, &efi_loaded_image_protocol_guid,
00208                                    &loaded.interface, efi_image_handle,
00209                                    NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
00210         if ( efirc ) {
00211                 /* Should never happen */
00212                 rc = -EEFI ( efirc );
00213                 goto err_open_protocol;
00214         }
00215 
00216         /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
00217         if ( loaded.image->DeviceHandle == NULL ) {
00218                 DBGC ( image, "EFIIMAGE %p filling in missing DeviceHandle\n",
00219                        image );
00220                 loaded.image->DeviceHandle = snpdev->handle;
00221         }
00222 
00223         /* Sanity checks */
00224         assert ( loaded.image->ParentHandle == efi_image_handle );
00225         assert ( loaded.image->DeviceHandle == snpdev->handle );
00226         assert ( loaded.image->LoadOptionsSize == 0 );
00227         assert ( loaded.image->LoadOptions == NULL );
00228 
00229         /* Set command line */
00230         loaded.image->LoadOptions = cmdline;
00231         loaded.image->LoadOptionsSize =
00232                 ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
00233 
00234         /* Release network devices for use via SNP */
00235         efi_snp_release();
00236 
00237         /* Wrap calls made by the loaded image (for debugging) */
00238         efi_wrap ( handle );
00239 
00240         /* Reset console since image will probably use it */
00241         console_reset();
00242 
00243         /* Start the image */
00244         if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
00245                 rc = -EEFI_START ( efirc );
00246                 DBGC ( image, "EFIIMAGE %p could not start (or returned with "
00247                        "error): %s\n", image, strerror ( rc ) );
00248                 goto err_start_image;
00249         }
00250 
00251         /* Success */
00252         rc = 0;
00253 
00254  err_start_image:
00255         efi_snp_claim();
00256  err_open_protocol:
00257         /* If there was no error, then the image must have been
00258          * started and returned successfully.  It either unloaded
00259          * itself, or it intended to remain loaded (e.g. it was a
00260          * driver).  We therefore do not unload successful images.
00261          *
00262          * If there was an error, attempt to unload the image.  This
00263          * may not work.  In particular, there is no way to tell
00264          * whether an error returned from StartImage() was due to
00265          * being unable to start the image (in which case we probably
00266          * should call UnloadImage()), or due to the image itself
00267          * returning an error (in which case we probably should not
00268          * call UnloadImage()).  We therefore ignore any failures from
00269          * the UnloadImage() call itself.
00270          */
00271         if ( rc != 0 )
00272                 bs->UnloadImage ( handle );
00273  err_load_image:
00274         free ( cmdline );
00275  err_cmdline:
00276         free ( path );
00277  err_image_path:
00278         efi_download_uninstall ( snpdev->handle );
00279  err_download_install:
00280         efi_pxe_uninstall ( snpdev->handle );
00281  err_pxe_install:
00282         efi_file_uninstall ( snpdev->handle );
00283  err_file_install:
00284  err_no_snpdev:
00285         return rc;
00286 }
00287 
00288 /**
00289  * Probe EFI image
00290  *
00291  * @v image             EFI file
00292  * @ret rc              Return status code
00293  */
00294 static int efi_image_probe ( struct image *image ) {
00295         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00296         static EFI_DEVICE_PATH_PROTOCOL empty_path = {
00297                 .Type = END_DEVICE_PATH_TYPE,
00298                 .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
00299                 .Length[0] = sizeof ( empty_path ),
00300         };
00301         EFI_HANDLE handle;
00302         EFI_STATUS efirc;
00303         int rc;
00304 
00305         /* Attempt loading image */
00306         if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
00307                                        user_to_virt ( image->data, 0 ),
00308                                        image->len, &handle ) ) != 0 ) {
00309                 /* Not an EFI image */
00310                 rc = -EEFI_LOAD ( efirc );
00311                 DBGC ( image, "EFIIMAGE %p could not load: %s\n",
00312                        image, strerror ( rc ) );
00313                 return rc;
00314         }
00315 
00316         /* Unload the image.  We can't leave it loaded, because we
00317          * have no "unload" operation.
00318          */
00319         bs->UnloadImage ( handle );
00320 
00321         return 0;
00322 }
00323 
00324 /** EFI image type */
00325 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
00326         .name = "EFI",
00327         .probe = efi_image_probe,
00328         .exec = efi_image_exec,
00329 };