Home | History | Annotate | Download | only in MarvellYukonDxe
      1 /**  <at> file
      2   Implementation of driver entry point and driver binding protocol.
      3 
      4 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
      5 Copyright (c) 2011 - 2016, ARM Limited. All rights reserved.
      6 
      7 This program and the accompanying materials are licensed
      8 and made available under the terms and conditions of the BSD License which
      9 accompanies this distribution. The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include <Library/NetLib.h>
     18 #include <Library/DevicePathLib.h>
     19 #include "MarvellYukon.h"
     20 #include "if_msk.h"
     21 
     22 STATIC LIST_ENTRY MarvellYukonDrvDataHead;
     23 
     24 /**
     25   Test to see if this driver supports ControllerHandle. This service
     26   is called by the EFI boot service ConnectController(). In
     27   order to make drivers as small as possible, there are a few calling
     28   restrictions for this service. ConnectController() must
     29   follow these calling restrictions. If any other agent wishes to call
     30   Supported() it must also follow these calling restrictions.
     31 
     32    <at> param  This                   Protocol instance pointer.
     33    <at> param  ControllerHandle       Handle of device to test.
     34    <at> param  RemainingDevicePath    Optional parameter use to pick a specific child
     35                                                              device to start.
     36 
     37    <at> retval EFI_SUCCESS            This driver supports this device.
     38    <at> retval EFI_ALREADY_STARTED    This driver is already running on this device.
     39    <at> retval other                  This driver does not support this device.
     40 
     41 **/
     42 EFI_STATUS
     43 EFIAPI
     44 MarvellYukonDriverSupported (
     45     IN EFI_DRIVER_BINDING_PROTOCOL    *This,
     46     IN EFI_HANDLE                     Controller,
     47     IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
     48     )
     49 {
     50   EFI_STATUS              Status;
     51   EFI_PCI_IO_PROTOCOL     *PciIo;
     52 
     53   //
     54   // Test that the PCI IO Protocol is attached to the controller handle and no other driver is consuming it
     55   //
     56   Status = gBS->OpenProtocol (
     57         Controller,
     58         &gEfiPciIoProtocolGuid,
     59         (VOID **) &PciIo,
     60         This->DriverBindingHandle,
     61         Controller,
     62         EFI_OPEN_PROTOCOL_BY_DRIVER
     63         );
     64 
     65   if (!EFI_ERROR (Status)) {
     66     //
     67     // Test whether the controller is on a supported NIC
     68     //
     69     Status = mskc_probe (PciIo);
     70     if (EFI_ERROR (Status)) {
     71       Status = EFI_UNSUPPORTED;
     72     } else {
     73       DEBUG ((EFI_D_NET, "Marvell Yukon: MarvellYukonDriverSupported: Supported Controller = %p\n", Controller));
     74     }
     75 
     76     gBS->CloseProtocol (
     77           Controller,
     78           &gEfiPciIoProtocolGuid,
     79           This->DriverBindingHandle,
     80           Controller
     81           );
     82   }
     83 
     84   return Status;
     85 }
     86 
     87 /**
     88   Start this driver on Controller by opening PciIo and DevicePath protocols.
     89   Initialize PXE structures, create a copy of the Controller Device Path with the
     90   NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
     91   on the newly created Device Path.
     92 
     93   @param [in] pThis                   Protocol instance pointer.
     94   @param [in] Controller              Handle of device to work with.
     95   @param [in] pRemainingDevicePath    Not used, always produce all possible children.
     96 
     97   @retval EFI_SUCCESS                 This driver is added to Controller.
     98   @retval other                       This driver does not support this device.
     99 
    100 **/
    101 EFI_STATUS
    102 EFIAPI
    103 MarvellYukonDriverStart (
    104     IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
    105     IN EFI_HANDLE Controller,
    106     IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
    107     )
    108 {
    109 
    110   EFI_STATUS                       Status;
    111   EFI_DEVICE_PATH_PROTOCOL         *ParentDevicePath;
    112   MAC_ADDR_DEVICE_PATH             MacDeviceNode;
    113   VOID                            *ChildPciIo;
    114   YUKON_DRIVER                    *YukonDriver;
    115   struct msk_softc                *ScData;
    116   EFI_PCI_IO_PROTOCOL             *PciIo;
    117   UINTN                            Port;
    118 
    119   Status = gBS->OpenProtocol (
    120         Controller,
    121         &gEfiPciIoProtocolGuid,
    122         (VOID **) &PciIo,
    123         pThis->DriverBindingHandle,
    124         Controller,
    125         EFI_OPEN_PROTOCOL_BY_DRIVER
    126         );
    127 
    128   if (EFI_ERROR (Status)) {
    129     DEBUG ((EFI_D_ERROR, "Marvell Yukon: OpenProtocol: EFI_PCI_IO_PROTOCOL ERROR Status = %r\n", Status));
    130     gBS->FreePool (YukonDriver);
    131     return Status;
    132   }
    133 
    134   //
    135   // Initialize Marvell Yukon controller
    136   // Get number of ports and MAC address for each port
    137   //
    138   Status = mskc_attach (PciIo, &ScData);
    139   if (EFI_ERROR (Status)) {
    140     return Status;
    141   }
    142 
    143   Status = MarvellYukonAddControllerData (Controller, ScData);
    144   if (EFI_ERROR (Status)) {
    145     return Status;
    146   }
    147 
    148   for (Port = 0; Port < ScData->msk_num_port; Port++) {
    149 
    150     Status = gBS->AllocatePool (EfiBootServicesData,
    151                                 sizeof (YUKON_DRIVER),
    152                                 (VOID**) &YukonDriver);
    153     if (EFI_ERROR (Status)) {
    154       DEBUG ((DEBUG_ERROR, "Marvell Yukon: AllocatePool() failed with Status = %r\n", Status));
    155       return Status;
    156     }
    157 
    158     if (ScData->msk_if[Port] == NULL) {
    159       DEBUG ((DEBUG_ERROR, "Marvell Yukon: AllocatePool() failed with Status = %r\n", EFI_BAD_BUFFER_SIZE));
    160       return EFI_BAD_BUFFER_SIZE;
    161     }
    162 
    163     gBS->SetMem (YukonDriver, sizeof (YUKON_DRIVER), 0);
    164     EfiInitializeLock (&YukonDriver->Lock, TPL_NOTIFY);
    165 
    166     //
    167     //  Set the structure signature
    168     //
    169     YukonDriver->Signature = YUKON_DRIVER_SIGNATURE;
    170 
    171     //
    172     // Set MAC address
    173     //
    174     gBS->CopyMem (&YukonDriver->SnpMode.PermanentAddress, &(ScData->msk_if[Port])->MacAddress,
    175                   sizeof (EFI_MAC_ADDRESS));
    176 
    177     //
    178     // Set Port number
    179     //
    180     YukonDriver->Port = Port;
    181 
    182     //
    183     //  Initialize the simple network protocol
    184     //
    185     Status = InitializeSNPProtocol (YukonDriver);
    186 
    187     if (EFI_ERROR (Status)) {
    188       DEBUG ((DEBUG_ERROR, "Marvell Yukon: InitializeSNPProtocol: ERROR Status = %r\n", Status));
    189       gBS->CloseProtocol (
    190             Controller,
    191             &gEfiPciIoProtocolGuid,
    192             pThis->DriverBindingHandle,
    193             Controller
    194             );
    195     }
    196 
    197     //
    198     // Set Device Path
    199     //
    200     Status = gBS->OpenProtocol (
    201           Controller,
    202           &gEfiDevicePathProtocolGuid,
    203           (VOID **) &ParentDevicePath,
    204           pThis->DriverBindingHandle,
    205           Controller,
    206           EFI_OPEN_PROTOCOL_GET_PROTOCOL
    207           );
    208 
    209     if (EFI_ERROR (Status)) {
    210       DEBUG ((DEBUG_ERROR, "Marvell Yukon: OpenProtocol:EFI_DEVICE_PATH_PROTOCOL error. Status = %r\n", Status));
    211 
    212       gBS->CloseProtocol (
    213             Controller,
    214             &gEfiPciIoProtocolGuid,
    215             pThis->DriverBindingHandle,
    216             Controller
    217             );
    218 
    219       gBS->FreePool (YukonDriver);
    220       return Status;
    221     }
    222 
    223     gBS->SetMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH), 0);
    224     MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
    225     MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
    226 
    227     SetDevicePathNodeLength (&MacDeviceNode, sizeof (MacDeviceNode));
    228 
    229     //
    230     // Assign fields for device path
    231     //
    232     gBS->CopyMem (&YukonDriver->SnpMode.CurrentAddress, &YukonDriver->SnpMode.PermanentAddress,
    233                   sizeof (EFI_MAC_ADDRESS));
    234     gBS->CopyMem (&MacDeviceNode.MacAddress, &YukonDriver->SnpMode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));
    235 
    236     MacDeviceNode.IfType = YukonDriver->SnpMode.IfType;
    237     YukonDriver->DevicePath = AppendDevicePathNode (ParentDevicePath, &MacDeviceNode.Header);
    238     if (YukonDriver->DevicePath == NULL) {
    239       DEBUG ((DEBUG_ERROR, "Marvell Yukon: AppendDevicePathNode: ERROR Status = %r\n", EFI_OUT_OF_RESOURCES));
    240       gBS->CloseProtocol (
    241             Controller,
    242             &gEfiPciIoProtocolGuid,
    243             pThis->DriverBindingHandle,
    244             Controller
    245             );
    246       gBS->FreePool (YukonDriver);
    247       return EFI_OUT_OF_RESOURCES;
    248     }
    249 
    250     //
    251     //  Install both the simple network and device path protocols.
    252     //
    253     Status = gBS->InstallMultipleProtocolInterfaces (
    254           &YukonDriver->Controller,
    255           &gEfiSimpleNetworkProtocolGuid,
    256           &YukonDriver->Snp,
    257           &gEfiDevicePathProtocolGuid,
    258           YukonDriver->DevicePath,
    259           NULL
    260           );
    261 
    262     if (EFI_ERROR (Status)) {
    263       DEBUG ((DEBUG_ERROR, "Marvell Yukon: InstallMultipleProtocolInterfaces error. Status = %r\n", Status));
    264 
    265       gBS->CloseProtocol (
    266             Controller,
    267             &gEfiPciIoProtocolGuid,
    268             pThis->DriverBindingHandle,
    269             Controller
    270             );
    271 
    272       gBS->FreePool (YukonDriver->DevicePath);
    273       gBS->FreePool (YukonDriver);
    274       return Status;
    275     } else {
    276 
    277       //
    278       // Hook as a child device
    279       //
    280       Status = gBS->OpenProtocol (Controller,
    281                                   &gEfiPciIoProtocolGuid,
    282                                   &ChildPciIo,
    283                                   pThis->DriverBindingHandle,
    284                                   YukonDriver->Controller,
    285                                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
    286       if (EFI_ERROR (Status)) {
    287         DEBUG ((DEBUG_ERROR, "Marvell Yukon: OpenProtocol: child controller error. Status = %r\n", Status));
    288 
    289         gBS->UninstallMultipleProtocolInterfaces (
    290               Controller,
    291               &gEfiSimpleNetworkProtocolGuid,
    292               &YukonDriver->Snp,
    293               &gEfiDevicePathProtocolGuid,
    294               YukonDriver->DevicePath,
    295               NULL
    296               );
    297 
    298         gBS->CloseProtocol (
    299               Controller,
    300               &gEfiPciIoProtocolGuid,
    301               pThis->DriverBindingHandle,
    302               Controller
    303               );
    304 
    305         gBS->FreePool (YukonDriver->DevicePath);
    306         gBS->FreePool (YukonDriver);
    307         return Status;
    308       } else {
    309         DEBUG ((DEBUG_NET, "Marvell Yukon: MarvellYukonDriverSupported: New Controller Handle = %p\n",
    310                YukonDriver->Controller));
    311       }
    312 
    313       Status = MarvellYukonAddControllerData (YukonDriver->Controller, ScData);
    314       if (EFI_ERROR (Status)) {
    315         DEBUG ((DEBUG_ERROR, "Marvell Yukon: Failed to register port %d with controller handle %p\n", Port,
    316                YukonDriver->Controller));
    317       }
    318 
    319     }
    320 
    321     if (!EFI_ERROR (Status)) {
    322       Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
    323                       &MarvellYukonNotifyExitBoot, YukonDriver, &YukonDriver->ExitBootEvent);
    324     }
    325   }
    326 
    327   return Status;
    328 }
    329 
    330 /**
    331   Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
    332   closing the DevicePath and PciIo protocols on Controller.
    333 
    334   @param [in] pThis                   Protocol instance pointer.
    335   @param [in] Controller              Handle of device to stop driver on.
    336   @param [in] NumberOfChildren        How many children need to be stopped.
    337   @param [in] pChildHandleBuffer      Not used.
    338 
    339   @retval EFI_SUCCESS                 This driver is removed Controller.
    340   @retval EFI_DEVICE_ERROR            The device could not be stopped due to a device error.
    341   @retval other                       This driver was not removed from this device.
    342 
    343 **/
    344 EFI_STATUS
    345 EFIAPI
    346 MarvellYukonDriverStop (
    347     IN  EFI_DRIVER_BINDING_PROTOCOL * pThis,
    348     IN  EFI_HANDLE Controller,
    349     IN  UINTN NumberOfChildren,
    350     IN  EFI_HANDLE * ChildHandleBuffer
    351     )
    352 {
    353   EFI_SIMPLE_NETWORK_PROTOCOL  *SimpleNetwork;
    354   EFI_STATUS                   Status;
    355   YUKON_DRIVER                 *YukonDriver;
    356   EFI_TPL                      OldTpl;
    357   UINTN                        ChildController;
    358   struct msk_softc             *ScData;
    359 
    360   if (pThis == NULL) {
    361     DEBUG ((EFI_D_ERROR, "Marvell Yukon: MarvellYukonDriverStop() failed with Status = %r\n", EFI_INVALID_PARAMETER));
    362     return EFI_INVALID_PARAMETER;
    363   }
    364 
    365   if (NumberOfChildren > 0 && ChildHandleBuffer == NULL) {
    366     DEBUG ((EFI_D_ERROR, "Marvell Yukon: MarvellYukonDriverStop() failed with Status = %r\n", EFI_INVALID_PARAMETER));
    367     return EFI_INVALID_PARAMETER;
    368   }
    369 
    370   for (ChildController = 0; ChildController < NumberOfChildren; ChildController ++) {
    371 
    372     Status = gBS->OpenProtocol (
    373           ChildHandleBuffer[ChildController],
    374           &gEfiSimpleNetworkProtocolGuid,
    375           (VOID **) &SimpleNetwork,
    376           pThis->DriverBindingHandle,
    377           Controller,
    378           EFI_OPEN_PROTOCOL_GET_PROTOCOL
    379           );
    380 
    381     if (!EFI_ERROR(Status)) {
    382 
    383       YukonDriver = YUKON_DEV_FROM_THIS_SNP (SimpleNetwork);
    384 
    385       Status = MarvellYukonGetControllerData (YukonDriver->Controller, &ScData);
    386       if (EFI_ERROR (Status)) {
    387         continue;
    388       }
    389 
    390       OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    391 
    392       ASSERT (YukonDriver->Controller == ChildHandleBuffer[ChildController]);
    393       if (YukonDriver->SnpMode.State != EfiSimpleNetworkStopped) {
    394 
    395          //
    396          // Device in use, cannot stop driver instance
    397          //
    398          Status = EFI_DEVICE_ERROR;
    399          DEBUG ((DEBUG_ERROR,
    400                 "Marvell Yukon: MarvellYukonDriverStop: Error: SNP is not stopped. Status %r\n", Status));
    401        } else {
    402 
    403          //
    404          // Unhook the child controller
    405          //
    406          Status = gBS->CloseProtocol (Controller,
    407                              &gEfiPciIoProtocolGuid,
    408                              pThis->DriverBindingHandle,
    409                              YukonDriver->Controller);
    410 
    411          if (EFI_ERROR (Status)) {
    412            DEBUG ((DEBUG_ERROR,
    413                   "Marvell Yukon: MarvellYukonDriverStop:Close Child EfiPciIoProtocol error. Status %r\n", Status));
    414          }
    415 
    416          Status = gBS->UninstallMultipleProtocolInterfaces (
    417               YukonDriver->Controller,
    418               &gEfiSimpleNetworkProtocolGuid,
    419               &YukonDriver->Snp,
    420               &gEfiDevicePathProtocolGuid,
    421               YukonDriver->DevicePath,
    422               NULL
    423               );
    424 
    425          if (EFI_ERROR(Status)){
    426            DEBUG ((DEBUG_ERROR,
    427                   "Marvell Yukon: MarvellYukonDriverStop:UninstallMultipleProtocolInterfaces error. Status %r\n",
    428                   Status));
    429          }
    430 
    431          MarvellYukonDelControllerData (YukonDriver->Controller);
    432 
    433          gBS->CloseEvent (YukonDriver->ExitBootEvent);
    434          gBS->FreePool (YukonDriver->DevicePath);
    435          gBS->FreePool (YukonDriver);
    436        }
    437        gBS->RestoreTPL (OldTpl);
    438     }
    439   }
    440 
    441   Status = gBS->CloseProtocol (
    442         Controller,
    443         &gEfiPciIoProtocolGuid,
    444         pThis->DriverBindingHandle,
    445         Controller
    446         );
    447 
    448   if (EFI_ERROR (Status)) {
    449     DEBUG ((DEBUG_ERROR, "Marvell Yukon: MarvellYukonDriverStop:Close EfiPciIoProtocol error. Status %r\n", Status));
    450   }
    451 
    452   Status = MarvellYukonGetControllerData (Controller, &ScData);
    453   if (EFI_ERROR (Status)) {
    454     return Status;
    455   }
    456 
    457   mskc_detach (ScData);
    458   gBS->FreePool (ScData);
    459   Status = MarvellYukonDelControllerData (Controller);
    460 
    461   return Status;
    462 }
    463 
    464 /**
    465   Process exit boot event.
    466 
    467   @param [in] Event                   Event id.
    468   @param [in] Context                 Driver context.
    469 
    470 **/
    471 VOID
    472 EFIAPI
    473 MarvellYukonNotifyExitBoot (
    474   IN EFI_EVENT Event,
    475   IN VOID *Context
    476   )
    477 {
    478   YUKON_DRIVER    *YukonDriver;
    479   EFI_STATUS      Status;
    480 
    481   if (Context == NULL) {
    482     DEBUG ((DEBUG_ERROR,
    483            "Marvell Yukon: MarvellYukonNotifyExitBoot() failed with Status = %r\n", EFI_INVALID_PARAMETER));
    484   } else {
    485 
    486     YukonDriver = Context;
    487 
    488     if (YukonDriver->SnpMode.State != EfiSimpleNetworkStopped) {
    489       Status  = YukonDriver->Snp.Shutdown(&YukonDriver->Snp);
    490       if (!EFI_ERROR (Status)) {
    491         YukonDriver->Snp.Stop(&YukonDriver->Snp);
    492       }
    493     }
    494   }
    495 }
    496 
    497 /**
    498   Get driver's data structure associated with controller
    499 
    500   @param [in] Controller           Controller Id.
    501   @param [out] Data                Driver's data.
    502 
    503 **/
    504 EFI_STATUS
    505 EFIAPI
    506 MarvellYukonGetControllerData (
    507   IN EFI_HANDLE Controller,
    508   OUT struct msk_softc **Data
    509   )
    510 {
    511   MSK_LINKED_DRV_BUF *DrvNode;
    512   EFI_STATUS         Status;
    513 
    514   Status = MarvellYukonFindControllerNode (Controller, &DrvNode);
    515   if (!EFI_ERROR (Status)) {
    516     *Data = DrvNode->Data;
    517   }
    518   return Status;
    519 }
    520 
    521 /**
    522   Add driver's data structure associated with controller
    523 
    524   @param [in] Controller           Controller Id.
    525   @param [in] Data                 Driver's data.
    526 
    527 **/
    528 EFI_STATUS
    529 EFIAPI
    530 MarvellYukonAddControllerData (
    531   IN EFI_HANDLE Controller,
    532   IN struct msk_softc *Data
    533   )
    534 {
    535   MSK_LINKED_DRV_BUF *DrvNode;
    536   EFI_STATUS         Status;
    537 
    538   Status = MarvellYukonFindControllerNode (Controller, &DrvNode);
    539   if (EFI_ERROR (Status)) {
    540     Status = gBS->AllocatePool (EfiBootServicesData,
    541                                 sizeof (MSK_LINKED_DRV_BUF),
    542                                 (VOID**) &DrvNode);
    543     if (!EFI_ERROR (Status)) {
    544       DrvNode->Signature = MSK_DRV_SIGNATURE;
    545       DrvNode->Controller = Controller;
    546       DrvNode->Data = Data;
    547       InsertTailList (&MarvellYukonDrvDataHead, &DrvNode->Link);
    548     }
    549   } else {
    550     Status = EFI_ALREADY_STARTED;
    551   }
    552 
    553   return Status;
    554 }
    555 
    556 /**
    557   Delete driver's data structure associated with controller
    558 
    559   @param [in] Controller           Controller Id.
    560 
    561 **/
    562 EFI_STATUS
    563 EFIAPI
    564 MarvellYukonDelControllerData (
    565   IN EFI_HANDLE Controller
    566   )
    567 {
    568   MSK_LINKED_DRV_BUF *DrvNode;
    569   EFI_STATUS         Status;
    570 
    571   Status = MarvellYukonFindControllerNode (Controller, &DrvNode);
    572   if (!EFI_ERROR (Status)) {
    573     RemoveEntryList (&DrvNode->Link);
    574     gBS->FreePool (DrvNode);
    575   }
    576 
    577   return Status;
    578 }
    579 
    580 /**
    581   Find node associated with controller
    582 
    583   @param [in] Controller           Controller Id.
    584   @param [out] DrvLinkedBuff       Controller's node.
    585 
    586 **/
    587 EFI_STATUS
    588 EFIAPI
    589 MarvellYukonFindControllerNode (
    590   IN EFI_HANDLE Controller,
    591   OUT MSK_LINKED_DRV_BUF **DrvLinkedBuff
    592   )
    593 {
    594   MSK_LINKED_DRV_BUF *DrvBuffNode;
    595   EFI_STATUS         Status;
    596   LIST_ENTRY         *Node;
    597 
    598   Status = EFI_NOT_FOUND;
    599 
    600   Node = GetFirstNode (&MarvellYukonDrvDataHead);
    601   while (!IsNull (&MarvellYukonDrvDataHead, Node)) {
    602     DrvBuffNode = MSK_DRV_INFO_FROM_THIS (Node);
    603     if (DrvBuffNode->Controller == Controller) {
    604       *DrvLinkedBuff = DrvBuffNode;
    605       Status = EFI_SUCCESS;
    606       break;
    607     }
    608     Node = GetNextNode (&MarvellYukonDrvDataHead, Node);
    609   }
    610 
    611   return Status;
    612 }
    613 
    614 //
    615 // Simple Network Protocol Driver Global Variables
    616 //
    617 EFI_DRIVER_BINDING_PROTOCOL gMarvellYukonDriverBinding = {
    618   MarvellYukonDriverSupported,
    619   MarvellYukonDriverStart,
    620   MarvellYukonDriverStop,
    621   0xa,
    622   NULL,
    623   NULL
    624 };
    625 
    626 /**
    627   The Marvell Yukon driver entry point.
    628 
    629    <at> param ImageHandle             The driver image handle.
    630    <at> param SystemTable             The system table.
    631 
    632    <at> retval EFI_SUCCESS            Initialization routine has found and initialized
    633                                       hardware successfully.
    634    <at> retval Other                  Return value from HandleProtocol for
    635                                       DeviceIoProtocol or LoadedImageProtocol
    636 
    637 **/
    638 EFI_STATUS
    639 EFIAPI
    640 InitializeMarvellYukonDriver (
    641     IN EFI_HANDLE       ImageHandle,
    642     IN EFI_SYSTEM_TABLE *SystemTable
    643     )
    644 {
    645   EFI_STATUS                           Status;
    646 
    647   DEBUG ((EFI_D_NET, "Marvell Yukon: InitializeMarvellYukonDriver()\n"));
    648 
    649   if (SystemTable == NULL) {
    650     DEBUG ((DEBUG_ERROR,
    651            "Marvell Yukon: InitializeMarvellYukonDriver() failed with Status = %r\n", EFI_INVALID_PARAMETER));
    652     return EFI_INVALID_PARAMETER;
    653   }
    654 
    655   Status = EfiLibInstallDriverBindingComponentName2 (
    656         ImageHandle,
    657         SystemTable,
    658         &gMarvellYukonDriverBinding,
    659         NULL,
    660         &gSimpleNetworkComponentName,
    661         &gSimpleNetworkComponentName2
    662         );
    663 
    664   if (EFI_ERROR (Status)) {
    665     DEBUG ((EFI_D_ERROR, "Marvell Yukon: InitializeMarvellYukonDriver(): Driver binding failed\n"));
    666     return Status;
    667   }
    668 
    669   InitializeListHead (&MarvellYukonDrvDataHead);
    670 
    671   return Status;
    672 }
    673