mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Merge remote-tracking branch 'devdl11/upsilon-dev-1.0.1.01fix' into upsilon-dev
This commit is contained in:
@@ -37,6 +37,7 @@ bootloader_src += $(addprefix bootloader/interface/menus/, \
|
|||||||
warning.cpp \
|
warning.cpp \
|
||||||
slot_recovery.cpp \
|
slot_recovery.cpp \
|
||||||
crash.cpp \
|
crash.cpp \
|
||||||
|
upsilon_recovery.cpp \
|
||||||
)
|
)
|
||||||
|
|
||||||
bootloader_images = $(addprefix bootloader/, \
|
bootloader_images = $(addprefix bootloader/, \
|
||||||
|
|||||||
@@ -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;
|
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
|
// a simple function
|
||||||
Ion::Device::Flash::ClearInternalFlashErrors();
|
Ion::Device::Flash::ClearInternalFlashErrors();
|
||||||
asm("bx lr");
|
asm("bx lr");
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
static void bootSlot(Bootloader::Slot slot);
|
static void bootSlot(Bootloader::Slot slot);
|
||||||
static void bootSelectedSlot();
|
static void bootSelectedSlot();
|
||||||
__attribute__ ((noreturn)) static void jumpToInternalBootloader();
|
__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 bootloader();
|
||||||
static void lockInternal();
|
static void lockInternal();
|
||||||
|
|||||||
48
bootloader/interface/menus/upsilon_recovery.cpp
Normal file
48
bootloader/interface/menus/upsilon_recovery.cpp
Normal 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(;;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
bootloader/interface/menus/upsilon_recovery.h
Normal file
15
bootloader/interface/menus/upsilon_recovery.h
Normal 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
|
||||||
@@ -53,6 +53,15 @@ public:
|
|||||||
constexpr static const char * recoveryMessage4 = "Press Back to continue.";
|
constexpr static const char * recoveryMessage4 = "Press Back to continue.";
|
||||||
constexpr static const char * recoveryMessage5 = "(you will not be able to recover your data !)";
|
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
|
// Warning menu
|
||||||
constexpr static const char * epsilonWarningTitle = "Epsilon Slot";
|
constexpr static const char * epsilonWarningTitle = "Epsilon Slot";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <bootloader/recovery.h>
|
#include <bootloader/recovery.h>
|
||||||
#include <ion.h>
|
#include <ion.h>
|
||||||
#include <ion/src/device/n0110/drivers/power.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/reset.h>
|
||||||
#include <ion/src/device/shared/drivers/board.h>
|
#include <ion/src/device/shared/drivers/board.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include <bootloader/usb_data.h>
|
#include <bootloader/usb_data.h>
|
||||||
#include <bootloader/interface/menus/slot_recovery.h>
|
#include <bootloader/interface/menus/slot_recovery.h>
|
||||||
#include <bootloader/interface/menus/crash.h>
|
#include <bootloader/interface/menus/crash.h>
|
||||||
|
#include <bootloader/interface/menus/upsilon_recovery.h>
|
||||||
|
|
||||||
constexpr static uint32_t MagicStorage = 0xEE0BDDBA;
|
constexpr static uint32_t MagicStorage = 0xEE0BDDBA;
|
||||||
|
|
||||||
@@ -76,7 +78,15 @@ void Bootloader::Recovery::recoverData() {
|
|||||||
Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite);
|
Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite);
|
||||||
Ion::Backlight::init();
|
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);
|
SlotRecoveryMenu menu = SlotRecoveryMenu(&udata);
|
||||||
menu.open();
|
menu.open();
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <ion/src/device/shared/drivers/flash.h>
|
#include <ion/src/device/shared/drivers/flash.h>
|
||||||
#include <ion/src/device/shared/drivers/external_flash.h>
|
#include <ion/src/device/shared/drivers/external_flash.h>
|
||||||
#include <bootloader/boot.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));
|
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);
|
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 {
|
const KernelHeader* Slot::kernelHeader() const {
|
||||||
return m_kernelHeader;
|
return m_kernelHeader;
|
||||||
}
|
}
|
||||||
@@ -65,6 +76,9 @@ const UserlandHeader* Slot::userlandHeader() const {
|
|||||||
// Configure the MPU for the booted firmware
|
// Configure the MPU for the booted firmware
|
||||||
Ion::Device::Board::bootloaderMPU();
|
Ion::Device::Board::bootloaderMPU();
|
||||||
|
|
||||||
|
// Deinitialize the backlight to prevent bugs when the firmware boots
|
||||||
|
Ion::Backlight::shutdown();
|
||||||
|
|
||||||
// Jump
|
// Jump
|
||||||
jump_to_firmware(kernelHeader()->stackPointer(), kernelHeader()->startPointer());
|
jump_to_firmware(kernelHeader()->stackPointer(), kernelHeader()->startPointer());
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public:
|
|||||||
static const Slot A();
|
static const Slot A();
|
||||||
static const Slot B();
|
static const Slot B();
|
||||||
static const Slot Khi();
|
static const Slot Khi();
|
||||||
|
static const bool hasUpsilon();
|
||||||
|
static const Slot Upsilon();
|
||||||
|
|
||||||
static bool isFullyValid(const Slot& slot) {
|
static bool isFullyValid(const Slot& slot) {
|
||||||
return slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid();
|
return slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid();
|
||||||
|
|||||||
@@ -40,4 +40,16 @@ const size_t UserlandHeader::storageSize() const {
|
|||||||
return m_storageSizeRAM;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,17 @@ public:
|
|||||||
const char * upsilonVersion() const;
|
const char * upsilonVersion() const;
|
||||||
const void * storageAddress() const;
|
const void * storageAddress() const;
|
||||||
const size_t storageSize() const;
|
const size_t storageSize() const;
|
||||||
|
const bool hasUpsilonExtras() const;
|
||||||
|
const void (*upsilonRecoveryBootFunction() const)();
|
||||||
|
const uint32_t getExtraVersion() const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UserlandHeader();
|
UserlandHeader();
|
||||||
constexpr static uint32_t Magic = 0xDEC0EDFE;
|
constexpr static uint32_t Magic = 0xDEC0EDFE;
|
||||||
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
||||||
constexpr static uint32_t UpsilonMagic = 0x55707369;
|
constexpr static uint32_t UpsilonMagic = 0x55707369;
|
||||||
|
constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
|
||||||
uint32_t m_header;
|
uint32_t m_header;
|
||||||
const char m_expectedEpsilonVersion[8];
|
const char m_expectedEpsilonVersion[8];
|
||||||
void * m_storageAddressRAM;
|
void * m_storageAddressRAM;
|
||||||
@@ -42,6 +47,10 @@ private:
|
|||||||
const char m_UpsilonVersion[16];
|
const char m_UpsilonVersion[16];
|
||||||
uint32_t m_osType;
|
uint32_t m_osType;
|
||||||
uint32_t m_upsilonMagicFooter;
|
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;
|
extern const UserlandHeader* s_userlandHeaderA;
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ion.h>
|
#include <ion.h>
|
||||||
|
#include <ion/led.h>
|
||||||
|
#include <ion/storage.h>
|
||||||
|
#include <ion/internal_storage.h>
|
||||||
#include <boot/isr.h>
|
#include <boot/isr.h>
|
||||||
#include <drivers/board.h>
|
#include <drivers/board.h>
|
||||||
#include <drivers/rtc.h>
|
#include <drivers/rtc.h>
|
||||||
#include <drivers/reset.h>
|
#include <drivers/reset.h>
|
||||||
#include <drivers/timing.h>
|
#include <drivers/timing.h>
|
||||||
|
#include <drivers/bldata.h>
|
||||||
|
|
||||||
typedef void (*cxx_constructor)();
|
typedef void (*cxx_constructor)();
|
||||||
|
|
||||||
@@ -14,6 +18,8 @@ extern "C" {
|
|||||||
extern char _data_section_start_ram;
|
extern char _data_section_start_ram;
|
||||||
extern char _data_section_end_ram;
|
extern char _data_section_end_ram;
|
||||||
extern char _bss_section_start_ram;
|
extern char _bss_section_start_ram;
|
||||||
|
extern char _static_storage_start;
|
||||||
|
extern char _static_storage_end;
|
||||||
extern char _bss_section_end_ram;
|
extern char _bss_section_end_ram;
|
||||||
extern cxx_constructor _init_array_start;
|
extern cxx_constructor _init_array_start;
|
||||||
extern cxx_constructor _init_array_end;
|
extern cxx_constructor _init_array_end;
|
||||||
@@ -129,6 +135,45 @@ void __attribute__((noinline)) start() {
|
|||||||
abort();
|
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() {
|
void __attribute__((interrupt, noinline)) isr_systick() {
|
||||||
auto t = Ion::Device::Timing::MillisElapsed;
|
auto t = Ion::Device::Timing::MillisElapsed;
|
||||||
t++;
|
t++;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
BOOTLOADER_SHARED_OFFSET = 0x3d0;
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.signed_payload_prefix ORIGIN(FLASH) : {
|
.signed_payload_prefix ORIGIN(FLASH) : {
|
||||||
@@ -34,7 +35,14 @@ SECTIONS {
|
|||||||
_isr_vector_table_end_ram = .;
|
_isr_vector_table_end_ram = .;
|
||||||
} >SRAM
|
} >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);
|
. = ALIGN(4K);
|
||||||
_exam_mode_buffer_start = .;
|
_exam_mode_buffer_start = .;
|
||||||
KEEP(*(.exam_mode_buffer))
|
KEEP(*(.exam_mode_buffer))
|
||||||
@@ -49,6 +57,13 @@ SECTIONS {
|
|||||||
KEEP(*(.userland_header));
|
KEEP(*(.userland_header));
|
||||||
} > FLASH
|
} > FLASH
|
||||||
|
|
||||||
|
.recovery_boot : {
|
||||||
|
. = ALIGN(4);
|
||||||
|
_recovery_boot_start = .;
|
||||||
|
KEEP(*(.recovery_boot));
|
||||||
|
_recovery_boot_end = .;
|
||||||
|
} >FLASH
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.text)
|
*(.text)
|
||||||
@@ -88,6 +103,17 @@ SECTIONS {
|
|||||||
_data_section_end_ram = .;
|
_data_section_end_ram = .;
|
||||||
} >SRAM AT> FLASH
|
} >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 : {
|
.bss : {
|
||||||
/* The bss section contains data for all uninitialized variables
|
/* The bss section contains data for all uninitialized variables
|
||||||
* So like the .data section, it will go in RAM, but unlike the data section
|
* 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
|
* Before execution, crt0 will erase that section of memory though, so we'll
|
||||||
* need pointers to the beginning and end of this section. */
|
* need pointers to the beginning and end of this section. */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_bss_section_start_ram = .;
|
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss.*)
|
*(.bss.*)
|
||||||
/* The compiler may choose to allocate uninitialized global variables as
|
/* The compiler may choose to allocate uninitialized global variables as
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ MEMORY {
|
|||||||
STACK_SIZE = 32K;
|
STACK_SIZE = 32K;
|
||||||
TRAMPOLINES_OFFSET = 0xE000;
|
TRAMPOLINES_OFFSET = 0xE000;
|
||||||
CUSTOM_TRAMPOLINES_OFFSET = 64K - 64;
|
CUSTOM_TRAMPOLINES_OFFSET = 64K - 64;
|
||||||
|
BOOTLOADER_SHARED_OFFSET = 0x3d0;
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
|
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
|
||||||
@@ -31,7 +32,16 @@ SECTIONS {
|
|||||||
KEEP(*(.header))
|
KEEP(*(.header))
|
||||||
} >INTERNAL_FLASH
|
} >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);
|
. = ALIGN(4);
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
*(.rodata.*)
|
*(.rodata.*)
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
#error This file expects UPSILON_VERSION to be defined
|
#error This file expects UPSILON_VERSION to be defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern char _recovery_boot_start;
|
||||||
|
}
|
||||||
namespace Ion {
|
namespace Ion {
|
||||||
extern char staticStorageArea[];
|
extern char staticStorageArea[];
|
||||||
}
|
}
|
||||||
@@ -72,7 +75,11 @@ public:
|
|||||||
m_upsilonMagicHeader(UpsilonMagic),
|
m_upsilonMagicHeader(UpsilonMagic),
|
||||||
m_UpsilonVersion{UPSILON_VERSION},
|
m_UpsilonVersion{UPSILON_VERSION},
|
||||||
m_osType(OSType),
|
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 {
|
const char * omegaVersion() const {
|
||||||
assert(m_storageAddressRAM != nullptr);
|
assert(m_storageAddressRAM != nullptr);
|
||||||
@@ -109,6 +116,7 @@ private:
|
|||||||
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
||||||
constexpr static uint32_t UpsilonMagic = 0x55707369;
|
constexpr static uint32_t UpsilonMagic = 0x55707369;
|
||||||
constexpr static uint32_t OSType = 0x79827178;
|
constexpr static uint32_t OSType = 0x79827178;
|
||||||
|
constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
|
||||||
uint32_t m_header;
|
uint32_t m_header;
|
||||||
const char m_expectedEpsilonVersion[8];
|
const char m_expectedEpsilonVersion[8];
|
||||||
void * m_storageAddressRAM;
|
void * m_storageAddressRAM;
|
||||||
@@ -128,6 +136,10 @@ private:
|
|||||||
const char m_UpsilonVersion[16];
|
const char m_UpsilonVersion[16];
|
||||||
uint32_t m_osType;
|
uint32_t m_osType;
|
||||||
uint32_t m_upsilonMagicFooter;
|
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;
|
const UserlandHeader __attribute__((section(".userland_header"), used)) k_userlandHeader;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ extern "C" {
|
|||||||
void start();
|
void start();
|
||||||
void abort();
|
void abort();
|
||||||
void isr_systick();
|
void isr_systick();
|
||||||
|
void recovery_start();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,5 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
|
|||||||
timing.cpp \
|
timing.cpp \
|
||||||
usb.cpp \
|
usb.cpp \
|
||||||
wakeup.cpp \
|
wakeup.cpp \
|
||||||
|
bldata.cpp \
|
||||||
)
|
)
|
||||||
|
|||||||
21
ion/src/device/shared/drivers/bldata.cpp
Normal file
21
ion/src/device/shared/drivers/bldata.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ion/src/device/shared/drivers/bldata.h
Normal file
24
ion/src/device/shared/drivers/bldata.h
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -336,18 +336,14 @@ void InternalStorage::destroyRecordsWithExtension(const char * extension) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalStorage::InternalStorage() :
|
InternalStorage::InternalStorage() {
|
||||||
m_magicHeader(Magic),
|
m_magicHeader = Magic;
|
||||||
m_buffer(),
|
m_magicFooter = Magic;
|
||||||
m_magicFooter(Magic),
|
m_delegate = nullptr;
|
||||||
m_delegate(nullptr),
|
m_lastRecordRetrieved = nullptr;
|
||||||
m_lastRecordRetrieved(nullptr),
|
m_lastRecordRetrievedPointer = nullptr;
|
||||||
m_lastRecordRetrievedPointer(nullptr)
|
|
||||||
{
|
|
||||||
assert(m_magicHeader == Magic);
|
assert(m_magicHeader == Magic);
|
||||||
assert(m_magicFooter == Magic);
|
assert(m_magicFooter == Magic);
|
||||||
// Set the size of the first record to 0
|
|
||||||
overrideSizeAtPosition(m_buffer, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE
|
// PRIVATE
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace Ion {
|
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() {
|
Storage * Storage::sharedStorage() {
|
||||||
static Storage * storage = new (staticStorageArea) Storage();
|
static Storage * storage = new (staticStorageArea) Storage();
|
||||||
|
|||||||
Reference in New Issue
Block a user