greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.08k stars 505 forks source link

RAW write to the SD-Card #328

Open karstengit opened 3 years ago

karstengit commented 3 years ago

This is not a bug - it is a feature request.

Is it possible to write direct to sectors of the SD-card using SdFat?

This could be helpful when a filesystem is not needed. But actual there is another problem with a virus that has made an sd-card unusable and should be solved without using an OS: https://www.easeus.com/partition-master/sd-card-mounted-as-read-only.html

We have tried everything to get rid of the write protection, but every OS (Linux/Windows) always sees the card as write protected medium and denies to write on it.

Your formatting example is working and says it has cleared the card, but afterwards nothing has happened. The card is still write protected and shows a (bad) file system on the card in Linux.

So it seems your format never touch the partition table that must be overwritten now.

init time: 0x1e7 ms

Card type: SDXC

Manufacturer ID: 0X28
OEM ID: BE
Product:
Version: 0.2
Serial number: 0X3B0300BA
Manufacturing date: 2/2010

cardSize: 128109.77 MB (MB = 1,000,000 bytes)
flashEraseSize: 128 blocks
eraseSingleBlock: true

OCR: 0XC0FF8000

SD Partition Table
part,boot,bgnCHS[3],type,endCHS[3],start,length
1,0X0,0X0,0X2,0X0,0XEE,0XFF,0XFF,0XFF,1,250214399
2,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
3,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0
4,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0X0,0,0

volumeBegin failed. Is the card formatted?

How can this be done with SdFat ?

The example RawWrite.ino seems to write to a file too and cannot overwrite the partition table.

karstengit commented 3 years ago

That's the way the partition of the SD-Card is shown in Linux:

Warning: Unable to open /dev/sdc read-write (file system read-only).
/dev/sdc has been opened read-only.
Model: Generic STORAGE DEVICE (scsi)                                      
Disk /dev/sdc: 128GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name            Flags
 1      1049kB  17,8MB  16,8MB               android_meta
 2      17,8MB  128GB   128GB                android_expand

This are the kernel messages:

[14178.606998] sd 6:0:0:0: [sdc] 250214400 512-byte logical blocks: (128 GB/119 GiB)
[14178.609999] sd 6:0:0:0: [sdc] Write Protect is on
[14178.610010] sd 6:0:0:0: [sdc] Mode Sense: 21 00 80 00
[14178.639003]  sdc: sdc1 sdc2
[14190.339859] /dev/sdc1: Can't open blockdev
[14203.636695] attempt to access beyond end of device
               sdc1: rw=524288, want=2639392, limit=32768
[14203.636709] attempt to access beyond end of device
               sdc1: rw=0, want=2639368, limit=32768
[14203.637195] attempt to access beyond end of device
               sdc1: rw=0, want=2639368, limit=32768
[14203.637208] attempt to access beyond end of device
               sdc1: rw=524288, want=2640799, limit=32768
[14203.637212] attempt to access beyond end of device
               sdc1: rw=0, want=2640799, limit=32768
[14203.637216] attempt to access beyond end of device
               sdc1: rw=0, want=2640799, limit=32768
[14203.637218] attempt to access beyond end of device
               sdc1: rw=0, want=2640799, limit=32768
[14203.637223] attempt to access beyond end of device
               sdc1: rw=524288, want=2640792, limit=32768
[14203.637225] attempt to access beyond end of device
               sdc1: rw=0, want=2640792, limit=32768
[14203.637229] attempt to access beyond end of device
               sdc1: rw=0, want=2640792, limit=32768
[14355.691800] sdc: detected capacity change from 128109772800 to 0
[14991.615327] sd 6:0:0:0: [sdc] 250214400 512-byte logical blocks: (128 GB/119 GiB)
[14991.647594]  sdc: sdc1 sdc2

A complete clean of the SD-Card is needed without any checks before.

greiman commented 3 years ago

There are many custom formats and partition layouts used for SD cards but SdFat only supports the SD association standard format for SD cards. SD card hardware internals and firmware algorithms for modern SD cards are optimized for this format.

You can try their formatter but will probably get the same result.

The SdSpicard class can be used to for raw read/write of SD cards and the core library has support for multiple partition. I just don't have time or interest to support all the issues that occur with apps that do raw I/O or non-standard SD formats.

Here is an example that can do raw read/write and supports multiple partitions.

#include "SdFat.h"
SdSpiCard card;
FatVolume vol;
FatFile file;
uint8_t buf[512];
#define SD_CONFIG SdSpiConfig(SS,SHARED_SPI, SD_SCK_MHZ(20))
#define MBR_PART 1
#define error(msg) {Serial.println(msg);while (true);}

void setup() {
  Serial.begin(9600);
  if (!card.begin(SD_CONFIG)) error("card.begin");
  //  Read sector print signature.
  if (!card.readSector(0, buf)) error("card.readSector");
  Serial.print(buf[510], HEX);
  Serial.println(buf[511], HEX);  
  if (!vol.begin(&card, true, MBR_PART)) error("vol.begin");
  if (!file.open("test.txt", O_RDWR | O_CREAT)) error("file.open");
  if (file.write("test line\n") != 10) error("file.write");
  file.close();
  Serial.println("done");
}
void loop() {
}

The output is:

55AA done

Note that FatFile does not support Print. The File class is a template class that is derived from Stream and FatFile.

You should be able to use the File class in the above code.

You can us ExFatVolume/ExFatFile or FsVolume/FsFile in the same way. FsVolume does not have the partition argument yet.

karstengit commented 3 years ago

Thank you for your quick response! I am really thankful for your wonderful library that makes it possible to log data direct as files on an SD-Card. So Thank You for your work and this library!

You are really not forced to give support for all the issues that occur with apps that do raw I/O. :-) In this case the result was the work of an virus on an Android device.

Any tool that works on an PC or other Device with an "real OS" like Posix or Windows fails to recover the SD-Card, because the SD-Card is identifying somehow as read-only device and the kernel is blocking any write afterwards.

That is the reason i tried to recover it with an Microcontroller (STM32), that has no kernel with "unneeded routines" to check such nasty things. ;-)

In your example SdInfo.ino you read the MBR:

bool mbrDmp() {
  MbrSector_t mbr;
  bool valid = true;
  if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
    cout << F("\nread MBR failed.\n");
    errorPrint();
    return false;
  }
  cout << F("\nSD Partition Table\n");
  cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n");

...

It's hard to understand what you are doing there, but at least i only need to overwrite the first sectors with 0. Is there a corresponding sd.card()->writeSector() and how it can be used?

That's all support i need to try to write an own "SD-Card cleaner". :-) Hopefully the virus has modified only some informations in the partition.

karstengit commented 3 years ago

O.K. I found the documentation and the function description now:

writeSector() bool SdSpiCard::writeSector ( uint32_t sector, const uint8_t * src ) inline

Writes a 512 byte sector to an SD card.

Parameters [in] sector Logical sector to be written. [in] src Pointer to the location of the data to be written.

Returns true for success or false for failure.

Do you have a simple example to use it?

greiman commented 3 years ago

To zero the first sector just add the following to the above example.

  memset(buf, 0, 512);
  if (!card.writeSector(0, buf)) error("card.writeSector");

After this the MBR sector will be entirely zero so a reformat will be needed.

format

Better to use the SD Association Formatter.

karstengit commented 3 years ago

Thank you for the hint to use writesector.

The first run i only have overwritten the MBR - without success. This results in

Warning: Unable to open /dev/sdc read-write (Das Dateisystem ist nur lesbar).
/dev/sdc has been opened read-only.
Model: Generic STORAGE DEVICE (scsi)                                      
Disk /dev/sdc: 128GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name            Flags
 1      1049kB  17,8MB  16,8MB               android_meta
 2      17,8MB  128GB   128GB                android_expand

So i made a loop over sector 0-99 and the Partitioning is still there. Unbelievable what have been done with the SD-Card - a really good hack! It seems the controller of the SD-Card itself denies any write to the card?

Your complete enhanced example looks now the following way and i hope this is correct? (see function eraseMBR())

/*
 * 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 "SdFat.h"
#include "sdios.h"

/*
  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;
/*
  Change the value of SD_CS_PIN if you are using SPI
  and your hardware does not use the default value, SS.
  Common values are:
  Arduino Ethernet shield: pin 4
  Sparkfun SD shield: pin 8
  Adafruit SD shields and modules: pin 10
*/

// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = PA4;
#else  // SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif  // SDCARD_SS_PIN

// 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_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
#else  // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
#endif  // HAS_SDIO_CLASS
*/

// SPI1 on F103C8
static SPIClass mySPI1(PA7, PA6, PA5);
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI1)

// SPI2 on F103C8
//static SPIClass mySPI2(PB15, PB14, PB13);
//#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI2)

//==============================================================================
// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
uint32_t cardSectorCount = 0;
uint8_t  sectorBuffer[512];
//------------------------------------------------------------------------------
// SdCardFactory constructs and initializes the appropriate card.
SdCardFactory cardFactory;
// Pointer to generic SD card.
SdCard* m_card = nullptr;
//------------------------------------------------------------------------------
#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;
  }
  SysCall::halt();
}
//------------------------------------------------------------------------------
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");
}
//------------------------------------------------------------------------------
// flash erase all data
void eraseComplete() {
  cout << endl << F("Erasing complete\n");
  uint32_t firstBlock = 0;
  uint32_t lastBlock;
  uint16_t n = 0;

  do {
    lastBlock = cardSectorCount - 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");
}
//------------------------------------------------------------------------------
// flash erase all data
void eraseMBR() {
  cout << endl << F("Erasing MBR + 99 sectors\n");
  MbrSector_t mbr;
  bool valid = true;
  if (!m_card->readSector(0, sectorBuffer)) {
    sdError("readBlock");
  }

  cout << endl << F("MBR read - write now\n");
  memset(sectorBuffer, 0, 512);
  for (int c = 0; c < 100; c ++) {
    if (!m_card->writeSector(c, sectorBuffer)) sdError("card.writeSector");
  }
  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_PIN to change the SD chip select pin.\n");
}
//------------------------------------------------------------------------------
void printConfig(SdioConfig config) {
  (void)config;
  cout << F("Assuming an SDIO interface.\n");
}
//------------------------------------------------------------------------------
void setup() {
  char c;
  Serial.begin(115200);
  // Wait for USB Serial
  while (!Serial) {
    SysCall::yield();
  }
  printConfig(SD_CONFIG);
  cout << F("\nType any character to start\n");
  while (!Serial.available()) {
    SysCall::yield();
  }
  // Discard any extra characters.
  clearSerialInput();

  cout << F(
         "\n"
         "This program can erase and/or format SD/SDHC/SDXC cards.\n"
         "\n"
         "Erase uses the card's fast flash erase command.\n"
         "Flash erase sets all data to 0X00 for most cards\n"
         "and 0XFF for a few vendor's cards.\n"
         "\n"
         "Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n"
         "Cards larger than 2 GiB and up to 32 GiB will be formatted\n"
         "FAT32. Cards larger than 32 GiB will be formatted exFAT.\n"
         "\n"
         "Warning, all data on the card will be erased.\n"
         "Enter 'Y' to continue: ");
  while (!Serial.available()) {
    SysCall::yield();
  }
  c = Serial.read();
  cout << c << endl;
  if (c != 'Y') {
    cout << F("Quiting, you did not enter 'Y'.\n");
    return;
  }
  // Read any existing Serial data.
  clearSerialInput();

  // Select and initialize proper card driver.
  m_card = cardFactory.newCard(SD_CONFIG);
  if (!m_card || m_card->errorCode()) {
    sdError("card init failed.");
    return;
  }

  cardSectorCount = m_card->sectorCount();
  if (!cardSectorCount) {
    sdError("Get sector count failed.");
    return;
  }

  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");
  }
  cout << F(
         "\n"
         "Options are:\n"
         "E - erase the card and skip formatting.\n"
         "F - erase and then format the card. (recommended)\n"
         "C - erase complete card and then format the card.\n"
         "M - erase complete MBR.\n"
         "Q - quick format the card without erase.\n"
         "\n"
         "Enter option: ");

  while (!Serial.available()) {
    SysCall::yield();
  }
  c = Serial.read();
  cout << c << endl;
  if (!strchr("EFCMQ", c)) {
    cout << F("Quiting, invalid option entered.") << endl;
    return;
  }
  if (c == 'E' || c == 'F') {
    eraseCard();
  }
  if (c == 'F' || c == 'Q') {
    formatCard();
  }
  if (c == 'C') {
    eraseComplete();
  }
  if (c == 'M') {
    eraseMBR();
  }
}
void loop() {
}
greiman commented 3 years ago

I just noticed the card is GPT. The MBR is not used. It is just protective.

Did you try the SdFormatter example with the 'E' option. It uses the hardware erase option to clear every sector of flash to the default erase state.

karstengit commented 3 years ago

Yes - all options are tested without success. And as already told every option in Linux and Windows was tested to format and to repartition.

The interesting thing is the kernel message "[sdc] Write Protect is on" so there must be an option for it. Maybe such a thing has been specified as replacement for the write protect switch on the SD-Card? Nobody uses it and a hacker has find it and has fun with it.

greiman commented 3 years ago

SD cards can be write protected. SD stands for Secure Digital.

Cards can protect their contents from erasure or modification, prevent access by non-authorized users, and protect copyrighted content using digital rights management, DRM.

If content is password protected as DRM data, you are out of luck. DRM protected data can't be erased without the password.

A host device can lock an SD card using a password of up to 16 bytes, typically supplied by the user. A locked card interacts normally with the host device except that it rejects commands to read and write data. A locked card can be unlocked only by providing the same password. The host device can, after supplying the old password, specify a new password or disable locking. Without the password (typically, in the case that the user forgets the password), the host device can command the card to erase all the data on the card for future re-use (except card data under DRM), but there is no way to gain access to the existing data.

Clearly portions of your card can't be erased with the standard non-password erase commands.

greiman commented 3 years ago

You may be able to save the card if simple write protection was used.

https://www.diskpart.com/articles/remove-write-protection-on-micro-sd-card-sandisk.html

You will need a utility like the AOMEI Partition Assistant.

Maybe you formatted the card as internal Android storage. If so try formatting is as external storage on that Android device.

Android devices lock cards so no other device can access data.

karstengit commented 3 years ago

You may be able to save the card if simple write protection was used.

https://www.diskpart.com/articles/remove-write-protection-on-micro-sd-card-sandisk.html

You will need a utility like the AOMEI Partition Assistant.

Maybe you formatted the card as internal Android storage. If so try formatting is as external storage on that Android device.

Android devices lock cards so no other device can access data.

Thank you for your investigation and answer!

This is not my SD-Card and i only want to help someone else. Additional this is an interesting case. We will try the described tools on a Windows PC to recover the card and i will report the result.

What a nonsense when the card cannot be recovered! https://unix.stackexchange.com/a/138521 There should be always the possibility to delete the complete content. This is the same with the protected flash of a microcontroller.

greiman commented 3 years ago

The card was definitely formatted as internal in an Android device. I went back and found this earlier in your post.

Number Start End Size File system Name Flags 1 1049kB 17,8MB 16,8MB android_meta 2 17,8MB 128GB 128GB android_expand

Look for articles like this:

https://source.android.com/devices/storage/adoptable

https://forum.fairphone.com/t/a-little-guide-to-using-sd-cards/37297

