mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[bootloader] Fix exam mode with Epsilon 19 and add support for Epsilon 20 (#302)
* [bootloader] Fix exam mode on Epsilon 19 * [bootloader] Fix comment indentation * [bootloader] Restore comment indentation (even if GitHub tell that it isn't indented properly) * [bootloader] Turn tabulations into spaces * [bootloader] Mark Epsilon 19 as "safe to boot" * [bootloader] Fix Epsilon 20 boot * [bootloader] Chang version to 1.0.2
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ epsilon.map
|
||||
.gradle
|
||||
.idea/
|
||||
.vs
|
||||
.cache/
|
||||
compile_commands.json
|
||||
|
||||
@@ -107,7 +107,7 @@ void Boot::bootSlot(Bootloader::Slot 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 = "20.0.0";
|
||||
int versionSum = Utility::versionSum(version, strlen(version));
|
||||
int minimalVersionTrigger = Utility::versionSum(min, strlen(min));
|
||||
if (versionSum >= minimalVersionTrigger) {
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
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 * 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";
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
constexpr static const char * aboutMessage4 = "and select the OS";
|
||||
constexpr static const char * aboutMessage5 = "to boot.";
|
||||
|
||||
constexpr static const char * bootloaderVersion = "Version 1.0.1 - FREED0M.19";
|
||||
constexpr static const char * bootloaderVersion = "Version 1.0.2 - FREED0M.20";
|
||||
|
||||
//USB NAMES
|
||||
constexpr static const char * usbUpsilonBootloader = "Upsilon Bootloader";
|
||||
|
||||
@@ -20,30 +20,29 @@ __attribute__ ((noreturn)) void ion_main(int argc, const char * const argv[]) {
|
||||
bool isSlotA = Bootloader::Slot::isFullyValid(Bootloader::Slot::A());
|
||||
|
||||
if (isSlotA) {
|
||||
Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(!Bootloader::Slot::A().userlandHeader()->isOmega());
|
||||
Bootloader::ExamMode::ExamMode SlotAExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotAExamMode(Bootloader::Slot::A().userlandHeader()->version());
|
||||
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::isFullyValid(Bootloader::Slot::B());
|
||||
|
||||
if (isSlotB) {
|
||||
Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(!Bootloader::Slot::B().userlandHeader()->isOmega());
|
||||
Bootloader::ExamMode::ExamMode SlotBExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotBExamMode(Bootloader::Slot::B().userlandHeader()->version());
|
||||
if (SlotBExamMode != Bootloader::ExamMode::ExamMode::Off && SlotBExamMode != Bootloader::ExamMode::ExamMode::Unknown && isSlotB) {
|
||||
// We boot the slot in exam_mode
|
||||
Bootloader::Slot::B().boot();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// I have no idea if this will work, but if Pariss did a good job, it should
|
||||
// I have no idea if this will work, but if Parisse 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();
|
||||
Bootloader::ExamMode::ExamMode KhiExamMode = (Bootloader::ExamMode::ExamMode)Bootloader::ExamMode::SlotsExamMode::FetchSlotKhiExamMode(Bootloader::Slot::Khi().userlandHeader()->version());
|
||||
if (KhiExamMode != Bootloader::ExamMode::ExamMode::Off && KhiExamMode != Bootloader::ExamMode::ExamMode::Unknown && isKhiSlot) {
|
||||
// We boot the slot in exam_mode
|
||||
Bootloader::Slot::Khi().boot();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <bootloader/slots/slot.h>
|
||||
#include <ion/src/device/shared/drivers/board.h>
|
||||
#include <ion/src/device/shared/drivers/flash.h>
|
||||
#include <ion/src/device/shared/drivers/external_flash.h>
|
||||
#include <bootloader/boot.h>
|
||||
|
||||
extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
|
||||
@@ -24,7 +25,13 @@ const KernelHeader* Slot::kernelHeader() const {
|
||||
}
|
||||
|
||||
const UserlandHeader* Slot::userlandHeader() const {
|
||||
return m_userlandHeader;
|
||||
if (m_userlandHeader->isValid()) {
|
||||
return m_userlandHeader;
|
||||
} else if (m_userland2Header->isValid()) {
|
||||
return m_userland2Header;
|
||||
} else {
|
||||
return m_userlandHeader;
|
||||
}
|
||||
}
|
||||
|
||||
[[ noreturn ]] void Slot::boot() const {
|
||||
@@ -37,6 +44,24 @@ const UserlandHeader* Slot::userlandHeader() const {
|
||||
Ion::Device::Flash::LockSlotA();
|
||||
}
|
||||
|
||||
// Erase the bootloader integrated in slots in Epsilon 20
|
||||
if (m_userland2Header->isValid()) {
|
||||
if (m_address == 0x90000000) {
|
||||
// Check if bootloader is present in slot A
|
||||
if (*(uint32_t*)0x90010000 != 0xFFFFFFFF) {
|
||||
// Erase bootloader in slot A
|
||||
Ion::Device::ExternalFlash::EraseSector(9);
|
||||
}
|
||||
}
|
||||
else if (m_address == 0x90400000) {
|
||||
// Check if bootloader is present in slot B
|
||||
if (*(uint32_t*)0x90410000 != 0xFFFFFFFF) {
|
||||
// Erase bootloader in slot B
|
||||
Ion::Device::ExternalFlash::EraseSector(73);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the MPU for the booted firmware
|
||||
Ion::Device::Board::bootloaderMPU();
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ public:
|
||||
Slot(uint32_t address) :
|
||||
m_kernelHeader(reinterpret_cast<KernelHeader*>(address)),
|
||||
m_userlandHeader(reinterpret_cast<UserlandHeader*>(address + 64 * 1024)),
|
||||
m_address(address) { }
|
||||
m_userland2Header(reinterpret_cast<UserlandHeader*>(address + 128 * 1024)),
|
||||
m_address(address) {}
|
||||
|
||||
const KernelHeader* kernelHeader() const;
|
||||
const UserlandHeader* userlandHeader() const;
|
||||
@@ -32,6 +33,7 @@ public:
|
||||
private:
|
||||
const KernelHeader* m_kernelHeader;
|
||||
const UserlandHeader* m_userlandHeader;
|
||||
const UserlandHeader* m_userland2Header;
|
||||
const uint32_t m_address;
|
||||
|
||||
};
|
||||
|
||||
@@ -40,88 +40,70 @@ size_t numberOfBitsAfterLeadingZeroes(int i) {
|
||||
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 SlotsExamMode::FetchSlotExamMode(const char * version, const char * Slot) {
|
||||
// Get start and end from version and slot
|
||||
uint32_t start = 0;
|
||||
uint32_t end = 0;
|
||||
if (Slot == "A") {
|
||||
// If version under 16 get old addresses
|
||||
if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
|
||||
start = getSlotAStartExamAddress(0);
|
||||
end = getSlotAEndExamAddress(0);
|
||||
}
|
||||
// Else get new addresses
|
||||
else {
|
||||
start = getSlotAStartExamAddress(1);
|
||||
end = getSlotAEndExamAddress(1);
|
||||
}
|
||||
}
|
||||
else if (Slot == "B") {
|
||||
// If version under 16 get old
|
||||
if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
|
||||
start = getSlotBStartExamAddress(0);
|
||||
end = getSlotBEndExamAddress(0);
|
||||
}
|
||||
// Else get new
|
||||
else {
|
||||
start = getSlotBStartExamAddress(1);
|
||||
end = getSlotBEndExamAddress(1);
|
||||
}
|
||||
} else if (Slot == "Khi") {
|
||||
// We directly get the address of the Khi exam mode without checking the
|
||||
// version, because on Khi, version is KhiCAS version, not the OS version
|
||||
start = getSlotKhiStartExamAddress();
|
||||
end = getSlotKhiEndExamAddress();
|
||||
}
|
||||
|
||||
if (strcmp("15.9.0", version) >= 0) {
|
||||
return examFetch15(start, end);
|
||||
} else if (strcmp("16.9.0", version) > 0) {
|
||||
return examFetch16(start, end);
|
||||
}
|
||||
else if (strcmp("19.0.0", version) > 0) {
|
||||
return examFetch1718(start, end);
|
||||
}
|
||||
else {
|
||||
return examFetch19(start, end);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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(const char* version) {
|
||||
return FetchSlotExamMode(version, "A");
|
||||
}
|
||||
|
||||
uint8_t * SignificantSlotKhiExamModeAddress() {
|
||||
uint32_t * persitence_start_32 = (uint32_t *)SlotsExamMode::getSlotKhiStartExamAddress();
|
||||
uint32_t * persitence_end_32 = (uint32_t *)SlotsExamMode::getSlotKhiEndExamAddress();
|
||||
|
||||
uint8_t SlotsExamMode::FetchSlotBExamMode(const char* version) {
|
||||
return FetchSlotExamMode(version, "B");
|
||||
}
|
||||
|
||||
uint8_t SlotsExamMode::FetchSlotKhiExamMode(const char* version) {
|
||||
return FetchSlotExamMode(version, "Khi");
|
||||
}
|
||||
|
||||
uint8_t SlotsExamMode::examFetch15(uint32_t start, uint32_t end) {
|
||||
uint32_t * persitence_start_32 = (uint32_t *)start;
|
||||
uint32_t * persitence_end_32 = (uint32_t *)end;
|
||||
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
|
||||
@@ -136,65 +118,86 @@ uint8_t * SignificantSlotKhiExamModeAddress() {
|
||||
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) {
|
||||
// Count the number of 0[3] before reading address
|
||||
uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)getSlotAStartExamAddress(newVersion)) * numberOfBitsInByte) % 4;
|
||||
assert(Ion::Device::Flash::SectorAtAddress(start) >= 0);
|
||||
Ion::Device::Flash::EraseSector(start);
|
||||
uint32_t nbOfZerosBefore = (((uint8_t*)start - (uint8_t*)start) * numberOfBitsInByte) % 4;
|
||||
// Count the number of 0[3] at reading address
|
||||
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
|
||||
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*(uint8_t*)start)) % 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;
|
||||
uint32_t nbOfZerosBefore = ((persitence_start_8 - (uint8_t*)start) * numberOfBitsInByte) % 4;
|
||||
// Count the number of 0[3] at reading address
|
||||
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4;
|
||||
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*persitence_start_8)) % 4;
|
||||
return (nbOfZerosBefore + numberOfLeading0) % 4;
|
||||
} else {
|
||||
return *((uint8_t *)readingAddress);
|
||||
}
|
||||
|
||||
uint8_t SlotsExamMode::examFetch16(uint32_t start, uint32_t end) {
|
||||
uint8_t* persitence_start_8 = (uint8_t*)start;
|
||||
uint8_t* persitence_end_8 = (uint8_t*)end;
|
||||
while (persitence_start_8 + 1 <= persitence_end_8 && (*persitence_start_8 != 0xFF)) {
|
||||
// Scan by groups of 8 bits to reach first non-zero bit
|
||||
persitence_start_8++;
|
||||
}
|
||||
|
||||
|
||||
return *(persitence_start_8 - 1);
|
||||
}
|
||||
|
||||
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;
|
||||
uint8_t SlotsExamMode::examFetch1718(uint32_t start, uint32_t end) {
|
||||
uint8_t* persitence_start_8 = (uint8_t*)start;
|
||||
uint8_t* persitence_end_8 = (uint8_t*)end;
|
||||
while (persitence_start_8 + 1 <= persitence_end_8 && (*persitence_start_8 != 0xFF)) {
|
||||
// Scan by groups of 8 bits to reach first non-zero bit
|
||||
persitence_start_8++;
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotAStartExamAddress(bool newVersion) {
|
||||
return newVersion ? SlotAExamModeBufferStartNewVersions : SlotAExamModeBufferStartOldVersions;
|
||||
return *(persitence_start_8 - 2);
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotAEndExamAddress(bool newVersion) {
|
||||
return newVersion ? SlotAExamModeBufferEndNewVersions : SlotAExamModeBufferEndOldVersions;
|
||||
uint8_t SlotsExamMode::examFetch19(uint32_t start, uint32_t end) {
|
||||
uint16_t* start16 = (uint16_t*)start;
|
||||
uint16_t* end16 = (uint16_t*)end;
|
||||
|
||||
while (start16 + 1 <= end16 && *start16 != 0xFFFF) {
|
||||
start16++;
|
||||
}
|
||||
|
||||
return *(start16 - 1) >> 8;
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotBStartExamAddress(bool newVersion) {
|
||||
return newVersion ? SlotBExamModeBufferStartNewVersions : SlotBExamModeBufferStartOldVersions;
|
||||
uint32_t SlotsExamMode::getSlotAStartExamAddress(int ExamVersion) {
|
||||
if (ExamVersion == 0) {
|
||||
return SlotAExamModeBufferStartOldVersions;
|
||||
}
|
||||
else {
|
||||
return SlotAExamModeBufferStartNewVersions;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotBEndExamAddress(bool newVersion) {
|
||||
return newVersion ? SlotBExamModeBufferEndNewVersions : SlotBExamModeBufferEndOldVersions;
|
||||
uint32_t SlotsExamMode::getSlotAEndExamAddress(int ExamVersion) {
|
||||
if (ExamVersion == 0) {
|
||||
return SlotAExamModeBufferEndOldVersions;
|
||||
}
|
||||
else {
|
||||
return SlotAExamModeBufferEndNewVersions;;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotBStartExamAddress(int ExamVersion) {
|
||||
if (ExamVersion == 0) {
|
||||
return SlotBExamModeBufferStartOldVersions;
|
||||
}
|
||||
else {
|
||||
return SlotBExamModeBufferStartNewVersions;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotBEndExamAddress(int ExamVersion) {
|
||||
if (ExamVersion == 0) {
|
||||
return SlotBExamModeBufferEndOldVersions;
|
||||
}
|
||||
else {
|
||||
return SlotBExamModeBufferEndNewVersions;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SlotsExamMode::getSlotKhiStartExamAddress() {
|
||||
|
||||
@@ -25,17 +25,23 @@ 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 uint8_t FetchSlotExamMode(const char* version, const char* Slot);
|
||||
static uint8_t FetchSlotAExamMode(const char* version);
|
||||
static uint8_t FetchSlotBExamMode(const char* version);
|
||||
static uint8_t FetchSlotKhiExamMode(const char* version);
|
||||
|
||||
static uint32_t getSlotAStartExamAddress(int ExamVersion);
|
||||
static uint32_t getSlotAEndExamAddress(int ExamVersion);
|
||||
static uint32_t getSlotBStartExamAddress(int ExamVersion);
|
||||
static uint32_t getSlotBEndExamAddress(int ExamVersion);
|
||||
static uint32_t getSlotKhiStartExamAddress();
|
||||
static uint32_t getSlotKhiEndExamAddress();
|
||||
|
||||
static uint8_t examFetch15(uint32_t start, uint32_t end);
|
||||
static uint8_t examFetch1718(uint32_t start, uint32_t end);
|
||||
static uint8_t examFetch16(uint32_t start, uint32_t end);
|
||||
static uint8_t examFetch19(uint32_t start, uint32_t end);
|
||||
|
||||
};
|
||||
|
||||
enum class ExamMode : int8_t {
|
||||
|
||||
@@ -10,7 +10,9 @@ const char * UserlandHeader::version() const {
|
||||
}
|
||||
|
||||
const bool UserlandHeader::isValid() const {
|
||||
return m_header == Magic && m_footer == Magic;
|
||||
// We only verify only the first Magic Number, to display version such as
|
||||
// Epsilon 16 with older UserlandHeader layout
|
||||
return m_header == Magic;
|
||||
}
|
||||
|
||||
const bool UserlandHeader::isOmega() const {
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
#include <bootloader/utility.h>
|
||||
#include <string.h>
|
||||
|
||||
// This function takes a pointer to a string (version) and the size of the
|
||||
// string (versionSize) and returns an integer representing the version.
|
||||
// Example: "1.2.3" will return 10203.
|
||||
// "1.0.1-dev" will return 10001.
|
||||
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);
|
||||
int currentNumber = 0;
|
||||
// List of numbers that are allowed in a version
|
||||
const char * allowedNumbers = "0123456789";
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (version[i] == '.') {
|
||||
sum = sum * 100 + currentNumber;
|
||||
currentNumber = 0;
|
||||
} else if (strchr(allowedNumbers, version[i]) != nullptr) {
|
||||
currentNumber = currentNumber * 10 + (version[i] - '0');
|
||||
} else {
|
||||
// We found a character that is not a number or a dot, so we stop
|
||||
break;
|
||||
}
|
||||
}
|
||||
sum = sum * 100 + currentNumber;
|
||||
return sum;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user