Skip to content

Commit b5a5394

Browse files
committed
Initial commit
0 parents  commit b5a5394

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed

Diff for: LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2013 Severin Schols
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Diff for: README.md

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SD Card Recovery using an Arduino
2+
3+
One of my SD card "died". More specifically, my laptop wouldn't read it anymore, and neither would any other machines or cameras I tried. It did react (looking at the dmesg output), but would only though errors. So I decided to try and read it using an Arduino.
4+
5+
## Background
6+
__Attention__ _Dangerous half knowledge ahead_
7+
8+
SD cards have two modes in which they can be accessed. One is the SDIO mode, which is used by your average card reader, your camera, etc. It's fast, and somewhat complicated. The other mode is SPI mode. It's much slower, but it's fairly simple. That's what you use if you connect your SD card to a microcontroller such as an arduino.
9+
10+
## Hardware
11+
I used a Playduino One Arduino clone, that I had lying around, and a SD card shield I got from ElectroDragon. Just plugged them together, and done is the card reader hardware.
12+
13+
## Software
14+
I took 3 steps in the recovery process.
15+
16+
### cardinfo
17+
The SD card library in the Arduino IDE contains an example called _cardinfo_. It connects to the card, and gets information such as size, filesystem type, and a list of files on the card.
18+
19+
That worked, so I kept going.
20+
21+
### sd_recovery_files
22+
The sketch `sd_recovery_files.ino` tries to iterate over the filesystem, and outputs all files in a HEX encoded format over the serial port. If you save the output to a file on your machine, you can then parse the file using the supplied python script `parse_files.py`.
23+
24+
This surprisingly worked for a number of files, but the `openNextFile()` doesn't seem to work all that well, so not all files were copied.
25+
26+
### sd_recovery_raw
27+
The sketch `sd_recovery_raw.ino` reads the SD card block by block, and outputs it in a HEX encoded format over the serial port. You can parse the output back into a binary file using the supplied `parse_raw.py` python script.
28+
29+
This may just take forever, and I have not been successful in using that file, but I have yet to actually copy the entire SD card that way (might take a few days for the 4GB card I have).

Diff for: parse_files.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/python
2+
import re
3+
import fileinput
4+
5+
# Header for each file, with filename and size
6+
prog = re.compile('^--- (.*);(\d*)')
7+
8+
9+
raw = fileinput.input()
10+
11+
while (True):
12+
first = raw.readline()
13+
if len(first) == 0:
14+
break
15+
second = raw.readline()
16+
header = prog.match(first)
17+
name = header.group(1)
18+
size = int(header.group(2))
19+
20+
print "Name: " + name
21+
print "Size: " + str(size)
22+
print "Length: " + str(len(second))
23+
if len(second) - 2 <> size * 2:
24+
print "Size mismatch. Skipping."
25+
else:
26+
print "Size matches, writing file..."
27+
28+
output = open("out/" + name, "wb")
29+
30+
for i in range(0,size*2,2):
31+
output.write( chr( int (second[i:i+2], 16 ) ) )
32+
33+
output.close()
34+
print "---"

Diff for: parse_raw.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/python
2+
3+
import fileinput
4+
import sys
5+
import os
6+
7+
def zeroLine():
8+
for i in range(0,512):
9+
output.write(chr(0x00))
10+
11+
output = open("sdcard01.img", "wb")
12+
13+
normal_lines = 0
14+
zero_lines = 0
15+
error_lines = 0
16+
17+
for line in fileinput.input():
18+
line = line.rstrip()
19+
if line == "Y":
20+
zero_lines += 1
21+
zeroLine()
22+
elif line == "Z":
23+
error_lines += 1
24+
zeroLine()
25+
else:
26+
if len(line) <> 1025:
27+
print >> sys.stderr, "short line (" + str(len(line)) + ")"
28+
error_lines += 1
29+
zeroLine()
30+
else:
31+
for i in range(0,512,2):
32+
output.write( chr( int (line[i:i+2], 16 ) ) )
33+
normal_lines += 1
34+
35+
36+
print >> sys.stderr, "normal: ", normal_lines
37+
print >> sys.stderr, "zero: ", zero_lines
38+
print >> sys.stderr, "error: ", error_lines

