Home | History | Annotate | Download | only in Ipf
      1 /*++
      2 
      3 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 
     13 Module Name:
     14 
     15   EsalServiceLib.c
     16 
     17 Abstract:
     18 
     19 --*/
     20 
     21 #include <Ipf/IpfDefines.h>
     22 
     23 #include "EdkIIGlueDxe.h"
     24 
     25 EXTENDED_SAL_BOOT_SERVICE_PROTOCOL  *mEsalBootService = NULL;
     26 EFI_PLABEL                          mPlabel;
     27 
     28 STATIC
     29 EFI_STATUS
     30 EFIAPI
     31 DxeSalLibInitialize (
     32   VOID
     33   )
     34 {
     35   EFI_PLABEL  *Plabel;
     36   EFI_STATUS  Status;
     37 
     38   if (mEsalBootService != NULL) {
     39     return EFI_SUCCESS;
     40   }
     41 
     42   //
     43   // The protocol contains a function pointer, which is an indirect procedure call.
     44   // An indirect procedure call goes through a plabel, and pointer to a function is
     45   // a pointer to a plabel. To implement indirect procedure calls that can work in
     46   // both physical and virtual mode, two plabels are required (one physical and one
     47   // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it
     48   // away. We cache it in a module global, so we can register the vitrual version.
     49   //
     50   Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, (VOID **) &mEsalBootService);
     51   if (EFI_ERROR (Status)) {
     52     mEsalBootService = NULL;
     53     return EFI_SUCCESS;
     54   }
     55 
     56   Plabel              = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;
     57 
     58   mPlabel.EntryPoint  = Plabel->EntryPoint;
     59   mPlabel.GP          = Plabel->GP;
     60   SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
     61 
     62   return EFI_SUCCESS;
     63 }
     64 
     65 EFI_STATUS
     66 EFIAPI
     67 RegisterEsalFunction (
     68   IN  UINT64                                    FunctionId,
     69   IN  EFI_GUID                                  *ClassGuid,
     70   IN  SAL_INTERNAL_EXTENDED_SAL_PROC            Function,
     71   IN  VOID                                      *ModuleGlobal
     72   )
     73 /*++
     74 
     75 Routine Description:
     76 
     77   Register ESAL Class Function and it's asociated global.
     78   This function is boot service only!
     79 
     80 Arguments:
     81   FunctionId    - ID of function to register
     82   ClassGuid     - GUID of function class
     83   Function      - Function to register under ClassGuid/FunctionId pair
     84   ModuleGlobal  - Module global for Function.
     85 
     86 Returns:
     87   EFI_SUCCESS - If ClassGuid/FunctionId Function was registered.
     88 
     89 --*/
     90 {
     91   DxeSalLibInitialize ();
     92   return mEsalBootService->AddExtendedSalProc (
     93                             mEsalBootService,
     94                             ClassGuid,
     95                             FunctionId,
     96                             Function,
     97                             ModuleGlobal
     98                             );
     99 }
    100 
    101 EFI_STATUS
    102 EFIAPI
    103 RegisterEsalClass (
    104   IN  EFI_GUID                                  *ClassGuid,
    105   IN  VOID                                      *ModuleGlobal,
    106   ...
    107   )
    108 /*++
    109 
    110 Routine Description:
    111 
    112   Register ESAL Class and it's asociated global.
    113   This function is boot service only!
    114 
    115 Arguments:
    116   ClassGuid     - GUID of function class
    117   ModuleGlobal  - Module global for Function.
    118   ...           - SAL_INTERNAL_EXTENDED_SAL_PROC and FunctionId pairs. NULL
    119                   indicates the end of the list.
    120 
    121 Returns:
    122   EFI_SUCCESS - All members of ClassGuid registered
    123 
    124 --*/
    125 {
    126   VA_LIST                         Args;
    127   EFI_STATUS                      Status;
    128   SAL_INTERNAL_EXTENDED_SAL_PROC  Function;
    129   UINT64                          FunctionId;
    130   EFI_HANDLE                      NewHandle;
    131 
    132   VA_START (Args, ModuleGlobal);
    133 
    134   Status = EFI_SUCCESS;
    135   while (!EFI_ERROR (Status)) {
    136     Function = (SAL_INTERNAL_EXTENDED_SAL_PROC) VA_ARG (Args, SAL_INTERNAL_EXTENDED_SAL_PROC);
    137     if (Function == NULL) {
    138       break;
    139     }
    140 
    141     FunctionId  = VA_ARG (Args, UINT64);
    142 
    143     Status      = RegisterEsalFunction (FunctionId, ClassGuid, Function, ModuleGlobal);
    144   }
    145 
    146   VA_END (Args);
    147 
    148   if (EFI_ERROR (Status)) {
    149     return Status;
    150   }
    151 
    152   NewHandle = NULL;
    153   return gBS->InstallProtocolInterface (
    154                 &NewHandle,
    155                 ClassGuid,
    156                 EFI_NATIVE_INTERFACE,
    157                 NULL
    158                 );
    159 }
    160 
    161 SAL_RETURN_REGS
    162 EFIAPI
    163 EfiCallEsalService (
    164   IN  EFI_GUID                                      *ClassGuid,
    165   IN  UINT64                                        FunctionId,
    166   IN  UINT64                                        Arg2,
    167   IN  UINT64                                        Arg3,
    168   IN  UINT64                                        Arg4,
    169   IN  UINT64                                        Arg5,
    170   IN  UINT64                                        Arg6,
    171   IN  UINT64                                        Arg7,
    172   IN  UINT64                                        Arg8
    173   )
    174 /*++
    175 
    176 Routine Description:
    177 
    178   Call module that is not linked direclty to this module. This code is IP
    179   relative and hides the binding issues of virtual or physical calling. The
    180   function that gets dispatched has extra arguments that include the registered
    181   module global and a boolean flag to indicate if the system is in virutal mode.
    182 
    183 Arguments:
    184   ClassGuid   - GUID of function
    185   FunctionId  - Function in ClassGuid to call
    186   Arg2        - Argument 2 ClassGuid/FunctionId defined
    187   Arg3        - Argument 3 ClassGuid/FunctionId defined
    188   Arg4        - Argument 4 ClassGuid/FunctionId defined
    189   Arg5        - Argument 5 ClassGuid/FunctionId defined
    190   Arg6        - Argument 6 ClassGuid/FunctionId defined
    191   Arg7        - Argument 7 ClassGuid/FunctionId defined
    192   Arg8        - Argument 8 ClassGuid/FunctionId defined
    193 
    194 Returns:
    195   Status of ClassGuid/FuncitonId
    196 
    197 --*/
    198 {
    199   SAL_RETURN_REGS       ReturnReg;
    200   SAL_EXTENDED_SAL_PROC EsalProc;
    201 
    202   ReturnReg = GetEsalEntryPoint ();
    203   if (ReturnReg.Status != EFI_SAL_SUCCESS) {
    204     return ReturnReg;
    205   }
    206 
    207   //
    208   // Look at the physical mode ESAL entry point to determine of the ESAL entry point has been initialized
    209   //
    210   if (*(UINT64 *)ReturnReg.r9 == 0 && *(UINT64 *)(ReturnReg.r9 + 8) == 0) {
    211     //
    212     // Both the function ponter and the GP value are zero, so attempt to initialize the ESAL Entry Point
    213     //
    214     DxeSalLibInitialize ();
    215     ReturnReg = GetEsalEntryPoint ();
    216     if (ReturnReg.Status != EFI_SAL_SUCCESS) {
    217       return ReturnReg;
    218     }
    219     if (*(UINT64 *)ReturnReg.r9 == 0 && *(UINT64 *)(ReturnReg.r9 + 8) == 0) {
    220       //
    221       // The ESAL Entry Point could not be initialized
    222       //
    223       ReturnReg.Status = EFI_SAL_ERROR;
    224       return ReturnReg;
    225     }
    226   }
    227 
    228   if (ReturnReg.r11 & PSR_IT_MASK) {
    229     //
    230     // Virtual mode plabel to entry point
    231     //
    232     EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r10;
    233   } else {
    234     //
    235     // Physical mode plabel to entry point
    236     //
    237     EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r9;
    238   }
    239 
    240   return EsalProc (
    241           ClassGuid,
    242           FunctionId,
    243           Arg2,
    244           Arg3,
    245           Arg4,
    246           Arg5,
    247           Arg6,
    248           Arg7,
    249           Arg8
    250           );
    251 }
    252