diff --git a/bootloader/Makefile b/bootloader/Makefile index ff7a5599a..89308cccd 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -1,38 +1,49 @@ bootloader_src += $(addprefix bootloader/,\ - slot_exam_mode.cpp \ + utility.cpp \ boot.cpp \ main.cpp \ - kernel_header.cpp \ - userland_header.cpp \ - slot.cpp \ - interface.cpp \ jump_to_firmware.s \ trampoline.cpp \ recovery.cpp \ usb_data.cpp \ - itoa.cpp \ - utility.cpp \ ) -bootloader_images = $(addprefix bootloader/, \ - computer.png \ +bootloader_src += $(addprefix bootloader/slots/, \ + slot_exam_mode.cpp \ + slot.cpp \ + userland_header.cpp \ + kernel_header.cpp \ +) + +bootloader_src += $(addprefix bootloader/drivers/, \ + stm32_drivers.cpp \ +) + +bootloader_src += $(addprefix bootloader/interface/static/, \ + interface.cpp \ ) bootloader_src += $(addprefix bootloader/interface/src/,\ menu.cpp \ ) -bootloader_src += $(addprefix bootloader/interface/menus/about/,\ + +bootloader_src += $(addprefix bootloader/interface/menus/, \ about.cpp \ -) - -bootloader_src += $(addprefix bootloader/interface/menus/home/,\ home.cpp \ + dfu.cpp \ + installer.cpp \ + warning.cpp \ + slot_recovery.cpp \ + crash.cpp \ ) +bootloader_images = $(addprefix bootloader/, \ + computer.png \ +) bootloader_src += $(ion_src) $(simple_kandinsky_src) $(liba_src) $(libaxx_src) $(bootloader_images) -$(eval $(call depends_on_image,bootloader/interface.cpp,$(bootloader_images))) -$(eval $(call depends_on_image,bootloader/interface/menus/home/home.cpp,$(bootloader_images))) +$(eval $(call depends_on_image,bootloader/interface/static/interface.cpp,$(bootloader_images))) +$(eval $(call depends_on_image,bootloader/interface/src/menu.cpp,$(bootloader_images))) diff --git a/bootloader/boot.cpp b/bootloader/boot.cpp index 765368b39..405b54d7f 100644 --- a/bootloader/boot.cpp +++ b/bootloader/boot.cpp @@ -1,19 +1,33 @@ #include -#include -#include -#include -#include -#include +#include +#include #include #include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +using namespace Utility; + +extern "C" { + extern char _fake_isr_function_start; +} + namespace Bootloader { +BootConfig * Boot::config() { + static BootConfig * bootcfg = new BootConfig(); + return bootcfg; +} + BootMode Boot::mode() { return BootMode::SlotA; } @@ -22,36 +36,86 @@ void Boot::setMode(BootMode mode) { // We dont use the exam mode driver as storage for the boot mode because we need the 16k of storage x) } +void Boot::busErr() { + if (config()->isBooting()) { + config()->slot()->boot(); + } + Bootloader::Recovery::crash_handler("BusFault"); +} + +bool Boot::isKernelPatched(const Slot & s) { + if (s.userlandHeader()->isOmega()) { + // we don't need to patch the kernel + return true; + } + + // It's an epsilon kernel, so we need to check if it's patched + + uint32_t origin_isr = s.address() + sizeof(Bootloader::KernelHeader) - sizeof(uint32_t) * 3; + + if (*(uint32_t *)(origin_isr + sizeof(uint32_t) * 12) == (uint32_t)0x0) { + // fake epsilon + return true; + } + + return *(uint32_t *)(origin_isr + sizeof(uint32_t) * 21) == (uint32_t)&_fake_isr_function_start; +} + +__attribute((section(".fake_isr_function"))) __attribute__((used)) void Boot::flsh_intr() { + // a simple function + while (1) {} +} + +void Boot::patchKernel(const Slot & s) { + uint32_t origin_isr = s.address() + sizeof(Bootloader::KernelHeader) - sizeof(uint32_t) * 3 - 0x90000000; + // we allocate a big buffer to store the first sector + uint8_t data[1024*4]; + memcpy(data, (void*)0x90000000, 1024*4); + uint32_t dummy_address = (uint32_t)&_fake_isr_function_start; + uint8_t * ptr = (uint8_t *)&dummy_address; + data[origin_isr + sizeof(uint32_t) * 21] = ptr[0]; + data[origin_isr + sizeof(uint32_t) * 21 + 1] = ptr[1]; + data[origin_isr + sizeof(uint32_t) * 21 + 2] = ptr[2]; + data[origin_isr + sizeof(uint32_t) * 21 + 3] = ptr[3]; + Ion::Device::ExternalFlash::EraseSector(0); + Ion::Device::ExternalFlash::WriteMemory((uint8_t*)0x90000000, data, 1024*4); +} + void Boot::bootSlot(Bootloader::Slot s) { + config()->setSlot(&s); if (!s.userlandHeader()->isOmega() && !s.userlandHeader()->isUpsilon()) { // We are trying to boot epsilon, so we check the version and show an advertisement if needed const char * version = s.userlandHeader()->version(); - const char * min = "18.2.4"; + const char * min = "18.2.0"; int vsum = Utility::versionSum(version, strlen(version)); int minsum = Utility::versionSum(min, strlen(min)); if (vsum >= minsum) { - Interface::drawEpsilonAdvertisement(); - uint64_t scan = 0; - while (scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - scan = Ion::Keyboard::scan(); - if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::EXE) || scan == Ion::Keyboard::State(Ion::Keyboard::Key::OK)) { - scan = Ion::Keyboard::State(Ion::Keyboard::Key::Back); - s.boot(); - } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { - Ion::Power::standby(); // Force a core reset to exit - } - } - Interface::drawMenu(); + WarningMenu menu = WarningMenu(); + menu.open(); return; } } - s.boot(); - Interface::drawMenu(); + bootSelectedSlot(); +} + +void Boot::bootSelectedSlot() { + lockInternal(); + enableFlashIntr(); + config()->setBooting(true); + Ion::Device::Flash::EnableInternalSessionLock(); } __attribute__((noreturn)) void Boot::boot() { assert(mode() != BootMode::Unknown); + Boot::config()->clearSlot(); + Boot::config()->setBooting(false); + + if (!Boot::isKernelPatched(Slot::A())) { + Boot::patchKernel(Slot::A()); + Ion::LED::setColor(KDColorRed); + } + while (true) { HomeMenu menu = HomeMenu(); menu.open(true); @@ -61,67 +125,6 @@ __attribute__((noreturn)) void Boot::boot() { bootloader(); } -void Boot::installerMenu() { - Interface::drawInstallerSelection(); - uint64_t scan = 0; - while (scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - scan = Ion::Keyboard::scan(); - if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::One)) { - scan = Ion::Keyboard::State(Ion::Keyboard::Key::Back); - bootloader(); - continue; - } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Two)) { - scan = Ion::Keyboard::State(Ion::Keyboard::Key::Back); - bootloaderUpdate(); - continue; - } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { - Ion::Power::standby(); // Force a core reset to exit - } - } - - Interface::drawMenu(); -} - -void Boot::aboutMenu() { - // Draw the about menu - Interface::drawAbout(); - // Wait for the user to press OK, EXE or Back button - while (true) { - uint64_t scan = Ion::Keyboard::scan(); - if ((scan == Ion::Keyboard::State(Ion::Keyboard::Key::OK)) || - (scan == Ion::Keyboard::State(Ion::Keyboard::Key::EXE)) || - (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back))) { - // Redraw the menu and return - Interface::drawMenu(); - return; - } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { - Ion::Power::standby(); // Force a core reset to exit - } - } - -} - -void Boot::bootloaderUpdate() { - USBData data = USBData::BOOTLOADER_UPDATE(); - - for (;;) { - Bootloader::Interface::drawBootloaderUpdate(); - Ion::USB::enable(); - do { - uint64_t scan = Ion::Keyboard::scan(); - if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - Ion::USB::disable(); - Interface::drawMenu(); - return; - } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { - Ion::Power::standby(); - } - } while (!Ion::USB::isEnumerated()); - - Ion::USB::DFU(true, &data); - } -} - void Boot::bootloader() { USBData data = USBData::DEFAULT(); for(;;) { @@ -138,7 +141,6 @@ void Boot::bootloader() { if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { // Disable USB, redraw the menu and return Ion::USB::disable(); - Interface::drawMenu(); return; } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { Ion::Power::standby(); // Force a core reset to exit @@ -150,6 +152,10 @@ void Boot::bootloader() { } } +void Boot::jumpToInternalBootloader() { + Ion::Device::Board::jumpToInternalBootloader(); +} + void Boot::lockInternal() { Ion::Device::Flash::DisableInternalProtection(); Ion::Device::Flash::SetInternalSectorProtection(0, true); @@ -159,4 +165,8 @@ void Boot::lockInternal() { Ion::Device::Flash::EnableInternalProtection(); } +void Boot::enableFlashIntr() { + Ion::Device::Flash::EnableInternalFlashInterrupt(); +} + } diff --git a/bootloader/boot.h b/bootloader/boot.h index 0414ed22d..2b7d66d47 100644 --- a/bootloader/boot.h +++ b/bootloader/boot.h @@ -2,10 +2,25 @@ #define BOOTLOADER_BOOT_H #include -#include +#include namespace Bootloader { +class BootConfig { + public: + BootConfig() : m_slot(nullptr), m_booting(false) {}; + + void setSlot(Slot * slot) { m_slot = slot; } + Slot * slot() const { return m_slot; } + void clearSlot() { m_slot = nullptr; } + + void setBooting(bool booting) { m_booting = booting; } + bool isBooting() const { return m_booting; } + private: + Bootloader::Slot * m_slot; + bool m_booting; +}; + enum BootMode: uint8_t { SlotA = 0, SlotB = 1, @@ -20,15 +35,26 @@ class Boot { public: static BootMode mode(); static void setMode(BootMode mode); + static BootConfig * config(); + + static bool isKernelPatched(const Slot & slot); + static void patchKernel(const Slot & slot); + + static void busErr(); + __attribute__ ((noreturn)) static void boot(); - static void bootloader(); - static void aboutMenu(); - static void installerMenu(); - static void bootloaderUpdate(); + static void bootSlot(Bootloader::Slot slot); + static void bootSelectedSlot(); + __attribute__ ((noreturn)) static void jumpToInternalBootloader(); + __attribute((section(".fake_isr_function"))) __attribute__((used)) static void flsh_intr(); + + static void bootloader(); static void lockInternal(); + static void enableFlashIntr(); }; + } #endif \ No newline at end of file diff --git a/bootloader/boot/rt0.cpp b/bootloader/boot/rt0.cpp index 59751ca5f..65eedf985 100644 --- a/bootloader/boot/rt0.cpp +++ b/bootloader/boot/rt0.cpp @@ -7,6 +7,7 @@ #include #include #include +#include typedef void (*cxx_constructor)(); @@ -49,7 +50,7 @@ void __attribute__((noinline)) usage_fault_handler() { } void __attribute__((noinline)) bus_fault_handler() { - Bootloader::Recovery::crash_handler("BusFault"); + Bootloader::Boot::busErr(); } /* In order to ensure that this method is execute from the external flash, we diff --git a/bootloader/drivers/board.cpp b/bootloader/drivers/board.cpp index 2ee8fe666..0a80a89ec 100644 --- a/bootloader/drivers/board.cpp +++ b/bootloader/drivers/board.cpp @@ -4,9 +4,13 @@ #include #include #include +#include #include #include +#include + +using namespace STM32; typedef void(*ISR)(void); extern ISR InitialisationVector[]; @@ -439,6 +443,20 @@ bool pcbVersionIsLocked() { return *reinterpret_cast(InternalFlash::Config::OTPLockAddress(k_pcbVersionOTPIndex)) == 0; } +void jumpToInternalBootloader() { + asm volatile ("cpsie i" : : : "memory"); + + STM32::rcc_deinit(); + STM32::hal_deinit(); + STM32::systick_deinit(); + + const uint32_t p = (*((uint32_t *) 0x1FF00000)); + asm volatile ("MSR msp, %0" : : "r" (p) : ); + void (*SysMemBootJump)(void); + SysMemBootJump = (void (*)(void)) (*((uint32_t *) 0x1FF00004)); + SysMemBootJump(); +} + } } } diff --git a/bootloader/drivers/stm32_drivers.cpp b/bootloader/drivers/stm32_drivers.cpp new file mode 100644 index 000000000..6fd018aab --- /dev/null +++ b/bootloader/drivers/stm32_drivers.cpp @@ -0,0 +1,56 @@ +#include "stm32_drivers.h" + +void STM32::rcc_deinit() { + SET_BIT(STM_32_RCC->CR, (0x1UL << (0U))); + while (READ_BIT(STM_32_RCC->CR, (0x1UL << (1U))) == 0) {} + SET_BIT(STM_32_RCC->CR, (0x10UL << (3U))); + CLEAR_REG(STM_32_RCC->CFGR); + while (READ_BIT(STM_32_RCC->CFGR, (0x3UL << (2U))) != 0) {} + CLEAR_BIT(STM_32_RCC->CR, (0x1UL << (16U)) | (0x1UL << (18U)) | (0x1UL << (19U))); + while (READ_BIT(STM_32_RCC->CR, (0x1UL << (17U))) != 0) {} + CLEAR_BIT(STM_32_RCC->CR, (0x1UL << (24U))); + while (READ_BIT(STM_32_RCC->CR, (0x1UL << (25U))) != 0) {} + CLEAR_BIT(STM_32_RCC->CR, (0x1UL << (26U))); + while (READ_BIT(STM_32_RCC->CR, (0x1UL << (27U))) != 0) {} + CLEAR_BIT(STM_32_RCC->CR, (0x1UL << (28U))); + while (READ_BIT(STM_32_RCC->CR, (0x1UL << (29U))) != 0) {} + STM_32_RCC->PLLCFGR = ((0x10UL << (0x0U)) | (0x040UL << (6U)) | (0x080UL << (6U)) | (0x4UL << (24U)) | 0x20000000U); + STM_32_RCC->PLLI2SCFGR = ((0x040UL << (6U)) | (0x080UL << (6U)) | (0x4UL << (24U)) | (0x2UL << (28U))); + STM_32_RCC->PLLSAICFGR = ((0x040UL << (6U)) | (0x080UL << (6U)) | (0x4UL << (24U)) | 0x20000000U); + CLEAR_BIT(STM_32_RCC->CIR, ((0x1UL << (8U)) | (0x1UL << (9U)) | (0x1UL << (10U)) | (0x1UL << (11U)) | (0x1UL << (12U)) | (0x1UL << (13U)) | (0x1UL << (14U)))); + SET_BIT(STM_32_RCC->CIR, ((0x1UL << (16U)) | (0x1UL << (17U)) | (0x1UL << (18U)) | (0x1UL << (19U)) | (0x1UL << (20U)) | (0x1UL << (21U)) | (0x1UL << (22U)) | (0x1UL << (23U)))); + CLEAR_BIT(STM_32_RCC->CSR, ((0x1UL << (0U)))); + SET_BIT(STM_32_RCC->CSR, ((0x1UL << (24U)))); + uint32_t sysclock = ((uint32_t)16000000U); + uint32_t a = ((sysclock / 1000U)); + uint32_t b = 15U; + STM_32_SysTick->LOAD = (uint32_t)(a - 1UL); + STM_32_SCB->SHPR[(((uint32_t)(-1))&0xFUL)-4UL] = (uint8_t)((((1UL << 4U)-1UL) << (8U - 4UL)) & (uint32_t)0xFFUL); + STM_32_SysTick->VAL = 0U; + STM_32_SysTick->CTRL = (1UL << 2U) | (1UL << 1U) | (1UL); + uint32_t c = ((uint32_t)((STM_32_SCB->AIRCR & (7UL << 8U)) >> 8U)); + uint32_t d = (c & (uint32_t)0x07UL); + uint32_t e; + uint32_t f; + e = ((7UL - d) > (uint32_t)(4UL)) ? (uint32_t)(4UL) : (7UL - d); + f = ((d + (uint32_t)(4UL)) < (uint32_t)(7UL)) ? (uint32_t)(0UL) : (uint32_t)((d - 7UL) + (uint32_t)(4UL)); + uint32_t g = (((b & (uint32_t)((1UL << (e)) - 1UL)) << f) | ((0UL & (uint32_t)((1UL << (f)) - 1UL)))); + STM_32_SCB->SHPR[(((uint32_t)(-1))&0xFUL)-4UL] = (uint8_t)((g << (8U - 4UL)) & (uint32_t)0xFFUL); +} + +void STM32::hal_deinit() { + STM_32_RCC->APB1RSTR = 0xFFFFFFFFU; + STM_32_RCC->APB1RSTR = 0x00U; + STM_32_RCC->APB2RSTR = 0xFFFFFFFFU; + STM_32_RCC->APB2RSTR = 0x00U; + STM_32_RCC->AHB1RSTR = 0xFFFFFFFFU; + STM_32_RCC->AHB1RSTR = 0x00U; + STM_32_RCC->AHB2RSTR = 0xFFFFFFFFU; + STM_32_RCC->AHB2RSTR = 0x00U; + STM_32_RCC->AHB3RSTR = 0xFFFFFFFFU; + STM_32_RCC->AHB3RSTR = 0x00U; +} + +void STM32::systick_deinit() { + STM_32_SysTick->CTRL = STM_32_SysTick->LOAD = STM_32_SysTick->VAL = 0; +} diff --git a/bootloader/drivers/stm32_drivers.h b/bootloader/drivers/stm32_drivers.h new file mode 100644 index 000000000..bba55c74b --- /dev/null +++ b/bootloader/drivers/stm32_drivers.h @@ -0,0 +1,153 @@ +#include + +/* + Here we implement a very little part of the code from the default stm32 libs because we only need the unload function. + Now we include the license of the original code as required. +*/ + +/* +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the BSD-3-Clause license shall apply. +You may obtain a copy of the BSD-3-Clause at: +https://opensource.org/licenses/BSD-3-Clause +*/ + +namespace STM32 { + + typedef struct + { + volatile uint32_t CR; + volatile uint32_t PLLCFGR; + volatile uint32_t CFGR; + volatile uint32_t CIR; + volatile uint32_t AHB1RSTR; + volatile uint32_t AHB2RSTR; + volatile uint32_t AHB3RSTR; + uint32_t RESERVED0; + volatile uint32_t APB1RSTR; + volatile uint32_t APB2RSTR; + uint32_t RESERVED1[2]; + volatile uint32_t AHB1ENR; + volatile uint32_t AHB2ENR; + volatile uint32_t AHB3ENR; + uint32_t RESERVED2; + volatile uint32_t APB1ENR; + volatile uint32_t APB2ENR; + uint32_t RESERVED3[2]; + volatile uint32_t AHB1LPENR; + volatile uint32_t AHB2LPENR; + volatile uint32_t AHB3LPENR; + uint32_t RESERVED4; + volatile uint32_t APB1LPENR; + volatile uint32_t APB2LPENR; + uint32_t RESERVED5[2]; + volatile uint32_t BDCR; + volatile uint32_t CSR; + uint32_t RESERVED6[2]; + volatile uint32_t SSCGR; + volatile uint32_t PLLI2SCFGR; + volatile uint32_t PLLSAICFGR; + volatile uint32_t DCKCFGR1; + volatile uint32_t DCKCFGR2; + } STM32_RCC_TypeDef; + + typedef struct + { + volatile uint32_t CTRL; + volatile uint32_t LOAD; + volatile uint32_t VAL; + volatile const uint32_t CALIB; + } STM32_SysTick_Type; + + typedef struct + { + volatile uint32_t ISER[8U]; + uint32_t RESERVED0[24U]; + volatile uint32_t ICER[8U]; + uint32_t RSERVED1[24U]; + volatile uint32_t ISPR[8U]; + uint32_t RESERVED2[24U]; + volatile uint32_t ICPR[8U]; + uint32_t RESERVED3[24U]; + volatile uint32_t IABR[8U]; + uint32_t RESERVED4[56U]; + volatile uint8_t IP[240U]; + uint32_t RESERVED5[644U]; + volatile uint32_t STIR; + } STM32_NVIC_Type; + + typedef struct { + volatile const uint32_t CPUID; + volatile uint32_t ICSR; + volatile uint32_t VTOR; + volatile uint32_t AIRCR; + volatile uint32_t SCR; + volatile uint32_t CCR; + volatile uint8_t SHPR[12U]; + volatile uint32_t SHCSR; + volatile uint32_t CFSR; + volatile uint32_t HFSR; + volatile uint32_t DFSR; + volatile uint32_t MMFAR; + volatile uint32_t BFAR; + volatile uint32_t AFSR; + volatile const uint32_t ID_PFR[2U]; + volatile const uint32_t ID_DFR; + volatile const uint32_t ID_AFR; + volatile const uint32_t ID_MFR[4U]; + volatile const uint32_t ID_ISAR[5U]; + uint32_t RESERVED0[1U]; + volatile const uint32_t CLIDR; + volatile const uint32_t CTR; + volatile const uint32_t CCSIDR; + volatile uint32_t CSSELR; + volatile uint32_t CPACR; + uint32_t RESERVED3[93U]; + volatile uint32_t STIR; + uint32_t RESERVED4[15U]; + volatile const uint32_t MVFR0; + volatile const uint32_t MVFR1; + volatile const uint32_t MVFR2; + uint32_t RESERVED5[1U]; + volatile uint32_t ICIALLU; + uint32_t RESERVED6[1U]; + volatile uint32_t ICIMVAU; + volatile uint32_t DCIMVAC; + volatile uint32_t DCISW; + volatile uint32_t DCCMVAU; + volatile uint32_t DCCMVAC; + volatile uint32_t DCCSW; + volatile uint32_t DCCIMVAC; + volatile uint32_t DCCISW; + uint32_t RESERVED7[6U]; + volatile uint32_t ITCMCR; + volatile uint32_t DTCMCR; + volatile uint32_t AHBPCR; + volatile uint32_t CACR; + volatile uint32_t AHBSCR; + uint32_t RESERVED8[1U]; + volatile uint32_t ABFSR; + } STM32_SCB_Type; + + #define RCC_BASE 0x40023800UL + #define SysTick_BASE 0xE000E010UL + #define NVIC_BASE 0xE000E100UL + #define SCB_BASE 0xE000ED00UL + + #define SET_BIT(REG, BIT) ((REG) |= (BIT)) + #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + #define READ_BIT(REG, BIT) ((REG) & (BIT)) + #define CLEAR_REG(REG) ((REG) = (0x0)) + #define READ_REG(REG) ((REG)) + + #define STM_32_RCC ((STM32::STM32_RCC_TypeDef *) RCC_BASE) + #define STM_32_SysTick ((STM32::STM32_SysTick_Type *) SysTick_BASE) + #define STM_32_NVIC ((STM32::STM32_NVIC_Type *) NVIC_BASE) + #define STM_32_SCB ((STM32_SCB_Type *) SCB_BASE) + + extern void rcc_deinit(); + extern void hal_deinit(); + extern void systick_deinit(); +} \ No newline at end of file diff --git a/bootloader/interface.cpp b/bootloader/interface.cpp deleted file mode 100644 index 7d54da274..000000000 --- a/bootloader/interface.cpp +++ /dev/null @@ -1,328 +0,0 @@ - -#include -#include -#include - -#include -#include -#include -#include - -#include "computer.h" - -namespace Bootloader { - -void Interface::drawImage(KDContext * ctx, const Image * image, int offset) { - const uint8_t * data; - size_t size; - size_t pixelBufferSize; - - if (image != nullptr) { - data = image->compressedPixelData(); - size = image->compressedPixelDataSize(); - pixelBufferSize = image->width() * image->height(); - } else { - return; - } - - KDColor pixelBuffer[4000]; - assert(pixelBufferSize <= 4000); - assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack - - Ion::decompress( - data, - reinterpret_cast(pixelBuffer), - size, - pixelBufferSize * sizeof(KDColor) - ); - - KDRect bounds((320 - image->width()) / 2, offset, image->width(), image->height()); - - ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr); -} - -void Interface::drawHeader() { - KDContext * ctx = KDIonContext::sharedContext(); - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - drawImage(ctx, ImageStore::Computer, 25); - KDSize fontSize = KDFont::LargeFont->glyphSize(); - int initPos = (320 - fontSize.width() * strlen(Messages::mainTitle)) / 2; - ctx->drawString(Messages::mainTitle, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawMenu() { - // Get the context - KDContext * ctx = KDIonContext::sharedContext(); - // Clear the screen - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - // Draw the image - drawImage(ctx, ImageStore::Computer, 25); - // Get the font size - KDSize largeSize = KDFont::LargeFont->glyphSize(); - KDSize smallSize = KDFont::SmallFont->glyphSize(); - // Draw the title - int initPos = (320 - largeSize.width() * strlen(Messages::mainMenuTitle)) / 2; - ctx->drawString(Messages::mainMenuTitle, KDPoint(initPos, ImageStore::Computer->height() + largeSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); - - // Initialize the slot list - Slot slots[3] = {Slot::A(), Slot::Khi(), Slot::B()}; - char indexes[3] = {'1', '2', '3'}; - - // Set the khi slot index, improve this when Khi will have a dedicated header - const uint8_t khiIndex = 2 - 1; - - // Get the start y position - int y = ImageStore::Computer->height() + (largeSize.height() + 10) + (smallSize.height() + 10); - - // Iterate over the slot list - for (uint8_t i = 0; i < sizeof(indexes) / sizeof(indexes[0]); i++) { - // Get the slot from the list - Slot slot = slots[i]; - // Get the "X - " string - char converted[] = {indexes[i], ' ', '-', ' ', '\0'}; - // Setup the margin - int x = 10; - // If the slot is valid, draw the slot - if (slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid()) { - // Draw the slot number - ctx->drawString(converted, KDPoint(x, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the x position - x += strlen(converted) * smallSize.width(); - // Draw the slot version - ctx->drawString(slot.userlandHeader()->version(), KDPoint(x, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - - // Get if the commit (patchLevel) isn't empty - if (slot.kernelHeader()->patchLevel()[0] != '\0') { - // Increment the x position - x += strlen(slot.userlandHeader()->version()) * smallSize.width() + smallSize.width() * 2; - // Draw the slot commit - ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(x, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the x position - x += strlen(slot.kernelHeader()->patchLevel()) * smallSize.width() + smallSize.width(); - } else { - // Increment the x position - x += strlen(slot.userlandHeader()->version()) * smallSize.width() + smallSize.width(); - } - - const char * OSName = ""; - const char * OSVersion = ""; - // If the slot is Upsilon, draw the slot name - if (slot.userlandHeader()->isOmega() && slot.userlandHeader()->isUpsilon()) { - // Set the OS name - OSName = Messages::upsilon; - // Set the OS version - OSVersion = slot.userlandHeader()->upsilonVersion(); - } else if (slot.userlandHeader()->isOmega()) { - // Get if slot is Khi - bool isKhi = (i == khiIndex); - // If the slot is Khi, draw the slot name (Khi) - if (isKhi) { - // Set the OS name - OSName = Messages::khi; - } else { - // Set the OS name - OSName = Messages::omega; - } - // Set the OS version - OSVersion = slot.userlandHeader()->omegaVersion(); - } else { - // Set the OS name - OSName = Messages::epsilon; - } - // Draw the OS name - ctx->drawString(OSName, KDPoint(x, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the x position - x += strlen(OSName) * smallSize.width() + smallSize.width(); - // Draw the OS version - ctx->drawString(OSVersion, KDPoint(x, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Else, the slot is invalid - } else { - ctx->drawString(Messages::invalidSlot, KDPoint(10, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - } - // Increment the y position - y += smallSize.height() + 10; - } - - // Draw the DFU message - ctx->drawString(Messages::dfuText, KDPoint(10, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - - // Increment the y position - y += smallSize.height() + 10; - // Draw the about message - ctx->drawString(Messages::aboutText, KDPoint(10, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - - // Reboot is disabled for now - // y += smallSize.height() + 10; - // ctx->drawString(Messages::rebootText, KDPoint(10, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - - // Draw the footer - initPos = (320 - smallSize.width() * strlen(Messages::mainTitle)) / 2; - ctx->drawString(Messages::mainTitle, KDPoint(initPos, 240 - smallSize.height() - 10), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawFlasher() { - Interface::drawHeader(); - KDContext * ctx = KDIonContext::sharedContext(); - int y = ImageStore::Computer->height() + (KDFont::LargeFont->glyphSize().height() + 10) + (KDFont::SmallFont->glyphSize().height() + 10); - int initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::dfuSubtitle)) / 2; - ctx->drawString(Messages::dfuSubtitle, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawLoading() { - KDContext * ctx = KDIonContext::sharedContext(); - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - drawImage(ctx, ImageStore::Computer, 25); - Ion::Timing::msleep(250); - KDSize fontSize = KDFont::LargeFont->glyphSize(); - int initPos = (320 - fontSize.width() * strlen(Messages::mainTitle)) / 2; - for (uint8_t i = 0; i < strlen(Messages::mainTitle); i++) { - char tmp[2] = {Messages::mainTitle[i], '\0'}; - ctx->drawString(tmp, KDPoint(initPos + i * (fontSize.width()), ImageStore::Computer->height() + fontSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); - Ion::Timing::msleep(50); - } - Ion::Timing::msleep(500); -} - -void Interface::drawAbout() { - drawHeader(); - // Create the list of about messages - // TODO: Move it to messages.h - char aboutMessages[][38] = { - "This is the bootloader of", - "the Upsilon Calculator.", - "It is used to install", - "and select the OS", - "to boot." - }; - // Get the context - KDContext * ctx = KDIonContext::sharedContext(); - // Get the start Y position - KDSize largeSize = KDFont::LargeFont->glyphSize(); - KDSize smallSize = KDFont::SmallFont->glyphSize(); - int y = ImageStore::Computer->height() + (largeSize.height() + 10) + (smallSize.height() + 10); - // Iterate over the list and draw each message - for (uint8_t i = 0; i < sizeof(aboutMessages) / sizeof(aboutMessages[0]); i++) { - // Get the message - char * actualMessage = aboutMessages[i]; - // Get the start X position - int initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(actualMessage)) / 2; - // Draw the message - ctx->drawString(actualMessage, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the Y position - y += smallSize.height() + 10; - } - - ctx->drawString(Messages::bootloaderVersion, KDPoint((320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::bootloaderVersion)) / 2, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - -} - -void Interface::drawCrash(const char * error) { - KDContext * ctx = KDIonContext::sharedContext(); - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - drawImage(ctx, ImageStore::Computer, 25); - KDSize fontSize = KDFont::LargeFont->glyphSize(); - int initPos = (320 - fontSize.width() * strlen(Messages::crashTitle)) / 2; - ctx->drawString(Messages::crashTitle, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(error)) / 2; - ctx->drawString(error, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10 + KDFont::SmallFont->glyphSize().height() + 10), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::crashText1)) / 2; - ctx->drawString(Messages::crashText1, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10 + KDFont::SmallFont->glyphSize().height() + 10 + KDFont::SmallFont->glyphSize().height() + 10 + 20), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::crashText2)) / 2; - ctx->drawString(Messages::crashText2, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10 + KDFont::SmallFont->glyphSize().height() + 10 + KDFont::SmallFont->glyphSize().height() + 10 + 20 + KDFont::SmallFont->glyphSize().height() + 10), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawRecovery() { - KDContext * ctx = KDIonContext::sharedContext(); - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - drawImage(ctx, ImageStore::Computer, 25); - KDSize fontSize = KDFont::LargeFont->glyphSize(); - int initPos = (320 - fontSize.width() * strlen(Messages::recoveryTitle)) / 2; - int y = ImageStore::Computer->height() + fontSize.height() + 5; - ctx->drawString(Messages::recoveryTitle, KDPoint(initPos, y), KDFont::LargeFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::recoveryText1)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::recoveryText1, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::recoveryText2)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::recoveryText2, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::recoveryText3)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::recoveryText3, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::recoveryText4)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::recoveryText4, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::recoveryText5)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::recoveryText5, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawInstallerSelection() { - // Get the context - KDContext * ctx = KDIonContext::sharedContext(); - // Clear the screen - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); - // Draw the image - drawImage(ctx, ImageStore::Computer, 25); - // Get the font size - KDSize largeSize = KDFont::LargeFont->glyphSize(); - KDSize smallSize = KDFont::SmallFont->glyphSize(); - // Get the start x position - int initPos = (320 - largeSize.width() * strlen(Messages::installerSelectionTitle)) / 2; - // Get the start y position - int y = ImageStore::Computer->height() + largeSize.height() + 10; - // Draw the title - ctx->drawString(Messages::installerSelectionTitle, KDPoint(initPos, y), KDFont::LargeFont, KDColorBlack, KDColorWhite); - // Increment the y position - y += largeSize.height() + 5; - // Get the y position of the subtitle - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::installerText1)) / 2; - // Draw the subtitle - ctx->drawString(Messages::installerText1, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the y position - y += smallSize.height() + 10; - // Set the start x position - initPos = 10; - // Draw the first button (slot flash) - ctx->drawString(Messages::installerText2, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); - // Increment the y position - y += smallSize.height() + 10; - // Draw the second button (bootloader flash) - ctx->drawString(Messages::installerText3, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawBootloaderUpdate() { - Interface::drawHeader(); - KDContext * ctx = KDIonContext::sharedContext(); - int y = ImageStore::Computer->height() + (KDFont::LargeFont->glyphSize().height() + 10) + (KDFont::SmallFont->glyphSize().height() + 10); - int initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::bootloaderSubtitle)) / 2; - ctx->drawString(Messages::bootloaderSubtitle, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); -} - -void Interface::drawEpsilonAdvertisement() { - KDContext * ctx = KDIonContext::sharedContext(); - ctx->fillRect(KDRect(0, 0, 320, 240), KDColorRed); - drawImage(ctx, ImageStore::Computer, 25); - KDSize fontSize = KDFont::LargeFont->glyphSize(); - int initPos = (320 - fontSize.width() * strlen(Messages::epsilonWarningTitle)) / 2; - int y = ImageStore::Computer->height() + fontSize.height() + 15; - ctx->drawString(Messages::epsilonWarningTitle, KDPoint(initPos, y), KDFont::LargeFont, KDColorWhite, KDColorRed); - initPos = (320 - fontSize.width() * strlen(Messages::epsilonWarningText1)) / 2; - y += fontSize.height() + 5; - ctx->drawString(Messages::epsilonWarningText1, KDPoint(initPos, y), KDFont::LargeFont, KDColorWhite, KDColorRed); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::epsilonWarningText2)) / 2; - y += fontSize.height() + 2; - ctx->drawString(Messages::epsilonWarningText2, KDPoint(initPos, y), KDFont::SmallFont, KDColorWhite, KDColorRed); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::epsilonWarningText3)) / 2; - y += KDFont::SmallFont->glyphSize().height() + 5; - ctx->drawString(Messages::epsilonWarningText3, KDPoint(initPos, y), KDFont::SmallFont, KDColorWhite, KDColorRed); - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::epsilonWarningText4)) / 2; - y += KDFont::SmallFont->glyphSize().height() + 10; - ctx->drawString(Messages::epsilonWarningText4, KDPoint(initPos, y), KDFont::SmallFont, KDColorWhite, KDColorRed); - y += KDFont::SmallFont->glyphSize().height() + 10; - initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::epsilonWarningText5)) / 2; - ctx->drawString(Messages::epsilonWarningText5, KDPoint(initPos, y), KDFont::SmallFont, KDColorWhite, KDColorRed); - y += KDFont::SmallFont->glyphSize().height() + 5; - ctx->drawString(Messages::epsilonWarningText6, KDPoint(initPos, y), KDFont::SmallFont, KDColorWhite, KDColorRed); -} - -} diff --git a/bootloader/interface.h b/bootloader/interface.h deleted file mode 100644 index b89c3ce25..000000000 --- a/bootloader/interface.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef BOOTLOADER_INTERFACE -#define BOOTLOADER_INTERFACE - -#include -#include -#include - -namespace Bootloader { -class Interface { - -public: - static void drawImage(KDContext * ctx, const Image * image, int offset); - static void drawLoading(); - static void drawHeader(); - static void drawMenu(); - static void drawFlasher(); - static void drawAbout(); - static void drawCrash(const char * error); - static void drawRecovery(); - static void drawInstallerSelection(); - static void drawBootloaderUpdate(); - static void drawEpsilonAdvertisement(); - -}; - -} - -#endif \ No newline at end of file diff --git a/bootloader/interface/menus/about.cpp b/bootloader/interface/menus/about.cpp new file mode 100644 index 000000000..7e1d176bb --- /dev/null +++ b/bootloader/interface/menus/about.cpp @@ -0,0 +1,20 @@ +#include "about.h" +#include + +Bootloader::AboutMenu::AboutMenu() : Menu(KDColorBlack, KDColorWhite, Messages::aboutMenuTitle, Messages::bootloaderVersion) { + setup(); +} + +void Bootloader::AboutMenu::setup() { + m_default_columns[0] = Column(Messages::aboutMessage1, k_small_font, 0, true); + m_default_columns[1] = Column(Messages::aboutMessage2, k_small_font, 0, true); + m_default_columns[2] = Column(Messages::aboutMessage3, k_small_font, 0, true); + m_default_columns[3] = Column(Messages::aboutMessage4, k_small_font, 0, true); + m_default_columns[4] = Column(Messages::aboutMessage5, k_small_font, 0, true); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); + m_columns[1] = ColumnBinder(&m_default_columns[1]); + m_columns[2] = ColumnBinder(&m_default_columns[2]); + m_columns[3] = ColumnBinder(&m_default_columns[3]); + m_columns[4] = ColumnBinder(&m_default_columns[4]); +} \ No newline at end of file diff --git a/bootloader/interface/menus/about/about.h b/bootloader/interface/menus/about.h similarity index 61% rename from bootloader/interface/menus/about/about.h rename to bootloader/interface/menus/about.h index 96dc86c11..4f3df1c91 100644 --- a/bootloader/interface/menus/about/about.h +++ b/bootloader/interface/menus/about.h @@ -1,5 +1,5 @@ -#ifndef _BOOTLOADER_INTERFACE_ABOUT_ABOUT_H_ -#define _BOOTLOADER_INTERFACE_ABOUT_ABOUT_H_ +#ifndef _BOOTLOADER_INTERFACE_ABOUT_H_ +#define _BOOTLOADER_INTERFACE_ABOUT_H_ #include @@ -9,7 +9,7 @@ namespace Bootloader { AboutMenu(); void setup() override; - + void post_open() override {}; }; } diff --git a/bootloader/interface/menus/about/about.cpp b/bootloader/interface/menus/about/about.cpp deleted file mode 100644 index 4c73b95bc..000000000 --- a/bootloader/interface/menus/about/about.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "about.h" - -Bootloader::AboutMenu::AboutMenu() : Menu(KDColorBlack, KDColorWhite, Messages::aboutMenuTitle, Messages::bootloaderVersion) { - setup(); -} - -void Bootloader::AboutMenu::setup() { - m_colomns[0] = Colomn("This is the bootloader of", k_small_font, 0, true); - m_colomns[1] = Colomn("the Upsilon Calculator.", k_small_font, 0, true); - m_colomns[2] = Colomn("It is used to install", k_small_font, 0, true); - m_colomns[3] = Colomn("and select the OS", k_small_font, 0, true); - m_colomns[4] = Colomn("to boot.", k_small_font, 0, true); -} \ No newline at end of file diff --git a/bootloader/interface/menus/crash.cpp b/bootloader/interface/menus/crash.cpp new file mode 100644 index 000000000..d7ed3a19e --- /dev/null +++ b/bootloader/interface/menus/crash.cpp @@ -0,0 +1,22 @@ +#include "crash.h" + +Bootloader::CrashMenu::CrashMenu(const char * err) : Menu(KDColorBlack, KDColorWhite, Bootloader::Messages::bootloaderCrashTitle, Bootloader::Messages::mainTitle), m_error(err) { + setup(); +} + +void Bootloader::CrashMenu::setup() { + m_default_columns[0] = Column(m_error, k_large_font, 0, true); + m_default_columns[1] = Column(Bootloader::Messages::bootloaderCrashMessage1, k_small_font, 0, true); + m_default_columns[2] = Column(Bootloader::Messages::bootloaderCrashMessage2, k_small_font, 0, true); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); + m_columns[1] = ColumnBinder(&m_default_columns[1]); + m_columns[2] = ColumnBinder(&m_default_columns[2]); +} + +void Bootloader::CrashMenu::post_open() { + // We override the open method + for (;;) { + // Infinite loop + } +} \ No newline at end of file diff --git a/bootloader/interface/menus/crash.h b/bootloader/interface/menus/crash.h new file mode 100644 index 000000000..c73c3dbd6 --- /dev/null +++ b/bootloader/interface/menus/crash.h @@ -0,0 +1,19 @@ +#ifndef _BOOTLOADER_INTERFACE_MENUS_CRASH_H_ +#define _BOOTLOADER_INTERFACE_MENUS_CRASH_H_ + +#include + +namespace Bootloader { + class CrashMenu : public Menu { + public: + CrashMenu(const char * error); + + void setup() override; + void post_open() override; + + private: + const char * m_error; + }; +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/menus/dfu.cpp b/bootloader/interface/menus/dfu.cpp new file mode 100644 index 000000000..537108f3c --- /dev/null +++ b/bootloader/interface/menus/dfu.cpp @@ -0,0 +1,37 @@ +#include "dfu.h" +#include +#include + +Bootloader::DfuMenu::DfuMenu(const char * text, const USBData * data) : Menu(KDColorBlack, KDColorWhite, Messages::dfuTitle, Messages::mainTitle), m_submenu_text(text), m_data(data) { + setup(); +} + +void Bootloader::DfuMenu::setup() { + m_default_columns[0] = Column(m_submenu_text, k_small_font, 0, true); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); +} + +void Bootloader::DfuMenu::post_open() { + // We override the open method + if (!m_data->getData().isProtectedInternal() && m_data->getData().isProtectedExternal()) { + // Because we want to flash the internal, we will jump into the stm32 bootloader + Bootloader::Boot::jumpToInternalBootloader(); + return; // We never reach this point + } + for (;;) { + Ion::USB::enable(); + do { + uint64_t scan = Ion::Keyboard::scan(); + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { + Ion::USB::disable(); + forceExit(); + return; + } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { + Ion::Power::standby(); + return; + } + } while (!Ion::USB::isEnumerated()); + Ion::USB::DFU(true, (void *)m_data); + } +} \ No newline at end of file diff --git a/bootloader/interface/menus/dfu.h b/bootloader/interface/menus/dfu.h new file mode 100644 index 000000000..ddb957fcb --- /dev/null +++ b/bootloader/interface/menus/dfu.h @@ -0,0 +1,21 @@ +#ifndef _BOOTLOADER_INTERFACE_MENUS_DFU_H_ +#define _BOOTLOADER_INTERFACE_MENUS_DFU_H_ + +#include +#include + +namespace Bootloader { + class DfuMenu : public Menu { + public: + DfuMenu(const char * submenu, const USBData * usbData); + + void setup() override; + void post_open() override; + + private: + const char * m_submenu_text; + const USBData * m_data; + }; +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/menus/home.cpp b/bootloader/interface/menus/home.cpp new file mode 100644 index 000000000..7805d7996 --- /dev/null +++ b/bootloader/interface/menus/home.cpp @@ -0,0 +1,144 @@ +#include "home.h" +#include +#include +#include +#include + +Bootloader::AboutMenu * Bootloader::HomeMenu::aboutMenu() { + static AboutMenu * aboutMenu = new AboutMenu(); + return aboutMenu; +} + +Bootloader::InstallerMenu * Bootloader::HomeMenu::installerMenu() { + static InstallerMenu * installerMenu = new InstallerMenu(); + return installerMenu; +} + +Bootloader::HomeMenu::HomeMenu() : Menu(KDColorBlack, KDColorWhite, Messages::homeTitle, Messages::mainTitle) { + setup(); +} + +bool slotA_submenu() { + if (Bootloader::Slot::isFullyValid(Bootloader::Slot::A())) { + Bootloader::Boot::bootSlot(Bootloader::Slot::A()); + return true; + } + return false; +} + +bool slotKhi_submenu() { + if (Bootloader::Slot::isFullyValid(Bootloader::Slot::Khi())) { + Bootloader::Boot::bootSlot(Bootloader::Slot::Khi()); + return true; + } + return false; +} + +bool slotB_submenu() { + if (Bootloader::Slot::isFullyValid(Bootloader::Slot::B())) { + Bootloader::Boot::bootSlot(Bootloader::Slot::B()); + return true; + } + return false; +} + +bool installer_submenu() { + Bootloader::HomeMenu::installerMenu()->open(); + return true; +} + +bool about_submenu() { + Bootloader::HomeMenu::aboutMenu()->open(); + return true; +} + +const char * Bootloader::HomeMenu::slotA_text() { + return Slot::isFullyValid(Slot::A()) ? Messages::homeSlotASubmenu : Messages::invalidSlot; +} + +const char * Bootloader::HomeMenu::slotA_kernel_text() { + return Slot::isFullyValid(Slot::A()) ? Slot::A().kernelHeader()->patchLevel() : nullptr; +} + +const char * Bootloader::HomeMenu::slotA_version_text() { + return Slot::isFullyValid(Slot::A()) ? Slot::A().userlandHeader()->isOmega() && Slot::A().userlandHeader()->isUpsilon() ? Slot::A().userlandHeader()->upsilonVersion() : Slot::A().userlandHeader()->isOmega() ? Slot::A().userlandHeader()->omegaVersion() : Slot::A().kernelHeader()->version() : nullptr; +} + +const char * Bootloader::HomeMenu::slotA_os_text() { + if (Slot::isFullyValid(Slot::A())) { + if (Slot::A().userlandHeader()->isOmega() && Slot::A().userlandHeader()->isUpsilon()) { + return Messages::upsilonSlot; + } else if (Slot::A().userlandHeader()->isOmega()) { + return Messages::omegaSlot; + } else { + return Messages::epsilonSlot; + } + } + return nullptr; +} + +const char * Bootloader::HomeMenu::slotKhi_text() { + return Slot::isFullyValid(Slot::Khi()) ? Messages:: homeSlotKhiSubmenu : Messages::invalidSlot; +} + +const char * Bootloader::HomeMenu::slotKhi_kernel_text() { + return Slot::isFullyValid(Slot::Khi()) ? Slot::Khi().kernelHeader()->patchLevel() : nullptr; +} + +const char * Bootloader::HomeMenu::slotKhi_os_text() { + if (Slot::isFullyValid(Slot::Khi())) { + if (Slot::Khi().userlandHeader()->isOmega() && Slot::Khi().userlandHeader()->isUpsilon()) { + return Messages::upsilonSlot; + } else if (Slot::Khi().userlandHeader()->isOmega()) { + return Messages::omegaSlot; + } else { + return Messages::epsilonSlot; + } + } + return nullptr; +} + +const char * Bootloader::HomeMenu::slotKhi_version_text() { + return Slot::isFullyValid(Slot::Khi()) ? Slot::Khi().userlandHeader()->isOmega() && Slot::Khi().userlandHeader()->isUpsilon() ? Slot::Khi().userlandHeader()->upsilonVersion() : Slot::Khi().userlandHeader()->isOmega() ? Slot::Khi().userlandHeader()->omegaVersion() : Slot::Khi().kernelHeader()->version() : nullptr; +} + +const char * Bootloader::HomeMenu::slotB_text() { + return Slot::isFullyValid(Slot::B()) ? Messages::homeSlotBSubmenu : Messages::invalidSlot; +} + +const char * Bootloader::HomeMenu::slotB_kernel_text() { + return Slot::isFullyValid(Slot::B()) ? Slot::B().kernelHeader()->patchLevel() : nullptr; +} + +const char * Bootloader::HomeMenu::slotB_os_text() { + if (Slot::isFullyValid(Slot::B())) { + if (Slot::B().userlandHeader()->isOmega() && Slot::B().userlandHeader()->isUpsilon()) { + return Messages::upsilonSlot; + } else if (Slot::B().userlandHeader()->isOmega()) { + return Messages::omegaSlot; + } else { + return Messages::epsilonSlot; + } + } + return nullptr; +} + +const char * Bootloader::HomeMenu::slotB_version_text() { + return Slot::isFullyValid(Slot::B()) ? Slot::B().userlandHeader()->isOmega() && Slot::B().userlandHeader()->isUpsilon() ? Slot::B().userlandHeader()->upsilonVersion() : Slot::B().userlandHeader()->isOmega() ? Slot::B().userlandHeader()->omegaVersion() : Slot::B().kernelHeader()->version() : nullptr; +} + +void Bootloader::HomeMenu::setup() { + m_slot_columns[0] = SlotColumn(slotA_text(), slotA_kernel_text(), slotA_os_text(), slotA_version_text(), Ion::Keyboard::Key::One, k_small_font, 10, false, &slotA_submenu); + m_slot_columns[1] = SlotColumn(slotKhi_text(), slotKhi_kernel_text(), slotKhi_os_text(), slotKhi_version_text(), Ion::Keyboard::Key::Two, k_small_font, 10, false, &slotKhi_submenu); + m_slot_columns[2] = SlotColumn(slotB_text(), slotB_kernel_text(), slotB_os_text(), slotB_version_text(), Ion::Keyboard::Key::Three, k_small_font, 10, false, &slotB_submenu); + m_default_columns[0] = Column(Messages::homeInstallerSubmenu, Ion::Keyboard::Key::Four, k_small_font, 10, false, &installer_submenu); + m_default_columns[1] = Column(Messages::homeAboutSubmenu, Ion::Keyboard::Key::Five, k_small_font, 10, false, &about_submenu); + + + m_columns[0] = ColumnBinder(&m_slot_columns[0]); + m_columns[1] = ColumnBinder(&m_slot_columns[1]); + m_columns[2] = ColumnBinder(&m_slot_columns[2]); + m_columns[3] = ColumnBinder(&m_default_columns[0]); + m_columns[4] = ColumnBinder(&m_default_columns[1]); + +} \ No newline at end of file diff --git a/bootloader/interface/menus/home.h b/bootloader/interface/menus/home.h new file mode 100644 index 000000000..00de3edc3 --- /dev/null +++ b/bootloader/interface/menus/home.h @@ -0,0 +1,36 @@ +#ifndef _BOOTLOADER_INTERFACE_MENUS_HOME_H_ +#define _BOOTLOADER_INTERFACE_MENUS_HOME_H_ + +#include +#include +#include + +namespace Bootloader { + class HomeMenu : public Menu { + public: + HomeMenu(); + + void setup() override; + void post_open() override {}; + + static AboutMenu * aboutMenu(); + static InstallerMenu * installerMenu(); + + private: + const char * slotA_text(); + const char * slotA_kernel_text(); + const char * slotA_os_text(); + const char * slotA_version_text(); + const char * slotKhi_text(); + const char * slotKhi_kernel_text(); + const char * slotKhi_os_text(); + const char * slotKhi_version_text(); + const char * slotB_text(); + const char * slotB_kernel_text(); + const char * slotB_os_text(); + const char * slotB_version_text(); + + }; +} + +#endif diff --git a/bootloader/interface/menus/home/home.cpp b/bootloader/interface/menus/home/home.cpp deleted file mode 100644 index 2529547e5..000000000 --- a/bootloader/interface/menus/home/home.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "home.h" -#include -#include - -Bootloader::AboutMenu * Bootloader::HomeMenu::aboutMenu() { - static AboutMenu * aboutMenu = new AboutMenu(); - return aboutMenu; -} - -Bootloader::HomeMenu::HomeMenu() : Menu(KDColorBlack, KDColorWhite, Messages::mainMenuTitle, Messages::mainTitle) { - setup(); -} - -bool slotA_submenu() { - if (Bootloader::Slot::isFullyValid(Bootloader::Slot::A())) { - - } - return false; -} - -bool slotKhi_submenu() { - if (Bootloader::Slot::isFullyValid(Bootloader::Slot::Khi())) { - - } - return false; -} - -bool slotB_submenu() { - if (Bootloader::Slot::isFullyValid(Bootloader::Slot::B())) { - - } - return false; -} - -bool installer_submenu() { - return false; -} - -bool about_submenu() { - Bootloader::HomeMenu::aboutMenu()->open(); - return true; -} - -const char * Bootloader::HomeMenu::slotA_text() { - return Slot::isFullyValid(Slot::A()) ? "1 - Slot A" : Messages::invalidSlot; -} - -const char * Bootloader::HomeMenu::slotKhi_text() { - return Slot::isFullyValid(Slot::Khi()) ? "2 - Slot Khi" : Messages::invalidSlot; -} - -const char * Bootloader::HomeMenu::slotB_text() { - return Slot::isFullyValid(Slot::B()) ? "3 - Slot B" : Messages::invalidSlot; -} - -void Bootloader::HomeMenu::setup() { - m_colomns[0] = Colomn(slotA_text(), Ion::Keyboard::Key::One, k_small_font, 30, false, &slotA_submenu); - m_colomns[1] = Colomn(slotKhi_text(), Ion::Keyboard::Key::Two, k_small_font, 30, false, &slotKhi_submenu); - m_colomns[2] = Colomn(slotB_text(), Ion::Keyboard::Key::Three, k_small_font, 30, false, &slotB_submenu); - m_colomns[3] = Colomn("4- installer", Ion::Keyboard::Key::Four, k_small_font, 30, false, &installer_submenu); - m_colomns[4] = Colomn("5- about", Ion::Keyboard::Key::Five, k_small_font, 30, false, &about_submenu); -} \ No newline at end of file diff --git a/bootloader/interface/menus/home/home.h b/bootloader/interface/menus/home/home.h deleted file mode 100644 index 6f6c43037..000000000 --- a/bootloader/interface/menus/home/home.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _BOOTLOADER_INTERFACE_HOME_HOME_H_ -#define _BOOTLOADER_INTERFACE_HOME_HOME_H_ - -#include -#include - -namespace Bootloader { - class HomeMenu : public Menu { - public: - HomeMenu(); - - void setup() override; - static AboutMenu * aboutMenu(); - - private: - const char * slotA_text(); - const char * slotKhi_text(); - const char * slotB_text(); - - }; -} - -#endif diff --git a/bootloader/interface/menus/installer.cpp b/bootloader/interface/menus/installer.cpp new file mode 100644 index 000000000..a82b4aebe --- /dev/null +++ b/bootloader/interface/menus/installer.cpp @@ -0,0 +1,41 @@ +#include "installer.h" +#include +#include + +#include + +Bootloader::DfuMenu * Bootloader::InstallerMenu::SlotsDFU() { + USBData data = USBData::DEFAULT(); + static DfuMenu * slotsDfu = new DfuMenu(Messages::dfuSlotsUpdate, &data); + return slotsDfu; +} + +Bootloader::DfuMenu * Bootloader::InstallerMenu::BootloaderDFU() { + USBData data = USBData::BOOTLOADER_UPDATE(); + static DfuMenu * bootloaderDfu = new DfuMenu(Messages::dfuBootloaderUpdate, &data); + return bootloaderDfu; +} + +Bootloader::InstallerMenu::InstallerMenu() : Menu(KDColorBlack, KDColorWhite, Messages::installerTitle, Messages::mainTitle) { + setup(); +} + +bool slots_submenu() { + Bootloader::InstallerMenu::SlotsDFU()->open(); + return true; +} + +bool bootloader_submenu() { + Bootloader::InstallerMenu::BootloaderDFU()->open(); + return true; +} + +void Bootloader::InstallerMenu::setup() { + m_default_columns[0] = Column(Messages::installerText1, k_large_font, 0, true); + m_default_columns[1] = Column(Messages::installerSlotsSubmenu, Ion::Keyboard::Key::One, k_small_font, 30, false, &slots_submenu); + m_default_columns[2] = Column(Messages::installerBootloaderSubmenu, Ion::Keyboard::Key::Two, k_small_font, 30, false, &bootloader_submenu); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); + m_columns[1] = ColumnBinder(&m_default_columns[1]); + m_columns[2] = ColumnBinder(&m_default_columns[2]); +} \ No newline at end of file diff --git a/bootloader/interface/menus/installer.h b/bootloader/interface/menus/installer.h new file mode 100644 index 000000000..b68a49aab --- /dev/null +++ b/bootloader/interface/menus/installer.h @@ -0,0 +1,20 @@ +#ifndef _BOOTLOADER_INTERFACE_MENUS_INSTALLER_H_ +#define _BOOTLOADER_INTERFACE_MENUS_INSTALLER_H_ + +#include +#include + +namespace Bootloader { + class InstallerMenu : public Menu { + public: + InstallerMenu(); + + void setup() override; + void post_open() override {}; + + static DfuMenu * SlotsDFU(); + static DfuMenu * BootloaderDFU(); + }; +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/menus/installer/installer.h b/bootloader/interface/menus/installer/installer.h deleted file mode 100644 index be9f49fb4..000000000 --- a/bootloader/interface/menus/installer/installer.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BOOTLOADER_INTERFACE_MENUS_INSTALLER_INSTALLER_H_ -#define _BOOTLOADER_INTERFACE_MENUS_INSTALLER_INSTALLER_H_ - -#include - -namespace Bootloader { - class InstallerMenu : public Menu { - public: - InstallerMenu(); - - void setup() override; - }; -} - -#endif \ No newline at end of file diff --git a/bootloader/interface/menus/slot_recovery.cpp b/bootloader/interface/menus/slot_recovery.cpp new file mode 100644 index 000000000..d026f2be3 --- /dev/null +++ b/bootloader/interface/menus/slot_recovery.cpp @@ -0,0 +1,39 @@ +#include "slot_recovery.h" +#include + +Bootloader::SlotRecoveryMenu::SlotRecoveryMenu(USBData * usb) : Menu(KDColorBlack, KDColorWhite, Messages::recoveryTitle, Messages::mainTitle), m_data(usb) { + setup(); +} + +void Bootloader::SlotRecoveryMenu::setup() { + m_default_columns[0] = Column(Messages::recoveryMessage1, k_small_font, 0, true); + m_default_columns[1] = Column(Messages::recoveryMessage2, k_small_font, 0, true); + m_default_columns[2] = Column(Messages::recoveryMessage3, k_small_font, 0, true); + m_default_columns[3] = Column(Messages::recoveryMessage4, k_small_font, 0, true); + m_default_columns[4] = Column(Messages::recoveryMessage5, k_small_font, 0, true); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); + m_columns[1] = ColumnBinder(&m_default_columns[1]); + m_columns[2] = ColumnBinder(&m_default_columns[2]); + m_columns[3] = ColumnBinder(&m_default_columns[3]); + m_columns[4] = ColumnBinder(&m_default_columns[4]); +} + +void Bootloader::SlotRecoveryMenu::post_open() { + // We override the open method + for (;;) { + Ion::USB::enable(); + do { + uint64_t scan = Ion::Keyboard::scan(); + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { + Ion::USB::disable(); + forceExit(); + return; + } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { + Ion::Power::standby(); + return; + } + } while (!Ion::USB::isEnumerated()); + Ion::USB::DFU(true, (void *)m_data); + } +} \ No newline at end of file diff --git a/bootloader/interface/menus/slot_recovery.h b/bootloader/interface/menus/slot_recovery.h new file mode 100644 index 000000000..452868dee --- /dev/null +++ b/bootloader/interface/menus/slot_recovery.h @@ -0,0 +1,19 @@ +#ifndef _BOOTLOADER_INTERFACE_MENU_SLOT_RECOVERY_H +#define _BOOTLOADER_INTERFACE_MENU_SLOT_RECOVERY_H + +#include +#include + +namespace Bootloader { + class SlotRecoveryMenu : public Menu { + public: + SlotRecoveryMenu(USBData * usbData); + + void setup() override; + void post_open() override; + private: + const USBData * m_data; + }; +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/menus/warning.cpp b/bootloader/interface/menus/warning.cpp new file mode 100644 index 000000000..316dfde69 --- /dev/null +++ b/bootloader/interface/menus/warning.cpp @@ -0,0 +1,35 @@ +#include "warning.h" +#include +#include + +Bootloader::WarningMenu::WarningMenu() : Menu(KDColorWhite, KDColorRed, Messages::epsilonWarningTitle, Messages::mainTitle, false, 3) { + setup(); +} + +bool proceed() { + Bootloader::Boot::bootSelectedSlot(); + return true; +} + +bool backoff() { + if (Bootloader::Boot::config()->slot() != nullptr) { + Bootloader::Boot::config()->clearSlot(); + } + return true; +} + +void Bootloader::WarningMenu::setup() { + m_default_columns[0] = Column(Messages::epsilonWarningMessage1, k_small_font, 0, true); + m_default_columns[1] = Column(Messages::epsilonWarningMessage2, k_small_font, 0, true); + m_default_columns[2] = Column(Messages::epsilonWarningMessage3, k_small_font, 0, true); + m_default_columns[3] = Column(Messages::epsilonWarningMessage4, k_small_font, 0, true); + m_default_columns[4] = Column(Messages::epsilonWarningMessage5, Ion::Keyboard::Key::EXE, k_small_font, 0, true, &proceed); + m_default_columns[5] = Column(Messages::epsilonWarningMessage6, Ion::Keyboard::Key::Back, k_small_font, 0, true, &backoff); + + m_columns[0] = ColumnBinder(&m_default_columns[0]); + m_columns[1] = ColumnBinder(&m_default_columns[1]); + m_columns[2] = ColumnBinder(&m_default_columns[2]); + m_columns[3] = ColumnBinder(&m_default_columns[3]); + m_columns[4] = ColumnBinder(&m_default_columns[4]); + m_columns[5] = ColumnBinder(&m_default_columns[5]); +} \ No newline at end of file diff --git a/bootloader/interface/menus/warning.h b/bootloader/interface/menus/warning.h new file mode 100644 index 000000000..bc98a5640 --- /dev/null +++ b/bootloader/interface/menus/warning.h @@ -0,0 +1,17 @@ +#ifndef _BOOTLOADER_INTERFACE_MENUS_WARNING_H_ +#define _BOOTLOADER_INTERFACE_MENUS_WARNING_H_ + +#include +#include + +namespace Bootloader { + class WarningMenu : public Menu { + public: + WarningMenu(); + + void setup() override; + void post_open() override {}; + }; +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/src/menu.cpp b/bootloader/interface/src/menu.cpp index 6b197e4d1..1d81287ae 100644 --- a/bootloader/interface/src/menu.cpp +++ b/bootloader/interface/src/menu.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -9,7 +9,7 @@ const Ion::Keyboard::Key Bootloader::Menu::k_breaking_keys[]; void Bootloader::Menu::setup() { - // Here we add the colomns to the menu. + // Here we add the columns to the menu. } void Bootloader::Menu::open(bool noreturn) { @@ -17,8 +17,10 @@ void Bootloader::Menu::open(bool noreturn) { uint64_t scan = 0; bool exit = false; + + post_open(); - while(!exit) { + while(!exit && !m_forced_exit) { scan = Ion::Keyboard::scan(); exit = !handleKey(scan); if (noreturn) { @@ -40,13 +42,17 @@ void Bootloader::Menu::showMenu() { ctx->drawString(m_title, KDPoint(x, y), k_large_font, m_foreground, m_background); y += largeFontHeight() + 10; - //TODO: center the colomns if m_centerY is true + //TODO: center the columns if m_centerY is true - for (Colomn & colomn : m_colomns) { - if (colomn.isNull()) { - break; + for (ColumnBinder column : m_columns) { + if (column.isNull()) { + continue; + } + if (column.type() == ColumnType::SLOT) { + y += ((SlotColumn *)column.getColumn())->draw(ctx, y, m_background, m_foreground) + m_margin; + } else if (column.type() == ColumnType::DEFAULT) { + y += ((Column *)column.getColumn())->draw(ctx, y, m_background, m_foreground) + m_margin; } - y += colomn.draw(ctx, y, m_background, m_foreground) + k_colomns_margin; } if (m_bottom != nullptr) { @@ -66,26 +72,32 @@ bool Bootloader::Menu::handleKey(uint64_t key) { Ion::Power::standby(); return false; } - for (Colomn & colomn : this->m_colomns) { - if (colomn.isNull() || !colomn.isClickable()) { + for (ColumnBinder column : m_columns) { + if (column.isNull()) { continue; } else { - if (colomn.didHandledEvent(key)) { - redraw(); + if (column.type() == ColumnType::SLOT) { + if (((SlotColumn *)column.getColumn())->didHandledEvent(key)) { + redraw(); + } + } else if (column.type() == ColumnType::DEFAULT) { + if (((Column *)column.getColumn())->didHandledEvent(key)) { + redraw(); + } } } } return true; } -bool Bootloader::Menu::Colomn::didHandledEvent(uint64_t key) { +bool Bootloader::Menu::Column::didHandledEvent(uint64_t key) { if (isMyKey(key) && isClickable()) { return m_callback(); } return false; } -int Bootloader::Menu::Colomn::draw(KDContext * ctx, int y, KDColor background, KDColor foreground) { +int Bootloader::Menu::Column::draw(KDContext * ctx, int y, KDColor background, KDColor foreground) { int x = m_extraX; if (m_center) { x += Bootloader::Menu::calculateCenterX(m_text, m_font->glyphSize().width()); @@ -93,3 +105,32 @@ int Bootloader::Menu::Colomn::draw(KDContext * ctx, int y, KDColor background, K ctx->drawString(m_text, KDPoint(x, y), m_font, foreground, background); return m_font->glyphSize().height(); } + +int Bootloader::Menu::SlotColumn::draw(KDContext * ctx, int y, KDColor background, KDColor foreground) { + int x = m_extraX; + + int width = strlen(m_text); + if (m_kernalPatch != nullptr) { + width += strlen(m_kernalPatch) + m_font->glyphSize().width(); + } + if (m_osType != nullptr) { + width += strlen(m_osType) + m_font->glyphSize().width(); + } + if (m_center) { + x += Bootloader::Menu::getScreen().width() - width * m_font->glyphSize().width(); + } + ctx->drawString(m_text, KDPoint(x, y), m_font, foreground, background); + x += strlen(m_text) * m_font->glyphSize().width() + m_font->glyphSize().width(); + if (m_kernalPatch != nullptr) { + ctx->drawString(m_kernalPatch, KDPoint(x, y), m_font, foreground, background); + } + x += strlen(m_kernalPatch) * m_font->glyphSize().width() + m_font->glyphSize().width(); + if (m_osType != nullptr) { + ctx->drawString(m_osType, KDPoint(x, y), m_font, foreground, background); + } + x += strlen(m_osType) * m_font->glyphSize().width() + m_font->glyphSize().width(); + if (m_kernelVersion != nullptr) { + ctx->drawString(m_kernelVersion, KDPoint(x, y), m_font, foreground, background); + } + return m_font->glyphSize().height(); +} diff --git a/bootloader/interface/src/menu.h b/bootloader/interface/src/menu.h index 46cb56017..da591a022 100644 --- a/bootloader/interface/src/menu.h +++ b/bootloader/interface/src/menu.h @@ -2,48 +2,82 @@ #define _BOOTLOADER_MENU_H_ #include -#include +#include #include namespace Bootloader { class Menu { public: - Menu() : m_colomns(), m_background(KDColorWhite), m_title(Messages::mainTitle), m_foreground(KDColorBlack), m_bottom(nullptr), m_centerY(false) { - setup(); - }; - Menu(KDColor forground, KDColor background, const char * title) : m_colomns(), m_background(background), m_title(title), m_foreground(forground), m_bottom(nullptr), m_centerY(false) { - setup(); - }; - Menu(KDColor forground, KDColor background, const char * title, const char * bottom) : m_colomns(), m_background(background), m_title(title), m_foreground(forground), m_bottom(bottom), m_centerY(false) { - setup(); - }; - Menu(KDColor forground, KDColor background, const char * title, const char * bottom, bool centerY) : m_colomns(), m_background(background), m_title(title), m_foreground(forground), m_bottom(bottom), m_centerY(centerY) { + Menu() : Menu(KDColorBlack, KDColorWhite, Messages::mainTitle) { }; + Menu(KDColor forground, KDColor background, const char * title) : Menu(forground, background, title, nullptr) {}; + Menu(KDColor forground, KDColor background, const char * title, const char * bottom) : Menu(forground, background, title, bottom, false) {}; + Menu(KDColor forground, KDColor background, const char * title, const char * bottom, bool centerY) : Menu(forground, background, title, bottom, centerY, k_columns_margin) {}; + Menu(KDColor forground, KDColor background, const char * title, const char * bottom, bool centerY, int margin) : m_columns(), m_default_columns(), m_slot_columns(), m_background(background), m_title(title), m_foreground(forground), m_bottom(bottom), m_centerY(centerY), m_forced_exit(false), m_margin(margin) { setup(); } + static const int k_columns_margin = 5; virtual void setup() = 0; + virtual void post_open() = 0; + + enum ColumnType { + DEFAULT, + SLOT + }; - class Colomn { + class Column { public: - Colomn() : m_text(nullptr), m_key(Ion::Keyboard::Key::None), m_font(KDFont::SmallFont), m_extraX(0), m_center(false), m_callback(nullptr) {}; - Colomn(const char * t, Ion::Keyboard::Key k, const KDFont * font, int extraX, bool center, bool(*pointer)()) : m_text(t), m_key(k), m_font(font), m_extraX(extraX), m_center(center), m_callback(pointer), m_clickable(true) {}; - Colomn(const char * t, const KDFont * font, int extraX, bool center) : m_text(t), m_key(Ion::Keyboard::Key::None), m_font(font), m_extraX(extraX), m_center(center), m_callback(nullptr), m_clickable(false) {}; + Column() : m_text(nullptr), m_key(Ion::Keyboard::Key::None), m_font(KDFont::SmallFont), m_extraX(0), m_center(false), m_callback(nullptr), m_clickable(false) {}; + + Column(const char * t, Ion::Keyboard::Key k, const KDFont * font, int extraX, bool center, bool(*pointer)()) : m_text(t), m_key(k), m_font(font), m_extraX(extraX), m_center(center), m_callback(pointer), m_clickable(true) {}; + Column(const char * t, const KDFont * font, int extraX, bool center) : m_text(t), m_key(Ion::Keyboard::Key::None), m_font(font), m_extraX(extraX), m_center(center), m_callback(nullptr), m_clickable(false) {}; bool isNull() const { return m_text == nullptr; }; bool isClickable() const { return m_clickable; }; bool didHandledEvent(uint64_t key); - int draw(KDContext * ctx, int y, KDColor background, KDColor foreground); + virtual int draw(KDContext * ctx, int y, KDColor background, KDColor foreground); + virtual int columnType() { return ColumnType::DEFAULT; }; private: bool isMyKey(uint64_t key) const { return Ion::Keyboard::State(m_key) == key; }; - + protected: const char * m_text; Ion::Keyboard::Key m_key; const KDFont * m_font; int m_extraX; bool m_center; - bool m_clickable; bool (*m_callback)(); + bool m_clickable; + }; + + class SlotColumn : public Column { + public: + SlotColumn() : Column(), m_kernalPatch(nullptr), m_osType(nullptr), m_kernelVersion(nullptr) {}; + + SlotColumn(const char * t, Ion::Keyboard::Key k, const KDFont * font, int extraX, bool center, bool(*pointer)()) : Column(t, k, font, extraX, center, pointer), m_kernalPatch(nullptr), m_osType(nullptr), m_kernelVersion(nullptr) {}; + SlotColumn(const char * t, const char * k, const char * o, const char * kernelV, Ion::Keyboard::Key key, const KDFont * font, int extraX, bool center, bool(*pointer)()) : Column(t, key, font, extraX, center, pointer), m_kernalPatch(k), m_osType(o), m_kernelVersion(kernelV) {}; + + int draw(KDContext * ctx, int y, KDColor background, KDColor foreground) override; + virtual int columnType() { return ColumnType::SLOT; }; + + private: + const char * m_kernalPatch; + const char * m_osType; + const char * m_kernelVersion; + }; + + class ColumnBinder { + public: + ColumnBinder() : m_pointer(nullptr), m_type(ColumnType::DEFAULT) {}; + ColumnBinder(Column * pointer) : m_pointer(pointer), m_type(ColumnType::DEFAULT) {}; + ColumnBinder(SlotColumn * pointer) : m_pointer(pointer), m_type(ColumnType::SLOT) {}; + + bool isNull() const { return m_pointer == nullptr; }; + void * getColumn() const { return m_pointer; }; + ColumnType type() const { return m_type; }; + private: + void * m_pointer; + ColumnType m_type; }; void open(bool noreturn = false); @@ -56,9 +90,11 @@ namespace Bootloader { static const KDRect getScreen() { return KDRect(0, 0, 320, 240); }; + protected: + void forceExit() { m_forced_exit = true; }; + private: - static const int k_max_colomns = 5; - static const int k_colomns_margin = 5; + static const int k_max_columns = 6; static constexpr Ion::Keyboard::Key k_breaking_keys[] = {Ion::Keyboard::Key::Back, Ion::Keyboard::Key::Home}; @@ -72,12 +108,18 @@ namespace Bootloader { void showMenu(); protected: - Colomn m_colomns[k_max_colomns]; + ColumnBinder m_columns[k_max_columns]; + // Columns Storage + Column m_default_columns[k_max_columns]; + SlotColumn m_slot_columns[k_max_columns]; KDColor m_background; KDColor m_foreground; const char * m_title; const char * m_bottom; bool m_centerY; + int m_margin; + private: + bool m_forced_exit; }; } diff --git a/bootloader/interface/static/interface.cpp b/bootloader/interface/static/interface.cpp new file mode 100644 index 000000000..817b6f2c0 --- /dev/null +++ b/bootloader/interface/static/interface.cpp @@ -0,0 +1,68 @@ + +#include +#include +#include +#include +#include + +#include + +namespace Bootloader { + +void Interface::drawImage(KDContext * ctx, const Image * image, int offset) { + const uint8_t * data; + size_t size; + size_t pixelBufferSize; + + if (image != nullptr) { + data = image->compressedPixelData(); + size = image->compressedPixelDataSize(); + pixelBufferSize = image->width() * image->height(); + } else { + return; + } + + KDColor pixelBuffer[4000]; + assert(pixelBufferSize <= 4000); + assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack + + Ion::decompress( + data, + reinterpret_cast(pixelBuffer), + size, + pixelBufferSize * sizeof(KDColor) + ); + + KDRect bounds((320 - image->width()) / 2, offset, image->width(), image->height()); + + ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr); +} + +void Interface::drawFlasher() { + KDContext * ctx = KDIonContext::sharedContext(); + ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); + drawImage(ctx, ImageStore::Computer, 25); + KDSize fontSize = KDFont::LargeFont->glyphSize(); + int initPos = (320 - fontSize.width() * strlen(Messages::mainTitle)) / 2; + ctx->drawString(Messages::mainTitle, KDPoint(initPos, ImageStore::Computer->height() + fontSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); + int y = ImageStore::Computer->height() + (KDFont::LargeFont->glyphSize().height() + 10) + (KDFont::SmallFont->glyphSize().height() + 10); + initPos = (320 - KDFont::SmallFont->glyphSize().width() * strlen(Messages::dfuSlotsUpdate)) / 2; + ctx->drawString(Messages::dfuSlotsUpdate, KDPoint(initPos, y), KDFont::SmallFont, KDColorBlack, KDColorWhite); +} + +void Interface::drawLoading() { + KDContext * ctx = KDIonContext::sharedContext(); + ctx->fillRect(KDRect(0, 0, 320, 240), KDColorWhite); + drawImage(ctx, ImageStore::Computer, 25); + Ion::Timing::msleep(250); + KDSize fontSize = KDFont::LargeFont->glyphSize(); + int initPos = (320 - fontSize.width() * strlen(Messages::mainTitle)) / 2; + for (uint8_t i = 0; i < strlen(Messages::mainTitle); i++) { + char tmp[2] = {Messages::mainTitle[i], '\0'}; + ctx->drawString(tmp, KDPoint(initPos + i * (fontSize.width()), ImageStore::Computer->height() + fontSize.height() + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite); + Ion::Timing::msleep(50); + } + Ion::Timing::msleep(500); +} + +} diff --git a/bootloader/interface/static/interface.h b/bootloader/interface/static/interface.h new file mode 100644 index 000000000..8c5234fc4 --- /dev/null +++ b/bootloader/interface/static/interface.h @@ -0,0 +1,19 @@ +#ifndef BOOTLOADER_INTERFACE_STATIC_INTERFACE_H +#define BOOTLOADER_INTERFACE_STATIC_INTERFACE_H + +#include +#include +#include + +namespace Bootloader { +class Interface { + +public: + static void drawImage(KDContext * ctx, const Image * image, int offset); + static void drawLoading(); + static void drawFlasher(); +}; + +} + +#endif \ No newline at end of file diff --git a/bootloader/interface/static/messages.h b/bootloader/interface/static/messages.h new file mode 100644 index 000000000..de63bf3d3 --- /dev/null +++ b/bootloader/interface/static/messages.h @@ -0,0 +1,93 @@ +#ifndef BOOTLOADER_INTERFACE_STATIC_MESSAGES_H +#define BOOTLOADER_INTERFACE_STATIC_MESSAGES_H + +namespace Bootloader { + +class Messages { +public: + // TODO: Remove it when this fork will be updated + #ifdef UPSILON_VERSION + constexpr static const char * mainTitle = "Upsilon Calculator"; + #elif defined OMEGA_VERSION + constexpr static const char * mainTitle = "Omega Calculator"; + #else + constexpr static const char * mainTitle = "NumWorks Calculator"; + #endif + + // home menu + constexpr static const char * homeTitle = "Select a slot"; + + // Slots OS Type + constexpr static const char * upsilonSlot = "-- Upsilon "; + constexpr static const char * khiSlot = "-- Khi "; + constexpr static const char * omegaSlot = "-- Omega "; + constexpr static const char * epsilonSlot = "-- Epsilon "; + constexpr static const char * invalidSlot = "X - Invalid slot"; + + // Home Submenu + constexpr static const char * homeSlotASubmenu = "1 - Slot A"; + constexpr static const char * homeSlotKhiSubmenu = "2 - Slot Khi"; + constexpr static const char * homeSlotBSubmenu = "3 - Slot B"; + constexpr static const char * homeInstallerSubmenu = "4 - Installer Mode"; + constexpr static const char * homeAboutSubmenu = "5 - About"; + constexpr static const char * homeRebootSubmenu = "6 - Reboot"; + + // DFU menu + constexpr static const char * dfuTitle = "Installer"; + + constexpr static const char * dfuSlotsUpdate = "Waiting for Slots..."; + constexpr static const char * dfuBootloaderUpdate = "Waiting for Bootloader..."; + + // Installer menu + constexpr static const char * installerTitle = "Installer mode"; + + constexpr static const char * installerText1 = "Please select a mode:"; + constexpr static const char * installerSlotsSubmenu = "1 - Flash Slots"; + constexpr static const char * installerBootloaderSubmenu = "2 - Flash Bootloader"; + + // Bootloader Crash Handler + constexpr static const char * bootloaderCrashTitle = "BOOTLOADER CRASH"; + + constexpr static const char * bootloaderCrashMessage1 = "The bootloader has crashed."; + constexpr static const char * bootloaderCrashMessage2 = "Please restart the calculator."; + + // Recovery menu + constexpr static const char * recoveryTitle = "Recovery mode"; + + constexpr static const char * recoveryMessage1 = "The bootloader has detected a crash."; + constexpr static const char * recoveryMessage2 = "Plug the calculator to a device capable of"; + constexpr static const char * recoveryMessage3 = "accessing the internal storage."; + constexpr static const char * recoveryMessage4 = "Press Back to continue."; + constexpr static const char * recoveryMessage5 = "(you will not be able to recover your data !)"; + + // Warning menu + constexpr static const char * epsilonWarningTitle = "Epsilon Slot"; + + constexpr static const char * epsilonWarningMessage1 = "!! WARNING !! "; + constexpr static const char * epsilonWarningMessage2 = "This version of epsilon"; + constexpr static const char * epsilonWarningMessage3 = "can lock the calculator."; + constexpr static const char * epsilonWarningMessage4 = "Proceed the boot ?"; + constexpr static const char * epsilonWarningMessage5 = "EXE - Yes"; + constexpr static const char * epsilonWarningMessage6 = "BACK - No"; + + // About menu + constexpr static const char * aboutMenuTitle = "About"; + + constexpr static const char * aboutMessage1 = "This is the bootloader of"; + constexpr static const char * aboutMessage2 = "the Upsilon Calculator."; + constexpr static const char * aboutMessage3 = "It is used to install"; + constexpr static const char * aboutMessage4 = "and select the OS"; + constexpr static const char * aboutMessage5 = "to boot."; + + constexpr static const char * bootloaderVersion = "Version 1.0.0 - FREED0M"; + + //USB NAMES + constexpr static const char * usbUpsilonBootloader = "Upsilon Bootloader"; + constexpr static const char * usbUpsilonRecovery = "Upsilon Recovery"; + constexpr static const char * usbBootloaderUpdate = "Bootloader Update"; + +}; + +}; + +#endif diff --git a/bootloader/main.cpp b/bootloader/main.cpp index c847ad882..7902fc7d0 100644 --- a/bootloader/main.cpp +++ b/bootloader/main.cpp @@ -3,9 +3,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include @@ -17,20 +17,20 @@ __attribute__ ((noreturn)) void ion_main(int argc, const char * const argv[]) { // We check if there is a slot in exam_mode - bool isSlotA = Bootloader::Slot::A().kernelHeader()->isValid(); + bool isSlotA = Bootloader::Slot::isFullyValid(Bootloader::Slot::A()); if (isSlotA) { - Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(Bootloader::Slot::A().kernelHeader()->isAboveVersion16()); + Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(!Bootloader::Slot::A().userlandHeader()->isOmega()); if (SlotAExamMode != Bootloader::ExamMode::ExamMode::Off && SlotAExamMode != Bootloader::ExamMode::ExamMode::Unknown) { // We boot the slot in exam_mode Bootloader::Slot::A().boot(); } } - bool isSlotB = Bootloader::Slot::B().kernelHeader()->isValid(); + bool isSlotB = Bootloader::Slot::isFullyValid(Bootloader::Slot::B()); if (isSlotB) { - Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(Bootloader::Slot::B().kernelHeader()->isAboveVersion16()); + Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(!Bootloader::Slot::B().userlandHeader()->isOmega()); if (SlotBExamMode != Bootloader::ExamMode::ExamMode::Off && SlotBExamMode != Bootloader::ExamMode::ExamMode::Unknown && isSlotB) { // We boot the slot in exam_mode Bootloader::Slot::B().boot(); @@ -38,6 +38,18 @@ __attribute__ ((noreturn)) void ion_main(int argc, const char * const argv[]) { } + // I have no idea if this will work, but if Pariss did a good job, it should + + bool isKhiSlot = Bootloader::Slot::isFullyValid(Bootloader::Slot::Khi()); + + if (isKhiSlot) { + Bootloader::ExamMode::ExamMode KhiExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotKhiExamMode(); + if (KhiExamMode != Bootloader::ExamMode::ExamMode::Off && KhiExamMode != Bootloader::ExamMode::ExamMode::Unknown && isKhiSlot) { + // We boot the slot in exam_mode + Bootloader::Slot::Khi().boot(); + } + } + if (Bootloader::Recovery::has_crashed()) { Bootloader::Recovery::recover_data(); } diff --git a/bootloader/messages.h b/bootloader/messages.h deleted file mode 100644 index 6d8e90c39..000000000 --- a/bootloader/messages.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef BOOTLOADER_INTERFACE_MESSAGES_H -#define BOOTLOADER_INTERFACE_MESSAGES_H - -namespace Bootloader { - -class Messages { -public: - // TODO: Remove it when this fork will be updated - #ifdef UPSILON_VERSION - constexpr static const char * mainTitle = "Upsilon Calculator"; - #elif defined OMEGA_VERSION - constexpr static const char * mainTitle = "Omega Calculator"; - #else - constexpr static const char * mainTitle = "NumWorks Calculator"; - #endif - constexpr static const char * mainMenuTitle = "Select a slot"; - constexpr static const char * upsilon = "-- Upsilon "; - constexpr static const char * khi = "-- Khi "; - constexpr static const char * omega = "-- Omega "; - constexpr static const char * epsilon = "-- Epsilon "; - constexpr static const char * invalidSlot = "X - Invalid slot"; - constexpr static const char * dfuText = "4 - Installer Mode"; - constexpr static const char * aboutText = "5 - About"; - constexpr static const char * rebootText = "6 - Reboot"; - constexpr static const char * dfuSubtitle = "Waiting for Slots..."; - constexpr static const char * crashTitle = "BOOTLOADER CRASH"; - constexpr static const char * crashText1 = "The bootloader has crashed."; - constexpr static const char * crashText2 = "Please restart the calculator."; - constexpr static const char * recoveryTitle = "Recovery mode"; - constexpr static const char * recoveryText1 = "The bootloader has detected a crash."; - constexpr static const char * recoveryText2 = "Plug the calculator to a device capable of"; - constexpr static const char * recoveryText3 = "accessing the internal storage."; - constexpr static const char * recoveryText4 = "Press Back to continue."; - constexpr static const char * recoveryText5 = "(you will not be able to recover your data !)"; - constexpr static const char * installerSelectionTitle = "Installer Mode"; - constexpr static const char * installerText1 = "Please select a mode:"; - constexpr static const char * installerText2 = "1. Flash slots"; - constexpr static const char * installerText3 = "2. Flash the bootloader"; - constexpr static const char * bootloaderSubtitle = "Waiting for the bootloader..."; - constexpr static const char * epsilonWarningTitle = "Epsilon Slot"; - constexpr static const char * epsilonWarningText1 = "!! WARNING !! "; - constexpr static const char * epsilonWarningText2 = "This version of epsilon"; - constexpr static const char * epsilonWarningText3 = "can lock the calculator."; - constexpr static const char * epsilonWarningText4 = "Proceed the boot ?"; - constexpr static const char * epsilonWarningText5 = "EXE - Yes"; - constexpr static const char * epsilonWarningText6 = "BACK - No"; - constexpr static const char * bootloaderVersion = "Version 1.0.0 - FREEDOM"; - constexpr static const char * aboutMenuTitle = "About"; - - //USB NAMES - - constexpr static const char * upsilonBootloader = "Upsilon Bootloader"; - constexpr static const char * upsilonRecovery = "Upsilon Recovery"; - constexpr static const char * bootloaderUpdate = "Bootloader Update"; - -}; - -}; - -#endif diff --git a/bootloader/recovery.cpp b/bootloader/recovery.cpp index eb99bfbbc..5d357de30 100644 --- a/bootloader/recovery.cpp +++ b/bootloader/recovery.cpp @@ -5,9 +5,11 @@ #include #include -#include -#include +#include +#include #include +#include +#include constexpr static uint32_t MagicStorage = 0xEE0BDDBA; @@ -19,11 +21,8 @@ void Bootloader::Recovery::crash_handler(const char *error) { Ion::Backlight::setBrightness(180); Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite); - Interface::drawCrash(error); - - while (true) { - - } + CrashMenu menu(error); + menu.open(true); } bool Bootloader::Recovery::has_crashed() { @@ -76,55 +75,13 @@ void Bootloader::Recovery::recover_data() { Ion::Device::Board::initPeripherals(false); Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite); Ion::Backlight::init(); - Interface::drawRecovery(); - - uint64_t scan = 0; USBData udata = USBData::Recovery((uint32_t)getSlotConcerned().getStorageAddress(), (uint32_t)getSlotConcerned().getStorageSize()); - - while (scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - Ion::USB::enable(); - do { - scan = Ion::Keyboard::scan(); - if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - Ion::USB::disable(); - } - } while (!Ion::USB::isEnumerated() && scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)); - - if (scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - Ion::USB::DFU(true, &udata); - } - } + + SlotRecoveryMenu menu = SlotRecoveryMenu(&udata); + menu.open(); // Invalidate storage header *(uint32_t *)(getSlotConcerned().getStorageAddress()) = (uint32_t)0x0; } - -void Bootloader::Recovery::debug() { - bool isA = Bootloader::Slot::A().kernelHeader()->isValid() && Bootloader::Slot::A().userlandHeader()->isValid(); - bool isB = Bootloader::Slot::B().kernelHeader()->isValid() && Bootloader::Slot::B().userlandHeader()->isValid(); - - if (isA) { - const uint32_t * storage = (uint32_t *)Bootloader::Slot::A().userlandHeader()->storageAddress(); - *(uint32_t *)(0x20000070) = *storage; - if (*storage == MagicStorage) { - *(uint32_t *)(0x20000070 + (sizeof(uint32_t))) = 0xDEADBEEF; - } - } - - if (isB) { - const uint32_t * storage = (uint32_t *)Bootloader::Slot::B().userlandHeader()->storageAddress(); - *(uint32_t *)(0x20000070 + 2*(sizeof(uint32_t))) = *storage; - if (*storage == MagicStorage) { - *(uint32_t *)(0x20000070 + 3*(sizeof(uint32_t))) = 0xDEADBEEF; - } - } - - if (has_crashed()) { - *(uint32_t *)(0x20000070 + 4*(sizeof(uint32_t))) = 0xDEADBEEF; - } else { - *(uint32_t *)(0x20000070 + 4*(sizeof(uint32_t))) = 0xBEEFDEAD; - } - -} diff --git a/bootloader/recovery.h b/bootloader/recovery.h index e9273bbfd..f5327c914 100644 --- a/bootloader/recovery.h +++ b/bootloader/recovery.h @@ -24,7 +24,6 @@ class Recovery { static void crash_handler(const char * error); static void recover_data(); static bool has_crashed(); - static void debug(); }; }; diff --git a/bootloader/kernel_header.cpp b/bootloader/slots/kernel_header.cpp similarity index 93% rename from bootloader/kernel_header.cpp rename to bootloader/slots/kernel_header.cpp index 53e02cfaf..c323046d9 100644 --- a/bootloader/kernel_header.cpp +++ b/bootloader/slots/kernel_header.cpp @@ -1,4 +1,4 @@ -#include +#include #include namespace Bootloader { diff --git a/bootloader/kernel_header.h b/bootloader/slots/kernel_header.h similarity index 88% rename from bootloader/kernel_header.h rename to bootloader/slots/kernel_header.h index ad7fbaf4b..835aa9338 100644 --- a/bootloader/kernel_header.h +++ b/bootloader/slots/kernel_header.h @@ -1,5 +1,5 @@ -#ifndef BOOTLOADER_KERNEL_HEADER_H -#define BOOTLOADER_KERNEL_HEADER_H +#ifndef BOOTLOADER_SLOTS_KERNEL_HEADER_H +#define BOOTLOADER_SLOTS_KERNEL_HEADER_H #include #include diff --git a/bootloader/slot.cpp b/bootloader/slots/slot.cpp similarity index 95% rename from bootloader/slot.cpp rename to bootloader/slots/slot.cpp index a6ffe0e1d..d8ce93398 100644 --- a/bootloader/slot.cpp +++ b/bootloader/slots/slot.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -37,8 +37,6 @@ const UserlandHeader* Slot::userlandHeader() const { Ion::Device::Flash::LockSlotA(); } - Boot::lockInternal(); - // Configure the MPU for the booted firmware Ion::Device::Board::bootloaderMPU(); diff --git a/bootloader/slot.h b/bootloader/slots/slot.h similarity index 86% rename from bootloader/slot.h rename to bootloader/slots/slot.h index 0550b0222..8aa97b4d3 100644 --- a/bootloader/slot.h +++ b/bootloader/slots/slot.h @@ -1,5 +1,5 @@ -#ifndef BOOTLOADER_SLOT_H -#define BOOTLOADER_SLOT_H +#ifndef BOOTLOADER_SLOTS_SLOT_H +#define BOOTLOADER_SLOTS_SLOT_H #include @@ -19,6 +19,7 @@ public: const KernelHeader* kernelHeader() const; const UserlandHeader* userlandHeader() const; [[ noreturn ]] void boot() const; + const uint32_t address() const { return m_address; } static const Slot A(); static const Slot B(); diff --git a/bootloader/slot_exam_mode.cpp b/bootloader/slots/slot_exam_mode.cpp similarity index 77% rename from bootloader/slot_exam_mode.cpp rename to bootloader/slots/slot_exam_mode.cpp index 983a51fa8..45b312323 100644 --- a/bootloader/slot_exam_mode.cpp +++ b/bootloader/slots/slot_exam_mode.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -118,6 +118,32 @@ uint8_t * SignificantSlotBExamModeAddress(bool newVersion) { } +uint8_t * SignificantSlotKhiExamModeAddress() { + uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotKhiStartExamAddress(); + uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotKhiEndExamAddress(); + + assert((persitence_end_32 - persitence_start_32) % 4 == 0); + while (persitence_start_32 < persitence_end_32 && *persitence_start_32 == 0x0) { + // Scan by groups of 32 bits to reach first non-zero bit + persitence_start_32++; + } + uint8_t * persitence_start_8 = (uint8_t *)persitence_start_32; + uint8_t * persitence_end_8 = (uint8_t *)persitence_end_32; + while (persitence_start_8 < persitence_end_8 && *persitence_start_8 == 0x0) { + // Scan by groups of 8 bits to reach first non-zero bit + persitence_start_8++; + } + if (persitence_start_8 == persitence_end_8 + // we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector + || (persitence_start_8 + 1 == persitence_end_8 && *persitence_start_8 == 1)) { + assert(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotKhiStartExamAddress()) >= 0); + Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotKhiStartExamAddress())); + return (uint8_t *)SlotsExamMode::getSlotKhiStartExamAddress(); + } + + return persitence_start_8; +} + uint8_t SlotsExamMode::FetchSlotAExamMode(bool newVersion) { uint8_t * readingAddress = SignificantSlotAExamModeAddress(newVersion); if (!newVersion) { @@ -146,6 +172,15 @@ uint8_t SlotsExamMode::FetchSlotBExamMode(bool newVersion) { } +uint8_t SlotsExamMode::FetchSlotKhiExamMode() { + uint8_t * readingAddress = SignificantSlotKhiExamModeAddress(); + // Count the number of 0[3] before reading address + uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotKhiStartExamAddress()) * numberOfBitsInByte) % 4; + // Count the number of 0[3] at reading address + size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4; + return (nbOfZerosBefore + numberOfLeading0) % 4; +} + uint32_t SlotsExamMode::getSlotAStartExamAddress(bool newVersion) { return newVersion ? SlotAExamModeBufferStartNewVersions : SlotAExamModeBufferStartOldVersions; } @@ -162,5 +197,13 @@ uint32_t SlotsExamMode::getSlotBEndExamAddress(bool newVersion) { return newVersion ? SlotBExamModeBufferEndNewVersions : SlotBExamModeBufferEndOldVersions; } +uint32_t SlotsExamMode::getSlotKhiStartExamAddress() { + return SlotKhiExamModeBufferStart; +} + +uint32_t SlotsExamMode::getSlotKhiEndExamAddress() { + return SlotKhiExamModeBufferEnd; +} + } } diff --git a/bootloader/slot_exam_mode.h b/bootloader/slots/slot_exam_mode.h similarity index 78% rename from bootloader/slot_exam_mode.h rename to bootloader/slots/slot_exam_mode.h index 7c93eed72..d9e380e9a 100644 --- a/bootloader/slot_exam_mode.h +++ b/bootloader/slots/slot_exam_mode.h @@ -1,5 +1,5 @@ -#ifndef BOOTLOADER_EXAM_MODE_H -#define BOOTLOADER_EXAM_MODE_H +#ifndef BOOTLOADER_SLOTS_EXAM_MODE_H +#define BOOTLOADER_SLOTS_EXAM_MODE_H extern "C" { #include @@ -20,15 +20,21 @@ static const uint32_t SlotBExamModeBufferEndOldVersions = 0x90403000; static const uint32_t SlotBExamModeBufferStartNewVersions = 0x907f0000; static const uint32_t SlotBExamModeBufferEndNewVersions = 0x90800000; +static const uint32_t SlotKhiExamModeBufferStart = 0x90181000; +static const uint32_t SlotKhiExamModeBufferEnd = 0x90183000; + class SlotsExamMode{ public: static uint8_t FetchSlotAExamMode(bool newVersion); static uint8_t FetchSlotBExamMode(bool newVerion); + static uint8_t FetchSlotKhiExamMode(); static uint32_t getSlotAStartExamAddress(bool newVersion); static uint32_t getSlotAEndExamAddress(bool newVersion); static uint32_t getSlotBStartExamAddress(bool newVersion); static uint32_t getSlotBEndExamAddress(bool newVersion); + static uint32_t getSlotKhiStartExamAddress(); + static uint32_t getSlotKhiEndExamAddress(); }; diff --git a/bootloader/userland_header.cpp b/bootloader/slots/userland_header.cpp similarity index 95% rename from bootloader/userland_header.cpp rename to bootloader/slots/userland_header.cpp index ee1f8b15d..3c8a91908 100644 --- a/bootloader/userland_header.cpp +++ b/bootloader/slots/userland_header.cpp @@ -1,4 +1,4 @@ -#include +#include namespace Bootloader { diff --git a/bootloader/userland_header.h b/bootloader/slots/userland_header.h similarity index 94% rename from bootloader/userland_header.h rename to bootloader/slots/userland_header.h index 39356f3d3..382e409b0 100644 --- a/bootloader/userland_header.h +++ b/bootloader/slots/userland_header.h @@ -1,5 +1,5 @@ -#ifndef BOOTLOADER_USERLAND_HEADER_H -#define BOOTLOADER_USERLAND_HEADER_H +#ifndef BOOTLOADER_SLOTS_USERLAND_HEADER_H +#define BOOTLOADER_SLOTS_USERLAND_HEADER_H #include #include diff --git a/bootloader/usb_data.cpp b/bootloader/usb_data.cpp index b161df94c..bd8843791 100644 --- a/bootloader/usb_data.cpp +++ b/bootloader/usb_data.cpp @@ -1,10 +1,10 @@ #include +#include + #include #include -#include #include #include -#include extern "C" { } @@ -13,13 +13,13 @@ static char data[255]; const char * Bootloader::USBData::buildStringDescriptor(StringHeader header, uint32_t startAddress, uint32_t size) { strlcpy(data, header.getString(), sizeof(data)); - Bootloader::Utility::itoa((int32_t)startAddress, &data[strlen(header.getString())], 16); + itoa((int32_t)startAddress, &data[strlen(header.getString())], 16); data[strlen(header.getString()) + 8] = '/'; data[strlen(header.getString()) + 8 + 1] = '0'; data[strlen(header.getString()) + 8 + 2] = '1'; data[strlen(header.getString()) + 8 + 3] = '*'; data[strlen(header.getString()) + 8 + 4] = '0'; - Bootloader::Utility::itoa((int32_t)size/1024, &data[strlen(header.getString()) + 8 + 5], 10); + itoa((int32_t)size/1024, &data[strlen(header.getString()) + 8 + 5], 10); data[strlen(header.getString()) + 8 + 5 + 2] = 'K'; data[strlen(header.getString()) + 8 + 5 + 2 + 1] = 'g'; data[strlen(header.getString()) + 8 + 5 + 2 + 2] = '\0'; @@ -27,13 +27,13 @@ const char * Bootloader::USBData::buildStringDescriptor(StringHeader header, uin } const Bootloader::USBData Bootloader::USBData::DEFAULT() { - return USBData("@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg", Messages::upsilonBootloader, ProtectionState()); + return USBData("@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg", Messages::usbUpsilonBootloader, ProtectionState(false, true)); } const Bootloader::USBData Bootloader::USBData::BOOTLOADER_UPDATE() { - return USBData("@Flash/0x08000000/04*016Kg", Messages::bootloaderUpdate, ProtectionState(true, false)); + return USBData("@Flash/0x08000000/04*016Kg", Messages::usbBootloaderUpdate, ProtectionState(true, false)); } Bootloader::USBData Bootloader::USBData::Recovery(uint32_t startAddress, uint32_t size) { - return USBData(buildStringDescriptor(StringHeader::SRAM(), startAddress, size), Messages::upsilonRecovery, ProtectionState(false, false)); + return USBData(buildStringDescriptor(StringHeader::SRAM(), startAddress, size), Messages::usbUpsilonRecovery, ProtectionState(false, false)); } diff --git a/bootloader/usb_data.h b/bootloader/usb_data.h index 33398595d..a0477edbd 100644 --- a/bootloader/usb_data.h +++ b/bootloader/usb_data.h @@ -33,11 +33,11 @@ class USBData { const char * m_string; }; - USBData(const char * desc, const char * name, ProtectionState data = ProtectionState()) : m_stringDescriptor(desc), m_name(name), m_data(&data) {}; + USBData(const char * desc, const char * name, ProtectionState data = ProtectionState()) : m_stringDescriptor(desc), m_name(name), m_data(data) {}; const char * stringDescriptor() const { return m_stringDescriptor; } const char * getName() const { return m_name; } - ProtectionState * getData() const { return m_data; } + ProtectionState getData() const { return m_data; } static const char * buildStringDescriptor(StringHeader header, uint32_t startAddress, uint32_t size); @@ -48,7 +48,7 @@ class USBData { private: const char * m_stringDescriptor; const char * m_name; - ProtectionState * m_data; + ProtectionState m_data; }; } diff --git a/bootloader/usb_desc.cpp b/bootloader/usb_desc.cpp deleted file mode 100644 index be4930600..000000000 --- a/bootloader/usb_desc.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -namespace Ion { -namespace Device { -namespace USB { - -const char* stringDescriptor() { - return "@Flash/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg"; -} - -} -} -} diff --git a/bootloader/utility.cpp b/bootloader/utility.cpp index 1329351e5..fb6d676ac 100644 --- a/bootloader/utility.cpp +++ b/bootloader/utility.cpp @@ -1,10 +1,10 @@ #include #include -int Bootloader::Utility::versionSum(const char * version, int length) { - int sum = 0; - for (int i = 0; i < length; i++) { - sum += version[i] * (strlen(version) * 100 - i * 10); - } - return sum; +int Utility::versionSum(const char * version, int length) { + int sum = 0; + for (int i = 0; i < length; i++) { + sum += version[i] * (strlen(version) * 100 - i * 10); + } + return sum; } diff --git a/bootloader/utility.h b/bootloader/utility.h index 12c6ce329..6a2c0d590 100644 --- a/bootloader/utility.h +++ b/bootloader/utility.h @@ -1,12 +1,8 @@ #ifndef _BOOTLOADER_ITOA_H_ #define _BOOTLOADER_ITOA_H_ -namespace Bootloader { - class Utility { - public: - static char * itoa(int value, char * result, int base); - static int versionSum(const char * version, int length); - }; +namespace Utility { + extern int versionSum(const char * version, int length); } #endif diff --git a/ion/src/device/bootloader/internal_flash.ld b/ion/src/device/bootloader/internal_flash.ld index ebbf98a51..e441c6527 100644 --- a/ion/src/device/bootloader/internal_flash.ld +++ b/ion/src/device/bootloader/internal_flash.ld @@ -45,6 +45,14 @@ SECTIONS { _exam_mode_buffer_end = .; } >INTERNAL_FLASH + .fake_isr_function : { + . = ALIGN(4); + _fake_isr_function_start = .; + KEEP(*(.fake_isr_function)) + KEEP(*(.fake_isr_function.*)) + _fake_isr_function_end = .; + } + .text : { . = ALIGN(4); *(.text) diff --git a/ion/src/device/bootloader/usb/dfu_interface.cpp b/ion/src/device/bootloader/usb/dfu_interface.cpp index 0b6abb611..05e86f4ed 100644 --- a/ion/src/device/bootloader/usb/dfu_interface.cpp +++ b/ion/src/device/bootloader/usb/dfu_interface.cpp @@ -211,23 +211,14 @@ void DFUInterface::eraseMemoryIfNeeded() { willErase(); - Bootloader::ProtectionState * config = getDfuConfig(); + Bootloader::ProtectionState config = getDfuConfig(); - if (config != nullptr) { - // More simple to read - if ((0x08000000 <= m_eraseAddress && m_eraseAddress <= 0x08010000)&& !m_dfuData.isProtectedInternal()) { - Flash::EraseSector(m_erasePage); - } else if ((0x90000000 <= m_eraseAddress && m_eraseAddress <= 0x90800000)&& !m_dfuData.isProtectedExternal()) { - Flash::EraseSector(m_erasePage); - } - } else { - if (m_erasePage == Flash::TotalNumberOfSectors()) { - Flash::MassErase(); - } else { - Flash::EraseSector(m_erasePage); - } + // More simple to read + if ((0x08000000 <= m_eraseAddress && m_eraseAddress <= 0x08010000)&& !m_dfuData.isProtectedInternal()) { + Flash::EraseSector(m_erasePage); + } else if ((0x90000000 <= m_eraseAddress && m_eraseAddress <= 0x90800000)&& !m_dfuData.isProtectedExternal()) { + Flash::EraseSector(m_erasePage); } - /* Put an out of range value in m_erasePage to indicate that no erase is * waiting. */ m_erasePage = -1; @@ -242,15 +233,11 @@ void DFUInterface::writeOnMemory() { memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { - Bootloader::ProtectionState * config = getDfuConfig(); + Bootloader::ProtectionState config = getDfuConfig(); - if (config != nullptr) { - if (m_writeAddress >= 0x08000000 && m_writeAddress <= 0x08010000 && !m_dfuData.isProtectedInternal()) { - Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); - } else if (m_writeAddress >= 0x90000000 && m_writeAddress <= 0x90800000 && !m_dfuData.isProtectedExternal()) { - Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); - } - } else { + if (m_writeAddress >= 0x08000000 && m_writeAddress <= 0x08010000 && !m_dfuData.isProtectedInternal()) { + Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); + } else if (m_writeAddress >= 0x90000000 && m_writeAddress <= 0x90800000 && !m_dfuData.isProtectedExternal()) { Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); } @@ -306,7 +293,7 @@ void DFUInterface::leaveDFUAndReset() { } void DFUInterface::copyDfuData() { - m_dfuData = Bootloader::ProtectionState(!m_dfuConfig->isProtectedInternal(), !m_dfuConfig->isProtectedExternal()); + m_dfuData = Bootloader::ProtectionState(!m_dfuConfig.isProtectedInternal(), !m_dfuConfig.isProtectedExternal()); } } diff --git a/ion/src/device/bootloader/usb/dfu_interface.h b/ion/src/device/bootloader/usb/dfu_interface.h index 2cb2eaeee..4fa319bd9 100644 --- a/ion/src/device/bootloader/usb/dfu_interface.h +++ b/ion/src/device/bootloader/usb/dfu_interface.h @@ -30,7 +30,7 @@ public: m_writeAddress(0), m_bInterfaceAlternateSetting(bInterfaceAlternateSetting), m_isErasingAndWriting(false), - m_dfuConfig(nullptr), + m_dfuConfig(), m_eraseAddress(0), m_dfuData() { @@ -40,8 +40,8 @@ public: void wholeDataSentCallback(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength) override; bool isErasingAndWriting() const { return m_isErasingAndWriting; } - void setDfuConfig(Bootloader::ProtectionState * data) { m_dfuConfig = data; copyDfuData(); } - Bootloader::ProtectionState * getDfuConfig() const { return m_dfuConfig; } + void setDfuConfig(Bootloader::ProtectionState data) { m_dfuConfig = data; copyDfuData(); } + Bootloader::ProtectionState getDfuConfig() const { return m_dfuConfig; } protected: void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { @@ -180,7 +180,7 @@ private: uint32_t m_writeAddress; uint8_t m_bInterfaceAlternateSetting; bool m_isErasingAndWriting; - Bootloader::ProtectionState * m_dfuConfig; + Bootloader::ProtectionState m_dfuConfig; uint32_t m_eraseAddress; Bootloader::ProtectionState m_dfuData; }; diff --git a/ion/src/device/shared/drivers/board.h b/ion/src/device/shared/drivers/board.h index 8d1d1bbb6..ff6e88ac8 100644 --- a/ion/src/device/shared/drivers/board.h +++ b/ion/src/device/shared/drivers/board.h @@ -40,6 +40,7 @@ void writePCBVersion(PCBVersion version); void lockPCBVersion(); bool pcbVersionIsLocked(); +void jumpToInternalBootloader(); } } } diff --git a/ion/src/device/shared/drivers/flash.cpp b/ion/src/device/shared/drivers/flash.cpp index 0d2fb959f..2860dd593 100644 --- a/ion/src/device/shared/drivers/flash.cpp +++ b/ion/src/device/shared/drivers/flash.cpp @@ -62,6 +62,14 @@ void SetInternalSectorProtection(int i, bool protect) { InternalFlash::SetSectorProtection(i, protect); } +void EnableInternalSessionLock() { + InternalFlash::EnableSessionLock(); +} + +void EnableInternalFlashInterrupt() { + InternalFlash::EnableFlashInterrupt(); +} + void LockSlotA() { ExternalFlash::LockSlotA(); } diff --git a/ion/src/device/shared/drivers/flash.h b/ion/src/device/shared/drivers/flash.h index d385add1f..91f942a20 100644 --- a/ion/src/device/shared/drivers/flash.h +++ b/ion/src/device/shared/drivers/flash.h @@ -18,6 +18,8 @@ void WriteMemory(uint8_t * destination, uint8_t * source, size_t length); void DisableInternalProtection(); void EnableInternalProtection(); void SetInternalSectorProtection(int i, bool protect); +void EnableInternalSessionLock(); // Will cause BUSERR when enabled +void EnableInternalFlashInterrupt(); void LockSlotA(); void LockSlotB(); diff --git a/ion/src/device/shared/drivers/internal_flash.cpp b/ion/src/device/shared/drivers/internal_flash.cpp index f71d8f7ac..91292c0af 100644 --- a/ion/src/device/shared/drivers/internal_flash.cpp +++ b/ion/src/device/shared/drivers/internal_flash.cpp @@ -344,6 +344,25 @@ void SetSectorProtection(int i, bool protect) { } } +void EnableSessionLock() { + if (FLASH.OPTCR()->getLOCK()) { + // writing bullshit to the lock register to lock it until next core reset + FLASH.OPTKEYR()->set(0x00000000); + FLASH.OPTKEYR()->set(0xFFFFFFFF); + } +} + +void EnableFlashInterrupt() { + open(); + FLASH.CR()->setERRIE(true); + wait(); + FLASH.CR()->setEOPIE(true); + wait(); + FLASH.CR()->setRDERRIE(true); + wait(); + close(); +} + } } } diff --git a/ion/src/device/shared/drivers/internal_flash.h b/ion/src/device/shared/drivers/internal_flash.h index 3961884f2..cf351a1b6 100644 --- a/ion/src/device/shared/drivers/internal_flash.h +++ b/ion/src/device/shared/drivers/internal_flash.h @@ -18,6 +18,8 @@ void WriteMemory(uint8_t * destination, uint8_t * source, size_t length); void EnableProtection(); void DisableProtection(); void SetSectorProtection(int i, bool protect); +void EnableSessionLock(); +void EnableFlashInterrupt(); /* The Device is powered by a 2.8V LDO. This allows us to perform writes to the * Flash 32 bits at once. */ diff --git a/ion/src/device/shared/regs/flash.h b/ion/src/device/shared/regs/flash.h index b289d0227..4896e2b42 100644 --- a/ion/src/device/shared/regs/flash.h +++ b/ion/src/device/shared/regs/flash.h @@ -45,6 +45,9 @@ public: REGS_FIELD(SNB, uint8_t, 6, 3); REGS_TYPE_FIELD(PSIZE, 9, 8); REGS_BOOL_FIELD(STRT, 16); + REGS_BOOL_FIELD(EOPIE, 24); + REGS_BOOL_FIELD(ERRIE, 25); + REGS_BOOL_FIELD(RDERRIE, 26) REGS_BOOL_FIELD(LOCK, 31); }; diff --git a/ion/src/device/shared/regs/rcc.h b/ion/src/device/shared/regs/rcc.h index 135508574..050512632 100644 --- a/ion/src/device/shared/regs/rcc.h +++ b/ion/src/device/shared/regs/rcc.h @@ -14,6 +14,12 @@ public: public: REGS_BOOL_FIELD(HSION, 0); REGS_BOOL_FIELD(HSIRDY, 1); + REGS_BOOL_FIELD(HSITRIM1, 3); + REGS_BOOL_FIELD(HSITRIM2, 4); + REGS_BOOL_FIELD(HSITRIM3, 5); + REGS_BOOL_FIELD(HSITRIM4, 6); + REGS_BOOL_FIELD(HSITRIM5, 7); + REGS_BOOL_FIELD(HSICAL, 8); REGS_BOOL_FIELD(HSEON, 16); REGS_BOOL_FIELD_R(HSERDY, 17); REGS_BOOL_FIELD(PLLON, 24); diff --git a/ion/src/device/shared/regs/syscfg.h b/ion/src/device/shared/regs/syscfg.h index 82dfddda6..e044a65f6 100644 --- a/ion/src/device/shared/regs/syscfg.h +++ b/ion/src/device/shared/regs/syscfg.h @@ -5,6 +5,8 @@ #include #include "gpio.h" +#define REGS_SYSCFG_CONFIG_F412 1 + namespace Ion { namespace Device { namespace Regs { diff --git a/liba/Makefile b/liba/Makefile index 639bf196d..98cf53848 100644 --- a/liba/Makefile +++ b/liba/Makefile @@ -24,6 +24,7 @@ liba_src += $(addprefix liba/src/, \ strlcpy.c \ strlen.c \ external/sqlite/mem5.c \ + itoa.c \ ) liba_src += $(addprefix liba/src/external/openbsd/, \ diff --git a/liba/include/stdlib.h b/liba/include/stdlib.h index 6c27b3d6e..7bac0e2fa 100644 --- a/liba/include/stdlib.h +++ b/liba/include/stdlib.h @@ -10,6 +10,7 @@ void free(void *ptr); void * malloc(size_t size); void * realloc(void *ptr, size_t size); void * calloc(size_t count, size_t size); +char * itoa(int value, char *str, int base); void abort(void) __attribute__((noreturn)); diff --git a/bootloader/itoa.cpp b/liba/src/itoa.c similarity index 92% rename from bootloader/itoa.cpp rename to liba/src/itoa.c index 8235e7b32..25c5a61bf 100644 --- a/bootloader/itoa.cpp +++ b/liba/src/itoa.c @@ -1,6 +1,5 @@ #include #include -#include // https://www.techiedelight.com/implement-itoa-function-in-c/ @@ -19,7 +18,7 @@ char* reverse(char *buffer, int i, int j) { } // Iterative function to implement `itoa()` function in C -char* Bootloader::Utility::itoa(int value, char* buffer, int base) { +char* itoa(int value, char* buffer, int base) { // invalid input if (base < 2 || base > 32) { return buffer; diff --git a/themes/themes/local/upsilon_light/bootloader/cable.png b/themes/themes/local/upsilon_light/bootloader/cable.png new file mode 100644 index 000000000..ac0996ca7 Binary files /dev/null and b/themes/themes/local/upsilon_light/bootloader/cable.png differ diff --git a/themes/themes/local/upsilon_light/bootloader/computer.xcf b/themes/themes/local/upsilon_light/bootloader/computer.xcf new file mode 100644 index 000000000..4ad99c7c0 Binary files /dev/null and b/themes/themes/local/upsilon_light/bootloader/computer.xcf differ