Skip to content

Commit 707f919

Browse files
committed
[omega] 2.0.2
2 parents 8e63e2a + 6742299 commit 707f919

File tree

11 files changed

+313
-1
lines changed

11 files changed

+313
-1
lines changed

bootloader/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ bootloader_src += $(addprefix bootloader/,\
99
jump_to_firmware.s \
1010
trampoline.cpp \
1111
usb_desc.cpp \
12+
slot_exam_mode.cpp \
13+
utility.cpp \
1214
)
1315

1416
bootloader_images = $(addprefix bootloader/, \

bootloader/boot.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ __attribute__((noreturn)) void Boot::boot() {
4545
setMode(BootMode::SlotA);
4646
Slot::A().boot();
4747
} else {
48+
49+
Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(!Bootloader::Slot::A().userlandHeader()->isOmega());
50+
if (SlotAExamMode != Bootloader::ExamMode::ExamMode::Off && SlotAExamMode != Bootloader::ExamMode::ExamMode::Unknown) {
51+
// We boot the slot in exam_mode
52+
Bootloader::Slot::A().boot();
53+
}
54+
55+
Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(!Bootloader::Slot::B().userlandHeader()->isOmega());
56+
if (SlotBExamMode != Bootloader::ExamMode::ExamMode::Off && SlotBExamMode != Bootloader::ExamMode::ExamMode::Unknown) {
57+
// We boot the slot in exam_mode
58+
Bootloader::Slot::B().boot();
59+
}
60+
4861
// Both valid, boot the selected one
4962
if (mode() == BootMode::SlotA) {
5063
Slot::A().boot();

bootloader/interface.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ void Interface::draw() {
7676
} else {
7777
ctx->drawString("Invalid", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
7878
}
79+
80+
}
81+
82+
if (Bootloader::Slot::A().kernelHeader()->isValid()) {
83+
Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(!Bootloader::Slot::A().userlandHeader()->isOmega());
84+
if (SlotAExamMode != Bootloader::ExamMode::ExamMode::Off && SlotAExamMode != Bootloader::ExamMode::ExamMode::Unknown) {
85+
ctx->drawString("E", KDPoint(238, 0), KDFont::SmallFont, KDColorWhite, KDColorBlack);
86+
}
87+
}
88+
89+
if (Bootloader::Slot::B().kernelHeader()->isValid()) {
90+
Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(!Bootloader::Slot::B().userlandHeader()->isOmega());
91+
if (SlotBExamMode != Bootloader::ExamMode::ExamMode::Off && SlotBExamMode != Bootloader::ExamMode::ExamMode::Unknown) {
92+
ctx->drawString("E", KDPoint(238, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
93+
}
7994
}
8095

8196
}

bootloader/kernel_header.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <bootloader/kernel_header.h>
2+
#include <bootloader/utility.h>
23

34
namespace Bootloader {
45

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

26+
const bool KernelHeader::isAboveVersion16() const {
27+
int sum = Utility::versionSum(m_version, 2);
28+
char newVersion[] = "16";
29+
int min = Utility::versionSum(newVersion, 2);
30+
return sum >= min;
31+
}
32+
2533
}

bootloader/kernel_header.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class KernelHeader {
1111
const char * patchLevel() const;
1212
const bool isValid() const;
1313

14+
const bool isAboveVersion16() const;
15+
1416
const uint32_t* stackPointer() const;
1517
const void(*startPointer() const)();
1618

bootloader/slot.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "kernel_header.h"
77
#include "userland_header.h"
8+
#include "slot_exam_mode.h"
89

910
namespace Bootloader {
1011

bootloader/slot_exam_mode.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#include <bootloader/slot_exam_mode.h>
2+
#include <assert.h>
3+
#include <ion.h>
4+
#include <ion/src/device/shared/drivers/flash.h>
5+
6+
/*
7+
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
8+
*
9+
* Thanks to the Upsilon team, specifically:
10+
* - devdl11
11+
* - Yaya-Cout
12+
* - Lauryy06
13+
*/
14+
15+
namespace Bootloader {
16+
namespace ExamMode {
17+
18+
/* The exam mode is written in flash so that it is resilient to resets.
19+
* We erase the dedicated flash sector (all bits written to 1) and, upon
20+
* deactivating or activating standard, nosym or Dutch exam mode we write one, two or tree
21+
* bits to 0. To determine in which exam mode we are, we count the number of
22+
* leading 0 bits. If it is equal to:
23+
* - 0[3]: the exam mode is off;
24+
* - 1[3]: the standard exam mode is activated;
25+
* - 2[3]: the NoSym exam mode is activated;
26+
* - 3[3]: the Dutch exam mode is activated;
27+
* - 4[3]: the NoSymNoText exam mode is activated. */
28+
29+
/* significantExamModeAddress returns the first uint32_t * in the exam mode
30+
* flash sector that does not point to 0. If this flash sector has only 0s or
31+
* if it has only one 1, it is erased (to 1) and significantExamModeAddress
32+
* returns the start of the sector. */
33+
34+
constexpr static size_t numberOfBitsInByte = 8;
35+
36+
// if i = 0b000011101, firstOneBitInByte(i) returns 5
37+
size_t numberOfBitsAfterLeadingZeroes(int i) {
38+
int minShift = 0;
39+
int maxShift = numberOfBitsInByte;
40+
while (maxShift > minShift+1) {
41+
int shift = (minShift + maxShift)/2;
42+
int shifted = i >> shift;
43+
if (shifted == 0) {
44+
maxShift = shift;
45+
} else {
46+
minShift = shift;
47+
}
48+
}
49+
return maxShift;
50+
}
51+
52+
uint8_t * SignificantSlotAExamModeAddress(bool newVersion) {
53+
uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotAStartExamAddress(newVersion);
54+
uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotAEndExamAddress(newVersion);
55+
if (!newVersion) {
56+
assert((persitence_end_32 - persitence_start_32) % 4 == 0);
57+
while (persitence_start_32 < persitence_end_32 && *persitence_start_32 == 0x0) {
58+
// Scan by groups of 32 bits to reach first non-zero bit
59+
persitence_start_32++;
60+
}
61+
uint8_t * persitence_start_8 = (uint8_t *)persitence_start_32;
62+
uint8_t * persitence_end_8 = (uint8_t *)persitence_end_32;
63+
while (persitence_start_8 < persitence_end_8 && *persitence_start_8 == 0x0) {
64+
// Scan by groups of 8 bits to reach first non-zero bit
65+
persitence_start_8++;
66+
}
67+
if (persitence_start_8 == persitence_end_8
68+
// we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector
69+
|| (persitence_start_8 + 1 == persitence_end_8 && *persitence_start_8 == 1)) {
70+
assert(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotAStartExamAddress(newVersion)) >= 0);
71+
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotAStartExamAddress(newVersion)));
72+
return (uint8_t *)SlotsExamMode::getSlotAStartExamAddress(newVersion);
73+
}
74+
75+
return persitence_start_8;
76+
} else {
77+
persitence_end_32 = persitence_end_32 - 1;
78+
while (persitence_end_32 - (uint32_t)(10 / 8) >= persitence_end_32 && *persitence_end_32 == 0xFFFFFFFF) {
79+
persitence_end_32 -= 1;
80+
}
81+
uint8_t * start = reinterpret_cast<uint8_t *>(persitence_start_32);
82+
uint8_t * end = reinterpret_cast<uint8_t *>(persitence_end_32 + 1) - 1;
83+
while (end >= start + 2 && *end == 0xFF) {
84+
end -= 1;
85+
}
86+
return end - 1;
87+
}
88+
89+
}
90+
91+
uint8_t * SignificantSlotBExamModeAddress(bool newVersion) {
92+
uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotBStartExamAddress(newVersion);
93+
uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotBEndExamAddress(newVersion);
94+
if (!newVersion) {
95+
assert((persitence_end_32 - persitence_start_32) % 4 == 0);
96+
while (persitence_start_32 < persitence_end_32 && *persitence_start_32 == 0x0) {
97+
// Scan by groups of 32 bits to reach first non-zero bit
98+
persitence_start_32++;
99+
}
100+
uint8_t * persitence_start_8 = (uint8_t *)persitence_start_32;
101+
uint8_t * persitence_end_8 = (uint8_t *)persitence_end_32;
102+
while (persitence_start_8 < persitence_end_8 && *persitence_start_8 == 0x0) {
103+
// Scan by groups of 8 bits to reach first non-zero bit
104+
persitence_start_8++;
105+
}
106+
if (persitence_start_8 == persitence_end_8
107+
// we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector
108+
|| (persitence_start_8 + 1 == persitence_end_8 && *persitence_start_8 == 1)) {
109+
assert(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotBStartExamAddress(newVersion)) >= 0);
110+
Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress(SlotsExamMode::getSlotBStartExamAddress(newVersion)));
111+
return (uint8_t *)SlotsExamMode::getSlotBStartExamAddress(newVersion);
112+
}
113+
114+
return persitence_start_8;
115+
} else {
116+
persitence_end_32 = persitence_end_32 - 1;
117+
while (persitence_end_32 - (uint32_t)(10 / 8) >= persitence_end_32 && *persitence_end_32 == 0xFFFFFFFF) {
118+
persitence_end_32 -= 1;
119+
}
120+
uint8_t * start = reinterpret_cast<uint8_t *>(persitence_start_32);
121+
uint8_t * end = reinterpret_cast<uint8_t *>(persitence_end_32 + 1) - 1;
122+
while (end >= start + 2 && *end == 0xFF) {
123+
end -= 1;
124+
}
125+
return end - 1;
126+
}
127+
128+
}
129+
130+
uint8_t SlotsExamMode::FetchSlotAExamMode(bool newVersion) {
131+
uint8_t * readingAddress = SignificantSlotAExamModeAddress(newVersion);
132+
if (!newVersion) {
133+
// Count the number of 0[3] before reading address
134+
uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotAStartExamAddress(newVersion)) * numberOfBitsInByte) % 4;
135+
// Count the number of 0[3] at reading address
136+
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
137+
return (nbOfZerosBefore + numberOfLeading0) % 4;
138+
} else {
139+
return *((uint8_t *)readingAddress);
140+
}
141+
142+
}
143+
144+
uint8_t SlotsExamMode::FetchSlotBExamMode(bool newVersion) {
145+
uint8_t * readingAddress = SignificantSlotBExamModeAddress(newVersion);
146+
if (!newVersion) {
147+
// Count the number of 0[3] before reading address
148+
uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotBStartExamAddress(newVersion)) * numberOfBitsInByte) % 4;
149+
// Count the number of 0[3] at reading address
150+
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
151+
return (nbOfZerosBefore + numberOfLeading0) % 4;
152+
} else {
153+
return *((uint8_t *)readingAddress);
154+
}
155+
156+
}
157+
158+
uint32_t SlotsExamMode::getSlotAStartExamAddress(bool newVersion) {
159+
return newVersion ? SlotAExamModeBufferStartNewVersions : SlotAExamModeBufferStartOldVersions;
160+
}
161+
162+
uint32_t SlotsExamMode::getSlotAEndExamAddress(bool newVersion) {
163+
return newVersion ? SlotAExamModeBufferEndNewVersions : SlotAExamModeBufferEndOldVersions;
164+
}
165+
166+
uint32_t SlotsExamMode::getSlotBStartExamAddress(bool newVersion) {
167+
return newVersion ? SlotBExamModeBufferStartNewVersions : SlotBExamModeBufferStartOldVersions;
168+
}
169+
170+
uint32_t SlotsExamMode::getSlotBEndExamAddress(bool newVersion) {
171+
return newVersion ? SlotBExamModeBufferEndNewVersions : SlotBExamModeBufferEndOldVersions;
172+
}
173+
174+
}
175+
}

