From b2e0fde025204be39b98b194acdb8ad9caac9095 Mon Sep 17 00:00:00 2001 From: Spacehuhn Date: Wed, 2 Nov 2022 12:02:15 +0100 Subject: [PATCH] Format SD card --- USBNova.ino | 5 +- src/cli/cli.cpp | 5 +- src/msc/format.cpp | 184 ++++++++++++++++++++++++++++++++ src/msc/format.h | 7 ++ src/msc/msc.cpp | 3 +- src/msc/msc.h | 2 +- src/preferences/preferences.cpp | 8 +- 7 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 src/msc/format.cpp create mode 100644 src/msc/format.h diff --git a/USBNova.ino b/USBNova.ino index 8824526..164b4d4 100644 --- a/USBNova.ino +++ b/USBNova.ino @@ -11,6 +11,7 @@ #include "src/duckparser/duckparser.h" #include "src/tasks/tasks.h" #include "src/cli/cli.h" +#include "src/msc/format.h" void update() { led::update(); @@ -64,12 +65,12 @@ void setup() { // Attack settings keyboard::setLocale(locale::get(preferences::getDefaultLayout().c_str())); duckparser::setDefaultDelay(preferences::getDefaultDelay()); - /* + // Format Flash (if specified in preferences.json) if ((selector::mode() == SETUP) && preferences::getFormat()) { led::setColor(255, 255, 255); msc::format(preferences::getDriveName().c_str()); - }*/ + } // Create preferences file if it doesn't exist yet if (!msc::exists(PREFERENCES_PATH)) { diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index b218ce7..3773ef2 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -11,6 +11,7 @@ #include "../attack/attack.h" #include "../msc/msc.h" #include "../../config.h" +#include "../msc/format.h" #define BUFFER_SIZE 1024 @@ -92,7 +93,7 @@ namespace cli { Serial.println("Made with <3 by Spacehuhn (spacehuhn.com)"); Serial.println(); }).setDescription(" Print the firmware version."); - /* + // format cli.addCmd("format", [](cmd* c) { led::setColor(255, 255, 255); @@ -107,7 +108,7 @@ namespace cli { Serial.println("Done formatting!"); Serial.println(); }).setDescription(" Fromat the internal memory."); - */ + // reset cli.addCmd("reset", [](cmd* c) { preferences::reset(); diff --git a/src/msc/format.cpp b/src/msc/format.cpp new file mode 100644 index 0000000..c1d0736 --- /dev/null +++ b/src/msc/format.cpp @@ -0,0 +1,184 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#include "format.h" + +#include "../../config.h" +#include "../../debug.h" + +/* + * This program will format SD/SDHC/SDXC cards. + * Warning all data will be deleted! + * + * This program attempts to match the format + * generated by SDFormatter available here: + * + * http://www.sdcard.org/consumers/formatter/ + * + * For very small cards this program uses FAT16 + * and the above SDFormatter uses FAT12. + */ +#include +#include + +// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur. +#define SPI_CLOCK SD_SCK_MHZ(12) + +// Try to select the best SD card configuration. +#if HAS_SDIO_CLASS +#define SD_CONFIG SdioConfig(FIFO_SDIO) +#elif ENABLE_DEDICATED_SPI +#define SD_CONFIG SdSpiConfig(SD_CS, DEDICATED_SPI, SPI_CLOCK) +#else // HAS_SDIO_CLASS +#define SD_CONFIG SdSpiConfig(SD_CS, SHARED_SPI, SPI_CLOCK) +#endif // HAS_SDIO_CLASS + +namespace format { + // ========== PRIVATE ========= // + /* + Set DISABLE_CS_PIN to disable a second SPI device. + For example, with the Ethernet shield, set DISABLE_CS_PIN + to 10 to disable the Ethernet controller. + */ + const int8_t DISABLE_CS_PIN = -1; + + // Serial output stream + ArduinoOutStream cout(Serial); + + uint32_t cardSectorCount = 0; + uint8_t sectorBuffer[512]; + + SdCardFactory cardFactory; // SdCardFactory constructs and initializes the appropriate card. + SdCard* m_card = nullptr; // Pointer to generic SD card. + + #define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();} + + void sdErrorHalt() { + if (!m_card) { + cout << F("Invalid SD_CONFIG") << endl; + } else if (m_card->errorCode()) { + if (m_card->errorCode() == SD_CARD_ERROR_CMD0) { + cout << F("No card, wrong chip select pin, or wiring error?") << endl; + } + cout << F("SD errorCode: ") << hex << showbase; + printSdErrorSymbol(&Serial, m_card->errorCode()); + cout << F(" = ") << int(m_card->errorCode()) << endl; + cout << F("SD errorData = ") << int(m_card->errorData()) << endl; + } + while (true) {} + } + + void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); + } + + // flash erase all data + uint32_t const ERASE_SIZE = 262144L; + void eraseCard() { + cout << endl << F("Erasing\n"); + uint32_t firstBlock = 0; + uint32_t lastBlock; + uint16_t n = 0; + + do { + lastBlock = firstBlock + ERASE_SIZE - 1; + if (lastBlock >= cardSectorCount) { + lastBlock = cardSectorCount - 1; + } + if (!m_card->erase(firstBlock, lastBlock)) { + sdError("erase failed"); + } + cout << '.'; + if ((n++)%64 == 63) { + cout << endl; + } + firstBlock += ERASE_SIZE; + } while (firstBlock < cardSectorCount); + cout << endl; + + if (!m_card->readSector(0, sectorBuffer)) { + sdError("readBlock"); + } + cout << hex << showbase << setfill('0') << internal; + cout << F("All data set to ") << setw(4) << int(sectorBuffer[0]) << endl; + cout << dec << noshowbase << setfill(' ') << right; + cout << F("Erase done\n"); + } + + void formatCard() { + ExFatFormatter exFatFormatter; + FatFormatter fatFormatter; + + // Format exFAT if larger than 32GB. + bool rtn = cardSectorCount > 67108864 ? + exFatFormatter.format(m_card, sectorBuffer, &Serial) : + fatFormatter.format(m_card, sectorBuffer, &Serial); + + if (!rtn) { + sdErrorHalt(); + } + cout << F("Run the SdInfo example for format details.") << endl; + } + + void printConfig(SdSpiConfig config) { + if (DISABLE_CS_PIN < 0) { + cout << F( + "\nAssuming the SD is the only SPI device.\n" + "Edit DISABLE_CS_PIN to disable an SPI device.\n"); + } else { + cout << F("\nDisabling SPI device on pin "); + cout << int(DISABLE_CS_PIN) << endl; + pinMode(DISABLE_CS_PIN, OUTPUT); + digitalWrite(DISABLE_CS_PIN, HIGH); + } + cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin); + cout << F("\nEdit SD_CS to change the SD chip select pin.\n"); + } + + void printConfig(SdioConfig config) { + (void)config; + cout << F("Assuming an SDIO interface.\n"); + } + + // ========== PUBLIC ========= // + bool start(const char* drive_name) { + debugln("Starting format..."); + + printConfig(SD_CONFIG); + + // Select and initialize proper card driver. + m_card = cardFactory.newCard(SD_CONFIG); + if (!m_card || m_card->errorCode()) { + sdError("card init failed."); + return false; + } + + cardSectorCount = m_card->sectorCount(); + if (!cardSectorCount) { + sdError("Get sector count failed."); + return false; + } + + cout << F("\nCard size: ") << cardSectorCount*5.12e-7; + cout << F(" GB (GB = 1E9 bytes)\n"); + cout << F("Card size: ") << cardSectorCount/2097152.0; + cout << F(" GiB (GiB = 2^30 bytes)\n"); + + cout << F("Card will be formated "); + if (cardSectorCount > 67108864) { + cout << F("exFAT\n"); + } else if (cardSectorCount > 4194304) { + cout << F("FAT32\n"); + } else { + cout << F("FAT16\n"); + } + + formatCard(); + + return true; + } +} \ No newline at end of file diff --git a/src/msc/format.h b/src/msc/format.h new file mode 100644 index 0000000..b2a8017 --- /dev/null +++ b/src/msc/format.h @@ -0,0 +1,7 @@ +/* This software is licensed under the MIT License: https://github.com/spacehuhntech/usbnova */ + +#pragma once + +namespace format { + bool start(const char* drive_name = "MalDuino"); +} \ No newline at end of file diff --git a/src/msc/msc.cpp b/src/msc/msc.cpp index b05255e..4ddb905 100644 --- a/src/msc/msc.cpp +++ b/src/msc/msc.cpp @@ -4,6 +4,7 @@ #include "../../config.h" #include "../../debug.h" +#include "format.h" #include @@ -84,7 +85,7 @@ namespace msc { } bool format(const char* drive_name) { - return false;//format::start(drive_name); + return format::start(drive_name); } void print() { diff --git a/src/msc/msc.h b/src/msc/msc.h index da9c791..3dec9c2 100644 --- a/src/msc/msc.h +++ b/src/msc/msc.h @@ -8,7 +8,7 @@ namespace msc { bool init(); - bool format(const char* drive_name = "USB Nova"); + bool format(const char* drive_name = "MalDuino"); void print(); void setID(const char* vid, const char* pid, const char* rev); diff --git a/src/preferences/preferences.cpp b/src/preferences/preferences.cpp index dd94ee3..7a3a5e0 100644 --- a/src/preferences/preferences.cpp +++ b/src/preferences/preferences.cpp @@ -168,13 +168,13 @@ namespace preferences { read_array(config_doc, "attack_color", attack_color, 4); read_array(config_doc, "setup_color", setup_color, 4); read_array(config_doc, "idle_color", idle_color, 4); - +*/ // Format Flash (Drive name/Disk label max 11 characters) format = config_doc.containsKey("format"); if (format) { drive_name = config_doc["format"].as().substr(0, 11); } -*/ + disable_capslock = config_doc["disable_capslock"].as(); run_on_indicator = config_doc["run_on_indicator"].as(); run_on_msc = config_doc["run_on_msc"].as(); @@ -235,10 +235,10 @@ namespace preferences { idle_color[1] = 0; idle_color[2] = 0; idle_color[3] = 0; - +*/ format = false; drive_name = "MalDuino"; -*/ + disable_capslock = true; run_on_indicator = false; run_on_msc = false;