Bootloader pre-release

This commit is contained in:
devdl11
2022-04-25 18:22:19 +02:00
parent add333b920
commit 5ed8aef907
65 changed files with 1328 additions and 810 deletions

View File

@@ -0,0 +1,20 @@
#include "about.h"
#include <bootloader/interface/static/messages.h>
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]);
}

View File

@@ -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 <bootloader/interface/src/menu.h>
@@ -9,7 +9,7 @@ namespace Bootloader {
AboutMenu();
void setup() override;
void post_open() override {};
};
}

View File

@@ -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);
}

View File

@@ -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
}
}

View File

@@ -0,0 +1,19 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_CRASH_H_
#define _BOOTLOADER_INTERFACE_MENUS_CRASH_H_
#include <bootloader/interface/src/menu.h>
namespace Bootloader {
class CrashMenu : public Menu {
public:
CrashMenu(const char * error);
void setup() override;
void post_open() override;
private:
const char * m_error;
};
}
#endif

View File

@@ -0,0 +1,37 @@
#include "dfu.h"
#include <bootloader/boot.h>
#include <ion.h>
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);
}
}

View File

@@ -0,0 +1,21 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_DFU_H_
#define _BOOTLOADER_INTERFACE_MENUS_DFU_H_
#include <bootloader/interface/src/menu.h>
#include <bootloader/usb_data.h>
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

View File

@@ -0,0 +1,144 @@
#include "home.h"
#include <bootloader/boot.h>
#include <bootloader/slots/slot.h>
#include <bootloader/interface/menus/about.h>
#include <stdlib.h>
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]);
}

View File

@@ -0,0 +1,36 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_HOME_H_
#define _BOOTLOADER_INTERFACE_MENUS_HOME_H_
#include <bootloader/interface/src/menu.h>
#include <bootloader/interface/menus/about.h>
#include <bootloader/interface/menus/installer.h>
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

View File

@@ -1,62 +0,0 @@
#include "home.h"
#include <bootloader/slot.h>
#include <bootloader/interface/menus/about/about.h>
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);
}

View File

@@ -1,23 +0,0 @@
#ifndef _BOOTLOADER_INTERFACE_HOME_HOME_H_
#define _BOOTLOADER_INTERFACE_HOME_HOME_H_
#include <bootloader/interface/src/menu.h>
#include <bootloader/interface/menus/about/about.h>
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

View File

@@ -0,0 +1,41 @@
#include "installer.h"
#include <bootloader/interface/static/messages.h>
#include <bootloader/usb_data.h>
#include <bootloader/interface/menus/dfu.h>
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]);
}

View File

@@ -0,0 +1,20 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_INSTALLER_H_
#define _BOOTLOADER_INTERFACE_MENUS_INSTALLER_H_
#include <bootloader/interface/src/menu.h>
#include <bootloader/interface/menus/dfu.h>
namespace Bootloader {
class InstallerMenu : public Menu {
public:
InstallerMenu();
void setup() override;
void post_open() override {};
static DfuMenu * SlotsDFU();
static DfuMenu * BootloaderDFU();
};
}
#endif

View File

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

View File

@@ -0,0 +1,39 @@
#include "slot_recovery.h"
#include <ion.h>
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);
}
}

View File

@@ -0,0 +1,19 @@
#ifndef _BOOTLOADER_INTERFACE_MENU_SLOT_RECOVERY_H
#define _BOOTLOADER_INTERFACE_MENU_SLOT_RECOVERY_H
#include <bootloader/interface/src/menu.h>
#include <bootloader/usb_data.h>
namespace Bootloader {
class SlotRecoveryMenu : public Menu {
public:
SlotRecoveryMenu(USBData * usbData);
void setup() override;
void post_open() override;
private:
const USBData * m_data;
};
}
#endif

View File

@@ -0,0 +1,35 @@
#include "warning.h"
#include <bootloader/slots/slot.h>
#include <bootloader/boot.h>
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]);
}

View File

@@ -0,0 +1,17 @@
#ifndef _BOOTLOADER_INTERFACE_MENUS_WARNING_H_
#define _BOOTLOADER_INTERFACE_MENUS_WARNING_H_
#include <bootloader/interface/src/menu.h>
#include <bootloader/slots/slot.h>
namespace Bootloader {
class WarningMenu : public Menu {
public:
WarningMenu();
void setup() override;
void post_open() override {};
};
}
#endif

View File

@@ -1,5 +1,5 @@
#include <bootloader/interface/src/menu.h>
#include <bootloader/interface.h>
#include <bootloader/interface/static/interface.h>
#include <ion.h>
#include <kandinsky/context.h>
#include <string.h>
@@ -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();
}

View File

@@ -2,48 +2,82 @@
#define _BOOTLOADER_MENU_H_
#include <ion/keyboard.h>
#include <bootloader/messages.h>
#include <bootloader/interface/static/messages.h>
#include <kandinsky/context.h>
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;
};
}

View File

@@ -0,0 +1,68 @@
#include <assert.h>
#include <ion.h>
#include <ion/timing.h>
#include <bootloader/interface/static/interface.h>
#include <bootloader/interface/static/messages.h>
#include <bootloader/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<uint8_t *>(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);
}
}

View File

@@ -0,0 +1,19 @@
#ifndef BOOTLOADER_INTERFACE_STATIC_INTERFACE_H
#define BOOTLOADER_INTERFACE_STATIC_INTERFACE_H
#include <stdint.h>
#include <kandinsky/context.h>
#include <escher/image.h>
namespace Bootloader {
class Interface {
public:
static void drawImage(KDContext * ctx, const Image * image, int offset);
static void drawLoading();
static void drawFlasher();
};
}
#endif

View File

@@ -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