mirror of
				https://github.com/Atmosphere-NX/Atmosphere.git
				synced 2025-10-31 03:05:48 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			104 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * 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 <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| #include <stratosphere.hpp>
 | |
| #include "boot_power_utils.hpp"
 | |
| #include "boot_pmic_driver.hpp"
 | |
| #include "fusee_bin.h"
 | |
| 
 | |
| namespace ams::boot {
 | |
| 
 | |
|     namespace {
 | |
| 
 | |
|         /* Convenience definitions. */
 | |
|         constexpr uintptr_t IramBase = 0x40000000ull;
 | |
|         constexpr uintptr_t IramPayloadBase = 0x40010000ull;
 | |
|         constexpr size_t IramSize = 0x40000;
 | |
|         constexpr size_t IramPayloadMaxSize = 0x24000;
 | |
|         constexpr size_t IramFatalErrorContextOffset = 0x2E000;
 | |
| 
 | |
|         /* Globals. */
 | |
|         alignas(os::MemoryPageSize) u8 g_work_page[os::MemoryPageSize];
 | |
| 
 | |
|         /* Helpers. */
 | |
|         void ClearIram() {
 | |
|             /* Make page FFs. */
 | |
|             std::memset(g_work_page, 0xFF, sizeof(g_work_page));
 | |
| 
 | |
|             /* Overwrite all of IRAM with FFs. */
 | |
|             for (size_t ofs = 0; ofs < IramSize; ofs += sizeof(g_work_page)) {
 | |
|                 exosphere::CopyToIram(IramBase + ofs, g_work_page, sizeof(g_work_page));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void DoRebootToPayload() {
 | |
|             /* Ensure clean IRAM state. */
 | |
|             ClearIram();
 | |
| 
 | |
|             /* Copy in payload. */
 | |
|             for (size_t ofs = 0; ofs < fusee_bin_size; ofs += sizeof(g_work_page)) {
 | |
|                 std::memcpy(g_work_page, &fusee_bin[ofs], std::min(static_cast<size_t>(fusee_bin_size - ofs), sizeof(g_work_page)));
 | |
|                 exosphere::CopyToIram(IramPayloadBase + ofs, g_work_page, sizeof(g_work_page));
 | |
|             }
 | |
| 
 | |
|             exosphere::ForceRebootToIramPayload();
 | |
|         }
 | |
| 
 | |
|         void DoRebootToFatalError(const ams::FatalErrorContext *ctx) {
 | |
|             /* Ensure clean IRAM state. */
 | |
|             ClearIram();
 | |
| 
 | |
|             /* Copy in payload. */
 | |
|             for (size_t ofs = 0; ofs < fusee_bin_size; ofs += sizeof(g_work_page)) {
 | |
|                 std::memcpy(g_work_page, &fusee_bin[ofs], std::min(static_cast<size_t>(fusee_bin_size - ofs), sizeof(g_work_page)));
 | |
|                 exosphere::CopyToIram(IramPayloadBase + ofs, g_work_page, sizeof(g_work_page));
 | |
|             }
 | |
| 
 | |
| 
 | |
|             /* Copy in fatal error context, if relevant. */
 | |
|             if (ctx != nullptr) {
 | |
|                 std::memset(g_work_page, 0xCC, sizeof(g_work_page));
 | |
|                 std::memcpy(g_work_page, ctx, sizeof(*ctx));
 | |
|                 exosphere::CopyToIram(IramPayloadBase + IramFatalErrorContextOffset, g_work_page, sizeof(g_work_page));
 | |
|             }
 | |
| 
 | |
|             exosphere::ForceRebootToFatalError();
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     void RebootSystem() {
 | |
|         if (spl::GetSocType() == spl::SocType_Erista) {
 | |
|             DoRebootToPayload();
 | |
|         } else {
 | |
|             /* On Mariko, we can't reboot to payload, so we should just do a reboot. */
 | |
|             PmicDriver().RebootSystem();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void ShutdownSystem() {
 | |
|         PmicDriver().ShutdownSystem();
 | |
|     }
 | |
| 
 | |
|     void SetInitialRebootPayload() {
 | |
|         ::ams::SetInitialRebootPayload(fusee_bin, fusee_bin_size);
 | |
|     }
 | |
| 
 | |
|     void RebootForFatalError(ams::FatalErrorContext *ctx) {
 | |
|         DoRebootToFatalError(ctx);
 | |
|     }
 | |
| 
 | |
| }
 |