iPXE
efi_driver.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 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 <stddef.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <errno.h>
00027 #include <ipxe/version.h>
00028 #include <ipxe/efi/efi.h>
00029 #include <ipxe/efi/Protocol/DriverBinding.h>
00030 #include <ipxe/efi/Protocol/ComponentName2.h>
00031 #include <ipxe/efi/Protocol/DevicePath.h>
00032 #include <ipxe/efi/efi_strings.h>
00033 #include <ipxe/efi/efi_utils.h>
00034 #include <ipxe/efi/efi_driver.h>
00035 
00036 /** @file
00037  *
00038  * EFI driver interface
00039  *
00040  */
00041 
00042 static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding;
00043 
00044 /** List of controlled EFI devices */
00045 static LIST_HEAD ( efi_devices );
00046 
00047 /** We are currently disconnecting drivers */
00048 static int efi_driver_disconnecting;
00049 
00050 /**
00051  * Find EFI device
00052  *
00053  * @v device            EFI device handle
00054  * @ret efidev          EFI device, or NULL if not found
00055  */
00056 static struct efi_device * efidev_find ( EFI_HANDLE device ) {
00057         struct efi_device *efidev;
00058 
00059         /* Look for an existing EFI device */
00060         list_for_each_entry ( efidev, &efi_devices, dev.siblings ) {
00061                 if ( efidev->device == device )
00062                         return efidev;
00063         }
00064 
00065         return NULL;
00066 }
00067 
00068 /**
00069  * Get parent EFI device
00070  *
00071  * @v dev               Generic device
00072  * @ret efidev          Parent EFI device, or NULL
00073  */
00074 struct efi_device * efidev_parent ( struct device *dev ) {
00075         struct device *parent;
00076         struct efi_device *efidev;
00077 
00078         /* Walk upwards until we find a registered EFI device */
00079         while ( ( parent = dev->parent ) ) {
00080                 list_for_each_entry ( efidev, &efi_devices, dev.siblings ) {
00081                         if ( parent == &efidev->dev )
00082                                 return efidev;
00083                 }
00084                 dev = parent;
00085         }
00086 
00087         return NULL;
00088 }
00089 
00090 /**
00091  * Check to see if driver supports a device
00092  *
00093  * @v driver            EFI driver
00094  * @v device            EFI device
00095  * @v child             Path to child device, if any
00096  * @ret efirc           EFI status code
00097  */
00098 static EFI_STATUS EFIAPI
00099 efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
00100                        EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
00101         struct efi_driver *efidrv;
00102         int rc;
00103 
00104         DBGCP ( device, "EFIDRV %s DRIVER_SUPPORTED",
00105                 efi_handle_name ( device ) );
00106         if ( child )
00107                 DBGCP ( device, " (child %s)", efi_devpath_text ( child ) );
00108         DBGCP ( device, "\n" );
00109 
00110         /* Do nothing if we are already driving this device */
00111         if ( efidev_find ( device ) != NULL ) {
00112                 DBGCP ( device, "EFIDRV %s is already started\n",
00113                         efi_handle_name ( device ) );
00114                 return EFI_ALREADY_STARTED;
00115         }
00116 
00117         /* Look for a driver claiming to support this device */
00118         for_each_table_entry ( efidrv, EFI_DRIVERS ) {
00119                 if ( ( rc = efidrv->supported ( device ) ) == 0 ) {
00120                         DBGC ( device, "EFIDRV %s has driver \"%s\"\n",
00121                                efi_handle_name ( device ), efidrv->name );
00122                         return 0;
00123                 }
00124         }
00125         DBGCP ( device, "EFIDRV %s has no driver\n",
00126                 efi_handle_name ( device ) );
00127 
00128         return EFI_UNSUPPORTED;
00129 }
00130 
00131 /**
00132  * Attach driver to device
00133  *
00134  * @v driver            EFI driver
00135  * @v device            EFI device
00136  * @v child             Path to child device, if any
00137  * @ret efirc           EFI status code
00138  */
00139 static EFI_STATUS EFIAPI
00140 efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
00141                    EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
00142         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00143         struct efi_driver *efidrv;
00144         struct efi_device *efidev;
00145         union {
00146                 EFI_DEVICE_PATH_PROTOCOL *path;
00147                 void *interface;
00148         } path;
00149         EFI_DEVICE_PATH_PROTOCOL *path_end;
00150         size_t path_len;
00151         EFI_TPL saved_tpl;
00152         EFI_STATUS efirc;
00153         int rc;
00154 
00155         DBGC ( device, "EFIDRV %s DRIVER_START", efi_handle_name ( device ) );
00156         if ( child )
00157                 DBGC ( device, " (child %s)", efi_devpath_text ( child ) );
00158         DBGC ( device, "\n" );
00159 
00160         /* Do nothing if we are already driving this device */
00161         efidev = efidev_find ( device );
00162         if ( efidev ) {
00163                 DBGCP ( device, "EFIDRV %s is already started\n",
00164                         efi_handle_name ( device ) );
00165                 efirc = EFI_ALREADY_STARTED;
00166                 goto err_already_started;
00167         }
00168 
00169         /* Raise TPL */
00170         saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
00171 
00172         /* Do nothing if we are currently disconnecting drivers */
00173         if ( efi_driver_disconnecting ) {
00174                 DBGC ( device, "EFIDRV %s refusing to start during "
00175                        "disconnection\n", efi_handle_name ( device ) );
00176                 efirc = EFI_NOT_READY;
00177                 goto err_disconnecting;
00178         }
00179 
00180         /* Open device path */
00181         if ( ( efirc = bs->OpenProtocol ( device,
00182                                           &efi_device_path_protocol_guid,
00183                                           &path.interface, efi_image_handle,
00184                                           device,
00185                                           EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
00186                 rc = -EEFI ( efirc );
00187                 DBGC ( device, "EFIDRV %s could not open device path: %s\n",
00188                        efi_handle_name ( device ), strerror ( rc ) );
00189                 goto err_open_path;
00190         }
00191         path_len = ( efi_devpath_len ( path.path ) + sizeof ( *path_end ) );
00192 
00193         /* Allocate and initialise structure */
00194         efidev = zalloc ( sizeof ( *efidev ) + path_len );
00195         if ( ! efidev ) {
00196                 efirc = EFI_OUT_OF_RESOURCES;
00197                 goto err_alloc;
00198         }
00199         efidev->device = device;
00200         efidev->dev.desc.bus_type = BUS_TYPE_EFI;
00201         efidev->path = ( ( ( void * ) efidev ) + sizeof ( *efidev ) );
00202         memcpy ( efidev->path, path.path, path_len );
00203         INIT_LIST_HEAD ( &efidev->dev.children );
00204         list_add ( &efidev->dev.siblings, &efi_devices );
00205 
00206         /* Close device path */
00207         bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
00208                             efi_image_handle, device );
00209         path.path = NULL;
00210 
00211         /* Try to start this device */
00212         for_each_table_entry ( efidrv, EFI_DRIVERS ) {
00213                 if ( ( rc = efidrv->supported ( device ) ) != 0 ) {
00214                         DBGC ( device, "EFIDRV %s is not supported by driver "
00215                                "\"%s\": %s\n", efi_handle_name ( device ),
00216                                efidrv->name,
00217                                strerror ( rc ) );
00218                         continue;
00219                 }
00220                 if ( ( rc = efidrv->start ( efidev ) ) == 0 ) {
00221                         efidev->driver = efidrv;
00222                         DBGC ( device, "EFIDRV %s using driver \"%s\"\n",
00223                                efi_handle_name ( device ),
00224                                efidev->driver->name );
00225                         bs->RestoreTPL ( saved_tpl );
00226                         return 0;
00227                 }
00228                 DBGC ( device, "EFIDRV %s could not start driver \"%s\": %s\n",
00229                        efi_handle_name ( device ), efidrv->name,
00230                        strerror ( rc ) );
00231         }
00232         efirc = EFI_UNSUPPORTED;
00233 
00234         list_del ( &efidev->dev.siblings );
00235         free ( efidev );
00236  err_alloc:
00237         if ( path.path ) {
00238                 bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
00239                                     efi_image_handle, device );
00240         }
00241  err_open_path:
00242  err_disconnecting:
00243         bs->RestoreTPL ( saved_tpl );
00244  err_already_started:
00245         return efirc;
00246 }
00247 
00248 /**
00249  * Detach driver from device
00250  *
00251  * @v driver            EFI driver
00252  * @v device            EFI device
00253  * @v pci               PCI device
00254  * @v num_children      Number of child devices
00255  * @v children          List of child devices
00256  * @ret efirc           EFI status code
00257  */
00258 static EFI_STATUS EFIAPI
00259 efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
00260                   EFI_HANDLE device, UINTN num_children,
00261                   EFI_HANDLE *children ) {
00262         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00263         struct efi_driver *efidrv;
00264         struct efi_device *efidev;
00265         EFI_TPL saved_tpl;
00266         UINTN i;
00267 
00268         DBGC ( device, "EFIDRV %s DRIVER_STOP", efi_handle_name ( device ) );
00269         for ( i = 0 ; i < num_children ; i++ ) {
00270                 DBGC ( device, "%s%s", ( i ? ", " : " child " ),
00271                        efi_handle_name ( children[i] ) );
00272         }
00273         DBGC ( device, "\n" );
00274 
00275         /* Do nothing unless we are driving this device */
00276         efidev = efidev_find ( device );
00277         if ( ! efidev ) {
00278                 DBGCP ( device, "EFIDRV %s is not started\n",
00279                         efi_handle_name ( device ) );
00280                 return EFI_DEVICE_ERROR;
00281         }
00282 
00283         /* Raise TPL */
00284         saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
00285 
00286         /* Stop this device */
00287         efidrv = efidev->driver;
00288         assert ( efidrv != NULL );
00289         efidrv->stop ( efidev );
00290         list_del ( &efidev->dev.siblings );
00291         free ( efidev );
00292 
00293         bs->RestoreTPL ( saved_tpl );
00294         return 0;
00295 }
00296 
00297 /** EFI driver binding protocol */
00298 static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding = {
00299         .Supported = efi_driver_supported,
00300         .Start = efi_driver_start,
00301         .Stop = efi_driver_stop,
00302 };
00303 
00304 /**
00305  * Look up driver name
00306  *
00307  * @v wtf               Component name protocol
00308  * @v language          Language to use
00309  * @v driver_name       Driver name to fill in
00310  * @ret efirc           EFI status code
00311  */
00312 static EFI_STATUS EFIAPI
00313 efi_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
00314                   CHAR8 *language __unused, CHAR16 **driver_name ) {
00315         const wchar_t *name;
00316 
00317         name = ( product_wname[0] ? product_wname : build_wname );
00318         *driver_name = ( ( wchar_t * ) name );
00319         return 0;
00320 }
00321 
00322 /**
00323  * Look up controller name
00324  *
00325  * @v wtf               Component name protocol
00326  * @v device            Device
00327  * @v child             Child device, or NULL
00328  * @v language          Language to use
00329  * @v driver_name       Device name to fill in
00330  * @ret efirc           EFI status code
00331  */
00332 static EFI_STATUS EFIAPI
00333 efi_driver_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
00334                              EFI_HANDLE device, EFI_HANDLE child,
00335                              CHAR8 *language, CHAR16 **controller_name ) {
00336         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00337         union {
00338                 EFI_COMPONENT_NAME2_PROTOCOL *name2;
00339                 void *interface;
00340         } name2;
00341         EFI_STATUS efirc;
00342 
00343         /* Delegate to the EFI_COMPONENT_NAME2_PROTOCOL instance
00344          * installed on child handle, if present.
00345          */
00346         if ( ( child != NULL ) &&
00347              ( ( efirc = bs->OpenProtocol (
00348                           child, &efi_component_name2_protocol_guid,
00349                           &name2.interface, NULL, NULL,
00350                           EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) == 0 ) ) {
00351                 return name2.name2->GetControllerName ( name2.name2, device,
00352                                                         child, language,
00353                                                         controller_name );
00354         }
00355 
00356         /* Otherwise, let EFI use the default Device Path Name */
00357         return EFI_UNSUPPORTED;
00358 }
00359 
00360 /** EFI component name protocol */
00361 static EFI_COMPONENT_NAME2_PROTOCOL efi_wtf = {
00362         .GetDriverName = efi_driver_name,
00363         .GetControllerName = efi_driver_controller_name,
00364         .SupportedLanguages = "en",
00365 };
00366 
00367 /**
00368  * Install EFI driver
00369  *
00370  * @ret rc              Return status code
00371  */
00372 int efi_driver_install ( void ) {
00373         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00374         EFI_STATUS efirc;
00375         int rc;
00376 
00377         /* Calculate driver version number.  We use the build
00378          * timestamp (in seconds since the Epoch) shifted right by six
00379          * bits: this gives us an approximately one-minute resolution
00380          * and a scheme which will last until the year 10680.
00381          */
00382         efi_driver_binding.Version = ( build_timestamp >> 6 );
00383 
00384         /* Install protocols on image handle */
00385         efi_driver_binding.ImageHandle = efi_image_handle;
00386         efi_driver_binding.DriverBindingHandle = efi_image_handle;
00387         if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
00388                         &efi_image_handle,
00389                         &efi_driver_binding_protocol_guid, &efi_driver_binding,
00390                         &efi_component_name2_protocol_guid, &efi_wtf,
00391                         NULL ) ) != 0 ) {
00392                 rc = -EEFI ( efirc );
00393                 DBGC ( &efi_driver_binding, "EFIDRV could not install "
00394                        "protocols: %s\n", strerror ( rc ) );
00395                 return rc;
00396         }
00397 
00398         return 0;
00399 }
00400 
00401 /**
00402  * Uninstall EFI driver
00403  *
00404  */
00405 void efi_driver_uninstall ( void ) {
00406         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00407 
00408         /* Uninstall protocols */
00409         bs->UninstallMultipleProtocolInterfaces (
00410                 efi_image_handle,
00411                 &efi_driver_binding_protocol_guid, &efi_driver_binding,
00412                 &efi_component_name2_protocol_guid, &efi_wtf, NULL );
00413 }
00414 
00415 /**
00416  * Try to connect EFI driver
00417  *
00418  * @v device            EFI device
00419  * @ret rc              Return status code
00420  */
00421 static int efi_driver_connect ( EFI_HANDLE device ) {
00422         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00423         EFI_HANDLE drivers[2] =
00424                 { efi_driver_binding.DriverBindingHandle, NULL };
00425         EFI_STATUS efirc;
00426         int rc;
00427 
00428         /* Check if we want to drive this device */
00429         if ( ( efirc = efi_driver_supported ( &efi_driver_binding, device,
00430                                               NULL ) ) != 0 ) {
00431                 /* Not supported; not an error */
00432                 return 0;
00433         }
00434 
00435         /* Disconnect any existing drivers */
00436         DBGC2 ( device, "EFIDRV %s before disconnecting:\n",
00437                 efi_handle_name ( device ) );
00438         DBGC2_EFI_PROTOCOLS ( device, device );
00439         DBGC ( device, "EFIDRV %s disconnecting existing drivers\n",
00440                efi_handle_name ( device ) );
00441         efi_driver_disconnecting = 1;
00442         if ( ( efirc = bs->DisconnectController ( device, NULL,
00443                                                   NULL ) ) != 0 ) {
00444                 rc = -EEFI ( efirc );
00445                 DBGC ( device, "EFIDRV %s could not disconnect existing "
00446                        "drivers: %s\n", efi_handle_name ( device ),
00447                        strerror ( rc ) );
00448                 /* Ignore the error and attempt to connect our drivers */
00449         }
00450         efi_driver_disconnecting = 0;
00451         DBGC2 ( device, "EFIDRV %s after disconnecting:\n",
00452                 efi_handle_name ( device ) );
00453         DBGC2_EFI_PROTOCOLS ( device, device );
00454 
00455         /* Connect our driver */
00456         DBGC ( device, "EFIDRV %s connecting new drivers\n",
00457                efi_handle_name ( device ) );
00458         if ( ( efirc = bs->ConnectController ( device, drivers, NULL,
00459                                                FALSE ) ) != 0 ) {
00460                 rc = -EEFI ( efirc );
00461                 DBGC ( device, "EFIDRV %s could not connect new drivers: "
00462                        "%s\n", efi_handle_name ( device ), strerror ( rc ) );
00463                 return rc;
00464         }
00465         DBGC2 ( device, "EFIDRV %s after connecting:\n",
00466                 efi_handle_name ( device ) );
00467         DBGC2_EFI_PROTOCOLS ( device, device );
00468 
00469         return 0;
00470 }
00471 
00472 /**
00473  * Try to disconnect EFI driver
00474  *
00475  * @v device            EFI device
00476  * @ret rc              Return status code
00477  */
00478 static int efi_driver_disconnect ( EFI_HANDLE device ) {
00479         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00480 
00481         /* Disconnect our driver */
00482         efi_driver_disconnecting = 1;
00483         bs->DisconnectController ( device,
00484                                    efi_driver_binding.DriverBindingHandle,
00485                                    NULL );
00486         efi_driver_disconnecting = 0;
00487         return 0;
00488 }
00489 
00490 /**
00491  * Reconnect original EFI driver
00492  *
00493  * @v device            EFI device
00494  * @ret rc              Return status code
00495  */
00496 static int efi_driver_reconnect ( EFI_HANDLE device ) {
00497         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00498 
00499         /* Reconnect any available driver */
00500         bs->ConnectController ( device, NULL, NULL, FALSE );
00501 
00502         return 0;
00503 }
00504 
00505 /**
00506  * Connect/disconnect EFI driver from all handles
00507  *
00508  * @v method            Connect/disconnect method
00509  * @ret rc              Return status code
00510  */
00511 static int efi_driver_handles ( int ( * method ) ( EFI_HANDLE handle ) ) {
00512         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00513         EFI_HANDLE *handles;
00514         UINTN num_handles;
00515         EFI_STATUS efirc;
00516         UINTN i;
00517         int rc;
00518 
00519         /* Enumerate all handles */
00520         if ( ( efirc = bs->LocateHandleBuffer ( AllHandles, NULL, NULL,
00521                                                 &num_handles,
00522                                                 &handles ) ) != 0 ) {
00523                 rc = -EEFI ( efirc );
00524                 DBGC ( &efi_driver_binding, "EFIDRV could not list handles: "
00525                        "%s\n", strerror ( rc ) );
00526                 goto err_locate;
00527         }
00528 
00529         /* Connect/disconnect driver from all handles */
00530         for ( i = 0 ; i < num_handles ; i++ ) {
00531                 if ( ( rc = method ( handles[i] ) ) != 0 ) {
00532                         /* Ignore errors and continue to process
00533                          * remaining handles.
00534                          */
00535                 }
00536         }
00537 
00538         /* Success */
00539         rc = 0;
00540 
00541         bs->FreePool ( handles );
00542  err_locate:
00543         return rc;
00544 }
00545 
00546 /**
00547  * Connect EFI driver to all possible devices
00548  *
00549  * @ret rc              Return status code
00550  */
00551 int efi_driver_connect_all ( void ) {
00552 
00553         DBGC ( &efi_driver_binding, "EFIDRV connecting our drivers\n" );
00554         return efi_driver_handles ( efi_driver_connect );
00555 }
00556 
00557 /**
00558  * Disconnect EFI driver from all possible devices
00559  *
00560  * @ret rc              Return status code
00561  */
00562 void efi_driver_disconnect_all ( void ) {
00563 
00564         DBGC ( &efi_driver_binding, "EFIDRV disconnecting our drivers\n" );
00565         efi_driver_handles ( efi_driver_disconnect );
00566 }
00567 
00568 /**
00569  * Reconnect original EFI drivers to all possible devices
00570  *
00571  * @ret rc              Return status code
00572  */
00573 void efi_driver_reconnect_all ( void ) {
00574 
00575         DBGC ( &efi_driver_binding, "EFIDRV reconnecting old drivers\n" );
00576         efi_driver_handles ( efi_driver_reconnect );
00577 }