Last active
August 1, 2025 12:47
-
-
Save lesterlo/bff0286bfbfd90c5dafecc34df245488 to your computer and use it in GitHub Desktop.
Evaluate eMMC block integrity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Changable Variables | |
| DEV="/dev/mmcblk1" | |
| TEST_PATTERN_FILENAME="test_pattern.bin" | |
| BLOCKS_PER_CHUNK=$((2** 13)) # Increase this will make the test go faster. The value should be a multiple of power of 2. Value 15 is the MAX, value >= 13 didn't have a big impact on speed. | |
| # Calculate total blocks based on block size | |
| TOTAL_BYTES=$(blockdev --getsize64 "$DEV") | |
| #TOTAL_BYTES=$((50 * 1024 * 1024)) # Test | |
| LOGICAL_BLOCK_SIZE=$(blockdev --getbsz "$DEV") | |
| CHUNK_SIZE=$((LOGICAL_BLOCK_SIZE * BLOCKS_PER_CHUNK)) | |
| TOTAL_BLOCKS=$((TOTAL_BYTES / LOGICAL_BLOCK_SIZE)) | |
| TOTAL_CHUNKS=$((TOTAL_BLOCKS / BLOCKS_PER_CHUNK)) | |
| TEST_PATTERN="/tmp/$TEST_PATTERN_FILENAME" | |
| echo " " | |
| gen_test_pattern() { | |
| local gen_size=$1 | |
| echo "[INFO] Generating test pattern file: $TEST_PATTERN with size $gen_size bytes" | |
| head -c $gen_size /dev/urandom > "$TEST_PATTERN" | |
| } | |
| # Generate the Block pattern file | |
| gen_test_pattern $CHUNK_SIZE | |
| # Get total size in bytes | |
| echo "---------- Test Info -------------" | |
| echo "[INFO] Choosing Device: $DEV" | |
| echo "[INFO] Device Size: $(echo "scale=2; $TOTAL_BYTES/ 1024 / 1024 " | bc) MB" | |
| echo "[INFO] Logical Block size: $LOGICAL_BLOCK_SIZE bytes" | |
| echo "[INFO] Total blocks on dev: $TOTAL_BLOCKS" | |
| echo "[INFO] Chunk size on test: $(echo "scale=2; $CHUNK_SIZE / 1024 / 1024 " | bc) MB" | |
| echo "[INFO] Total chunk to test: $TOTAL_CHUNKS" | |
| echo "---------- Test Running ----------" | |
| fail_flag=0 | |
| total_write_time=0 | |
| total_read_time=0 | |
| successful_chunks=0 | |
| success_remaining_blocks=0 | |
| for ((i=0; i<TOTAL_CHUNKS; i++)); do | |
| # Write pattern to block i | |
| write_start=$(date +%s.%N) | |
| dd if="$TEST_PATTERN" of="$DEV" bs=$CHUNK_SIZE seek=$i count=1 oflag=direct status=none | |
| write_end=$(date +%s.%N) | |
| write_time=$(echo "$write_end - $write_start" | bc) | |
| write_speed=$(echo "scale=2; $CHUNK_SIZE / 1024 / 1024 / $write_time" | bc) | |
| total_write_time=$(echo "$total_write_time + $write_time" | bc) | |
| # Read back and compare | |
| read_start=$(date +%s.%N) | |
| dd if="$DEV" bs=$CHUNK_SIZE skip=$i count=1 iflag=direct status=none | cmp -s "$TEST_PATTERN" | |
| read_result=$? | |
| read_end=$(date +%s.%N) | |
| read_time=$(echo "$read_end - $read_start" | bc) | |
| read_speed=$(echo "scale=2; $CHUNK_SIZE / 1024 / 1024 / $read_time" | bc) | |
| total_read_time=$(echo "$total_read_time + $read_time" | bc) | |
| # Print progress | |
| echo -ne "\r[INFO] Testing block $i / $TOTAL_CHUNKS... Write: ${write_speed} MB/s, Read: ${read_speed} MB/s" | |
| if [ $read_result -ne 0 ]; then | |
| echo -e "\n[FAIL] Mismatch at block $i" | |
| fail_flag=1 | |
| else | |
| successful_chunks=$((successful_chunks + 1)) | |
| success_blocks=$((success_blocks+BLOCKS_PER_CHUNK)) | |
| fi | |
| done | |
| # Process remaining blocks if any | |
| REMAINING_BLOCKS=$(( TOTAL_BLOCKS - TOTAL_CHUNKS * BLOCKS_PER_CHUNK )) | |
| REMAINING_BYTES=$(( REMAINING_BLOCKS * LOGICAL_BLOCK_SIZE )) | |
| echo " " | |
| echo "[INFO] Remaining block to test: $REMAINING_BLOCKS" | |
| if [ "$REMAINING_BYTES" -gt 0 ]; then | |
| gen_test_pattern $REMAINING_BYTES | |
| echo "[INFO] Testing last partial chunk..." | |
| seek_block=$((TOTAL_CHUNKS * BLOCKS_PER_CHUNK)) | |
| dd if="$TEST_PATTERN" of="$DEV" bs=$LOGICAL_BLOCK_SIZE seek=$seek_block count=$REMAINING_BLOCKS oflag=direct conv=notrunc status=none | |
| dd if="$DEV" bs=$LOGICAL_BLOCK_SIZE skip=$seek_block count=$REMAINING_BLOCKS iflag=direct status=none | cmp -s "$TEST_PATTERN" | |
| if [ $? -ne 0 ]; then | |
| echo "[FAIL] Mismatch in final partial chunk" | |
| fail_flag=1 | |
| else | |
| success_remaining_blocks=$REMAINING_BLOCKS | |
| fi | |
| fi | |
| echo -e "\n[INFO] Testing complete." | |
| # --- Calculation --- | |
| total_success_bytes=$((successful_chunks * CHUNK_SIZE + success_remaining_blocks * LOGICAL_BLOCK_SIZE)) | |
| total_mb=$(echo "scale=2; $total_success_bytes / 1024 / 1024" | bc) | |
| avg_write_speed=$(echo "scale=2; $total_mb / $total_write_time" | bc) | |
| avg_read_speed=$(echo "scale=2; $total_mb / $total_read_time" | bc) | |
| # Print summary | |
| echo "---------- Full Test Summary ----------" | |
| echo "eMMC extcid: $(cat /sys/kernel/debug/mmc1/mmc1:0001/ext_csd)" | |
| echo "---------- Summary --------------------" | |
| echo "Success Rate : $(echo "scale=2; $total_success_bytes / $TOTAL_BYTES * 100" | bc)%" | |
| echo "Success Block : $((successful_chunks * BLOCKS_PER_CHUNK + success_remaining_blocks))/$TOTAL_BLOCKS" | |
| echo "Tested Chunk size : $(echo "scale=2; $CHUNK_SIZE / 1024 " | bc) KB" | |
| echo "Total data tested : $total_mb MB" | |
| echo "Avg Write Speed : $avg_write_speed MB/s" | |
| echo "Avg Read Speed : $avg_read_speed MB/s" | |
| if [ $fail_flag -ne 0 ]; then | |
| echo -e "\n[ERROR] Some blocks failed verification." | |
| exit 1 | |
| else | |
| echo -e "\n[SUCCESS] All blocks passed verification." | |
| exit 0 | |
| fi | |
| #------------ Notes --------------- | |
| # Manual Check for first 1 M | |
| # dd if=/dev/mmcblk1 bs=4096 count=2 | hexdump -C | head | |
| #Manual fill, contaminate block 10 | |
| #yes '2' | tr -d '\n' | head -c $((1 * 1024)) | dd of="/dev/mmcblk1" bs=4096 seek=10 status=progress oflag=direct |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment