Skip to content

Commit

Permalink
[omega] 2.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
M4xi1m3 committed Apr 17, 2022
2 parents 8e63e2a + 6742299 commit 707f919
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 1 deletion.
2 changes: 2 additions & 0 deletions bootloader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ bootloader_src += $(addprefix bootloader/,\
jump_to_firmware.s \
trampoline.cpp \
usb_desc.cpp \
slot_exam_mode.cpp \
utility.cpp \
)

bootloader_images = $(addprefix bootloader/, \
Expand Down
13 changes: 13 additions & 0 deletions bootloader/boot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ __attribute__((noreturn)) void Boot::boot() {
setMode(BootMode::SlotA);
Slot::A().boot();
} else {

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

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) {
// We boot the slot in exam_mode
Bootloader::Slot::B().boot();
}

// Both valid, boot the selected one
if (mode() == BootMode::SlotA) {
Slot::A().boot();
Expand Down
15 changes: 15 additions & 0 deletions bootloader/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ void Interface::draw() {
} else {
ctx->drawString("Invalid", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}

}

if (Bootloader::Slot::A().kernelHeader()->isValid()) {
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) {
ctx->drawString("E", KDPoint(238, 0), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}
}

if (Bootloader::Slot::B().kernelHeader()->isValid()) {
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) {
ctx->drawString("E", KDPoint(238, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}
}

}
Expand Down
8 changes: 8 additions & 0 deletions bootloader/kernel_header.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <bootloader/kernel_header.h>
#include <bootloader/utility.h>

namespace Bootloader {

Expand All @@ -22,4 +23,11 @@ const void(*KernelHeader::startPointer() const)() {
return m_startPointer;
}

const bool KernelHeader::isAboveVersion16() const {
int sum = Utility::versionSum(m_version, 2);
char newVersion[] = "16";
int min = Utility::versionSum(newVersion, 2);
return sum >= min;
}

}
2 changes: 2 additions & 0 deletions bootloader/kernel_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class KernelHeader {
const char * patchLevel() const;
const bool isValid() const;

const bool isAboveVersion16() const;

const uint32_t* stackPointer() const;
const void(*startPointer() const)();

Expand Down
1 change: 1 addition & 0 deletions bootloader/slot.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "kernel_header.h"
#include "userland_header.h"
#include "slot_exam_mode.h"

namespace Bootloader {

Expand Down
175 changes: 175 additions & 0 deletions bootloader/slot_exam_mode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include <bootloader/slot_exam_mode.h>
#include <assert.h>
#include <ion.h>
#include <ion/src/device/shared/drivers/flash.h>

/*
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
*
* Thanks to the Upsilon team, specifically:
* - devdl11
* - Yaya-Cout
* - Lauryy06
*/

namespace Bootloader {
namespace ExamMode {

/* The exam mode is written in flash so that it is resilient to resets.
* We erase the dedicated flash sector (all bits written to 1) and, upon
* deactivating or activating standard, nosym or Dutch exam mode we write one, two or tree
* bits to 0. To determine in which exam mode we are, we count the number of
* leading 0 bits. If it is equal to:
* - 0[3]: the exam mode is off;
* - 1[3]: the standard exam mode is activated;
* - 2[3]: the NoSym exam mode is activated;
* - 3[3]: the Dutch exam mode is activated;
* - 4[3]: the NoSymNoText exam mode is activated. */

/* significantExamModeAddress returns the first uint32_t * in the exam mode
* flash sector that does not point to 0. If this flash sector has only 0s or
* if it has only one 1, it is erased (to 1) and significantExamModeAddress
* returns the start of the sector. */

constexpr static size_t numberOfBitsInByte = 8;

// if i = 0b000011101, firstOneBitInByte(i) returns 5
size_t numberOfBitsAfterLeadingZeroes(int i) {
int minShift = 0;
int maxShift = numberOfBitsInByte;
while (maxShift > minShift+1) {
int shift = (minShift + maxShift)/2;
int shifted = i >> shift;
if (shifted == 0) {
maxShift = shift;
} else {
minShift = shift;
}
}
return maxShift;
}

uint8_t * SignificantSlotAExamModeAddress(bool newVersion) {
uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotAStartExamAddress(newVersion);
uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotAEndExamAddress(newVersion);
if (!newVersion) {
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::getSlotAStartExamAddress(newVersion)) >= 0);
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotAStartExamAddress(newVersion)));
return (uint8_t *)SlotsExamMode::getSlotAStartExamAddress(newVersion);
}

return persitence_start_8;
} else {
persitence_end_32 = persitence_end_32 - 1;
while (persitence_end_32 - (uint32_t)(10 / 8) >= persitence_end_32 && *persitence_end_32 == 0xFFFFFFFF) {
persitence_end_32 -= 1;
}
uint8_t * start = reinterpret_cast<uint8_t *>(persitence_start_32);
uint8_t * end = reinterpret_cast<uint8_t *>(persitence_end_32 + 1) - 1;
while (end >= start + 2 && *end == 0xFF) {
end -= 1;
}
return end - 1;
}

}

uint8_t * SignificantSlotBExamModeAddress(bool newVersion) {
uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotBStartExamAddress(newVersion);
uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotBEndExamAddress(newVersion);
if (!newVersion) {
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::getSlotBStartExamAddress(newVersion)) >= 0);
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotBStartExamAddress(newVersion)));
return (uint8_t *)SlotsExamMode::getSlotBStartExamAddress(newVersion);
}

