mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
rk27xx: add the Scheme B flash translation layer
Scheme B is the self-describing NAND format of the HiFiMAN HM-601 and similar players: every block carries its logical number and a version in its metadata, so the mapping is rebuilt by a scan at mount, and small writes go through a 16-page RAM cache journalled to flash. ftl-scheme-b.c is a reimplementation from reverse engineering. The format and the behaviour were worked out by analysing the machine code of the HM-601's NAND bootloader and of a compiled Rockchip FTL object from the rk2808 platform, which handles the same format, and checked against dumps of the media; no source code was used. Where the two binaries differ the HM-601 is followed: 16-bit versions compared across wrap, plain 0xF200/0xF100 tags, a copy that stamps one header on every page. The number of open exchange blocks is configurable - 8 on the HM-601, whose mount recovers no more. Checked by running the compiled object under qemu over a NAND simulator, side by side with this code, on a 4 GiB HM-601 dump: the same state after mount, identical reads of all 3958 logical blocks, and flash programs and erases identical one for one - over 600 random writes on each of three seeds and at every power-cut point of three sweeps, 1435 points - with 0 wrong sectors. Not built yet: no target selects it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: Icb935ea78d716c1e51f1453fc3ab3f47f3467027
This commit is contained in:
parent
efde59472e
commit
16492de569
2 changed files with 1867 additions and 0 deletions
1780
firmware/target/arm/rk27xx/ftl-scheme-b.c
Normal file
1780
firmware/target/arm/rk27xx/ftl-scheme-b.c
Normal file
File diff suppressed because it is too large
Load diff
87
firmware/target/arm/rk27xx/ftl-scheme-b.h
Normal file
87
firmware/target/arm/rk27xx/ftl-scheme-b.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2026 by Marcin Bukat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* The "Scheme B" flash translation layer of rk27xx devices - the
|
||||
* self-describing on-flash format the original firmware of the HiFiMAN
|
||||
* HM-601 and similar players uses, read and written compatibly so that the
|
||||
* original firmware keeps working on the same media. A reimplementation
|
||||
* from reverse engineering; see ftl-scheme-b.c for how it works. */
|
||||
|
||||
#ifndef __FTL_SCHEME_B_H__
|
||||
#define __FTL_SCHEME_B_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct ftl_b_config
|
||||
{
|
||||
/* The first block the FTL owns; the boot area is everything before it.
|
||||
* Not recorded in the FTL's own structures. */
|
||||
uint16_t first_block;
|
||||
/* Exchange blocks open at once. The original firmware's own count must
|
||||
* not be exceeded: its mount recovers no more than that many, and loses
|
||||
* the data of the rest. 8 on the HM-601. */
|
||||
uint8_t exch_blocks;
|
||||
/* Never write, not even the repairs a mount normally makes. */
|
||||
bool read_only;
|
||||
};
|
||||
|
||||
/* Why a mount failed */
|
||||
enum ftl_b_error
|
||||
{
|
||||
FTL_B_OK = 0,
|
||||
FTL_B_ERR_GEOMETRY, /* the chip is not one this FTL can map */
|
||||
FTL_B_ERR_CONFIG, /* an unusable configuration */
|
||||
FTL_B_ERR_NO_TABLE, /* no bad-block table: not formatted */
|
||||
FTL_B_ERR_TABLE, /* the bad-block table is damaged */
|
||||
FTL_B_ERR_VERSION, /* a format generation not supported */
|
||||
FTL_B_ERR_TOO_BIG, /* more logical blocks than fit in RAM */
|
||||
};
|
||||
|
||||
struct ftl_b_status
|
||||
{
|
||||
enum ftl_b_error error;
|
||||
bool writable;
|
||||
uint16_t format_version; /* as recorded in the bad-block table */
|
||||
uint16_t logical_blocks;
|
||||
uint16_t bad_blocks;
|
||||
uint16_t free_blocks; /* erased or erasable, queued for use */
|
||||
uint8_t open_exch; /* exchange blocks in progress */
|
||||
uint8_t cached_pages; /* pages held in the write cache */
|
||||
};
|
||||
|
||||
/* Mount the media. Returns FTL_B_OK or the reason it failed. */
|
||||
enum ftl_b_error ftl_b_mount(const struct ftl_b_config *config);
|
||||
void ftl_b_get_status(struct ftl_b_status *status);
|
||||
|
||||
/* Sectors in the logical space; 0 when not mounted */
|
||||
uint32_t ftl_b_capacity(void);
|
||||
|
||||
/* Return 0, or non-zero if the request was refused or a sector could not be
|
||||
* read reliably. Sectors are 512 bytes. */
|
||||
int ftl_b_read(uint32_t sector, void *buf, uint32_t count);
|
||||
int ftl_b_write(uint32_t sector, const void *buf, uint32_t count);
|
||||
|
||||
/* Every write is on the flash when ftl_b_write() returns - the write cache
|
||||
* is journalled as it changes - so there is nothing to write out. Kept for
|
||||
* the storage layer's interface. */
|
||||
void ftl_b_sync(void);
|
||||
|
||||
#endif /* __FTL_SCHEME_B_H__ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue