mirror of
https://github.com/AltraMayor/f3.git
synced 2025-09-09 15:22:40 -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"
|
#include "libprobe.h"
|
||||||
|
|
||||||
static const char const *ftype_to_name[] = {
|
static const char const *ftype_to_name[FKTY_MAX] = {
|
||||||
[FKTY_GOOD] = "good",
|
[FKTY_GOOD] = "good",
|
||||||
|
[FKTY_BAD] = "bad",
|
||||||
[FKTY_LIMBO] = "limbo",
|
[FKTY_LIMBO] = "limbo",
|
||||||
[FKTY_WRAPAROUND] = "wraparound",
|
[FKTY_WRAPAROUND] = "wraparound",
|
||||||
[FKTY_MAX] = "max",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *fake_type_to_name(enum fake_type fake_type)
|
const char *fake_type_to_name(enum fake_type fake_type)
|
||||||
{
|
{
|
||||||
|
assert(fake_type < FKTY_MAX);
|
||||||
return ftype_to_name[fake_type];
|
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) {
|
switch (fdev->fake_type) {
|
||||||
case FKTY_LIMBO:
|
case FKTY_LIMBO:
|
||||||
if (offset >= GIGABYTE * fdev->file_size_gb) {
|
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);
|
memset(buf, 0, BLOCK_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -160,7 +158,6 @@ static void fdev_free(struct device *dev)
|
|||||||
assert(!close(fdev->fd));
|
assert(!close(fdev->fd));
|
||||||
assert(!unlink(fdev->filename));
|
assert(!unlink(fdev->filename));
|
||||||
free((void *)fdev->filename);
|
free((void *)fdev->filename);
|
||||||
fdev->filename = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX Validate parameters.
|
/* XXX Validate parameters.
|
||||||
@ -197,7 +194,6 @@ struct device *create_file_device(const char *filename,
|
|||||||
|
|
||||||
filename:
|
filename:
|
||||||
free((void *)fdev->filename);
|
free((void *)fdev->filename);
|
||||||
fdev->filename = NULL;
|
|
||||||
fdev:
|
fdev:
|
||||||
free(fdev);
|
free(fdev);
|
||||||
error:
|
error:
|
||||||
@ -313,26 +309,115 @@ static inline int dev_get_size_gb(struct device *dev)
|
|||||||
return dev->get_size_gb(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
|
/* XXX Don't write at the very beginning of the card to avoid
|
||||||
* losing the partition table.
|
* losing the partition table.
|
||||||
* But write at a random locations to make harder for fake chips
|
* But write at a random locations to make harder for fake chips
|
||||||
* to become "smarter".
|
* 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.
|
/* 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.
|
* 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)
|
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 */
|
assert(device_size_gb > 0);
|
||||||
dev_read_block(dev, buf, 10);
|
|
||||||
dev_write_block(dev, buf, 10);
|
|
||||||
|
|
||||||
*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;
|
return FKTY_GOOD;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
*preal_size_gb = 0;
|
||||||
|
return FKTY_BAD;
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
#define HEADER_LIBPROBE_H
|
#define HEADER_LIBPROBE_H
|
||||||
|
|
||||||
enum fake_type {
|
enum fake_type {
|
||||||
FKTY_GOOD,
|
FKTY_GOOD, /* Device is good. */
|
||||||
FKTY_LIMBO,
|
FKTY_BAD, /* Device is at least partially damaged. */
|
||||||
FKTY_WRAPAROUND,
|
FKTY_LIMBO, /* Device discards data after a given limit. */
|
||||||
|
FKTY_WRAPAROUND,/* Device overwrites data after a given limit. */
|
||||||
FKTY_MAX,
|
FKTY_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user