It should not be easy to access data on a secure card so that's what you get if you select secure/encrypted.

Look for Android articles about Internal (adopted) storage and External (portable) storage.

karstengit commented 3 years ago

Thanks again.

It seems that as internal storage the external SD is somehow mounted into the root filesystem. Google has blemished more and more the Linux kernel in Android and there are tons of mounts in a running system.

Formatting the SD card as internal storage on the FP3 under android 10 is confirmed to break storage on the card and to make some things unusable. Forum topic here

When i remember correct, the issue with the unwritable flash comes suddenly in the usage of the smartphone, without a new format or change / update of the Android. That was the reason to think for the work of an virus. I don't know if the card has been become full or what the user has done in detail. The Android has been reinstalled in the time between, so any old key is lost.

The data content is irrelevant - the aim is to get the SD-Card usable again for further use.

greiman commented 3 years ago

You can see why I have avoided using any of the mysterious "Secure Digital" features of cards. Some users have asked for this.

I don't even support an API for the simplest write protect of micro-SD cards, it's too easy to lock them forever since there is write once protect bit.

Apple and Google want to sell products that are secure at the level of stopping the CIA.

Using an SD card with encryption and DRM is too fragile. I think many manufacturers like Samsung have disabled the internal/adopted feature for SD cards in the latest Android.

karstengit commented 3 years ago

I agree with you that such features protect only the revenue of the SD-Card manufacturer. When a bigger card like this gets unusable it is really troublesome.

The kernel encryption with up to AES512 is perfectly sufficient (when needed) and cost only a little bit CPU performance. In most CPU's this is already implemented as instruction set https://en.wikipedia.org/wiki/AES_instruction_set

greiman commented 3 years ago

Don't blame the SD-Card manufacturer - DRM was never intended for this use.

Looks like Samsung allows encrypted filesystems on SD cards but does not use the new ASSD features of SD cards so you can wipe the card. Still dangerous since you can lose the data (but not the card).

The data on your SD card will not be able to be read or decrypted after a reset or in another device. The only option to use the microSD card again is to wipe it completely.

karstengit commented 3 years ago

When the data is lost it can be seen as the responsibility of the user that uses such a encryption. The biggest problem ist that people just think "encryption is good - it makes it safe" without knowing the risks for data lost.

But when the hardware / firmware allows to lock the card in a way that it is unusable, then the manufacturer can be blamed for it. There are commands in the instruction set of some CPU's that can burn it - that's a similar problem.

greiman commented 3 years ago

If you use the write once option for an SD card you get what you asked for. If you use the ASSD features of an SD card same thing.

The ASSD feature does what the SmartSD standard specifies, it can implement a SmartCard but is much more general.

If you activate ASSD features you get what you asked for. It restricts attempts to access to the card without the correct key.

karstengit commented 3 years ago

https://www.sdcard.org/developers/sd-standard-overview/assd/

I don't read the details but do you know how the ASSD features can be activated? Is there a protection that it can be done only with something like root / admin privileges?

Because there is a high risk that a hacker will abuse this feature to encrypt the data of the card to extort money for the key.

greiman commented 3 years ago

Enabling secure features for a card is protected by the OS kernel. Once enabled access is protected by the card's security processor.

If you use a card in a non-secure OS it's easy to do anything. You can just encrypt it like any disk.

You can make it unusable by setting this bit in the CSD:

PERM_WRITE_PROTECT Permanently protects the entire card content against overwriting or erasing (all write and erase commands for this card are permanently disabled). The default value is 0, i.e. not permanently write protected.

This bit can't be cleared.

There is a reversible write protect:

TMP_WRITE_PROTECT Temporarily protects the entire card content from being overwritten or erased (all write and erase commands for this card are temporarily disabled). This bit can be set and reset. The default value is 0, i.e. not write protected.

I will not add any access to any of these features from SdFat.

karstengit commented 3 years ago

The PERM_WRITE_PROTECT is somehow unbelievable, because you can de facto kill an SD-Card with it.