Merge remote-tracking branch 'devdl11/upsilon-dev-1.0.1.01fix' into upsilon-dev

This commit is contained in:
Yaya-Cout
2024-12-27 19:01:17 +01:00
21 changed files with 273 additions and 18 deletions

View File

@@ -37,6 +37,7 @@ bootloader_src += $(addprefix bootloader/interface/menus/, \
warning.cpp \
slot_recovery.cpp \
crash.cpp \
upsilon_recovery.cpp \
)
bootloader_images = $(addprefix bootloader/, \

View File

@@ -63,7 +63,7 @@ bool Boot::isKernelPatched(const Slot & s) {
return *(uint32_t *)(origin_isr + sizeof(uint32_t) * 7) == ((uint32_t)&_fake_isr_function_start) + 1;
}
__attribute((section(".fake_isr_function"))) __attribute__((used)) void Boot::flash_interrupt() {
__attribute__((section(".fake_isr_function"))) __attribute__((used)) void Boot::flash_interrupt() {
// a simple function
Ion::Device::Flash::ClearInternalFlashErrors();
asm("bx lr");

View File

@@ -47,7 +47,7 @@ public:
static void bootSlot(Bootloader::Slot slot);
static void bootSelectedSlot();
__attribute__ ((noreturn)) static void jumpToInternalBootloader();
__attribute((section(".fake_isr_function"))) __attribute__((used)) static void flash_interrupt();
__attribute__ ((section(".fake_isr_function"))) __attribute__((used)) static void flash_interrupt();
static void bootloader();
static void lockInternal();

View File

@@ -0,0 +1,48 @@
#include "upsilon_recovery.h"
#include <bootloader/slots/slot.h>
#include <bootloader/usb_data.h>
#include <ion/src/device/shared/drivers/board.h>
#include <ion.h>
#include <stdlib.h>
extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
Bootloader::UpsilonRecoveryMenu::UpsilonRecoveryMenu() : Menu(KDColorBlack, KDColorWhite, Messages::upsilonRecoveryTitle, Messages::mainTitle) {
setup();
}
void Bootloader::UpsilonRecoveryMenu::setup() {
m_defaultColumns[0] = Column(Messages::upsilonRecoveryMessage1, k_small_font, 0, true);
m_defaultColumns[1] = Column(Messages::upsilonRecoveryMessage2, k_small_font, 0, true);
m_defaultColumns[2] = Column(Messages::upsilonRecoveryMessage3, k_small_font, 0, true);
m_defaultColumns[3] = Column(Messages::upsilonRecoveryMessage4, k_small_font, 0, true);
m_defaultColumns[4] = Column(Messages::upsilonRecoveryMessage5, k_small_font, 0, true);
m_columns[0] = ColumnBinder(&m_defaultColumns[0]);
m_columns[1] = ColumnBinder(&m_defaultColumns[1]);
m_columns[2] = ColumnBinder(&m_defaultColumns[2]);
m_columns[3] = ColumnBinder(&m_defaultColumns[3]);
m_columns[4] = ColumnBinder(&m_defaultColumns[4]);
}
void Bootloader::UpsilonRecoveryMenu::postOpen() {
// We override the open method
for (;;) {
uint64_t scan = Ion::Keyboard::scan();
if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) {
while (Ion::Keyboard::scan() == Ion::Keyboard::State(Ion::Keyboard::Key::Back));
forceExit();
return;
} else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) {
Ion::Power::suspend();
return;
} else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OK)) {
Slot slot = Slot::Upsilon();
Ion::Device::Board::bootloaderMPU();
// Deinitialize the backlight to prevent bugs when the firmware boots
Ion::Backlight::shutdown();
jump_to_firmware(slot.kernelHeader()->stackPointer(), slot.userlandHeader()->upsilonRecoveryBootFunction());
for(;;);
}
}
}

View File