Diff for: sd_recovery_files.ino

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <SD.h>
2+
3+
File root;
4+
5+
void setup()
6+
{
7+
Serial.begin(115200);
8+
pinMode(10, OUTPUT);
9+
10+
SD.begin(10);
11+
12+
root = SD.open("/");
13+
readDirectory(root, "");
14+
15+
Serial.println("done!");
16+
}
17+
18+
void loop()
19+
{
20+
// nothing happens after setup finishes.
21+
}
22+
23+
void readDirectory(File dir, String folder) {
24+
boolean files = true;
25+
while(files) {
26+
File entry = dir.openNextFile();
27+
if (! entry) {
28+
files = false;
29+
} else {
30+
if (entry.isDirectory()) {
31+
String folder_new = folder;
32+
folder_new += entry.name();
33+
folder_new += "/";
34+
readDirectory(entry, folder_new);
35+
} else {
36+
outputFile(entry, folder);
37+
}
38+
}
39+
}
40+
}
41+
42+
void outputFile(File entry, String folder) {
43+
Serial.print("--- ");
44+
Serial.print(folder);
45+
Serial.print(entry.name());
46+
Serial.print(";");
47+
Serial.println(entry.size(), DEC);
48+
byte r;
49+
while (entry.available()) {
50+
r = entry.read();
51+
if (r < 0x10) {
52+
Serial.print("0");
53+
}
54+
Serial.print(r, HEX);
55+
}
56+
Serial.println();
57+
}
58+

Diff for: sd_recovery_raw.ino

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <SD.h>
2+
3+
File root;
4+
5+
Sd2Card card;
6+
7+
void setup()
8+
{
9+
Serial.begin(115200);
10+
pinMode(10, OUTPUT);
11+
12+
card.init(SPI_HALF_SPEED, 10);
13+
// SD.begin(10);
14+
15+
long blocks = card.cardSize();
16+
//Serial.println(blocks);
17+
18+
uint8_t data[512];
19+
int i = 0;
20+
boolean notZero = false;
21+
for (long blockNumber = 0; blockNumber < blocks; blockNumber++) {
22+
//card.chipSelectLow();
23+
if (!card.readBlock(blockNumber, data)) {
24+
Serial.println("Z");
25+
break;
26+
}
27+
28+
notZero = false;
29+
30+
for (i = 0; i<512; i++) {
31+
if (data[i] > 0x00) {
32+
notZero = true;
33+
break;
34+
}
35+
}
36+
if (notZero) {
37+
for (i = 0; i<512; i++) {
38+
if (data[i] < 0x10) {
39+
Serial.print("0");
40+
}
41+
Serial.print(data[i], HEX);
42+
}
43+
Serial.println("X");
44+
} else {
45+
Serial.println("Y");
46+
47+
}
48+
49+
//Serial.println("done!");
50+
}
51+
52+
void loop()
53+
{
54+
// nothing happens after setup finishes.
55+
}
56+
57+
void printDirectory(File dir, String folder) {
58+
boolean files = true;
59+
while(files) {
60+
File entry = dir.openNextFile();
61+
if (! entry) {
62+
files = false;
63+
} else {
64+
if (entry.isDirectory()) {
65+
String folder_new = folder;
66+
folder_new += entry.name();
67+
folder_new += "/";
68+
printDirectory(entry, folder_new);
69+
} else {
70+
Serial.print("--- ");
71+
Serial.print(folder);
72+
Serial.print(entry.name());
73+
Serial.print(";");
74+
Serial.println(entry.size(), DEC);
75+
byte r;
76+
while (entry.available()) {
77+
r = entry.read();
78+
if (r < 0x10) {
79+
Serial.print("0");
80+
}
81+
Serial.print(r, HEX);
82+
}
83+
Serial.println();
84+
}
85+
}
86+
}
87+
}
88+
89+

0 commit comments

Comments
 (0)