forked from numworks/epsilon
-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
313 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters