Annotation of qemu/roms/ipxe/src/interface/efi/efi_pci.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2008 Michael Brown <[email protected]>.
                      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., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <stdlib.h>
                     22: #include <errno.h>
                     23: #include <ipxe/pci.h>
                     24: #include <ipxe/init.h>
                     25: #include <ipxe/efi/efi.h>
                     26: #include <ipxe/efi/efi_pci.h>
                     27: #include <ipxe/efi/efi_driver.h>
                     28: #include <ipxe/efi/Protocol/PciIo.h>
                     29: #include <ipxe/efi/Protocol/PciRootBridgeIo.h>
                     30: 
                     31: /** @file
                     32:  *
                     33:  * iPXE PCI I/O API for EFI
                     34:  *
                     35:  */
                     36: 
                     37: /******************************************************************************
                     38:  *
                     39:  * iPXE PCI API
                     40:  *
                     41:  ******************************************************************************
                     42:  */
                     43: 
                     44: /** PCI root bridge I/O protocol */
                     45: static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
                     46: EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
                     47: 
                     48: static unsigned long efipci_address ( struct pci_device *pci,
                     49:                                      unsigned long location ) {
                     50:        return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ),
                     51:                                 PCI_SLOT ( pci->busdevfn ),
                     52:                                 PCI_FUNC ( pci->busdevfn ),
                     53:                                 EFIPCI_OFFSET ( location ) );
                     54: }
                     55: 
                     56: int efipci_read ( struct pci_device *pci, unsigned long location,
                     57:                  void *value ) {
                     58:        EFI_STATUS efirc;
                     59: 
                     60:        if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ),
                     61:                                          efipci_address ( pci, location ), 1,
                     62:                                          value ) ) != 0 ) {
                     63:                DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx "
                     64:                      "failed: %s\n", PCI_ARGS ( pci ),
                     65:                      EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) );
                     66:                return -EIO;
                     67:        }
                     68: 
                     69:        return 0;
                     70: }
                     71: 
                     72: int efipci_write ( struct pci_device *pci, unsigned long location,
                     73:                   unsigned long value ) {
                     74:        EFI_STATUS efirc;
                     75: 
                     76:        if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ),
                     77:                                           efipci_address ( pci, location ), 1,
                     78:                                           &value ) ) != 0 ) {
                     79:                DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx "
                     80:                      "failed: %s\n", PCI_ARGS ( pci ),
                     81:                      EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) );
                     82:                return -EIO;
                     83:        }
                     84: 
                     85:        return 0;
                     86: }
                     87: 
                     88: PROVIDE_PCIAPI_INLINE ( efi, pci_num_bus );
                     89: PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte );
                     90: PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word );
                     91: PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword );
                     92: PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
                     93: PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
                     94: PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword );
                     95: 
                     96: /******************************************************************************
                     97:  *
                     98:  * EFI PCI device instantiation
                     99:  *
                    100:  ******************************************************************************
                    101:  */
                    102: 
                    103: /** EFI PCI I/O protocol GUID */
                    104: static EFI_GUID efi_pci_io_protocol_guid
                    105:        = EFI_PCI_IO_PROTOCOL_GUID;
                    106: 
                    107: /** EFI device path protocol GUID */
                    108: static EFI_GUID efi_device_path_protocol_guid
                    109:        = EFI_DEVICE_PATH_PROTOCOL_GUID;
                    110: 
                    111: /** EFI PCI devices */
                    112: static LIST_HEAD ( efi_pci_devices );
                    113: 
                    114: /**
                    115:  * Create EFI PCI device
                    116:  *
                    117:  * @v efidrv           EFI driver
                    118:  * @v device           EFI device
                    119:  * @ret efipci         EFI PCI device, or NULL
                    120:  */
                    121: struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
                    122:                                        EFI_HANDLE device ) {
                    123:        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
                    124:        struct efi_pci_device *efipci;
                    125:        union {
                    126:                EFI_PCI_IO_PROTOCOL *pci_io;
                    127:                void *interface;
                    128:        } pci_io;
                    129:        union {
                    130:                EFI_DEVICE_PATH_PROTOCOL *path;
                    131:                void *interface;
                    132:        } path;
                    133:        UINTN pci_segment, pci_bus, pci_dev, pci_fn;
                    134:        EFI_STATUS efirc;
                    135:        int rc;
                    136: 
                    137:        /* Allocate PCI device */
                    138:        efipci = zalloc ( sizeof ( *efipci ) );
                    139:        if ( ! efipci )
                    140:                goto err_zalloc;
                    141:        efipci->device = device;
                    142:        efipci->efidrv = efidrv;
                    143: 
                    144:        /* See if device is a PCI device */
                    145:        if ( ( efirc = bs->OpenProtocol ( device,
                    146:                                          &efi_pci_io_protocol_guid,
                    147:                                          &pci_io.interface,
                    148:                                          efidrv->driver.DriverBindingHandle,
                    149:                                          device,
                    150:                                          EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
                    151:                DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n",
                    152:                        device );
                    153:                goto err_open_protocol;
                    154:        }
                    155:        efipci->pci_io = pci_io.pci_io;
                    156: 
                    157:        /* Get PCI bus:dev.fn address */
                    158:        if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
                    159:                                                    &pci_segment,
                    160:                                                    &pci_bus, &pci_dev,
                    161:                                                    &pci_fn ) ) != 0 ) {
                    162:                DBGC ( efipci, "EFIPCI device %p could not get PCI "
                    163:                       "location: %s\n", device, efi_strerror ( efirc ) );
                    164:                goto err_get_location;
                    165:        }
                    166:        DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n",
                    167:                device, ( ( unsigned long ) pci_segment ),
                    168:                ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
                    169:                ( ( unsigned long ) pci_fn ) );
                    170: 
                    171:        /* Populate PCI device */
                    172:        pci_init ( &efipci->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
                    173:        if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) {
                    174:                DBGC ( efipci, "EFIPCI " PCI_FMT " cannot read PCI "
                    175:                       "configuration: %s\n",
                    176:                       PCI_ARGS ( &efipci->pci ), strerror ( rc ) );
                    177:                goto err_pci_read_config;
                    178:        }
                    179: 
                    180:        /* Retrieve device path */
                    181:        if ( ( efirc = bs->OpenProtocol ( device,
                    182:                                          &efi_device_path_protocol_guid,
                    183:                                          &path.interface,
                    184:                                          efidrv->driver.DriverBindingHandle,
                    185:                                          device,
                    186:                                          EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
                    187:                DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n",
                    188:                       PCI_ARGS ( &efipci->pci ) );
                    189:                goto err_no_device_path;
                    190:        }
                    191:        efipci->path = path.path;
                    192: 
                    193:        /* Add to list of PCI devices */
                    194:        list_add ( &efipci->list, &efi_pci_devices );
                    195: 
                    196:        return efipci;
                    197: 
                    198:        bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
                    199:                            efidrv->driver.DriverBindingHandle, device );
                    200:  err_no_device_path:
                    201:  err_pci_read_config:
                    202:  err_get_location:
                    203:        bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
                    204:                            efidrv->driver.DriverBindingHandle, device );
                    205:  err_open_protocol:
                    206:        free ( efipci );
                    207:  err_zalloc:
                    208:        return NULL;
                    209: }
                    210: 
                    211: /**
                    212:  * Enable EFI PCI device
                    213:  *
                    214:  * @v efipci           EFI PCI device
                    215:  * @ret efirc          EFI status code
                    216:  */
                    217: EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) {
                    218:        EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
                    219:        EFI_STATUS efirc;
                    220: 
                    221:        /* Enable device */
                    222:        if ( ( efirc = pci_io->Attributes ( pci_io,
                    223:                                            EfiPciIoAttributeOperationSet,
                    224:                                            EFI_PCI_DEVICE_ENABLE,
                    225:                                            NULL ) ) != 0 ) {
                    226:                DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n",
                    227:                       PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
                    228:                return efirc;
                    229:        }
                    230: 
                    231:        return 0;
                    232: }
                    233: 
                    234: /**
                    235:  * Find EFI PCI device by EFI device
                    236:  *
                    237:  * @v device           EFI device
                    238:  * @ret efipci         EFI PCI device, or NULL
                    239:  */
                    240: struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ) {
                    241:        struct efi_pci_device *efipci;
                    242: 
                    243:        list_for_each_entry ( efipci, &efi_pci_devices, list ) {
                    244:                if ( efipci->device == device )
                    245:                        return efipci;
                    246:        }
                    247:        return NULL;
                    248: }
                    249: 
                    250: /**
                    251:  * Find EFI PCI device by iPXE device
                    252:  *
                    253:  * @v dev              Device
                    254:  * @ret efipci         EFI PCI device, or NULL
                    255:  */
                    256: struct efi_pci_device * efipci_find ( struct device *dev ) {
                    257:        struct efi_pci_device *efipci;
                    258: 
                    259:        list_for_each_entry ( efipci, &efi_pci_devices, list ) {
                    260:                if ( &efipci->pci.dev == dev )
                    261:                        return efipci;
                    262:        }
                    263:        return NULL;
                    264: }
                    265: 
                    266: /**
                    267:  * Add EFI device as child of EFI PCI device
                    268:  *
                    269:  * @v efipci           EFI PCI device
                    270:  * @v device           EFI child device
                    271:  * @ret efirc          EFI status code
                    272:  */
                    273: EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci,
                    274:                              EFI_HANDLE device ) {
                    275:        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
                    276:        struct efi_driver *efidrv = efipci->efidrv;
                    277:        union {
                    278:                EFI_PCI_IO_PROTOCOL *pci_io;
                    279:                void *interface;
                    280:        } pci_io;
                    281:        EFI_STATUS efirc;
                    282: 
                    283:        /* Re-open the PCI_IO_PROTOCOL */
                    284:        if ( ( efirc = bs->OpenProtocol ( efipci->device,
                    285:                                          &efi_pci_io_protocol_guid,
                    286:                                          &pci_io.interface,
                    287:                                          efidrv->driver.DriverBindingHandle,
                    288:                                          device,
                    289:                                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                    290:                                          ) ) != 0 ) {
                    291:                DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n",
                    292:                       PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
                    293:                return efirc;
                    294:        }
                    295: 
                    296:        return 0;
                    297: }
                    298: 
                    299: /**
                    300:  * Remove EFI device as child of PCI device
                    301:  *
                    302:  * @v efipci           EFI PCI device
                    303:  * @v device           EFI child device
                    304:  * @ret efirc          EFI status code
                    305:  */
                    306: void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
                    307:        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
                    308:        struct efi_driver *efidrv = efipci->efidrv;
                    309: 
                    310:        bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
                    311:                            efidrv->driver.DriverBindingHandle, device );
                    312: }
                    313: 
                    314: /**
                    315:  * Destroy EFI PCI device
                    316:  *
                    317:  * @v efidrv           EFI driver
                    318:  * @v efipci           EFI PCI device
                    319:  */
                    320: void efipci_destroy ( struct efi_driver *efidrv,
                    321:                      struct efi_pci_device *efipci ) {
                    322:        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
                    323: 
                    324:        list_del ( &efipci->list );
                    325:        bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
                    326:                            efidrv->driver.DriverBindingHandle,
                    327:                            efipci->device );
                    328:        bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
                    329:                            efidrv->driver.DriverBindingHandle,
                    330:                            efipci->device );
                    331:        free ( efipci );
                    332: }
                    333: 
                    334: /******************************************************************************
                    335:  *
                    336:  * EFI PCI driver
                    337:  *
                    338:  ******************************************************************************
                    339:  */
                    340: 
                    341: /**
                    342:  * Check to see if driver supports a device
                    343:  *
                    344:  * @v driver           EFI driver
                    345:  * @v device           EFI device
                    346:  * @v child            Path to child device, if any
                    347:  * @ret efirc          EFI status code
                    348:  */
                    349: static EFI_STATUS EFIAPI
                    350: efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
                    351:                   EFI_DEVICE_PATH_PROTOCOL *child ) {
                    352:        struct efi_driver *efidrv =
                    353:                container_of ( driver, struct efi_driver, driver );
                    354:        struct efi_pci_device *efipci;
                    355:        EFI_STATUS efirc;
                    356:        int rc;
                    357: 
                    358:        DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child );
                    359: 
                    360:        /* Create temporary corresponding PCI device, if any */
                    361:        efipci = efipci_create ( efidrv, device );
                    362:        if ( ! efipci ) {
                    363:                /* Non-PCI devices are simply unsupported */
                    364:                efirc = EFI_UNSUPPORTED;
                    365:                goto err_not_pci;
                    366:        }
                    367: 
                    368:        /* Look for a driver */
                    369:        if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
                    370:                DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
                    371:                        PCI_ARGS ( &efipci->pci ) );
                    372:                efirc = EFI_UNSUPPORTED;
                    373:                goto err_no_driver;
                    374:        }
                    375: 
                    376:        DBGC ( efipci, "EFIPCI " PCI_FMT " is supported by driver \"%s\"\n",
                    377:               PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
                    378: 
                    379:        /* Destroy temporary PCI device */
                    380:        efipci_destroy ( efidrv, efipci );
                    381: 
                    382:        return 0;
                    383: 
                    384:  err_no_driver:
                    385:        efipci_destroy ( efidrv, efipci );
                    386:  err_not_pci:
                    387:        return efirc;
                    388: }
                    389: 
                    390: /**
                    391:  * Attach driver to device
                    392:  *
                    393:  * @v driver           EFI driver
                    394:  * @v device           EFI device
                    395:  * @v child            Path to child device, if any
                    396:  * @ret efirc          EFI status code
                    397:  */
                    398: static EFI_STATUS EFIAPI
                    399: efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
                    400:               EFI_DEVICE_PATH_PROTOCOL *child ) {
                    401:        struct efi_driver *efidrv =
                    402:                container_of ( driver, struct efi_driver, driver );
                    403:        struct efi_pci_device *efipci;
                    404:        EFI_STATUS efirc;
                    405:        int rc;
                    406: 
                    407:        DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child );
                    408: 
                    409:        /* Create corresponding PCI device */
                    410:        efipci = efipci_create ( efidrv, device );
                    411:        if ( ! efipci ) {
                    412:                efirc = EFI_OUT_OF_RESOURCES;
                    413:                goto err_create;
                    414:        }
                    415: 
                    416:        /* Find driver */
                    417:        if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
                    418:                DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
                    419:                       PCI_ARGS ( &efipci->pci ) );
                    420:                efirc = RC_TO_EFIRC ( rc );
                    421:                goto err_find_driver;
                    422:        }
                    423: 
                    424:        /* Enable PCI device */
                    425:        if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
                    426:                goto err_enable;
                    427: 
                    428:        /* Probe driver */
                    429:        if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
                    430:                DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver "
                    431:                       "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ),
                    432:                       efipci->pci.id->name, strerror ( rc ) );
                    433:                efirc = RC_TO_EFIRC ( rc );
                    434:                goto err_probe;
                    435:        }
                    436: 
                    437:        return 0;
                    438: 
                    439:        pci_remove ( &efipci->pci );
                    440:  err_probe:
                    441:  err_enable:
                    442:  err_find_driver:
                    443:        efipci_destroy ( efidrv, efipci );
                    444:  err_create:
                    445:        return efirc;
                    446: }
                    447: 
                    448: /**
                    449:  * Detach driver from device
                    450:  *
                    451:  * @v driver           EFI driver
                    452:  * @v device           EFI device
                    453:  * @v pci              PCI device
                    454:  * @v num_children     Number of child devices
                    455:  * @v children         List of child devices
                    456:  * @ret efirc          EFI status code
                    457:  */
                    458: static EFI_STATUS EFIAPI
                    459: efipci_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
                    460:              UINTN num_children, EFI_HANDLE *children ) {
                    461:        struct efi_driver *efidrv =
                    462:                container_of ( driver, struct efi_driver, driver );
                    463:        struct efi_pci_device *efipci;
                    464: 
                    465:        DBGC ( efidrv, "EFIPCI DRIVER_STOP %p (%ld %p)\n",
                    466:               device, ( ( unsigned long ) num_children ), children );
                    467: 
                    468:        /* Find PCI device */
                    469:        efipci = efipci_find_efi ( device );
                    470:        if ( ! efipci ) {
                    471:                DBGC ( efidrv, "EFIPCI device %p not started!\n", device );
                    472:                return EFI_INVALID_PARAMETER;
                    473:        }
                    474: 
                    475:        /* Remove device */
                    476:        pci_remove ( &efipci->pci );
                    477: 
                    478:        /* Delete EFI PCI device */
                    479:        efipci_destroy ( efidrv, efipci );
                    480: 
                    481:        return 0;
                    482: }
                    483: 
                    484: /** EFI PCI driver */
                    485: static struct efi_driver efipci_driver =
                    486:        EFI_DRIVER_INIT ( "PCI", efipci_supported, efipci_start, efipci_stop );
                    487: 
                    488: /**
                    489:  * Install EFI PCI driver
                    490:  *
                    491:  */
                    492: static void efipci_driver_startup ( void ) {
                    493:        struct efi_driver *efidrv = &efipci_driver;
                    494:        EFI_STATUS efirc;
                    495: 
                    496:        /* Install driver */
                    497:        if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
                    498:                DBGC ( efidrv, "EFIPCI could not install driver: %s\n",
                    499:                       efi_strerror ( efirc ) );
                    500:                return;
                    501:        }
                    502: 
                    503:        DBGC ( efidrv, "EFIPCI driver installed\n" );
                    504: }
                    505: 
                    506: /**
                    507:  * Shut down EFI PCI driver
                    508:  *
                    509:  * @v booting          System is shutting down for OS boot
                    510:  */
                    511: static void efipci_driver_shutdown ( int booting __unused ) {
                    512:        struct efi_driver *efidrv = &efipci_driver;
                    513:        struct efi_pci_device *efipci;
                    514:        struct efi_pci_device *tmp;
                    515: 
                    516:        /* Shut down any remaining devices */
                    517:        list_for_each_entry_safe ( efipci, tmp, &efi_pci_devices, list ) {
                    518:                DBGC ( efipci, "EFIPCI " PCI_FMT " still active at shutdown; "
                    519:                       "forcing close\n", PCI_ARGS ( &efipci->pci ) );
                    520:                pci_remove ( &efipci->pci );
                    521:                efipci_destroy ( efidrv, efipci );
                    522:        }
                    523: }
                    524: 
                    525: /** EFI PCI startup function */
                    526: struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = {
                    527:        .startup = efipci_driver_startup,
                    528:        .shutdown = efipci_driver_shutdown,
                    529: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.