From 43de4938642e4b6f41f240975532d435c111cd7a Mon Sep 17 00:00:00 2001 From: Lisra-git <89012417+Lisra-git@users.noreply.github.com> Date: Sun, 27 Nov 2022 14:49:10 +0100 Subject: [PATCH 1/5] [bootloader] Fix Exam Mode Added E19+ Compatibility Fixed E16 which was mistakenly assumed to be like E17/E18 --- bootloader/slot_exam_mode.cpp | 244 +++++++++++++++++++--------------- bootloader/slot_exam_mode.h | 15 ++- 2 files changed, 144 insertions(+), 115 deletions(-) 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); }; From 9c5a887d1a39c361ced45796f7e044f90b28108b Mon Sep 17 00:00:00 2001 From: Lisra-git <89012417+Lisra-git@users.noreply.github.com> Date: Sun, 27 Nov 2022 14:52:56 +0100 Subject: [PATCH 2/5] [bootloader] Add protection against E20 E20 integrates a copy of the bootloader at the address of the old userland in order to be able to update the bootloader, we tackle this by checking if the E20 userland is used and deleting the sector containing the update data. --- bootloader/slot.cpp | 26 +++++++++++++++++++++++++- bootloader/slot.h | 7 +++++-- 2 files changed, 30 insertions(+), 3 deletions(-) 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; }; From 5b5ce78da971d991b226d78cbe505a653c5b6ac1 Mon Sep 17 00:00:00 2001 From: Lisra-git <89012417+Lisra-git@users.noreply.github.com> Date: Sun, 27 Nov 2022 14:56:37 +0100 Subject: [PATCH 3/5] [bootloader] QOL changes - Exam corrections - Added a new key and USB manager for a better user experience - The user interface now uses messages at the bottom of the screen for controls and status. - Calculator can be rebooted using Power key - The slot can be swapped on the bootloader menu --- bootloader/boot.cpp | 97 +++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 30 deletions(-) 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); + + } } } From a21f8149e64b6d6ad9c6c5b8fe8d54cc91bd3128 Mon Sep 17 00:00:00 2001 From: Lisra-git <89012417+Lisra-git@users.noreply.github.com> Date: Sun, 27 Nov 2022 14:58:02 +0100 Subject: [PATCH 4/5] [bootloader] Adding screen bottom messages method - Added test corrections in the interface - New messageBox method for status and controls - Correction of the reading of E20 --- bootloader/interface.cpp | 40 +++++++++++++++++++++++++++++++--------- bootloader/interface.h | 1 + 2 files changed, 32 insertions(+), 9 deletions(-) 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); }; From 7593b3b73772d21b52473cc18d8aa66de9ab38ae Mon Sep 17 00:00:00 2001 From: Lisra-git <89012417+Lisra-git@users.noreply.github.com> Date: Sun, 27 Nov 2022 14:59:21 +0100 Subject: [PATCH 5/5] [bootloader] Fix E16 reading E16 uses fewer keys in its header, which causes E16 to not be read in the bootloader menu. We fix this by only checking the header magic in userlandHeader. --- bootloader/userland_header.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 {