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 Module Name:
     13 
     14   RuntimeLib.c
     15 
     16 Abstract:
     17 
     18   Light weight lib to support Tiano Sal drivers.
     19 
     20 --*/
     21 
     22 #include "Tiano.h"
     23 #include "EfiRuntimeLib.h"
     24 #include EFI_PROTOCOL_DEFINITION (ExtendedSalBootService)
     25 #include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)
     26 #include "IpfDefines.h"
     27 #include "SalApi.h"
     28 
     29 //
     30 // Worker functions in EsalLib.s
     31 //
     32 SAL_RETURN_REGS
     33 GetEsalEntryPoint (
     34   VOID
     35   );
     36 
     37 SAL_RETURN_REGS
     38 SetEsalPhysicalEntryPoint (
     39   IN  UINT64  EntryPoint,
     40   IN  UINT64  Gp
     41   );
     42 
     43 SAL_RETURN_REGS
     44 SetEsalVirtualEntryPoint (
     45   IN  UINT64  EntryPoint,
     46   IN  UINT64  Gp
     47   );
     48 
     49 VOID
     50 SalFlushCache (
     51   IN EFI_PHYSICAL_ADDRESS  Start,
     52   IN UINT64                Length
     53   );
     54 
     55 //
     56 // Module Globals. It's not valid to use these after the
     57 // EfiRuntimeLibVirtualNotifyEvent has fired.
     58 //
     59 static EFI_EVENT                          mEfiVirtualNotifyEvent;
     60 static EFI_RUNTIME_SERVICES               *mRT;
     61 static EFI_PLABEL                         mPlabel;
     62 static EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService;
     63 static BOOLEAN                            mRuntimeLibInitialized = FALSE;
     64 
     65 VOID
     66 EFIAPI
     67 EfiRuntimeLibVirtualNotifyEvent (
     68   IN EFI_EVENT        Event,
     69   IN VOID             *Context
     70   )
     71 /*++
     72 
     73 Routine Description:
     74 
     75   Fixup internal data so that EFI and SAL can be call in virtual mode.
     76   Call the passed in Child Notify event and convert any pointers in
     77   lib to virtual mode.
     78 
     79 Arguments:
     80 
     81   Event   - The Event that is being processed
     82 
     83   Context - Event Context
     84 
     85 Returns:
     86 
     87   None
     88 
     89 --*/
     90 {
     91   EFI_EVENT_NOTIFY  ChildNotify;
     92 
     93   if (Context != NULL) {
     94     //
     95     // Call child event
     96     //
     97     ChildNotify = (EFI_EVENT_NOTIFY) (UINTN) Context;
     98     ChildNotify (Event, NULL);
     99   }
    100 
    101   mRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mPlabel.EntryPoint);
    102   mRT->ConvertPointer (EFI_INTERNAL_POINTER | EFI_IPF_GP_POINTER, (VOID **) &mPlabel.GP);
    103 
    104   SetEsalVirtualEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
    105 
    106   //
    107   // Clear out BootService globals
    108   //
    109   gBS = NULL;
    110   gST = NULL;
    111   mRT = NULL;
    112 
    113   //
    114   // Pointers don't work you must use a direct lib call
    115   //
    116 }
    117 
    118 EFI_STATUS
    119 EfiInitializeRuntimeDriverLib (
    120   IN EFI_HANDLE           ImageHandle,
    121   IN EFI_SYSTEM_TABLE     *SystemTable,
    122   IN EFI_EVENT_NOTIFY     GoVirtualChildEvent
    123   )
    124 /*++
    125 
    126 Routine Description:
    127 
    128   Intialize runtime Driver Lib if it has not yet been initialized.
    129 
    130 Arguments:
    131 
    132   ImageHandle     - The firmware allocated handle for the EFI image.
    133 
    134   SystemTable     - A pointer to the EFI System Table.
    135 
    136   GoVirtualChildEvent - Caller can register a virtual notification event.
    137 
    138 Returns:
    139 
    140   EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started.
    141 
    142 --*/
    143 {
    144   EFI_STATUS  Status;
    145   EFI_PLABEL  *Plabel;
    146 
    147   if (mRuntimeLibInitialized) {
    148     return EFI_ALREADY_STARTED;
    149   }
    150 
    151   mRuntimeLibInitialized  = TRUE;
    152 
    153   gST                     = SystemTable;
    154   gBS                     = SystemTable->BootServices;
    155   mRT                     = SystemTable->RuntimeServices;
    156   Status                  = EfiLibGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
    157   ASSERT_EFI_ERROR (Status);
    158 
    159   //
    160   // The protocol contains a function pointer, which is an indirect procedure call.
    161   // An indirect procedure call goes through a plabel, and pointer to a function is
    162   // a pointer to a plabel. To implement indirect procedure calls that can work in
    163   // both physical and virtual mode, two plabels are required (one physical and one
    164   // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it
    165   // away. We cache it in a module global, so we can register the vitrual version.
    166   //
    167   Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, (VOID **) &mEsalBootService);
    168   ASSERT_EFI_ERROR (Status);
    169 
    170   Plabel              = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc;
    171 
    172   mPlabel.EntryPoint  = Plabel->EntryPoint;
    173   mPlabel.GP          = Plabel->GP;
    174 
    175   SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP);
    176 
    177   //
    178   // Create a Virtual address change notification event. Pass in the callers
    179   // GoVirtualChildEvent so it's get passed to the event as contex.
    180   //
    181   Status = gBS->CreateEvent (
    182                   EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
    183                   EFI_TPL_NOTIFY,
    184                   EfiRuntimeLibVirtualNotifyEvent,
    185                   (VOID *) GoVirtualChildEvent,
    186                   &mEfiVirtualNotifyEvent
    187                   );
    188   ASSERT_EFI_ERROR (Status);
    189 
    190   return EFI_SUCCESS;
    191 }
    192 
    193 EFI_STATUS
    194 EfiShutdownRuntimeDriverLib (
    195   VOID
    196   )
    197 /*++
    198 
    199 Routine Description:
    200 
    201   This routine will free some resources which have been allocated in
    202   EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error,
    203   it must call this routine to free the allocated resource before the exiting.
    204 
    205 Arguments:
    206 
    207   None
    208 
    209 Returns:
    210 
    211   EFI_SUCCESS     - Shotdown the Runtime Driver Lib successfully
    212   EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all
    213 
    214 --*/
    215 {
    216   EFI_STATUS  Status;
    217 
    218   if (!mRuntimeLibInitialized) {
    219     //
    220     // You must call EfiInitializeRuntimeDriverLib() first
    221     //
    222     return EFI_UNSUPPORTED;
    223   }
    224 
    225   mRuntimeLibInitialized = FALSE;
    226 
    227   //
    228   // Close SetVirtualAddressMap () notify function
    229   //
    230   Status = gBS->CloseEvent (mEfiVirtualNotifyEvent);
    231   ASSERT_EFI_ERROR (Status);
    232 
    233   return EFI_SUCCESS;
    234 }
    235 
    236 EFI_STATUS
    237 RegisterEsalFunction (
    238   IN  UINT64                                    FunctionId,
    239   IN  EFI_GUID                                  *ClassGuid,
    240   IN  SAL_INTERNAL_EXTENDED_SAL_PROC            Function,
    241   IN  VOID                                      *ModuleGlobal
    242   )
    243 /*++
    244 
    245 Routine Description:
    246 
    247   Register ESAL Class Function and it's asociated global.
    248   This function is boot service only!
    249 
    250 Arguments:
    251   FunctionId    - ID of function to register
    252   ClassGuid     - GUID of function class
    253   Function      - Function to register under ClassGuid/FunctionId pair
    254   ModuleGlobal  - Module global for Function.
    255 
    256 Returns:
    257   EFI_SUCCESS - If ClassGuid/FunctionId Function was registered.
    258 
    259 --*/
    260 {
    261   return mEsalBootService->AddExtendedSalProc (
    262                             mEsalBootService,
    263                             ClassGuid,
    264                             FunctionId,
    265                             Function,
    266                             ModuleGlobal
    267                             );
    268 }
    269 
    270 EFI_STATUS
    271 RegisterEsalClass (
    272   IN  EFI_GUID                                  *ClassGuid,
    273   IN  VOID                                      *ModuleGlobal,
    274   ...
    275   )
    276 /*++
    277 
    278 Routine Description:
    279 
    280   Register ESAL Class and it's asociated global.
    281   This function is boot service only!
    282 
    283 Arguments:
    284   ClassGuid     - GUID of function class
    285   ModuleGlobal  - Module global for Function.
    286   ...           - SAL_INTERNAL_EXTENDED_SAL_PROC and FunctionId pairs. NULL
    287                   indicates the end of the list.
    288 
    289 Returns:
    290   EFI_SUCCESS - All members of ClassGuid registered
    291 
    292 --*/
    293 {
    294   VA_LIST                         Args;
    295   EFI_STATUS                      Status;
    296   SAL_INTERNAL_EXTENDED_SAL_PROC  Function;
    297   UINT64                          FunctionId;
    298   EFI_HANDLE                      NewHandle;
    299 
    300   VA_START (Args, ModuleGlobal);
    301 
    302   Status = EFI_SUCCESS;
    303   while (!EFI_ERROR (Status)) {
    304     Function = (SAL_INTERNAL_EXTENDED_SAL_PROC) VA_ARG (Args, SAL_INTERNAL_EXTENDED_SAL_PROC);
    305     if (Function == NULL) {
    306       break;
    307     }
    308 
    309     FunctionId  = VA_ARG (Args, UINT64);
    310 
    311     Status      = RegisterEsalFunction (FunctionId, ClassGuid, Function, ModuleGlobal);
    312   }
    313 
    314   VA_END (Args);
    315 
    316   if (EFI_ERROR (Status)) {
    317     return Status;
    318   }
    319 
    320   NewHandle = NULL;
    321   return gBS->InstallProtocolInterface (
    322                 &NewHandle,
    323                 ClassGuid,
    324                 EFI_NATIVE_INTERFACE,
    325                 NULL
    326                 );
    327 }
    328 
    329 SAL_RETURN_REGS
    330 EfiCallEsalService (
    331   IN  EFI_GUID                                      *ClassGuid,
    332   IN  UINT64                                        FunctionId,
    333   IN  UINT64                                        Arg2,
    334   IN  UINT64                                        Arg3,
    335   IN  UINT64                                        Arg4,
    336   IN  UINT64                                        Arg5,
    337   IN  UINT64                                        Arg6,
    338   IN  UINT64                                        Arg7,
    339   IN  UINT64                                        Arg8
    340   )
    341 /*++
    342 
    343 Routine Description:
    344 
    345   Call module that is not linked direclty to this module. This code is IP
    346   relative and hides the binding issues of virtual or physical calling. The
    347   function that gets dispatched has extra arguments that include the registered
    348   module global and a boolean flag to indicate if the system is in virutal mode.
    349 
    350 Arguments:
    351   ClassGuid   - GUID of function
    352   FunctionId  - Function in ClassGuid to call
    353   Arg2        - Argument 2 ClassGuid/FunctionId defined
    354   Arg3        - Argument 3 ClassGuid/FunctionId defined
    355   Arg4        - Argument 4 ClassGuid/FunctionId defined
    356   Arg5        - Argument 5 ClassGuid/FunctionId defined
    357   Arg6        - Argument 6 ClassGuid/FunctionId defined
    358   Arg7        - Argument 7 ClassGuid/FunctionId defined
    359   Arg8        - Argument 8 ClassGuid/FunctionId defined
    360 
    361 Returns:
    362   Status of ClassGuid/FuncitonId
    363 
    364 --*/
    365 {
    366   SAL_RETURN_REGS       ReturnReg;
    367   SAL_EXTENDED_SAL_PROC EsalProc;
    368 
    369   ReturnReg = GetEsalEntryPoint ();
    370   if (ReturnReg.Status != EFI_SAL_SUCCESS) {
    371     return ReturnReg;
    372   }
    373 
    374   if (ReturnReg.r11 & PSR_IT_MASK) {
    375     //
    376     // Virtual mode plabel to entry point
    377     //
    378     EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r10;
    379   } else {
    380     //
    381     // Physical mode plabel to entry point
    382     //
    383     EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r9;
    384   }
    385 
    386   return EsalProc (
    387           ClassGuid,
    388           FunctionId,
    389           Arg2,
    390           Arg3,
    391           Arg4,
    392           Arg5,
    393           Arg6,
    394           Arg7,
    395           Arg8
    396           );
    397 }
    398 
    399 EFI_STATUS
    400 EfiConvertPointer (
    401   IN UINTN                     DebugDisposition,
    402   IN OUT VOID                  *Address
    403   )
    404 /*++
    405 
    406 Routine Description:
    407 
    408   Determines the new virtual address that is to be used on subsequent memory accesses.
    409 
    410 Arguments:
    411 
    412   DebugDisposition  - Supplies type information for the pointer being converted.
    413   Address           - A pointer to a pointer that is to be fixed to be the value needed
    414                       for the new virtual address mappings being applied.
    415 
    416 Returns:
    417 
    418   Status code
    419 
    420 --*/
    421 {
    422   return mRT->ConvertPointer (DebugDisposition, Address);
    423 }
    424 
    425 BOOLEAN
    426 EfiGoneVirtual (
    427   VOID
    428   )
    429 /*++
    430 
    431 Routine Description:
    432   Return TRUE if SetVirtualAddressMap () has been called
    433 
    434 Arguments:
    435   NONE
    436 
    437 Returns:
    438   TRUE - If SetVirtualAddressMap () has been called
    439 
    440 --*/
    441 {
    442   EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
    443   SAL_RETURN_REGS ReturnReg;
    444 
    445   ReturnReg = EfiCallEsalService (&Guid, IsVirtual, 0, 0, 0, 0, 0, 0, 0);
    446 
    447   return (BOOLEAN) (ReturnReg.r9 == 1);
    448 }
    449 
    450 BOOLEAN
    451 EfiAtRuntime (
    452   VOID
    453   )
    454 /*++
    455 
    456 Routine Description:
    457   Return TRUE if ExitBootService () has been called
    458 
    459 Arguments:
    460   NONE
    461 
    462 Returns:
    463   TRUE - If ExitBootService () has been called
    464 
    465 --*/
    466 {
    467   EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID;
    468   SAL_RETURN_REGS ReturnReg;
    469 
    470   ReturnReg = EfiCallEsalService (&Guid, IsEfiRuntime, 0, 0, 0, 0, 0, 0, 0);
    471 
    472   return (BOOLEAN) (ReturnReg.r9 == 1);
    473 }
    474 
    475 EFI_STATUS
    476 EfiReportStatusCode (
    477   IN EFI_STATUS_CODE_TYPE     CodeType,
    478   IN EFI_STATUS_CODE_VALUE    Value,
    479   IN UINT32                   Instance,
    480   IN EFI_GUID                 * CallerId,
    481   IN EFI_STATUS_CODE_DATA     * Data OPTIONAL
    482   )
    483 /*++
    484 
    485 Routine Description:
    486 
    487   Status Code reporter
    488 
    489 Arguments:
    490 
    491   CodeType    - Type of Status Code.
    492 
    493   Value       - Value to output for Status Code.
    494 
    495   Instance    - Instance Number of this status code.
    496 
    497   CallerId    - ID of the caller of this status code.
    498 
    499   Data        - Optional data associated with this status code.
    500 
    501 Returns:
    502 
    503   Status code
    504 
    505 --*/
    506 {
    507   EFI_GUID Guid = EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_PROTOCOL_GUID;
    508   SAL_RETURN_REGS ReturnReg;
    509 
    510 
    511   ReturnReg = EfiCallEsalService (
    512                 &Guid,
    513                 StatusCode,
    514                 (UINT64) CodeType,
    515                 (UINT64) Value,
    516                 (UINT64) Instance,
    517                 (UINT64) CallerId,
    518                 (UINT64) Data,
    519                 0,
    520                 0
    521                 );
    522 
    523   return (EFI_STATUS) ReturnReg.Status;
    524 }
    525 //
    526 //  Sal Reset Driver Class
    527 //
    528 VOID
    529 EfiResetSystem (
    530   IN EFI_RESET_TYPE     ResetType,
    531   IN EFI_STATUS         ResetStatus,
    532   IN UINTN              DataSize,
    533   IN CHAR16             *ResetData
    534   )
    535 /*++
    536 
    537 Routine Description:
    538 
    539   Resets the entire platform.
    540 
    541 Arguments:
    542 
    543   ResetType   - The type of reset to perform.
    544   ResetStatus - The status code for the reset.
    545   DataSize    - The size, in bytes, of ResetData.
    546   ResetData   - A data buffer that includes a Null-terminated Unicode string, optionally
    547                 followed by additional binary data.
    548 
    549 Returns:
    550 
    551   None
    552 
    553 --*/
    554 {
    555   EFI_GUID Guid = EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID;
    556 
    557   EfiCallEsalService (
    558     &Guid,
    559     ResetSystem,
    560     (UINT64) ResetType,
    561     (UINT64) ResetStatus,
    562     (UINT64) DataSize,
    563     (UINT64) ResetData,
    564     0,
    565     0,
    566     0
    567     );
    568 }
    569 //
    570 //  Sal MTC Driver Class
    571 //
    572 EFI_STATUS
    573 EfiGetNextHighMonotonicCount (
    574   OUT UINT32      *HighCount
    575   )
    576 /*++
    577 
    578 Routine Description:
    579 
    580   Returns the next high 32 bits of the platform's monotonic counter.
    581 
    582 Arguments:
    583 
    584   HighCount - Pointer to returned value.
    585 
    586 Returns:
    587 
    588   Status code
    589 
    590 --*/
    591 {
    592   SAL_RETURN_REGS ReturnReg;
    593 
    594   EFI_GUID Guid = EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID;
    595 
    596   ReturnReg = EfiCallEsalService (&Guid, GetNextHighMonotonicCount, (UINT64) HighCount, 0, 0, 0, 0, 0, 0);
    597   return (EFI_STATUS) ReturnReg.Status;
    598 }
    599 //
    600 // Sal Variable Driver Class
    601 //
    602 EFI_STATUS
    603 EfiGetVariable (
    604   IN CHAR16                       *VariableName,
    605   IN EFI_GUID                     * VendorGuid,
    606   OUT UINT32                      *Attributes OPTIONAL,
    607   IN OUT UINTN                    *DataSize,
    608   OUT VOID                        *Data
    609   )
    610 /*++
    611 
    612 Routine Description:
    613 
    614   Returns the value of a variable.
    615 
    616 Arguments:
    617 
    618   VariableName  - A Null-terminated Unicode string that is the name of the
    619                   vendor's variable.
    620   VendorGuid    - A unique identifier for the vendor.
    621   Attributes    - If not NULL, a pointer to the memory location to return the
    622                   attributes bitmask for the variable.
    623   DataSize      - On input, the size in bytes of the return Data buffer.
    624                   On output the size of data returned in Data.
    625   Data          - The buffer to return the contents of the variable.
    626 
    627 Returns:
    628 
    629   Status code
    630 
    631 --*/
    632 {
    633   SAL_RETURN_REGS ReturnReg;
    634   EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID;
    635 
    636   ReturnReg = EfiCallEsalService (
    637                 &Guid,
    638                 EsalGetVariable,
    639                 (UINT64) VariableName,
    640                 (UINT64) VendorGuid,
    641                 (UINT64) Attributes,
    642                 (UINT64) DataSize,
    643                 (UINT64) Data,
    644                 0,
    645                 0
    646                 );
    647   return (EFI_STATUS) ReturnReg.Status;
    648 }
    649 
    650 EFI_STATUS
    651 EfiGetNextVariableName (
    652   IN OUT UINTN                    *VariableNameSize,
    653   IN OUT CHAR16                   *VariableName,
    654   IN OUT EFI_GUID                 *VendorGuid
    655   )
    656 /*++
    657 
    658 Routine Description:
    659 
    660   Enumerates the current variable names.
    661 
    662 Arguments:
    663 
    664   VariableNameSize  - The size of the VariableName buffer.
    665   VariableName      - On input, supplies the last VariableName that was returned
    666                       by GetNextVariableName().
    667                       On output, returns the Nullterminated Unicode string of the
    668                       current variable.
    669   VendorGuid        - On input, supplies the last VendorGuid that was returned by
    670                       GetNextVariableName().
    671                       On output, returns the VendorGuid of the current variable.
    672 
    673 Returns:
    674 
    675   Status code
    676 
    677 --*/
    678 {
    679   SAL_RETURN_REGS ReturnReg;
    680   EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID;
    681 
    682   ReturnReg = EfiCallEsalService (
    683                 &Guid,
    684                 EsalGetNextVariableName,
    685                 (UINT64) VariableNameSize,
    686                 (UINT64) VariableName,
    687                 (UINT64) VendorGuid,
    688                 0,
    689                 0,
    690                 0,
    691                 0
    692                 );
    693   return (EFI_STATUS) ReturnReg.Status;
    694 }
    695 
    696 EFI_STATUS
    697 EfiSetVariable (
    698   IN CHAR16                       *VariableName,
    699   IN EFI_GUID                     *VendorGuid,
    700   IN UINT32                       Attributes,
    701   IN UINTN                        DataSize,
    702   IN VOID                         *Data
    703   )
    704 /*++
    705 
    706 Routine Description:
    707 
    708   Sets the value of a variable.
    709 
    710 Arguments:
    711 
    712   VariableName  - A Null-terminated Unicode string that is the name of the
    713                   vendor's variable.
    714   VendorGuid    - A unique identifier for the vendor.
    715   Attributes    - Attributes bitmask to set for the variable.
    716   DataSize      - The size in bytes of the Data buffer.
    717   Data          - The contents for the variable.
    718 
    719 Returns:
    720 
    721   Status code
    722 
    723 --*/
    724 {
    725   SAL_RETURN_REGS ReturnReg;
    726   EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID;
    727 
    728   ReturnReg = EfiCallEsalService (
    729                 &Guid,
    730                 EsalSetVariable,
    731                 (UINT64) VariableName,
    732                 (UINT64) VendorGuid,
    733                 (UINT64) Attributes,
    734                 (UINT64) DataSize,
    735                 (UINT64) Data,
    736                 0,
    737                 0
    738                 );
    739   return (EFI_STATUS) ReturnReg.Status;
    740 }
    741 
    742 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
    743 
    744 EFI_STATUS
    745 EfiQueryVariableInfo (
    746   IN UINT32           Attributes,
    747   OUT UINT64          *MaximumVariableStorageSize,
    748   OUT UINT64          *RemainingVariableStorageSize,
    749   OUT UINT64          *MaximumVariableSize
    750   )
    751 /*++
    752 
    753 Routine Description:
    754 
    755   This code returns information about the EFI variables.
    756 
    757 Arguments:
    758 
    759   Attributes                      Attributes bitmask to specify the type of variables
    760                                   on which to return information.
    761   MaximumVariableStorageSize      Pointer to the maximum size of the storage space available
    762                                   for the EFI variables associated with the attributes specified.
    763   RemainingVariableStorageSize    Pointer to the remaining size of the storage space available
    764                                   for the EFI variables associated with the attributes specified.
    765   MaximumVariableSize             Pointer to the maximum size of the individual EFI variables
    766                                   associated with the attributes specified.
    767 
    768 Returns:
    769 
    770   Status code
    771 
    772 --*/
    773 {
    774   SAL_RETURN_REGS ReturnReg;
    775   EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID;
    776 
    777   ReturnReg = EfiCallEsalService (
    778                 &Guid,
    779                 EsalQueryVariableInfo,
    780                 (UINT64) Attributes,
    781                 (UINT64) MaximumVariableStorageSize,
    782                 (UINT64) RemainingVariableStorageSize,
    783                 (UINT64) MaximumVariableSize,
    784                 0,
    785                 0,
    786                 0
    787                 );
    788   return (EFI_STATUS) ReturnReg.Status;
    789 }
    790 
    791 #endif
    792 
    793 //
    794 //  Sal RTC Driver Class.
    795 //
    796 EFI_STATUS
    797 EfiGetTime (
    798   OUT EFI_TIME              *Time,
    799   OUT EFI_TIME_CAPABILITIES *Capabilities
    800   )
    801 /*++
    802 
    803 Routine Description:
    804 
    805   Returns the current time and date information, and the time-keeping
    806   capabilities of the hardware platform.
    807 
    808 Arguments:
    809 
    810   Time          - A pointer to storage to receive a snapshot of the current time.
    811   Capabilities  - An optional pointer to a buffer to receive the real time clock device's
    812                   capabilities.
    813 
    814 Returns:
    815 
    816   Status code
    817 
    818 --*/
    819 {
    820   SAL_RETURN_REGS ReturnReg;
    821   EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID;
    822 
    823   ReturnReg = EfiCallEsalService (&Guid, GetTime, (UINT64) Time, (UINT64) Capabilities, 0, 0, 0, 0, 0);
    824   return ReturnReg.Status;
    825 }
    826 
    827 EFI_STATUS
    828 EfiSetTime (
    829   OUT EFI_TIME              *Time
    830   )
    831 /*++
    832 
    833 Routine Description:
    834 
    835   Sets the current local time and date information.
    836 
    837 Arguments:
    838 
    839   Time  - A pointer to the current time.
    840 
    841 Returns:
    842 
    843   Status code
    844 
    845 --*/
    846 {
    847   SAL_RETURN_REGS ReturnReg;
    848 
    849   EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID;
    850 
    851   ReturnReg = EfiCallEsalService (&Guid, SetTime, (UINT64) Time, 0, 0, 0, 0, 0, 0);
    852   return ReturnReg.Status;
    853 }
    854 
    855 EFI_STATUS
    856 EfiGetWakeupTime (
    857   OUT BOOLEAN       *Enabled,
    858   OUT BOOLEAN       *Pending,
    859   OUT EFI_TIME      *Time
    860   )
    861 /*++
    862 
    863 Routine Description:
    864 
    865   Returns the current wakeup alarm clock setting.
    866 
    867 Arguments:
    868 
    869   Enabled - Indicates if the alarm is currently enabled or disabled.
    870   Pending - Indicates if the alarm signal is pending and requires acknowledgement.
    871   Time    - The current alarm setting.
    872 
    873 Returns:
    874 
    875   Status code
    876 
    877 --*/
    878 {
    879   SAL_RETURN_REGS ReturnReg;
    880 
    881   EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID;
    882 
    883   ReturnReg = EfiCallEsalService (&Guid, GetWakeupTime, (UINT64) Enabled, (UINT64) Pending, (UINT64) Time, 0, 0, 0, 0);
    884   return ReturnReg.Status;
    885 }
    886 
    887 EFI_STATUS
    888 EfiSetWakeupTime (
    889   IN BOOLEAN        Enable,
    890   IN EFI_TIME       *Time
    891   )
    892 /*++
    893 
    894 Routine Description:
    895 
    896   Sets the system wakeup alarm clock time.
    897 
    898 Arguments:
    899 
    900   Enable  - Enable or disable the wakeup alarm.
    901   Time    - If Enable is TRUE, the time to set the wakeup alarm for.
    902             If Enable is FALSE, then this parameter is optional, and may be NULL.
    903 
    904 Returns:
    905 
    906   Status code
    907 
    908 --*/
    909 {
    910   SAL_RETURN_REGS ReturnReg;
    911 
    912   EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID;
    913 
    914   ReturnReg = EfiCallEsalService (&Guid, SetWakeupTime, (UINT64) Enable, (UINT64) Time, 0, 0, 0, 0, 0);
    915   return ReturnReg.Status;
    916 }
    917 
    918 
    919 
    920 //
    921 //  Base IO Services
    922 //
    923 EFI_STATUS
    924 EfiIoRead (
    925   IN     EFI_CPU_IO_PROTOCOL_WIDTH  Width,
    926   IN     UINT64                     Address,
    927   IN     UINTN                      Count,
    928   IN OUT VOID                       *Buffer
    929   )
    930 /*++
    931 
    932 Routine Description:
    933   Perform an IO read into Buffer.
    934 
    935 Arguments:
    936   Width   - Width of read transaction, and repeat operation to use
    937   Address - IO address to read
    938   Count   - Number of times to read the IO address.
    939   Buffer  - Buffer to read data into. size is Width * Count
    940 
    941 Returns:
    942   Status code
    943 
    944 --*/
    945 {
    946 
    947   SAL_RETURN_REGS ReturnReg;
    948 
    949   EFI_GUID Guid = EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID;
    950 
    951   ReturnReg = EfiCallEsalService (&Guid, IoRead, (UINT64) Width, Address, Count, (UINT64) Buffer, 0, 0, 0);
    952   ASSERT (ReturnReg.Status == EFI_SAL_SUCCESS);
    953 
    954   return ReturnReg.Status;
    955 
    956 }
    957 
    958 EFI_STATUS
    959 EfiIoWrite (
    960   IN     EFI_CPU_IO_PROTOCOL_WIDTH  Width,
    961   IN     UINT64                     Address,
    962   IN     UINTN                      Count,
    963   IN OUT VOID                       *Buffer
    964   )
    965 /*++
    966 
    967 Routine Description:
    968   Perform an IO write into Buffer.
    969 
    970 Arguments:
    971   Width   - Width of write transaction, and repeat operation to use
    972   Address - IO address to write
    973   Count   - Number of times to write the IO address.
    974   Buffer  - Buffer to write data from. size is Width * Count
    975 
    976 Returns:
    977   Status code
    978 
    979 --*/
    980 {
    981 
    982   SAL_RETURN_REGS ReturnReg;
    983 
    984   EFI_GUID Guid = EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID;
    985 
    986   ReturnReg = EfiCallEsalService (&Guid, IoWrite, (UINT64) Width, Address, Count, (UINT64) Buffer, 0, 0, 0);
    987 
    988   return ReturnReg.Status;
    989 
    990 }
    991 
    992 EFI_STATUS
    993 EfiMemRead (
    994   IN     EFI_CPU_IO_PROTOCOL_WIDTH  Width,
    995   IN     UINT64                     Address,
    996   IN     UINTN                      Count,
    997   IN  OUT VOID                      *Buffer
    998   )
    999 /*++
   1000 
   1001 Routine Description:
   1002   Perform a Memory mapped IO read into Buffer.
   1003 
   1004 Arguments:
   1005   Width   - Width of each read transaction.
   1006   Address - Memory mapped IO address to read
   1007   Count   - Number of Width quanta to read
   1008   Buffer  - Buffer to read data into. size is Width * Count
   1009 
   1010 Returns:
   1011   Status code
   1012 
   1013 --*/
   1014 {
   1015 
   1016   SAL_RETURN_REGS ReturnReg;
   1017 
   1018   EFI_GUID Guid = EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID;
   1019 
   1020   ReturnReg = EfiCallEsalService (&Guid, MemRead, (UINT64) Width, Address, Count, (UINT64) Buffer, 0, 0, 0);
   1021   ASSERT (ReturnReg.Status == EFI_SAL_SUCCESS);
   1022 
   1023   return ReturnReg.Status;
   1024 
   1025 }
   1026 
   1027 EFI_STATUS
   1028 EfiMemWrite (
   1029   IN     EFI_CPU_IO_PROTOCOL_WIDTH  Width,
   1030   IN     UINT64                     Address,
   1031   IN     UINTN                      Count,
   1032   IN OUT VOID                       *Buffer
   1033   )
   1034 /*++
   1035 
   1036 Routine Description:
   1037   Perform a memory mapped IO write into Buffer.
   1038 
   1039 Arguments:
   1040   Width   - Width of write transaction, and repeat operation to use
   1041   Address - IO address to write
   1042   Count   - Number of times to write the IO address.
   1043   Buffer  - Buffer to write data from. size is Width * Count
   1044 
   1045 Returns:
   1046   Status code
   1047 
   1048 --*/
   1049 {
   1050 
   1051   SAL_RETURN_REGS ReturnReg;
   1052 
   1053   EFI_GUID Guid = EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID;
   1054 
   1055   ReturnReg = EfiCallEsalService (&Guid, MemWrite, (UINT64) Width, Address, Count, (UINT64) Buffer, 0, 0, 0);
   1056 
   1057   return ReturnReg.Status;
   1058 
   1059 }
   1060 
   1061 
   1062 #define EFI_PCI_ADDRESS_IPF(_seg, _bus, _devfunc, _reg) \
   1063     (((_seg) << 24) | ((_bus) << 16) | ((_devfunc) << 8) | (_reg)) & 0xFFFFFFFF
   1064 
   1065 //
   1066 //  PCI Class Functions
   1067 //
   1068 UINT8
   1069 PciRead8 (
   1070   UINT8   Segment,
   1071   UINT8   Bus,
   1072   UINT8   DevFunc,
   1073   UINT8   Register
   1074   )
   1075 /*++
   1076 
   1077 Routine Description:
   1078   Perform an one byte PCI config cycle read
   1079 
   1080 Arguments:
   1081   Segment   - PCI Segment ACPI _SEG
   1082   Bus       - PCI Bus
   1083   DevFunc   - PCI Device(7:3) and Func(2:0)
   1084   Register  - PCI config space register
   1085 
   1086 Returns:
   1087   Data read from PCI config space
   1088 
   1089 --*/
   1090 {
   1091   EFI_GUID        Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1092   UINT64          Address;
   1093   SAL_RETURN_REGS Return;
   1094 
   1095   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1096   Return  = EfiCallEsalService (&Guid, SalPciConfigRead, Address, 1, 0, 0, 0, 0, 0);
   1097 
   1098   return (UINT8) Return.r9;
   1099 }
   1100 
   1101 
   1102 UINT16
   1103 PciRead16 (
   1104   UINT8   Segment,
   1105   UINT8   Bus,
   1106   UINT8   DevFunc,
   1107   UINT8   Register
   1108   )
   1109 /*++
   1110 
   1111 Routine Description:
   1112   Perform an two byte PCI config cycle read
   1113 
   1114 Arguments:
   1115   Segment   - PCI Segment ACPI _SEG
   1116   Bus       - PCI Bus
   1117   DevFunc   - PCI Device(7:3) and Func(2:0)
   1118   Register  - PCI config space register
   1119 
   1120 Returns:
   1121   Data read from PCI config space
   1122 
   1123 --*/
   1124 {
   1125   EFI_GUID        Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1126   UINT64          Address;
   1127   SAL_RETURN_REGS Return;
   1128 
   1129   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1130   Return  = EfiCallEsalService (&Guid, SalPciConfigRead, Address, 2, 0, 0, 0, 0, 0);
   1131 
   1132   return (UINT16) Return.r9;
   1133 }
   1134 
   1135 UINT32
   1136 PciRead32 (
   1137   UINT8   Segment,
   1138   UINT8   Bus,
   1139   UINT8   DevFunc,
   1140   UINT8   Register
   1141   )
   1142 /*++
   1143 
   1144 Routine Description:
   1145   Perform an four byte PCI config cycle read
   1146 
   1147 Arguments:
   1148   Segment   - PCI Segment ACPI _SEG
   1149   Bus       - PCI Bus
   1150   DevFunc   - PCI Device(7:3) and Func(2:0)
   1151   Register  - PCI config space register
   1152 
   1153 Returns:
   1154   Data read from PCI config space
   1155 
   1156 --*/
   1157 {
   1158   EFI_GUID        Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1159   UINT64          Address;
   1160   SAL_RETURN_REGS Return;
   1161 
   1162   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1163   Return  = EfiCallEsalService (&Guid, SalPciConfigRead, Address, 4, 0, 0, 0, 0, 0);
   1164 
   1165   return (UINT32) Return.r9;
   1166 }
   1167 
   1168 VOID
   1169 PciWrite8 (
   1170   UINT8   Segment,
   1171   UINT8   Bus,
   1172   UINT8   DevFunc,
   1173   UINT8   Register,
   1174   UINT8   Data
   1175   )
   1176 /*++
   1177 
   1178 Routine Description:
   1179   Perform an one byte PCI config cycle write
   1180 
   1181 Arguments:
   1182   Segment   - PCI Segment ACPI _SEG
   1183   Bus       - PCI Bus
   1184   DevFunc   - PCI Device(7:3) and Func(2:0)
   1185   Register  - PCI config space register
   1186   Data      - Data to write
   1187 
   1188 Returns:
   1189   NONE
   1190 
   1191 --*/
   1192 {
   1193   EFI_GUID        Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1194   UINT64    Address;
   1195 
   1196   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1197   EfiCallEsalService (&Guid, SalPciConfigWrite, Address, 1, Data, 0, 0, 0, 0);
   1198 }
   1199 
   1200 VOID
   1201 PciWrite16 (
   1202   UINT8   Segment,
   1203   UINT8   Bus,
   1204   UINT8   DevFunc,
   1205   UINT8   Register,
   1206   UINT16  Data
   1207   )
   1208 /*++
   1209 
   1210 Routine Description:
   1211   Perform an two byte PCI config cycle write
   1212 
   1213 Arguments:
   1214   Segment   - PCI Segment ACPI _SEG
   1215   Bus       - PCI Bus
   1216   DevFunc   - PCI Device(7:3) and Func(2:0)
   1217   Register  - PCI config space register
   1218   Data      - Data to write
   1219 
   1220 Returns:
   1221   None.
   1222 
   1223 --*/
   1224 {
   1225   EFI_GUID        Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1226   UINT64    Address;
   1227 
   1228   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1229   EfiCallEsalService (&Guid, SalPciConfigWrite, Address, 2, Data, 0, 0, 0, 0);
   1230 }
   1231 
   1232 VOID
   1233 PciWrite32 (
   1234   UINT8   Segment,
   1235   UINT8   Bus,
   1236   UINT8   DevFunc,
   1237   UINT8   Register,
   1238   UINT32  Data
   1239   )
   1240 /*++
   1241 
   1242 Routine Description:
   1243   Perform an four byte PCI config cycle write
   1244 
   1245 Arguments:
   1246   Segment   - PCI Segment ACPI _SEG
   1247   Bus       - PCI Bus
   1248   DevFunc   - PCI Device(7:3) and Func(2:0)
   1249   Register  - PCI config space register
   1250   Data      - Data to write
   1251 
   1252 Returns:
   1253   NONE
   1254 
   1255 --*/
   1256 {
   1257   EFI_GUID  Guid = EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID;
   1258   UINT64    Address;
   1259 
   1260   Address = EFI_PCI_ADDRESS_IPF (Segment, Bus, DevFunc, Register);
   1261   EfiCallEsalService (&Guid, SalPciConfigWrite, Address, 4, Data, 0, 0, 0, 0);
   1262 }
   1263 
   1264 //
   1265 // Stall class functions
   1266 //
   1267 VOID
   1268 EfiStall (
   1269   IN  UINTN   Microseconds
   1270   )
   1271 /*++
   1272 
   1273 Routine Description:
   1274  Delay for at least the request number of microseconds
   1275 
   1276 Arguments:
   1277   Microseconds - Number of microseconds to delay.
   1278 
   1279 Returns:
   1280   NONE
   1281 
   1282 --*/
   1283 {
   1284   EFI_GUID        Guid = EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID;
   1285 
   1286   if (EfiAtRuntime ()) {
   1287     EfiCallEsalService (&Guid, Stall, Microseconds, 4, 0, 0, 0, 0, 0);
   1288   } else {
   1289     gBS->Stall (Microseconds);
   1290   }
   1291 }
   1292 //
   1293 // Cache Flush Routine.
   1294 //
   1295 EFI_STATUS
   1296 EfiCpuFlushCache (
   1297   IN EFI_PHYSICAL_ADDRESS          Start,
   1298   IN UINT64                        Length
   1299   )
   1300 /*++
   1301 
   1302 Routine Description:
   1303 
   1304   Flush cache with specified range.
   1305 
   1306 Arguments:
   1307 
   1308   Start   - Start address
   1309   Length  - Length in bytes
   1310 
   1311 Returns:
   1312 
   1313   Status code
   1314 
   1315   EFI_SUCCESS - success
   1316 
   1317 --*/
   1318 {
   1319   SalFlushCache (Start, Length);
   1320   return EFI_SUCCESS;
   1321 }
   1322