@@ -0,0 +1,15 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_UPSILON_RECOVERY_H_
#define _BOOTLOADER_INTERFACE_MENUS_UPSILON_RECOVERY_H_
#include <bootloader/interface/src/menu.h>
namespace Bootloader {
class UpsilonRecoveryMenu : public Menu {
public:
UpsilonRecoveryMenu();
void setup() override;
void postOpen() override;
};
}
#endif

View File

@@ -53,6 +53,15 @@ public:
constexpr static const char * recoveryMessage4 = "Press Back to continue.";
constexpr static const char * recoveryMessage5 = "(you will not be able to recover your data !)";
// Upsilon Recovery menu
constexpr static const char * upsilonRecoveryTitle = "Upsilon Recovery";
constexpr static const char * upsilonRecoveryMessage1 = "The bootloader has detected a crash.";
constexpr static const char * upsilonRecoveryMessage2 = "Because you also have an Upsilon slot,";
constexpr static const char * upsilonRecoveryMessage3 = "you can recover your data by booting";
constexpr static const char * upsilonRecoveryMessage4 = "the Upsilon slot.";
constexpr static const char * upsilonRecoveryMessage5 = "Press OK to continue, BACK to cancel";
// Warning menu
constexpr static const char * epsilonWarningTitle = "Epsilon Slot";

View File

@@ -1,6 +1,7 @@
#include <bootloader/recovery.h>
#include <ion.h>
#include <ion/src/device/n0110/drivers/power.h>
#include <ion/src/device/shared/drivers/bldata.h>
#include <ion/src/device/shared/drivers/reset.h>
#include <ion/src/device/shared/drivers/board.h>
#include <assert.h>
@@ -10,6 +11,7 @@
#include <bootloader/usb_data.h>
#include <bootloader/interface/menus/slot_recovery.h>
#include <bootloader/interface/menus/crash.h>
#include <bootloader/interface/menus/upsilon_recovery.h>
constexpr static uint32_t MagicStorage = 0xEE0BDDBA;
@@ -76,7 +78,15 @@ void Bootloader::Recovery::recoverData() {
Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite);
Ion::Backlight::init();
USBData udata = USBData::Recovery((uint32_t)getSlotConcerned().getStorageAddress(), (uint32_t)getSlotConcerned().getStorageSize());
CrashedSlot slot = getSlotConcerned();
if (Slot::hasUpsilon() && Slot::Upsilon().userlandHeader()->hasUpsilonExtras()) {
Ion::Device::BootloaderSharedData::sharedBootloaderData()->setRecovery((uint32_t)slot.getStorageAddress(), slot.getStorageSize());
UpsilonRecoveryMenu reco = UpsilonRecoveryMenu();
reco.open();
}
USBData udata = USBData::Recovery((uint32_t)slot.getStorageAddress(), (uint32_t)slot.getStorageSize());
SlotRecoveryMenu menu = SlotRecoveryMenu(&udata);
menu.open();

View File

