hocclk: add bpmpfw loading
This commit is contained in:
1 parent
7fea98a72d
commit
bd468f087d
14 files changed
+522
-3
No files matched your search
@@ -0,0 +1,44 @@
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
TARGET := bpmpfw
|
||||
BUILDDIR := build
|
||||
OUTPUTDIR := out
|
||||
SOURCEDIR := source
|
||||
|
||||
OBJS := $(BUILDDIR)/start.o $(BUILDDIR)/main.o
|
||||
|
||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
||||
CXXFLAGS := $(ARCH) -O2 -g -ffreestanding -nostdlib -fno-exceptions -fno-rtti \
|
||||
-fno-unwind-tables -fno-threadsafe-statics -ffunction-sections -fdata-sections \
|
||||
-fomit-frame-pointer -std=gnu++20 -Wall -Wextra $(CUSTOMDEFINES)
|
||||
ASFLAGS := $(ARCH) -g
|
||||
LDFLAGS := $(ARCH) -nostartfiles -nodefaultlibs -Wl,--nmagic,--gc-sections \
|
||||
-T $(SOURCEDIR)/../bpmpfw.ld -lgcc
|
||||
|
||||
BIN_TARGET := $(OUTPUTDIR)/$(TARGET).bin
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BIN_TARGET)
|
||||
|
||||
$(BIN_TARGET): $(BUILDDIR)/$(TARGET).elf
|
||||
@mkdir -p $(OUTPUTDIR)
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(BUILDDIR)/$(TARGET).elf: $(OBJS)
|
||||
@$(CXX) $(LDFLAGS) $(OBJS) -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.cpp | $(BUILDDIR)
|
||||
@$(CXX) $(CXXFLAGS) -I$(SOURCEDIR) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: $(SOURCEDIR)/%.s | $(BUILDDIR)
|
||||
@$(CXX) $(ASFLAGS) -I$(SOURCEDIR) -c $< -o $@
|
||||
|
||||
$(BUILDDIR):
|
||||
@mkdir -p $(BUILDDIR)
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILDDIR) $(OUTPUTDIR)
|
||||
@@ -0,0 +1,151 @@
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(reset)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
bpmpfw : ORIGIN = 0x40004000, LENGTH = 32K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__start__ = ORIGIN(bpmpfw));
|
||||
. = __start__;
|
||||
__code_start = . ;
|
||||
|
||||
.vectors :
|
||||
{
|
||||
KEEP (*(.vectors .vectors.*))
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
. = ALIGN(8);
|
||||
__rodata_start = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
} >bpmpfw
|
||||
|
||||
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >bpmpfw
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >bpmpfw
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >bpmpfw
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >bpmpfw
|
||||
|
||||
.hash : { *(.hash) } >bpmpfw
|
||||
|
||||
. = ALIGN(8);
|
||||
__data_start = . ;
|
||||
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >bpmpfw
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >bpmpfw
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >bpmpfw
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >bpmpfw
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >bpmpfw
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >bpmpfw
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >bpmpfw
|
||||
|
||||
.ctors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >bpmpfw
|
||||
|
||||
.dtors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >bpmpfw
|
||||
|
||||
__got_start__ = .;
|
||||
|
||||
.got : { *(.got) *(.igot) } >bpmpfw
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) } >bpmpfw
|
||||
|
||||
__got_end__ = .;
|
||||
|
||||
.data ALIGN(8) :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
} >bpmpfw
|
||||
|
||||
__bss_start__ = .;
|
||||
.bss ALIGN(8) :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(16);
|
||||
} >bpmpfw
|
||||
__bss_end__ = .;
|
||||
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
__stack_top = ORIGIN(bpmpfw) + LENGTH(bpmpfw) - 0x10;
|
||||
|
||||
/DISCARD/ : { *(.group .comment .note .interp .ARM.attributes) }
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
#include "regs.hpp"
|
||||
|
||||
extern "C" void main() {
|
||||
UartPuts("[bpmpfw]: Hello from BPMP-FW\n");
|
||||
|
||||
for (;;) {
|
||||
FlowCtlrHaltUsec(200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
|
||||
#define MMIO32(addr) (*reinterpret_cast<volatile u32 *>(addr))
|
||||
|
||||
constexpr u32 FlowCtlrBase = 0x60007000;
|
||||
constexpr u32 FlowCtlrHaltCopEvents = 0x004;
|
||||
|
||||
constexpr u32 HaltModeWaitEvent = (2u << 29);
|
||||
constexpr u32 HaltUsec = (0u << 24);
|
||||
|
||||
inline void FlowCtlrHaltUsec(u32 usec) {
|
||||
MMIO32(FlowCtlrBase + FlowCtlrHaltCopEvents) = HaltModeWaitEvent | HaltUsec | (usec & 0xFFFFFFu);
|
||||
}
|
||||
|
||||
constexpr u32 UartBBase = 0x70006040;
|
||||
constexpr u32 UartThr = 0x00;
|
||||
constexpr u32 UartLsr = 0x14;
|
||||
constexpr u32 UartLsrThre = (1u << 5);
|
||||
|
||||
inline void UartPutc(char c) {
|
||||
while (!(MMIO32(UartBBase + UartLsr) & UartLsrThre))
|
||||
;
|
||||
MMIO32(UartBBase + UartThr) = static_cast<u32>(static_cast<u8>(c));
|
||||
}
|
||||
|
||||
inline void UartPuts(const char *s) {
|
||||
while (*s) {
|
||||
UartPutc(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
inline void UartPutHex32(u32 v) {
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
for (int i = 28; i >= 0; i -= 4) {
|
||||
UartPutc(digits[(v >> i) & 0xF]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
.section .vectors, "ax", %progbits
|
||||
.align 3
|
||||
.global reset
|
||||
reset:
|
||||
b _start
|
||||
b _panic
|
||||
|
||||
.section .text.start, "ax", %progbits
|
||||
.align 3
|
||||
.global _start
|
||||
.extern main
|
||||
_start:
|
||||
/* Mask IRQ + FIQ, enter SVC mode. */
|
||||
msr cpsr_f, #0xC0
|
||||
msr cpsr_cf, #0xD3
|
||||
|
||||
/* Set the stack pointer. */
|
||||
ldr sp, =__stack_top
|
||||
|
||||
/* Zero .bss. */
|
||||
ldr r0, =__bss_start__
|
||||
ldr r1, =__bss_end__
|
||||
mov r2, #0
|
||||
1:
|
||||
cmp r0, r1
|
||||
bge 2f
|
||||
str r2, [r0], #4
|
||||
b 1b
|
||||
2:
|
||||
|
||||
/* Run global constructors. */
|
||||
ldr r4, =__init_array_start
|
||||
ldr r5, =__init_array_end
|
||||
3:
|
||||
cmp r4, r5
|
||||
bge 4f
|
||||
ldr r0, [r4], #4
|
||||
mov lr, pc
|
||||
bx r0
|
||||
b 3b
|
||||
4:
|
||||
|
||||
bl main
|
||||
|
||||
.global _panic
|
||||
_panic:
|
||||
ldr r0, =0x70006040 /* UART_B_BASE */
|
||||
adr r3, _panic_msg
|
||||
7:
|
||||
ldrb r1, [r3], #1
|
||||
cmp r1, #0
|
||||
beq _panic_hang
|
||||
8:
|
||||
ldr r2, [r0, #0x14] /* UART_LSR */
|
||||
tst r2, #0x20 /* UART_LSR_THRE */
|
||||
beq 8b
|
||||
str r1, [r0]
|
||||
b 7b
|
||||
|
||||
_panic_msg:
|
||||
.asciz "[bpmpfw] PANIC\n"
|
||||
.align 2
|
||||
|
||||
_panic_hang:
|
||||
b _panic_hang
|
||||
@@ -42,6 +42,15 @@ mkdir -p "$DIST_DIR/switch/.overlays"
|
||||
cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl"
|
||||
echo
|
||||
|
||||
echo "*** Compiling bpmpfw ***"
|
||||
pushd "$ROOT_DIR/bpmpfw"
|
||||
make -j$CORES
|
||||
popd > /dev/null
|
||||
|
||||
mkdir -p "$DIST_DIR/config/horizon-oc"
|
||||
cp -vf "$ROOT_DIR/bpmpfw/out/bpmpfw.bin" "$DIST_DIR/config/horizon-oc/bpmpfw.bin"
|
||||
echo
|
||||
|
||||
echo "*** Copying assets ***"
|
||||
mkdir -p "$DIST_DIR/config/horizon-oc"
|
||||
cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
|
||||
|
||||
@@ -22,7 +22,7 @@ CONFIG_DIR := horizon-oc
|
||||
BUILD := build
|
||||
OUTDIR := out
|
||||
RESOURCES := res
|
||||
SOURCES := src src/hos src/i2c src/ipc src/board src/display src/tsensor src/mgr src/file src/soc src/mapping src/pwr src/util
|
||||
SOURCES := src src/hos src/i2c src/ipc src/board src/bpmp src/display src/tsensor src/mgr src/file src/soc src/mapping src/pwr src/util
|
||||
DATA := data
|
||||
INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc
|
||||
EXEFS_SRC := exefs_src
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <t210.h>
|
||||
#include <tmp451.h>
|
||||
|
||||
#include "../bpmp/bpmp.hpp"
|
||||
#include "../display/display_refresh_rate.hpp"
|
||||
#include "../file/file_utils.hpp"
|
||||
#include "../hos/apm_ext.h"
|
||||
@@ -52,7 +53,7 @@
|
||||
|
||||
namespace board {
|
||||
|
||||
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
|
||||
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr, sysVirtAddr, actmonVirtAddr;
|
||||
|
||||
HocClkSocType gSocType;
|
||||
u8 gDramID;
|
||||
@@ -153,6 +154,10 @@ namespace board {
|
||||
rc = QueryMemoryMapping(&fuseVirtAddr, 0x7000F000, 0x1000);
|
||||
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (fuse)");
|
||||
|
||||
rc = QueryMemoryMapping(&sysVirtAddr, 0x6000C000, 0x1000);
|
||||
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (sys)");
|
||||
actmonVirtAddr = sysVirtAddr + 0x800;
|
||||
|
||||
FetchHardwareInfos();
|
||||
|
||||
Result nvCheck = 1;
|
||||
@@ -173,6 +178,11 @@ namespace board {
|
||||
|
||||
tsensor::InitializeSoctherm(); // SOCTHERM must be init before AOTAG
|
||||
|
||||
Result bpmpfwRc = bpmp::StartBpmfwExecution();
|
||||
if (R_FAILED(bpmpfwRc)) {
|
||||
fileUtils::LogLine("[bpmp] StartBpmfwExecution failed: 0x%x", bpmpfwRc);
|
||||
}
|
||||
|
||||
// PMC exosphere check
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#define HOSSVC_HAS_TC (hosversionAtLeast(5, 0, 0))
|
||||
|
||||
namespace board {
|
||||
extern u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
|
||||
extern u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr, sysVirtAddr, actmonVirtAddr;
|
||||
extern HocClkSocType gSocType;
|
||||
extern u8 gDramID;
|
||||
extern HocClkConsoleType gConsoleType;
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
|
||||
*
|
||||
* 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 <cstdio>
|
||||
#include <cstring>
|
||||
#include <switch.h>
|
||||
|
||||
#include "../board/board.hpp"
|
||||
#include "../file/file_utils.hpp"
|
||||
#include "../mapping/mem_map.hpp"
|
||||
#include "bpmp.hpp"
|
||||
|
||||
namespace bpmp {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u64 FlowCtlrPhysBase = 0x60007000;
|
||||
constexpr u64 EvpPhysBase = 0x6000F000;
|
||||
|
||||
constexpr u32 ClkRstRstDevLSet = 0x300;
|
||||
constexpr u32 ClkRstRstDevLClr = 0x304;
|
||||
constexpr u32 RstDevLCopRstBit = (1u << 1); /* SWR_COP_RST */
|
||||
|
||||
constexpr u32 ApbMiscSlaveSecurityReg0 = 0xC00;
|
||||
constexpr u32 ApbMiscSlaveSecurityReg1 = 0xC04;
|
||||
constexpr u32 ApbMiscSlaveSecurityReg2 = 0xC08;
|
||||
|
||||
/* Relative to actmonVirtAddr */
|
||||
constexpr u32 ActmonCopCtrl = 0xC0;
|
||||
constexpr u32 ActmonCopIntrStatus = 0xE4;
|
||||
|
||||
constexpr u32 EvpCopResetVector = 0x200;
|
||||
constexpr u32 EvpCopUndefVector = 0x204;
|
||||
constexpr u32 EvpCopSwiVector = 0x208;
|
||||
constexpr u32 EvpCopPrefetchAbortVector = 0x20C;
|
||||
constexpr u32 EvpCopDataAbortVector = 0x210;
|
||||
constexpr u32 EvpCopRsvdVector = 0x214;
|
||||
constexpr u32 EvpCopIrqVector = 0x218;
|
||||
constexpr u32 EvpCopFiqVector = 0x21C;
|
||||
|
||||
constexpr u32 FlowCtlrHaltCopEvents = 0x004;
|
||||
constexpr u32 FlowModeNone = 0x00000000;
|
||||
|
||||
constexpr u64 FwIramPhysBase = 0x40004000;
|
||||
constexpr u32 FwStagingSize = 0x8000;
|
||||
|
||||
alignas(4096) u8 s_fwStageBuf[FwStagingSize];
|
||||
|
||||
inline volatile u32 &Mmio(u64 base_va, u32 offset) {
|
||||
return *reinterpret_cast<volatile u32 *>(base_va + offset);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Result StartBpmfwExecution() {
|
||||
if (!IsPatchedExosphere()) {
|
||||
fileUtils::LogLine("[bpmp] Cannot start without patched exosphere");
|
||||
return (Result)1;
|
||||
}
|
||||
|
||||
std::memset(s_fwStageBuf, 0, sizeof(s_fwStageBuf));
|
||||
|
||||
FILE *f = fopen("sdmc:/config/horizon-oc/bpmpfw.bin", "rb");
|
||||
if (!f) {
|
||||
fileUtils::LogLine("[bpmp] StartBpmfwExecution: bpmpfw.bin not found");
|
||||
return (Result)1;
|
||||
}
|
||||
|
||||
const size_t fw_size = fread(s_fwStageBuf, 1, sizeof(s_fwStageBuf), f);
|
||||
fclose(f);
|
||||
|
||||
if (fw_size == 0) {
|
||||
fileUtils::LogLine("[bpmp] StartBpmfwExecution: bpmpfw.bin is empty");
|
||||
return (Result)1;
|
||||
}
|
||||
|
||||
fileUtils::LogLine("[bpmp] StartBpmfwExecution: loaded %zu bytes, loading at 0x%llx",
|
||||
fw_size, static_cast<unsigned long long>(FwIramPhysBase));
|
||||
|
||||
/* Set BPMP reset */
|
||||
Mmio(board::clkVirtAddr, ClkRstRstDevLSet) = RstDevLCopRstBit;
|
||||
|
||||
/* Grant BPMP access to all a bunch of registers that are useful */
|
||||
Mmio(board::apbVirtAddr, ApbMiscSlaveSecurityReg0) = 0;
|
||||
Mmio(board::apbVirtAddr, ApbMiscSlaveSecurityReg1) = 0;
|
||||
Mmio(board::apbVirtAddr, ApbMiscSlaveSecurityReg2) = 0;
|
||||
|
||||
/* Set up exeption vectors for bpmp */
|
||||
const u32 fw_reset_vector = static_cast<u32>(FwIramPhysBase + 0x0);
|
||||
const u32 fw_panic_vector = static_cast<u32>(FwIramPhysBase + 0x4);
|
||||
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopResetVector, 0xFFFFFFFF, fw_reset_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopUndefVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopSwiVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopPrefetchAbortVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopDataAbortVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopRsvdVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopIrqVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
SmcReadWriteRegister(EvpPhysBase + EvpCopFiqVector, 0xFFFFFFFF, fw_panic_vector);
|
||||
|
||||
/* Disable actmon monitoring to avoid hang on FW >4.0.0 */
|
||||
Mmio(board::actmonVirtAddr, ActmonCopCtrl) = 0;
|
||||
Mmio(board::actmonVirtAddr, ActmonCopIntrStatus) = Mmio(board::actmonVirtAddr, ActmonCopIntrStatus);
|
||||
|
||||
/* Load the BPMPFW into iram per page. TODO: determine if this is nessesary */
|
||||
constexpr size_t PageSize = 4096;
|
||||
for (size_t ofs = 0; ofs < fw_size; ofs += PageSize) {
|
||||
const size_t chunk = (fw_size - ofs) < PageSize ? (fw_size - ofs) : PageSize;
|
||||
|
||||
Result copy_rc = SmcCopyToIram(FwIramPhysBase + ofs, s_fwStageBuf + ofs, static_cast<u32>(chunk));
|
||||
if (R_FAILED(copy_rc)) {
|
||||
fileUtils::LogLine("[bpmp] SmcCopyToIram failed at +0x%zx: 0x%x", ofs, copy_rc);
|
||||
return copy_rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear BPMP reset. */
|
||||
Mmio(board::clkVirtAddr, ClkRstRstDevLClr) = RstDevLCopRstBit;
|
||||
|
||||
/* Clear the halt written by bootloader. */
|
||||
SmcReadWriteRegister(FlowCtlrPhysBase + FlowCtlrHaltCopEvents, 0xFFFFFFFF, FlowModeNone);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace bpmp
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Souldbminer, Lightos and Horizon OC Contributors
|
||||
*
|
||||
* 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 <switch.h>
|
||||
|
||||
namespace bpmp {
|
||||
Result StartBpmfwExecution();
|
||||
}
|
||||
@@ -65,4 +65,28 @@ Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size) {
|
||||
rc = (26u | ((u32)args.X[0] << 9u));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool IsPatchedExosphere() {
|
||||
constexpr u64 EvpPhysBase = 0x6000F000;
|
||||
constexpr u64 EvpCopResetVector = 0x200;
|
||||
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = EvpPhysBase + EvpCopResetVector;
|
||||
args.X[2] = 0;
|
||||
args.X[3] = 0;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return args.X[0] == 0;
|
||||
}
|
||||
|
||||
u32 SmcReadWriteRegister(u64 phys_addr, u32 mask, u32 value) {
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = phys_addr;
|
||||
args.X[2] = mask;
|
||||
args.X[3] = value;
|
||||
svcCallSecureMonitor(&args);
|
||||
return (u32)args.X[1];
|
||||
}
|
||||
@@ -22,3 +22,5 @@ Result QueryMemoryMapping(u64 *virtaddr, u64 physaddr, u64 size);
|
||||
Result MapAddress(u64 &va, const u64 &physAddr, const char *name);
|
||||
Result SmcCopyFromIram(void *dest, uintptr_t src, u32 size);
|
||||
Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size);
|
||||
bool IsPatchedExosphere();
|
||||
u32 SmcReadWriteRegister(u64 phys_addr, u32 mask, u32 value);
|
||||
Reference in new issue
Block a user