mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-15 23:54:24 -04:00
fusee-cpp: add basic structural stubs
This commit is contained in:
parent
165c926135
commit
5f60bc7186
21 changed files with 1280 additions and 2 deletions
47
fusee_cpp/loader_stub/source/fusee_loader_error.cpp
Normal file
47
fusee_cpp/loader_stub/source/fusee_loader_error.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 "fusee_loader_error.hpp"
|
||||
|
||||
namespace ams::diag {
|
||||
|
||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
|
||||
AMS_UNUSED(file, line, func, expr, value, format);
|
||||
ams::nxboot::loader::ErrorStop();
|
||||
}
|
||||
|
||||
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
|
||||
AMS_UNUSED(file, line, func, expr, value);
|
||||
ams::nxboot::loader::ErrorStop();
|
||||
}
|
||||
|
||||
NORETURN void AbortImpl() {
|
||||
ams::nxboot::loader::ErrorStop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::nxboot::loader {
|
||||
|
||||
NORETURN void ErrorStop() {
|
||||
/* Halt ourselves. */
|
||||
while (true) {
|
||||
reg::Write(secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress() + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
||||
FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, ENABLED));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
23
fusee_cpp/loader_stub/source/fusee_loader_error.hpp
Normal file
23
fusee_cpp/loader_stub/source/fusee_loader_error.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/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#pragma once
|
||||
|
||||
namespace ams::nxboot::loader {
|
||||
|
||||
NORETURN void ErrorStop();
|
||||
|
||||
}
|
61
fusee_cpp/loader_stub/source/fusee_loader_main.cpp
Normal file
61
fusee_cpp/loader_stub/source/fusee_loader_main.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 "fusee_loader_uncompress.hpp"
|
||||
#include "program_lz4.h"
|
||||
|
||||
namespace ams::nxboot::loader {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uintptr_t ProgramImageBase = 0x40001000;
|
||||
constexpr uintptr_t ProgramImageEnd = 0x4003D000;
|
||||
constexpr size_t ProgramImageSizeMax = ProgramImageEnd - ProgramImageBase;
|
||||
|
||||
void CopyBackwards(void *dst, const void *src, size_t size) {
|
||||
/* We want to copy 32-bits at a time from destination to source. */
|
||||
const size_t words = util::DivideUp(size, sizeof(u32));
|
||||
|
||||
/* Convert to 32-bit pointers. */
|
||||
u32 *dst_32 = static_cast<u32 *>(dst) + words;
|
||||
const u32 *src_32 = static_cast<const u32 *>(src) + words;
|
||||
|
||||
/* Copy data. */
|
||||
for (size_t i = 0; i < words; ++i) {
|
||||
*(--dst_32) = *(--src_32);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NORETURN void UncompressAndExecute(const void *program, size_t program_size) {
|
||||
/* Relocate the compressed binary to a place where we can safely decompress it. */
|
||||
void *relocated_program = reinterpret_cast<void *>(util::AlignDown(ProgramImageEnd - program_size, sizeof(u32)));
|
||||
if (relocated_program != program) {
|
||||
CopyBackwards(relocated_program, program, program_size);
|
||||
}
|
||||
|
||||
/* Uncompress the program image. */
|
||||
Uncompress(reinterpret_cast<void *>(ProgramImageBase), ProgramImageSizeMax, relocated_program, program_size);
|
||||
|
||||
/* Jump to the boot image. */
|
||||
reinterpret_cast<void (*)()>(ProgramImageBase)();
|
||||
|
||||
/* We will never reach this point. */
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
59
fusee_cpp/loader_stub/source/fusee_loader_start.s
Normal file
59
fusee_cpp/loader_stub/source/fusee_loader_start.s
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
.section .crt0._ZN3ams6nxboot6loader5StartEv, "ax", %progbits
|
||||
.arm
|
||||
.align 5
|
||||
.global _ZN3ams6nxboot6loader5StartEv
|
||||
.type _ZN3ams6nxboot6loader5StartEv, %function
|
||||
_ZN3ams6nxboot6loader5StartEv:
|
||||
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||
msr cpsr_cxsf, #0xDF
|
||||
|
||||
/* Relocate loader stub. */
|
||||
ldr r0, =_ZN3ams6nxboot6loader5StartEv
|
||||
adr r1, _ZN3ams6nxboot6loader5StartEv
|
||||
ldr r2, =__loader_stub_lma__
|
||||
sub r2, r2, r0
|
||||
add r2, r2, r1
|
||||
|
||||
ldr r3, =__loader_stub_start__
|
||||
ldr r4, =__loader_stub_end__
|
||||
sub r4, r4, r3
|
||||
0:
|
||||
ldmia r2!, {r5-r12}
|
||||
stmia r3!, {r5-r12}
|
||||
subs r4, #0x20
|
||||
bne 0b
|
||||
|
||||
/* Set the stack pointer */
|
||||
ldr sp, =0x40001000
|
||||
mov fp, #0
|
||||
|
||||
/* Generate arguments. */
|
||||
ldr r3, =program_lz4
|
||||
ldr r4, =program_lz4_end
|
||||
sub r4, r4, r3
|
||||
sub r3, r3, r0
|
||||
add r3, r3, r1
|
||||
mov r0, r3
|
||||
mov r1, r4
|
||||
|
||||
/* Jump to the loader stub. */
|
||||
ldr r3, =_ZN3ams6nxboot6loader20UncompressAndExecuteEPKvj
|
||||
bx r3
|
103
fusee_cpp/loader_stub/source/fusee_loader_uncompress.cpp
Normal file
103
fusee_cpp/loader_stub/source/fusee_loader_uncompress.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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 "fusee_loader_uncompress.hpp"
|
||||
|
||||
namespace ams::nxboot::loader {
|
||||
|
||||
namespace {
|
||||
|
||||
class Lz4Uncompressor {
|
||||
private:
|
||||
const u8 *src;
|
||||
size_t src_size;
|
||||
size_t src_offset;
|
||||
u8 *dst;
|
||||
size_t dst_size;
|
||||
size_t dst_offset;
|
||||
public:
|
||||
Lz4Uncompressor(void *dst, size_t dst_size, const void *src, size_t src_size) : src(static_cast<const u8 *>(src)), src_size(src_size), src_offset(0), dst(static_cast<u8 *>(dst)), dst_size(dst_size), dst_offset(0) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void Uncompress() {
|
||||
while (true) {
|
||||
/* Read a control byte. */
|
||||
const u8 control = this->ReadByte();
|
||||
|
||||
/* Copy what it specifies we should copy. */
|
||||
this->Copy(this->GetCopySize(control >> 4));
|
||||
|
||||
/* If we've exceeded size, we're done. */
|
||||
if (this->src_offset >= this->src_size) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the wide copy offset. */
|
||||
u16 wide_offset = this->ReadByte();
|
||||
AMS_ABORT_UNLESS(this->CanRead());
|
||||
wide_offset |= (this->ReadByte() << 8);
|
||||
|
||||
/* Determine the copy size. */
|
||||
const size_t wide_copy_size = this->GetCopySize(control & 0xF);
|
||||
|
||||
/* Copy bytes. */
|
||||
const size_t end_offset = this->dst_offset + wide_copy_size + 4;
|
||||
for (size_t cur_offset = this->dst_offset; cur_offset < end_offset; this->dst_offset = (++cur_offset)) {
|
||||
AMS_ABORT_UNLESS(wide_offset <= cur_offset);
|
||||
|
||||
this->dst[cur_offset] = this->dst[cur_offset - wide_offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
u8 ReadByte() {
|
||||
return this->src[this->src_offset++];
|
||||
}
|
||||
|
||||
bool CanRead() const {
|
||||
return this->src_offset < this->src_size;
|
||||
}
|
||||
|
||||
size_t GetCopySize(u8 control) {
|
||||
size_t size = control;
|
||||
|
||||
if (control >= 0xF) {
|
||||
do {
|
||||
AMS_ABORT_UNLESS(this->CanRead());
|
||||
control = this->ReadByte();
|
||||
size += control;
|
||||
} while (control == 0xFF);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void Copy(size_t size) {
|
||||
__builtin_memcpy(this->dst + this->dst_offset, this->src + this->src_offset, size);
|
||||
this->dst_offset += size;
|
||||
this->src_offset += size;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void Uncompress(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||
/* Create an execute a decompressor. */
|
||||
Lz4Uncompressor(dst, dst_size, src, src_size).Uncompress();
|
||||
}
|
||||
|
||||
}
|
23
fusee_cpp/loader_stub/source/fusee_loader_uncompress.hpp
Normal file
23
fusee_cpp/loader_stub/source/fusee_loader_uncompress.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/>.
|
||||
*/
|
||||
#include <vapours.hpp>
|
||||
#pragma once
|
||||
|
||||
namespace ams::nxboot::loader {
|
||||
|
||||
void Uncompress(void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue