mirror of
https://github.com/AltraMayor/f3.git
synced 2025-09-08 14:50:13 -04:00
f3probe: implement probe_device()
This commit is contained in:
parent
96f9995d50
commit
b1fbd48675
117
libprobe.c
117
libprobe.c
@ -17,15 +17,16 @@
|
||||
|
||||
#include "libprobe.h"
|
||||
|
||||
static const char const *ftype_to_name[] = {
|
||||
static const char const *ftype_to_name[FKTY_MAX] = {
|
||||
[FKTY_GOOD] = "good",
|
||||
[FKTY_BAD] = "bad",
|
||||
[FKTY_LIMBO] = "limbo",
|
||||
[FKTY_WRAPAROUND] = "wraparound",
|
||||
[FKTY_MAX] = "max",
|
||||
};
|
||||
|
||||
const char *fake_type_to_name(enum fake_type fake_type)
|
||||
{
|
||||
assert(fake_type < FKTY_MAX);
|
||||
return ftype_to_name[fake_type];
|
||||
}
|
||||
|
||||
@ -67,9 +68,6 @@ static int fdev_read_block(struct device *dev, char *buf, uint64_t block)
|
||||
switch (fdev->fake_type) {
|
||||
case FKTY_LIMBO:
|
||||
if (offset >= GIGABYTE * fdev->file_size_gb) {
|
||||
/* XXX Support different types of LIMBO.
|
||||
* For example: all zeros, all ones, and random.
|
||||
*/
|
||||
memset(buf, 0, BLOCK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
@ -160,7 +158,6 @@ static void fdev_free(struct device *dev)
|
||||
assert(!close(fdev->fd));
|
||||
assert(!unlink(fdev->filename));
|
||||
free((void *)fdev->filename);
|
||||
fdev->filename = NULL;
|
||||
}
|
||||
|
||||
/* XXX Validate parameters.
|
||||
@ -197,7 +194,6 @@ struct device *create_file_device(const char *filename,
|
||||
|
||||
filename:
|
||||
free((void *)fdev->filename);
|
||||
fdev->filename = NULL;
|
||||
fdev:
|
||||
free(fdev);
|
||||
error:
|
||||
@ -313,26 +309,115 @@ static inline int dev_get_size_gb(struct device *dev)
|
||||
return dev->get_size_gb(dev);
|
||||
}
|
||||
|
||||
/* XXX Write random data for testing.
|
||||
* There would be a random seed, and all the other blocks would be
|
||||
* this seed XOR'd with the number of the test.
|
||||
*/
|
||||
static void fill_buffer(char *buf, int len, int signature)
|
||||
{
|
||||
memset(buf, signature, len);
|
||||
}
|
||||
|
||||
static inline int equal_blk(const char *b1, const char *b2)
|
||||
{
|
||||
return !memcmp(b1, b2, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static inline void *align_512(void *p)
|
||||
{
|
||||
uintptr_t ip = (uintptr_t)p;
|
||||
return (void *)( (ip + 511) & ~511 );
|
||||
}
|
||||
|
||||
/* XXX Don't write at the very beginning of the card to avoid
|
||||
* losing the partition table.
|
||||
* But write at a random locations to make harder for fake chips
|
||||
* to become "smarter".
|
||||
*/
|
||||
/* XXX Write random data for testing.
|
||||
* There would be a random seed, and all the other blocks would be
|
||||
* this seed XOR'd with the number of the test.
|
||||
*/
|
||||
/* XXX Finish testing the last block, and the next one that should fail.
|
||||
* Then report the last block, so user can create the largest partition.
|
||||
*/
|
||||
/* XXX Properly handle read and write errors. */
|
||||
enum fake_type probe_device(struct device *dev, int *preal_size_gb)
|
||||
{
|
||||
char buf[BLOCK_SIZE];
|
||||
int device_size_gb = dev_get_size_gb(dev);
|
||||
char stack[511 + 3 * BLOCK_SIZE];
|
||||
char *first_blk, *stamp_blk, *probe_blk;
|
||||
const int step = GIGABYTE / BLOCK_SIZE;
|
||||
uint64_t first_pos = 10;
|
||||
uint64_t pos = first_pos + step;
|
||||
int i;
|
||||
|
||||
/* TODO */
|
||||
dev_read_block(dev, buf, 10);
|
||||
dev_write_block(dev, buf, 10);
|
||||
assert(device_size_gb > 0);
|
||||
|
||||
*preal_size_gb = dev_get_size_gb(dev);
|
||||
/* Aligning these pointers is necessary to directly read and write
|
||||
* the block device.
|
||||
* For the file device, this is superfluous.
|
||||
*/
|
||||
first_blk = align_512(stack);
|
||||
stamp_blk = first_blk + BLOCK_SIZE;
|
||||
probe_blk = stamp_blk + BLOCK_SIZE;
|
||||
|
||||
/* Base case. */
|
||||
fill_buffer(first_blk, BLOCK_SIZE, 1);
|
||||
dev_write_block(dev, first_blk, first_pos);
|
||||
dev_read_block(dev, probe_blk, first_pos);
|
||||
if (!equal_blk(first_blk, probe_blk)) {
|
||||
/* There is a block before the first 1GB that seems to
|
||||
* be damaged. Trying a second time...
|
||||
*/
|
||||
dev_write_block(dev, first_blk, first_pos);
|
||||
dev_read_block(dev, probe_blk, first_pos);
|
||||
if (!equal_blk(first_blk, probe_blk)) {
|
||||
/* Okay, this device is damaged. */
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inductive step. */
|
||||
fill_buffer(stamp_blk, BLOCK_SIZE, 2);
|
||||
for (i = 1; i < device_size_gb; i++) {
|
||||
dev_write_block(dev, stamp_blk, pos);
|
||||
|
||||
dev_read_block(dev, probe_blk, first_pos);
|
||||
if (!equal_blk(first_blk, probe_blk)) {
|
||||
/* Wrapping around? */
|
||||
if (equal_blk(stamp_blk, probe_blk)) {
|
||||
/* yes. */
|
||||
*preal_size_gb = i;
|
||||
return FKTY_WRAPAROUND;
|
||||
}
|
||||
|
||||
/* The block at @first_pos changed to a value
|
||||
* different from the one written.
|
||||
* Trying a second time...
|
||||
*/
|
||||
dev_write_block(dev, first_blk, first_pos);
|
||||
dev_write_block(dev, stamp_blk, pos);
|
||||
dev_read_block(dev, probe_blk, first_pos);
|
||||
if (!equal_blk(first_blk, probe_blk)) {
|
||||
if (equal_blk(stamp_blk, probe_blk)) {
|
||||
*preal_size_gb = i;
|
||||
return FKTY_WRAPAROUND;
|
||||
}
|
||||
/* Okay, this device is damaged. */
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
dev_read_block(dev, probe_blk, pos);
|
||||
if (!equal_blk(stamp_blk, probe_blk)) {
|
||||
*preal_size_gb = i;
|
||||
return FKTY_LIMBO;
|
||||
}
|
||||
|
||||
pos += step;
|
||||
}
|
||||
|
||||
*preal_size_gb = device_size_gb;
|
||||
return FKTY_GOOD;
|
||||
|
||||
bad:
|
||||
*preal_size_gb = 0;
|
||||
return FKTY_BAD;
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
#define HEADER_LIBPROBE_H
|
||||
|
||||
enum fake_type {
|
||||
FKTY_GOOD,
|
||||
FKTY_LIMBO,
|
||||
FKTY_WRAPAROUND,
|
||||
FKTY_GOOD, /* Device is good. */
|
||||
FKTY_BAD, /* Device is at least partially damaged. */
|
||||
FKTY_LIMBO, /* Device discards data after a given limit. */
|
||||
FKTY_WRAPAROUND,/* Device overwrites data after a given limit. */
|
||||
FKTY_MAX,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user