@@ -3,6 +3,8 @@
#include <ion/src/device/shared/drivers/flash.h>
#include <ion/src/device/shared/drivers/external_flash.h>
#include <bootloader/boot.h>
#include <assert.h>
#include <ion.h>
extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
@@ -20,6 +22,15 @@ const Slot Slot::Khi() {
return Slot(0x90180000);
}
const bool Slot::hasUpsilon() {
return (isFullyValid(A()) && A().userlandHeader()->isUpsilon()) || (isFullyValid(B()) && B().userlandHeader()->isUpsilon());
}
const Slot Slot::Upsilon() {
assert(hasUpsilon());
return (isFullyValid(A()) && A().userlandHeader()->isUpsilon()) ? A() : B();
}
const KernelHeader* Slot::kernelHeader() const {
return m_kernelHeader;
}
@@ -65,6 +76,9 @@ const UserlandHeader* Slot::userlandHeader() const {
// Configure the MPU for the booted firmware
Ion::Device::Board::bootloaderMPU();
// Deinitialize the backlight to prevent bugs when the firmware boots
Ion::Backlight::shutdown();
// Jump
jump_to_firmware(kernelHeader()->stackPointer(), kernelHeader()->startPointer());
for(;;);

View File

@@ -25,6 +25,8 @@ public:
static const Slot A();
static const Slot B();
static const Slot Khi();
static const bool hasUpsilon();
static const Slot Upsilon();
static bool isFullyValid(const Slot& slot) {
return slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid();

View File

@@ -40,4 +40,16 @@ const size_t UserlandHeader::storageSize() const {
return m_storageSizeRAM;
}
const bool UserlandHeader::hasUpsilonExtras() const {
return m_upsilonExtraMagicHeader == UpsilonExtraMagic && m_upsilonExtraMagicFooter == UpsilonExtraMagic;
}
const uint16_t UserlandHeader::getExtraVersion() const {
return m_extraVersion;
}
const void (*UserlandHeader::upsilonRecoveryBootFunction() const)() {
return m_recoveryAddress;
}
}

View File

@@ -17,12 +17,17 @@ public:
const char * upsilonVersion() const;
const void * storageAddress() const;
const size_t storageSize() const;
const bool hasUpsilonExtras() const;
const void (*upsilonRecoveryBootFunction() const)();
const uint32_t getExtraVersion() const;
private:
UserlandHeader();
constexpr static uint32_t Magic = 0xDEC0EDFE;
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
constexpr static uint32_t UpsilonMagic = 0x55707369;
constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
uint32_t m_header;
const char m_expectedEpsilonVersion[8];
void * m_storageAddressRAM;
@@ -42,6 +47,10 @@ private:
const char m_UpsilonVersion[16];
uint32_t m_osType;
uint32_t m_upsilonMagicFooter;
uint32_t m_upsilonExtraMagicHeader;
const void (*m_recoveryAddress)();
uint32_t m_extraVersion;
uint32_t m_upsilonExtraMagicFooter;
};
extern const UserlandHeader* s_userlandHeaderA;

View File

