mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-29 14:05:17 -04:00
exo2: implement SmcIramCopy/reboot to payload/rcm
This commit is contained in:
parent
bb6671a94a
commit
6c145d76c7
31 changed files with 868 additions and 47 deletions
|
@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
|
|||
#---------------------------------------------------------------------------------
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -fno-non-call-exceptions
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -flto -fno-non-call-exceptions
|
||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||
|
@ -125,7 +125,7 @@ $(OFILES) : $(GCH_FILES)
|
|||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
libc.o: CFLAGS += -fno-builtin
|
||||
libc.o: CFLAGS += -fno-builtin -fno-lto
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
|
|
|
@ -126,7 +126,7 @@ $(OFILES) : $(GCH_FILES)
|
|||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
libc.o: CFLAGS += -fno-builtin
|
||||
libc.o: CFLAGS += -fno-builtin -fno-lto
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <exosphere/uart.hpp>
|
||||
#include <exosphere/pinmux.hpp>
|
||||
#include <exosphere/pmic.hpp>
|
||||
#include <exosphere/rtc.hpp>
|
||||
#include <exosphere/log.hpp>
|
||||
#include <exosphere/clkrst.hpp>
|
||||
#include <exosphere/actmon.hpp>
|
||||
|
|
|
@ -43,11 +43,13 @@ namespace ams::hw::arch::arm64 {
|
|||
}
|
||||
|
||||
ALWAYS_INLINE void InvalidateTlb(uintptr_t address) {
|
||||
__asm__ __volatile__("tlbi vae3is, %[address]" :: [address]"r"(address) : "memory");
|
||||
const uintptr_t page_index = address / 4_KB;
|
||||
__asm__ __volatile__("tlbi vae3is, %[page_index]" :: [page_index]"r"(page_index) : "memory");
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void InvalidateTlbLastLevel(uintptr_t address) {
|
||||
__asm__ __volatile__("tlbi vale3is, %[address]" :: [address]"r"(address) : "memory");
|
||||
const uintptr_t page_index = address / 4_KB;
|
||||
__asm__ __volatile__("tlbi vale3is, %[page_index]" :: [page_index]"r"(page_index) : "memory");
|
||||
}
|
||||
|
||||
void FlushDataCache(const void *ptr, size_t size);
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
|
||||
constexpr inline u64 MemoryRegionAttributeWidth = 8;
|
||||
|
||||
constexpr PageTableMappingAttribute AddMappingAttributeIndex(PageTableMappingAttribute attr, int index) {
|
||||
constexpr ALWAYS_INLINE PageTableMappingAttribute AddMappingAttributeIndex(PageTableMappingAttribute attr, int index) {
|
||||
return static_cast<PageTableMappingAttribute>(attr | (static_cast<typename std::underlying_type<PageTableMappingAttribute>::type>(index) << 2));
|
||||
}
|
||||
|
||||
|
@ -169,35 +169,35 @@ namespace ams::mmu::arch::arm64 {
|
|||
constexpr inline u64 EntryBlock = 0x1ul;
|
||||
constexpr inline u64 EntryPage = 0x3ul;
|
||||
|
||||
constexpr u64 MakeTableEntry(u64 address, PageTableTableAttribute attr) {
|
||||
constexpr ALWAYS_INLINE u64 MakeTableEntry(u64 address, PageTableTableAttribute attr) {
|
||||
return address | static_cast<u64>(attr) | 0x3ul;
|
||||
}
|
||||
|
||||
constexpr u64 MakeL1BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE u64 MakeL1BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
return address | static_cast<u64>(attr) | static_cast<u64>(PageTableMappingAttribute_AccessFlagAccessed) | 0x1ul;
|
||||
}
|
||||
|
||||
constexpr u64 MakeL2BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE u64 MakeL2BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
return address | static_cast<u64>(attr) | static_cast<u64>(PageTableMappingAttribute_AccessFlagAccessed) | 0x1ul;
|
||||
}
|
||||
|
||||
constexpr u64 MakeL3BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE u64 MakeL3BlockEntry(u64 address, PageTableMappingAttribute attr) {
|
||||
return address | static_cast<u64>(attr) | static_cast<u64>(PageTableMappingAttribute_AccessFlagAccessed) | 0x3ul;
|
||||
}
|
||||
|
||||
constexpr uintptr_t GetL2Offset(uintptr_t address) {
|
||||
constexpr ALWAYS_INLINE uintptr_t GetL2Offset(uintptr_t address) {
|
||||
return address & ((1ul << L2EntryShift) - 1);
|
||||
}
|
||||
|
||||
constexpr u64 GetL1EntryIndex(uintptr_t address) {
|
||||
constexpr ALWAYS_INLINE u64 GetL1EntryIndex(uintptr_t address) {
|
||||
return ((address >> L1EntryShift) & TableEntryIndexMask);
|
||||
}
|
||||
|
||||
constexpr u64 GetL2EntryIndex(uintptr_t address) {
|
||||
constexpr ALWAYS_INLINE u64 GetL2EntryIndex(uintptr_t address) {
|
||||
return ((address >> L2EntryShift) & TableEntryIndexMask);
|
||||
}
|
||||
|
||||
constexpr u64 GetL3EntryIndex(uintptr_t address) {
|
||||
constexpr ALWAYS_INLINE u64 GetL3EntryIndex(uintptr_t address) {
|
||||
return ((address >> L3EntryShift) & TableEntryIndexMask);
|
||||
}
|
||||
|
||||
|
@ -218,15 +218,15 @@ namespace ams::mmu::arch::arm64 {
|
|||
SetTableEntryImpl(table, index, value);
|
||||
}
|
||||
|
||||
constexpr void SetL1TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
|
||||
constexpr ALWAYS_INLINE void SetL1TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
|
||||
SetTableEntry(table, GetL1EntryIndex(virt_addr), MakeTableEntry(phys_addr & TableEntryMask, attr));
|
||||
}
|
||||
|
||||
constexpr void SetL2TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
|
||||
constexpr ALWAYS_INLINE void SetL2TableEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, PageTableTableAttribute attr) {
|
||||
SetTableEntry(table, GetL2EntryIndex(virt_addr), MakeTableEntry(phys_addr & TableEntryMask, attr));
|
||||
}
|
||||
|
||||
constexpr void SetL1BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE void SetL1BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
const u64 start = GetL1EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L1EntryShift);
|
||||
|
||||
|
@ -235,7 +235,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr void SetL2BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE void SetL2BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
const u64 start = GetL2EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L2EntryShift);
|
||||
|
||||
|
@ -244,7 +244,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr void SetL3BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
constexpr ALWAYS_INLINE void SetL3BlockEntry(u64 *table, uintptr_t virt_addr, uintptr_t phys_addr, size_t size, PageTableMappingAttribute attr) {
|
||||
const u64 start = GetL3EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L3EntryShift);
|
||||
|
||||
|
@ -253,7 +253,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr void InvalidateL1Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
constexpr ALWAYS_INLINE void InvalidateL1Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
const u64 start = GetL1EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L1EntryShift);
|
||||
const u64 end = start + count;
|
||||
|
@ -263,7 +263,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr void InvalidateL2Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
constexpr ALWAYS_INLINE void InvalidateL2Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
const u64 start = GetL2EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L2EntryShift);
|
||||
const u64 end = start + count;
|
||||
|
@ -273,7 +273,7 @@ namespace ams::mmu::arch::arm64 {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr void InvalidateL3Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
constexpr ALWAYS_INLINE void InvalidateL3Entries(volatile u64 *table, uintptr_t virt_addr, size_t size) {
|
||||
const u64 start = GetL3EntryIndex(virt_addr);
|
||||
const u64 count = (size >> L3EntryShift);
|
||||
const u64 end = start + count;
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace ams::pmic {
|
|||
void EnableVddCpu(Regulator regulator);
|
||||
void DisableVddCpu(Regulator regulator);
|
||||
void EnableSleep();
|
||||
void PowerOff();
|
||||
bool IsAcOk();
|
||||
|
||||
}
|
23
libraries/libexosphere/include/exosphere/rtc.hpp
Normal file
23
libraries/libexosphere/include/exosphere/rtc.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::rtc {
|
||||
|
||||
void StopAlarm();
|
||||
|
||||
}
|
|
@ -287,4 +287,6 @@ namespace ams::secmon {
|
|||
constexpr inline const MemoryRegion MemoryRegionPhysicalIramWarmbootBin = MemoryRegion(UINT64_C(0x4003E000), 0x17F0);
|
||||
constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootConfig = MemoryRegion(UINT64_C(0x4003F800), 0x400);
|
||||
|
||||
constexpr inline const MemoryRegion MemoryRegionPhysicalIramRebootStub = MemoryRegion(UINT64_C(0x4003F000), 0x1000);
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#define APBDEV_PMC_CRYPTO_OP (0x0F4)
|
||||
#define APBDEV_PMC_SCRATCH31 (0x118)
|
||||
#define APBDEV_PMC_SCRATCH32 (0x11C)
|
||||
#define APBDEV_PMC_SCRATCH33 (0x120)
|
||||
#define APBDEV_PMC_SCRATCH40 (0x13C)
|
||||
#define APBDEV_PMC_WAKE2_MASK (0x160)
|
||||
#define APBDEV_PMC_WAKE2_LVL (0x164)
|
||||
#define APBDEV_PMC_WAKE2_STATUS (0x168)
|
||||
|
@ -54,6 +56,8 @@
|
|||
#define APBDEV_PMC_IO_DPD2_REQ (0x1C0)
|
||||
#define APBDEV_PMC_IO_DPD2_STATUS (0x1C4)
|
||||
#define APBDEV_PMC_SEL_DPD_TIM (0x1C8)
|
||||
#define APBDEV_PMC_SCRATCH45 (0x234)
|
||||
#define APBDEV_PMC_SCRATCH46 (0x238)
|
||||
#define APBDEV_PMC_TSC_MULT (0x2B4)
|
||||
#define APBDEV_PMC_WEAK_BIAS (0x2C8)
|
||||
#define APBDEV_PMC_GPU_RG_CNTRL (0x2D4)
|
||||
|
|
|
@ -145,12 +145,17 @@ namespace ams::pmic {
|
|||
u8 cnfg = i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1);
|
||||
|
||||
/* Set SlpEn. */
|
||||
cnfg |= (1 << 2);
|
||||
cnfg |= MAX77620_ONOFFCNFG1_SLPEN;
|
||||
|
||||
/* Write the new cfg. */
|
||||
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1, cnfg);
|
||||
}
|
||||
|
||||
void PowerOff() {
|
||||
/* Write power-off to onoff cfg. */
|
||||
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Pmic, Max77620RegisterOnOffCnfg1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
}
|
||||
|
||||
bool IsAcOk() {
|
||||
return (GetPmicOnOffStat() & (1 << 1)) != 0;
|
||||
}
|
||||
|
|
60
libraries/libexosphere/source/rtc/max77620-rtc.h
Normal file
60
libraries/libexosphere/source/rtc/max77620-rtc.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
|
||||
*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _MFD_MAX77620_RTC_H_
|
||||
#define _MFD_MAX77620_RTC_H_
|
||||
|
||||
#define MAX77620_RTC_I2C_ADDR 0x68
|
||||
|
||||
#define MAX77620_RTC_NR_TIME_REGS 7
|
||||
|
||||
#define MAX77620_RTC_CONTROLM_REG 0x02
|
||||
#define MAX77620_RTC_CONTROL_REG 0x03
|
||||
#define MAX77620_RTC_BIN_FORMAT (1 << 0)
|
||||
#define MAX77620_RTC_24H (1 << 1)
|
||||
|
||||
#define MAX77620_RTC_UPDATE0_REG 0x04
|
||||
#define MAX77620_RTC_WRITE_UPDATE (1 << 0)
|
||||
#define MAX77620_RTC_READ_UPDATE (1 << 4)
|
||||
|
||||
#define MAX77620_RTC_SEC_REG 0x07
|
||||
#define MAX77620_RTC_MIN_REG 0x08
|
||||
#define MAX77620_RTC_HOUR_REG 0x09
|
||||
#define MAX77620_RTC_HOUR_PM_MASK (1 << 6)
|
||||
#define MAX77620_RTC_WEEKDAY_REG 0x0A
|
||||
#define MAX77620_RTC_MONTH_REG 0x0B
|
||||
#define MAX77620_RTC_YEAR_REG 0x0C
|
||||
#define MAX77620_RTC_DATE_REG 0x0D
|
||||
|
||||
#define MAX77620_ALARM1_SEC_REG 0x0E
|
||||
#define MAX77620_ALARM1_MIN_REG 0x0F
|
||||
#define MAX77620_ALARM1_HOUR_REG 0x10
|
||||
#define MAX77620_ALARM1_WEEKDAY_REG 0x11
|
||||
#define MAX77620_ALARM1_MONTH_REG 0x12
|
||||
#define MAX77620_ALARM1_YEAR_REG 0x13
|
||||
#define MAX77620_ALARM1_DATE_REG 0x14
|
||||
#define MAX77620_ALARM2_SEC_REG 0x15
|
||||
#define MAX77620_ALARM2_MIN_REG 0x16
|
||||
#define MAX77620_ALARM2_HOUR_REG 0x17
|
||||
#define MAX77620_ALARM2_WEEKDAY_REG 0x18
|
||||
#define MAX77620_ALARM2_MONTH_REG 0x19
|
||||
#define MAX77620_ALARM2_YEAR_REG 0x1A
|
||||
#define MAX77620_ALARM2_DATE_REG 0x1B
|
||||
#define MAX77620_RTC_ALARM_EN_MASK (1 << 7)
|
||||
|
||||
#endif /* _MFD_MAX77620_RTC_H_ */
|
65
libraries/libexosphere/source/rtc/rtc_api.cpp
Normal file
65
libraries/libexosphere/source/rtc/rtc_api.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 <exosphere.hpp>
|
||||
#include "max77620-rtc.h"
|
||||
|
||||
namespace ams::rtc {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline int I2cAddressMax77620Rtc = 0x68;
|
||||
|
||||
/* TODO: Find datasheet, link to it instead. */
|
||||
/* NOTE: Tentatively, Max77620 "mostly" matches https://datasheets.maximintegrated.com/en/ds/MAX77863.pdf. */
|
||||
constexpr inline int Max77620RtcRegisterUpdate0 = 0x04;
|
||||
|
||||
constexpr inline int Max77620RtcRegisterAlarmStart = 0x0E;
|
||||
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Sec = 0x0E;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Min = 0x0F;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Hour = 0x10;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Weekday = 0x11;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Month = 0x12;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Year = 0x13;
|
||||
constexpr inline int Max77620RtcRegisterAlarm1Date = 0x14;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Sec = 0x15;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Min = 0x16;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Hour = 0x17;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Weekday = 0x18;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Month = 0x19;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Year = 0x1A;
|
||||
constexpr inline int Max77620RtcRegisterAlarm2Date = 0x1B;
|
||||
|
||||
constexpr inline int Max77620RtcRegisterAlarmLast = 0x1B;
|
||||
|
||||
}
|
||||
|
||||
void StopAlarm() {
|
||||
/* Begin update. */
|
||||
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Rtc, Max77620RtcRegisterUpdate0, MAX77620_RTC_READ_UPDATE);
|
||||
|
||||
/* Clear ALARM_EN for all alarm registers. */
|
||||
for (auto reg = Max77620RtcRegisterAlarmStart; reg <= Max77620RtcRegisterAlarmLast; ++reg) {
|
||||
u8 val = i2c::QueryByte(i2c::Port_5, I2cAddressMax77620Rtc, reg);
|
||||
val &= ~MAX77620_RTC_ALARM_EN_MASK;
|
||||
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Rtc, reg, val);
|
||||
}
|
||||
|
||||
/* End update. */
|
||||
i2c::SendByte(i2c::Port_5, I2cAddressMax77620Rtc, Max77620RtcRegisterUpdate0, MAX77620_RTC_WRITE_UPDATE);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue