diff --git a/bootloader/boot.cpp b/bootloader/boot.cpp index ebaa4e7fc67..8970e12506c 100644 --- a/bootloader/boot.cpp +++ b/bootloader/boot.cpp @@ -39,30 +39,29 @@ __attribute__((noreturn)) void Boot::boot() { } else if (!Slot::A().kernelHeader()->isValid()) { // If slot A is invalid and B valid, boot B setMode(BootMode::SlotB); - Slot::B().boot(); + Slot::B().boot("B"); } else if (!Slot::B().kernelHeader()->isValid()) { // If slot B is invalid and A valid, boot A setMode(BootMode::SlotA); - Slot::A().boot(); + Slot::A().boot("A"); } 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(); - } + const char* version = Bootloader::Slot::A().kernelHeader()->version(); + bool isExam = Bootloader::ExamMode::SlotsExamMode::FetchSlotExamMode(version, "A") > 0; + if (isExam) { + Bootloader::Slot::A().boot("A"); + } - 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(); - } + version = Bootloader::Slot::B().kernelHeader()->version(); + isExam = Bootloader::ExamMode::SlotsExamMode::FetchSlotExamMode(version, "B") > 0; + if (isExam) { + Bootloader::Slot::B().boot("B"); + } // Both valid, boot the selected one if (mode() == BootMode::SlotA) { - Slot::A().boot(); + Slot::A().boot("A"); } else if (mode() == BootMode::SlotB) { - Slot::B().boot(); + Slot::B().boot("B"); } } @@ -74,21 +73,59 @@ __attribute__ ((noreturn)) void Boot::bootloader() { for(;;) { // Draw the interfaces and infos Bootloader::Interface::draw(); - - // Enable USB - Ion::USB::enable(); - - // Wait for the device to be enumerated - do { - // If we pressed back while waiting, reset. - uint64_t scan = Ion::Keyboard::scan(); - if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { - Ion::Device::Reset::core(); - } - } while (!Ion::USB::isEnumerated()); - - // Launch the DFU stack, allowing to press Back to quit and reset - Ion::USB::DFU(true); + Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + + bool abortUSB = false; + while (1) { + uint64_t scan = Ion::Keyboard::scan(); + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) { + Ion::Device::Reset::core(); + } + //allow to set bootmode with 1 and 2 + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::One)) { + Bootloader::Boot::setMode(Bootloader::BootMode::SlotA); + Bootloader::Interface::draw(); + Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + Ion::Timing::msleep(100); + } + if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Two)) { + Bootloader::Boot::setMode(Bootloader::BootMode::SlotB); + Bootloader::Interface::draw(); + Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + Ion::Timing::msleep(100); + } + + if (Ion::USB::isPlugged() && !abortUSB) { + // Enable USB + Ion::USB::enable(); + + Bootloader::Interface::drawMessageBox("USB Enabled", "Press Back to disable USB"); + // Launch the DFU stack, allowing to press Back to quit and reset + Ion::USB::DFU(true); + //wait for usb to be unplugged or back to be pressed + while (Ion::USB::isPlugged() && scan != Ion::Keyboard::State(Ion::Keyboard::Key::Back)) { + scan = Ion::Keyboard::scan(); + Ion::Timing::msleep(100); + } + //cehck if usb is plugged + if (Ion::USB::isPlugged()) { + abortUSB = true; + } + // Disable USB + Ion::USB::disable(); + Bootloader::Interface::draw(); + Bootloader::Interface::drawMessageBox("Press (1)/(2) to select slot", "Press Power to reset"); + + } + + //Prevent USB from launching after Back press + if (!Ion::USB::isPlugged() && abortUSB) { + abortUSB = false; + } + + Ion::Timing::msleep(100); + + } } } diff --git a/bootloader/interface.cpp b/bootloader/interface.cpp index 510271431b7..de86046c8ff 100644 --- a/bootloader/interface.cpp +++ b/bootloader/interface.cpp @@ -11,6 +11,19 @@ namespace Bootloader { + void Interface::drawMessageBox(const char* line1, const char* line2) { + KDContext* ctx = KDIonContext::sharedContext(); + //draw a red box at bottom of screen + ctx->fillRect(KDRect(0, 210, 320, 32), KDColorRed); + //get lenght of each line + int line1Length = strlen(line1); + int line2Length = strlen(line2); + //draw the message + ctx->drawString(line1, KDPoint(160-((line1Length*8)/2), 210), KDFont::SmallFont, KDColorWhite, KDColorRed); + ctx->drawString(line2, KDPoint(160 - ((line2Length*8)/ 2), 228), KDFont::SmallFont, KDColorWhite, KDColorRed); + + } + void Interface::drawImage(KDContext* ctx, const Image* image, int offset) { const uint8_t* data; size_t size; @@ -74,23 +87,32 @@ void Interface::draw() { } ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack); } else { - ctx->drawString("Invalid", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + if (slot.userland2Header()->isValid()) { + ctx->drawString("Epsilon", KDPoint(56, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString(slot.userland2Header()->version(), KDPoint(112, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i * 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + } + 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); - } + const char* version = Bootloader::Slot::A().kernelHeader()->version(); + bool isExam = Bootloader::ExamMode::SlotsExamMode::FetchSlotExamMode(version, "A") > 0; + if (isExam) { + 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); - } + const char* version = Bootloader::Slot::B().kernelHeader()->version(); + bool isExam = Bootloader::ExamMode::SlotsExamMode::FetchSlotExamMode(version, "B") > 0; + if (isExam) { + ctx->drawString("E", KDPoint(238, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack); + } } } diff --git a/bootloader/interface.h b/bootloader/interface.h index 0a98c2b57b6..7cd61329044 100644 --- a/bootloader/interface.h +++ b/bootloader/interface.h @@ -14,6 +14,7 @@ class Interface { public: static void draw(); + static void drawMessageBox(const char* line1, const char* line2); }; diff --git a/bootloader/slot.cpp b/bootloader/slot.cpp index b23655aedef..b3b44344d5d 100644 --- a/bootloader/slot.cpp +++ b/bootloader/slot.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void)); @@ -21,7 +23,29 @@ const UserlandHeader* Slot::userlandHeader() const { return m_userlandHeader; } -[[ noreturn ]] void Slot::boot() const { +const UserlandHeader* Slot::userland2Header() const { + return m_userland2Header; +} + +[[ noreturn ]] void Slot::boot(const char* Slot) const { + //protection mechanism against bootloader update introduced in E20 + //check if the slot use Userland2Header + if (m_userland2Header->isValid()) { + if (Slot == "A") { + //check if 0x90010000 = 0xFFFFFFFF + if (*(uint32_t*)0x90010000 != 0xFFFFFFFF) { + Ion::Device::ExternalFlash::EraseSector(9); + } + } + else if (Slot == "B") { + //check if 0x90410000 = 0xFFFFFFFF + if (*(uint32_t*)0x90410000 != 0xFFFFFFFF) { + Ion::Device::ExternalFlash::EraseSector(73); + } + + } + + } // Configure the MPU for the booted firmware Ion::Device::Board::bootloaderMPU(); diff --git a/bootloader/slot.h b/bootloader/slot.h index cd821df53ec..096ad7db86e 100644 --- a/bootloader/slot.h +++ b/bootloader/slot.h @@ -14,11 +14,13 @@ class Slot { public: Slot(uint32_t address) : m_kernelHeader(reinterpret_cast(address)), - m_userlandHeader(reinterpret_cast(address + 64 * 1024)) { } + m_userlandHeader(reinterpret_cast(address + 64 * 1024)), + m_userland2Header(reinterpret_cast(address + 128 * 1024)) { } const KernelHeader* kernelHeader() const; const UserlandHeader* userlandHeader() const; - [[ noreturn ]] void boot() const; + const UserlandHeader* userland2Header() const; + [[ noreturn ]] void boot(const char* Slot) const; static const Slot A(); static const Slot B(); @@ -26,6 +28,7 @@ class Slot { private: const KernelHeader* m_kernelHeader; const UserlandHeader* m_userlandHeader; + const UserlandHeader* m_userland2Header; }; diff --git a/bootloader/slot_exam_mode.cpp b/bootloader/slot_exam_mode.cpp index fc8d09e9a7d..fc96b541998 100644 --- a/bootloader/slot_exam_mode.cpp +++ b/bootloader/slot_exam_mode.cpp @@ -35,141 +35,167 @@ 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; + 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; + 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; + +uint32_t SlotsExamMode::getSlotAStartExamAddress(int ExamVersion) { + if (ExamVersion == 0) { + return SlotAExamModeBufferStartOldVersions; + } + else { + return SlotAExamModeBufferStartNewVersions; + } +} + +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; + } +} + +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 + if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) { + start = getSlotAStartExamAddress(0); + end = getSlotAEndExamAddress(0); + } + //else get new + 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); + } + } + + if (strcmp("15.9.0", version) >= 0) { + return examFetch15(start, end); + } else if (strcmp("16.9.0", version) > 0) { + return examFetch16(start, end); } - uint8_t * start = reinterpret_cast(persitence_start_32); - uint8_t * end = reinterpret_cast(persitence_end_32 + 1) - 1; - while (end >= start + 2 && *end == 0xFF) { - end -= 1; + else if (strcmp("19.0.0", version) > 0) { + return examFetch1718(start, end); + } + else { + return examFetch19(start, end); } - 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) { +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 - persitence_start_32++; + // 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; + 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++; + // 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); + // 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(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(*(uint8_t*)start)) % 4; + return (nbOfZerosBefore + numberOfLeading0) % 4; } - - 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(persitence_start_32); - uint8_t * end = reinterpret_cast(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; + 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::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); - } - -} +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++; + } -uint32_t SlotsExamMode::getSlotAStartExamAddress(bool newVersion) { - return newVersion ? SlotAExamModeBufferStartNewVersions : SlotAExamModeBufferStartOldVersions; + return *(persitence_start_8 - 1); } -uint32_t SlotsExamMode::getSlotAEndExamAddress(bool newVersion) { - return newVersion ? SlotAExamModeBufferEndNewVersions : SlotAExamModeBufferEndOldVersions; -} +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::getSlotBStartExamAddress(bool newVersion) { - return newVersion ? SlotBExamModeBufferStartNewVersions : SlotBExamModeBufferStartOldVersions; + return *(persitence_start_8 - 2); } -uint32_t SlotsExamMode::getSlotBEndExamAddress(bool newVersion) { - return newVersion ? SlotBExamModeBufferEndNewVersions : SlotBExamModeBufferEndOldVersions; +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; } + + + + } } diff --git a/bootloader/slot_exam_mode.h b/bootloader/slot_exam_mode.h index d6831baa6c4..1e79576939f 100644 --- a/bootloader/slot_exam_mode.h +++ b/bootloader/slot_exam_mode.h @@ -31,13 +31,16 @@ static const uint32_t SlotBExamModeBufferEndNewVersions = 0x90800000; class SlotsExamMode{ public: - static uint8_t FetchSlotAExamMode(bool newVersion); - static uint8_t FetchSlotBExamMode(bool newVerion); + static uint8_t FetchSlotExamMode(const char* version, const char* Slot); - 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 uint32_t getSlotAStartExamAddress(int ExamVersion); + static uint32_t getSlotAEndExamAddress(int ExamVersion); + static uint32_t getSlotBStartExamAddress(int ExamVersion); + static uint32_t getSlotBEndExamAddress(int ExamVersion); + 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); }; diff --git a/bootloader/userland_header.cpp b/bootloader/userland_header.cpp index 5108b187dfa..3c3fcb4f188 100644 --- a/bootloader/userland_header.cpp +++ b/bootloader/userland_header.cpp @@ -9,8 +9,9 @@ const char * UserlandHeader::version() const { return m_expectedEpsilonVersion; } +//verifying only first Magic allow to display version such as E16 with older UserlandHeader Layout const bool UserlandHeader::isValid() const { - return m_header == Magic && m_footer == Magic; + return m_header == Magic; } const bool UserlandHeader::isOmega() const {