return persitence_start_8;
} else {
persitence_end_32 = persitence_end_32 - 1;
while (persitence_end_32 - (uint32_t)(10 / 8) >= persitence_end_32 && *persitence_end_32 == 0xFFFFFFFF) {
persitence_end_32 -= 1;
}
uint8_t * start = reinterpret_cast<uint8_t *>(persitence_start_32);
uint8_t * end = reinterpret_cast<uint8_t *>(persitence_end_32 + 1) - 1;
while (end >= start + 2 && *end == 0xFF) {
end -= 1;
}
return end - 1;
}

}

uint8_t SlotsExamMode::FetchSlotAExamMode(bool newVersion) {
uint8_t * readingAddress = SignificantSlotAExamModeAddress(newVersion);
if (!newVersion) {
// Count the number of 0[3] before reading address
uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotAStartExamAddress(newVersion)) * numberOfBitsInByte) % 4;
// Count the number of 0[3] at reading address
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
return (nbOfZerosBefore + numberOfLeading0) % 4;
} else {
return *((uint8_t *)readingAddress);
}

}

uint8_t SlotsExamMode::FetchSlotBExamMode(bool newVersion) {
uint8_t * readingAddress = SignificantSlotBExamModeAddress(newVersion);
if (!newVersion) {
// Count the number of 0[3] before reading address
uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotBStartExamAddress(newVersion)) * numberOfBitsInByte) % 4;
// Count the number of 0[3] at reading address
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
return (nbOfZerosBefore + numberOfLeading0) % 4;
} else {
return *((uint8_t *)readingAddress);
}

}

uint32_t SlotsExamMode::getSlotAStartExamAddress(bool newVersion) {
return newVersion ? SlotAExamModeBufferStartNewVersions : SlotAExamModeBufferStartOldVersions;
}

uint32_t SlotsExamMode::getSlotAEndExamAddress(bool newVersion) {
return newVersion ? SlotAExamModeBufferEndNewVersions : SlotAExamModeBufferEndOldVersions;
}

uint32_t SlotsExamMode::getSlotBStartExamAddress(bool newVersion) {
return newVersion ? SlotBExamModeBufferStartNewVersions : SlotBExamModeBufferStartOldVersions;
}

uint32_t SlotsExamMode::getSlotBEndExamAddress(bool newVersion) {
return newVersion ? SlotBExamModeBufferEndNewVersions : SlotBExamModeBufferEndOldVersions;
}

}
}
56 changes: 56 additions & 0 deletions bootloader/slot_exam_mode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef BOOTLOADER_EXAM_MODE_H
#define BOOTLOADER_EXAM_MODE_H

/*
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
*
* Thanks to the Upsilon team, specifically:
* - devdl11
* - Yaya-Cout
* - Lauryy06
*/

extern "C" {
#include <stdint.h>
}

namespace Bootloader {
namespace ExamMode {

static const uint32_t SlotAExamModeBufferStartOldVersions = 0x90001000;
static const uint32_t SlotAExamModeBufferEndOldVersions = 0x90003000;

static const uint32_t SlotAExamModeBufferStartNewVersions = 0x903f0000;
static const uint32_t SlotAExamModeBufferEndNewVersions = 0x90400000;

static const uint32_t SlotBExamModeBufferStartOldVersions = 0x90401000;
static const uint32_t SlotBExamModeBufferEndOldVersions = 0x90403000;

static const uint32_t SlotBExamModeBufferStartNewVersions = 0x907f0000;
static const uint32_t SlotBExamModeBufferEndNewVersions = 0x90800000;

class SlotsExamMode{
public:
static uint8_t FetchSlotAExamMode(bool newVersion);
static uint8_t FetchSlotBExamMode(bool newVerion);

static uint32_t getSlotAStartExamAddress(bool newVersion);
static uint32_t getSlotAEndExamAddress(bool newVersion);
static uint32_t getSlotBStartExamAddress(bool newVersion);
static uint32_t getSlotBEndExamAddress(bool newVersion);

};

enum class ExamMode : int8_t {
Unknown = -1,
Off = 0,
Standard = 1,
NoSym = 2,
NoSymNoText = 3,
Dutch = 4,
};

}
}

#endif
19 changes: 19 additions & 0 deletions bootloader/utility.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <bootloader/utility.h>
#include <string.h>

/*
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
*
* Thanks to the Upsilon team, specifically:
* - devdl11
* - Yaya-Cout
* - Lauryy06
*/

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;
}
21 changes: 21 additions & 0 deletions bootloader/utility.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef _BOOTLOADER_ITOA_H_
#define _BOOTLOADER_ITOA_H_

/*
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
*
* Thanks to the Upsilon team, specifically:
* - devdl11
* - Yaya-Cout
* - Lauryy06
*/

namespace Bootloader {
class Utility {
public:
static char * itoa(int value, char * result, int base);
static int versionSum(const char * version, int length);
};
}

#endif
2 changes: 1 addition & 1 deletion build/config.mak
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ DEBUG ?= 0

HOME_DISPLAY_EXTERNALS ?= 1
EPSILON_VERSION ?= 15.5.0
OMEGA_VERSION ?= 2.0.1
OMEGA_VERSION ?= 2.0.2
# OMEGA_USERNAME ?= N/A
OMEGA_STATE ?= public
EPSILON_APPS ?= calculation rpn graph code statistics probability solver atomic sequence regression settings external
Expand Down

0 comments on commit 707f919

Please sign in to comment.