bootloader/slot_exam_mode.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef BOOTLOADER_EXAM_MODE_H
2+
#define BOOTLOADER_EXAM_MODE_H
3+
4+
/*
5+
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
6+
*
7+
* Thanks to the Upsilon team, specifically:
8+
* - devdl11
9+
* - Yaya-Cout
10+
* - Lauryy06
11+
*/
12+
13+
extern "C" {
14+
#include <stdint.h>
15+
}
16+
17+
namespace Bootloader {
18+
namespace ExamMode {
19+
20+
static const uint32_t SlotAExamModeBufferStartOldVersions = 0x90001000;
21+
static const uint32_t SlotAExamModeBufferEndOldVersions = 0x90003000;
22+
23+
static const uint32_t SlotAExamModeBufferStartNewVersions = 0x903f0000;
24+
static const uint32_t SlotAExamModeBufferEndNewVersions = 0x90400000;
25+
26+
static const uint32_t SlotBExamModeBufferStartOldVersions = 0x90401000;
27+
static const uint32_t SlotBExamModeBufferEndOldVersions = 0x90403000;
28+
29+
static const uint32_t SlotBExamModeBufferStartNewVersions = 0x907f0000;
30+
static const uint32_t SlotBExamModeBufferEndNewVersions = 0x90800000;
31+
32+
class SlotsExamMode{
33+
public:
34+
static uint8_t FetchSlotAExamMode(bool newVersion);
35+
static uint8_t FetchSlotBExamMode(bool newVerion);
36+
37+
static uint32_t getSlotAStartExamAddress(bool newVersion);
38+
static uint32_t getSlotAEndExamAddress(bool newVersion);
39+
static uint32_t getSlotBStartExamAddress(bool newVersion);
40+
static uint32_t getSlotBEndExamAddress(bool newVersion);
41+
42+
};
43+
44+
enum class ExamMode : int8_t {
45+
Unknown = -1,
46+
Off = 0,
47+
Standard = 1,
48+
NoSym = 2,
49+
NoSymNoText = 3,
50+
Dutch = 4,
51+
};
52+
53+
}
54+
}
55+
56+
#endif

bootloader/utility.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <bootloader/utility.h>
2+
#include <string.h>
3+
4+
/*
5+
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
6+
*
7+
* Thanks to the Upsilon team, specifically:
8+
* - devdl11
9+
* - Yaya-Cout
10+
* - Lauryy06
11+
*/
12+
13+
int Bootloader::Utility::versionSum(const char * version, int length) {
14+
int sum = 0;
15+
for (int i = 0; i < length; i++) {
16+
sum += version[i] * (strlen(version) * 100 - i * 10);
17+
}
18+
return sum;
19+
}

bootloader/utility.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef _BOOTLOADER_ITOA_H_
2+
#define _BOOTLOADER_ITOA_H_
3+
4+
/*
5+
* Taken from https://github.com/UpsilonNumworks/Upsilon/pull/205
6+
*
7+
* Thanks to the Upsilon team, specifically:
8+
* - devdl11
9+
* - Yaya-Cout
10+
* - Lauryy06
11+
*/
12+
13+
namespace Bootloader {
14+
class Utility {
15+
public:
16+
static char * itoa(int value, char * result, int base);
17+
static int versionSum(const char * version, int length);
18+
};
19+
}
20+
21+
#endif

0 commit comments

Comments
 (0)