/** Reads memory-mapped registers in the EFI system memory space. Reads the MMIO registers specified by Address with registers width specified by Width. The read value is returned. If such operations are not supported, then ASSERT(). This function must guarantee that all MMIO read and write operations are serialized. @param Address The MMIO register to read. The caller is responsible for aligning the Address if required. @param Width The width of the I/O operation. @return Data read from registers in the EFI system memory space. **/ UINT64 EFIAPI MmioReadWorker ( IN UINTN Address, IN EFI_CPU_IO_PROTOCOL_WIDTH Width ) { SAL_RETURN_REGS ReturnReg; UINT64 Data; Data = 0; ReturnReg = EsalCall ( EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_HI, MemReadFunctionId, (UINT64)Width, Address, 1, (UINT64)&Data, 0, 0, 0 ); ASSERT (ReturnReg.Status == EFI_SAL_SUCCESS); return Data; }
/** Writes registers in the EFI CPU I/O space. Writes the I/O port specified by Port with registers width and value specified by Width and Data respectively. Data is returned. If such operations are not supported, then ASSERT(). This function must guarantee that all I/O read and write operations are serialized. @param Port The base address of the I/O operation. The caller is responsible for aligning the Address if required. @param Width The width of the I/O operation. @param Data The value to write to the I/O port. @return The parameter of Data. **/ UINT64 EFIAPI IoWriteWorker ( IN UINTN Port, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Data ) { SAL_RETURN_REGS ReturnReg; ReturnReg = EsalCall ( EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_HI, IoWriteFunctionId, (UINT64)Width, Port, 1, (UINT64)&Data, 0, 0, 0 ); ASSERT (ReturnReg.Status == EFI_SAL_SUCCESS); return Data; }
/** Stalls the CPU for at least the given number of nanoseconds. This function wraps EsalStall function of Extended SAL Stall Services Class. It stalls the CPU for the number of nanoseconds specified by NanoSeconds. @param NanoSeconds The minimum number of nanoseconds to delay. @return NanoSeconds **/ UINTN EFIAPI NanoSecondDelay ( IN UINTN NanoSeconds ) { UINT64 MicroSeconds; // // The unit of ESAL Stall service is microsecond, so we turn the time interval // from nanosecond to microsecond, using the ceiling value to ensure stalling // at least the given number of nanoseconds. // MicroSeconds = DivU64x32 (NanoSeconds + 999, 1000); EsalCall ( EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_HI, StallFunctionId, MicroSeconds, 0, 0, 0, 0, 0, 0 ); return NanoSeconds; }
/** Internal worker function to read a PCI configuration register. This function wraps EsalPciConfigRead function of Extended SAL PCI Services Class. It reads and returns the PCI configuration register specified by Address, the width of data is specified by Width. @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Width Width of data to read @return The value read from the PCI configuration register. **/ UINT32 DxePciSegmentLibEsalReadWorker ( IN UINT64 Address, IN UINTN Width ) { SAL_RETURN_REGS Return; if (IS_PCI_COMPATIBLE_ADDRESS(Address)) { Return = EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigReadFunctionId, CONVERT_PCI_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS0 (Address), Width, EFI_SAL_PCI_COMPATIBLE_ADDRESS, 0, 0, 0, 0 ); } else { Return = EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigReadFunctionId, CONVERT_PCI_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS1 (Address), Width, EFI_SAL_PCI_EXTENDED_REGISTER_ADDRESS, 0, 0, 0, 0 ); } return (UINT32) Return.r9; }
/** Internal worker function to writes a PCI configuration register. This function wraps EsalPciConfigWrite function of Extended SAL PCI Services Class. It writes the PCI configuration register specified by Address with the value specified by Data. The width of data is specifed by Width. Data is returned. @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Width Width of data to write @param Data The value to write. @return The value written to the PCI configuration register. **/ UINT32 DxePciSegmentLibEsalWriteWorker ( IN UINT64 Address, IN UINTN Width, IN UINT32 Data ) { if (IS_PCI_COMPATIBLE_ADDRESS(Address)) { EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigWriteFunctionId, CONVERT_PCI_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS0 (Address), Width, Data, EFI_SAL_PCI_COMPATIBLE_ADDRESS, 0, 0, 0 ); } else { EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigWriteFunctionId, CONVERT_PCI_SEGMENT_LIB_ADDRESS_TO_PCI_ESAL_ADDRESS1 (Address), Width, Data, EFI_SAL_PCI_EXTENDED_REGISTER_ADDRESS, 0, 0, 0 ); } return Data; }
/** Stalls the CPU for at least the given number of microseconds. This function wraps EsalStall function of Extended SAL Stall Services Class. It stalls the CPU for the number of microseconds specified by MicroSeconds. @param MicroSeconds The minimum number of microseconds to delay. @return MicroSeconds **/ UINTN EFIAPI MicroSecondDelay ( IN UINTN MicroSeconds ) { EsalCall ( EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_HI, StallFunctionId, MicroSeconds, 0, 0, 0, 0, 0, 0 ); return MicroSeconds; }
/** Makes a SAL procedure call. This is a wrapper function to make a SAL procedure call. No parameter checking is performed on the 8 input parameters, but there are some common rules that the caller should follow when making a SAL call. Any address passed to SAL as buffers for return parameters must be 8-byte aligned. Unaligned addresses may cause undefined results. For those parameters defined as reserved or some fields defined as reserved must be zero filled or the invalid argument return value may be returned or undefined result may occur during the execution of the procedure. This function is only available on IPF. @param Index The SAL procedure Index number @param Arg2 The 2nd parameter for SAL procedure calls @param Arg3 The 3rd parameter for SAL procedure calls @param Arg4 The 4th parameter for SAL procedure calls @param Arg5 The 5th parameter for SAL procedure calls @param Arg6 The 6th parameter for SAL procedure calls @param Arg7 The 7th parameter for SAL procedure calls @param Arg8 The 8th parameter for SAL procedure calls @return SAL returned registers. **/ SAL_RETURN_REGS EFIAPI SalCall ( IN UINT64 Index, IN UINT64 Arg2, IN UINT64 Arg3, IN UINT64 Arg4, IN UINT64 Arg5, IN UINT64 Arg6, IN UINT64 Arg7, IN UINT64 Arg8 ) { SAL_RETURN_REGS Regs; // // Initial all members in this structure. // Regs.r9 = 0; Regs.r10 = 0; Regs.r11 = 0; Regs.Status = EFI_SAL_INVALID_ARGUMENT; switch (Index) { case EFI_SAL_SET_VECTORS: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, SalSetVectorsFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_GET_STATE_INFO: return EsalCall ( EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_HI, SalGetStateInfoFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_GET_STATE_INFO_SIZE: return EsalCall ( EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_HI, SalGetStateInfoSizeFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_CLEAR_STATE_INFO: return EsalCall ( EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_HI, SalClearStateInfoFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_MC_RENDEZ: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, SalMcRendezFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_MC_SET_PARAMS: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, SalMcSetParamsFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_REGISTER_PHYSICAL_ADDR: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, EsalRegisterPhysicalAddrFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_CACHE_FLUSH: return EsalCall ( EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_HI, SalCacheFlushFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_CACHE_INIT: return EsalCall ( EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_HI, SalCacheInitFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_PCI_CONFIG_READ: return EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigReadFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_PCI_CONFIG_WRITE: return EsalCall ( EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI, SalPciConfigWriteFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_FREQ_BASE: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, EsalGetPlatformBaseFreqFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_PHYSICAL_ID_INFO: return EsalCall ( EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI, EsalPhysicalIdInfoFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; case EFI_SAL_UPDATE_PAL: return EsalCall ( EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID_LO, EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID_HI, EsalUpdatePalFunctionId, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8 ); break; default: return Regs; break; } }