/* * Copyright (c) 2018-2020 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "secmon_boot.hpp" #include "secmon_boot_functions.hpp" #include "../smc/secmon_random_cache.hpp" #include "../secmon_setup.hpp" #include "../secmon_misc.hpp" namespace ams::secmon { void Main() { /* Set library register addresses. */ /* actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress()); */ clkrst::SetRegisterAddress(MemoryRegionVirtualDeviceClkRst.GetAddress()); flow::SetRegisterAddress(MemoryRegionVirtualDeviceFlowController.GetAddress()); fuse::SetRegisterAddress(MemoryRegionVirtualDeviceFuses.GetAddress()); gic::SetRegisterAddress(MemoryRegionVirtualDeviceGicDistributor.GetAddress(), MemoryRegionVirtualDeviceGicCpuInterface.GetAddress()); i2c::SetRegisterAddress(i2c::Port_1, MemoryRegionVirtualDeviceI2c1.GetAddress()); i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress()); /* pinmux::SetRegisterAddress(); */ pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress()); se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress()); uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress()); wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress()); util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress()); /* Get the secure monitor parameters. */ auto &secmon_params = *reinterpret_cast(MemoryRegionVirtualDeviceBootloaderParams.GetAddress()); /* Perform initialization. */ { /* Perform initial setup. */ /* This checks the security engine's validity, and configures common interrupts in the GIC. */ /* This also initializes the global configuration context. */ secmon::Setup1(); /* Save the boot info. */ secmon::SaveBootInfo(secmon_params); /* Perform cold-boot specific init. */ secmon::boot::InitializeColdBoot(); /* Setup the SoC security measures. */ secmon::SetupSocSecurity(); /* Setup the Cpu core context. */ secmon::SetupCpuCoreContext(); /* Clear the crt0 code that was present in iram. */ secmon::boot::ClearIram(); /* Alert the bootloader that we're initialized. */ secmon_params.secmon_state = pkg1::SecureMonitorState_Initialized; /* Initialize the random cache. */ secmon::smc::FillRandomCache(); } /* Wait for NX Bootloader to finish loading the BootConfig. */ secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_LoadedBootConfig); hw::DataSynchronizationBarrierInnerShareable(); /* Load the bootconfig. */ secmon::boot::LoadBootConfig(MemoryRegionPhysicalIramBootConfig.GetPointer()); /* Verify or clear the boot config. */ secmon::boot::VerifyOrClearBootConfig(); /* Get the boot config. */ const auto &bc = secmon::GetBootConfig(); /* Set the tsc value by the boot config. */ { constexpr u64 TscMask = (static_cast(1) << 55) - 1; secmon::boot::EnableTsc(bc.data.GetInitialTscValue() & TscMask); } /* Wait for NX Bootloader to initialize DRAM. */ secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_InitializedDram); /* Secure the PMC and MC. */ secmon::SetupPmcAndMcSecure(); /* Copy warmboot to dram. */ { /* Define warmboot extents. */ const void * const src = MemoryRegionPhysicalIramWarmbootBin.GetPointer(); void * const dst = MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware.GetPointer(); const size_t size = MemoryRegionPhysicalIramWarmbootBin.GetSize(); /* Ensure we copy the correct data. */ hw::FlushDataCache(src, size); hw::DataSynchronizationBarrierInnerShareable(); /* Copy warmboot.bin to its secure dram location. */ std::memcpy(dst, src, size); } /* Unmap the identity mapping. */ secmon::boot::UnmapPhysicalIdentityMapping(); /* Setup the GPU carveout's magic numbers. */ secmon::boot::WriteGpuCarveoutMagicNumbers(); /* Wait for NX bootloader to load Package2. */ secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_LoadedPackage2); /* Parse and decrypt the package2 header. */ pkg2::Package2Meta pkg2_meta; const uintptr_t pkg2_segments_start = MemoryRegionDramPackage2.GetAddress() + sizeof(pkg2::Package2Header); { /* Read the encrypred header. */ pkg2::Package2Header encrypted_header; const auto *dram_header = MemoryRegionDramPackage2.GetPointer(); hw::FlushDataCache(dram_header, sizeof(*dram_header)); hw::DataSynchronizationBarrierInnerShareable(); std::memcpy(std::addressof(encrypted_header), dram_header, sizeof(encrypted_header)); /* Atmosphere extension: support plaintext package2, identified by all-zeroes signature and decrypted header. */ secmon::boot::UpdateBootConfigForPackage2Header(encrypted_header); /* Verify the package2 header's signature. */ secmon::boot::VerifyPackage2HeaderSignature(encrypted_header, !bc.signed_data.IsPackage2SignatureVerificationDisabled()); /* Decrypt the package2 header. */ secmon::boot::DecryptPackage2Header(std::addressof(pkg2_meta), encrypted_header.meta, !bc.signed_data.IsPackage2EncryptionDisabled()); } /* TODO */ AMS_UNUSED(pkg2_segments_start); } }