/** Collect the keyboard input for a cmd line. Carriage Return, New Line, or ESC terminates the command line. You can edit the command line via left arrow, delete and backspace and they all back up and erase the command line. No edit of command line is possible without deletion at this time! The up arrow and down arrow fill Cmd with information from the history buffer. @param Cmd Command line to return @param CmdMaxSize Maximum size of Cmd @return The Status of EblGetCharKey() **/ EFI_STATUS GetCmd ( IN OUT CHAR8 *Cmd, IN UINTN CmdMaxSize ) { EFI_STATUS Status; UINTN Index; UINTN Index2; CHAR8 Char; CHAR8 *History; EFI_INPUT_KEY Key; for (Index = 0; Index < CmdMaxSize - 1;) { Status = EblGetCharKey (&Key, 0, NULL); if (EFI_ERROR (Status)) { Cmd[Index] = '\0'; AsciiPrint ("\n"); return Status; } Char = (CHAR8)Key.UnicodeChar; if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) { Cmd[Index] = '\0'; if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { AsciiPrint ("\n\r"); } return EFI_SUCCESS; } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){ if (Index != 0) { Index--; // // Update the display // AsciiPrint ("\b \b"); } } else if ((Key.ScanCode == SCAN_UP) || Key.ScanCode == SCAN_DOWN) { History = GetCmdHistory (Key.ScanCode); // // Clear display line // for (Index2 = 0; Index2 < Index; Index2++) { AsciiPrint ("\b \b"); } AsciiPrint (History); Index = AsciiStrLen (History); AsciiStrnCpyS (Cmd, CmdMaxSize, History, CmdMaxSize); } else { Cmd[Index++] = Char; if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { AsciiPrint ("%c", Char); } } } return EFI_SUCCESS; }
STATIC VOID SetSataCapabilities ( EFI_PHYSICAL_ADDRESS AhciBaseAddr ) { UINT32 Capability; Capability = 0; if (FixedPcdGetBool (PcdSataSssSupport)) // Staggered Spin-Up Support bit Capability |= EFI_AHCI_CAP_SSS; if (FixedPcdGetBool (PcdSataSmpsSupport)) // Mechanical Presence Support bit Capability |= EFI_AHCI_CAP_SMPS; MmioOr32 (AhciBaseAddr + EFI_AHCI_CAPABILITY_OFFSET, Capability); }
STATIC VOID InitializeSataPorts ( EFI_PHYSICAL_ADDRESS AhciBaseAddr, UINTN PortCount ) { INTN PortNum; BOOLEAN IsCpd; BOOLEAN IsMpsp; UINT32 PortRegAddr; UINT32 RegVal; // Set Ports Implemented (PI) MmioWrite32 (AhciBaseAddr + EFI_AHCI_PI_OFFSET, (1 << PortCount) - 1); IsCpd = FixedPcdGetBool (PcdSataPortCpd); IsMpsp = FixedPcdGetBool (PcdSataPortMpsp); if (!IsCpd && !IsMpsp) { return; } for (PortNum = 0; PortNum < PortCount; PortNum++) { PortRegAddr = EFI_AHCI_PORT_OFFSET (PortNum) + EFI_AHCI_PORT_CMD; RegVal = MmioRead32(AhciBaseAddr + PortRegAddr); if (IsCpd) RegVal |= EFI_AHCI_PORT_CMD_CPD; else RegVal &= ~EFI_AHCI_PORT_CMD_CPD; if (IsMpsp) RegVal |= EFI_AHCI_PORT_CMD_MPSP; else RegVal &= ~EFI_AHCI_PORT_CMD_MPSP; RegVal |= EFI_AHCI_PORT_CMD_HPCP; MmioWrite32(AhciBaseAddr + PortRegAddr, RegVal); } }
/** *--------------------------------------------------------------------------------------- * PlatInitPeiEntryPoint * * Description: * Entry point of the PlatInit PEI module. * * Control flow: * Query platform parameters via ISCP. * * Parameters: * @param[in] FfsHeader EFI_PEI_FILE_HANDLE * @param[in] **PeiServices Pointer to the PEI Services Table. * * @return EFI_STATUS * *--------------------------------------------------------------------------------------- */ EFI_STATUS EFIAPI PlatInitPeiEntryPoint ( IN EFI_PEI_FILE_HANDLE FfsHeader, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status = EFI_SUCCESS; AMD_MEMORY_RANGE_DESCRIPTOR IscpMemDescriptor = {0}; ISCP_FUSE_INFO IscpFuseInfo = {0}; ISCP_CPU_RESET_INFO CpuResetInfo = {0}; #if DO_XGBE == 1 ISCP_MAC_INFO MacAddrInfo = {0}; UINT64 MacAddr0, MacAddr1; #endif UINTN CpuCoreCount, CpuMap, CpuMapSize; UINTN Index, CoreNum; UINT32 *CpuIdReg = (UINT32 *)FixedPcdGet32 (PcdCpuIdRegister); DEBUG ((EFI_D_ERROR, "PlatInit PEIM Loaded\n")); // CPUID PcdSet32 (PcdSocCpuId, *CpuIdReg); DEBUG ((EFI_D_ERROR, "SocCpuId = 0x%X\n", PcdGet32 (PcdSocCpuId))); // Update core count based on PCD option if (mAmdCoreCount > PcdGet32 (PcdSocCoreCount)) { mAmdCoreCount = PcdGet32 (PcdSocCoreCount); } if (FixedPcdGetBool (PcdIscpSupport)) { Status = PeiServicesLocatePpi (&gPeiIscpPpiGuid, 0, NULL, (VOID**)&PeiIscpPpi); ASSERT_EFI_ERROR (Status); // Get fuse information from ISCP Status = PeiIscpPpi->ExecuteFuseTransaction (PeiServices, &IscpFuseInfo); ASSERT_EFI_ERROR (Status); CpuMap = IscpFuseInfo.SocConfiguration.CpuMap; CpuCoreCount = IscpFuseInfo.SocConfiguration.CpuCoreCount; CpuMapSize = sizeof (IscpFuseInfo.SocConfiguration.CpuMap) * 8; ASSERT (CpuMap != 0); ASSERT (CpuCoreCount != 0); ASSERT (CpuCoreCount <= CpuMapSize); // Update core count based on fusing if (mAmdCoreCount > CpuCoreCount) { mAmdCoreCount = CpuCoreCount; } } // // Update per-core information from ISCP // if (!FixedPcdGetBool (PcdIscpSupport)) { DEBUG ((EFI_D_ERROR, "Warning: Could not get CPU info via ISCP, using default values.\n")); } else { // // Walk CPU map to enumerate active cores // for (CoreNum = 0, Index = 0; CoreNum < CpuMapSize && Index < mAmdCoreCount; ++CoreNum) { if (CpuMap & 1) { CpuResetInfo.CoreNum = CoreNum; Status = PeiIscpPpi->ExecuteCpuRetrieveIdTransaction ( PeiServices, &CpuResetInfo ); ASSERT_EFI_ERROR (Status); ASSERT (CpuResetInfo.CoreStatus.Status != CPU_CORE_DISABLED); ASSERT (CpuResetInfo.CoreStatus.Status != CPU_CORE_UNDEFINED); mAmdMpCoreInfoTable[Index].ClusterId = CpuResetInfo.CoreStatus.ClusterId; mAmdMpCoreInfoTable[Index].CoreId = CpuResetInfo.CoreStatus.CoreId; DEBUG ((EFI_D_ERROR, "Core[%d]: ClusterId = %d CoreId = %d\n", Index, mAmdMpCoreInfoTable[Index].ClusterId, mAmdMpCoreInfoTable[Index].CoreId)); // Next core in Table ++Index; } // Next core in Map CpuMap >>= 1; } // Update core count based on CPU map if (mAmdCoreCount > Index) { mAmdCoreCount = Index; } } // Update SocCoreCount on Dynamic PCD if (PcdGet32 (PcdSocCoreCount) != mAmdCoreCount) { PcdSet32 (PcdSocCoreCount, mAmdCoreCount); } DEBUG ((EFI_D_ERROR, "SocCoreCount = %d\n", PcdGet32 (PcdSocCoreCount))); // Build AmdMpCoreInfo HOB BuildGuidDataHob (&gAmdStyxMpCoreInfoGuid, mAmdMpCoreInfoTable, sizeof (ARM_CORE_INFO) * mAmdCoreCount); // Get SystemMemorySize from ISCP IscpMemDescriptor.Size0 = 0; if (FixedPcdGetBool (PcdIscpSupport)) { Status = PeiIscpPpi->ExecuteMemoryTransaction (PeiServices, &IscpMemDescriptor); ASSERT_EFI_ERROR (Status); // Update SystemMemorySize on Dynamic PCD if (IscpMemDescriptor.Size0) { PcdSet64 (PcdSystemMemorySize, IscpMemDescriptor.Size0); } } if (IscpMemDescriptor.Size0 == 0) { DEBUG ((EFI_D_ERROR, "Warning: Could not get SystemMemorySize via ISCP, using default value.\n")); } DEBUG ((EFI_D_ERROR, "SystemMemorySize = %ld\n", PcdGet64 (PcdSystemMemorySize))); #if DO_XGBE == 1 // Get MAC Address from ISCP if (FixedPcdGetBool (PcdIscpSupport)) { Status = PeiIscpPpi->ExecuteGetMacAddressTransaction ( PeiServices, &MacAddrInfo ); ASSERT_EFI_ERROR (Status); MacAddr0 = MacAddr1 = 0; for (Index = 0; Index < 6; ++Index) { MacAddr0 |= (UINT64)MacAddrInfo.MacAddress0[Index] << (Index * 8); MacAddr1 |= (UINT64)MacAddrInfo.MacAddress1[Index] << (Index * 8); } PcdSet64 (PcdEthMacA, MacAddr0); PcdSet64 (PcdEthMacB, MacAddr1); } DEBUG ((EFI_D_ERROR, "EthMacA = 0x%lX\n", PcdGet64 (PcdEthMacA))); DEBUG ((EFI_D_ERROR, "EthMacB = 0x%lX\n", PcdGet64 (PcdEthMacB))); #endif // Let other PEI modules know we're done! Status = (*PeiServices)->InstallPpi (PeiServices, &mPlatInitPpiDescriptor); ASSERT_EFI_ERROR (Status); return Status; }
VOID CEntryPoint ( IN UINTN MpId, IN UINTN SecBootMode ) { CHAR8 Buffer[100]; UINTN CharCount; UINTN JumpAddress; // Invalidate the data cache. Doesn't have to do the Data cache clean. ArmInvalidateDataCache (); // Invalidate Instruction Cache ArmInvalidateInstructionCache (); // Invalidate I & D TLBs ArmInvalidateInstructionAndDataTlb (); // CPU specific settings ArmCpuSetup (MpId); // Enable Floating Point Coprocessor if supported by the platform if (FixedPcdGet32 (PcdVFPEnabled)) { ArmEnableVFP (); } // Initialize peripherals that must be done at the early stage // Example: Some L2 controller, interconnect, clock, DMC, etc ArmPlatformSecInitialize (MpId); // Primary CPU clears out the SCU tag RAMs, secondaries wait if (ArmPlatformIsPrimaryCore (MpId) && (SecBootMode == ARM_SEC_COLD_BOOT)) { if (ArmIsMpCore()) { // Signal for the initial memory is configured (event: BOOT_MEM_INIT) ArmCallSEV (); } // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib // In non SEC modules the init call is in autogenerated code. SerialPortInitialize (); // Start talking if (FixedPcdGetBool (PcdTrustzoneSupport)) { CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Secure firmware (version %s built at %a on %a)\n\r", (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); } else { CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Boot firmware (version %s built at %a on %a)\n\r", (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); } SerialPortWrite ((UINT8 *) Buffer, CharCount); // Initialize the Debug Agent for Source Level Debugging InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL); SaveAndSetDebugTimerInterrupt (TRUE); // Enable the GIC distributor and CPU Interface // - no other Interrupts are enabled, doesn't have to worry about the priority. // - all the cores are in secure state, use secure SGI's ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase)); ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); } else { // Enable the GIC CPU Interface ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase)); } // Enable Full Access to CoProcessors ArmWriteCpacr (CPACR_CP_FULL_ACCESS); // Test if Trustzone is supported on this platform if (FixedPcdGetBool (PcdTrustzoneSupport)) { if (ArmIsMpCore ()) { // Setup SMP in Non Secure world ArmCpuSetupSmpNonSecure (GET_CORE_ID(MpId)); } // Either we use the Secure Stacks for Secure Monitor (in this case (Base == 0) && (Size == 0)) // Or we use separate Secure Monitor stacks (but (Base != 0) && (Size != 0)) ASSERT (((PcdGet32(PcdCPUCoresSecMonStackBase) == 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) == 0)) || ((PcdGet32(PcdCPUCoresSecMonStackBase) != 0) && (PcdGet32(PcdCPUCoreSecMonStackSize) != 0))); // Enter Monitor Mode enter_monitor_mode ( (UINTN)TrustedWorldInitialization, MpId, SecBootMode, (VOID*) (PcdGet32 (PcdCPUCoresSecMonStackBase) + (PcdGet32 (PcdCPUCoreSecMonStackSize) * (ArmPlatformGetCorePosition (MpId) + 1))) ); } else { if (ArmPlatformIsPrimaryCore (MpId)) { SerialPrint ("Trust Zone Configuration is disabled\n\r"); } // With Trustzone support the transition from Sec to Normal world is done by return_from_exception(). // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program // Status Register as the the current one (CPSR). copy_cpsr_into_spsr (); // Call the Platform specific function to execute additional actions if required JumpAddress = PcdGet32 (PcdFvBaseAddress); ArmPlatformSecExtraAction (MpId, &JumpAddress); NonTrustedWorldTransition (MpId, JumpAddress); } ASSERT (0); // We must never return from the above function }