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