@@ -1,11 +1,15 @@
#include <stdint.h>
#include <string.h>
#include <ion.h>
#include <ion/led.h>
#include <ion/storage.h>
#include <ion/internal_storage.h>
#include <boot/isr.h>
#include <drivers/board.h>
#include <drivers/rtc.h>
#include <drivers/reset.h>
#include <drivers/timing.h>
#include <drivers/bldata.h>
typedef void (*cxx_constructor)();
@@ -14,6 +18,8 @@ extern "C" {
extern char _data_section_start_ram;
extern char _data_section_end_ram;
extern char _bss_section_start_ram;
extern char _static_storage_start;
extern char _static_storage_end;
extern char _bss_section_end_ram;
extern cxx_constructor _init_array_start;
extern cxx_constructor _init_array_end;
@@ -129,6 +135,45 @@ void __attribute__((noinline)) start() {
abort();
}
void __attribute__((noinline)) __attribute__((section(".recovery_boot"))) __attribute__((used)) recovery_start() {
// Here we are in the recovery boot.
Ion::Device::Board::initFPU();
bool is_recoverying = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageAddress() != 0;
if (is_recoverying) {
uint32_t address = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageAddress();
uint32_t size = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageSize();
size_t storageSize = (&_static_storage_end - &_static_storage_start);
memcpy(&_static_storage_start, (void*)address, size);
size_t dataSectionLength = (&_data_section_end_ram - &_data_section_start_ram);
memcpy(&_data_section_start_ram, &_data_section_start_flash, dataSectionLength);
size_t bssSectionLength = (&_bss_section_end_ram - &_static_storage_end);
memset(&_static_storage_end, 0, bssSectionLength);
} else {
size_t dataSectionLength = (&_data_section_end_ram - &_data_section_start_ram);
memcpy(&_data_section_start_ram, &_data_section_start_flash, dataSectionLength);
size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram);
memset(&_bss_section_start_ram, 0, bssSectionLength);
}
if (&_init_array_start != &_init_array_end) {
abort();
}
size_t isrSectionLength = (&_isr_vector_table_end_ram - &_isr_vector_table_start_ram);
memcpy(&_isr_vector_table_start_ram, &_isr_vector_table_start_flash, isrSectionLength);
Ion::Device::Board::init();
jump_to_external_flash();
abort();
}
void __attribute__((interrupt, noinline)) isr_systick() {
auto t = Ion::Device::Timing::MillisElapsed;
t++;

View File

@@ -1,3 +1,4 @@
BOOTLOADER_SHARED_OFFSET = 0x3d0;
SECTIONS {
.signed_payload_prefix ORIGIN(FLASH) : {
@@ -34,7 +35,14 @@ SECTIONS {
_isr_vector_table_end_ram = .;
} >SRAM
.exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) : {
.bootloader_shared ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET : AT(ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) + SIZEOF(.slot_info)) {
_bootloader_shared_start = .;
KEEP(*(.bootloader_shared))
KEEP(*(.bootloader_shared.*))
_bootloader_shared_end = .;
} >SRAM
.exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) + SIZEOF(.bootloader_shared) + SIZEOF(.slot_info) : {
. = ALIGN(4K);
_exam_mode_buffer_start = .;
KEEP(*(.exam_mode_buffer))
@@ -49,6 +57,13 @@ SECTIONS {
KEEP(*(.userland_header));
} > FLASH
.recovery_boot : {
. = ALIGN(4);
_recovery_boot_start = .;
KEEP(*(.recovery_boot));
_recovery_boot_end = .;
} >FLASH
.text : {
. = ALIGN(4);
*(.text)
@@ -88,6 +103,17 @@ SECTIONS {
_data_section_end_ram = .;
} >SRAM AT> FLASH
/*
* We set the .static_storage right after the .data section, even if it's a bss region, because we need to fix it in memory.
*/
.static_storage : {
. = ALIGN(4);
_bss_section_start_ram = .;
_static_storage_start = .;
KEEP (*(.static_storage))
_static_storage_end = .;
} > SRAM
.bss : {
/* The bss section contains data for all uninitialized variables
* So like the .data section, it will go in RAM, but unlike the data section
@@ -96,7 +122,6 @@ SECTIONS {
* Before execution, crt0 will erase that section of memory though, so we'll
* need pointers to the beginning and end of this section. */
. = ALIGN(4);
_bss_section_start_ram = .;
*(.bss)
*(.bss.*)
/* The compiler may choose to allocate uninitialized global variables as

View File

@@ -8,6 +8,7 @@ MEMORY {
STACK_SIZE = 32K;
TRAMPOLINES_OFFSET = 0xE000;
CUSTOM_TRAMPOLINES_OFFSET = 64K - 64;
BOOTLOADER_SHARED_OFFSET = 0x3d0;
SECTIONS {
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
@@ -31,7 +32,16 @@ SECTIONS {
KEEP(*(.header))
} >INTERNAL_FLASH
.rodata : {
.bootloader_shared ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET : AT(ORIGIN(INTERNAL_FLASH) + SIZEOF(.isr_vector_table) + SIZEOF(.header)) {
. = ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET;
_bootloader_shared_start = .;
KEEP(*(.bootloader_shared))
KEEP(*(.bootloader_shared.*))
_bootloader_shared_end = .;
} >SRAM
.rodata ORIGIN(INTERNAL_FLASH) + SIZEOF(.isr_vector_table) + SIZEOF(.header) + SIZEOF(.bootloader_shared) : {
. = ALIGN(4);
*(.rodata)
*(.rodata.*)

View File

@@ -17,6 +17,9 @@
#error This file expects UPSILON_VERSION to be defined
#endif
extern "C" {
extern char _recovery_boot_start;
}
namespace Ion {
extern char staticStorageArea[];
}
@@ -72,7 +75,11 @@ public:
m_upsilonMagicHeader(UpsilonMagic),
m_UpsilonVersion{UPSILON_VERSION},
m_osType(OSType),
m_upsilonMagicFooter(UpsilonMagic) { }
m_upsilonMagicFooter(UpsilonMagic),
m_upsilonExtraMagicHeader(UpsilonExtraMagic),
m_recoveryAddress(((uint32_t)&_recovery_boot_start) + 1),
m_extraVersion(1),
m_upsilonExtraMagicFooter(UpsilonExtraMagic) { }
const char * omegaVersion() const {
assert(m_storageAddressRAM != nullptr);
@@ -109,6 +116,7 @@ private:
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
constexpr static uint32_t UpsilonMagic = 0x55707369;
constexpr static uint32_t OSType = 0x79827178;
constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
uint32_t m_header;
const char m_expectedEpsilonVersion[8];
void * m_storageAddressRAM;
@@ -128,6 +136,10 @@ private:
const char m_UpsilonVersion[16];
uint32_t m_osType;
uint32_t m_upsilonMagicFooter;
uint32_t m_upsilonExtraMagicHeader;
uint32_t m_recoveryAddress;
uint32_t m_extraVersion;
uint32_t m_upsilonExtraMagicFooter;
};
const UserlandHeader __attribute__((section(".userland_header"), used)) k_userlandHeader;

View File

@@ -8,6 +8,7 @@ extern "C" {
void start();
void abort();
void isr_systick();
void recovery_start();
#ifdef __cplusplus
}

View File

@@ -26,4 +26,5 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
timing.cpp \
usb.cpp \
wakeup.cpp \
bldata.cpp \
)

View File

@@ -0,0 +1,21 @@
#include "bldata.h"
#include <ion.h>
#include <new>
namespace Ion {
uint32_t staticSharedData[sizeof(Ion::Device::BootloaderSharedData)/sizeof(uint32_t)] __attribute__((section(".bootloader_shared"))) __attribute__((used)) = {0};
Device::BootloaderSharedData * Device::BootloaderSharedData::sharedBootloaderData() {
static BootloaderSharedData * sharedData = new (staticSharedData) BootloaderSharedData();
return sharedData;
}
Device::BootloaderSharedData::BootloaderSharedData() {
if (m_header != Magic || m_footer != Magic) {
m_header = Magic;
m_storageAddress = 0;
m_storageSize = 0;
m_footer = Magic;
}
}
}

View File

@@ -0,0 +1,24 @@
#include <ion.h>
namespace Ion
{
namespace Device
{
class BootloaderSharedData {
public:
constexpr static uint32_t Magic = 0x626C6461;
static BootloaderSharedData * sharedBootloaderData();
BootloaderSharedData();
void setRecovery(uint32_t address, uint32_t size) { m_storageAddress = address; m_storageSize = size; }
uint32_t storageAddress() const { return m_storageAddress; }
uint32_t storageSize() const { return m_storageSize; }
private:
uint32_t m_header;
uint32_t m_storageAddress;
uint32_t m_storageSize;
uint32_t m_footer;
};
}
}

View File

@@ -336,18 +336,14 @@ void InternalStorage::destroyRecordsWithExtension(const char * extension) {
}
}
InternalStorage::InternalStorage() :
m_magicHeader(Magic),
m_buffer(),
m_magicFooter(Magic),
m_delegate(nullptr),
m_lastRecordRetrieved(nullptr),
m_lastRecordRetrievedPointer(nullptr)
{
InternalStorage::InternalStorage() {
m_magicHeader = Magic;
m_magicFooter = Magic;
m_delegate = nullptr;
m_lastRecordRetrieved = nullptr;
m_lastRecordRetrievedPointer = nullptr;
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
// Set the size of the first record to 0
overrideSizeAtPosition(m_buffer, 0);
}
// PRIVATE

View File

@@ -6,7 +6,7 @@
namespace Ion {
uint32_t staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
uint32_t __attribute__((section(".static_storage"))) staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
Storage * Storage::sharedStorage() {
static Storage * storage = new (staticStorageArea) Storage();