From aef43bfd488685c8606dabf14269773badfdbe8b Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 12:44:38 +0100 Subject: [PATCH 01/21] USB Protection correction --- .../sub_menu/usb_protection_controller.cpp | 43 +- ion/src/device/shared/usb/dfu_interface.cpp | 230 +++++----- ion/src/device/shared/usb/dfu_interface.h | 407 ++++++++++-------- 3 files changed, 370 insertions(+), 310 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index f551f6121e7..5f77445e079 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -13,11 +13,10 @@ using namespace Shared; namespace Settings { -UsbInfoController::UsbInfoController(Responder *parentResponder): - GenericSubController(parentResponder), - m_usbProtectionLevelController(this), - m_contentView(&m_selectableTableView) -{ +UsbInfoController::UsbInfoController(Responder *parentResponder) : + GenericSubController(parentResponder), + m_usbProtectionLevelController(this), + m_contentView(&m_selectableTableView) { m_switchCell.setMessageFont(KDFont::LargeFont); m_dfuLevelCell.setMessageFont(KDFont::LargeFont); } @@ -39,14 +38,7 @@ bool UsbInfoController::handleEvent(Ion::Events::Event event) { m_selectableTableView.reloadCellAtLocation(0, 0); return true; } - // We cannot use things like willExitResponderChain because this view can disappear due to an USB connection, - // and in this case we must keep the DFU status. - if ((Ion::Events::Left == event || Ion::Events::Home == event || Ion::Events::Back == event) && GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()) { - GlobalPreferences::sharedGlobalPreferences()->setDfuUnlocked(false); - m_selectableTableView.reloadCellAtLocation(0, 0); - Container::activeApp()->displayWarning(I18n::Message::USBProtectionReactivated); - return true; - } + if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 1) { GenericSubController *subController = &m_usbProtectionLevelController; subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(1)); @@ -55,6 +47,20 @@ bool UsbInfoController::handleEvent(Ion::Events::Event event) { stack->push(subController); return true; } + + // We cannot use things like willExitResponderChain because this view can disappear due to an USB connection, + // and in this case we must keep the DFU status. + if ((event != Ion::Events::USBPlug && event != Ion::Events::USBEnumeration) && + GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()) { + GlobalPreferences::sharedGlobalPreferences()->setDfuUnlocked(false); + m_selectableTableView.reloadCellAtLocation(0, 0); + Container::activeApp()->displayWarning(I18n::Message::USBProtectionReactivated); + if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + Ion::LED::setColor(KDColorBlack); + } + return true; + } + return GenericSubController::handleEvent(event); } @@ -75,15 +81,15 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) GenericSubController::willDisplayCellForIndex(cell, index); if (index == 0) { - MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *)cell; - SwitchView *mySwitch = (SwitchView *)myCell->accessoryView(); + MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *) cell; + SwitchView *mySwitch = (SwitchView *) myCell->accessoryView(); mySwitch->setState(!GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()); } else if (index == 1) { - MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *)cell; + MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *) cell; int currentLevel = GlobalPreferences::sharedGlobalPreferences()->dfuLevel(); if (currentLevel == 0) { mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); - } else if (currentLevel == 1) {; + } else if (currentLevel == 1) { ; mcell->setSubtitle(I18n::Message::USBLowLevelDesc); } else { assert(currentLevel == 2); @@ -94,7 +100,8 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) void UsbInfoController::didEnterResponderChain(Responder *previousFirstResponder) { m_contentView.reload(); - I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2, I18n::Message::USBExplanation3}; + I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2, + I18n::Message::USBExplanation3}; m_contentView.setMessages(infoMessages, k_numberOfExplanationMessages); } } diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 6a7a024411a..e32e63bfde7 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -15,8 +15,6 @@ namespace Ion { namespace Device { namespace USB { -constexpr static uint8_t k_externalMagik[9] = {0x64, 0x6c, 0x31, 0x31, 0x23, 0x39, 0x38, 0x33, 0x35}; - static inline uint32_t minUint32T(uint32_t x, uint32_t y) { return x < y ? x : y; } void DFUInterface::StatusData::push(Channel *c) const { @@ -32,16 +30,17 @@ void DFUInterface::StateData::push(Channel *c) const { c->push(m_bState); } -void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t)DFURequest::Download) { +void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) { + if (request->bRequest() == (uint8_t) DFURequest::Download) { // Handle a download request if (request->wValue() == 0) { // The request is a special command switch (transferBuffer[0]) { - case (uint8_t)DFUDownloadCommand::SetAddressPointer: + case (uint8_t) DFUDownloadCommand::SetAddressPointer: setAddressPointerCommand(request, transferBuffer, *transferBufferLength); return; - case (uint8_t)DFUDownloadCommand::Erase: + case (uint8_t) DFUDownloadCommand::Erase: eraseCommand(transferBuffer, *transferBufferLength); return; default: @@ -57,6 +56,7 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran if (request->wLength() > 0) { // The request is a "real" download. Compute the writing address. m_writeAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; + // Store the received data until we copy it on the flash. memcpy(m_largeBuffer, transferBuffer, *transferBufferLength); m_largeBufferLength = *transferBufferLength; @@ -65,21 +65,23 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran } } -void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { +void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) { + if (request->bRequest() == (uint8_t) DFURequest::GetStatus) { // Do any needed action after the GetStatus request. if (m_state == State::dfuMANIFEST) { /* If we leave the DFU and reset immediately, dfu-util outputs an error: - * "File downloaded successfully - * dfu-util: Error during download get_status" - * If we sleep 1us here, there is no error. We put 1ms for security. - * This error might be due to the USB connection being cut too soon after - * the last USB exchange, so the host does not have time to process the - * answer received for the last GetStatus request. */ + * "File downloaded successfully + * dfu-util: Error during download get_status" + * If we sleep 1us here, there is no error. We put 1ms for security. + * This error might be due to the USB connection being cut too soon after + * the last USB exchange, so the host does not have time to process the + * answer received for the last GetStatus request. */ Ion::Timing::msleep(1); // Leave DFU routine: Leave DFU, reset device, jump to application code leaveDFUAndReset(); } else if (m_state == State::dfuDNBUSY) { + m_state = State::dfuDNBUSY; if (m_largeBufferLength != 0) { // Here, copy the data from the transfer buffer to the flash memory writeOnMemory(); @@ -91,25 +93,27 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer } } -bool DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool +DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) { if (Interface::processSetupInRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength)) { return true; } switch (request->bRequest()) { - case (uint8_t)DFURequest::Detach: + case (uint8_t) DFURequest::Detach: m_device->detach(); return true; - case (uint8_t)DFURequest::Download: + case (uint8_t) DFURequest::Download: return processDownloadRequest(request->wLength(), transferBufferLength); - case (uint8_t)DFURequest::Upload: + case (uint8_t) DFURequest::Upload: return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::GetStatus: + case (uint8_t) DFURequest::GetStatus: return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::ClearStatus: + case (uint8_t) DFURequest::ClearStatus: return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::GetState: + case (uint8_t) DFURequest::GetState: return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t)DFURequest::Abort: + case (uint8_t) DFURequest::Abort: return dfuAbort(transferBufferLength); } return false; @@ -133,43 +137,44 @@ bool DFUInterface::processDownloadRequest(uint16_t wLength, uint16_t *transferBu return true; } -bool DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool +DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) { if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) { m_ep0->stallTransaction(); return false; } if (request->wValue() == 0) { /* The host requests to read the commands supported by the bootloader. After - * receiving this command, the device should returns N bytes representing - * the command codes for : - * Get command / Set Address Pointer / Erase / Read Unprotect - * We no not need it for now. */ + * receiving this command, the device should returns N bytes representing + * the command codes for : + * Get command / Set Address Pointer / Erase / Read Unprotect + * We no not need it for now. */ return false; } else if (request->wValue() == 1) { m_ep0->stallTransaction(); return false; } else { /* We decided to never protect Read operation. Else we would have to check - * here it is not protected before reading. */ + * here it is not protected before reading. */ // Compute the reading address uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; // Copy the requested memory zone into the transfer buffer. uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); - memcpy(transferBuffer, (void *)readAddress, copySize); + memcpy(transferBuffer, (void *) readAddress, copySize); *transferBufferLength = copySize; } m_state = State::dfuUPLOADIDLE; return true; } -void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength) { +void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, + uint16_t transferBufferLength) { assert(transferBufferLength == 5); // Compute the new address but change it after the next getStatus request. - m_potentialNewAddressPointer = transferBuffer[1] - + (transferBuffer[2] << 8) - + (transferBuffer[3] << 16) - + (transferBuffer[4] << 24); + m_potentialNewAddressPointer = + transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); m_state = State::dfuDNLOADSYNC; } @@ -187,7 +192,7 @@ void DFUInterface::changeAddressPointerIfNeeded() { void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength) { /* We determine whether the commands asks for a mass erase or which sector to - * erase. The erase must be done after the next getStatus request. */ + * erase. The erase must be done after the next getStatus request. */ m_state = State::dfuDNLOADSYNC; if (transferBufferLength == 1) { @@ -199,10 +204,8 @@ void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBuffer // Sector erase assert(transferBufferLength == 5); - uint32_t m_eraseAddress = transferBuffer[1] - + (transferBuffer[2] << 8) - + (transferBuffer[3] << 16) - + (transferBuffer[4] << 24); + m_eraseAddress = + transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); m_erasePage = Flash::SectorAtAddress(m_eraseAddress); if (m_erasePage < 0) { @@ -214,24 +217,14 @@ void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBuffer void DFUInterface::eraseMemoryIfNeeded() { if (m_erasePage < 0) { - // There was no erase waiting. return; } - willErase(); - -#if 0 // We don't erase now the flash memory to avoid crash if writing is refused - if (m_erasePage == Flash::TotalNumberOfSectors()) { - Flash::MassErase(); - } -#endif - - if ((m_eraseAddress >= k_externalAppsBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || m_dfuUnlocked) { - Flash::EraseSector(m_erasePage); + if ((m_eraseAddress >= k_ExternalBorderAddress && m_eraseAddress < ExternalFlash::Config::EndAddress) || + m_dfuUnlocked) { + int32_t order = Flash::SectorAtAddress(m_eraseAddress); + Flash::EraseSector(order); } - /* Put an out of range value in m_erasePage to indicate that no erase is - * waiting. */ - m_erasePage = -1; m_state = State::dfuDNLOADIDLE; m_status = Status::OK; m_erasePage = -1; @@ -241,68 +234,91 @@ void DFUInterface::writeOnMemory() { if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { // Write on SRAM // FIXME We should check that we are not overriding the current instructions. - memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); - resetProtectionVariables(); // We can reset the protection variables because update process is finsihed. + memcpy((void *) m_writeAddress, m_largeBuffer, m_largeBufferLength); + resetFlashParameters(); // We are writing in SRAM, so we can reset flash parameters } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { - if (m_dfuLevel == 2) { // If no-update mode, we throw an error + if (m_dfuLevel == 2) { // We don't accept update m_largeBufferLength = 0; m_state = State::dfuERROR; m_status = Status::errWRITE; - leaveDFUAndReset(false); return; } - - if (!(m_isTemporaryUnlocked || m_dfuUnlocked)) { - if (m_writeAddress >= InternalFlash::Config::StartAddress && m_writeAddress <= InternalFlash::Config::EndAddress) { - // We check if the user is autorized to write on the internal flash - if (m_haveAlreadyFlashedExternal) { - for (size_t i = 0; i < 4; i++) { - if (k_internalMagik[i] != m_largeBuffer[k_internalMagikPointer + i]) { - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errWRITE; - // We don't leave DFU to avoid having only external flashed - return; - } - m_largeBuffer[k_internalMagikPointer + i] = 0; // We reset the buffer to its initial value + + int currentMemoryType; // Detection of the current memory type (Internal or External) + + if (m_writeAddress >= InternalFlash::Config::StartAddress && + m_writeAddress <= InternalFlash::Config::EndAddress) { + // We are writing in Internal where live the internal recovery (it's the most sensitive memory type) + if (m_isInternalLocked && !m_dfuUnlocked) { + // We have to check if external was written in order to + // prevent recovery mode loop or the necessity to activate STM bootloader (which is like a superuser mode) + // Nevertheless, unlike NumWorks, we don't forbid its access. + m_largeBufferLength = 0; + m_state = State::dfuERROR; + m_status = Status::errTARGET; + leaveDFUAndReset(false); + return; + } + + currentMemoryType = 0; + + // If the protection is activated, + // we check the internal magic code in order to prevent the NumWorks' Bootloader flash + + if (m_isFirstInternalPacket && !m_dfuUnlocked) { + for (int i = 0; i < 4; i++) { + if (k_omegaMagic[i] != m_largeBuffer[k_internalMagicAddress + i]) { + m_largeBufferLength = 0; + m_state = State::dfuERROR; + m_status = Status::errVERIFY; + return; } } - else { // All people trying to write on the internal flash before external are considered as not authorized - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errTARGET; - leaveDFUAndReset(false); - return; - } + // We only check the first packet because there is some predictable data in there + m_isFirstInternalPacket = false; } - else if (m_writeAddress < k_externalAppsBorderAddress) { // If we are not installing external apps - if (m_dfuLevel == 0) { - for (size_t i = 0; i < 9; i++) { - if (k_externalMagik[i] != m_largeBuffer[k_externalMagikPointer + i]) { - m_largeBufferLength = 0; - m_state = State::dfuERROR; - m_status = Status::errWRITE; - leaveDFUAndReset(false); - return; - } - m_largeBuffer[k_externalMagikPointer + i] = 0; // We reset the buffer to its initial value + } else { + + currentMemoryType = 1; + // We are writing in the external part where live the users apps. It's not a sensitive memory, + // but we check it in Upsilon Mode to ensure compatibility between the internal and the external. + if (m_writeAddress < k_ExternalBorderAddress && m_isFirstExternalPacket && m_dfuLevel == 0 && + !m_dfuUnlocked) { + // We skip any data verification if the user is writing in the Optionals Applications part in the + // external (Externals Apps) + for (int i = 0; i < 4; i++) { + if (k_externalUpsilonMagic[i] != m_largeBuffer[k_externalMagicAddress + i]) { + m_largeBufferLength = 0; + leaveDFUAndReset(false); + return; } - m_isTemporaryUnlocked = true; // We can unlock the flash because signature is good - } - else { - m_haveAlreadyFlashedExternal = true; } } + // We only check the first packet because there is some predictable data in there, + // and we unlock the internal memory + m_isFirstExternalPacket = false; + m_isInternalLocked = false; } - int pageToErase = Flash::SectorAtAddress(m_writeAddress); + // We check if we changed the memory type where we are writing from last time. + if (m_lastMemoryType >= 0 && currentMemoryType != m_lastMemoryType) { + m_lastMemoryType = -1; + } - //On vérifie qu'on a pas déjà effacé le secteur et si ce n'est pas un secteur external déjà effacé - if ((m_lastErasedPage == -1 || pageToErase != m_lastErasedPage) && m_writeAddress < k_externalAppsBorderAddress && !m_dfuUnlocked) { - Flash::EraseSector(pageToErase); - m_lastErasedPage = pageToErase; + m_erasePage = Flash::SectorAtAddress(m_writeAddress); + + // We check if the Sector where we are writing was not already erased and if not, we erase it. + if ((m_lastMemoryType < 0 || m_erasePage != m_lastPageErased) && + m_writeAddress < k_ExternalBorderAddress && !m_dfuUnlocked) { + Flash::EraseSector(m_erasePage); + m_lastMemoryType = currentMemoryType; } + m_lastPageErased = m_erasePage; + m_erasePage = -1; + + // We wait a little before writing in order to prevent some memory error. + Ion::Timing::msleep(1); Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); } else { // Invalid write address @@ -311,7 +327,6 @@ void DFUInterface::writeOnMemory() { m_status = Status::errTARGET; return; } - // Reset the buffer length m_largeBufferLength = 0; // Change the interface state and status @@ -319,7 +334,8 @@ void DFUInterface::writeOnMemory() { m_status = Status::OK; } -bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) { // Change the status if needed if (m_state == State::dfuMANIFESTSYNC) { m_state = State::dfuMANIFEST; @@ -331,7 +347,8 @@ bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint return true; } -bool DFUInterface::clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool DFUInterface::clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) { m_status = Status::OK; m_state = State::dfuIDLE; return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); @@ -350,11 +367,14 @@ bool DFUInterface::dfuAbort(uint16_t *transferBufferLength) { } void DFUInterface::leaveDFUAndReset(bool do_reset) { - resetProtectionVariables(); + resetFlashParameters(); + m_isInternalLocked = true; + m_isFirstInternalPacket = true; + m_isFirstExternalPacket = true; m_device->setResetOnDisconnect(do_reset); m_device->detach(); } -} -} -} +} // namespace USB +} // namespace Device +} // namespace Ion diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index dd87c6cddfd..f9b030c1a4d 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -11,199 +11,232 @@ #include #include -namespace Ion -{ -namespace Device -{ -namespace USB -{ - -class DFUInterface : public Interface { - -public: - DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting): - Interface(ep0), - m_device(device), - m_status(Status::OK), - m_state(State::dfuIDLE), - m_addressPointer(0), - m_potentialNewAddressPointer(0), - m_erasePage(-1), - m_largeBuffer{0}, - m_largeBufferLength(0), - m_writeAddress(0), - m_eraseAddress(0), - m_bInterfaceAlternateSetting(bInterfaceAlternateSetting), - m_lastErasedPage(-1), - m_isErasingAndWriting(false), - m_isTemporaryUnlocked(false), - m_haveAlreadyFlashedExternal(false), - m_dfuUnlocked(false), - m_dfuLevel(0) - { - - } - uint32_t addressPointer() const { return m_addressPointer; } - void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; - void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; - bool isErasingAndWriting() const { return m_isErasingAndWriting; } - void unlockDfu() { m_dfuUnlocked = true; }; - void setLevel(uint8_t lvl) { m_dfuLevel = lvl; } - -protected: - void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { - assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); - } - uint8_t getActiveInterfaceAlternative() override { - return m_bInterfaceAlternateSetting; - } - bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override; - -private: - // DFU Request Codes - enum class DFURequest { - Detach = 0, - Download = 1, - Upload = 2, - GetStatus = 3, - ClearStatus = 4, - GetState = 5, - Abort = 6 - }; - - // DFU Download Commmand Codes - enum class DFUDownloadCommand { - GetCommand = 0x00, - SetAddressPointer = 0x21, - Erase = 0x41, - ReadUnprotect = 0x92 - }; - - enum class Status : uint8_t { - OK = 0x00, - errTARGET = 0x01, - errFILE = 0x02, - errWRITE = 0x03, - errERASE = 0x04, - errCHECK_ERASED = 0x05, - errPROG = 0x06, - errVERIFY = 0x07, - errADDRESS = 0x08, - errNOTDONE = 0x09, - errFIRMWARE = 0x0A, - errVENDOR = 0x0B, - errUSBR = 0x0C, - errPOR = 0x0D, - errUNKNOWN = 0x0E, - errSTALLEDPKT = 0x0F - }; - - enum class State : uint8_t { - appIDLE = 0, - appDETACH = 1, - dfuIDLE = 2, - dfuDNLOADSYNC = 3, - dfuDNBUSY = 4, - dfuDNLOADIDLE = 5, - dfuMANIFESTSYNC = 6, - dfuMANIFEST = 7, - dfuMANIFESTWAITRESET = 8, - dfuUPLOADIDLE = 9, - dfuERROR = 10 - }; - - class StatusData : public Streamable { - public: - StatusData(Status status, State state, uint32_t pollTimeout = 10): - /* We put a default pollTimeout value of 1ms: if the device is busy, the - * host has to wait 1ms before sending a getStatus Request. */ - m_bStatus((uint8_t)status), - m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), uint8_t(pollTimeout & 0xFF)}, - m_bState((uint8_t)state), - m_iString(0) - { - } - protected: - void push(Channel * c) const override; - private: - uint8_t m_bStatus; // Status resulting from the execution of the most recent request - uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits - uint8_t m_bState; // State of the device immediately following transmission of this response - uint8_t m_iString; - }; - - class StateData : public Streamable - { - public: - StateData(State state) : m_bState((uint8_t)state) {} - protected: - void push(Channel *c) const override; - private: - uint8_t m_bState; // Current state of the device - }; - - /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is +namespace Ion { + namespace Device { + namespace USB { + + class DFUInterface : public Interface { + + public: + DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), + m_device(device), + m_status(Status::OK), + m_state(State::dfuIDLE), + m_addressPointer(0), + m_potentialNewAddressPointer( + 0), + m_erasePage(-1), + m_largeBuffer{0}, + m_largeBufferLength( + 0), + m_writeAddress(0), + m_eraseAddress(0), + m_bInterfaceAlternateSetting( + bInterfaceAlternateSetting), + m_isErasingAndWriting( + false), + m_isFirstInternalPacket( + true), + m_isInternalLocked( + true), + m_isFirstExternalPacket( + true), + m_lastMemoryType( + -1), + m_lastPageErased(-1), + m_dfuUnlocked(false), + m_dfuLevel(0) { + } + + uint32_t addressPointer() const { return m_addressPointer; } + + void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) override; + + void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) override; + + bool isErasingAndWriting() const { return m_isErasingAndWriting; } + + void unlockDfu() { m_dfuUnlocked = true; }; + + void setLevel(int lvl) { m_dfuLevel = lvl; } + + protected: + void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { + assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); + } + + uint8_t getActiveInterfaceAlternative() override { + return m_bInterfaceAlternateSetting; + } + + bool + processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) override; + + private: + // DFU Request Codes + enum class DFURequest { + Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6 + }; + + // DFU Download Commmand Codes + enum class DFUDownloadCommand { + GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 + }; + + enum class Status : uint8_t { + OK = 0x00, + errTARGET = 0x01, + errFILE = 0x02, + errWRITE = 0x03, + errERASE = 0x04, + errCHECK_ERASED = 0x05, + errPROG = 0x06, + errVERIFY = 0x07, + errADDRESS = 0x08, + errNOTDONE = 0x09, + errFIRMWARE = 0x0A, + errVENDOR = 0x0B, + errUSBR = 0x0C, + errPOR = 0x0D, + errUNKNOWN = 0x0E, + errSTALLEDPKT = 0x0F + }; + + enum class State : uint8_t { + appIDLE = 0, + appDETACH = 1, + dfuIDLE = 2, + dfuDNLOADSYNC = 3, + dfuDNBUSY = 4, + dfuDNLOADIDLE = 5, + dfuMANIFESTSYNC = 6, + dfuMANIFEST = 7, + dfuMANIFESTWAITRESET = 8, + dfuUPLOADIDLE = 9, + dfuERROR = 10 + }; + + class StatusData : public Streamable { + public: + StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the + * host has to wait 1ms before sending a getStatus Request. */ + m_bStatus((uint8_t) status), + m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), + uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { + } + + protected: + void push(Channel *c) const override; + + private: + uint8_t m_bStatus; // Status resulting from the execution of the most recent request + uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits + uint8_t m_bState; // State of the device immediately following transmission of this response + uint8_t m_iString; + }; + + class StateData : public Streamable { + public: + StateData(State state) : m_bState((uint8_t) state) {} + + protected: + void push(Channel *c) const override; + + private: + uint8_t m_bState; // Current state of the device + }; + + /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is * linked with dfu.ld, so we cannot access the values. */ - constexpr static uint32_t k_sramStartAddress = 0x20000000; - constexpr static uint32_t k_sramEndAddress = 0x20040000; - constexpr static uint32_t k_externalAppsBorderAddress = 0x90200000; - - constexpr static int k_internalMagikPointer = 0x1C4; - constexpr static int k_externalMagikPointer = 0x44F; - constexpr static uint8_t k_internalMagik[4] = {0xF0, 0x0D, 0xC0, 0xDE}; - constexpr static uint8_t k_externalMagik[4] = {0x32, 0x30, 0x30, 0x36}; - - // Download and upload - bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); - bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - // Address pointer - void setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); - void changeAddressPointerIfNeeded(); - // Access memory - void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); - void eraseMemoryIfNeeded(); - void eraseMemoryIfNeededWithoutErasingAtAll(); - void writeOnMemory(); - void unlockFlashMemory(); - void lockFlashMemoryAndPurgeCaches(); - // Status - bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); - // State - bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); - // Abort - bool dfuAbort(uint16_t *transferBufferLength); - // Leave DFU - void leaveDFUAndReset(bool do_reset=true); - /* Erase and Write state. After starting the erase of flash memory, the user + constexpr static uint32_t k_sramStartAddress = 0x20000000; + constexpr static uint32_t k_sramEndAddress = 0x20040000; + constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; + + const static int k_internalMagicAddress = 0x1C4; + constexpr static int k_externalMagicAddress = 0x44f; + constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; + // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) + constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; + + // Download and upload + bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); + + bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + // Address pointer + void + setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); + + void changeAddressPointerIfNeeded(); + + // Access memory + void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); + + void eraseMemoryIfNeeded(); + + void eraseMemoryIfNeededWithoutErasingAtAll(); + + void writeOnMemory(); + + void unlockFlashMemory(); + + void lockFlashMemoryAndPurgeCaches(); + + // Status + bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + // State + bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); + + // Abort + bool dfuAbort(uint16_t *transferBufferLength); + + // Leave DFU + void leaveDFUAndReset(bool do_reset = true); + + /* Erase and Write state. After starting the erase of flash memory, the user * can no longer leave DFU mode by pressing the Back key of the keyboard. This * way, we prevent the user from interrupting a software download. After every * software download, the calculator resets, which unlocks the "exit on * pressing back". */ - void willErase() { m_isErasingAndWriting = true; } - void resetProtectionVariables() { m_lastErasedPage = -1; m_isTemporaryUnlocked = false; m_haveAlreadyFlashedExternal = false; } - - Device *m_device; - Status m_status; - State m_state; - uint32_t m_addressPointer; - uint32_t m_potentialNewAddressPointer; - int32_t m_erasePage; - uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; - uint16_t m_largeBufferLength; - uint32_t m_writeAddress; - uint32_t m_eraseAddress; - uint8_t m_bInterfaceAlternateSetting; - uint8_t m_lastErasedPage; - bool m_isErasingAndWriting; - bool m_isTemporaryUnlocked; - bool m_haveAlreadyFlashedExternal; - bool m_dfuUnlocked; - uint8_t m_dfuLevel; // 0: Upsilon only, 1: Omega-forked only, 2: No update -}; + void willErase() { m_isErasingAndWriting = true; } + + void resetFlashParameters() { + m_lastMemoryType = -1; + m_lastPageErased = -1; + } + + Device *m_device; + Status m_status; + State m_state; + uint32_t m_addressPointer; + uint32_t m_potentialNewAddressPointer; + int32_t m_erasePage; + uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; + uint16_t m_largeBufferLength; + uint32_t m_writeAddress; + uint32_t m_eraseAddress; + uint8_t m_bInterfaceAlternateSetting; + bool m_isErasingAndWriting; + bool m_isFirstInternalPacket; + bool m_isInternalLocked; + bool m_isFirstExternalPacket; + int m_lastMemoryType; // -1: aucune; 0: internal; 1: external + int m_lastPageErased; // -1 par défaut + bool m_dfuUnlocked; + int m_dfuLevel; + }; -} -} + } + } } #endif From 5c7e4be74ff4e5b3fb47a7eb4ce4c0fe46892dd0 Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 13:38:12 +0100 Subject: [PATCH 02/21] Indentation Fix --- apps/settings/sub_menu/usb_protection_controller.cpp | 6 +++--- ion/src/device/shared/usb/dfu_interface.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index 5f77445e079..e03dacdff85 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -14,9 +14,9 @@ using namespace Shared; namespace Settings { UsbInfoController::UsbInfoController(Responder *parentResponder) : - GenericSubController(parentResponder), - m_usbProtectionLevelController(this), - m_contentView(&m_selectableTableView) { + GenericSubController(parentResponder), + m_usbProtectionLevelController(this), + m_contentView(&m_selectableTableView) { m_switchCell.setMessageFont(KDFont::LargeFont); m_dfuLevelCell.setMessageFont(KDFont::LargeFont); } diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index e32e63bfde7..fba94b05b38 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -174,7 +174,7 @@ void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *trans assert(transferBufferLength == 5); // Compute the new address but change it after the next getStatus request. m_potentialNewAddressPointer = - transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); + transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); m_state = State::dfuDNLOADSYNC; } @@ -205,7 +205,7 @@ void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBuffer assert(transferBufferLength == 5); m_eraseAddress = - transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); + transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); m_erasePage = Flash::SectorAtAddress(m_eraseAddress); if (m_erasePage < 0) { From 6f47e94802de31c3786570ba5804dfb7b94abbc1 Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 13:44:03 +0100 Subject: [PATCH 03/21] Indentation Fix --- .../sub_menu/usb_protection_controller.cpp | 6 ++--- ion/src/device/shared/usb/dfu_interface.cpp | 26 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index e03dacdff85..de1853e9f22 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -81,11 +81,11 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) GenericSubController::willDisplayCellForIndex(cell, index); if (index == 0) { - MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *) cell; - SwitchView *mySwitch = (SwitchView *) myCell->accessoryView(); + MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *)cell; + SwitchView *mySwitch = (SwitchView *)myCell->accessoryView(); mySwitch->setState(!GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()); } else if (index == 1) { - MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *) cell; + MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *)cell; int currentLevel = GlobalPreferences::sharedGlobalPreferences()->dfuLevel(); if (currentLevel == 0) { mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index fba94b05b38..81f82ca4b9b 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -32,15 +32,15 @@ void DFUInterface::StateData::push(Channel *c) const { void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t) DFURequest::Download) { + if (request->bRequest() == (uint8_t)DFURequest::Download) { // Handle a download request if (request->wValue() == 0) { // The request is a special command switch (transferBuffer[0]) { - case (uint8_t) DFUDownloadCommand::SetAddressPointer: + case (uint8_t)DFUDownloadCommand::SetAddressPointer: setAddressPointerCommand(request, transferBuffer, *transferBufferLength); return; - case (uint8_t) DFUDownloadCommand::Erase: + case (uint8_t)DFUDownloadCommand::Erase: eraseCommand(transferBuffer, *transferBufferLength); return; default: @@ -67,7 +67,7 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t) DFURequest::GetStatus) { + if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { // Do any needed action after the GetStatus request. if (m_state == State::dfuMANIFEST) { /* If we leave the DFU and reset immediately, dfu-util outputs an error: @@ -100,20 +100,20 @@ DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffe return true; } switch (request->bRequest()) { - case (uint8_t) DFURequest::Detach: + case (uint8_t)DFURequest::Detach: m_device->detach(); return true; - case (uint8_t) DFURequest::Download: + case (uint8_t)DFURequest::Download: return processDownloadRequest(request->wLength(), transferBufferLength); - case (uint8_t) DFURequest::Upload: + case (uint8_t)DFURequest::Upload: return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::GetStatus: + case (uint8_t)DFURequest::GetStatus: return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::ClearStatus: + case (uint8_t)DFURequest::ClearStatus: return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::GetState: + case (uint8_t)DFURequest::GetState: return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::Abort: + case (uint8_t)DFURequest::Abort: return dfuAbort(transferBufferLength); } return false; @@ -162,7 +162,7 @@ DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; // Copy the requested memory zone into the transfer buffer. uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); - memcpy(transferBuffer, (void *) readAddress, copySize); + memcpy(transferBuffer, (void *)readAddress, copySize); *transferBufferLength = copySize; } m_state = State::dfuUPLOADIDLE; @@ -234,7 +234,7 @@ void DFUInterface::writeOnMemory() { if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { // Write on SRAM // FIXME We should check that we are not overriding the current instructions. - memcpy((void *) m_writeAddress, m_largeBuffer, m_largeBufferLength); + memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); resetFlashParameters(); // We are writing in SRAM, so we can reset flash parameters } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { if (m_dfuLevel == 2) { // We don't accept update From e3740cb70010cdf4aa2b9bb8320d5d9fc274e9ae Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 13:44:03 +0100 Subject: [PATCH 04/21] Indentation Fix --- .../sub_menu/usb_protection_controller.cpp | 6 ++--- ion/src/device/shared/usb/dfu_interface.cpp | 26 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index 5f77445e079..be2ab10d5c8 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -81,11 +81,11 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) GenericSubController::willDisplayCellForIndex(cell, index); if (index == 0) { - MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *) cell; - SwitchView *mySwitch = (SwitchView *) myCell->accessoryView(); + MessageTableCellWithSwitch *myCell = (MessageTableCellWithSwitch *)cell; + SwitchView *mySwitch = (SwitchView *)myCell->accessoryView(); mySwitch->setState(!GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()); } else if (index == 1) { - MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *) cell; + MessageTableCellWithChevronAndMessage *mcell = (MessageTableCellWithChevronAndMessage *)cell; int currentLevel = GlobalPreferences::sharedGlobalPreferences()->dfuLevel(); if (currentLevel == 0) { mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index e32e63bfde7..fc1b41944c5 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -32,15 +32,15 @@ void DFUInterface::StateData::push(Channel *c) const { void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t) DFURequest::Download) { + if (request->bRequest() == (uint8_t)DFURequest::Download) { // Handle a download request if (request->wValue() == 0) { // The request is a special command switch (transferBuffer[0]) { - case (uint8_t) DFUDownloadCommand::SetAddressPointer: + case (uint8_t)DFUDownloadCommand::SetAddressPointer: setAddressPointerCommand(request, transferBuffer, *transferBufferLength); return; - case (uint8_t) DFUDownloadCommand::Erase: + case (uint8_t)DFUDownloadCommand::Erase: eraseCommand(transferBuffer, *transferBufferLength); return; default: @@ -67,7 +67,7 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { - if (request->bRequest() == (uint8_t) DFURequest::GetStatus) { + if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { // Do any needed action after the GetStatus request. if (m_state == State::dfuMANIFEST) { /* If we leave the DFU and reset immediately, dfu-util outputs an error: @@ -100,20 +100,20 @@ DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffe return true; } switch (request->bRequest()) { - case (uint8_t) DFURequest::Detach: + case (uint8_t)DFURequest::Detach: m_device->detach(); return true; - case (uint8_t) DFURequest::Download: + case (uint8_t)DFURequest::Download: return processDownloadRequest(request->wLength(), transferBufferLength); - case (uint8_t) DFURequest::Upload: + case (uint8_t)DFURequest::Upload: return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::GetStatus: + case (uint8_t)DFURequest::GetStatus: return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::ClearStatus: + case (uint8_t)DFURequest::ClearStatus: return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::GetState: + case (uint8_t)DFURequest::GetState: return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); - case (uint8_t) DFURequest::Abort: + case (uint8_t)DFURequest::Abort: return dfuAbort(transferBufferLength); } return false; @@ -162,7 +162,7 @@ DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; // Copy the requested memory zone into the transfer buffer. uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); - memcpy(transferBuffer, (void *) readAddress, copySize); + memcpy(transferBuffer, (void *)readAddress, copySize); *transferBufferLength = copySize; } m_state = State::dfuUPLOADIDLE; @@ -234,7 +234,7 @@ void DFUInterface::writeOnMemory() { if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { // Write on SRAM // FIXME We should check that we are not overriding the current instructions. - memcpy((void *) m_writeAddress, m_largeBuffer, m_largeBufferLength); + memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); resetFlashParameters(); // We are writing in SRAM, so we can reset flash parameters } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { if (m_dfuLevel == 2) { // We don't accept update From d8dbd1f6d62da0d5930c765ebe9532a394efd2a2 Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 19:07:19 +0100 Subject: [PATCH 05/21] =?UTF-8?q?Add=20osType=20in=20platform=5Finfo=20(Up?= =?UTF-8?q?silon=20Magic)=20and=20=E2=9A=A0=E2=9A=A0=20**DFU=20COMMAND=20D?= =?UTF-8?q?ISABLING=20THE=20PROTECTION**=20=E2=9A=A0=E2=9A=A0=20in=20order?= =?UTF-8?q?=20to=20fix=20epsilon=5F=20flash=20(very=20dangerous=20thing=20?= =?UTF-8?q?!!)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/device/dfu.py | 8 ++++++- ion/src/device/n0110/flash.ld | 11 +++++++-- ion/src/device/shared/usb/dfu_interface.cpp | 3 +++ ion/src/device/shared/usb/dfu_interface.h | 2 +- ion/src/shared/platform_info.cpp | 25 ++++++++++++--------- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/build/device/dfu.py b/build/device/dfu.py index bac05e3e5d7..770c32b48a7 100644 --- a/build/device/dfu.py +++ b/build/device/dfu.py @@ -46,7 +46,8 @@ __DFU_GETSTATUS = 3 __DFU_CLRSTATUS = 4 __DFU_GETSTATE = 5 -__DFU_ABORT = 6 +__DFU_ABORT = 6 +__DFU_UNLOCK = 11 # DFU status __DFU_STATE_APP_IDLE = 0x00 @@ -145,6 +146,10 @@ def abort_request(): __dev.ctrl_transfer(0x21, __DFU_ABORT, 0, __DFU_INTERFACE, None, __TIMEOUT) +def unlock_request(): + """Deactivate the protection""" + __dev.ctrl_transfer(0x21, __DFU_UNLOCK, 0, __DFU_INTERFACE, None, __TIMEOUT) + def clr_status(): """Clears any error status (perhaps left over from a previous session).""" __dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE, @@ -587,6 +592,7 @@ def main(): elements = read_dfu_file(args.path) if not elements: return + unlock_request() print("Writing memory...") write_elements(elements, args.mass_erase, progress=cli_progress) diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index 1f2ebb8bbc0..4bdf639f5dd 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -176,8 +176,8 @@ SECTIONS { *(.text._ZN20KDPostProcessContext15setClippingRectE6KDRect) *(.text._ZNK6KDFont17indexForCodePointE9CodePoint) *(.text._ZNK6KDFont26fetchGrayscaleGlyphAtIndexEhPh) - *(.text.LZ4_decompress_safe) - *(.text.LZ4_wildCopy) + *(.text.LZ4_decompress_safe*) + *(.text.LZ4_wildCopy*) *(.text.*DFU*) *(.text.*isEnumerated*) *(.text._ZN3Ion3USB6enableEv) @@ -214,6 +214,7 @@ SECTIONS { *(.text._ZNK10Statistics5Store33sortedElementAtCumulatedFrequencyEidb) *(.text.round) *(.text._ZNK10Statistics5Store8minIndexEPdi*) + *(.text.LZ4_decompress_safe*) /* 'standby' dependencies '*/ *(.text._ZN3Ion6Device5Power20internalFlashStandbyEv) @@ -277,6 +278,12 @@ SECTIONS { *(.rodata._ZN8Sequence23TypeParameterController25willDisplayCellAtLocationEP13HighlightCellii*) *(.rodata._ZN6KDFont16privateSmallFontE) *(.rodata._ZN4I18nL23CountryPreferencesArrayE) + *(.rodata._ZN3Ion6Device3LED6ConfigL7RGBPinsE*) + *(.rodata._ZN4I18nL23CountryPreferencesArrayE*) + *(.rodata._ZN3Ion6Device3USB6ConfigL7VbusPinE*) + *(.rodata.bp*) + *(.rodata.dp_l*) + *(.rodata.dp_h*) *(.rodata.abort_sleeping.str1.1) *(.rodata.abort_core.str1.1) *(.rodata.dfu_bootloader) diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index fc1b41944c5..16711be96c2 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -115,6 +115,9 @@ DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffe return getState(transferBuffer, transferBufferLength, transferBufferMaxLength); case (uint8_t)DFURequest::Abort: return dfuAbort(transferBufferLength); + case (uint8_t)DFURequest::Unlock: + m_dfuUnlocked = true; + return true; } return false; } diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index f9b030c1a4d..798c87dfb7e 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -78,7 +78,7 @@ namespace Ion { private: // DFU Request Codes enum class DFURequest { - Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6 + Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 }; // DFU Download Commmand Codes diff --git a/ion/src/shared/platform_info.cpp b/ion/src/shared/platform_info.cpp index 1950cf09e67..2e53f58d458 100644 --- a/ion/src/shared/platform_info.cpp +++ b/ion/src/shared/platform_info.cpp @@ -25,20 +25,21 @@ constexpr void * storageAddress = &(Ion::staticStorageArea); class PlatformInfo { public: constexpr PlatformInfo() : - m_header(Magic), - m_version{EPSILON_VERSION}, - m_patchLevel{PATCH_LEVEL}, - m_storageAddress(storageAddress), - m_storageSize(Ion::Storage::k_storageSize), - m_footer(Magic), - m_ohm_header(OmegaMagic), - m_UpsilonVersion{OMEGA_VERSION}, + m_header(Magic), + m_version{EPSILON_VERSION}, + m_patchLevel{PATCH_LEVEL}, + m_storageAddress(storageAddress), + m_storageSize(Ion::Storage::k_storageSize), + m_footer(Magic), + m_ohm_header(OmegaMagic), + m_UpsilonVersion{OMEGA_VERSION}, #ifdef OMEGA_USERNAME - m_username{OMEGA_USERNAME}, + m_username{OMEGA_USERNAME}, #else - m_username{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, + m_username{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, #endif - m_ohm_footer(OmegaMagic) { } + m_osType(UpsilonMagic), + m_ohm_footer(OmegaMagic) { } const char * version() const { assert(m_storageAddress != nullptr); assert(m_storageSize != 0); @@ -78,6 +79,7 @@ class PlatformInfo { private: constexpr static uint32_t Magic = 0xDEC00DF0; constexpr static uint32_t OmegaMagic = 0xEFBEADDE; + constexpr static uint32_t UpsilonMagic = 0x55707369; uint32_t m_header; const char m_version[8]; const char m_patchLevel[8]; @@ -87,6 +89,7 @@ class PlatformInfo { uint32_t m_ohm_header; const char m_UpsilonVersion[16]; const volatile char m_username[16]; + uint32_t m_osType; uint32_t m_ohm_footer; }; From 26236370118e849c915ab6524956dce72bad11f1 Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 4 Dec 2021 19:23:39 +0100 Subject: [PATCH 06/21] @Yaya-Cout settings suggestion ;-) --- apps/settings/sub_menu/usb_protection_controller.cpp | 4 ++-- ion/src/device/shared/usb/dfu_interface.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index de1853e9f22..0ca9c65dc06 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -22,7 +22,7 @@ UsbInfoController::UsbInfoController(Responder *parentResponder) : } bool UsbInfoController::handleEvent(Ion::Events::Event event) { - if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 0) { + if ((Ion::Events::OK == event || Ion::Events::EXE == event || Ion::Events::Right == event) && selectedRow() == 0) { if (!GlobalPreferences::sharedGlobalPreferences()->dfuUnlocked()) { if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { Ion::LED::setColor(KDColorPurple); @@ -39,7 +39,7 @@ bool UsbInfoController::handleEvent(Ion::Events::Event event) { return true; } - if ((Ion::Events::OK == event || Ion::Events::EXE == event) && selectedRow() == 1) { + if ((Ion::Events::OK == event || Ion::Events::EXE == event || Ion::Events::Right == event) && selectedRow() == 1) { GenericSubController *subController = &m_usbProtectionLevelController; subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(1)); StackViewController *stack = stackController(); diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 3d3c3f88e02..04275659117 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -378,6 +378,6 @@ void DFUInterface::leaveDFUAndReset(bool do_reset) { m_device->detach(); } -} // namespace USB -} // namespace Device -} // namespace Ion +} +} +} From 762be7bda930d6fb787d02ce86c1bc31c212b2bb Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 16:56:15 +0100 Subject: [PATCH 07/21] Indentation Correction --- .../sub_menu/usb_protection_controller.cpp | 12 +- build/device/dfu.py | 4 +- ion/include/ion/storage.h | 28 +- ion/src/device/shared/usb/dfu_interface.cpp | 48 +- ion/src/device/shared/usb/dfu_interface.h | 442 +++++++++--------- ion/src/shared/platform_info.cpp | 24 +- ion/src/shared/storage.cpp | 74 ++- 7 files changed, 349 insertions(+), 283 deletions(-) diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index 0ca9c65dc06..7ffcbb20c91 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -14,9 +14,10 @@ using namespace Shared; namespace Settings { UsbInfoController::UsbInfoController(Responder *parentResponder) : - GenericSubController(parentResponder), - m_usbProtectionLevelController(this), - m_contentView(&m_selectableTableView) { + GenericSubController(parentResponder), + m_usbProtectionLevelController(this), + m_contentView(&m_selectableTableView) +{ m_switchCell.setMessageFont(KDFont::LargeFont); m_dfuLevelCell.setMessageFont(KDFont::LargeFont); } @@ -89,7 +90,7 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) int currentLevel = GlobalPreferences::sharedGlobalPreferences()->dfuLevel(); if (currentLevel == 0) { mcell->setSubtitle(I18n::Message::USBDefaultLevelDesc); - } else if (currentLevel == 1) { ; + } else if (currentLevel == 1) {; mcell->setSubtitle(I18n::Message::USBLowLevelDesc); } else { assert(currentLevel == 2); @@ -100,8 +101,7 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) void UsbInfoController::didEnterResponderChain(Responder *previousFirstResponder) { m_contentView.reload(); - I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2, - I18n::Message::USBExplanation3}; + I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2,I18n::Message::USBExplanation3}; m_contentView.setMessages(infoMessages, k_numberOfExplanationMessages); } } diff --git a/build/device/dfu.py b/build/device/dfu.py index 770c32b48a7..47358c53d46 100644 --- a/build/device/dfu.py +++ b/build/device/dfu.py @@ -46,8 +46,8 @@ __DFU_GETSTATUS = 3 __DFU_CLRSTATUS = 4 __DFU_GETSTATE = 5 -__DFU_ABORT = 6 -__DFU_UNLOCK = 11 +__DFU_ABORT = 6 +__DFU_UNLOCK = 11 # DFU status __DFU_STATE_APP_IDLE = 0x00 diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 14d70900463..dbf846e2987 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -18,6 +18,7 @@ class Storage { typedef uint16_t record_size_t; constexpr static size_t k_storageSize = 64000; + constexpr static size_t k_fullNameMaxSize = 220 + 5; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); static Storage * sharedStorage(); @@ -27,6 +28,7 @@ class Storage { static constexpr char expExtension[] = "exp"; static constexpr char funcExtension[] = "func"; static constexpr char seqExtension[] = "seq"; + static constexpr char examPrefix[] = "exam"; class Record { /* A Record is identified by the CRC32 on its fullName because: @@ -64,13 +66,13 @@ class Storage { return m_fullNameCRC32 == 0; } const char * fullName() const { - return Storage::sharedStorage()->fullNameOfRecord(*this); + return Storage::sharedStorage()->fullNameOfRecord(*this, false); } ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension) { - return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension); + return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension, false); } ErrorStatus setName(const char * fullName) { - return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName); + return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName, false); } Data value() const { return Storage::sharedStorage()->valueOfRecord(*this); @@ -120,9 +122,16 @@ class Storage { void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); + // Exam Mode + void activateQuarantine(); + void deactivateQuarantine(); + void setFullNameBufferWithPrefix(const char * prefix, const char * name); + static bool fullNameAuthorized(const char * fullname); + // Useful - static bool FullNameCompliant(const char * name); - + static bool FullNameCompliant(const char * name, bool withoutExtension = false); + static bool strstr(const char * first, const char * second); + // User by Python OS module int numberOfRecords(); Record recordAtIndex(int index); @@ -134,9 +143,9 @@ class Storage { Storage(); /* Getters/Setters on recordID */ - const char * fullNameOfRecord(const Record record); - Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName); - Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension); + const char * fullNameOfRecord(const Record record, bool system = false); + Record::ErrorStatus setFullNameOfRecord(const Record record, const char *fullName, bool system = false); + Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system = false); Record::Data valueOfRecord(const Record record); Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data); void destroyRecord(const Record record); @@ -186,6 +195,9 @@ class Storage { StorageDelegate * m_delegate; mutable Record m_lastRecordRetrieved; mutable char * m_lastRecordRetrievedPointer; + bool m_quarantine; + int m_examNumber; + char m_fullNameBuffer[k_fullNameMaxSize]; }; /* Some apps memoize records and need to be notified when a record might have diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 04275659117..87446dcde99 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -30,8 +30,7 @@ void DFUInterface::StateData::push(Channel *c) const { c->push(m_bState); } -void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) { +void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { if (request->bRequest() == (uint8_t)DFURequest::Download) { // Handle a download request if (request->wValue() == 0) { @@ -56,7 +55,6 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran if (request->wLength() > 0) { // The request is a "real" download. Compute the writing address. m_writeAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; - // Store the received data until we copy it on the flash. memcpy(m_largeBuffer, transferBuffer, *transferBufferLength); m_largeBufferLength = *transferBufferLength; @@ -65,18 +63,17 @@ void DFUInterface::wholeDataReceivedCallback(SetupPacket *request, uint8_t *tran } } -void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) { +void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) { if (request->bRequest() == (uint8_t)DFURequest::GetStatus) { // Do any needed action after the GetStatus request. if (m_state == State::dfuMANIFEST) { /* If we leave the DFU and reset immediately, dfu-util outputs an error: - * "File downloaded successfully - * dfu-util: Error during download get_status" - * If we sleep 1us here, there is no error. We put 1ms for security. - * This error might be due to the USB connection being cut too soon after - * the last USB exchange, so the host does not have time to process the - * answer received for the last GetStatus request. */ + * "File downloaded successfully + * dfu-util: Error during download get_status" + * If we sleep 1us here, there is no error. We put 1ms for security. + * This error might be due to the USB connection being cut too soon after + * the last USB exchange, so the host does not have time to process the + * answer received for the last GetStatus request. */ Ion::Timing::msleep(1); // Leave DFU routine: Leave DFU, reset device, jump to application code leaveDFUAndReset(); @@ -94,8 +91,7 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer } bool -DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) { +DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { if (Interface::processSetupInRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength)) { return true; } @@ -141,17 +137,16 @@ bool DFUInterface::processDownloadRequest(uint16_t wLength, uint16_t *transferBu } bool -DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) { +DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) { m_ep0->stallTransaction(); return false; } if (request->wValue() == 0) { /* The host requests to read the commands supported by the bootloader. After - * receiving this command, the device should returns N bytes representing - * the command codes for : - * Get command / Set Address Pointer / Erase / Read Unprotect + * receiving this command, the device should returns N bytes representing + * the command codes for : + * Get command / Set Address Pointer / Erase / Read Unprotect * We no not need it for now. */ return false; } else if (request->wValue() == 1) { @@ -159,7 +154,7 @@ DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer return false; } else { /* We decided to never protect Read operation. Else we would have to check - * here it is not protected before reading. */ + * here it is not protected before reading. */ // Compute the reading address uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; @@ -172,12 +167,13 @@ DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer return true; } -void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, - uint16_t transferBufferLength) { +void DFUInterface::setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength) { assert(transferBufferLength == 5); // Compute the new address but change it after the next getStatus request. - m_potentialNewAddressPointer = - transferBuffer[1] + (transferBuffer[2] << 8) + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); + m_potentialNewAddressPointer = transferBuffer[1] + + (transferBuffer[2] << 8) + + (transferBuffer[3] << 16) + + (transferBuffer[4] << 24); m_state = State::dfuDNLOADSYNC; } @@ -337,8 +333,7 @@ void DFUInterface::writeOnMemory() { m_status = Status::OK; } -bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) { +bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { // Change the status if needed if (m_state == State::dfuMANIFESTSYNC) { m_state = State::dfuMANIFEST; @@ -350,8 +345,7 @@ bool DFUInterface::getStatus(SetupPacket *request, uint8_t *transferBuffer, uint return true; } -bool DFUInterface::clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) { +bool DFUInterface::clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { m_status = Status::OK; m_state = State::dfuIDLE; return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength); diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index 798c87dfb7e..654eb2db6ce 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -12,231 +12,231 @@ #include namespace Ion { - namespace Device { - namespace USB { - - class DFUInterface : public Interface { - - public: - DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), - m_device(device), - m_status(Status::OK), - m_state(State::dfuIDLE), - m_addressPointer(0), - m_potentialNewAddressPointer( - 0), - m_erasePage(-1), - m_largeBuffer{0}, - m_largeBufferLength( - 0), - m_writeAddress(0), - m_eraseAddress(0), - m_bInterfaceAlternateSetting( - bInterfaceAlternateSetting), - m_isErasingAndWriting( - false), - m_isFirstInternalPacket( - true), - m_isInternalLocked( - true), - m_isFirstExternalPacket( - true), - m_lastMemoryType( - -1), - m_lastPageErased(-1), - m_dfuUnlocked(false), - m_dfuLevel(0) { - } - - uint32_t addressPointer() const { return m_addressPointer; } - - void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) override; - - void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, +namespace Device { +namespace USB { + + class DFUInterface : public Interface { + + public: + DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), + m_device(device), + m_status(Status::OK), + m_state(State::dfuIDLE), + m_addressPointer(0), + m_potentialNewAddressPointer( + 0), + m_erasePage(-1), + m_largeBuffer{0}, + m_largeBufferLength( + 0), + m_writeAddress(0), + m_eraseAddress(0), + m_bInterfaceAlternateSetting( + bInterfaceAlternateSetting), + m_isErasingAndWriting( + false), + m_isFirstInternalPacket( + true), + m_isInternalLocked( + true), + m_isFirstExternalPacket( + true), + m_lastMemoryType( + -1), + m_lastPageErased(-1), + m_dfuUnlocked(false), + m_dfuLevel(0) { + } + + uint32_t addressPointer() const { return m_addressPointer; } + + void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; - bool isErasingAndWriting() const { return m_isErasingAndWriting; } - - void unlockDfu() { m_dfuUnlocked = true; }; - - void setLevel(int lvl) { m_dfuLevel = lvl; } - - protected: - void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { - assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); - } - - uint8_t getActiveInterfaceAlternative() override { - return m_bInterfaceAlternateSetting; - } - - bool - processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) override; - - private: - // DFU Request Codes - enum class DFURequest { - Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 - }; - - // DFU Download Commmand Codes - enum class DFUDownloadCommand { - GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 - }; - - enum class Status : uint8_t { - OK = 0x00, - errTARGET = 0x01, - errFILE = 0x02, - errWRITE = 0x03, - errERASE = 0x04, - errCHECK_ERASED = 0x05, - errPROG = 0x06, - errVERIFY = 0x07, - errADDRESS = 0x08, - errNOTDONE = 0x09, - errFIRMWARE = 0x0A, - errVENDOR = 0x0B, - errUSBR = 0x0C, - errPOR = 0x0D, - errUNKNOWN = 0x0E, - errSTALLEDPKT = 0x0F - }; - - enum class State : uint8_t { - appIDLE = 0, - appDETACH = 1, - dfuIDLE = 2, - dfuDNLOADSYNC = 3, - dfuDNBUSY = 4, - dfuDNLOADIDLE = 5, - dfuMANIFESTSYNC = 6, - dfuMANIFEST = 7, - dfuMANIFESTWAITRESET = 8, - dfuUPLOADIDLE = 9, - dfuERROR = 10 - }; - - class StatusData : public Streamable { - public: - StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the - * host has to wait 1ms before sending a getStatus Request. */ - m_bStatus((uint8_t) status), - m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), - uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { - } - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bStatus; // Status resulting from the execution of the most recent request - uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits - uint8_t m_bState; // State of the device immediately following transmission of this response - uint8_t m_iString; - }; - - class StateData : public Streamable { - public: - StateData(State state) : m_bState((uint8_t) state) {} - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bState; // Current state of the device - }; - - /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is - * linked with dfu.ld, so we cannot access the values. */ - constexpr static uint32_t k_sramStartAddress = 0x20000000; - constexpr static uint32_t k_sramEndAddress = 0x20040000; - constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; - - const static int k_internalMagicAddress = 0x1C4; - constexpr static int k_externalMagicAddress = 0x44f; - constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; - // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) - constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; - - // Download and upload - bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); - - bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - - // Address pointer - void - setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); - - void changeAddressPointerIfNeeded(); - - // Access memory - void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); - - void eraseMemoryIfNeeded(); - - void eraseMemoryIfNeededWithoutErasingAtAll(); - - void writeOnMemory(); - - void unlockFlashMemory(); - - void lockFlashMemoryAndPurgeCaches(); - - // Status - bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - - bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - - // State - bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); - - // Abort - bool dfuAbort(uint16_t *transferBufferLength); - - // Leave DFU - void leaveDFUAndReset(bool do_reset = true); - - /* Erase and Write state. After starting the erase of flash memory, the user - * can no longer leave DFU mode by pressing the Back key of the keyboard. This - * way, we prevent the user from interrupting a software download. After every - * software download, the calculator resets, which unlocks the "exit on - * pressing back". */ - void willErase() { m_isErasingAndWriting = true; } - - void resetFlashParameters() { - m_lastMemoryType = -1; - m_lastPageErased = -1; - } - - Device *m_device; - Status m_status; - State m_state; - uint32_t m_addressPointer; - uint32_t m_potentialNewAddressPointer; - int32_t m_erasePage; - uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; - uint16_t m_largeBufferLength; - uint32_t m_writeAddress; - uint32_t m_eraseAddress; - uint8_t m_bInterfaceAlternateSetting; - bool m_isErasingAndWriting; - bool m_isFirstInternalPacket; - bool m_isInternalLocked; - bool m_isFirstExternalPacket; - int m_lastMemoryType; // -1: aucune; 0: internal; 1: external - int m_lastPageErased; // -1 par défaut - bool m_dfuUnlocked; - int m_dfuLevel; - }; + void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) override; + + bool isErasingAndWriting() const { return m_isErasingAndWriting; } + + void unlockDfu() { m_dfuUnlocked = true; }; + + void setLevel(int lvl) { m_dfuLevel = lvl; } + + protected: + void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { + assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); + } + + uint8_t getActiveInterfaceAlternative() override { + return m_bInterfaceAlternateSetting; + } + bool + processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) override; + + private: + // DFU Request Codes + enum class DFURequest { + Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 + }; + + // DFU Download Commmand Codes + enum class DFUDownloadCommand { + GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 + }; + + enum class Status : uint8_t { + OK = 0x00, + errTARGET = 0x01, + errFILE = 0x02, + errWRITE = 0x03, + errERASE = 0x04, + errCHECK_ERASED = 0x05, + errPROG = 0x06, + errVERIFY = 0x07, + errADDRESS = 0x08, + errNOTDONE = 0x09, + errFIRMWARE = 0x0A, + errVENDOR = 0x0B, + errUSBR = 0x0C, + errPOR = 0x0D, + errUNKNOWN = 0x0E, + errSTALLEDPKT = 0x0F + }; + + enum class State : uint8_t { + appIDLE = 0, + appDETACH = 1, + dfuIDLE = 2, + dfuDNLOADSYNC = 3, + dfuDNBUSY = 4, + dfuDNLOADIDLE = 5, + dfuMANIFESTSYNC = 6, + dfuMANIFEST = 7, + dfuMANIFESTWAITRESET = 8, + dfuUPLOADIDLE = 9, + dfuERROR = 10 + }; + + class StatusData : public Streamable { + public: + StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the + * host has to wait 1ms before sending a getStatus Request. */ + m_bStatus((uint8_t) status), + m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), + uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { + } + + protected: + void push(Channel *c) const override; + + private: + uint8_t m_bStatus; // Status resulting from the execution of the most recent request + uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits + uint8_t m_bState; // State of the device immediately following transmission of this response + uint8_t m_iString; + }; + + class StateData : public Streamable { + public: + StateData(State state) : m_bState((uint8_t) state) {} + + protected: + void push(Channel *c) const override; + + private: + uint8_t m_bState; // Current state of the device + }; + + /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is +* linked with dfu.ld, so we cannot access the values. */ + constexpr static uint32_t k_sramStartAddress = 0x20000000; + constexpr static uint32_t k_sramEndAddress = 0x20040000; + constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; + + const static int k_internalMagicAddress = 0x1C4; + constexpr static int k_externalMagicAddress = 0x44f; + constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; + // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) + constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; + + // Download and upload + bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); + + bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + // Address pointer + void + setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); + + void changeAddressPointerIfNeeded(); + + // Access memory + void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); + + void eraseMemoryIfNeeded(); + + void eraseMemoryIfNeededWithoutErasingAtAll(); + + void writeOnMemory(); + + void unlockFlashMemory(); + + void lockFlashMemoryAndPurgeCaches(); + + // Status + bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); + + // State + bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); + + // Abort + bool dfuAbort(uint16_t *transferBufferLength); + + // Leave DFU + void leaveDFUAndReset(bool do_reset = true); + + /* Erase and Write state. After starting the erase of flash memory, the user +* can no longer leave DFU mode by pressing the Back key of the keyboard. This +* way, we prevent the user from interrupting a software download. After every +* software download, the calculator resets, which unlocks the "exit on +* pressing back". */ + void willErase() { m_isErasingAndWriting = true; } + + void resetFlashParameters() { + m_lastMemoryType = -1; + m_lastPageErased = -1; } - } + + Device *m_device; + Status m_status; + State m_state; + uint32_t m_addressPointer; + uint32_t m_potentialNewAddressPointer; + int32_t m_erasePage; + uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; + uint16_t m_largeBufferLength; + uint32_t m_writeAddress; + uint32_t m_eraseAddress; + uint8_t m_bInterfaceAlternateSetting; + bool m_isErasingAndWriting; + bool m_isFirstInternalPacket; + bool m_isInternalLocked; + bool m_isFirstExternalPacket; + int m_lastMemoryType; // -1: aucune; 0: internal; 1: external + int m_lastPageErased; // -1 par défaut + bool m_dfuUnlocked; + int m_dfuLevel; + }; + +} +} } #endif diff --git a/ion/src/shared/platform_info.cpp b/ion/src/shared/platform_info.cpp index 2e53f58d458..2167f528f48 100644 --- a/ion/src/shared/platform_info.cpp +++ b/ion/src/shared/platform_info.cpp @@ -25,21 +25,21 @@ constexpr void * storageAddress = &(Ion::staticStorageArea); class PlatformInfo { public: constexpr PlatformInfo() : - m_header(Magic), - m_version{EPSILON_VERSION}, - m_patchLevel{PATCH_LEVEL}, - m_storageAddress(storageAddress), - m_storageSize(Ion::Storage::k_storageSize), - m_footer(Magic), - m_ohm_header(OmegaMagic), - m_UpsilonVersion{OMEGA_VERSION}, + m_header(Magic), + m_version{EPSILON_VERSION}, + m_patchLevel{PATCH_LEVEL}, + m_storageAddress(storageAddress), + m_storageSize(Ion::Storage::k_storageSize), + m_footer(Magic), + m_ohm_header(OmegaMagic), + m_UpsilonVersion{OMEGA_VERSION}, #ifdef OMEGA_USERNAME - m_username{OMEGA_USERNAME}, + m_username{OMEGA_USERNAME}, #else - m_username{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, + m_username{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, #endif - m_osType(UpsilonMagic), - m_ohm_footer(OmegaMagic) { } + m_osType(UpsilonMagic), + m_ohm_footer(OmegaMagic) { } const char * version() const { assert(m_storageAddress != nullptr); assert(m_storageSize != 0); diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 3419e3d8c53..c4b9f45c0da 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -2,6 +2,8 @@ #include #include #include +#include "ion/storage.h" + #if ION_STORAGE_LOG #include #endif @@ -26,6 +28,7 @@ constexpr char Storage::expExtension[]; constexpr char Storage::funcExtension[]; constexpr char Storage::seqExtension[]; constexpr char Storage::eqExtension[]; +constexpr char Storage::examPrefix[]; Storage * Storage::sharedStorage() { static Storage * storage = new (staticStorageArea) Storage(); @@ -146,11 +149,15 @@ Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const { } Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) { + setFullNameBufferWithPrefix(examPrefix, fullName); + if (m_quarantine) { + fullName = m_fullNameBuffer; + } size_t recordSize = sizeOfRecordWithFullName(fullName, size); if (recordSize >= k_maxRecordSize || recordSize > availableSize()) { return notifyFullnessToDelegate(); } - if (isFullNameTaken(fullName)) { + if (isFullNameTaken(fullName) || (!m_quarantine && !fullNameAuthorized(fullName))) { return Record::ErrorStatus::NameTaken; } // Find the end of data @@ -328,7 +335,10 @@ Storage::Storage() : m_magicFooter(Magic), m_delegate(nullptr), m_lastRecordRetrieved(nullptr), - m_lastRecordRetrievedPointer(nullptr) + m_lastRecordRetrievedPointer(nullptr), + m_quarantine(false), + m_examNumber(0), + m_fullNameBuffer() { assert(m_magicHeader == Magic); assert(m_magicFooter == Magic); @@ -336,15 +346,16 @@ Storage::Storage() : overrideSizeAtPosition(m_buffer, 0); } -const char * Storage::fullNameOfRecord(const Record record) { +const char * Storage::fullNameOfRecord(const Record record, bool system) { char * p = pointerOfRecord(record); if (p != nullptr) { - return fullNameOfRecordStarting(p); + const char * name = fullNameOfRecordStarting(p); + return m_quarantine && !system && Storage::strstr(name, examPrefix) ? name + sizeof(examPrefix) : name; } return nullptr; } -Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char * fullName) { +Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char *fullName, bool system) { if (!FullNameCompliant(fullName)) { return Record::ErrorStatus::NonCompliantName; } @@ -370,7 +381,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c return Record::ErrorStatus::RecordDoesNotExist; } -Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) { +Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system) { if (isBaseNameWithExtensionTaken(baseName, extension, &record)) { return Record::ErrorStatus::NameTaken; } @@ -527,7 +538,7 @@ bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) { return false; } -bool Storage::FullNameCompliant(const char * fullName) { +bool Storage::FullNameCompliant(const char * fullName, bool withoutExtension) { // We check that there is one dot and one dot only. const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar); if (*dotChar == 0) { @@ -619,6 +630,55 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension return Record(); } +void Storage::activateQuarantine() { + m_quarantine = true; + // TODO maybe do: check if there is enough space for the exam +} + +bool Storage::strstr(const char * first, const char * second) { + size_t fSize = strlen(first); + size_t sSize = strlen(second); + if (fSize == sSize) { + return strcmp(first, second) == 0; + } + if (sSize > fSize) { + const char * buf = first; + first = second; + second = buf; + fSize = strlen(first); + sSize = strlen(second); + } + bool result = false; + int index = 0; + for (int i = 0; (size_t)i < fSize; i++) { + if (first[i] == second[index]) { + index++; + result = (size_t)index >= sSize; + } else if (fSize - 1 - (size_t)i < sSize - 1 - (size_t)index) { + break; + } else { + index = 0; + } + if (result) break; + } + return result; +} + +void Storage::deactivateQuarantine() { + +} + +void Storage::setFullNameBufferWithPrefix(const char *prefix, const char *name) { + assert(sizeof(prefix) + sizeof(name) <= k_fullNameMaxSize); + memset(m_fullNameBuffer, 0, k_fullNameMaxSize); + strlcpy(m_fullNameBuffer, prefix, k_fullNameMaxSize); + strlcpy(m_fullNameBuffer, name, k_fullNameMaxSize); +} + +bool Storage::fullNameAuthorized(const char *fullname) { + return !Storage::strstr(fullname, examPrefix); +} + Storage::RecordIterator & Storage::RecordIterator::operator++() { assert(m_recordStart); record_size_t size = StorageHelper::unalignedShort(m_recordStart); From 8c3398d42847353b9f989a72e5d0f5f52f43760e Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 17:13:29 +0100 Subject: [PATCH 08/21] CLion mistake fix --- ion/include/ion/storage.h | 28 +++++---------- ion/src/shared/storage.cpp | 74 ++++---------------------------------- 2 files changed, 15 insertions(+), 87 deletions(-) diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index dbf846e2987..14d70900463 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -18,7 +18,6 @@ class Storage { typedef uint16_t record_size_t; constexpr static size_t k_storageSize = 64000; - constexpr static size_t k_fullNameMaxSize = 220 + 5; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); static Storage * sharedStorage(); @@ -28,7 +27,6 @@ class Storage { static constexpr char expExtension[] = "exp"; static constexpr char funcExtension[] = "func"; static constexpr char seqExtension[] = "seq"; - static constexpr char examPrefix[] = "exam"; class Record { /* A Record is identified by the CRC32 on its fullName because: @@ -66,13 +64,13 @@ class Storage { return m_fullNameCRC32 == 0; } const char * fullName() const { - return Storage::sharedStorage()->fullNameOfRecord(*this, false); + return Storage::sharedStorage()->fullNameOfRecord(*this); } ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension) { - return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension, false); + return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension); } ErrorStatus setName(const char * fullName) { - return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName, false); + return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName); } Data value() const { return Storage::sharedStorage()->valueOfRecord(*this); @@ -122,16 +120,9 @@ class Storage { void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); - // Exam Mode - void activateQuarantine(); - void deactivateQuarantine(); - void setFullNameBufferWithPrefix(const char * prefix, const char * name); - static bool fullNameAuthorized(const char * fullname); - // Useful - static bool FullNameCompliant(const char * name, bool withoutExtension = false); - static bool strstr(const char * first, const char * second); - + static bool FullNameCompliant(const char * name); + // User by Python OS module int numberOfRecords(); Record recordAtIndex(int index); @@ -143,9 +134,9 @@ class Storage { Storage(); /* Getters/Setters on recordID */ - const char * fullNameOfRecord(const Record record, bool system = false); - Record::ErrorStatus setFullNameOfRecord(const Record record, const char *fullName, bool system = false); - Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system = false); + const char * fullNameOfRecord(const Record record); + Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName); + Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension); Record::Data valueOfRecord(const Record record); Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data); void destroyRecord(const Record record); @@ -195,9 +186,6 @@ class Storage { StorageDelegate * m_delegate; mutable Record m_lastRecordRetrieved; mutable char * m_lastRecordRetrievedPointer; - bool m_quarantine; - int m_examNumber; - char m_fullNameBuffer[k_fullNameMaxSize]; }; /* Some apps memoize records and need to be notified when a record might have diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index c4b9f45c0da..3419e3d8c53 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -2,8 +2,6 @@ #include #include #include -#include "ion/storage.h" - #if ION_STORAGE_LOG #include #endif @@ -28,7 +26,6 @@ constexpr char Storage::expExtension[]; constexpr char Storage::funcExtension[]; constexpr char Storage::seqExtension[]; constexpr char Storage::eqExtension[]; -constexpr char Storage::examPrefix[]; Storage * Storage::sharedStorage() { static Storage * storage = new (staticStorageArea) Storage(); @@ -149,15 +146,11 @@ Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const { } Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) { - setFullNameBufferWithPrefix(examPrefix, fullName); - if (m_quarantine) { - fullName = m_fullNameBuffer; - } size_t recordSize = sizeOfRecordWithFullName(fullName, size); if (recordSize >= k_maxRecordSize || recordSize > availableSize()) { return notifyFullnessToDelegate(); } - if (isFullNameTaken(fullName) || (!m_quarantine && !fullNameAuthorized(fullName))) { + if (isFullNameTaken(fullName)) { return Record::ErrorStatus::NameTaken; } // Find the end of data @@ -335,10 +328,7 @@ Storage::Storage() : m_magicFooter(Magic), m_delegate(nullptr), m_lastRecordRetrieved(nullptr), - m_lastRecordRetrievedPointer(nullptr), - m_quarantine(false), - m_examNumber(0), - m_fullNameBuffer() + m_lastRecordRetrievedPointer(nullptr) { assert(m_magicHeader == Magic); assert(m_magicFooter == Magic); @@ -346,16 +336,15 @@ Storage::Storage() : overrideSizeAtPosition(m_buffer, 0); } -const char * Storage::fullNameOfRecord(const Record record, bool system) { +const char * Storage::fullNameOfRecord(const Record record) { char * p = pointerOfRecord(record); if (p != nullptr) { - const char * name = fullNameOfRecordStarting(p); - return m_quarantine && !system && Storage::strstr(name, examPrefix) ? name + sizeof(examPrefix) : name; + return fullNameOfRecordStarting(p); } return nullptr; } -Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char *fullName, bool system) { +Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char * fullName) { if (!FullNameCompliant(fullName)) { return Record::ErrorStatus::NonCompliantName; } @@ -381,7 +370,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c return Record::ErrorStatus::RecordDoesNotExist; } -Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system) { +Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) { if (isBaseNameWithExtensionTaken(baseName, extension, &record)) { return Record::ErrorStatus::NameTaken; } @@ -538,7 +527,7 @@ bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) { return false; } -bool Storage::FullNameCompliant(const char * fullName, bool withoutExtension) { +bool Storage::FullNameCompliant(const char * fullName) { // We check that there is one dot and one dot only. const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar); if (*dotChar == 0) { @@ -630,55 +619,6 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension return Record(); } -void Storage::activateQuarantine() { - m_quarantine = true; - // TODO maybe do: check if there is enough space for the exam -} - -bool Storage::strstr(const char * first, const char * second) { - size_t fSize = strlen(first); - size_t sSize = strlen(second); - if (fSize == sSize) { - return strcmp(first, second) == 0; - } - if (sSize > fSize) { - const char * buf = first; - first = second; - second = buf; - fSize = strlen(first); - sSize = strlen(second); - } - bool result = false; - int index = 0; - for (int i = 0; (size_t)i < fSize; i++) { - if (first[i] == second[index]) { - index++; - result = (size_t)index >= sSize; - } else if (fSize - 1 - (size_t)i < sSize - 1 - (size_t)index) { - break; - } else { - index = 0; - } - if (result) break; - } - return result; -} - -void Storage::deactivateQuarantine() { - -} - -void Storage::setFullNameBufferWithPrefix(const char *prefix, const char *name) { - assert(sizeof(prefix) + sizeof(name) <= k_fullNameMaxSize); - memset(m_fullNameBuffer, 0, k_fullNameMaxSize); - strlcpy(m_fullNameBuffer, prefix, k_fullNameMaxSize); - strlcpy(m_fullNameBuffer, name, k_fullNameMaxSize); -} - -bool Storage::fullNameAuthorized(const char *fullname) { - return !Storage::strstr(fullname, examPrefix); -} - Storage::RecordIterator & Storage::RecordIterator::operator++() { assert(m_recordStart); record_size_t size = StorageHelper::unalignedShort(m_recordStart); From 65419f5d530cf96f9d0c9654b78ebe8b4bb3bf1b Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 17:16:40 +0100 Subject: [PATCH 09/21] dfu_interface.h indentation correction --- ion/src/device/shared/usb/dfu_interface.h | 372 +++++++++++----------- 1 file changed, 186 insertions(+), 186 deletions(-) diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index 654eb2db6ce..fa8a073359d 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -15,225 +15,225 @@ namespace Ion { namespace Device { namespace USB { - class DFUInterface : public Interface { +class DFUInterface : public Interface { + +public: + DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), + m_device(device), + m_status(Status::OK), + m_state(State::dfuIDLE), + m_addressPointer(0), + m_potentialNewAddressPointer( + 0), + m_erasePage(-1), + m_largeBuffer{0}, + m_largeBufferLength( + 0), + m_writeAddress(0), + m_eraseAddress(0), + m_bInterfaceAlternateSetting( + bInterfaceAlternateSetting), + m_isErasingAndWriting( + false), + m_isFirstInternalPacket( + true), + m_isInternalLocked( + true), + m_isFirstExternalPacket( + true), + m_lastMemoryType( + -1), + m_lastPageErased(-1), + m_dfuUnlocked(false), + m_dfuLevel(0) { + } + + uint32_t addressPointer() const { return m_addressPointer; } + + void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) override; + + void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, + uint16_t *transferBufferLength) override; + + bool isErasingAndWriting() const { return m_isErasingAndWriting; } + + void unlockDfu() { m_dfuUnlocked = true; }; + + void setLevel(int lvl) { m_dfuLevel = lvl; } + +protected: + void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { + assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); + } + + uint8_t getActiveInterfaceAlternative() override { + return m_bInterfaceAlternateSetting; + } + + bool + processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength) override; + +private: + // DFU Request Codes + enum class DFURequest { + Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 + }; - public: - DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), - m_device(device), - m_status(Status::OK), - m_state(State::dfuIDLE), - m_addressPointer(0), - m_potentialNewAddressPointer( - 0), - m_erasePage(-1), - m_largeBuffer{0}, - m_largeBufferLength( - 0), - m_writeAddress(0), - m_eraseAddress(0), - m_bInterfaceAlternateSetting( - bInterfaceAlternateSetting), - m_isErasingAndWriting( - false), - m_isFirstInternalPacket( - true), - m_isInternalLocked( - true), - m_isFirstExternalPacket( - true), - m_lastMemoryType( - -1), - m_lastPageErased(-1), - m_dfuUnlocked(false), - m_dfuLevel(0) { - } + // DFU Download Commmand Codes + enum class DFUDownloadCommand { + GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 + }; - uint32_t addressPointer() const { return m_addressPointer; } + enum class Status : uint8_t { + OK = 0x00, + errTARGET = 0x01, + errFILE = 0x02, + errWRITE = 0x03, + errERASE = 0x04, + errCHECK_ERASED = 0x05, + errPROG = 0x06, + errVERIFY = 0x07, + errADDRESS = 0x08, + errNOTDONE = 0x09, + errFIRMWARE = 0x0A, + errVENDOR = 0x0B, + errUSBR = 0x0C, + errPOR = 0x0D, + errUNKNOWN = 0x0E, + errSTALLEDPKT = 0x0F + }; - void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) override; + enum class State : uint8_t { + appIDLE = 0, + appDETACH = 1, + dfuIDLE = 2, + dfuDNLOADSYNC = 3, + dfuDNBUSY = 4, + dfuDNLOADIDLE = 5, + dfuMANIFESTSYNC = 6, + dfuMANIFEST = 7, + dfuMANIFESTWAITRESET = 8, + dfuUPLOADIDLE = 9, + dfuERROR = 10 + }; - void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) override; + class StatusData : public Streamable { + public: + StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the + * host has to wait 1ms before sending a getStatus Request. */ + m_bStatus((uint8_t) status), + m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), + uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { + } - bool isErasingAndWriting() const { return m_isErasingAndWriting; } + protected: + void push(Channel *c) const override; - void unlockDfu() { m_dfuUnlocked = true; }; + private: + uint8_t m_bStatus; // Status resulting from the execution of the most recent request + uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits + uint8_t m_bState; // State of the device immediately following transmission of this response + uint8_t m_iString; + }; - void setLevel(int lvl) { m_dfuLevel = lvl; } + class StateData : public Streamable { + public: + StateData(State state) : m_bState((uint8_t) state) {} protected: - void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { - assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); - } - - uint8_t getActiveInterfaceAlternative() override { - return m_bInterfaceAlternateSetting; - } - - bool - processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) override; + void push(Channel *c) const override; private: - // DFU Request Codes - enum class DFURequest { - Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 - }; - - // DFU Download Commmand Codes - enum class DFUDownloadCommand { - GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 - }; - - enum class Status : uint8_t { - OK = 0x00, - errTARGET = 0x01, - errFILE = 0x02, - errWRITE = 0x03, - errERASE = 0x04, - errCHECK_ERASED = 0x05, - errPROG = 0x06, - errVERIFY = 0x07, - errADDRESS = 0x08, - errNOTDONE = 0x09, - errFIRMWARE = 0x0A, - errVENDOR = 0x0B, - errUSBR = 0x0C, - errPOR = 0x0D, - errUNKNOWN = 0x0E, - errSTALLEDPKT = 0x0F - }; - - enum class State : uint8_t { - appIDLE = 0, - appDETACH = 1, - dfuIDLE = 2, - dfuDNLOADSYNC = 3, - dfuDNBUSY = 4, - dfuDNLOADIDLE = 5, - dfuMANIFESTSYNC = 6, - dfuMANIFEST = 7, - dfuMANIFESTWAITRESET = 8, - dfuUPLOADIDLE = 9, - dfuERROR = 10 - }; - - class StatusData : public Streamable { - public: - StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the - * host has to wait 1ms before sending a getStatus Request. */ - m_bStatus((uint8_t) status), - m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), - uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { - } - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bStatus; // Status resulting from the execution of the most recent request - uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits - uint8_t m_bState; // State of the device immediately following transmission of this response - uint8_t m_iString; - }; - - class StateData : public Streamable { - public: - StateData(State state) : m_bState((uint8_t) state) {} - - protected: - void push(Channel *c) const override; - - private: - uint8_t m_bState; // Current state of the device - }; - - /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is + uint8_t m_bState; // Current state of the device + }; + + /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is * linked with dfu.ld, so we cannot access the values. */ - constexpr static uint32_t k_sramStartAddress = 0x20000000; - constexpr static uint32_t k_sramEndAddress = 0x20040000; - constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; + constexpr static uint32_t k_sramStartAddress = 0x20000000; + constexpr static uint32_t k_sramEndAddress = 0x20040000; + constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; - const static int k_internalMagicAddress = 0x1C4; - constexpr static int k_externalMagicAddress = 0x44f; - constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; - // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) - constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; + const static int k_internalMagicAddress = 0x1C4; + constexpr static int k_externalMagicAddress = 0x44f; + constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; + // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) + constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; - // Download and upload - bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); + // Download and upload + bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); - bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); + bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); - // Address pointer - void - setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); + // Address pointer + void + setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); - void changeAddressPointerIfNeeded(); + void changeAddressPointerIfNeeded(); - // Access memory - void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); + // Access memory + void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); - void eraseMemoryIfNeeded(); + void eraseMemoryIfNeeded(); - void eraseMemoryIfNeededWithoutErasingAtAll(); + void eraseMemoryIfNeededWithoutErasingAtAll(); - void writeOnMemory(); + void writeOnMemory(); - void unlockFlashMemory(); + void unlockFlashMemory(); - void lockFlashMemoryAndPurgeCaches(); + void lockFlashMemoryAndPurgeCaches(); - // Status - bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); + // Status + bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); - bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); + bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, + uint16_t transferBufferMaxLength); - // State - bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); + // State + bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); - // Abort - bool dfuAbort(uint16_t *transferBufferLength); + // Abort + bool dfuAbort(uint16_t *transferBufferLength); - // Leave DFU - void leaveDFUAndReset(bool do_reset = true); + // Leave DFU + void leaveDFUAndReset(bool do_reset = true); - /* Erase and Write state. After starting the erase of flash memory, the user + /* Erase and Write state. After starting the erase of flash memory, the user * can no longer leave DFU mode by pressing the Back key of the keyboard. This * way, we prevent the user from interrupting a software download. After every * software download, the calculator resets, which unlocks the "exit on * pressing back". */ - void willErase() { m_isErasingAndWriting = true; } - - void resetFlashParameters() { - m_lastMemoryType = -1; - m_lastPageErased = -1; - } - - Device *m_device; - Status m_status; - State m_state; - uint32_t m_addressPointer; - uint32_t m_potentialNewAddressPointer; - int32_t m_erasePage; - uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; - uint16_t m_largeBufferLength; - uint32_t m_writeAddress; - uint32_t m_eraseAddress; - uint8_t m_bInterfaceAlternateSetting; - bool m_isErasingAndWriting; - bool m_isFirstInternalPacket; - bool m_isInternalLocked; - bool m_isFirstExternalPacket; - int m_lastMemoryType; // -1: aucune; 0: internal; 1: external - int m_lastPageErased; // -1 par défaut - bool m_dfuUnlocked; - int m_dfuLevel; - }; + void willErase() { m_isErasingAndWriting = true; } + + void resetFlashParameters() { + m_lastMemoryType = -1; + m_lastPageErased = -1; + } + + Device *m_device; + Status m_status; + State m_state; + uint32_t m_addressPointer; + uint32_t m_potentialNewAddressPointer; + int32_t m_erasePage; + uint8_t m_largeBuffer[Endpoint0::MaxTransferSize]; + uint16_t m_largeBufferLength; + uint32_t m_writeAddress; + uint32_t m_eraseAddress; + uint8_t m_bInterfaceAlternateSetting; + bool m_isErasingAndWriting; + bool m_isFirstInternalPacket; + bool m_isInternalLocked; + bool m_isFirstExternalPacket; + int m_lastMemoryType; // -1: aucune; 0: internal; 1: external + int m_lastPageErased; // -1 par défaut + bool m_dfuUnlocked; + int m_dfuLevel; +}; } } From c425a8cdbff8b352acacd275c273dbd997128731 Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 17:27:36 +0100 Subject: [PATCH 10/21] dfu_interface.h indentation correction --- ion/src/device/shared/usb/dfu_interface.h | 172 +++++++++------------- 1 file changed, 73 insertions(+), 99 deletions(-) diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index fa8a073359d..faa63a80e3f 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -18,105 +18,98 @@ namespace USB { class DFUInterface : public Interface { public: - DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : Interface(ep0), - m_device(device), - m_status(Status::OK), - m_state(State::dfuIDLE), - m_addressPointer(0), - m_potentialNewAddressPointer( - 0), - m_erasePage(-1), - m_largeBuffer{0}, - m_largeBufferLength( - 0), - m_writeAddress(0), - m_eraseAddress(0), - m_bInterfaceAlternateSetting( - bInterfaceAlternateSetting), - m_isErasingAndWriting( - false), - m_isFirstInternalPacket( - true), - m_isInternalLocked( - true), - m_isFirstExternalPacket( - true), - m_lastMemoryType( - -1), - m_lastPageErased(-1), - m_dfuUnlocked(false), - m_dfuLevel(0) { + DFUInterface(Device *device, Endpoint0 *ep0, uint8_t bInterfaceAlternateSetting) : + Interface(ep0), + m_device(device), + m_status(Status::OK), + m_state(State::dfuIDLE), + m_addressPointer(0), + m_potentialNewAddressPointer(0), + m_erasePage(-1), + m_largeBuffer{0}, + m_largeBufferLength(0), + m_writeAddress(0), + m_eraseAddress(0), + m_bInterfaceAlternateSetting(bInterfaceAlternateSetting), + m_isErasingAndWriting(false), + m_isFirstInternalPacket(true), + m_isInternalLocked(true), + m_isFirstExternalPacket(true), + m_lastMemoryType(-1), + m_lastPageErased(-1), + m_dfuUnlocked(false), + m_dfuLevel(0) { } uint32_t addressPointer() const { return m_addressPointer; } - void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) override; - - void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, - uint16_t *transferBufferLength) override; - + void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; + void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; bool isErasingAndWriting() const { return m_isErasingAndWriting; } - void unlockDfu() { m_dfuUnlocked = true; }; - void setLevel(int lvl) { m_dfuLevel = lvl; } protected: void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting); } - uint8_t getActiveInterfaceAlternative() override { return m_bInterfaceAlternateSetting; } - - bool - processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength) override; + bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override; private: // DFU Request Codes enum class DFURequest { - Detach = 0, Download = 1, Upload = 2, GetStatus = 3, ClearStatus = 4, GetState = 5, Abort = 6, Unlock = 11 + Detach = 0, + Download = 1, + Upload = 2, + GetStatus = 3, + ClearStatus = 4, + GetState = 5, + Abort = 6, + Unlock = 11 }; // DFU Download Commmand Codes enum class DFUDownloadCommand { - GetCommand = 0x00, SetAddressPointer = 0x21, Erase = 0x41, ReadUnprotect = 0x92 + GetCommand = 0x00, + SetAddressPointer = 0x21, + Erase = 0x41, + ReadUnprotect = 0x92 }; enum class Status : uint8_t { OK = 0x00, - errTARGET = 0x01, - errFILE = 0x02, - errWRITE = 0x03, - errERASE = 0x04, + errTARGET = 0x01, + errFILE = 0x02, + errWRITE = 0x03, + errERASE = 0x04, errCHECK_ERASED = 0x05, - errPROG = 0x06, - errVERIFY = 0x07, - errADDRESS = 0x08, - errNOTDONE = 0x09, - errFIRMWARE = 0x0A, - errVENDOR = 0x0B, - errUSBR = 0x0C, - errPOR = 0x0D, - errUNKNOWN = 0x0E, - errSTALLEDPKT = 0x0F + errPROG = 0x06, + errVERIFY = 0x07, + errADDRESS = 0x08, + errNOTDONE = 0x09, + errFIRMWARE = 0x0A, + errVENDOR = 0x0B, + errUSBR = 0x0C, + errPOR = 0x0D, + errUNKNOWN = 0x0E, + errSTALLEDPKT = 0x0F }; enum class State : uint8_t { - appIDLE = 0, - appDETACH = 1, - dfuIDLE = 2, - dfuDNLOADSYNC = 3, - dfuDNBUSY = 4, - dfuDNLOADIDLE = 5, - dfuMANIFESTSYNC = 6, - dfuMANIFEST = 7, + appIDLE = 0, + appDETACH = 1, + dfuIDLE = 2, + dfuDNLOADSYNC = 3, + dfuDNBUSY = 4, + dfuDNLOADIDLE = 5, + dfuMANIFESTSYNC = 6, + dfuMANIFEST = 7, dfuMANIFESTWAITRESET = 8, - dfuUPLOADIDLE = 9, - dfuERROR = 10 + dfuUPLOADIDLE = 9, + dfuERROR = 10 }; class StatusData : public Streamable { @@ -124,8 +117,9 @@ class DFUInterface : public Interface { StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the * host has to wait 1ms before sending a getStatus Request. */ m_bStatus((uint8_t) status), - m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF), - uint8_t(pollTimeout & 0xFF)}, m_bState((uint8_t) state), m_iString(0) { + m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF),uint8_t(pollTimeout & 0xFF)}, + m_bState((uint8_t) state), + m_iString(0) { } protected: @@ -138,13 +132,12 @@ class DFUInterface : public Interface { uint8_t m_iString; }; - class StateData : public Streamable { + class StateData : public Streamable + { public: StateData(State state) : m_bState((uint8_t) state) {} - protected: void push(Channel *c) const override; - private: uint8_t m_bState; // Current state of the device }; @@ -163,52 +156,33 @@ class DFUInterface : public Interface { // Download and upload bool processDownloadRequest(uint16_t wLength, uint16_t *transferBufferLength); - - bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - + bool processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); // Address pointer - void - setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); - + void setAddressPointerCommand(SetupPacket *request, uint8_t *transferBuffer, uint16_t transferBufferLength); void changeAddressPointerIfNeeded(); - // Access memory void eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength); - void eraseMemoryIfNeeded(); - void eraseMemoryIfNeededWithoutErasingAtAll(); - void writeOnMemory(); - void unlockFlashMemory(); - void lockFlashMemoryAndPurgeCaches(); - // Status - bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - - bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, - uint16_t transferBufferMaxLength); - + bool getStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); + bool clearStatus(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength); // State bool getState(uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t maxSize); - // Abort bool dfuAbort(uint16_t *transferBufferLength); - // Leave DFU void leaveDFUAndReset(bool do_reset = true); /* Erase and Write state. After starting the erase of flash memory, the user -* can no longer leave DFU mode by pressing the Back key of the keyboard. This -* way, we prevent the user from interrupting a software download. After every -* software download, the calculator resets, which unlocks the "exit on -* pressing back". */ + * can no longer leave DFU mode by pressing the Back key of the keyboard. This + * way, we prevent the user from interrupting a software download. After every + * software download, the calculator resets, which unlocks the "exit on + * pressing back". */ void willErase() { m_isErasingAndWriting = true; } - void resetFlashParameters() { m_lastMemoryType = -1; m_lastPageErased = -1; From 3b5333c0ea8eac64758e9c173173de60172d1d7e Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 17:30:56 +0100 Subject: [PATCH 11/21] dfu_interface.h indentation correction --- ion/src/device/shared/usb/dfu_interface.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index faa63a80e3f..959d15da2a7 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -47,7 +47,7 @@ class DFUInterface : public Interface { void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override; bool isErasingAndWriting() const { return m_isErasingAndWriting; } void unlockDfu() { m_dfuUnlocked = true; }; - void setLevel(int lvl) { m_dfuLevel = lvl; } + void setLevel(uint8_t lvl) { m_dfuLevel = lvl; } protected: void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override { @@ -144,13 +144,13 @@ class DFUInterface : public Interface { /* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is * linked with dfu.ld, so we cannot access the values. */ - constexpr static uint32_t k_sramStartAddress = 0x20000000; - constexpr static uint32_t k_sramEndAddress = 0x20040000; + constexpr static uint32_t k_sramStartAddress = 0x20000000; + constexpr static uint32_t k_sramEndAddress = 0x20040000; constexpr static uint32_t k_ExternalBorderAddress = 0x90200000; - const static int k_internalMagicAddress = 0x1C4; - constexpr static int k_externalMagicAddress = 0x44f; - constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; + const static int k_internalMagicAddress = 0x1C4; + constexpr static int k_externalMagicAddress = 0x44f; + constexpr static uint8_t k_omegaMagic[4] = {0xF0, 0x0D, 0xC0, 0xDE}; // TODO maybe do: add seperated upsilon magic (k_upsilonMagic) constexpr static uint8_t k_externalUpsilonMagic[4] = {0x32, 0x30, 0x30, 0x36}; @@ -206,7 +206,7 @@ class DFUInterface : public Interface { int m_lastMemoryType; // -1: aucune; 0: internal; 1: external int m_lastPageErased; // -1 par défaut bool m_dfuUnlocked; - int m_dfuLevel; + uint8_t m_dfuLevel; }; } From 726fd3ed70891acfe6b1d464bef302c16ef1cdf4 Mon Sep 17 00:00:00 2001 From: devdl11 Date: Tue, 7 Dec 2021 20:16:44 +0100 Subject: [PATCH 12/21] Foundation --- ion/include/ion/storage.h | 28 ++++++++++----- ion/src/shared/storage.cpp | 74 ++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 14d70900463..dbf846e2987 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -18,6 +18,7 @@ class Storage { typedef uint16_t record_size_t; constexpr static size_t k_storageSize = 64000; + constexpr static size_t k_fullNameMaxSize = 220 + 5; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); static Storage * sharedStorage(); @@ -27,6 +28,7 @@ class Storage { static constexpr char expExtension[] = "exp"; static constexpr char funcExtension[] = "func"; static constexpr char seqExtension[] = "seq"; + static constexpr char examPrefix[] = "exam"; class Record { /* A Record is identified by the CRC32 on its fullName because: @@ -64,13 +66,13 @@ class Storage { return m_fullNameCRC32 == 0; } const char * fullName() const { - return Storage::sharedStorage()->fullNameOfRecord(*this); + return Storage::sharedStorage()->fullNameOfRecord(*this, false); } ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension) { - return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension); + return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension, false); } ErrorStatus setName(const char * fullName) { - return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName); + return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName, false); } Data value() const { return Storage::sharedStorage()->valueOfRecord(*this); @@ -120,9 +122,16 @@ class Storage { void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); + // Exam Mode + void activateQuarantine(); + void deactivateQuarantine(); + void setFullNameBufferWithPrefix(const char * prefix, const char * name); + static bool fullNameAuthorized(const char * fullname); + // Useful - static bool FullNameCompliant(const char * name); - + static bool FullNameCompliant(const char * name, bool withoutExtension = false); + static bool strstr(const char * first, const char * second); + // User by Python OS module int numberOfRecords(); Record recordAtIndex(int index); @@ -134,9 +143,9 @@ class Storage { Storage(); /* Getters/Setters on recordID */ - const char * fullNameOfRecord(const Record record); - Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName); - Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension); + const char * fullNameOfRecord(const Record record, bool system = false); + Record::ErrorStatus setFullNameOfRecord(const Record record, const char *fullName, bool system = false); + Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system = false); Record::Data valueOfRecord(const Record record); Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data); void destroyRecord(const Record record); @@ -186,6 +195,9 @@ class Storage { StorageDelegate * m_delegate; mutable Record m_lastRecordRetrieved; mutable char * m_lastRecordRetrievedPointer; + bool m_quarantine; + int m_examNumber; + char m_fullNameBuffer[k_fullNameMaxSize]; }; /* Some apps memoize records and need to be notified when a record might have diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 3419e3d8c53..c4b9f45c0da 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -2,6 +2,8 @@ #include #include #include +#include "ion/storage.h" + #if ION_STORAGE_LOG #include #endif @@ -26,6 +28,7 @@ constexpr char Storage::expExtension[]; constexpr char Storage::funcExtension[]; constexpr char Storage::seqExtension[]; constexpr char Storage::eqExtension[]; +constexpr char Storage::examPrefix[]; Storage * Storage::sharedStorage() { static Storage * storage = new (staticStorageArea) Storage(); @@ -146,11 +149,15 @@ Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const { } Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) { + setFullNameBufferWithPrefix(examPrefix, fullName); + if (m_quarantine) { + fullName = m_fullNameBuffer; + } size_t recordSize = sizeOfRecordWithFullName(fullName, size); if (recordSize >= k_maxRecordSize || recordSize > availableSize()) { return notifyFullnessToDelegate(); } - if (isFullNameTaken(fullName)) { + if (isFullNameTaken(fullName) || (!m_quarantine && !fullNameAuthorized(fullName))) { return Record::ErrorStatus::NameTaken; } // Find the end of data @@ -328,7 +335,10 @@ Storage::Storage() : m_magicFooter(Magic), m_delegate(nullptr), m_lastRecordRetrieved(nullptr), - m_lastRecordRetrievedPointer(nullptr) + m_lastRecordRetrievedPointer(nullptr), + m_quarantine(false), + m_examNumber(0), + m_fullNameBuffer() { assert(m_magicHeader == Magic); assert(m_magicFooter == Magic); @@ -336,15 +346,16 @@ Storage::Storage() : overrideSizeAtPosition(m_buffer, 0); } -const char * Storage::fullNameOfRecord(const Record record) { +const char * Storage::fullNameOfRecord(const Record record, bool system) { char * p = pointerOfRecord(record); if (p != nullptr) { - return fullNameOfRecordStarting(p); + const char * name = fullNameOfRecordStarting(p); + return m_quarantine && !system && Storage::strstr(name, examPrefix) ? name + sizeof(examPrefix) : name; } return nullptr; } -Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char * fullName) { +Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char *fullName, bool system) { if (!FullNameCompliant(fullName)) { return Record::ErrorStatus::NonCompliantName; } @@ -370,7 +381,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c return Record::ErrorStatus::RecordDoesNotExist; } -Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) { +Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system) { if (isBaseNameWithExtensionTaken(baseName, extension, &record)) { return Record::ErrorStatus::NameTaken; } @@ -527,7 +538,7 @@ bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) { return false; } -bool Storage::FullNameCompliant(const char * fullName) { +bool Storage::FullNameCompliant(const char * fullName, bool withoutExtension) { // We check that there is one dot and one dot only. const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar); if (*dotChar == 0) { @@ -619,6 +630,55 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension return Record(); } +void Storage::activateQuarantine() { + m_quarantine = true; + // TODO maybe do: check if there is enough space for the exam +} + +bool Storage::strstr(const char * first, const char * second) { + size_t fSize = strlen(first); + size_t sSize = strlen(second); + if (fSize == sSize) { + return strcmp(first, second) == 0; + } + if (sSize > fSize) { + const char * buf = first; + first = second; + second = buf; + fSize = strlen(first); + sSize = strlen(second); + } + bool result = false; + int index = 0; + for (int i = 0; (size_t)i < fSize; i++) { + if (first[i] == second[index]) { + index++; + result = (size_t)index >= sSize; + } else if (fSize - 1 - (size_t)i < sSize - 1 - (size_t)index) { + break; + } else { + index = 0; + } + if (result) break; + } + return result; +} + +void Storage::deactivateQuarantine() { + +} + +void Storage::setFullNameBufferWithPrefix(const char *prefix, const char *name) { + assert(sizeof(prefix) + sizeof(name) <= k_fullNameMaxSize); + memset(m_fullNameBuffer, 0, k_fullNameMaxSize); + strlcpy(m_fullNameBuffer, prefix, k_fullNameMaxSize); + strlcpy(m_fullNameBuffer, name, k_fullNameMaxSize); +} + +bool Storage::fullNameAuthorized(const char *fullname) { + return !Storage::strstr(fullname, examPrefix); +} + Storage::RecordIterator & Storage::RecordIterator::operator++() { assert(m_recordStart); record_size_t size = StorageHelper::unalignedShort(m_recordStart); From e8d75aa2b338d6cf75662c882c8a8be9a32064c7 Mon Sep 17 00:00:00 2001 From: dl11 Date: Sun, 19 Dec 2021 20:49:37 +0100 Subject: [PATCH 13/21] Avancement ExamMode --- apps/apps_container.cpp | 6 +- apps/exam_pop_up_controller.cpp | 1 + .../sub_menu/exam_mode_controller.cpp | 5 + ion/include/ion/storage.h | 4 +- ion/src/device/n0110/flash.ld | 2 +- ion/src/device/shared/boot/rt0.cpp | 2 +- ion/src/shared/storage.cpp | 245 +++++++++++++++++- 7 files changed, 249 insertions(+), 16 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 1eee9ce075e..b300e731511 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -411,7 +411,11 @@ void AppsContainer::redrawWindow(bool force) { void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { assert(examMode != GlobalPreferences::ExamMode::Off && examMode != GlobalPreferences::ExamMode::Unknown); - reset(); + if (examMode == GlobalPreferences::ExamMode::Standard) { + Ion::Storage::sharedStorage()->activateQuarantine(); + } else { + reset(); + } Ion::LED::setColor(KDColorRed); /* The Dutch exam mode LED is supposed to be orange but we can only make * blink "pure" colors: with RGB leds on or off (as the PWM is used for diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 75a998565ff..f72084b585e 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -17,6 +17,7 @@ ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode); AppsContainer * container = AppsContainer::sharedAppsContainer(); if (mode == GlobalPreferences::ExamMode::Off) { + Ion::Storage::sharedStorage()->deactivateQuarantine(); Ion::LED::setColor(KDColorBlack); Ion::LED::updateColorWithPlugAndCharge(); } else { diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 33a853eaab1..5a09ccad6f6 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace Poincare; using namespace Shared; @@ -112,7 +113,11 @@ GlobalPreferences::ExamMode ExamModeController::examMode() { GlobalPreferences::ExamMode mode = GlobalPreferences::sharedGlobalPreferences()->tempExamMode(); if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode + #ifdef ION_SIMULATOR_FILES + mode = GlobalPreferences::ExamMode::Off; + #else mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); + #endif } return mode; } diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index dbf846e2987..5415781df53 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -4,6 +4,7 @@ #include #include +#define ION_STORAGE_LOG 1 namespace Ion { /* Storage : | Magic | Record1 | Record2 | ... | Magic | @@ -90,6 +91,7 @@ class Storage { #if ION_STORAGE_LOG void log(); + void logMessage(const char * message); #endif size_t availableSize(); @@ -133,7 +135,7 @@ class Storage { static bool strstr(const char * first, const char * second); // User by Python OS module - int numberOfRecords(); + int numberOfRecords(bool system = false); Record recordAtIndex(int index); private: diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index 4bdf639f5dd..b8bee00a3d8 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -21,7 +21,7 @@ MEMORY { */ } -STACK_SIZE = 32K; +STACK_SIZE = 31K; FIRST_EXTERNAL_FLASH_SECTOR_SIZE = 4K; SECTIONS { diff --git a/ion/src/device/shared/boot/rt0.cpp b/ion/src/device/shared/boot/rt0.cpp index a2949b3c0d4..b091563c092 100644 --- a/ion/src/device/shared/boot/rt0.cpp +++ b/ion/src/device/shared/boot/rt0.cpp @@ -245,7 +245,7 @@ void __attribute__((noinline)) start() { Ion::Device::Board::initFPU(); /* Call static C++ object constructors - * The C++ compiler creates an initialization function for each static object. + * The C++ compiler creates an initialization function for each static object. * The linker then stores the address of each of those functions consecutively * between _init_array_start and _init_array_end. So to initialize all C++ * static objects we just have to iterate between theses two addresses and diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index c4b9f45c0da..922ad7ae9ce 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -97,6 +97,10 @@ void Storage::log() { Record(currentName).log(); } } + +void Storage::logMessage(const char * message) { + std::cout << message << std::endl; +} #endif size_t Storage::availableSize() { @@ -150,6 +154,9 @@ Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const { Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) { setFullNameBufferWithPrefix(examPrefix, fullName); + if (!fullNameAuthorized(fullName)) { + return Record::ErrorStatus::NameTaken; + } if (m_quarantine) { fullName = m_fullNameBuffer; } @@ -175,15 +182,32 @@ Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * full notifyChangeToDelegate(r); m_lastRecordRetrieved = r; m_lastRecordRetrievedPointer = newRecordAddress; + #if ION_STORAGE_LOG + logMessage("createRecordWithFullName start"); + log(); + r.log(); + logMessage("createRecordWithFullName end"); + #endif return Record::ErrorStatus::None; } Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) { + setFullNameBufferWithPrefix(examPrefix, baseName); + if (!fullNameAuthorized(baseName)) { + return Record::ErrorStatus::NameTaken; + } + #if ION_STORAGE_LOG + logMessage("createRecordWithExtension start"); + logMessage(baseName); + #endif + if (m_quarantine) { + baseName = m_fullNameBuffer; + } size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size); if (recordSize >= k_maxRecordSize || recordSize > availableSize()) { return notifyFullnessToDelegate(); } - if (isBaseNameWithExtensionTaken(baseName, extension)) { + if (isBaseNameWithExtensionTaken(baseName, extension) || (!m_quarantine && !fullNameAuthorized(baseName))) { return Record::ErrorStatus::NameTaken; } // Find the end of data @@ -201,27 +225,58 @@ Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * bas notifyChangeToDelegate(r); m_lastRecordRetrieved = r; m_lastRecordRetrievedPointer = newRecordAddress; + #if ION_STORAGE_LOG + log(); + r.log(); + logMessage("createRecordWithExtension end"); + #endif return Record::ErrorStatus::None; } int Storage::numberOfRecordsWithExtension(const char * extension) { int count = 0; size_t extensionLength = strlen(extension); + #if ION_STORAGE_LOG + logMessage("numberOfRecordsWithExtension start"); + #endif for (char * p : *this) { const char * name = fullNameOfRecordStarting(p); - if (FullNameHasExtension(name, extension, extensionLength)) { + #if ION_STORAGE_LOG + logMessage(name); + #endif + if (FullNameHasExtension(name, extension, extensionLength) && !(m_quarantine && !strstr(name, examPrefix))) { count++; + #if ION_STORAGE_LOG + logMessage("Counted !"); + #endif } } + #if ION_STORAGE_LOG + logMessage("numberOfRecordsWithExtension end"); + #endif return count; } -int Storage::numberOfRecords() { +int Storage::numberOfRecords(bool system) { int count = 0; + #if ION_STORAGE_LOG + logMessage("numberOfRecords start"); + #endif for (char * p : *this) { const char * name = fullNameOfRecordStarting(p); - count++; + #if ION_STORAGE_LOG + logMessage(name); + #endif + if(!(m_quarantine && !strstr(name, examPrefix)) || system){ + count++; + #if ION_STORAGE_LOG + logMessage("counted !"); + #endif + } } + #if ION_STORAGE_LOG + logMessage("numberOfRecords end"); + #endif return count; } @@ -229,15 +284,33 @@ Storage::Record Storage::recordAtIndex(int index) { int currentIndex = -1; const char * name = nullptr; char * recordAddress = nullptr; + #if ION_STORAGE_LOG + logMessage("recordAtIndex start"); + #endif for (char * p : *this) { const char * currentName = fullNameOfRecordStarting(p); + #if ION_STORAGE_LOG + logMessage(currentName); + #endif + if (m_quarantine && !strstr(currentName, examPrefix)) { + continue; + } currentIndex++; + #if ION_STORAGE_LOG + logMessage("currentIndex ++"); + #endif if (currentIndex == index) { recordAddress = p; name = currentName; + #if ION_STORAGE_LOG + logMessage("found !"); + #endif break; } } + #if ION_STORAGE_LOG + logMessage("recordAtIndex end"); + #endif if (name == nullptr) { return Record(); } @@ -252,17 +325,35 @@ Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int const char * name = nullptr; size_t extensionLength = strlen(extension); char * recordAddress = nullptr; + #if ION_STORAGE_LOG + logMessage("recordWithExtensionAtIndex start"); + #endif for (char * p : *this) { const char * currentName = fullNameOfRecordStarting(p); + #if ION_STORAGE_LOG + logMessage(currentName); + #endif + if (m_quarantine && !strstr(currentName, examPrefix)) { + continue; + } if (FullNameHasExtension(currentName, extension, extensionLength)) { + #if ION_STORAGE_LOG + logMessage("currentIndex ++"); + #endif currentIndex++; } if (currentIndex == index) { + #if ION_STORAGE_LOG + logMessage("found !"); + #endif recordAddress = p; name = currentName; break; } } + #if ION_STORAGE_LOG + logMessage("recordWithExtensionAtIndex end"); + #endif if (name == nullptr) { return Record(); } @@ -276,11 +367,36 @@ Storage::Record Storage::recordNamed(const char * fullName) { if (fullName == nullptr) { return Record(); } + #if ION_STORAGE_LOG + logMessage("recordNamed start"); + logMessage(fullName); + #endif Record r = Record(fullName); char * p = pointerOfRecord(r); - if (p != nullptr) { + if (p != nullptr && (!m_quarantine || strstr(fullName, examPrefix))) { + #if ION_STORAGE_LOG + logMessage("First return"); + logMessage("recordNamed end"); + #endif return r; + }else if (p == nullptr && m_quarantine) { + setFullNameBufferWithPrefix(examPrefix, fullName); + r = Record(m_fullNameBuffer); + p = pointerOfRecord(r); + #if ION_STORAGE_LOG + logMessage("Second if"); + #endif + if (p != nullptr) { + #if ION_STORAGE_LOG + logMessage("Second return"); + logMessage("recordNamed end"); + #endif + return r; + } } + #if ION_STORAGE_LOG + logMessage("recordNamed end"); + #endif return Record(); } @@ -350,18 +466,38 @@ const char * Storage::fullNameOfRecord(const Record record, bool system) { char * p = pointerOfRecord(record); if (p != nullptr) { const char * name = fullNameOfRecordStarting(p); - return m_quarantine && !system && Storage::strstr(name, examPrefix) ? name + sizeof(examPrefix) : name; + return m_quarantine && !system && Storage::strstr(name, examPrefix) ? name + strlen(examPrefix): name; } return nullptr; } Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char *fullName, bool system) { - if (!FullNameCompliant(fullName)) { + #if ION_STORAGE_LOG + logMessage("setFullNameOfRecord start"); + logMessage(fullName); + #endif + if (m_quarantine && !system) { + setFullNameBufferWithPrefix(examPrefix, fullName); + fullName = m_fullNameBuffer; + } + if (!FullNameCompliant(fullName) || (!m_quarantine && !fullNameAuthorized(fullName))) { + #if ION_STORAGE_LOG + logMessage("NonCompliant return"); + logMessage("setFullNameOfRecord end"); + #endif return Record::ErrorStatus::NonCompliantName; } if (isFullNameTaken(fullName, &record)) { + #if ION_STORAGE_LOG + logMessage("Taken return"); + logMessage("setFullNameOfRecord end"); + #endif return Record::ErrorStatus::NameTaken; } + #if ION_STORAGE_LOG + logMessage("After conditions"); + logMessage(fullName); + #endif size_t nameSize = strlen(fullName) + 1; char * p = pointerOfRecord(record); if (p != nullptr) { @@ -369,6 +505,10 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c record_size_t previousRecordSize = sizeOfRecordStarting(p); size_t newRecordSize = previousRecordSize-previousNameSize+nameSize; if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) { + #if ION_STORAGE_LOG + logMessage("notify return"); + logMessage("setFullNameOfRecord end"); + #endif return notifyFullnessToDelegate(); } overrideSizeAtPosition(p, newRecordSize); @@ -376,15 +516,39 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c notifyChangeToDelegate(record); m_lastRecordRetrieved = record; m_lastRecordRetrievedPointer = p; + #if ION_STORAGE_LOG + logMessage("return None"); + logMessage("setFullNameOfRecord end"); + #endif return Record::ErrorStatus::None; } + #if ION_STORAGE_LOG + logMessage("return NotExist"); + logMessage("setFullNameOfRecord end"); + #endif return Record::ErrorStatus::RecordDoesNotExist; } -Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Record record, const char *baseName, const char *extension, bool system) { - if (isBaseNameWithExtensionTaken(baseName, extension, &record)) { +Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char *baseName, const char *extension, bool system) { + #if ION_STORAGE_LOG + logMessage("setBaseNameWithExtensionOfRecord start"); + logMessage(baseName); + #endif + setFullNameBufferWithPrefix(examPrefix, baseName); + if (m_quarantine && !system) { + baseName = m_fullNameBuffer; + } + if (isBaseNameWithExtensionTaken(baseName, extension, &record) || (!m_quarantine && !fullNameAuthorized(baseName))) { + #if ION_STORAGE_LOG + logMessage("Taken return"); + logMessage("setBaseNameWithExtensionOfRecord end"); + #endif return Record::ErrorStatus::NameTaken; } + #if ION_STORAGE_LOG + logMessage("After conditions"); + logMessage(baseName); + #endif size_t nameSize = sizeOfBaseNameAndExtension(baseName, extension); char * p = pointerOfRecord(record); if (p != nullptr) { @@ -392,6 +556,10 @@ Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Rec record_size_t previousRecordSize = sizeOfRecordStarting(p); size_t newRecordSize = previousRecordSize-previousNameSize+nameSize; if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) { + #if ION_STORAGE_LOG + logMessage("notify return"); + logMessage("setBaseNameWithExtensionOfRecord end"); + #endif return notifyFullnessToDelegate(); } overrideSizeAtPosition(p, newRecordSize); @@ -402,8 +570,16 @@ Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(const Rec notifyChangeToDelegate(record); m_lastRecordRetrieved = record; m_lastRecordRetrievedPointer = p; + #if ION_STORAGE_LOG + logMessage("return None"); + logMessage("setBaseNameWithExtensionOfRecord end"); + #endif return Record::ErrorStatus::None; } + #if ION_STORAGE_LOG + logMessage("return NotExist"); + logMessage("setBaseNameWithExtensionOfRecord end"); + #endif return Record::ErrorStatus::RecordDoesNotExist; } @@ -595,6 +771,10 @@ bool Storage::slideBuffer(char * position, int delta) { } Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult, int baseNameLength) { + setFullNameBufferWithPrefix(examPrefix, baseName); + if (m_quarantine && !strstr(baseName, examPrefix)) { + baseName = m_fullNameBuffer; + } size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength; { const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer); @@ -665,14 +845,55 @@ bool Storage::strstr(const char * first, const char * second) { } void Storage::deactivateQuarantine() { - + assert(m_quarantine); + int count = numberOfRecords(true); + const char * buffer[count]; + int index = 0; + #ifdef ION_STORAGE_LOG + logMessage("deactivateQuarantine start"); + #endif + + for (char * p : *this) { + const char * name = fullNameOfRecordStarting(p); + if (strstr(name, examPrefix)) { + buffer[index] = name; + index ++; + } + } + for (int i = 0; i <= index; i++) { + Record r = Record(buffer[i]); + const char * originalName = fullNameOfRecord(r, false); + #ifdef ION_STORAGE_LOG + logMessage(originalName); + #endif + int current = 0; + char converted = current; + setFullNameBufferWithPrefix(originalName, &converted); + while (isFullNameTaken(m_fullNameBuffer)) { + current ++; + converted = current; + setFullNameBufferWithPrefix(originalName, &converted); + } + setFullNameOfRecord(r, m_fullNameBuffer, true); + } + #ifdef ION_STORAGE_LOG + logMessage("deactivateQuarantine end"); + #endif + m_quarantine = false; } void Storage::setFullNameBufferWithPrefix(const char *prefix, const char *name) { assert(sizeof(prefix) + sizeof(name) <= k_fullNameMaxSize); memset(m_fullNameBuffer, 0, k_fullNameMaxSize); - strlcpy(m_fullNameBuffer, prefix, k_fullNameMaxSize); - strlcpy(m_fullNameBuffer, name, k_fullNameMaxSize); + strlcat(m_fullNameBuffer, prefix, k_fullNameMaxSize); + strlcat(m_fullNameBuffer, name, k_fullNameMaxSize); + #ifdef ION_STORAGE_LOG + logMessage("setFullNameBufferWithPrefix start"); + logMessage(name); + logMessage(prefix); + logMessage(m_fullNameBuffer); + logMessage("setFullNameBufferWithPrefix end"); + #endif } bool Storage::fullNameAuthorized(const char *fullname) { From fb428cac8dc4d212ead8ec308ca1bd11796ab3c5 Mon Sep 17 00:00:00 2001 From: dl11 Date: Wed, 22 Dec 2021 15:47:44 +0100 Subject: [PATCH 14/21] =?UTF-8?q?Mode=20Examen=20Termin=C3=A9,=20Patch=20l?= =?UTF-8?q?d=20n=C3=A9cessaire=20pour=20device?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/apps_container.cpp | 17 +- apps/apps_container.h | 2 +- .../sub_menu/exam_mode_controller.cpp | 2 +- ion/include/ion/storage.h | 13 +- ion/src/device/n0110/flash.ld | 2 +- ion/src/shared/storage.cpp | 149 ++++++++++++++---- 6 files changed, 143 insertions(+), 42 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index b300e731511..c9a38c89502 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -92,9 +92,14 @@ App::Snapshot * AppsContainer::usbConnectedAppSnapshot() { return &m_usbConnectedSnapshot; } -void AppsContainer::reset() { - // Empty storage (delete functions, variables, python scripts) - Ion::Storage::sharedStorage()->destroyAllRecords(); +void AppsContainer::reset(bool storage) { + if (storage) { + // Empty storage (delete functions, variables, python scripts) + Ion::Storage::sharedStorage()->destroyAllRecords(); + } else { + // Activate Quarantine + Ion::Storage::sharedStorage()->activateQuarantine(); + } // Empty clipboard Clipboard::sharedClipboard()->reset(); for (int i = 0; i < numberOfApps(); i++) { @@ -411,11 +416,7 @@ void AppsContainer::redrawWindow(bool force) { void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { assert(examMode != GlobalPreferences::ExamMode::Off && examMode != GlobalPreferences::ExamMode::Unknown); - if (examMode == GlobalPreferences::ExamMode::Standard) { - Ion::Storage::sharedStorage()->activateQuarantine(); - } else { - reset(); - } + reset(examMode != GlobalPreferences::ExamMode::Standard); Ion::LED::setColor(KDColorRed); /* The Dutch exam mode LED is supposed to be orange but we can only make * blink "pure" colors: with RGB leds on or off (as the PWM is used for diff --git a/apps/apps_container.h b/apps/apps_container.h index f52d50b6c50..9f020777dc9 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -32,7 +32,7 @@ class AppsContainer : public Container, ExamPopUpControllerDelegate, Ion::Storag App::Snapshot * hardwareTestAppSnapshot(); App::Snapshot * onBoardingAppSnapshot(); App::Snapshot * usbConnectedAppSnapshot(); - void reset(); + void reset(bool storage = true); Poincare::Context * globalContext(); MathToolbox * mathToolbox(); MathVariableBoxController * variableBoxController(); diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 5a09ccad6f6..ccd86c47bf6 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -113,7 +113,7 @@ GlobalPreferences::ExamMode ExamModeController::examMode() { GlobalPreferences::ExamMode mode = GlobalPreferences::sharedGlobalPreferences()->tempExamMode(); if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode - #ifdef ION_SIMULATOR_FILES + #if 0 mode = GlobalPreferences::ExamMode::Off; #else mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 5415781df53..ac7892a65b3 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -3,8 +3,6 @@ #include #include - -#define ION_STORAGE_LOG 1 namespace Ion { /* Storage : | Magic | Record1 | Record2 | ... | Magic | @@ -20,6 +18,7 @@ class Storage { constexpr static size_t k_storageSize = 64000; constexpr static size_t k_fullNameMaxSize = 220 + 5; + constexpr static size_t k_extensionMaxSize = 10; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); static Storage * sharedStorage(); @@ -31,6 +30,13 @@ class Storage { static constexpr char seqExtension[] = "seq"; static constexpr char examPrefix[] = "exam"; + static constexpr uint8_t eqMaxRecords = 6; + static constexpr uint8_t expMaxRecords = -1; + static constexpr uint8_t funcMaxRecords = -1; + static constexpr uint8_t seqMaxRecords = 3; + + static constexpr uint8_t noMaxRecords = -1; + class Record { /* A Record is identified by the CRC32 on its fullName because: * - A record is identified by its fullName, which is unique @@ -104,7 +110,7 @@ class Storage { void notifyChangeToDelegate(const Record r = Record()) const; Record::ErrorStatus notifyFullnessToDelegate() const; - int numberOfRecordsWithExtension(const char * extension); + int numberOfRecordsWithExtension(const char * extension, bool system = false); static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength); // Record creation @@ -129,6 +135,7 @@ class Storage { void deactivateQuarantine(); void setFullNameBufferWithPrefix(const char * prefix, const char * name); static bool fullNameAuthorized(const char * fullname); + void deleteRecordByExtensionIfNeeded(const char * extension); // Useful static bool FullNameCompliant(const char * name, bool withoutExtension = false); diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index b8bee00a3d8..4bdf639f5dd 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -21,7 +21,7 @@ MEMORY { */ } -STACK_SIZE = 31K; +STACK_SIZE = 32K; FIRST_EXTERNAL_FLASH_SECTOR_SIZE = 4K; SECTIONS { diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 922ad7ae9ce..5be01b3e33b 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -3,6 +3,10 @@ #include #include #include "ion/storage.h" +#include +#include +#include +#include #if ION_STORAGE_LOG #include @@ -30,6 +34,13 @@ constexpr char Storage::seqExtension[]; constexpr char Storage::eqExtension[]; constexpr char Storage::examPrefix[]; +constexpr uint8_t Storage::expMaxRecords; +constexpr uint8_t Storage::funcMaxRecords; +constexpr uint8_t Storage::seqMaxRecords; +constexpr uint8_t Storage::eqMaxRecords; + +constexpr uint8_t Storage::noMaxRecords; + Storage * Storage::sharedStorage() { static Storage * storage = new (staticStorageArea) Storage(); return storage; @@ -210,6 +221,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * bas if (isBaseNameWithExtensionTaken(baseName, extension) || (!m_quarantine && !fullNameAuthorized(baseName))) { return Record::ErrorStatus::NameTaken; } + deleteRecordByExtensionIfNeeded(extension); // Find the end of data char * newRecordAddress = endBuffer(); char * newRecord = newRecordAddress; @@ -233,7 +245,7 @@ Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * bas return Record::ErrorStatus::None; } -int Storage::numberOfRecordsWithExtension(const char * extension) { +int Storage::numberOfRecordsWithExtension(const char * extension, bool system) { int count = 0; size_t extensionLength = strlen(extension); #if ION_STORAGE_LOG @@ -244,7 +256,7 @@ int Storage::numberOfRecordsWithExtension(const char * extension) { #if ION_STORAGE_LOG logMessage(name); #endif - if (FullNameHasExtension(name, extension, extensionLength) && !(m_quarantine && !strstr(name, examPrefix))) { + if (FullNameHasExtension(name, extension, extensionLength) && !(m_quarantine && !strstr(name, examPrefix) && !system)) { count++; #if ION_STORAGE_LOG logMessage("Counted !"); @@ -477,6 +489,13 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c logMessage(fullName); #endif if (m_quarantine && !system) { + if (!fullNameAuthorized(fullName)) { + #if ION_STORAGE_LOG + logMessage("NonCompliant return"); + logMessage("setFullNameOfRecord end"); + #endif + return Record::ErrorStatus::NonCompliantName; + } setFullNameBufferWithPrefix(examPrefix, fullName); fullName = m_fullNameBuffer; } @@ -534,8 +553,15 @@ Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record re logMessage("setBaseNameWithExtensionOfRecord start"); logMessage(baseName); #endif - setFullNameBufferWithPrefix(examPrefix, baseName); if (m_quarantine && !system) { + if (!fullNameAuthorized(baseName)) { + #if ION_STORAGE_LOG + logMessage("Taken return"); + logMessage("setBaseNameWithExtensionOfRecord end"); + #endif + return Record::ErrorStatus::NameTaken; + } + setFullNameBufferWithPrefix(examPrefix, baseName); baseName = m_fullNameBuffer; } if (isBaseNameWithExtensionTaken(baseName, extension, &record) || (!m_quarantine && !fullNameAuthorized(baseName))) { @@ -811,6 +837,9 @@ Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtension } void Storage::activateQuarantine() { + if (m_quarantine) { + deactivateQuarantine(); + } m_quarantine = true; // TODO maybe do: check if there is enough space for the exam } @@ -845,37 +874,74 @@ bool Storage::strstr(const char * first, const char * second) { } void Storage::deactivateQuarantine() { - assert(m_quarantine); - int count = numberOfRecords(true); - const char * buffer[count]; - int index = 0; + if (!m_quarantine) { + return; + } + int count = numberOfRecords(); #ifdef ION_STORAGE_LOG logMessage("deactivateQuarantine start"); #endif - for (char * p : *this) { - const char * name = fullNameOfRecordStarting(p); - if (strstr(name, examPrefix)) { - buffer[index] = name; - index ++; - } - } - for (int i = 0; i <= index; i++) { - Record r = Record(buffer[i]); - const char * originalName = fullNameOfRecord(r, false); - #ifdef ION_STORAGE_LOG - logMessage(originalName); - #endif - int current = 0; - char converted = current; - setFullNameBufferWithPrefix(originalName, &converted); - while (isFullNameTaken(m_fullNameBuffer)) { - current ++; - converted = current; - setFullNameBufferWithPrefix(originalName, &converted); + for (int i = 0; i < count; i++) { + for (char * p : *this) { + const char * name = fullNameOfRecordStarting(p); + if (strstr(name, examPrefix)) { + #ifdef ION_STORAGE_LOG + logMessage(name); + #endif + Record r = Record(name); + const char * originalNameP = fullNameOfRecord(r, false); + if (!isFullNameTaken(originalNameP)) { + setFullNameOfRecord(r, originalNameP, true); + break; + } + const char * dotChar = UTF8Helper::CodePointSearch(originalNameP, k_dotChar); + char originalName[k_fullNameMaxSize]; + char extension[k_extensionMaxSize]; + size_t originalSize; + if (*dotChar != 0) { + originalSize = strlen(originalNameP) - strlen(originalNameP + strlen(originalNameP) - strlen(dotChar)); + strlcpy(originalName, originalNameP, originalSize + 1); + originalName[originalSize + 1] = '\0'; + strlcpy(extension, originalNameP + originalSize, k_extensionMaxSize); + } else { + originalSize = strlen(originalNameP); + strlcpy(originalName, originalNameP, originalSize); + } + #ifdef ION_STORAGE_LOG + logMessage(originalNameP); + logMessage(originalName); + logMessage(extension); + #endif + int current = 0; + char converted[3]; + Poincare::Integer(current).serialize(&converted[0], 3); + // sprintf(converted, "%d", current); + setFullNameBufferWithPrefix(originalName, converted); + if (*dotChar != 0) { + strlcat(m_fullNameBuffer, extension, k_fullNameMaxSize); + #ifdef ION_STORAGE_LOG + logMessage("--"); + logMessage(m_fullNameBuffer); + logMessage("--"); + #endif + } + while (isFullNameTaken(m_fullNameBuffer)) { + current ++; + converted[3]; + Poincare::Integer(current).serialize(&converted[0], 3); + // sprintf(converted, "%d", current); + setFullNameBufferWithPrefix(originalName, converted); + if (*dotChar != 0) { + strlcat(m_fullNameBuffer, extension, k_fullNameMaxSize); + } + } + setFullNameOfRecord(r, m_fullNameBuffer, true); + break; + } } - setFullNameOfRecord(r, m_fullNameBuffer, true); } + #ifdef ION_STORAGE_LOG logMessage("deactivateQuarantine end"); #endif @@ -896,6 +962,33 @@ void Storage::setFullNameBufferWithPrefix(const char *prefix, const char *name) #endif } +void Storage::deleteRecordByExtensionIfNeeded(const char * extension) { + const uint8_t * limit; + if (strcmp(extension, eqExtension) == 0) { + limit = &eqMaxRecords; + } else if (strcmp(extension, seqExtension) == 0) { + limit = &seqMaxRecords; + } else { + limit = &noMaxRecords; + } + if (*limit == -1 || !m_quarantine) { + return; + } + int currentNumber = numberOfRecordsWithExtension(extension, true); + if (currentNumber + 1 <= *limit) { + return; + } + for (char * p : *this) { + const char * name = fullNameOfRecordStarting(p); + if (FullNameHasExtension(name, extension, strlen(extension)) && !strstr(name, examPrefix)) { + Record r = Record(name); + destroyRecord(r); + break; + } + } + +} + bool Storage::fullNameAuthorized(const char *fullname) { return !Storage::strstr(fullname, examPrefix); } From 0293797dedc7a012c188790e45338b00f28327ae Mon Sep 17 00:00:00 2001 From: dl11 Date: Sun, 26 Dec 2021 19:10:17 +0100 Subject: [PATCH 15/21] Exam Improvement And DFU fix --- apps/settings/base.fr.i18n | 2 +- apps/shared/function.h | 1 + apps/shared/sequence.cpp | 10 ++++++- ion/include/ion/storage.h | 2 +- ion/src/device/shared/usb/dfu_interface.h | 2 +- ion/src/shared/storage.cpp | 32 ++++++++++++++++++++--- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index b44969e73b3..70537539d9c 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -74,7 +74,7 @@ USBExplanation1= "La protection USB protège votre" USBExplanation2= "calculatrice contre un verrouillage" USBExplanation3= "non-intentionnel" USBProtection= "Protection USB" -USBProtectionLevel = "Mise à jour acceptées" +USBProtectionLevel = "Mises à jour acceptées" USBDefaultLevel = "Basées sur Upsilon" USBLowLevel = "Basées sur Omega" USBParanoidLevel = "Aucune" diff --git a/apps/shared/function.h b/apps/shared/function.h index a5daa9c5917..574cb14c528 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -78,6 +78,7 @@ class Function : public ExpressionModelHandle { } bool isActive() const { return m_active; } void setActive(bool active) { m_active = active; } + void setMyColor(KDColor color) {m_color = color; } private: #if __EMSCRIPTEN__ /* For emscripten memory representation, loads and stores must be aligned; diff --git a/apps/shared/sequence.cpp b/apps/shared/sequence.cpp index 20ffb0ec62c..aa550cfc7ae 100644 --- a/apps/shared/sequence.cpp +++ b/apps/shared/sequence.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace Poincare; @@ -315,7 +316,14 @@ void Sequence::rangeForDisplay(float * xMin, float * xMax, float * yMin, float * Sequence::RecordDataBuffer * Sequence::recordData() const { assert(!isNull()); Ion::Storage::Record::Data d = value(); - return reinterpret_cast(const_cast(d.buffer)); + Sequence::RecordDataBuffer * buffer = reinterpret_cast(const_cast(d.buffer)); + for (int i = 0; i < Shared::MaxNumberOfSequences; i++) { + if (Ion::Storage::strstr(fullName(), SequenceStore::k_sequenceNames[i])) { + buffer->setMyColor(Palette::DataColor[i]); + break; + } + } + return buffer; } /* Sequence Model */ diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index ac7892a65b3..9eec482ecf4 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -16,7 +16,7 @@ class Storage { public: typedef uint16_t record_size_t; - constexpr static size_t k_storageSize = 64000; + constexpr static size_t k_storageSize = 63996; constexpr static size_t k_fullNameMaxSize = 220 + 5; constexpr static size_t k_extensionMaxSize = 10; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index 959d15da2a7..d950abac6fa 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -114,7 +114,7 @@ class DFUInterface : public Interface { class StatusData : public Streamable { public: - StatusData(Status status, State state, uint32_t pollTimeout = 10) : /* We put a default pollTimeout value of 1ms: if the device is busy, the + StatusData(Status status, State state, uint32_t pollTimeout = 1) : /* We put a default pollTimeout value of 1ms: if the device is busy, the * host has to wait 1ms before sending a getStatus Request. */ m_bStatus((uint8_t) status), m_bwPollTimeout{uint8_t((pollTimeout >> 16) & 0xFF), uint8_t((pollTimeout >> 8) & 0xFF),uint8_t(pollTimeout & 0xFF)}, diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 5be01b3e33b..5647ca2ca19 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -3,12 +3,12 @@ #include #include #include "ion/storage.h" -#include #include #include #include #if ION_STORAGE_LOG +#include #include #endif @@ -881,6 +881,7 @@ void Storage::deactivateQuarantine() { #ifdef ION_STORAGE_LOG logMessage("deactivateQuarantine start"); #endif + char availableNames[3] = {'u', 'v', 'w'}; for (int i = 0; i < count; i++) { for (char * p : *this) { @@ -904,6 +905,9 @@ void Storage::deactivateQuarantine() { strlcpy(originalName, originalNameP, originalSize + 1); originalName[originalSize + 1] = '\0'; strlcpy(extension, originalNameP + originalSize, k_extensionMaxSize); + if (strcmp(originalNameP + originalSize + 1, seqExtension) == 0) { + continue; + } } else { originalSize = strlen(originalNameP); strlcpy(originalName, originalNameP, originalSize); @@ -916,7 +920,6 @@ void Storage::deactivateQuarantine() { int current = 0; char converted[3]; Poincare::Integer(current).serialize(&converted[0], 3); - // sprintf(converted, "%d", current); setFullNameBufferWithPrefix(originalName, converted); if (*dotChar != 0) { strlcat(m_fullNameBuffer, extension, k_fullNameMaxSize); @@ -930,7 +933,6 @@ void Storage::deactivateQuarantine() { current ++; converted[3]; Poincare::Integer(current).serialize(&converted[0], 3); - // sprintf(converted, "%d", current); setFullNameBufferWithPrefix(originalName, converted); if (*dotChar != 0) { strlcat(m_fullNameBuffer, extension, k_fullNameMaxSize); @@ -941,7 +943,29 @@ void Storage::deactivateQuarantine() { } } } - + int currentIndex = 0; + for (int i = 0; i < numberOfRecordsWithExtension(seqExtension, true); i ++) { + for (char *p : *this) { + const char * name = fullNameOfRecordStarting(p); + if (strstr(name, seqExtension)) { + if (currentIndex < i) { + currentIndex ++; + continue; + } + Record r = Record(name); + const char * originalNameP = fullNameOfRecord(r, false); + const char * dotChar = UTF8Helper::CodePointSearch(originalNameP, k_dotChar); + char extension[k_extensionMaxSize]; + size_t originalSize; + originalSize = strlen(originalNameP) - strlen(originalNameP + strlen(originalNameP) - strlen(dotChar)); + strlcpy(extension, originalNameP + originalSize, k_extensionMaxSize); + setFullNameBufferWithPrefix(&availableNames[i], extension); + setFullNameOfRecord(r, m_fullNameBuffer, true); + currentIndex = 0; + break; + } + } + } #ifdef ION_STORAGE_LOG logMessage("deactivateQuarantine end"); #endif From c7b24be69e8e086cb14e8abdc578b21edd234549 Mon Sep 17 00:00:00 2001 From: dl11 Date: Sun, 26 Dec 2021 23:48:18 +0100 Subject: [PATCH 16/21] Exam Fix --- apps/settings/sub_menu/exam_mode_controller.cpp | 2 +- ion/src/shared/storage.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index ccd86c47bf6..bcc07751d93 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -113,7 +113,7 @@ GlobalPreferences::ExamMode ExamModeController::examMode() { GlobalPreferences::ExamMode mode = GlobalPreferences::sharedGlobalPreferences()->tempExamMode(); if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode - #if 0 + #if ION_SIMULATOR_FILES mode = GlobalPreferences::ExamMode::Off; #else mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 5647ca2ca19..c02e48d9ab4 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -536,6 +536,7 @@ Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, c m_lastRecordRetrieved = record; m_lastRecordRetrievedPointer = p; #if ION_STORAGE_LOG + logMessage(record.fullName()); logMessage("return None"); logMessage("setFullNameOfRecord end"); #endif @@ -893,7 +894,9 @@ void Storage::deactivateQuarantine() { Record r = Record(name); const char * originalNameP = fullNameOfRecord(r, false); if (!isFullNameTaken(originalNameP)) { - setFullNameOfRecord(r, originalNameP, true); + memset(m_fullNameBuffer, 0, k_fullNameMaxSize); + strlcpy(m_fullNameBuffer, originalNameP, k_fullNameMaxSize); + setFullNameOfRecord(r, m_fullNameBuffer, true); break; } const char * dotChar = UTF8Helper::CodePointSearch(originalNameP, k_dotChar); From 6b4d21f8ef56beb598bbc4b789abe708f52e4a7c Mon Sep 17 00:00:00 2001 From: dl11 Date: Mon, 27 Dec 2021 11:36:57 +0100 Subject: [PATCH 17/21] Correcting Upstream Merge errors --- ion/src/device/shared/usb/dfu_interface.cpp | 14 ++++++++++---- ion/src/device/shared/usb/dfu_interface.h | 10 +++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index 52077403eed..eae4499240c 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -90,8 +90,7 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer } } -bool -DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool DFUInterface::processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { if (Interface::processSetupInRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength)) { return true; } @@ -136,8 +135,7 @@ bool DFUInterface::processDownloadRequest(uint16_t wLength, uint16_t *transferBu return true; } -bool -DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { +bool DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) { if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) { m_ep0->stallTransaction(); return false; @@ -155,7 +153,15 @@ DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferBuffer } else { /* We decided to never protect Read operation. Else we would have to check * here it is not protected before reading. */ + + // Compute the reading address + uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; + // Copy the requested memory zone into the transfer buffer. + uint16_t copySize = minUint32T(transferBufferMaxLength, request->wLength()); + memcpy(transferBuffer, (void *)readAddress, copySize); + *transferBufferLength = copySize; } + m_state = State::dfuUPLOADIDLE; return true; } diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index d8eabe5a660..543291abb30 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -80,7 +80,7 @@ class DFUInterface : public Interface { }; enum class Status : uint8_t { - OK = 0x00, + OK = 0x00, errTARGET = 0x01, errFILE = 0x02, errWRITE = 0x03, @@ -179,10 +179,10 @@ class DFUInterface : public Interface { void leaveDFUAndReset(bool do_reset = true); /* Erase and Write state. After starting the erase of flash memory, the user - * can no longer leave DFU mode by pressing the Back key of the keyboard. This - * way, we prevent the user from interrupting a software download. After every - * software download, the calculator resets, which unlocks the "exit on - * pressing back". */ + * can no longer leave DFU mode by pressing the Back key of the keyboard. This + * way, we prevent the user from interrupting a software download. After every + * software download, the calculator resets, which unlocks the "exit on + * pressing back". */ void willErase() { m_isErasingAndWriting = true; } void resetFlashParameters() { m_lastMemoryType = -1; From ef57ed7dddcc575551a695dee78e4fbe4c117092 Mon Sep 17 00:00:00 2001 From: dl11 Date: Mon, 27 Dec 2021 12:05:43 +0100 Subject: [PATCH 18/21] LD fix N0110 --- ion/include/ion/storage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 9eec482ecf4..1363dbf01a7 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -16,7 +16,7 @@ class Storage { public: typedef uint16_t record_size_t; - constexpr static size_t k_storageSize = 63996; + constexpr static size_t k_storageSize = 63964; constexpr static size_t k_fullNameMaxSize = 220 + 5; constexpr static size_t k_extensionMaxSize = 10; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); From 473b83bc946aa37d51e340d48bf8706c3b9afd7c Mon Sep 17 00:00:00 2001 From: dl11 Date: Mon, 27 Dec 2021 12:12:46 +0100 Subject: [PATCH 19/21] LD test Github Fix --- ion/include/ion/storage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 1363dbf01a7..fbc66947330 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -16,7 +16,7 @@ class Storage { public: typedef uint16_t record_size_t; - constexpr static size_t k_storageSize = 63964; + constexpr static size_t k_storageSize = 63900; constexpr static size_t k_fullNameMaxSize = 220 + 5; constexpr static size_t k_extensionMaxSize = 10; static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough"); From 674b8af5810179890a9fcbca3a4c28d5aa58928d Mon Sep 17 00:00:00 2001 From: devdl11 Date: Sat, 29 Jan 2022 21:18:13 +0100 Subject: [PATCH 20/21] Fix Sequences App Post Exam Mode --- ion/include/ion/storage.h | 8 ++++++++ ion/src/shared/storage.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index fbc66947330..2e34a820716 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -37,6 +37,14 @@ class Storage { static constexpr uint8_t noMaxRecords = -1; + + /* TODO + * Replace k_sequenceNames from sequence_store.h with this one + * */ + static constexpr const char * k_sequenceNames[seqMaxRecords] = { + "u", "v", "w" + }; + class Record { /* A Record is identified by the CRC32 on its fullName because: * - A record is identified by its fullName, which is unique diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index c02e48d9ab4..0637bb2ba84 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -9,7 +9,7 @@ #if ION_STORAGE_LOG #include -#include +#include #endif namespace Ion { @@ -41,6 +41,8 @@ constexpr uint8_t Storage::eqMaxRecords; constexpr uint8_t Storage::noMaxRecords; +constexpr const char * Storage::k_sequenceNames[seqMaxRecords]; + Storage * Storage::sharedStorage() { static Storage * storage = new (staticStorageArea) Storage(); return storage; @@ -882,8 +884,6 @@ void Storage::deactivateQuarantine() { #ifdef ION_STORAGE_LOG logMessage("deactivateQuarantine start"); #endif - char availableNames[3] = {'u', 'v', 'w'}; - for (int i = 0; i < count; i++) { for (char * p : *this) { const char * name = fullNameOfRecordStarting(p); @@ -962,7 +962,7 @@ void Storage::deactivateQuarantine() { size_t originalSize; originalSize = strlen(originalNameP) - strlen(originalNameP + strlen(originalNameP) - strlen(dotChar)); strlcpy(extension, originalNameP + originalSize, k_extensionMaxSize); - setFullNameBufferWithPrefix(&availableNames[i], extension); + setFullNameBufferWithPrefix(&k_sequenceNames[i][0], extension); setFullNameOfRecord(r, m_fullNameBuffer, true); currentIndex = 0; break; From b06f4f823b20904d7ccee7674dd509a0dd182ddd Mon Sep 17 00:00:00 2001 From: dl11 Date: Fri, 4 Feb 2022 17:54:53 +0100 Subject: [PATCH 21/21] Review --- apps/settings/sub_menu/exam_mode_controller.cpp | 8 ++++---- apps/settings/sub_menu/usb_protection_controller.cpp | 4 ++-- apps/shared/function.h | 2 +- apps/shared/sequence.cpp | 2 +- ion/src/device/shared/boot/rt0.cpp | 2 +- ion/src/device/shared/usb/dfu_interface.cpp | 5 ++--- ion/src/device/shared/usb/dfu_interface.h | 11 +++++++---- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index bcc07751d93..2c1df1a7ec5 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -113,11 +113,11 @@ GlobalPreferences::ExamMode ExamModeController::examMode() { GlobalPreferences::ExamMode mode = GlobalPreferences::sharedGlobalPreferences()->tempExamMode(); if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode - #if ION_SIMULATOR_FILES - mode = GlobalPreferences::ExamMode::Off; - #else + // #if ION_SIMULATOR_FILES + // mode = GlobalPreferences::ExamMode::Off; + // #else mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); - #endif + // #endif } return mode; } diff --git a/apps/settings/sub_menu/usb_protection_controller.cpp b/apps/settings/sub_menu/usb_protection_controller.cpp index 7ffcbb20c91..07eddc74363 100644 --- a/apps/settings/sub_menu/usb_protection_controller.cpp +++ b/apps/settings/sub_menu/usb_protection_controller.cpp @@ -13,7 +13,7 @@ using namespace Shared; namespace Settings { -UsbInfoController::UsbInfoController(Responder *parentResponder) : +UsbInfoController::UsbInfoController(Responder *parentResponder): GenericSubController(parentResponder), m_usbProtectionLevelController(this), m_contentView(&m_selectableTableView) @@ -101,7 +101,7 @@ void UsbInfoController::willDisplayCellForIndex(HighlightCell *cell, int index) void UsbInfoController::didEnterResponderChain(Responder *previousFirstResponder) { m_contentView.reload(); - I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2,I18n::Message::USBExplanation3}; + I18n::Message infoMessages[] = {I18n::Message::USBExplanation1, I18n::Message::USBExplanation2, I18n::Message::USBExplanation3}; m_contentView.setMessages(infoMessages, k_numberOfExplanationMessages); } } diff --git a/apps/shared/function.h b/apps/shared/function.h index 574cb14c528..1dcea372d3c 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -78,7 +78,7 @@ class Function : public ExpressionModelHandle { } bool isActive() const { return m_active; } void setActive(bool active) { m_active = active; } - void setMyColor(KDColor color) {m_color = color; } + void setGraphColor(KDColor color) { m_color = color; } private: #if __EMSCRIPTEN__ /* For emscripten memory representation, loads and stores must be aligned; diff --git a/apps/shared/sequence.cpp b/apps/shared/sequence.cpp index aa550cfc7ae..c2e963f5cc5 100644 --- a/apps/shared/sequence.cpp +++ b/apps/shared/sequence.cpp @@ -319,7 +319,7 @@ Sequence::RecordDataBuffer * Sequence::recordData() const { Sequence::RecordDataBuffer * buffer = reinterpret_cast(const_cast(d.buffer)); for (int i = 0; i < Shared::MaxNumberOfSequences; i++) { if (Ion::Storage::strstr(fullName(), SequenceStore::k_sequenceNames[i])) { - buffer->setMyColor(Palette::DataColor[i]); + buffer->setGraphColor(Palette::DataColor[i]); break; } } diff --git a/ion/src/device/shared/boot/rt0.cpp b/ion/src/device/shared/boot/rt0.cpp index b091563c092..a2949b3c0d4 100644 --- a/ion/src/device/shared/boot/rt0.cpp +++ b/ion/src/device/shared/boot/rt0.cpp @@ -245,7 +245,7 @@ void __attribute__((noinline)) start() { Ion::Device::Board::initFPU(); /* Call static C++ object constructors - * The C++ compiler creates an initialization function for each static object. + * The C++ compiler creates an initialization function for each static object. * The linker then stores the address of each of those functions consecutively * between _init_array_start and _init_array_end. So to initialize all C++ * static objects we just have to iterate between theses two addresses and diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index eae4499240c..0a343eb6cf4 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -78,7 +78,6 @@ void DFUInterface::wholeDataSentCallback(SetupPacket *request, uint8_t *transfer // Leave DFU routine: Leave DFU, reset device, jump to application code leaveDFUAndReset(); } else if (m_state == State::dfuDNBUSY) { - m_state = State::dfuDNBUSY; if (m_largeBufferLength != 0) { // Here, copy the data from the transfer buffer to the flash memory writeOnMemory(); @@ -153,7 +152,6 @@ bool DFUInterface::processUploadRequest(SetupPacket *request, uint8_t *transferB } else { /* We decided to never protect Read operation. Else we would have to check * here it is not protected before reading. */ - // Compute the reading address uint32_t readAddress = (request->wValue() - 2) * Endpoint0::MaxTransferSize + m_addressPointer; // Copy the requested memory zone into the transfer buffer. @@ -189,7 +187,7 @@ void DFUInterface::changeAddressPointerIfNeeded() { void DFUInterface::eraseCommand(uint8_t *transferBuffer, uint16_t transferBufferLength) { /* We determine whether the commands asks for a mass erase or which sector to - * erase. The erase must be done after the next getStatus request. */ + * erase. The erase must be done after the next getStatus request. */ m_state = State::dfuDNLOADSYNC; if (transferBufferLength == 1) { @@ -218,6 +216,7 @@ void DFUInterface::eraseMemoryIfNeeded() { if (m_erasePage < 0) { return; } + willErase(); #if 0 // We don't erase now the flash memory to avoid crash if writing is refused diff --git a/ion/src/device/shared/usb/dfu_interface.h b/ion/src/device/shared/usb/dfu_interface.h index 543291abb30..f05604e77b4 100644 --- a/ion/src/device/shared/usb/dfu_interface.h +++ b/ion/src/device/shared/usb/dfu_interface.h @@ -11,9 +11,12 @@ #include #include -namespace Ion { -namespace Device { -namespace USB { +namespace Ion +{ +namespace Device +{ +namespace USB +{ class DFUInterface : public Interface { @@ -207,7 +210,7 @@ class DFUInterface : public Interface { uint8_t m_lastMemoryType; // -1: None; 0: internal; 1: external uint8_t m_lastPageErased; // -1 default value bool m_dfuUnlocked; - uint8_t m_dfuLevel; + uint8_t m_dfuLevel; // 0: Upsilon only, 1: Omega-forked only, 2: No update }; }